1 /* 2 Copyright (c) 2020-2021 Intel Corporation 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 #if __INTEL_COMPILER && _MSC_VER 18 #pragma warning(disable : 2586) // decorated name length exceeded, name was truncated 19 #endif 20 21 #include "conformance_flowgraph.h" 22 23 //! \file conformance_indexer_node.cpp 24 //! \brief Test for [flow_graph.indexer_node] specification 25 26 using input_msg = conformance::message</*default_ctor*/false, /*copy_ctor*/true, /*copy_assign*/false>; 27 using my_indexer_type = oneapi::tbb::flow::indexer_node<int, float, input_msg>; 28 using my_output_type = my_indexer_type::output_type; 29 30 //! Test node broadcast messages to successors 31 //! \brief \ref requirement 32 TEST_CASE("indexer_node broadcasts"){ 33 oneapi::tbb::flow::graph g; 34 35 my_indexer_type testing_node(g); 36 std::vector<conformance::test_push_receiver<my_output_type>*> receiver_nodes; 37 38 for(std::size_t i = 0; i < 3; ++i) { 39 receiver_nodes.emplace_back(new conformance::test_push_receiver<my_output_type>(g)); 40 oneapi::tbb::flow::make_edge(testing_node, *receiver_nodes.back()); 41 } 42 43 oneapi::tbb::flow::input_port<0>(testing_node).try_put(6); 44 oneapi::tbb::flow::input_port<1>(testing_node).try_put(1.5); 45 oneapi::tbb::flow::input_port<2>(testing_node).try_put(input_msg(1)); 46 g.wait_for_all(); 47 48 for(auto receiver: receiver_nodes) { 49 auto values = conformance::get_values(*receiver); 50 CHECK_MESSAGE((values.size() == 3), std::string("Descendant of the node must receive 3 messages.")); 51 for(auto& value : values){ 52 if(value.is_a<int>()){ 53 CHECK_MESSAGE((value.cast_to<int>() == 6), "Value passed is the actual one received."); 54 } else if(value.is_a<float>()){ 55 CHECK_MESSAGE((value.cast_to<float>() == 1.5), "Value passed is the actual one received."); 56 } else { 57 CHECK_MESSAGE((value.cast_to<input_msg>() == 1), "Value passed is the actual one received."); 58 } 59 } 60 delete receiver; 61 } 62 } 63 64 //! Test inheritance relations 65 //! \brief \ref interface 66 TEST_CASE("indexer_node superclasses"){ 67 CHECK_MESSAGE((std::is_base_of<oneapi::tbb::flow::graph_node, my_indexer_type>::value), "indexer_node should be derived from graph_node"); 68 } 69 70 //! Test node not buffered unsuccessful message, and try_get after rejection should not succeed. 71 //! \brief \ref requirement 72 TEST_CASE("indexer_node buffering") { 73 oneapi::tbb::flow::graph g; 74 75 my_indexer_type testing_node(g); 76 77 oneapi::tbb::flow::limiter_node<my_output_type> rejecter(g,0); 78 oneapi::tbb::flow::make_edge(testing_node, rejecter); 79 80 oneapi::tbb::flow::input_port<0>(testing_node).try_put(6); 81 oneapi::tbb::flow::input_port<1>(testing_node).try_put(1.5); 82 oneapi::tbb::flow::input_port<2>(testing_node).try_put(input_msg(1)); 83 84 my_output_type tmp; 85 CHECK_MESSAGE((testing_node.try_get(tmp) == false), "Value should be discarded after rejection"); 86 g.wait_for_all(); 87 } 88 89 //! Test indexer behaviour 90 //! \brief \ref requirement 91 TEST_CASE("indexer_node behaviour") { 92 oneapi::tbb::flow::graph g; 93 oneapi::tbb::flow::function_node<int, int> f1( g, oneapi::tbb::flow::unlimited, 94 [](const int &i) { return 2*i; } ); 95 oneapi::tbb::flow::function_node<float, float> f2( g, oneapi::tbb::flow::unlimited, 96 [](const float &f) { return f/2; } ); 97 oneapi::tbb::flow::continue_node<input_msg> c1( g, 98 [](oneapi::tbb::flow::continue_msg) { return input_msg(5); } ); 99 100 my_indexer_type testing_node(g); 101 102 oneapi::tbb::flow::function_node<my_output_type> 103 f3( g, oneapi::tbb::flow::unlimited, 104 []( const my_output_type &v ) { 105 if (v.tag() == 0) { 106 CHECK_MESSAGE((v.is_a<int>()), "Expected to int" ); 107 CHECK_MESSAGE((oneapi::tbb::flow::cast_to<int>(v) == 6), "Expected to receive 6" ); 108 } else if (v.tag() == 1) { 109 CHECK_MESSAGE((v.is_a<float>()), "Expected to float" ); 110 CHECK_MESSAGE((oneapi::tbb::flow::cast_to<float>(v) == 1.5), "Expected to receive 1.5" ); 111 } else { 112 CHECK_MESSAGE((v.is_a<input_msg>()), "Expected to float" ); 113 CHECK_MESSAGE((oneapi::tbb::flow::cast_to<input_msg>(v) == 5), "Expected to receive input_msg(5)" ); 114 } 115 } 116 ); 117 118 oneapi::tbb::flow::make_edge(f1, oneapi::tbb::flow::input_port<0>(testing_node)); 119 oneapi::tbb::flow::make_edge(f2, oneapi::tbb::flow::input_port<1>(testing_node)); 120 oneapi::tbb::flow::make_edge(c1, oneapi::tbb::flow::input_port<2>(testing_node)); 121 oneapi::tbb::flow::make_edge(testing_node, f3); 122 123 f1.try_put(3); 124 f2.try_put(3); 125 c1.try_put(oneapi::tbb::flow::continue_msg()); 126 g.wait_for_all(); 127 } 128 129 //! The node that is constructed has a reference to the same graph object as src. 130 //! The list of predecessors, messages in the input ports, and successors are not copied. 131 //! \brief \ref interface 132 TEST_CASE("indexer_node copy constructor"){ 133 oneapi::tbb::flow::graph g; 134 oneapi::tbb::flow::continue_node<int> node0( g, 135 [](oneapi::tbb::flow::continue_msg) { return 1; } ); 136 137 my_indexer_type node1(g); 138 conformance::test_push_receiver<my_output_type> node2(g); 139 conformance::test_push_receiver<my_output_type> node3(g); 140 141 oneapi::tbb::flow::make_edge(node0, oneapi::tbb::flow::input_port<0>(node1)); 142 oneapi::tbb::flow::make_edge(node1, node2); 143 144 my_indexer_type node_copy(node1); 145 146 oneapi::tbb::flow::make_edge(node_copy, node3); 147 148 oneapi::tbb::flow::input_port<0>(node_copy).try_put(1); 149 g.wait_for_all(); 150 151 CHECK_MESSAGE((conformance::get_values(node2).size() == 0 && conformance::get_values(node3).size() == 1), "Copied node doesn`t copy successor"); 152 153 node0.try_put(oneapi::tbb::flow::continue_msg()); 154 g.wait_for_all(); 155 156 CHECK_MESSAGE((conformance::get_values(node2).size() == 1 && conformance::get_values(node3).size() == 0), "Copied node doesn`t copy predecessor"); 157 } 158 159 //! Test indexer_node output_type 160 //! \brief \ref interface \ref requirement 161 TEST_CASE("indexer_node output_type") { 162 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 } 164