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 
2151c0b2f7Stbbdev #include "conformance_flowgraph.h"
2251c0b2f7Stbbdev 
2351c0b2f7Stbbdev //! \file conformance_async_node.cpp
2451c0b2f7Stbbdev //! \brief Test for [flow_graph.async_node] specification
2551c0b2f7Stbbdev 
26*de0109beSIlya Mishin using input_msg = conformance::message</*default_ctor*/true, /*copy_ctor*/true, /*copy_assign*/false>;
27*de0109beSIlya Mishin using output_msg = conformance::message</*default_ctor*/false, /*copy_ctor*/false, /*copy_assign*/false>;
2851c0b2f7Stbbdev 
29*de0109beSIlya Mishin //! Test async_node constructors
3051c0b2f7Stbbdev //! \brief \ref requirement
31*de0109beSIlya Mishin TEST_CASE("async_node constructors"){
32*de0109beSIlya Mishin     using namespace oneapi::tbb::flow;
33*de0109beSIlya Mishin     graph g;
3451c0b2f7Stbbdev 
35*de0109beSIlya Mishin     conformance::dummy_functor<int> fun;
36*de0109beSIlya Mishin 
37*de0109beSIlya Mishin     async_node<int, int> fn1(g, unlimited, fun);
38*de0109beSIlya Mishin     async_node<int, int> fn2(g, unlimited, fun, oneapi::tbb::flow::node_priority_t(1));
39*de0109beSIlya Mishin 
40*de0109beSIlya Mishin     async_node<int, int, lightweight> lw_node1(g, serial, fun, lightweight());
41*de0109beSIlya Mishin     async_node<int, int, lightweight> lw_node2(g, serial, fun, lightweight(), oneapi::tbb::flow::node_priority_t(1));
4251c0b2f7Stbbdev }
4351c0b2f7Stbbdev 
44*de0109beSIlya Mishin //! Test buffering property
45*de0109beSIlya Mishin //! \brief \ref requirement
46*de0109beSIlya Mishin TEST_CASE("async_node buffering") {
47*de0109beSIlya Mishin     conformance::dummy_functor<int> fun;
48*de0109beSIlya Mishin     conformance::test_buffering<oneapi::tbb::flow::async_node<input_msg, int>, input_msg>(oneapi::tbb::flow::unlimited, fun);
4951c0b2f7Stbbdev }
5051c0b2f7Stbbdev 
51*de0109beSIlya Mishin //! Test priorities work in single-threaded configuration
52*de0109beSIlya Mishin //! \brief \ref requirement
53*de0109beSIlya Mishin TEST_CASE("async_node priority support"){
54*de0109beSIlya Mishin     conformance::test_priority<oneapi::tbb::flow::async_node<input_msg, int>, input_msg>(oneapi::tbb::flow::unlimited);
55*de0109beSIlya Mishin }
56*de0109beSIlya Mishin 
57*de0109beSIlya Mishin //! The node that is constructed has a reference to the same graph object as src, has a copy of the initial body used by src, and has the same concurrency threshold as src.
58*de0109beSIlya Mishin //! The predecessors and successors of src are not copied.
59*de0109beSIlya Mishin //! \brief \ref requirement
60*de0109beSIlya Mishin TEST_CASE("async_node copy constructor"){
61*de0109beSIlya Mishin     conformance::test_copy_ctor<oneapi::tbb::flow::async_node<int, int>>();
6251c0b2f7Stbbdev }
6351c0b2f7Stbbdev 
6451c0b2f7Stbbdev //! Test calling async body
6551c0b2f7Stbbdev //! \brief \ref interface \ref requirement
6651c0b2f7Stbbdev TEST_CASE("Test async_node body") {
67*de0109beSIlya Mishin     conformance::test_body_exec<oneapi::tbb::flow::async_node<input_msg, output_msg>, input_msg, output_msg>(oneapi::tbb::flow::unlimited);
6851c0b2f7Stbbdev }
6951c0b2f7Stbbdev 
7051c0b2f7Stbbdev //! Test async_node inheritance relations
7151c0b2f7Stbbdev //! \brief \ref interface
7251c0b2f7Stbbdev TEST_CASE("async_node superclasses"){
73*de0109beSIlya Mishin     conformance::test_inheritance<oneapi::tbb::flow::async_node<int, int>, int, int>();
74*de0109beSIlya Mishin     conformance::test_inheritance<oneapi::tbb::flow::async_node<void*, float>, void*, float>();
75*de0109beSIlya Mishin     conformance::test_inheritance<oneapi::tbb::flow::async_node<input_msg, output_msg>, input_msg, output_msg>();
76*de0109beSIlya Mishin }
77*de0109beSIlya Mishin 
78*de0109beSIlya Mishin //! Test node broadcast messages to successors
79*de0109beSIlya Mishin //! \brief \ref requirement
80*de0109beSIlya Mishin TEST_CASE("async_node broadcast"){
81*de0109beSIlya Mishin     conformance::counting_functor<int> fun(conformance::expected);
82*de0109beSIlya Mishin     conformance::test_forwarding<oneapi::tbb::flow::async_node<input_msg, int>, input_msg, int>(1, oneapi::tbb::flow::unlimited, fun);
83*de0109beSIlya Mishin }
84*de0109beSIlya Mishin 
85*de0109beSIlya Mishin //! Test async_node has a user-settable concurrency limit. It can be set to one of predefined values.
86*de0109beSIlya Mishin //! The user can also provide a value of type std::size_t to limit concurrency.
87*de0109beSIlya Mishin //! Test that not more than limited threads works in parallel.
88*de0109beSIlya Mishin //! \brief \ref requirement
89*de0109beSIlya Mishin TEST_CASE("concurrency follows set limits"){
90*de0109beSIlya Mishin     conformance::test_concurrency<oneapi::tbb::flow::async_node<int, int>>();
91*de0109beSIlya Mishin }
92*de0109beSIlya Mishin 
93*de0109beSIlya Mishin //! Test body copying and copy_body logic
94*de0109beSIlya Mishin //! Test the body object passed to a node is copied
95*de0109beSIlya Mishin //! \brief \ref interface
96*de0109beSIlya Mishin TEST_CASE("async_node body copying"){
97*de0109beSIlya Mishin     conformance::test_copy_body_function<oneapi::tbb::flow::async_node<int, int>, conformance::copy_counting_object<int>>(oneapi::tbb::flow::unlimited);
98*de0109beSIlya Mishin }
99*de0109beSIlya Mishin 
100*de0109beSIlya Mishin //! Test node reject the incoming message if the concurrency limit achieved.
101*de0109beSIlya Mishin //! \brief \ref interface
102*de0109beSIlya Mishin TEST_CASE("async_node with rejecting policy"){
103*de0109beSIlya Mishin     conformance::test_rejecting<oneapi::tbb::flow::async_node<int, int, oneapi::tbb::flow::rejecting>>();
104*de0109beSIlya Mishin }
105*de0109beSIlya Mishin 
106*de0109beSIlya Mishin //! Test node Input class meet the DefaultConstructible and CopyConstructible requirements and Output class meet the CopyConstructible requirements.
107*de0109beSIlya Mishin //! \brief \ref interface \ref requirement
108*de0109beSIlya Mishin TEST_CASE("Test async_node Output and Input class") {
109*de0109beSIlya Mishin     using Body = conformance::copy_counting_object<int>;
110*de0109beSIlya Mishin     conformance::test_output_input_class<oneapi::tbb::flow::async_node<Body, Body>, Body>();
111*de0109beSIlya Mishin }
112*de0109beSIlya Mishin 
113*de0109beSIlya Mishin //! Test the body of assync_node typically submits the messages to an external activity for processing outside of the graph.
114*de0109beSIlya Mishin //! \brief \ref interface
115*de0109beSIlya Mishin TEST_CASE("async_node with rejecting policy"){
116*de0109beSIlya Mishin     using async_node_type = tbb::flow::async_node<int, int>;
117*de0109beSIlya Mishin     using gateway_type = async_node_type::gateway_type;
118*de0109beSIlya Mishin 
119*de0109beSIlya Mishin     oneapi::tbb::flow::graph g;
120*de0109beSIlya Mishin     std::atomic<bool> flag{false};
121*de0109beSIlya Mishin     std::thread thr;
122*de0109beSIlya Mishin     async_node_type testing_node{
123*de0109beSIlya Mishin       g, tbb::flow::unlimited,
124*de0109beSIlya Mishin       [&](const int& input, gateway_type& gateway) {
125*de0109beSIlya Mishin           gateway.reserve_wait();
126*de0109beSIlya Mishin           thr = std::thread{[&]{
127*de0109beSIlya Mishin               flag = true;
128*de0109beSIlya Mishin               gateway.try_put(input);
129*de0109beSIlya Mishin               gateway.release_wait();
130*de0109beSIlya Mishin           }};
131*de0109beSIlya Mishin       }
132*de0109beSIlya Mishin     };
133*de0109beSIlya Mishin 
134*de0109beSIlya Mishin     testing_node.try_put(1);
135*de0109beSIlya Mishin     g.wait_for_all();
136*de0109beSIlya Mishin     CHECK_MESSAGE((flag.load()), "The body of assync_node must submits the messages to an external activity for processing outside of the graph");
137*de0109beSIlya Mishin     thr.join();
13851c0b2f7Stbbdev }
139