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