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