1 /* 2 Copyright (c) 2020 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 18 #include "common/test.h" 19 20 #include "common/utils.h" 21 #include "common/graph_utils.h" 22 23 #include "tbb/flow_graph.h" 24 #include "tbb/task_arena.h" 25 #include "tbb/global_control.h" 26 27 #include "conformance_flowgraph.h" 28 29 //! \file conformance_split_node.cpp 30 //! \brief Test for [flow_graph.split_node] specification 31 32 /* 33 TODO: implement missing conformance tests for split_node: 34 - [ ] Check that copy constructor and copy assignment is called for each type the tuple stores. 35 - [ ] Rewrite `test_forwarding' to check broadcast semantics of the node. 36 - [ ] Improve test for constructors. 37 - [ ] Unify code style in the test by extracting the implementation from the `TEST_CASE' scope 38 into separate functions. 39 - [ ] Rename discarding test to `test_buffering' and add checking that the value does not change 40 in the `try_get()' method of the output ports of the node. 41 - [ ] Add checking of the unlimited concurrency. 42 - [ ] Check that `try_put()' always returns `true'. 43 - [ ] Explicitly check that `output_ports_type' is defined, accessible. 44 - [ ] Explicitly check the method `indexer_node::output_ports()' exists, is accessible and it 45 returns a reference to the `output_ports_type' type. 46 */ 47 48 using namespace tbb::flow; 49 using namespace std; 50 51 template<typename T> 52 void test_inheritance(){ 53 CHECK_MESSAGE( (std::is_base_of<graph_node, split_node<std::tuple<T,T>>>::value), "split_node should be derived from graph_node"); 54 CHECK_MESSAGE( (std::is_base_of<receiver<std::tuple<T,T>>, split_node<std::tuple<T,T>>>::value), "split_node should be derived from receiver<T>"); 55 } 56 57 void test_split(){ 58 graph g; 59 60 queue_node<int> first_queue(g); 61 queue_node<int> second_queue(g); 62 split_node< std::tuple<int,int> > my_split_node(g); 63 make_edge(output_port<0>(my_split_node), first_queue); 64 make_edge(output_port<1>(my_split_node), second_queue); 65 66 tuple<int, int> my_tuple(0, 1); 67 my_split_node.try_put(my_tuple); 68 69 g.wait_for_all(); 70 71 int tmp = -1; 72 CHECK_MESSAGE((first_queue.try_get(tmp) == true), "Getting from target queue should succeed"); 73 CHECK_MESSAGE((tmp == 0), "Received value should be correct"); 74 75 tmp = -1; 76 CHECK_MESSAGE((second_queue.try_get(tmp) == true), "Getting from target queue should succeed"); 77 CHECK_MESSAGE((tmp == 1), "Received value should be correct"); 78 } 79 80 void test_copies(){ 81 using namespace tbb::flow; 82 83 graph g; 84 split_node<std::tuple<int, int>> n(g); 85 split_node<std::tuple<int, int>> n2(n); 86 } 87 88 void test_forwarding(){ 89 tbb::flow::graph g; 90 91 tbb::flow::split_node<std::tuple<int, int>> node1(g); 92 test_push_receiver<int> node2(g); 93 test_push_receiver<int> node3(g); 94 95 tbb::flow::make_edge(output_port<0>(node1), node2); 96 tbb::flow::make_edge(output_port<1>(node1), node3); 97 98 tuple<int, int> my_tuple(0, 1); 99 node1.try_put(my_tuple); 100 101 g.wait_for_all(); 102 103 CHECK_MESSAGE( (get_count(node2) == 1), "Descendant of the node needs to be receive N messages"); 104 CHECK_MESSAGE( (get_count(node3) == 1), "Descendant of the node must receive one message."); 105 } 106 107 //! Test broadcast 108 //! \brief \ref interface 109 TEST_CASE("split_node broadcast") { 110 test_forwarding(); 111 } 112 113 //! Test discarding property 114 //! \brief \ref requirement 115 TEST_CASE("split_node discarding") { 116 graph g; 117 118 split_node< std::tuple<int,int> > my_split_node(g); 119 120 limiter_node< int > rejecter1( g,0); 121 limiter_node< int > rejecter2( g,0); 122 123 make_edge(output_port<0>(my_split_node), rejecter2); 124 make_edge(output_port<1>(my_split_node), rejecter1); 125 126 tuple<int, int> my_tuple(0, 1); 127 my_split_node.try_put(my_tuple); 128 g.wait_for_all(); 129 130 int tmp = -1; 131 CHECK_MESSAGE((output_port<0>(my_split_node).try_get(tmp) == false), "Value should be discarded after rejection"); 132 CHECK_MESSAGE((output_port<1>(my_split_node).try_get(tmp) == false), "Value should be discarded after rejection"); 133 } 134 135 //! Test copy constructor 136 //! \brief \ref interface 137 TEST_CASE("split_node copy constructor") { 138 test_copies(); 139 } 140 141 //! Test copy constructor 142 //! \brief \ref interface \ref requirement 143 TEST_CASE("split_node messages") { 144 test_split(); 145 } 146 147 //! Test copy constructor 148 //! \brief \ref interface 149 TEST_CASE("split_node superclasses") { 150 test_inheritance<int>(); 151 } 152 153