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 "common/test.h" 22 23 #include "common/utils.h" 24 #include "common/graph_utils.h" 25 26 #include "oneapi/tbb/flow_graph.h" 27 #include "oneapi/tbb/task_arena.h" 28 #include "oneapi/tbb/global_control.h" 29 30 //! \file conformance_indexer_node.cpp 31 //! \brief Test for [flow_graph.indexer_node] specification 32 33 /* 34 TODO: implement missing conformance tests for buffer_node: 35 - [ ] The copy constructor is called for the node's type template parameter. 36 - [ ] Improve `test_forwarding' by checking that the value passed is the actual one received. 37 - [ ] Improve `test_buffering' by checking that additional `try_get()' does not receive the same value. 38 - [ ] Improve tests of the constructors. 39 - [ ] Based on the decision about the details for `try_put()' and `try_get()' write corresponding tests. 40 - [ ] Fix description in `TEST_CASEs'. 41 */ 42 using namespace oneapi::tbb::flow; 43 using namespace std; 44 45 template<typename I1, typename I2> 46 void test_inheritance(){ 47 using namespace oneapi::tbb::flow; 48 49 CHECK_MESSAGE( (std::is_base_of<graph_node, indexer_node<I1, I2>>::value), "indexer_node should be derived from graph_node"); 50 } 51 52 void test_copies(){ 53 using namespace oneapi::tbb::flow; 54 55 graph g; 56 indexer_node<int, int> fn(g); 57 58 indexer_node<int, int> f2(fn); 59 } 60 61 //! Test body copying and copy_body logic 62 //! \brief \ref interface 63 TEST_CASE("indexer_node and body copying"){ 64 test_copies(); 65 } 66 67 void test_broadcasting(){ 68 oneapi::tbb::flow::graph g; 69 70 typedef indexer_node<int,float> my_indexer_type; 71 typedef my_indexer_type::output_type my_output_type; 72 73 my_indexer_type o(g); 74 75 my_indexer_type node1(g); 76 queue_node<my_output_type> node2(g); 77 queue_node<my_output_type> node3(g); 78 79 oneapi::tbb::flow::make_edge(node1, node2); 80 oneapi::tbb::flow::make_edge(node1, node3); 81 82 input_port<0>(node1).try_put(6); 83 input_port<1>(node1).try_put(1.5); 84 g.wait_for_all(); 85 86 my_output_type tmp; 87 CHECK_MESSAGE( (node2.try_get(tmp)), "Descendant of the node needs to receive message once"); 88 CHECK_MESSAGE( (node3.try_get(tmp)), "Descendant of the node needs to receive message once"); 89 } 90 91 //! Test broadcasting property 92 //! \brief \ref requirement 93 TEST_CASE("indexer_node broadcasts"){ 94 test_broadcasting(); 95 } 96 97 //! Test inheritance relations 98 //! \brief \ref interface 99 TEST_CASE("indexer_node superclasses"){ 100 test_inheritance<int, int>(); 101 } 102 103 //! Test discarding property 104 //! \brief \ref requirement 105 TEST_CASE("indexer_node discarding") { 106 graph g; 107 108 typedef indexer_node<int,float> my_indexer_type; 109 my_indexer_type o(g); 110 111 limiter_node< my_indexer_type::output_type > rejecter( g,0); 112 make_edge( o, rejecter ); 113 114 input_port<0>(o).try_put(6); 115 input_port<1>(o).try_put(1.5); 116 117 my_indexer_type::output_type tmp; 118 CHECK_MESSAGE((o.try_get(tmp) == false), "Value should be discarded after rejection"); 119 g.wait_for_all(); 120 } 121 122 //! Test indexer body 123 //! \brief \ref requirement 124 TEST_CASE("indexer_node body") { 125 graph g; 126 function_node<int,int> f1( g, unlimited, 127 [](const int &i) { return 2*i; } ); 128 function_node<float,float> f2( g, unlimited, 129 [](const float &f) { return f/2; } ); 130 131 typedef indexer_node<int,float> my_indexer_type; 132 my_indexer_type o(g); 133 134 function_node< my_indexer_type::output_type > 135 f3( g, unlimited, 136 []( const my_indexer_type::output_type &v ) { 137 if (v.tag() == 0) { 138 CHECK_MESSAGE( (cast_to<int>(v) == 6), "Expected to receive 6" ); 139 } else { 140 CHECK_MESSAGE( (cast_to<float>(v) == 1.5), "Expected to receive 1.5" ); 141 } 142 } 143 ); 144 make_edge( f1, input_port<0>(o) ); 145 make_edge( f2, input_port<1>(o) ); 146 make_edge( o, f3 ); 147 148 f1.try_put( 3 ); 149 f2.try_put( 3 ); 150 g.wait_for_all(); 151 } 152