151c0b2f7Stbbdev /*
2c21e688aSSergey Zheltov Copyright (c) 2005-2022 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
20b15aabb3Stbbdev
2151c0b2f7Stbbdev #include "common/config.h"
2251c0b2f7Stbbdev
2351c0b2f7Stbbdev #include "tbb/flow_graph.h"
2451c0b2f7Stbbdev
2551c0b2f7Stbbdev #include "common/test.h"
2651c0b2f7Stbbdev #include "common/utils.h"
2751c0b2f7Stbbdev #include "common/utils_assert.h"
2851c0b2f7Stbbdev #include "common/test_follows_and_precedes_api.h"
2951c0b2f7Stbbdev
3051c0b2f7Stbbdev
3151c0b2f7Stbbdev //! \file test_indexer_node.cpp
3251c0b2f7Stbbdev //! \brief Test for [flow_graph.indexer_node] specification
3351c0b2f7Stbbdev
3451c0b2f7Stbbdev
3551c0b2f7Stbbdev #if defined(_MSC_VER) && _MSC_VER < 1600
3651c0b2f7Stbbdev #pragma warning (disable : 4503) //disabling the "decorated name length exceeded" warning for VS2008 and earlier
3751c0b2f7Stbbdev #endif
3851c0b2f7Stbbdev
3951c0b2f7Stbbdev const int Count = 150;
4051c0b2f7Stbbdev const int MaxPorts = 10;
4151c0b2f7Stbbdev const int MaxNInputs = 5; // max # of input_nodes to register for each indexer_node input in parallel test
4251c0b2f7Stbbdev bool outputCheck[MaxPorts][Count]; // for checking output
4351c0b2f7Stbbdev
4451c0b2f7Stbbdev void
check_outputCheck(int nUsed,int maxCnt)4551c0b2f7Stbbdev check_outputCheck( int nUsed, int maxCnt) {
4651c0b2f7Stbbdev for(int i=0; i < nUsed; ++i) {
4751c0b2f7Stbbdev for( int j = 0; j < maxCnt; ++j) {
4851c0b2f7Stbbdev CHECK_MESSAGE(outputCheck[i][j], "");
4951c0b2f7Stbbdev }
5051c0b2f7Stbbdev }
5151c0b2f7Stbbdev }
5251c0b2f7Stbbdev
5351c0b2f7Stbbdev void
reset_outputCheck(int nUsed,int maxCnt)5451c0b2f7Stbbdev reset_outputCheck( int nUsed, int maxCnt) {
5551c0b2f7Stbbdev for(int i=0; i < nUsed; ++i) {
5651c0b2f7Stbbdev for( int j = 0; j < maxCnt; ++j) {
5751c0b2f7Stbbdev outputCheck[i][j] = false;
5851c0b2f7Stbbdev }
5951c0b2f7Stbbdev }
6051c0b2f7Stbbdev }
6151c0b2f7Stbbdev
6251c0b2f7Stbbdev class test_class {
6351c0b2f7Stbbdev public:
test_class()6451c0b2f7Stbbdev test_class() { my_val = 0; }
test_class(int i)6551c0b2f7Stbbdev test_class(int i) { my_val = i; }
operator int()6651c0b2f7Stbbdev operator int() { return my_val; }
6751c0b2f7Stbbdev private:
6851c0b2f7Stbbdev int my_val;
6951c0b2f7Stbbdev };
7051c0b2f7Stbbdev
7151c0b2f7Stbbdev template<typename T>
7251c0b2f7Stbbdev class name_of {
7351c0b2f7Stbbdev public:
name()7451c0b2f7Stbbdev static const char* name() { return "Unknown"; }
7551c0b2f7Stbbdev };
7651c0b2f7Stbbdev template<>
7751c0b2f7Stbbdev class name_of<int> {
7851c0b2f7Stbbdev public:
name()7951c0b2f7Stbbdev static const char* name() { return "int"; }
8051c0b2f7Stbbdev };
8151c0b2f7Stbbdev template<>
8251c0b2f7Stbbdev class name_of<float> {
8351c0b2f7Stbbdev public:
name()8451c0b2f7Stbbdev static const char* name() { return "float"; }
8551c0b2f7Stbbdev };
8651c0b2f7Stbbdev template<>
8751c0b2f7Stbbdev class name_of<double> {
8851c0b2f7Stbbdev public:
name()8951c0b2f7Stbbdev static const char* name() { return "double"; }
9051c0b2f7Stbbdev };
9151c0b2f7Stbbdev template<>
9251c0b2f7Stbbdev class name_of<long> {
9351c0b2f7Stbbdev public:
name()9451c0b2f7Stbbdev static const char* name() { return "long"; }
9551c0b2f7Stbbdev };
9651c0b2f7Stbbdev template<>
9751c0b2f7Stbbdev class name_of<short> {
9851c0b2f7Stbbdev public:
name()9951c0b2f7Stbbdev static const char* name() { return "short"; }
10051c0b2f7Stbbdev };
10151c0b2f7Stbbdev template<>
10251c0b2f7Stbbdev class name_of<test_class> {
10351c0b2f7Stbbdev public:
name()10451c0b2f7Stbbdev static const char* name() { return "test_class"; }
10551c0b2f7Stbbdev };
10651c0b2f7Stbbdev
10751c0b2f7Stbbdev // TT must be arithmetic, and shouldn't wrap around for reasonable sizes of Count (which is now 150, and maxPorts is 10,
10851c0b2f7Stbbdev // so the max number generated right now is 1500 or so.) Input will generate a series of TT with value
10951c0b2f7Stbbdev // (init_val + (i-1)*addend) * my_mult, where i is the i-th invocation of the body. We are attaching addend
11051c0b2f7Stbbdev // input nodes to a indexer_port, and each will generate part of the numerical series the port is expecting
11151c0b2f7Stbbdev // to receive. If there is only one input node, the series order will be maintained; if more than one,
11251c0b2f7Stbbdev // this is not guaranteed.
11351c0b2f7Stbbdev // The manual specifies bodies can be assigned, so we can't hide the operator=.
11451c0b2f7Stbbdev template<typename TT>
11551c0b2f7Stbbdev class my_input_body {
11651c0b2f7Stbbdev TT my_mult;
11751c0b2f7Stbbdev int my_count;
11851c0b2f7Stbbdev int addend;
11951c0b2f7Stbbdev public:
my_input_body(TT multiplier,int init_val,int addto)12051c0b2f7Stbbdev my_input_body(TT multiplier, int init_val, int addto) : my_mult(multiplier), my_count(init_val), addend(addto) { }
operator ()(tbb::flow_control & fc)12151c0b2f7Stbbdev TT operator()( tbb::flow_control& fc) {
12251c0b2f7Stbbdev int lc = my_count;
12351c0b2f7Stbbdev TT ret = my_mult * (TT)my_count;
12451c0b2f7Stbbdev my_count += addend;
12551c0b2f7Stbbdev if ( lc < Count){
12651c0b2f7Stbbdev return ret;
12751c0b2f7Stbbdev }else{
12851c0b2f7Stbbdev fc.stop();
12951c0b2f7Stbbdev return TT();
13051c0b2f7Stbbdev }
13151c0b2f7Stbbdev }
13251c0b2f7Stbbdev };
13351c0b2f7Stbbdev
13451c0b2f7Stbbdev // allocator for indexer_node.
13551c0b2f7Stbbdev
13651c0b2f7Stbbdev template<typename IType>
13751c0b2f7Stbbdev class makeIndexer {
13851c0b2f7Stbbdev public:
create()13951c0b2f7Stbbdev static IType *create() {
14051c0b2f7Stbbdev IType *temp = new IType();
14151c0b2f7Stbbdev return temp;
14251c0b2f7Stbbdev }
destroy(IType * p)14351c0b2f7Stbbdev static void destroy(IType *p) { delete p; }
14451c0b2f7Stbbdev };
14551c0b2f7Stbbdev
14651c0b2f7Stbbdev template<int ELEM, typename INT>
14751c0b2f7Stbbdev struct getval_helper {
14851c0b2f7Stbbdev
14951c0b2f7Stbbdev typedef typename INT::output_type OT;
15051c0b2f7Stbbdev typedef typename std::tuple_element<ELEM-1, typename INT::tuple_types>::type stored_type;
15151c0b2f7Stbbdev
get_integer_valgetval_helper15251c0b2f7Stbbdev static int get_integer_val(OT const &o) {
15351c0b2f7Stbbdev stored_type res = tbb::flow::cast_to<stored_type>(o);
15451c0b2f7Stbbdev return (int)res;
15551c0b2f7Stbbdev }
15651c0b2f7Stbbdev };
15751c0b2f7Stbbdev
15851c0b2f7Stbbdev // holder for input_node pointers for eventual deletion
15951c0b2f7Stbbdev
16051c0b2f7Stbbdev static void* all_input_nodes[MaxPorts][MaxNInputs];
16151c0b2f7Stbbdev
16251c0b2f7Stbbdev template<int ELEM, typename INT>
16351c0b2f7Stbbdev class input_node_helper {
16451c0b2f7Stbbdev public:
16551c0b2f7Stbbdev typedef INT indexer_node_type;
16651c0b2f7Stbbdev typedef typename indexer_node_type::output_type TT;
16751c0b2f7Stbbdev typedef typename std::tuple_element<ELEM-1,typename INT::tuple_types>::type IT;
16851c0b2f7Stbbdev typedef typename tbb::flow::input_node<IT> my_input_node_type;
print_remark()16951c0b2f7Stbbdev static void print_remark() {
17051c0b2f7Stbbdev input_node_helper<ELEM-1,INT>::print_remark();
17151c0b2f7Stbbdev INFO(", " << name_of<IT>::name());
17251c0b2f7Stbbdev }
add_input_nodes(indexer_node_type & my_indexer,tbb::flow::graph & g,int nInputs)17351c0b2f7Stbbdev static void add_input_nodes(indexer_node_type &my_indexer, tbb::flow::graph &g, int nInputs) {
17451c0b2f7Stbbdev for(int i=0; i < nInputs; ++i) {
17551c0b2f7Stbbdev my_input_node_type *new_node = new my_input_node_type(g, my_input_body<IT>((IT)(ELEM+1), i, nInputs));
17651c0b2f7Stbbdev tbb::flow::make_edge(*new_node, tbb::flow::input_port<ELEM-1>(my_indexer));
17751c0b2f7Stbbdev
17851c0b2f7Stbbdev all_input_nodes[ELEM-1][i] = (void *)new_node;
17951c0b2f7Stbbdev new_node->activate();
18051c0b2f7Stbbdev }
18151c0b2f7Stbbdev
18251c0b2f7Stbbdev // add the next input_node
18351c0b2f7Stbbdev input_node_helper<ELEM-1, INT>::add_input_nodes(my_indexer, g, nInputs);
18451c0b2f7Stbbdev }
check_value(TT & v)18551c0b2f7Stbbdev static void check_value(TT &v) {
18651c0b2f7Stbbdev if(v.tag() == ELEM-1) {
18751c0b2f7Stbbdev int ival = getval_helper<ELEM,INT>::get_integer_val(v);
18851c0b2f7Stbbdev CHECK_MESSAGE(!(ival%(ELEM+1)), "");
18951c0b2f7Stbbdev ival /= (ELEM+1);
19051c0b2f7Stbbdev CHECK_MESSAGE(!outputCheck[ELEM-1][ival], "");
19151c0b2f7Stbbdev outputCheck[ELEM-1][ival] = true;
19251c0b2f7Stbbdev }
19351c0b2f7Stbbdev else {
19451c0b2f7Stbbdev input_node_helper<ELEM-1,INT>::check_value(v);
19551c0b2f7Stbbdev }
19651c0b2f7Stbbdev }
19751c0b2f7Stbbdev
remove_input_nodes(indexer_node_type & my_indexer,int nInputs)19851c0b2f7Stbbdev static void remove_input_nodes(indexer_node_type& my_indexer, int nInputs) {
19951c0b2f7Stbbdev for(int i=0; i< nInputs; ++i) {
20051c0b2f7Stbbdev my_input_node_type *dp = reinterpret_cast<my_input_node_type *>(all_input_nodes[ELEM-1][i]);
20151c0b2f7Stbbdev tbb::flow::remove_edge(*dp, tbb::flow::input_port<ELEM-1>(my_indexer));
20251c0b2f7Stbbdev delete dp;
20351c0b2f7Stbbdev }
20451c0b2f7Stbbdev input_node_helper<ELEM-1, INT>::remove_input_nodes(my_indexer, nInputs);
20551c0b2f7Stbbdev }
20651c0b2f7Stbbdev };
20751c0b2f7Stbbdev
20851c0b2f7Stbbdev template<typename INT>
20951c0b2f7Stbbdev class input_node_helper<1, INT> {
21051c0b2f7Stbbdev typedef INT indexer_node_type;
21151c0b2f7Stbbdev typedef typename indexer_node_type::output_type TT;
21251c0b2f7Stbbdev
21351c0b2f7Stbbdev typedef typename std::tuple_element<0, typename INT::tuple_types>::type IT;
21451c0b2f7Stbbdev typedef typename tbb::flow::input_node<IT> my_input_node_type;
21551c0b2f7Stbbdev public:
print_remark()21651c0b2f7Stbbdev static void print_remark() {
21751c0b2f7Stbbdev INFO("Parallel test of indexer_node< " << name_of<IT>::name());
21851c0b2f7Stbbdev }
add_input_nodes(indexer_node_type & my_indexer,tbb::flow::graph & g,int nInputs)21951c0b2f7Stbbdev static void add_input_nodes(indexer_node_type &my_indexer, tbb::flow::graph &g, int nInputs) {
22051c0b2f7Stbbdev for(int i=0; i < nInputs; ++i) {
22151c0b2f7Stbbdev my_input_node_type *new_node = new my_input_node_type(g, my_input_body<IT>((IT)2, i, nInputs));
22251c0b2f7Stbbdev tbb::flow::make_edge(*new_node, tbb::flow::input_port<0>(my_indexer));
22351c0b2f7Stbbdev all_input_nodes[0][i] = (void *)new_node;
22451c0b2f7Stbbdev new_node->activate();
22551c0b2f7Stbbdev }
22651c0b2f7Stbbdev }
check_value(TT & v)22751c0b2f7Stbbdev static void check_value(TT &v) {
22851c0b2f7Stbbdev int ival = getval_helper<1,INT>::get_integer_val(v);
22951c0b2f7Stbbdev CHECK_MESSAGE(!(ival%2), "");
23051c0b2f7Stbbdev ival /= 2;
23151c0b2f7Stbbdev CHECK_MESSAGE(!outputCheck[0][ival], "");
23251c0b2f7Stbbdev outputCheck[0][ival] = true;
23351c0b2f7Stbbdev }
remove_input_nodes(indexer_node_type & my_indexer,int nInputs)23451c0b2f7Stbbdev static void remove_input_nodes(indexer_node_type& my_indexer, int nInputs) {
23551c0b2f7Stbbdev for(int i=0; i < nInputs; ++i) {
23651c0b2f7Stbbdev my_input_node_type *dp = reinterpret_cast<my_input_node_type *>(all_input_nodes[0][i]);
23751c0b2f7Stbbdev tbb::flow::remove_edge(*dp, tbb::flow::input_port<0>(my_indexer));
23851c0b2f7Stbbdev delete dp;
23951c0b2f7Stbbdev }
24051c0b2f7Stbbdev }
24151c0b2f7Stbbdev };
24251c0b2f7Stbbdev
24351c0b2f7Stbbdev template<typename IType>
24451c0b2f7Stbbdev class parallel_test {
24551c0b2f7Stbbdev public:
24651c0b2f7Stbbdev typedef typename IType::output_type TType;
24751c0b2f7Stbbdev typedef typename IType::tuple_types union_types;
24851c0b2f7Stbbdev static const int SIZE = std::tuple_size<union_types>::value;
test()24951c0b2f7Stbbdev static void test() {
25051c0b2f7Stbbdev TType v;
25151c0b2f7Stbbdev input_node_helper<SIZE,IType>::print_remark();
25251c0b2f7Stbbdev INFO(" >\n");
25351c0b2f7Stbbdev for(int i=0; i < MaxPorts; ++i) {
25451c0b2f7Stbbdev for(int j=0; j < MaxNInputs; ++j) {
25557f524caSIlya Isaev all_input_nodes[i][j] = nullptr;
25651c0b2f7Stbbdev }
25751c0b2f7Stbbdev }
25851c0b2f7Stbbdev for(int nInputs = 1; nInputs <= MaxNInputs; ++nInputs) {
25951c0b2f7Stbbdev tbb::flow::graph g;
26051c0b2f7Stbbdev IType* my_indexer_ptr = new IType(g); //makeIndexer<IType>::create();
26151c0b2f7Stbbdev IType my_indexer = *my_indexer_ptr;
26251c0b2f7Stbbdev tbb::flow::queue_node<TType> outq1(g);
26351c0b2f7Stbbdev tbb::flow::queue_node<TType> outq2(g);
26451c0b2f7Stbbdev
26551c0b2f7Stbbdev tbb::flow::make_edge(my_indexer, outq1);
26651c0b2f7Stbbdev tbb::flow::make_edge(my_indexer, outq2);
26751c0b2f7Stbbdev
26851c0b2f7Stbbdev input_node_helper<SIZE, IType>::add_input_nodes(my_indexer, g, nInputs);
26951c0b2f7Stbbdev
27051c0b2f7Stbbdev g.wait_for_all();
27151c0b2f7Stbbdev makeIndexer<IType>::destroy(my_indexer_ptr);
27251c0b2f7Stbbdev
27351c0b2f7Stbbdev reset_outputCheck(SIZE, Count);
27451c0b2f7Stbbdev for(int i=0; i < Count*SIZE; ++i) {
27551c0b2f7Stbbdev CHECK_MESSAGE(outq1.try_get(v), "");
27651c0b2f7Stbbdev input_node_helper<SIZE, IType>::check_value(v);
27751c0b2f7Stbbdev }
27851c0b2f7Stbbdev
27951c0b2f7Stbbdev check_outputCheck(SIZE, Count);
28051c0b2f7Stbbdev reset_outputCheck(SIZE, Count);
28151c0b2f7Stbbdev
28251c0b2f7Stbbdev for(int i=0; i < Count*SIZE; i++) {
283*5e91b2c0SVladislav Shchapov CHECK_MESSAGE(outq2.try_get(v), "");
28451c0b2f7Stbbdev input_node_helper<SIZE, IType>::check_value(v);
28551c0b2f7Stbbdev }
28651c0b2f7Stbbdev check_outputCheck(SIZE, Count);
28751c0b2f7Stbbdev
28851c0b2f7Stbbdev CHECK_MESSAGE(!outq1.try_get(v), "");
28951c0b2f7Stbbdev CHECK_MESSAGE(!outq2.try_get(v), "");
29051c0b2f7Stbbdev
29151c0b2f7Stbbdev input_node_helper<SIZE, IType>::remove_input_nodes(my_indexer, nInputs);
29251c0b2f7Stbbdev tbb::flow::remove_edge(my_indexer, outq1);
29351c0b2f7Stbbdev tbb::flow::remove_edge(my_indexer, outq2);
29451c0b2f7Stbbdev }
29551c0b2f7Stbbdev }
29651c0b2f7Stbbdev };
29751c0b2f7Stbbdev
29851c0b2f7Stbbdev std::vector<int> last_index_seen;
29951c0b2f7Stbbdev
30051c0b2f7Stbbdev template<int ELEM, typename IType>
30151c0b2f7Stbbdev class serial_queue_helper {
30251c0b2f7Stbbdev public:
30351c0b2f7Stbbdev typedef typename IType::output_type OT;
30451c0b2f7Stbbdev typedef typename IType::tuple_types TT;
30551c0b2f7Stbbdev typedef typename std::tuple_element<ELEM-1,TT>::type IT;
print_remark()30651c0b2f7Stbbdev static void print_remark() {
30751c0b2f7Stbbdev serial_queue_helper<ELEM-1,IType>::print_remark();
30851c0b2f7Stbbdev INFO("," << name_of<IT>::name());
30951c0b2f7Stbbdev }
fill_one_queue(int maxVal,IType & my_indexer)31051c0b2f7Stbbdev static void fill_one_queue(int maxVal, IType &my_indexer) {
31151c0b2f7Stbbdev // fill queue to "left" of me
31251c0b2f7Stbbdev serial_queue_helper<ELEM-1,IType>::fill_one_queue(maxVal,my_indexer);
31351c0b2f7Stbbdev for(int i = 0; i < maxVal; ++i) {
31451c0b2f7Stbbdev CHECK_MESSAGE(tbb::flow::input_port<ELEM-1>(my_indexer).try_put((IT)(i*(ELEM+1))), "");
31551c0b2f7Stbbdev }
31651c0b2f7Stbbdev }
put_one_queue_val(int myVal,IType & my_indexer)31751c0b2f7Stbbdev static void put_one_queue_val(int myVal, IType &my_indexer) {
31851c0b2f7Stbbdev // put this val to my "left".
31951c0b2f7Stbbdev serial_queue_helper<ELEM-1,IType>::put_one_queue_val(myVal, my_indexer);
32051c0b2f7Stbbdev CHECK_MESSAGE(tbb::flow::input_port<ELEM-1>(my_indexer).try_put((IT)(myVal*(ELEM+1))), "");
32151c0b2f7Stbbdev }
check_queue_value(OT & v)32251c0b2f7Stbbdev static void check_queue_value(OT &v) {
32351c0b2f7Stbbdev if(ELEM - 1 == v.tag()) {
32451c0b2f7Stbbdev // this assumes each or node input is queueing.
32551c0b2f7Stbbdev int rval = getval_helper<ELEM,IType>::get_integer_val(v);
32651c0b2f7Stbbdev CHECK_MESSAGE( rval == (last_index_seen[ELEM-1]+1)*(ELEM+1), "");
32751c0b2f7Stbbdev last_index_seen[ELEM-1] = rval / (ELEM+1);
32851c0b2f7Stbbdev }
32951c0b2f7Stbbdev else {
33051c0b2f7Stbbdev serial_queue_helper<ELEM-1,IType>::check_queue_value(v);
33151c0b2f7Stbbdev }
33251c0b2f7Stbbdev }
33351c0b2f7Stbbdev };
33451c0b2f7Stbbdev
33551c0b2f7Stbbdev template<typename IType>
33651c0b2f7Stbbdev class serial_queue_helper<1, IType> {
33751c0b2f7Stbbdev public:
33851c0b2f7Stbbdev typedef typename IType::output_type OT;
33951c0b2f7Stbbdev typedef typename IType::tuple_types TT;
34051c0b2f7Stbbdev typedef typename std::tuple_element<0,TT>::type IT;
print_remark()34151c0b2f7Stbbdev static void print_remark() {
34251c0b2f7Stbbdev INFO("Serial test of indexer_node< " << name_of<IT>::name());
34351c0b2f7Stbbdev }
fill_one_queue(int maxVal,IType & my_indexer)34451c0b2f7Stbbdev static void fill_one_queue(int maxVal, IType &my_indexer) {
34551c0b2f7Stbbdev for(int i = 0; i < maxVal; ++i) {
34651c0b2f7Stbbdev CHECK_MESSAGE(tbb::flow::input_port<0>(my_indexer).try_put((IT)(i*2)), "");
34751c0b2f7Stbbdev }
34851c0b2f7Stbbdev }
put_one_queue_val(int myVal,IType & my_indexer)34951c0b2f7Stbbdev static void put_one_queue_val(int myVal, IType &my_indexer) {
35051c0b2f7Stbbdev CHECK_MESSAGE(tbb::flow::input_port<0>(my_indexer).try_put((IT)(myVal*2)), "");
35151c0b2f7Stbbdev }
check_queue_value(OT & v)35251c0b2f7Stbbdev static void check_queue_value(OT &v) {
35351c0b2f7Stbbdev CHECK_MESSAGE(v.tag() == 0, ""); // won't get here unless true
35451c0b2f7Stbbdev int rval = getval_helper<1,IType>::get_integer_val(v);
35551c0b2f7Stbbdev CHECK_MESSAGE( rval == (last_index_seen[0]+1)*2, "");
35651c0b2f7Stbbdev last_index_seen[0] = rval / 2;
35751c0b2f7Stbbdev }
35851c0b2f7Stbbdev };
35951c0b2f7Stbbdev
36051c0b2f7Stbbdev template<typename IType, typename TType, int SIZE>
test_one_serial(IType & my_indexer,tbb::flow::graph & g)36151c0b2f7Stbbdev void test_one_serial( IType &my_indexer, tbb::flow::graph &g) {
36251c0b2f7Stbbdev last_index_seen.clear();
36351c0b2f7Stbbdev for(int ii=0; ii < SIZE; ++ii) last_index_seen.push_back(-1);
36451c0b2f7Stbbdev
36551c0b2f7Stbbdev typedef TType q3_input_type;
36651c0b2f7Stbbdev tbb::flow::queue_node< q3_input_type > q3(g);
36751c0b2f7Stbbdev q3_input_type v;
36851c0b2f7Stbbdev
36951c0b2f7Stbbdev tbb::flow::make_edge(my_indexer, q3);
37051c0b2f7Stbbdev
37151c0b2f7Stbbdev // fill each queue with its value one-at-a-time
37251c0b2f7Stbbdev for (int i = 0; i < Count; ++i ) {
37351c0b2f7Stbbdev serial_queue_helper<SIZE,IType>::put_one_queue_val(i,my_indexer);
37451c0b2f7Stbbdev }
37551c0b2f7Stbbdev
37651c0b2f7Stbbdev g.wait_for_all();
37751c0b2f7Stbbdev for (int i = 0; i < Count * SIZE; ++i ) {
37851c0b2f7Stbbdev g.wait_for_all();
37951c0b2f7Stbbdev CHECK_MESSAGE( (q3.try_get( v )), "Error in try_get()");
38051c0b2f7Stbbdev {
38151c0b2f7Stbbdev serial_queue_helper<SIZE,IType>::check_queue_value(v);
38251c0b2f7Stbbdev }
38351c0b2f7Stbbdev }
38451c0b2f7Stbbdev CHECK_MESSAGE( (!q3.try_get( v )), "extra values in output queue");
38551c0b2f7Stbbdev for(int ii=0; ii < SIZE; ++ii) last_index_seen[ii] = -1;
38651c0b2f7Stbbdev
38751c0b2f7Stbbdev // fill each queue completely before filling the next.
38851c0b2f7Stbbdev serial_queue_helper<SIZE, IType>::fill_one_queue(Count,my_indexer);
38951c0b2f7Stbbdev
39051c0b2f7Stbbdev g.wait_for_all();
39151c0b2f7Stbbdev for (int i = 0; i < Count*SIZE; ++i ) {
39251c0b2f7Stbbdev g.wait_for_all();
39351c0b2f7Stbbdev CHECK_MESSAGE( (q3.try_get( v )), "Error in try_get()");
39451c0b2f7Stbbdev {
39551c0b2f7Stbbdev serial_queue_helper<SIZE,IType>::check_queue_value(v);
39651c0b2f7Stbbdev }
39751c0b2f7Stbbdev }
39851c0b2f7Stbbdev CHECK_MESSAGE( (!q3.try_get( v )), "extra values in output queue");
39951c0b2f7Stbbdev }
40051c0b2f7Stbbdev
40151c0b2f7Stbbdev //
40251c0b2f7Stbbdev template<typename NodeType>
test_input_ports_return_ref(NodeType & mip_node)40351c0b2f7Stbbdev void test_input_ports_return_ref(NodeType& mip_node) {
40451c0b2f7Stbbdev typename NodeType::input_ports_type& input_ports1 = mip_node.input_ports();
40551c0b2f7Stbbdev typename NodeType::input_ports_type& input_ports2 = mip_node.input_ports();
40651c0b2f7Stbbdev CHECK_MESSAGE( (&input_ports1 == &input_ports2), "input_ports() should return reference");
40751c0b2f7Stbbdev }
40851c0b2f7Stbbdev
40951c0b2f7Stbbdev // Single predecessor at each port, single accepting successor
41051c0b2f7Stbbdev // * put to buffer before port0, then put to buffer before port1, ...
41151c0b2f7Stbbdev // * fill buffer before port0 then fill buffer before port1, ...
41251c0b2f7Stbbdev
41351c0b2f7Stbbdev template<typename IType>
41451c0b2f7Stbbdev class serial_test {
41551c0b2f7Stbbdev typedef typename IType::output_type TType; // this is the union
41651c0b2f7Stbbdev typedef typename IType::tuple_types union_types;
41751c0b2f7Stbbdev static const int SIZE = std::tuple_size<union_types>::value;
41851c0b2f7Stbbdev public:
test()41951c0b2f7Stbbdev static void test() {
42051c0b2f7Stbbdev tbb::flow::graph g;
42151c0b2f7Stbbdev static const int ELEMS = 3;
42251c0b2f7Stbbdev IType* my_indexer = new IType(g); //makeIndexer<IType>::create(g);
42351c0b2f7Stbbdev
42451c0b2f7Stbbdev test_input_ports_return_ref(*my_indexer);
42551c0b2f7Stbbdev
42651c0b2f7Stbbdev serial_queue_helper<SIZE, IType>::print_remark(); INFO(" >\n");
42751c0b2f7Stbbdev
42851c0b2f7Stbbdev test_one_serial<IType,TType,SIZE>(*my_indexer, g);
42951c0b2f7Stbbdev
43051c0b2f7Stbbdev std::vector<IType> indexer_vector(ELEMS,*my_indexer);
43151c0b2f7Stbbdev
43251c0b2f7Stbbdev makeIndexer<IType>::destroy(my_indexer);
43351c0b2f7Stbbdev
43451c0b2f7Stbbdev for(int e = 0; e < ELEMS; ++e) {
43551c0b2f7Stbbdev test_one_serial<IType,TType,SIZE>(indexer_vector[e], g);
43651c0b2f7Stbbdev }
43751c0b2f7Stbbdev }
43851c0b2f7Stbbdev
43951c0b2f7Stbbdev }; // serial_test
44051c0b2f7Stbbdev
44151c0b2f7Stbbdev template<
44251c0b2f7Stbbdev template<typename> class TestType, // serial_test or parallel_test
44351c0b2f7Stbbdev typename T0, typename T1=void, typename T2=void, typename T3=void, typename T4=void,
44451c0b2f7Stbbdev typename T5=void, typename T6=void, typename T7=void, typename T8=void, typename T9=void> // type of the inputs to the indexer_node
44551c0b2f7Stbbdev class generate_test {
44651c0b2f7Stbbdev public:
44751c0b2f7Stbbdev typedef tbb::flow::indexer_node<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> indexer_node_type;
do_test()44851c0b2f7Stbbdev static void do_test() {
44951c0b2f7Stbbdev TestType<indexer_node_type>::test();
45051c0b2f7Stbbdev }
45151c0b2f7Stbbdev };
45251c0b2f7Stbbdev
45351c0b2f7Stbbdev //specializations for indexer node inputs
45451c0b2f7Stbbdev template<
45551c0b2f7Stbbdev template<typename> class TestType,
45651c0b2f7Stbbdev typename T0, typename T1, typename T2, typename T3, typename T4,
45751c0b2f7Stbbdev typename T5, typename T6, typename T7, typename T8>
45851c0b2f7Stbbdev class generate_test<TestType, T0, T1, T2, T3, T4, T5, T6, T7, T8> {
45951c0b2f7Stbbdev public:
46051c0b2f7Stbbdev typedef tbb::flow::indexer_node<T0, T1, T2, T3, T4, T5, T6, T7, T8> indexer_node_type;
do_test()46151c0b2f7Stbbdev static void do_test() {
46251c0b2f7Stbbdev TestType<indexer_node_type>::test();
46351c0b2f7Stbbdev }
46451c0b2f7Stbbdev };
46551c0b2f7Stbbdev
46651c0b2f7Stbbdev template<
46751c0b2f7Stbbdev template<typename> class TestType,
46851c0b2f7Stbbdev typename T0, typename T1, typename T2, typename T3, typename T4,
46951c0b2f7Stbbdev typename T5, typename T6, typename T7>
47051c0b2f7Stbbdev class generate_test<TestType, T0, T1, T2, T3, T4, T5, T6, T7> {
47151c0b2f7Stbbdev public:
47251c0b2f7Stbbdev typedef tbb::flow::indexer_node<T0, T1, T2, T3, T4, T5, T6, T7> indexer_node_type;
do_test()47351c0b2f7Stbbdev static void do_test() {
47451c0b2f7Stbbdev TestType<indexer_node_type>::test();
47551c0b2f7Stbbdev }
47651c0b2f7Stbbdev };
47751c0b2f7Stbbdev
47851c0b2f7Stbbdev template<
47951c0b2f7Stbbdev template<typename> class TestType,
48051c0b2f7Stbbdev typename T0, typename T1, typename T2, typename T3, typename T4,
48151c0b2f7Stbbdev typename T5, typename T6>
48251c0b2f7Stbbdev class generate_test<TestType, T0, T1, T2, T3, T4, T5, T6> {
48351c0b2f7Stbbdev public:
48451c0b2f7Stbbdev typedef tbb::flow::indexer_node<T0, T1, T2, T3, T4, T5, T6> indexer_node_type;
do_test()48551c0b2f7Stbbdev static void do_test() {
48651c0b2f7Stbbdev TestType<indexer_node_type>::test();
48751c0b2f7Stbbdev }
48851c0b2f7Stbbdev };
48951c0b2f7Stbbdev
49051c0b2f7Stbbdev template<
49151c0b2f7Stbbdev template<typename> class TestType,
49251c0b2f7Stbbdev typename T0, typename T1, typename T2, typename T3, typename T4,
49351c0b2f7Stbbdev typename T5>
49451c0b2f7Stbbdev class generate_test<TestType, T0, T1, T2, T3, T4, T5> {
49551c0b2f7Stbbdev public:
49651c0b2f7Stbbdev typedef tbb::flow::indexer_node<T0, T1, T2, T3, T4, T5> indexer_node_type;
do_test()49751c0b2f7Stbbdev static void do_test() {
49851c0b2f7Stbbdev TestType<indexer_node_type>::test();
49951c0b2f7Stbbdev }
50051c0b2f7Stbbdev };
50151c0b2f7Stbbdev
50251c0b2f7Stbbdev template<
50351c0b2f7Stbbdev template<typename> class TestType,
50451c0b2f7Stbbdev typename T0, typename T1, typename T2, typename T3, typename T4>
50551c0b2f7Stbbdev class generate_test<TestType, T0, T1, T2, T3, T4> {
50651c0b2f7Stbbdev public:
50751c0b2f7Stbbdev typedef tbb::flow::indexer_node<T0, T1, T2, T3, T4> indexer_node_type;
do_test()50851c0b2f7Stbbdev static void do_test() {
50951c0b2f7Stbbdev TestType<indexer_node_type>::test();
51051c0b2f7Stbbdev }
51151c0b2f7Stbbdev };
51251c0b2f7Stbbdev
51351c0b2f7Stbbdev template<
51451c0b2f7Stbbdev template<typename> class TestType,
51551c0b2f7Stbbdev typename T0, typename T1, typename T2, typename T3>
51651c0b2f7Stbbdev class generate_test<TestType, T0, T1, T2, T3> {
51751c0b2f7Stbbdev public:
51851c0b2f7Stbbdev typedef tbb::flow::indexer_node<T0, T1, T2, T3> indexer_node_type;
do_test()51951c0b2f7Stbbdev static void do_test() {
52051c0b2f7Stbbdev TestType<indexer_node_type>::test();
52151c0b2f7Stbbdev }
52251c0b2f7Stbbdev };
52351c0b2f7Stbbdev
52451c0b2f7Stbbdev template<
52551c0b2f7Stbbdev template<typename> class TestType,
52651c0b2f7Stbbdev typename T0, typename T1, typename T2>
52751c0b2f7Stbbdev class generate_test<TestType, T0, T1, T2> {
52851c0b2f7Stbbdev public:
52951c0b2f7Stbbdev typedef tbb::flow::indexer_node<T0, T1, T2> indexer_node_type;
do_test()53051c0b2f7Stbbdev static void do_test() {
53151c0b2f7Stbbdev TestType<indexer_node_type>::test();
53251c0b2f7Stbbdev }
53351c0b2f7Stbbdev };
53451c0b2f7Stbbdev
53551c0b2f7Stbbdev template<
53651c0b2f7Stbbdev template<typename> class TestType,
53751c0b2f7Stbbdev typename T0, typename T1>
53851c0b2f7Stbbdev class generate_test<TestType, T0, T1> {
53951c0b2f7Stbbdev public:
54051c0b2f7Stbbdev typedef tbb::flow::indexer_node<T0, T1> indexer_node_type;
do_test()54151c0b2f7Stbbdev static void do_test() {
54251c0b2f7Stbbdev TestType<indexer_node_type>::test();
54351c0b2f7Stbbdev }
54451c0b2f7Stbbdev };
54551c0b2f7Stbbdev
54651c0b2f7Stbbdev template<
54751c0b2f7Stbbdev template<typename> class TestType,
54851c0b2f7Stbbdev typename T0>
54951c0b2f7Stbbdev class generate_test<TestType, T0> {
55051c0b2f7Stbbdev public:
55151c0b2f7Stbbdev typedef tbb::flow::indexer_node<T0> indexer_node_type;
do_test()55251c0b2f7Stbbdev static void do_test() {
55351c0b2f7Stbbdev TestType<indexer_node_type>::test();
55451c0b2f7Stbbdev }
55551c0b2f7Stbbdev };
55651c0b2f7Stbbdev
55751c0b2f7Stbbdev #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
55851c0b2f7Stbbdev template<typename tagged_msg_t, typename input_t>
check_edge(tbb::flow::graph & g,tbb::flow::broadcast_node<input_t> & start,tbb::flow::buffer_node<tagged_msg_t> & buf,input_t input_value)55951c0b2f7Stbbdev bool check_edge(tbb::flow::graph& g,
56051c0b2f7Stbbdev tbb::flow::broadcast_node<input_t>& start,
56151c0b2f7Stbbdev tbb::flow::buffer_node<tagged_msg_t>& buf,
56251c0b2f7Stbbdev input_t input_value) {
56351c0b2f7Stbbdev start.try_put(input_value);
56451c0b2f7Stbbdev g.wait_for_all();
56551c0b2f7Stbbdev
56651c0b2f7Stbbdev tagged_msg_t msg;
56751c0b2f7Stbbdev bool is_get_succeeded = buf.try_get(msg);
56851c0b2f7Stbbdev
56951c0b2f7Stbbdev CHECK_MESSAGE( ((is_get_succeeded)), "There is no item in the buffer");
57051c0b2f7Stbbdev CHECK_MESSAGE( ((tbb::flow::cast_to<input_t>(msg) == input_value)), "Wrong item value");
57151c0b2f7Stbbdev return true;
57251c0b2f7Stbbdev }
57351c0b2f7Stbbdev
57451c0b2f7Stbbdev template <typename... T>
sink(T...)57551c0b2f7Stbbdev void sink(T...) {}
57651c0b2f7Stbbdev
57751c0b2f7Stbbdev template <typename indexer_output_t, typename Type, typename BN, std::size_t... Seq>
check_edge(tbb::flow::graph & g,BN & bn,tbb::flow::buffer_node<indexer_output_t> & buf,Type,tbb::detail::index_sequence<Seq...>)57851c0b2f7Stbbdev void check_edge(tbb::flow::graph& g, BN& bn, tbb::flow::buffer_node<indexer_output_t>& buf, Type, tbb::detail::index_sequence<Seq...>) {
57951c0b2f7Stbbdev sink(check_edge<indexer_output_t>(g, std::get<Seq>(bn), buf, typename std::tuple_element<Seq, Type>::type(Seq))...);
58051c0b2f7Stbbdev }
58151c0b2f7Stbbdev
58251c0b2f7Stbbdev template <typename... Args, std::size_t... Seq>
test_follows_impl(std::tuple<Args...> t,tbb::detail::index_sequence<Seq...> seq)58351c0b2f7Stbbdev void test_follows_impl(std::tuple<Args...> t, tbb::detail::index_sequence<Seq...> seq) {
58451c0b2f7Stbbdev using namespace tbb::flow;
58551c0b2f7Stbbdev using indexer_output_t = typename indexer_node<Args...>::output_type;
58651c0b2f7Stbbdev
58751c0b2f7Stbbdev graph g;
58851c0b2f7Stbbdev auto bn = std::make_tuple(broadcast_node<Args>(g)...);
58951c0b2f7Stbbdev
59051c0b2f7Stbbdev indexer_node<Args...> my_indexer(follows(std::get<Seq>(bn)...));
59151c0b2f7Stbbdev
59251c0b2f7Stbbdev buffer_node<indexer_output_t> buf(g);
59351c0b2f7Stbbdev make_edge(my_indexer, buf);
59451c0b2f7Stbbdev
59551c0b2f7Stbbdev check_edge<indexer_output_t>(g, bn, buf, t, seq);
59651c0b2f7Stbbdev }
59751c0b2f7Stbbdev
59851c0b2f7Stbbdev template <typename... Args>
test_follows()59951c0b2f7Stbbdev void test_follows() {
60051c0b2f7Stbbdev test_follows_impl(std::tuple<Args...>(), tbb::detail::make_index_sequence<sizeof...(Args)>());
60151c0b2f7Stbbdev }
60251c0b2f7Stbbdev
test_precedes()60351c0b2f7Stbbdev void test_precedes() {
60451c0b2f7Stbbdev using namespace tbb::flow;
60551c0b2f7Stbbdev
60651c0b2f7Stbbdev using indexer_output_t = indexer_node<int, float, double>::output_type;
60751c0b2f7Stbbdev
60851c0b2f7Stbbdev graph g;
60951c0b2f7Stbbdev
61051c0b2f7Stbbdev broadcast_node<int> start1(g);
61151c0b2f7Stbbdev broadcast_node<float> start2(g);
61251c0b2f7Stbbdev broadcast_node<double> start3(g);
61351c0b2f7Stbbdev
61451c0b2f7Stbbdev buffer_node<indexer_output_t> buf1(g);
61551c0b2f7Stbbdev buffer_node<indexer_output_t> buf2(g);
61651c0b2f7Stbbdev buffer_node<indexer_output_t> buf3(g);
61751c0b2f7Stbbdev
61851c0b2f7Stbbdev indexer_node<int, float, double> node(precedes(buf1, buf2, buf3));
61951c0b2f7Stbbdev
62051c0b2f7Stbbdev make_edge(start1, input_port<0>(node));
62151c0b2f7Stbbdev make_edge(start2, input_port<1>(node));
62251c0b2f7Stbbdev make_edge(start3, input_port<2>(node));
62351c0b2f7Stbbdev
62451c0b2f7Stbbdev check_edge<indexer_output_t, int>(g, start1, buf1, 1);
62551c0b2f7Stbbdev check_edge<indexer_output_t, float>(g, start2, buf2, 2.2f);
62651c0b2f7Stbbdev check_edge<indexer_output_t, double>(g, start3, buf3, 3.3);
62751c0b2f7Stbbdev }
62851c0b2f7Stbbdev
test_follows_and_precedes_api()62951c0b2f7Stbbdev void test_follows_and_precedes_api() {
63051c0b2f7Stbbdev test_follows<double>();
63151c0b2f7Stbbdev test_follows<int, double>();
63251c0b2f7Stbbdev test_follows<int, float, double>();
63351c0b2f7Stbbdev test_follows<float, double, int, double>();
63451c0b2f7Stbbdev test_follows<float, double, int, double, double>();
63551c0b2f7Stbbdev test_follows<float, double, int, double, double, float>();
63651c0b2f7Stbbdev test_follows<float, double, int, double, double, float, long>();
63751c0b2f7Stbbdev test_follows<float, double, int, double, double, float, long, int>();
63851c0b2f7Stbbdev test_follows<float, double, int, double, double, float, long, int, long>();
63951c0b2f7Stbbdev test_follows<float, double, int, double, double, float, long, int, float, long>();
64051c0b2f7Stbbdev test_precedes();
64151c0b2f7Stbbdev }
64251c0b2f7Stbbdev #endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
64351c0b2f7Stbbdev
64451c0b2f7Stbbdev #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
test_deduction_guides()64551c0b2f7Stbbdev void test_deduction_guides() {
64651c0b2f7Stbbdev using namespace tbb::flow;
64751c0b2f7Stbbdev graph g;
64851c0b2f7Stbbdev
64951c0b2f7Stbbdev broadcast_node<int> b1(g);
65051c0b2f7Stbbdev broadcast_node<double> b2(g);
65151c0b2f7Stbbdev indexer_node<int, double> i0(g);
65251c0b2f7Stbbdev
65351c0b2f7Stbbdev #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
65451c0b2f7Stbbdev indexer_node i1(follows(b1, b2));
65551c0b2f7Stbbdev static_assert(std::is_same_v<decltype(i1), indexer_node<int, double>>);
65651c0b2f7Stbbdev #endif
65751c0b2f7Stbbdev
65851c0b2f7Stbbdev indexer_node i2(i0);
65951c0b2f7Stbbdev static_assert(std::is_same_v<decltype(i2), indexer_node<int, double>>);
66051c0b2f7Stbbdev }
66151c0b2f7Stbbdev
66251c0b2f7Stbbdev #endif
66351c0b2f7Stbbdev
66451c0b2f7Stbbdev //! Serial and parallel test on various tuple sizes
66551c0b2f7Stbbdev //! \brief \ref error_guessing
66651c0b2f7Stbbdev TEST_CASE("Serial and parallel test") {
66751c0b2f7Stbbdev INFO("Testing indexer_node, ");
66851c0b2f7Stbbdev
66951c0b2f7Stbbdev for (int p = 0; p < 2; ++p) {
67051c0b2f7Stbbdev generate_test<serial_test, float>::do_test();
67151c0b2f7Stbbdev #if MAX_TUPLE_TEST_SIZE >= 4
67251c0b2f7Stbbdev generate_test<serial_test, float, double, int, short>::do_test();
67351c0b2f7Stbbdev #endif
67451c0b2f7Stbbdev #if MAX_TUPLE_TEST_SIZE >= 6
67551c0b2f7Stbbdev generate_test<serial_test, double, double, int, long, int, short>::do_test();
67651c0b2f7Stbbdev #endif
67751c0b2f7Stbbdev #if MAX_TUPLE_TEST_SIZE >= 8
67851c0b2f7Stbbdev generate_test<serial_test, float, double, double, double, float, int, float, long>::do_test();
67951c0b2f7Stbbdev #endif
68051c0b2f7Stbbdev #if MAX_TUPLE_TEST_SIZE >= 10
68151c0b2f7Stbbdev generate_test<serial_test, float, double, int, double, double, float, long, int, float, long>::do_test();
68251c0b2f7Stbbdev #endif
68351c0b2f7Stbbdev generate_test<parallel_test, float, double>::do_test();
68451c0b2f7Stbbdev #if MAX_TUPLE_TEST_SIZE >= 3
68551c0b2f7Stbbdev generate_test<parallel_test, float, int, long>::do_test();
68651c0b2f7Stbbdev #endif
68751c0b2f7Stbbdev #if MAX_TUPLE_TEST_SIZE >= 5
68851c0b2f7Stbbdev generate_test<parallel_test, double, double, int, int, short>::do_test();
68951c0b2f7Stbbdev #endif
69051c0b2f7Stbbdev #if MAX_TUPLE_TEST_SIZE >= 7
69151c0b2f7Stbbdev generate_test<parallel_test, float, int, double, float, long, float, long>::do_test();
69251c0b2f7Stbbdev #endif
69351c0b2f7Stbbdev #if MAX_TUPLE_TEST_SIZE >= 9
69451c0b2f7Stbbdev generate_test<parallel_test, float, double, int, double, double, long, int, float, long>::do_test();
69551c0b2f7Stbbdev #endif
69651c0b2f7Stbbdev }
69751c0b2f7Stbbdev }
69851c0b2f7Stbbdev
69951c0b2f7Stbbdev #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
70051c0b2f7Stbbdev //! Test follows and precedes API
70151c0b2f7Stbbdev //! \brief \ref error_guessing
70251c0b2f7Stbbdev TEST_CASE("Follows and precedes API") {
70351c0b2f7Stbbdev test_follows_and_precedes_api();
70451c0b2f7Stbbdev }
70551c0b2f7Stbbdev #endif
70651c0b2f7Stbbdev
70751c0b2f7Stbbdev #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
70851c0b2f7Stbbdev //! Test deduction guides
70951c0b2f7Stbbdev //! \brief \ref requirement
71051c0b2f7Stbbdev TEST_CASE("Deduction guides") {
71151c0b2f7Stbbdev test_deduction_guides();
71251c0b2f7Stbbdev }
71351c0b2f7Stbbdev #endif
71451c0b2f7Stbbdev
715