1*51c0b2f7Stbbdev /*
2*51c0b2f7Stbbdev     Copyright (c) 2020 Intel Corporation
3*51c0b2f7Stbbdev 
4*51c0b2f7Stbbdev     Licensed under the Apache License, Version 2.0 (the "License");
5*51c0b2f7Stbbdev     you may not use this file except in compliance with the License.
6*51c0b2f7Stbbdev     You may obtain a copy of the License at
7*51c0b2f7Stbbdev 
8*51c0b2f7Stbbdev         http://www.apache.org/licenses/LICENSE-2.0
9*51c0b2f7Stbbdev 
10*51c0b2f7Stbbdev     Unless required by applicable law or agreed to in writing, software
11*51c0b2f7Stbbdev     distributed under the License is distributed on an "AS IS" BASIS,
12*51c0b2f7Stbbdev     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*51c0b2f7Stbbdev     See the License for the specific language governing permissions and
14*51c0b2f7Stbbdev     limitations under the License.
15*51c0b2f7Stbbdev */
16*51c0b2f7Stbbdev 
17*51c0b2f7Stbbdev 
18*51c0b2f7Stbbdev #include "common/test.h"
19*51c0b2f7Stbbdev 
20*51c0b2f7Stbbdev #include "common/utils.h"
21*51c0b2f7Stbbdev #include "common/graph_utils.h"
22*51c0b2f7Stbbdev 
23*51c0b2f7Stbbdev #include "tbb/flow_graph.h"
24*51c0b2f7Stbbdev #include "tbb/task_arena.h"
25*51c0b2f7Stbbdev #include "tbb/global_control.h"
26*51c0b2f7Stbbdev 
27*51c0b2f7Stbbdev #include "conformance_flowgraph.h"
28*51c0b2f7Stbbdev 
29*51c0b2f7Stbbdev //! \file conformance_queue_node.cpp
30*51c0b2f7Stbbdev //! \brief Test for [flow_graph.queue_node] specification
31*51c0b2f7Stbbdev 
32*51c0b2f7Stbbdev /*
33*51c0b2f7Stbbdev TODO: implement missing conformance tests for queue_node:
34*51c0b2f7Stbbdev   - [ ] The copy constructor and copy assignment are called for the node's type template parameter.
35*51c0b2f7Stbbdev   - [ ] Improve `test_forwarding()'.
36*51c0b2f7Stbbdev   - [ ] Improve tests of the constructors.
37*51c0b2f7Stbbdev   - [ ] Improve `test_buffering' by checking that additional `try_get()' does not receive the same
38*51c0b2f7Stbbdev     value.
39*51c0b2f7Stbbdev - [ ] Based on the decision about the details for `try_put()' and `try_get()' write corresponding
40*51c0b2f7Stbbdev     tests.
41*51c0b2f7Stbbdev */
42*51c0b2f7Stbbdev 
43*51c0b2f7Stbbdev template<typename T>
44*51c0b2f7Stbbdev void test_inheritance(){
45*51c0b2f7Stbbdev     using namespace tbb::flow;
46*51c0b2f7Stbbdev 
47*51c0b2f7Stbbdev     CHECK_MESSAGE( (std::is_base_of<graph_node, queue_node<T>>::value), "queue_node should be derived from graph_node");
48*51c0b2f7Stbbdev     CHECK_MESSAGE( (std::is_base_of<receiver<T>, queue_node<T>>::value), "queue_node should be derived from receiver<T>");
49*51c0b2f7Stbbdev     CHECK_MESSAGE( (std::is_base_of<sender<T>, queue_node<T>>::value), "queue_node should be derived from sender<T>");
50*51c0b2f7Stbbdev }
51*51c0b2f7Stbbdev 
52*51c0b2f7Stbbdev void test_copies(){
53*51c0b2f7Stbbdev     using namespace tbb::flow;
54*51c0b2f7Stbbdev 
55*51c0b2f7Stbbdev     graph g;
56*51c0b2f7Stbbdev     queue_node<int> n(g);
57*51c0b2f7Stbbdev     queue_node<int> n2(n);
58*51c0b2f7Stbbdev 
59*51c0b2f7Stbbdev }
60*51c0b2f7Stbbdev 
61*51c0b2f7Stbbdev void test_buffering(){
62*51c0b2f7Stbbdev     tbb::flow::graph g;
63*51c0b2f7Stbbdev 
64*51c0b2f7Stbbdev     tbb::flow::queue_node<int> node(g);
65*51c0b2f7Stbbdev     tbb::flow::limiter_node<int> rejecter(g, 0);
66*51c0b2f7Stbbdev 
67*51c0b2f7Stbbdev     tbb::flow::make_edge(node, rejecter);
68*51c0b2f7Stbbdev     node.try_put(1);
69*51c0b2f7Stbbdev     g.wait_for_all();
70*51c0b2f7Stbbdev 
71*51c0b2f7Stbbdev     int tmp = -1;
72*51c0b2f7Stbbdev     CHECK_MESSAGE( (node.try_get(tmp) == true), "try_get after rejection should succeed");
73*51c0b2f7Stbbdev     CHECK_MESSAGE( (tmp == 1), "try_get after rejection should set value");
74*51c0b2f7Stbbdev }
75*51c0b2f7Stbbdev 
76*51c0b2f7Stbbdev void test_forwarding(){
77*51c0b2f7Stbbdev     tbb::flow::graph g;
78*51c0b2f7Stbbdev 
79*51c0b2f7Stbbdev     tbb::flow::queue_node<int> node1(g);
80*51c0b2f7Stbbdev     test_push_receiver<int> node2(g);
81*51c0b2f7Stbbdev     test_push_receiver<int> node3(g);
82*51c0b2f7Stbbdev 
83*51c0b2f7Stbbdev     tbb::flow::make_edge(node1, node2);
84*51c0b2f7Stbbdev     tbb::flow::make_edge(node1, node3);
85*51c0b2f7Stbbdev 
86*51c0b2f7Stbbdev     node1.try_put(1);
87*51c0b2f7Stbbdev     g.wait_for_all();
88*51c0b2f7Stbbdev 
89*51c0b2f7Stbbdev     int c2 = get_count(node2), c3 = get_count(node3);
90*51c0b2f7Stbbdev     CHECK_MESSAGE( (c2 != c3 ), "Only one descendant the node needs to receive");
91*51c0b2f7Stbbdev     CHECK_MESSAGE( (c2 + c3 == 1 ), "All messages need to be received");
92*51c0b2f7Stbbdev }
93*51c0b2f7Stbbdev 
94*51c0b2f7Stbbdev void test_queue_node(){
95*51c0b2f7Stbbdev     tbb::flow::graph g;
96*51c0b2f7Stbbdev 
97*51c0b2f7Stbbdev     tbb::flow::queue_node<int> node(g);
98*51c0b2f7Stbbdev     node.try_put(1);
99*51c0b2f7Stbbdev     node.try_put(2);
100*51c0b2f7Stbbdev     g.wait_for_all();
101*51c0b2f7Stbbdev 
102*51c0b2f7Stbbdev     int tmp = -1;
103*51c0b2f7Stbbdev     CHECK_MESSAGE( (node.try_get(tmp) == true), "try_get should succeed");
104*51c0b2f7Stbbdev     CHECK_MESSAGE( (tmp == 1), "try_get should set correct value");
105*51c0b2f7Stbbdev 
106*51c0b2f7Stbbdev     tmp = -1;
107*51c0b2f7Stbbdev     CHECK_MESSAGE( (node.try_get(tmp) == true), "try_get should succeed");
108*51c0b2f7Stbbdev     CHECK_MESSAGE( (tmp == 2), "try_get should set correct value");
109*51c0b2f7Stbbdev }
110*51c0b2f7Stbbdev 
111*51c0b2f7Stbbdev void test_double_reserve(){
112*51c0b2f7Stbbdev     tbb::flow::graph g;
113*51c0b2f7Stbbdev 
114*51c0b2f7Stbbdev     tbb::flow::queue_node<int> node(g);
115*51c0b2f7Stbbdev 
116*51c0b2f7Stbbdev     int tmp = -1;
117*51c0b2f7Stbbdev     node.try_reserve(tmp);
118*51c0b2f7Stbbdev     CHECK_MESSAGE((tmp == -1), "Should not be delivered");
119*51c0b2f7Stbbdev     node.try_reserve(tmp);
120*51c0b2f7Stbbdev     CHECK_MESSAGE((tmp == -1), "Should not be delivered");
121*51c0b2f7Stbbdev 
122*51c0b2f7Stbbdev     g.reset();
123*51c0b2f7Stbbdev 
124*51c0b2f7Stbbdev     node.try_reserve(tmp);
125*51c0b2f7Stbbdev     CHECK_MESSAGE((tmp == -1), "Should not be delivered");
126*51c0b2f7Stbbdev     node.try_reserve(tmp);
127*51c0b2f7Stbbdev     CHECK_MESSAGE((tmp == -1), "Should not be delivered");
128*51c0b2f7Stbbdev }
129*51c0b2f7Stbbdev 
130*51c0b2f7Stbbdev //! Test multiple reserves
131*51c0b2f7Stbbdev //! \brief \ref error_guessing
132*51c0b2f7Stbbdev TEST_CASE("queue_node double reserve"){
133*51c0b2f7Stbbdev     test_double_reserve();
134*51c0b2f7Stbbdev }
135*51c0b2f7Stbbdev 
136*51c0b2f7Stbbdev //! Test message logic
137*51c0b2f7Stbbdev //! \brief \ref requirement
138*51c0b2f7Stbbdev TEST_CASE("queue_node messages"){
139*51c0b2f7Stbbdev     test_queue_node();
140*51c0b2f7Stbbdev }
141*51c0b2f7Stbbdev 
142*51c0b2f7Stbbdev //! Test single-push
143*51c0b2f7Stbbdev //! \brief \ref requirement
144*51c0b2f7Stbbdev TEST_CASE("queue_node buffering"){
145*51c0b2f7Stbbdev     test_forwarding();
146*51c0b2f7Stbbdev }
147*51c0b2f7Stbbdev 
148*51c0b2f7Stbbdev //! Test buffering
149*51c0b2f7Stbbdev //! \brief \ref requirement
150*51c0b2f7Stbbdev TEST_CASE("queue_node buffering"){
151*51c0b2f7Stbbdev     test_buffering();
152*51c0b2f7Stbbdev }
153*51c0b2f7Stbbdev 
154*51c0b2f7Stbbdev //! Test copy constructor
155*51c0b2f7Stbbdev //! \brief \ref interface
156*51c0b2f7Stbbdev TEST_CASE("queue_node copy constructor"){
157*51c0b2f7Stbbdev     test_copies();
158*51c0b2f7Stbbdev }
159*51c0b2f7Stbbdev 
160*51c0b2f7Stbbdev //! Test inheritance relations
161*51c0b2f7Stbbdev //! \brief \ref interface
162*51c0b2f7Stbbdev TEST_CASE("queue_node superclasses"){
163*51c0b2f7Stbbdev     test_inheritance<int>();
164*51c0b2f7Stbbdev     test_inheritance<void*>();
165*51c0b2f7Stbbdev }
166*51c0b2f7Stbbdev 
167