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 "common/test.h" 22 23 #include "common/utils.h" 24 #include "common/graph_utils.h" 25 26 #include "oneapi/tbb/flow_graph.h" 27 #include "oneapi/tbb/task_arena.h" 28 #include "oneapi/tbb/global_control.h" 29 30 #include "conformance_flowgraph.h" 31 32 //! \file conformance_sequencer_node.cpp 33 //! \brief Test for [flow_graph.sequencer_node] specification 34 35 /* 36 TODO: implement missing conformance tests for sequencer_node: 37 - [ ] The copy constructor and copy assignment are called for the node's type template parameter. 38 - [ ] Explicit test that `Sequencer' requirements are necessary. 39 - [ ] Write tests for the constructors. 40 - [ ] Add CTAD test. 41 - [ ] Improve `test_buffering' by checking that additional `try_get()' does not receive the same 42 value. 43 - [ ] Add explicit test on the example from the specification. 44 */ 45 46 template<typename T> 47 void test_inheritance(){ 48 using namespace oneapi::tbb::flow; 49 50 CHECK_MESSAGE( (std::is_base_of<graph_node, sequencer_node<T>>::value), "sequencer_node should be derived from graph_node"); 51 CHECK_MESSAGE( (std::is_base_of<receiver<T>, sequencer_node<T>>::value), "sequencer_node should be derived from receiver<T>"); 52 CHECK_MESSAGE( (std::is_base_of<sender<T>, sequencer_node<T>>::value), "sequencer_node should be derived from sender<T>"); 53 } 54 55 template<typename T> 56 struct id_sequencer{ 57 using input_type = T; 58 59 T operator()(T v){ 60 return v; 61 } 62 }; 63 64 void test_copies(){ 65 using namespace oneapi::tbb::flow; 66 67 graph g; 68 id_sequencer<int> sequencer; 69 70 sequencer_node<int> n(g, sequencer); 71 sequencer_node<int> n2(n); 72 73 } 74 75 void test_buffering(){ 76 oneapi::tbb::flow::graph g; 77 78 id_sequencer<int> sequencer; 79 80 oneapi::tbb::flow::sequencer_node<int> node(g, sequencer); 81 oneapi::tbb::flow::limiter_node<int> rejecter(g, 0); 82 83 oneapi::tbb::flow::make_edge(node, rejecter); 84 node.try_put(1); 85 g.wait_for_all(); 86 87 int tmp = -1; 88 CHECK_MESSAGE( (node.try_get(tmp) == false), "try_get after rejection should not succeed"); 89 CHECK_MESSAGE( (tmp == -1), "try_get after rejection should not set value"); 90 } 91 92 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT 93 void test_deduction_guides(){ 94 // oneapi::tbb::flow::graph g; 95 // id_sequencer<int> sequ; 96 // oneapi::tbb::flow::sequencer_node node1(g, sequ); 97 } 98 #endif 99 100 void test_forwarding(){ 101 oneapi::tbb::flow::graph g; 102 id_sequencer<int> sequencer; 103 104 oneapi::tbb::flow::sequencer_node<int> node1(g, sequencer); 105 test_push_receiver<int> node2(g); 106 test_push_receiver<int> node3(g); 107 108 oneapi::tbb::flow::make_edge(node1, node2); 109 oneapi::tbb::flow::make_edge(node1, node3); 110 111 node1.try_put(0); 112 113 g.wait_for_all(); 114 115 int c2 = get_count(node2), c3 = get_count(node3); 116 CHECK_MESSAGE( (c2 != c3 ), "Only one descendant the node needs to receive"); 117 CHECK_MESSAGE( (c2 + c3 == 1 ), "Messages need to be received"); 118 } 119 120 void test_sequencer(){ 121 oneapi::tbb::flow::graph g; 122 id_sequencer<int> sequencer; 123 124 oneapi::tbb::flow::sequencer_node<int> node(g, sequencer); 125 126 node.try_put(1); 127 node.try_put(0); 128 node.try_put(1); 129 g.wait_for_all(); 130 131 int tmp = -1; 132 CHECK_MESSAGE((node.try_get(tmp) == true), "Getting from sequencer should succeed"); 133 CHECK_MESSAGE((tmp == 0), "Received value should be correct"); 134 135 tmp = -1; 136 CHECK_MESSAGE((node.try_get(tmp) == true), "Getting from sequencer should succeed"); 137 CHECK_MESSAGE((tmp == 1), "Received value should be correct"); 138 139 tmp = -1; 140 CHECK_MESSAGE((node.try_get(tmp) == false), "Getting from sequencer should not succeed"); 141 142 } 143 144 //! Test function_node buffering 145 //! \brief \ref requirement 146 TEST_CASE("sequencer_node buffering"){ 147 test_sequencer(); 148 } 149 150 //! Test function_node buffering 151 //! \brief \ref requirement 152 TEST_CASE("sequencer_node buffering"){ 153 test_forwarding(); 154 } 155 156 //! Test deduction guides 157 //! \brief \ref interface \ref requirement 158 TEST_CASE("Deduction guides"){ 159 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT 160 test_deduction_guides(); 161 #endif 162 } 163 164 //! Test priority_queue_node buffering 165 //! \brief \ref requirement 166 TEST_CASE("sequencer_node buffering"){ 167 test_buffering(); 168 } 169 170 //! Test copy constructor 171 //! \brief \ref interface 172 TEST_CASE("sequencer_node copy constructor"){ 173 test_copies(); 174 } 175 176 //! Test inheritance relations 177 //! \brief \ref interface 178 TEST_CASE("sequencer_node superclasses"){ 179 test_inheritance<int>(); 180 test_inheritance<void*>(); 181 } 182 183