151c0b2f7Stbbdev /* 2b15aabb3Stbbdev Copyright (c) 2020-2021 Intel Corporation 351c0b2f7Stbbdev 451c0b2f7Stbbdev Licensed under the Apache License, Version 2.0 (the "License"); 551c0b2f7Stbbdev you may not use this file except in compliance with the License. 651c0b2f7Stbbdev You may obtain a copy of the License at 751c0b2f7Stbbdev 851c0b2f7Stbbdev http://www.apache.org/licenses/LICENSE-2.0 951c0b2f7Stbbdev 1051c0b2f7Stbbdev Unless required by applicable law or agreed to in writing, software 1151c0b2f7Stbbdev distributed under the License is distributed on an "AS IS" BASIS, 1251c0b2f7Stbbdev WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1351c0b2f7Stbbdev See the License for the specific language governing permissions and 1451c0b2f7Stbbdev limitations under the License. 1551c0b2f7Stbbdev */ 1651c0b2f7Stbbdev 17b15aabb3Stbbdev #if __INTEL_COMPILER && _MSC_VER 18b15aabb3Stbbdev #pragma warning(disable : 2586) // decorated name length exceeded, name was truncated 19b15aabb3Stbbdev #endif 2051c0b2f7Stbbdev 2151c0b2f7Stbbdev #include "conformance_flowgraph.h" 2251c0b2f7Stbbdev 2351c0b2f7Stbbdev //! \file conformance_split_node.cpp 2451c0b2f7Stbbdev //! \brief Test for [flow_graph.split_node] specification 2551c0b2f7Stbbdev 26*de0109beSIlya Mishin using input_msg = conformance::message</*default_ctor*/true, /*copy_ctor*/true, /*copy_assign*/true/*enable for queue_node successor*/>; 27*de0109beSIlya Mishin using my_input_tuple = std::tuple<int, float, input_msg>; 28*de0109beSIlya Mishin using my_split_type = oneapi::tbb::flow::split_node<my_input_tuple>; 2951c0b2f7Stbbdev 30*de0109beSIlya Mishin //! Test node not buffered unsuccessful message, and try_get after rejection should not succeed. 31*de0109beSIlya Mishin //! \brief \ref requirement 32*de0109beSIlya Mishin TEST_CASE("split_node buffering") { 3349e08aacStbbdev oneapi::tbb::flow::graph g; 3451c0b2f7Stbbdev 35*de0109beSIlya Mishin my_split_type testing_node(g); 3651c0b2f7Stbbdev 37*de0109beSIlya Mishin oneapi::tbb::flow::limiter_node<int> rejecter1(g,0); 38*de0109beSIlya Mishin oneapi::tbb::flow::limiter_node<float> rejecter2(g,0); 39*de0109beSIlya Mishin oneapi::tbb::flow::limiter_node<input_msg> rejecter3(g,0); 4051c0b2f7Stbbdev 41*de0109beSIlya Mishin oneapi::tbb::flow::make_edge(oneapi::tbb::flow::output_port<0>(testing_node), rejecter1); 42*de0109beSIlya Mishin oneapi::tbb::flow::make_edge(oneapi::tbb::flow::output_port<1>(testing_node), rejecter2); 43*de0109beSIlya Mishin oneapi::tbb::flow::make_edge(oneapi::tbb::flow::output_port<2>(testing_node), rejecter3); 4451c0b2f7Stbbdev 45*de0109beSIlya Mishin my_input_tuple my_tuple(1, 1.5f, input_msg(2)); 46*de0109beSIlya Mishin testing_node.try_put(my_tuple); 4751c0b2f7Stbbdev g.wait_for_all(); 4851c0b2f7Stbbdev 49*de0109beSIlya Mishin int tmp1 = -1; 50*de0109beSIlya Mishin float tmp2 = -1; 51*de0109beSIlya Mishin input_msg tmp3(-1); 52*de0109beSIlya Mishin CHECK_MESSAGE((oneapi::tbb::flow::output_port<0>(testing_node).try_get(tmp1) == false 53*de0109beSIlya Mishin && tmp1 == -1), "Value should be discarded after rejection"); 54*de0109beSIlya Mishin CHECK_MESSAGE((oneapi::tbb::flow::output_port<1>(testing_node).try_get(tmp2) == false 55*de0109beSIlya Mishin && tmp2 == -1.f), "Value should be discarded after rejection"); 56*de0109beSIlya Mishin CHECK_MESSAGE((oneapi::tbb::flow::output_port<2>(testing_node).try_get(tmp3) == false 57*de0109beSIlya Mishin && tmp3 == -1), "Value should be discarded after rejection"); 5851c0b2f7Stbbdev } 5951c0b2f7Stbbdev 60*de0109beSIlya Mishin //! Test node broadcast messages to successors and splitting them in correct order 6151c0b2f7Stbbdev //! \brief \ref requirement 62*de0109beSIlya Mishin TEST_CASE("split_node broadcast and splitting"){ 63*de0109beSIlya Mishin using namespace oneapi::tbb::flow; 64*de0109beSIlya Mishin oneapi::tbb::flow::graph g; 6551c0b2f7Stbbdev 66*de0109beSIlya Mishin my_split_type testing_node(g); 67*de0109beSIlya Mishin conformance::test_push_receiver<int> node2(g); 68*de0109beSIlya Mishin conformance::test_push_receiver<float> node3(g); 69*de0109beSIlya Mishin conformance::test_push_receiver<input_msg> node4(g); 7051c0b2f7Stbbdev 71*de0109beSIlya Mishin oneapi::tbb::flow::make_edge(output_port<0>(testing_node), node2); 72*de0109beSIlya Mishin oneapi::tbb::flow::make_edge(output_port<1>(testing_node), node3); 73*de0109beSIlya Mishin oneapi::tbb::flow::make_edge(output_port<2>(testing_node), node4); 7451c0b2f7Stbbdev 75*de0109beSIlya Mishin my_input_tuple my_tuple(1, 1.5f, input_msg(2)); 7651c0b2f7Stbbdev 77*de0109beSIlya Mishin CHECK_MESSAGE((testing_node.try_put(my_tuple)), "`try_put()' must always returns `true'"); 7851c0b2f7Stbbdev g.wait_for_all(); 79*de0109beSIlya Mishin auto values1 = conformance::get_values(node2); 80*de0109beSIlya Mishin auto values2 = conformance::get_values(node3); 81*de0109beSIlya Mishin auto values3 = conformance::get_values(node4); 8251c0b2f7Stbbdev 83*de0109beSIlya Mishin CHECK_MESSAGE((values1.size() == 1), "Descendant of the node must receive one message."); 84*de0109beSIlya Mishin CHECK_MESSAGE((values2.size() == 1), "Descendant of the node must receive one message."); 85*de0109beSIlya Mishin CHECK_MESSAGE((values3.size() == 1), "Descendant of the node must receive one message."); 86*de0109beSIlya Mishin CHECK_MESSAGE((values1[0] == 1), "Descendant of the node needs to be receive N messages"); 87*de0109beSIlya Mishin CHECK_MESSAGE((values2[0] == 1.5f), "Descendant of the node must receive one message."); 88*de0109beSIlya Mishin CHECK_MESSAGE((values3[0] == 2), "Descendant of the node must receive one message."); 8951c0b2f7Stbbdev } 9051c0b2f7Stbbdev 91*de0109beSIlya Mishin //! The node that is constructed has a reference to the same graph object as src. 92*de0109beSIlya Mishin //! The predecessors and successors of src are not copied. 9351c0b2f7Stbbdev //! \brief \ref interface 9451c0b2f7Stbbdev TEST_CASE("split_node copy constructor"){ 95*de0109beSIlya Mishin oneapi::tbb::flow::graph g; 96*de0109beSIlya Mishin oneapi::tbb::flow::continue_node<std::tuple<int>> node0( g, __anoned94b1790102(oneapi::tbb::flow::continue_msg) 97*de0109beSIlya Mishin [](oneapi::tbb::flow::continue_msg) { return std::tuple<int>(1); } ); 9851c0b2f7Stbbdev 99*de0109beSIlya Mishin oneapi::tbb::flow::split_node<std::tuple<int>> node1(g); 100*de0109beSIlya Mishin conformance::test_push_receiver<int> node2(g); 101*de0109beSIlya Mishin conformance::test_push_receiver<int> node3(g); 102*de0109beSIlya Mishin 103*de0109beSIlya Mishin oneapi::tbb::flow::make_edge(node0, node1); 104*de0109beSIlya Mishin oneapi::tbb::flow::make_edge(oneapi::tbb::flow::output_port<0>(node1), node2); 105*de0109beSIlya Mishin 106*de0109beSIlya Mishin oneapi::tbb::flow::split_node<std::tuple<int>> node_copy(node1); 107*de0109beSIlya Mishin 108*de0109beSIlya Mishin oneapi::tbb::flow::make_edge(oneapi::tbb::flow::output_port<0>(node_copy), node3); 109*de0109beSIlya Mishin 110*de0109beSIlya Mishin node_copy.try_put(std::tuple<int>(1)); 111*de0109beSIlya Mishin g.wait_for_all(); 112*de0109beSIlya Mishin 113*de0109beSIlya Mishin CHECK_MESSAGE((conformance::get_values(node2).size() == 0 && conformance::get_values(node3).size() == 1), "Copied node doesn`t copy successor"); 114*de0109beSIlya Mishin 115*de0109beSIlya Mishin node0.try_put(oneapi::tbb::flow::continue_msg()); 116*de0109beSIlya Mishin g.wait_for_all(); 117*de0109beSIlya Mishin 118*de0109beSIlya Mishin CHECK_MESSAGE((conformance::get_values(node2).size() == 1 && conformance::get_values(node3).size() == 0), "Copied node doesn`t copy predecessor"); 11951c0b2f7Stbbdev } 12051c0b2f7Stbbdev 12151c0b2f7Stbbdev //! Test copy constructor 12251c0b2f7Stbbdev //! \brief \ref interface 12351c0b2f7Stbbdev TEST_CASE("split_node superclasses") { 124*de0109beSIlya Mishin CHECK_MESSAGE((std::is_base_of<oneapi::tbb::flow::graph_node, my_split_type>::value), "split_node should be derived from graph_node"); 125*de0109beSIlya Mishin CHECK_MESSAGE((std::is_base_of<oneapi::tbb::flow::receiver<my_input_tuple>, my_split_type>::value), "split_node should be derived from receiver<T>"); 12651c0b2f7Stbbdev } 12751c0b2f7Stbbdev 128*de0109beSIlya Mishin //! Test split_node output_ports() returns a tuple of output ports. 129*de0109beSIlya Mishin //! \brief \ref interface \ref requirement 130*de0109beSIlya Mishin TEST_CASE("split_node output_ports") { 131*de0109beSIlya Mishin oneapi::tbb::flow::graph g; 132*de0109beSIlya Mishin my_split_type node(g); 133*de0109beSIlya Mishin 134*de0109beSIlya Mishin CHECK_MESSAGE((std::is_same<my_split_type::output_ports_type&, 135*de0109beSIlya Mishin decltype(node.output_ports())>::value), "split_node output_ports should returns a tuple of output ports"); 136*de0109beSIlya Mishin } 137