1 /* 2 Copyright (c) 2020-2021 Intel Corporation 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 #if __INTEL_COMPILER && _MSC_VER 18 #pragma warning(disable : 2586) // decorated name length exceeded, name was truncated 19 #endif 20 21 #include "conformance_flowgraph.h" 22 23 using input_msg = conformance::message</*default_ctor*/true, /*copy_ctor*/true, /*copy_assign*/false>; 24 using output_msg = conformance::message</*default_ctor*/false, /*copy_ctor*/true, /*copy_assign*/false>; 25 26 //! \file conformance_function_node.cpp 27 //! \brief Test for [flow_graph.function_node] specification 28 29 /* 30 Test node deduction guides 31 */ 32 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT 33 34 int function_body_f(const int&) { return 1; } 35 36 template <typename Body> 37 void test_deduction_guides_common(Body body) { 38 using namespace tbb::flow; 39 graph g; 40 41 function_node f1(g, unlimited, body); 42 static_assert(std::is_same_v<decltype(f1), function_node<int, int>>); 43 44 function_node f2(g, unlimited, body, rejecting()); 45 static_assert(std::is_same_v<decltype(f2), function_node<int, int, rejecting>>); 46 47 function_node f3(g, unlimited, body, node_priority_t(5)); 48 static_assert(std::is_same_v<decltype(f3), function_node<int, int>>); 49 50 function_node f4(g, unlimited, body, rejecting(), node_priority_t(5)); 51 static_assert(std::is_same_v<decltype(f4), function_node<int, int, rejecting>>); 52 53 #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET 54 function_node f5(follows(f2), unlimited, body); 55 static_assert(std::is_same_v<decltype(f5), function_node<int, int>>); 56 57 function_node f6(follows(f5), unlimited, body, rejecting()); 58 static_assert(std::is_same_v<decltype(f6), function_node<int, int, rejecting>>); 59 60 function_node f7(follows(f6), unlimited, body, node_priority_t(5)); 61 static_assert(std::is_same_v<decltype(f7), function_node<int, int>>); 62 63 function_node f8(follows(f7), unlimited, body, rejecting(), node_priority_t(5)); 64 static_assert(std::is_same_v<decltype(f8), function_node<int, int, rejecting>>); 65 #endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET 66 67 function_node f9(f1); 68 static_assert(std::is_same_v<decltype(f9), function_node<int, int>>); 69 } 70 71 void test_deduction_guides() { 72 test_deduction_guides_common([](const int&)->int { return 1; }); 73 test_deduction_guides_common([](const int&) mutable ->int { return 1; }); 74 test_deduction_guides_common(function_body_f); 75 } 76 77 #endif 78 79 //! Test calling function body 80 //! \brief \ref interface \ref requirement 81 TEST_CASE("Test function_node body") { 82 conformance::test_body_exec<oneapi::tbb::flow::function_node<input_msg, output_msg>, input_msg, output_msg>(oneapi::tbb::flow::unlimited); 83 } 84 85 //! Test function_node constructors 86 //! \brief \ref requirement 87 TEST_CASE("function_node constructors"){ 88 using namespace oneapi::tbb::flow; 89 graph g; 90 91 conformance::counting_functor<int> fun; 92 93 function_node<int, int> fn1(g, unlimited, fun); 94 function_node<int, int> fn2(g, unlimited, fun, oneapi::tbb::flow::node_priority_t(1)); 95 96 function_node<int, int, lightweight> lw_node1(g, serial, fun, lightweight()); 97 function_node<int, int, lightweight> lw_node2(g, serial, fun, lightweight(), oneapi::tbb::flow::node_priority_t(1)); 98 } 99 100 //! The node that is constructed has a reference to the same graph object as src, has a copy of the initial body used by src, and has the same concurrency threshold as src. 101 //! The predecessors and successors of src are not copied. 102 //! \brief \ref requirement 103 TEST_CASE("function_node copy constructor"){ 104 conformance::test_copy_ctor<oneapi::tbb::flow::function_node<int, int>>(); 105 } 106 107 //! Test node reject the incoming message if the concurrency limit achieved. 108 //! \brief \ref interface 109 TEST_CASE("function_node with rejecting policy"){ 110 conformance::test_rejecting<oneapi::tbb::flow::function_node<int, int, oneapi::tbb::flow::rejecting>>(); 111 } 112 113 //! Test body copying and copy_body logic 114 //! Test the body object passed to a node is copied 115 //! \brief \ref interface 116 TEST_CASE("function_node and body copying"){ 117 conformance::test_copy_body_function<oneapi::tbb::flow::function_node<int, int>, conformance::copy_counting_object<int>>(oneapi::tbb::flow::unlimited); 118 } 119 120 //! Test function_node is a graph_node, receiver<Input>, and sender<Output> 121 //! \brief \ref interface 122 TEST_CASE("function_node superclasses"){ 123 conformance::test_inheritance<oneapi::tbb::flow::function_node<int, int>, int, int>(); 124 conformance::test_inheritance<oneapi::tbb::flow::function_node<void*, float>, void*, float>(); 125 conformance::test_inheritance<oneapi::tbb::flow::function_node<input_msg, output_msg>, input_msg, output_msg>(); 126 } 127 128 //! Test node not buffered unsuccessful message, and try_get after rejection should not succeed. 129 //! \brief \ref requirement 130 TEST_CASE("function_node buffering"){ 131 conformance::dummy_functor<int> fun; 132 conformance::test_buffering<oneapi::tbb::flow::function_node<input_msg, int, oneapi::tbb::flow::rejecting>, input_msg>(oneapi::tbb::flow::unlimited, fun); 133 conformance::test_buffering<oneapi::tbb::flow::function_node<input_msg, int, oneapi::tbb::flow::queueing>, input_msg>(oneapi::tbb::flow::unlimited, fun); 134 } 135 136 //! Test node broadcast messages to successors 137 //! \brief \ref requirement 138 TEST_CASE("function_node broadcast"){ 139 conformance::counting_functor<int> fun(conformance::expected); 140 conformance::test_forwarding<oneapi::tbb::flow::function_node<input_msg, int>, input_msg, int>(1, oneapi::tbb::flow::unlimited, fun); 141 } 142 143 //! Test deduction guides 144 //! \brief \ref interface \ref requirement 145 TEST_CASE("Deduction guides"){ 146 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT 147 test_deduction_guides(); 148 #endif 149 } 150 151 //! Test priorities work in single-threaded configuration 152 //! \brief \ref requirement 153 TEST_CASE("function_node priority support"){ 154 conformance::test_priority<oneapi::tbb::flow::function_node<input_msg, int>, input_msg>(oneapi::tbb::flow::unlimited); 155 } 156 157 //! Test function_node has a user-settable concurrency limit. It can be set to one of predefined values. 158 //! The user can also provide a value of type std::size_t to limit concurrency. 159 //! Test that not more than limited threads works in parallel. 160 //! \brief \ref requirement 161 TEST_CASE("concurrency follows set limits"){ 162 conformance::test_concurrency<oneapi::tbb::flow::function_node<int, int>>(); 163 } 164 165 //! Test node Input class meet the DefaultConstructible and CopyConstructible requirements and Output class meet the CopyConstructible requirements. 166 //! \brief \ref interface \ref requirement 167 TEST_CASE("Test function_node Output and Input class") { 168 using Body = conformance::copy_counting_object<int>; 169 conformance::test_output_input_class<oneapi::tbb::flow::function_node<Body, Body>, Body>(); 170 } 171