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 
21*de0109beSIlya Mishin #include "conformance_flowgraph.h"
2251c0b2f7Stbbdev 
2351c0b2f7Stbbdev //! \file conformance_indexer_node.cpp
2451c0b2f7Stbbdev //! \brief Test for [flow_graph.indexer_node] specification
2551c0b2f7Stbbdev 
26*de0109beSIlya Mishin using input_msg = conformance::message</*default_ctor*/false, /*copy_ctor*/true, /*copy_assign*/false>;
27*de0109beSIlya Mishin using my_indexer_type = oneapi::tbb::flow::indexer_node<int, float, input_msg>;
28*de0109beSIlya Mishin using my_output_type = my_indexer_type::output_type;
2951c0b2f7Stbbdev 
30*de0109beSIlya Mishin //! Test node broadcast messages to successors
3151c0b2f7Stbbdev //! \brief \ref requirement
3251c0b2f7Stbbdev TEST_CASE("indexer_node broadcasts"){
33*de0109beSIlya Mishin     oneapi::tbb::flow::graph g;
34*de0109beSIlya Mishin 
35*de0109beSIlya Mishin     my_indexer_type testing_node(g);
36*de0109beSIlya Mishin     std::vector<conformance::test_push_receiver<my_output_type>*> receiver_nodes;
37*de0109beSIlya Mishin 
38*de0109beSIlya Mishin     for(std::size_t i = 0; i < 3; ++i) {
39*de0109beSIlya Mishin         receiver_nodes.emplace_back(new conformance::test_push_receiver<my_output_type>(g));
40*de0109beSIlya Mishin         oneapi::tbb::flow::make_edge(testing_node, *receiver_nodes.back());
41*de0109beSIlya Mishin     }
42*de0109beSIlya Mishin 
43*de0109beSIlya Mishin     oneapi::tbb::flow::input_port<0>(testing_node).try_put(6);
44*de0109beSIlya Mishin     oneapi::tbb::flow::input_port<1>(testing_node).try_put(1.5);
45*de0109beSIlya Mishin     oneapi::tbb::flow::input_port<2>(testing_node).try_put(input_msg(1));
46*de0109beSIlya Mishin     g.wait_for_all();
47*de0109beSIlya Mishin 
48*de0109beSIlya Mishin     for(auto receiver: receiver_nodes) {
49*de0109beSIlya Mishin         auto values = conformance::get_values(*receiver);
50*de0109beSIlya Mishin         CHECK_MESSAGE((values.size() == 3), std::string("Descendant of the node must receive 3 messages."));
51*de0109beSIlya Mishin         for(auto& value : values){
52*de0109beSIlya Mishin             if(value.is_a<int>()){
53*de0109beSIlya Mishin                 CHECK_MESSAGE((value.cast_to<int>() == 6), "Value passed is the actual one received.");
54*de0109beSIlya Mishin             } else if(value.is_a<float>()){
55*de0109beSIlya Mishin                 CHECK_MESSAGE((value.cast_to<float>() == 1.5), "Value passed is the actual one received.");
56*de0109beSIlya Mishin             } else {
57*de0109beSIlya Mishin                 CHECK_MESSAGE((value.cast_to<input_msg>() == 1), "Value passed is the actual one received.");
58*de0109beSIlya Mishin             }
59*de0109beSIlya Mishin         }
60*de0109beSIlya Mishin         delete receiver;
61*de0109beSIlya Mishin     }
6251c0b2f7Stbbdev }
6351c0b2f7Stbbdev 
6451c0b2f7Stbbdev //! Test inheritance relations
6551c0b2f7Stbbdev //! \brief \ref interface
6651c0b2f7Stbbdev TEST_CASE("indexer_node superclasses"){
67*de0109beSIlya Mishin     CHECK_MESSAGE((std::is_base_of<oneapi::tbb::flow::graph_node, my_indexer_type>::value), "indexer_node should be derived from graph_node");
6851c0b2f7Stbbdev }
6951c0b2f7Stbbdev 
70*de0109beSIlya Mishin //! Test node not buffered unsuccessful message, and try_get after rejection should not succeed.
7151c0b2f7Stbbdev //! \brief \ref requirement
72*de0109beSIlya Mishin TEST_CASE("indexer_node buffering") {
73*de0109beSIlya Mishin     oneapi::tbb::flow::graph g;
7451c0b2f7Stbbdev 
75*de0109beSIlya Mishin     my_indexer_type testing_node(g);
7651c0b2f7Stbbdev 
77*de0109beSIlya Mishin     oneapi::tbb::flow::limiter_node<my_output_type> rejecter(g,0);
78*de0109beSIlya Mishin     oneapi::tbb::flow::make_edge(testing_node, rejecter);
7951c0b2f7Stbbdev 
80*de0109beSIlya Mishin     oneapi::tbb::flow::input_port<0>(testing_node).try_put(6);
81*de0109beSIlya Mishin     oneapi::tbb::flow::input_port<1>(testing_node).try_put(1.5);
82*de0109beSIlya Mishin     oneapi::tbb::flow::input_port<2>(testing_node).try_put(input_msg(1));
8351c0b2f7Stbbdev 
84*de0109beSIlya Mishin     my_output_type tmp;
85*de0109beSIlya Mishin     CHECK_MESSAGE((testing_node.try_get(tmp) == false), "Value should be discarded after rejection");
8651c0b2f7Stbbdev     g.wait_for_all();
8751c0b2f7Stbbdev }
8851c0b2f7Stbbdev 
89*de0109beSIlya Mishin //! Test indexer behaviour
9051c0b2f7Stbbdev //! \brief \ref requirement
91*de0109beSIlya Mishin TEST_CASE("indexer_node behaviour") {
92*de0109beSIlya Mishin     oneapi::tbb::flow::graph g;
93*de0109beSIlya Mishin     oneapi::tbb::flow::function_node<int, int> f1( g, oneapi::tbb::flow::unlimited,
__anon3412adbc0102(const int &i) 9451c0b2f7Stbbdev                                 [](const int &i) { return 2*i; } );
95*de0109beSIlya Mishin     oneapi::tbb::flow::function_node<float, float> f2( g, oneapi::tbb::flow::unlimited,
__anon3412adbc0202(const float &f) 9651c0b2f7Stbbdev                                 [](const float &f) { return f/2; } );
97*de0109beSIlya Mishin     oneapi::tbb::flow::continue_node<input_msg> c1( g,
__anon3412adbc0302(oneapi::tbb::flow::continue_msg) 98*de0109beSIlya Mishin                                 [](oneapi::tbb::flow::continue_msg) { return input_msg(5); } );
9951c0b2f7Stbbdev 
100*de0109beSIlya Mishin     my_indexer_type testing_node(g);
10151c0b2f7Stbbdev 
102*de0109beSIlya Mishin     oneapi::tbb::flow::function_node<my_output_type>
103*de0109beSIlya Mishin         f3( g, oneapi::tbb::flow::unlimited,
__anon3412adbc0402( const my_output_type &v ) 104*de0109beSIlya Mishin             []( const my_output_type &v ) {
10551c0b2f7Stbbdev                 if (v.tag() == 0) {
106*de0109beSIlya Mishin                     CHECK_MESSAGE((v.is_a<int>()), "Expected to int" );
107*de0109beSIlya Mishin                     CHECK_MESSAGE((oneapi::tbb::flow::cast_to<int>(v) == 6), "Expected to receive 6" );
108*de0109beSIlya Mishin                 } else if (v.tag() == 1) {
109*de0109beSIlya Mishin                     CHECK_MESSAGE((v.is_a<float>()), "Expected to float" );
110*de0109beSIlya Mishin                     CHECK_MESSAGE((oneapi::tbb::flow::cast_to<float>(v) == 1.5), "Expected to receive 1.5" );
11151c0b2f7Stbbdev                 } else {
112*de0109beSIlya Mishin                     CHECK_MESSAGE((v.is_a<input_msg>()), "Expected to float" );
113*de0109beSIlya Mishin                     CHECK_MESSAGE((oneapi::tbb::flow::cast_to<input_msg>(v) == 5), "Expected to receive input_msg(5)" );
11451c0b2f7Stbbdev                 }
11551c0b2f7Stbbdev             }
11651c0b2f7Stbbdev         );
117*de0109beSIlya Mishin 
118*de0109beSIlya Mishin     oneapi::tbb::flow::make_edge(f1, oneapi::tbb::flow::input_port<0>(testing_node));
119*de0109beSIlya Mishin     oneapi::tbb::flow::make_edge(f2, oneapi::tbb::flow::input_port<1>(testing_node));
120*de0109beSIlya Mishin     oneapi::tbb::flow::make_edge(c1, oneapi::tbb::flow::input_port<2>(testing_node));
121*de0109beSIlya Mishin     oneapi::tbb::flow::make_edge(testing_node, f3);
12251c0b2f7Stbbdev 
12351c0b2f7Stbbdev     f1.try_put(3);
12451c0b2f7Stbbdev     f2.try_put(3);
125*de0109beSIlya Mishin     c1.try_put(oneapi::tbb::flow::continue_msg());
12651c0b2f7Stbbdev     g.wait_for_all();
12751c0b2f7Stbbdev }
128*de0109beSIlya Mishin 
129*de0109beSIlya Mishin //! The node that is constructed has a reference to the same graph object as src.
130*de0109beSIlya Mishin //! The list of predecessors, messages in the input ports, and successors are not copied.
131*de0109beSIlya Mishin //! \brief \ref interface
132*de0109beSIlya Mishin TEST_CASE("indexer_node copy constructor"){
133*de0109beSIlya Mishin     oneapi::tbb::flow::graph g;
134*de0109beSIlya Mishin     oneapi::tbb::flow::continue_node<int> node0( g,
__anon3412adbc0502(oneapi::tbb::flow::continue_msg) 135*de0109beSIlya Mishin                                 [](oneapi::tbb::flow::continue_msg) { return 1; } );
136*de0109beSIlya Mishin 
137*de0109beSIlya Mishin     my_indexer_type node1(g);
138*de0109beSIlya Mishin     conformance::test_push_receiver<my_output_type> node2(g);
139*de0109beSIlya Mishin     conformance::test_push_receiver<my_output_type> node3(g);
140*de0109beSIlya Mishin 
141*de0109beSIlya Mishin     oneapi::tbb::flow::make_edge(node0, oneapi::tbb::flow::input_port<0>(node1));
142*de0109beSIlya Mishin     oneapi::tbb::flow::make_edge(node1, node2);
143*de0109beSIlya Mishin 
144*de0109beSIlya Mishin     my_indexer_type node_copy(node1);
145*de0109beSIlya Mishin 
146*de0109beSIlya Mishin     oneapi::tbb::flow::make_edge(node_copy, node3);
147*de0109beSIlya Mishin 
148*de0109beSIlya Mishin     oneapi::tbb::flow::input_port<0>(node_copy).try_put(1);
149*de0109beSIlya Mishin     g.wait_for_all();
150*de0109beSIlya Mishin 
151*de0109beSIlya Mishin     CHECK_MESSAGE((conformance::get_values(node2).size() == 0 && conformance::get_values(node3).size() == 1), "Copied node doesn`t copy successor");
152*de0109beSIlya Mishin 
153*de0109beSIlya Mishin     node0.try_put(oneapi::tbb::flow::continue_msg());
154*de0109beSIlya Mishin     g.wait_for_all();
155*de0109beSIlya Mishin 
156*de0109beSIlya Mishin     CHECK_MESSAGE((conformance::get_values(node2).size() == 1 && conformance::get_values(node3).size() == 0), "Copied node doesn`t copy predecessor");
157*de0109beSIlya Mishin }
158*de0109beSIlya Mishin 
159*de0109beSIlya Mishin //! Test indexer_node output_type
160*de0109beSIlya Mishin //! \brief \ref interface \ref requirement
161*de0109beSIlya Mishin TEST_CASE("indexer_node output_type") {
162*de0109beSIlya Mishin     CHECK_MESSAGE((conformance::check_output_type<my_output_type, oneapi::tbb::flow::tagged_msg<size_t, int, float, input_msg>>()), "indexer_node output_type should returns a tagged_msg");
163*de0109beSIlya Mishin }
164