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
20b15aabb3Stbbdev 
21*de0109beSIlya Mishin #define CONFORMANCE_MULTIFUNCTION_NODE
2251c0b2f7Stbbdev 
2351c0b2f7Stbbdev #include "conformance_flowgraph.h"
2451c0b2f7Stbbdev 
2551c0b2f7Stbbdev //! \file conformance_multifunction_node.cpp
2651c0b2f7Stbbdev //! \brief Test for [flow_graph.function_node] specification
2751c0b2f7Stbbdev 
28*de0109beSIlya Mishin using input_msg = conformance::message</*default_ctor*/true, /*copy_ctor*/true, /*copy_assign*/false>;
29*de0109beSIlya Mishin using output_msg = conformance::message</*default_ctor*/false, /*copy_ctor*/false, /*copy_assign*/false>;
30*de0109beSIlya Mishin 
3151c0b2f7Stbbdev /*
32*de0109beSIlya Mishin     Test function_node is a graph_node, receiver<Input>, and sender<Output>
3351c0b2f7Stbbdev */
3451c0b2f7Stbbdev template<typename I, typename O>
3551c0b2f7Stbbdev void test_inheritance(){
3649e08aacStbbdev     using namespace oneapi::tbb::flow;
3751c0b2f7Stbbdev 
3851c0b2f7Stbbdev     CHECK_MESSAGE((std::is_base_of<graph_node, multifunction_node<I, O>>::value), "multifunction_node should be derived from graph_node");
3951c0b2f7Stbbdev     CHECK_MESSAGE((std::is_base_of<receiver<I>, multifunction_node<I, O>>::value), "multifunction_node should be derived from receiver<Input>");
4051c0b2f7Stbbdev }
4151c0b2f7Stbbdev 
42*de0109beSIlya Mishin //! Test node reject the incoming message if the concurrency limit achieved.
4351c0b2f7Stbbdev //! \brief \ref interface
4451c0b2f7Stbbdev TEST_CASE("multifunction_node with rejecting policy"){
45*de0109beSIlya Mishin     conformance::test_rejecting<oneapi::tbb::flow::multifunction_node<int, std::tuple<int>, oneapi::tbb::flow::rejecting>>();
4651c0b2f7Stbbdev }
4751c0b2f7Stbbdev 
48*de0109beSIlya Mishin //! Test nodes for execution with priority in single-threaded configuration
4951c0b2f7Stbbdev //! \brief \ref interface
5051c0b2f7Stbbdev TEST_CASE("multifunction_node priority"){
51*de0109beSIlya Mishin     conformance::test_priority<oneapi::tbb::flow::multifunction_node<input_msg, std::tuple<int>>, input_msg>(oneapi::tbb::flow::unlimited);
5251c0b2f7Stbbdev }
5351c0b2f7Stbbdev 
54*de0109beSIlya Mishin //! Test function_node has a user-settable concurrency limit. It can be set to one of predefined values.
55*de0109beSIlya Mishin //! The user can also provide a value of type std::size_t to limit concurrency.
56*de0109beSIlya Mishin //! Test that not more than limited threads works in parallel.
5751c0b2f7Stbbdev //! \brief \ref interface
5851c0b2f7Stbbdev TEST_CASE("multifunction_node concurrency"){
59*de0109beSIlya Mishin     conformance::test_concurrency<oneapi::tbb::flow::multifunction_node<int, std::tuple<int>>>();
6051c0b2f7Stbbdev }
6151c0b2f7Stbbdev 
62*de0109beSIlya Mishin //! Test all node constructors
6351c0b2f7Stbbdev //! \brief \ref interface
6451c0b2f7Stbbdev TEST_CASE("multifunction_node constructors"){
65*de0109beSIlya Mishin     using namespace oneapi::tbb::flow;
66*de0109beSIlya Mishin     graph g;
67*de0109beSIlya Mishin 
68*de0109beSIlya Mishin     conformance::counting_functor<int> fun;
69*de0109beSIlya Mishin 
70*de0109beSIlya Mishin     multifunction_node<int, std::tuple<int>> fn1(g, unlimited, fun);
71*de0109beSIlya Mishin     multifunction_node<int, std::tuple<int>> fn2(g, unlimited, fun, oneapi::tbb::flow::node_priority_t(1));
72*de0109beSIlya Mishin 
73*de0109beSIlya Mishin     multifunction_node<int, std::tuple<int>, lightweight> lw_node1(g, serial, fun, lightweight());
74*de0109beSIlya Mishin     multifunction_node<int, std::tuple<int>, lightweight> lw_node2(g, serial, fun, lightweight(), oneapi::tbb::flow::node_priority_t(1));
7551c0b2f7Stbbdev }
7651c0b2f7Stbbdev 
77*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.
78*de0109beSIlya Mishin //! The predecessors and successors of src are not copied.
79*de0109beSIlya Mishin //! \brief \ref interface
80*de0109beSIlya Mishin TEST_CASE("multifunction_node copy constructor"){
81*de0109beSIlya Mishin     conformance::test_copy_ctor<oneapi::tbb::flow::multifunction_node<int, std::tuple<int>>>();
82*de0109beSIlya Mishin }
83*de0109beSIlya Mishin 
84*de0109beSIlya Mishin //! Test node not buffered unsuccessful message, and try_get after rejection should not succeed.
8551c0b2f7Stbbdev //! \brief \ref requirement
8651c0b2f7Stbbdev TEST_CASE("multifunction_node buffering"){
87*de0109beSIlya Mishin     conformance::dummy_functor<int> fun;
88*de0109beSIlya Mishin     conformance::test_buffering<oneapi::tbb::flow::multifunction_node<input_msg, std::tuple<int>,
89*de0109beSIlya Mishin     oneapi::tbb::flow::rejecting>, input_msg>(oneapi::tbb::flow::unlimited, fun);
9051c0b2f7Stbbdev }
9151c0b2f7Stbbdev 
92*de0109beSIlya Mishin //! Test multifunction_node broadcasting
9351c0b2f7Stbbdev //! \brief \ref requirement
9451c0b2f7Stbbdev TEST_CASE("multifunction_node broadcast"){
95*de0109beSIlya Mishin     conformance::counting_functor<int> fun(conformance::expected);
96*de0109beSIlya Mishin     conformance::test_forwarding<oneapi::tbb::flow::multifunction_node<input_msg, std::tuple<int>>, input_msg, int>(1, oneapi::tbb::flow::unlimited, fun);
9751c0b2f7Stbbdev }
9851c0b2f7Stbbdev 
99*de0109beSIlya Mishin //! Test the body object passed to a node is copied
10051c0b2f7Stbbdev //! \brief \ref interface
101*de0109beSIlya Mishin TEST_CASE("multifunction_node copy body"){
102*de0109beSIlya Mishin     conformance::test_copy_body_function<oneapi::tbb::flow::multifunction_node<int, std::tuple<int>>, conformance::copy_counting_object<int>>(oneapi::tbb::flow::unlimited);
10351c0b2f7Stbbdev }
10451c0b2f7Stbbdev 
105*de0109beSIlya Mishin //! Test execution of node body
106*de0109beSIlya Mishin //! Test node can do try_put call
10751c0b2f7Stbbdev //! \brief \ref interface \ref requirement
10851c0b2f7Stbbdev TEST_CASE("multifunction_node body") {
109*de0109beSIlya Mishin     conformance::test_body_exec<oneapi::tbb::flow::multifunction_node<input_msg, std::tuple<output_msg>, oneapi::tbb::flow::rejecting>, input_msg, output_msg>(oneapi::tbb::flow::unlimited);
110*de0109beSIlya Mishin }
111*de0109beSIlya Mishin 
112*de0109beSIlya Mishin //! Test multifunction_node output_ports() returns a tuple of output ports.
113*de0109beSIlya Mishin //! \brief \ref interface \ref requirement
114*de0109beSIlya Mishin TEST_CASE("multifunction_node output_ports") {
115*de0109beSIlya Mishin     using namespace oneapi::tbb::flow;
116*de0109beSIlya Mishin     graph g;
117*de0109beSIlya Mishin     conformance::dummy_functor<int> fun;
118*de0109beSIlya Mishin     oneapi::tbb::flow::multifunction_node <int, std::tuple<int>> node(g, unlimited, fun);
119*de0109beSIlya Mishin 
120*de0109beSIlya Mishin     CHECK_MESSAGE((std::is_same<oneapi::tbb::flow::multifunction_node<int, std::tuple<int>>::output_ports_type&,
121*de0109beSIlya Mishin         decltype(node.output_ports())>::value), "multifunction_node output_ports should returns a tuple of output ports");
12251c0b2f7Stbbdev }
12351c0b2f7Stbbdev 
12451c0b2f7Stbbdev //! Test inheritance relations
12551c0b2f7Stbbdev //! \brief \ref interface
12651c0b2f7Stbbdev TEST_CASE("multifunction_node superclasses"){
12751c0b2f7Stbbdev     test_inheritance<int, std::tuple<int>>();
12851c0b2f7Stbbdev     test_inheritance<void*, std::tuple<float>>();
129*de0109beSIlya Mishin     test_inheritance<input_msg, std::tuple<output_msg>>();
130*de0109beSIlya Mishin }
131*de0109beSIlya Mishin 
132*de0109beSIlya Mishin //! Test node Input class meet the DefaultConstructible and CopyConstructible requirements and Output class meet the CopyConstructible requirements.
133*de0109beSIlya Mishin //! \brief \ref interface \ref requirement
134*de0109beSIlya Mishin TEST_CASE("Test function_node Output and Input class") {
135*de0109beSIlya Mishin     using Body = conformance::copy_counting_object<int>;
136*de0109beSIlya Mishin     conformance::test_output_input_class<oneapi::tbb::flow::multifunction_node<Body, std::tuple<Body>>, Body>();
13751c0b2f7Stbbdev }
138