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_composite_node.cpp 2451c0b2f7Stbbdev //! \brief Test for [flow_graph.composite_node] specification 2551c0b2f7Stbbdev 26*de0109beSIlya Mishin class adder : public oneapi::tbb::flow::composite_node<std::tuple<int, int>, std::tuple<int>> { 27*de0109beSIlya Mishin oneapi::tbb::flow::join_node<std::tuple<int,int>, oneapi::tbb::flow::queueing> j; 28*de0109beSIlya Mishin oneapi::tbb::flow::function_node<std::tuple<int,int>, int> f; 29*de0109beSIlya Mishin oneapi::tbb::flow::queue_node<int> qn; 30*de0109beSIlya Mishin using base_type = oneapi::tbb::flow::composite_node<std::tuple<int,int>, std::tuple<int>>; 3151c0b2f7Stbbdev 3251c0b2f7Stbbdev struct f_body { operator ()adder::f_body33*de0109beSIlya Mishin int operator()(const std::tuple<int,int> &t) { 34*de0109beSIlya Mishin int sum = std::get<0>(t) + std::get<1>(t); 3551c0b2f7Stbbdev return sum; 3651c0b2f7Stbbdev } 3751c0b2f7Stbbdev }; 3851c0b2f7Stbbdev 3951c0b2f7Stbbdev public: adder(oneapi::tbb::flow::graph & g)40*de0109beSIlya Mishin adder(oneapi::tbb::flow::graph &g) : base_type(g), j(g), f(g, oneapi::tbb::flow::unlimited, f_body()), qn(g) { 4151c0b2f7Stbbdev make_edge(j, f); 4251c0b2f7Stbbdev make_edge(f, qn); 4351c0b2f7Stbbdev 44*de0109beSIlya Mishin base_type::input_ports_type input_tuple(oneapi::tbb::flow::input_port<0>(j), oneapi::tbb::flow::input_port<1>(j)); 4551c0b2f7Stbbdev base_type::output_ports_type output_tuple(qn); 4651c0b2f7Stbbdev base_type::set_external_ports(input_tuple, output_tuple); 4751c0b2f7Stbbdev } 4851c0b2f7Stbbdev }; 4951c0b2f7Stbbdev 50*de0109beSIlya Mishin template<int N, typename T1, typename T2> 51*de0109beSIlya Mishin struct compare { compare_refscompare52*de0109beSIlya Mishin static void compare_refs(T1 tuple1, T2 tuple2) { 53*de0109beSIlya Mishin CHECK_MESSAGE(( &std::get<N>(tuple1) == &std::get<N>(tuple2)), "ports not set correctly"); 54*de0109beSIlya Mishin compare<N-1, T1, T2>::compare_refs(tuple1, tuple2); 5551c0b2f7Stbbdev } 56*de0109beSIlya Mishin }; 57*de0109beSIlya Mishin 58*de0109beSIlya Mishin template<typename T1, typename T2> 59*de0109beSIlya Mishin struct compare<1, T1, T2> { compare_refscompare60*de0109beSIlya Mishin static void compare_refs(T1 tuple1, T2 tuple2) { 61*de0109beSIlya Mishin CHECK_MESSAGE((&std::get<0>(tuple1) == &std::get<0>(tuple2)), "port 0 not correctly set"); 62*de0109beSIlya Mishin } 63*de0109beSIlya Mishin }; 6451c0b2f7Stbbdev 6551c0b2f7Stbbdev //! Test inheritance relations 6651c0b2f7Stbbdev //! \brief \ref interface 6751c0b2f7Stbbdev TEST_CASE("composite_node superclasses"){ 68*de0109beSIlya Mishin CHECK_MESSAGE((std::is_base_of<oneapi::tbb::flow::graph_node, adder>::value), "composite_node should be derived from graph_node"); 6951c0b2f7Stbbdev } 7051c0b2f7Stbbdev 71*de0109beSIlya Mishin //! Test composite_node ports 7251c0b2f7Stbbdev //! \brief \ref interface \ref requirement 73*de0109beSIlya Mishin TEST_CASE("composite_node ports"){ 74*de0109beSIlya Mishin oneapi::tbb::flow::graph g; 75*de0109beSIlya Mishin 76*de0109beSIlya Mishin using InputTupleType = std::tuple<tbb::flow::continue_msg, std::tuple<int, int>, int, int, int, int, 77*de0109beSIlya Mishin int, int, int, int, int, int, int, int>; 78*de0109beSIlya Mishin 79*de0109beSIlya Mishin using OutputTupleType = std::tuple<tbb::flow::continue_msg, std::tuple<int, int>, oneapi::tbb::flow::tagged_msg<size_t, int, float>, 80*de0109beSIlya Mishin int, int, int, int, int, int, int, int, int, int, int, int>; 81*de0109beSIlya Mishin 82*de0109beSIlya Mishin using EmptyTupleType= std::tuple<>; 83*de0109beSIlya Mishin 84*de0109beSIlya Mishin using input_output_type = oneapi::tbb::flow::composite_node<InputTupleType, OutputTupleType>; 85*de0109beSIlya Mishin using input_only_type = oneapi::tbb::flow::composite_node<InputTupleType, EmptyTupleType>; 86*de0109beSIlya Mishin using output_only_type = oneapi::tbb::flow::composite_node<EmptyTupleType, OutputTupleType>; 87*de0109beSIlya Mishin 88*de0109beSIlya Mishin const size_t NUM_INPUTS = std::tuple_size<InputTupleType>::value; 89*de0109beSIlya Mishin const size_t NUM_OUTPUTS = std::tuple_size<OutputTupleType>::value; 90*de0109beSIlya Mishin 91*de0109beSIlya Mishin using body = conformance::dummy_functor<int>; 92*de0109beSIlya Mishin 93*de0109beSIlya Mishin //node types 94*de0109beSIlya Mishin oneapi::tbb::flow::continue_node<tbb::flow::continue_msg> ct(g, body()); 95*de0109beSIlya Mishin oneapi::tbb::flow::split_node< std::tuple<int, int> > s(g); 96*de0109beSIlya Mishin oneapi::tbb::flow::input_node<int> src(g, body()); 97*de0109beSIlya Mishin oneapi::tbb::flow::function_node<int, int> fxn(g, oneapi::tbb::flow::unlimited, body()); 98*de0109beSIlya Mishin oneapi::tbb::flow::multifunction_node<int, std::tuple<int, int> > m_fxn(g, oneapi::tbb::flow::unlimited, body()); 99*de0109beSIlya Mishin oneapi::tbb::flow::broadcast_node<int> bc(g); 100*de0109beSIlya Mishin oneapi::tbb::flow::limiter_node<int> lim(g, 2); 101*de0109beSIlya Mishin oneapi::tbb::flow::indexer_node<int, float> ind(g); 102*de0109beSIlya Mishin oneapi::tbb::flow::join_node< std::tuple< int, int >, oneapi::tbb::flow::queueing > j(g); 103*de0109beSIlya Mishin oneapi::tbb::flow::queue_node<int> q(g); 104*de0109beSIlya Mishin oneapi::tbb::flow::buffer_node<int> bf(g); 105*de0109beSIlya Mishin oneapi::tbb::flow::priority_queue_node<int> pq(g); 106*de0109beSIlya Mishin oneapi::tbb::flow::write_once_node<int> wo(g); 107*de0109beSIlya Mishin oneapi::tbb::flow::overwrite_node<int> ovw(g); 108*de0109beSIlya Mishin oneapi::tbb::flow::sequencer_node<int> seq(g, conformance::sequencer_functor<int>()); 109*de0109beSIlya Mishin 110*de0109beSIlya Mishin auto input_tuple = std::tie(ct, s, m_fxn, fxn, bc, oneapi::tbb::flow::input_port<0>(j), lim, q, oneapi::tbb::flow::input_port<0>(ind), 111*de0109beSIlya Mishin pq, ovw, wo, bf, seq); 112*de0109beSIlya Mishin auto output_tuple = std::tie(ct,j, ind, fxn, src, bc, oneapi::tbb::flow::output_port<0>(s), lim, oneapi::tbb::flow::output_port<0>(m_fxn), 113*de0109beSIlya Mishin q, pq, ovw, wo, bf, seq); 114*de0109beSIlya Mishin 115*de0109beSIlya Mishin //composite_node with both input_ports and output_ports 116*de0109beSIlya Mishin input_output_type a_node(g); 117*de0109beSIlya Mishin a_node.set_external_ports(input_tuple, output_tuple); 118*de0109beSIlya Mishin 119*de0109beSIlya Mishin a_node.add_visible_nodes(src, fxn, m_fxn, bc, lim, ind, s, ct, j, q, bf, pq, wo, ovw, seq); 120*de0109beSIlya Mishin a_node.add_nodes(src, fxn, m_fxn, bc, lim, ind, s, ct, j, q, bf, pq, wo, ovw, seq); 121*de0109beSIlya Mishin 122*de0109beSIlya Mishin auto a_node_input_ports_ptr = a_node.input_ports(); 123*de0109beSIlya Mishin compare<NUM_INPUTS-1, decltype(a_node_input_ports_ptr), decltype(input_tuple)>::compare_refs(a_node_input_ports_ptr, input_tuple); 124*de0109beSIlya Mishin CHECK_MESSAGE(NUM_INPUTS == std::tuple_size<decltype(a_node_input_ports_ptr)>::value, "not all declared input ports were bound to nodes"); 125*de0109beSIlya Mishin 126*de0109beSIlya Mishin auto a_node_output_ports_ptr = a_node.output_ports(); 127*de0109beSIlya Mishin compare<NUM_OUTPUTS-1, decltype(a_node_output_ports_ptr), decltype(output_tuple)>::compare_refs(a_node_output_ports_ptr, output_tuple); 128*de0109beSIlya Mishin CHECK_MESSAGE((NUM_OUTPUTS == std::tuple_size<decltype(a_node_output_ports_ptr)>::value), "not all declared output ports were bound to nodes"); 129*de0109beSIlya Mishin 130*de0109beSIlya Mishin //composite_node with only input_ports 131*de0109beSIlya Mishin input_only_type b_node(g); 132*de0109beSIlya Mishin b_node.set_external_ports(input_tuple); 133*de0109beSIlya Mishin 134*de0109beSIlya Mishin b_node.add_visible_nodes(src, fxn, m_fxn, bc, lim, ind, s, ct, j, q, bf, pq, wo, ovw, seq); 135*de0109beSIlya Mishin b_node.add_nodes(src, fxn, m_fxn, bc, lim, ind, s, ct, j, q, bf, pq, wo, ovw, seq); 136*de0109beSIlya Mishin 137*de0109beSIlya Mishin auto b_node_input_ports_ptr = b_node.input_ports(); 138*de0109beSIlya Mishin compare<NUM_INPUTS-1, decltype(b_node_input_ports_ptr), decltype(input_tuple)>::compare_refs(b_node_input_ports_ptr, input_tuple); 139*de0109beSIlya Mishin CHECK_MESSAGE(NUM_INPUTS == std::tuple_size<decltype(b_node_input_ports_ptr)>::value, "not all declared input ports were bound to nodes"); 140*de0109beSIlya Mishin 141*de0109beSIlya Mishin //composite_node with only output_ports 142*de0109beSIlya Mishin output_only_type c_node(g); 143*de0109beSIlya Mishin c_node.set_external_ports(output_tuple); 144*de0109beSIlya Mishin 145*de0109beSIlya Mishin // Reset is not suppose to do anything. Check that it can be called. 146*de0109beSIlya Mishin g.reset(); 147*de0109beSIlya Mishin 148*de0109beSIlya Mishin c_node.add_visible_nodes(src, fxn, m_fxn, bc, lim, ind, s, ct, j, q, bf, pq, wo, ovw, seq); 149*de0109beSIlya Mishin 150*de0109beSIlya Mishin c_node.add_nodes(src, fxn, m_fxn, bc, lim, ind, s, ct, j, q, bf, pq, wo, ovw, seq); 151*de0109beSIlya Mishin 152*de0109beSIlya Mishin auto c_node_output_ports_ptr = c_node.output_ports(); 153*de0109beSIlya Mishin compare<NUM_OUTPUTS-1, decltype(c_node_output_ports_ptr), decltype(output_tuple)>::compare_refs(c_node_output_ports_ptr, output_tuple); 154*de0109beSIlya Mishin CHECK_MESSAGE(NUM_OUTPUTS == std::tuple_size<decltype(c_node_output_ports_ptr)>::value, "not all declared input ports were bound to nodes"); 155*de0109beSIlya Mishin } 156*de0109beSIlya Mishin 157*de0109beSIlya Mishin //! Test composite_node construction and message passing 158*de0109beSIlya Mishin //! \brief \ref interface \ref requirement 159*de0109beSIlya Mishin TEST_CASE("composite_node construction and message test"){ 160*de0109beSIlya Mishin using namespace oneapi::tbb::flow; 16151c0b2f7Stbbdev graph g; 162*de0109beSIlya Mishin split_node<std::tuple<int, int, int, int>> s(g); 16351c0b2f7Stbbdev adder a0(g); 16451c0b2f7Stbbdev adder a1(g); 16551c0b2f7Stbbdev adder a2(g); 16651c0b2f7Stbbdev 16751c0b2f7Stbbdev make_edge(output_port<0>(s), input_port<0>(a0)); 16851c0b2f7Stbbdev make_edge(output_port<1>(s), input_port<1>(a0)); 16951c0b2f7Stbbdev 17051c0b2f7Stbbdev make_edge(output_port<0>(a0),input_port<0>(a1)); 17151c0b2f7Stbbdev make_edge(output_port<2>(s), input_port<1>(a1)); 17251c0b2f7Stbbdev 17351c0b2f7Stbbdev make_edge(output_port<0>(a1), input_port<0>(a2)); 17451c0b2f7Stbbdev make_edge(output_port<3>(s), input_port<1>(a2)); 17551c0b2f7Stbbdev 17651c0b2f7Stbbdev s.try_put(std::make_tuple(1,3,5,7)); 17751c0b2f7Stbbdev g.wait_for_all(); 17851c0b2f7Stbbdev 17951c0b2f7Stbbdev int tmp = -1; 18051c0b2f7Stbbdev CHECK_MESSAGE((output_port<0>(a2).try_get(tmp) == true), "Composite node should produce a value"); 18151c0b2f7Stbbdev CHECK_MESSAGE((tmp == 1+3+5+7), "Composite node should produce correct sum"); 18251c0b2f7Stbbdev } 183