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 
2151c0b2f7Stbbdev #include "conformance_flowgraph.h"
2251c0b2f7Stbbdev 
23*de0109beSIlya Mishin using input_msg = conformance::message</*default_ctor*/true, /*copy_ctor*/true, /*copy_assign*/false>;
24*de0109beSIlya Mishin using output_msg = conformance::message</*default_ctor*/false, /*copy_ctor*/true, /*copy_assign*/false>;
25*de0109beSIlya Mishin 
2651c0b2f7Stbbdev //! \file conformance_function_node.cpp
2751c0b2f7Stbbdev //! \brief Test for [flow_graph.function_node] specification
2851c0b2f7Stbbdev 
2951c0b2f7Stbbdev /*
30*de0109beSIlya Mishin     Test node deduction guides
3151c0b2f7Stbbdev */
3251c0b2f7Stbbdev #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
33*de0109beSIlya Mishin 
34*de0109beSIlya Mishin int function_body_f(const int&) { return 1; }
35*de0109beSIlya Mishin 
36*de0109beSIlya Mishin template <typename Body>
37*de0109beSIlya Mishin void test_deduction_guides_common(Body body) {
38*de0109beSIlya Mishin     using namespace tbb::flow;
3951c0b2f7Stbbdev     graph g;
4051c0b2f7Stbbdev 
4151c0b2f7Stbbdev     function_node f1(g, unlimited, body);
42*de0109beSIlya Mishin     static_assert(std::is_same_v<decltype(f1), function_node<int, int>>);
43*de0109beSIlya Mishin 
44*de0109beSIlya Mishin     function_node f2(g, unlimited, body, rejecting());
45*de0109beSIlya Mishin     static_assert(std::is_same_v<decltype(f2), function_node<int, int, rejecting>>);
46*de0109beSIlya Mishin 
47*de0109beSIlya Mishin     function_node f3(g, unlimited, body, node_priority_t(5));
48*de0109beSIlya Mishin     static_assert(std::is_same_v<decltype(f3), function_node<int, int>>);
49*de0109beSIlya Mishin 
50*de0109beSIlya Mishin     function_node f4(g, unlimited, body, rejecting(), node_priority_t(5));
51*de0109beSIlya Mishin     static_assert(std::is_same_v<decltype(f4), function_node<int, int, rejecting>>);
52*de0109beSIlya Mishin 
53*de0109beSIlya Mishin #if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
54*de0109beSIlya Mishin     function_node f5(follows(f2), unlimited, body);
55*de0109beSIlya Mishin     static_assert(std::is_same_v<decltype(f5), function_node<int, int>>);
56*de0109beSIlya Mishin 
57*de0109beSIlya Mishin     function_node f6(follows(f5), unlimited, body, rejecting());
58*de0109beSIlya Mishin     static_assert(std::is_same_v<decltype(f6), function_node<int, int, rejecting>>);
59*de0109beSIlya Mishin 
60*de0109beSIlya Mishin     function_node f7(follows(f6), unlimited, body, node_priority_t(5));
61*de0109beSIlya Mishin     static_assert(std::is_same_v<decltype(f7), function_node<int, int>>);
62*de0109beSIlya Mishin 
63*de0109beSIlya Mishin     function_node f8(follows(f7), unlimited, body, rejecting(), node_priority_t(5));
64*de0109beSIlya Mishin     static_assert(std::is_same_v<decltype(f8), function_node<int, int, rejecting>>);
65*de0109beSIlya Mishin #endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
66*de0109beSIlya Mishin 
67*de0109beSIlya Mishin     function_node f9(f1);
68*de0109beSIlya Mishin     static_assert(std::is_same_v<decltype(f9), function_node<int, int>>);
6951c0b2f7Stbbdev }
70*de0109beSIlya Mishin 
71*de0109beSIlya Mishin void test_deduction_guides() {
72*de0109beSIlya Mishin     test_deduction_guides_common([](const int&)->int { return 1; });
73*de0109beSIlya Mishin     test_deduction_guides_common([](const int&) mutable ->int { return 1; });
74*de0109beSIlya Mishin     test_deduction_guides_common(function_body_f);
75*de0109beSIlya Mishin }
76*de0109beSIlya Mishin 
7751c0b2f7Stbbdev #endif
7851c0b2f7Stbbdev 
79*de0109beSIlya Mishin //! Test calling function body
80*de0109beSIlya Mishin //! \brief \ref interface \ref requirement
81*de0109beSIlya Mishin TEST_CASE("Test function_node body") {
82*de0109beSIlya Mishin     conformance::test_body_exec<oneapi::tbb::flow::function_node<input_msg, output_msg>, input_msg, output_msg>(oneapi::tbb::flow::unlimited);
8351c0b2f7Stbbdev }
8451c0b2f7Stbbdev 
85*de0109beSIlya Mishin //! Test function_node constructors
86*de0109beSIlya Mishin //! \brief \ref requirement
87*de0109beSIlya Mishin TEST_CASE("function_node constructors"){
8849e08aacStbbdev     using namespace oneapi::tbb::flow;
8951c0b2f7Stbbdev     graph g;
9051c0b2f7Stbbdev 
91*de0109beSIlya Mishin     conformance::counting_functor<int> fun;
9251c0b2f7Stbbdev 
93*de0109beSIlya Mishin     function_node<int, int> fn1(g, unlimited, fun);
94*de0109beSIlya Mishin     function_node<int, int> fn2(g, unlimited, fun, oneapi::tbb::flow::node_priority_t(1));
95*de0109beSIlya Mishin 
96*de0109beSIlya Mishin     function_node<int, int, lightweight> lw_node1(g, serial, fun, lightweight());
97*de0109beSIlya Mishin     function_node<int, int, lightweight> lw_node2(g, serial, fun, lightweight(), oneapi::tbb::flow::node_priority_t(1));
9851c0b2f7Stbbdev }
9951c0b2f7Stbbdev 
100*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.
101*de0109beSIlya Mishin //! The predecessors and successors of src are not copied.
102*de0109beSIlya Mishin //! \brief \ref requirement
103*de0109beSIlya Mishin TEST_CASE("function_node copy constructor"){
104*de0109beSIlya Mishin     conformance::test_copy_ctor<oneapi::tbb::flow::function_node<int, int>>();
10551c0b2f7Stbbdev }
10651c0b2f7Stbbdev 
107*de0109beSIlya Mishin //! Test node reject the incoming message if the concurrency limit achieved.
10851c0b2f7Stbbdev //! \brief \ref interface
10951c0b2f7Stbbdev TEST_CASE("function_node with rejecting policy"){
110*de0109beSIlya Mishin     conformance::test_rejecting<oneapi::tbb::flow::function_node<int, int, oneapi::tbb::flow::rejecting>>();
11151c0b2f7Stbbdev }
11251c0b2f7Stbbdev 
11351c0b2f7Stbbdev //! Test body copying and copy_body logic
114*de0109beSIlya Mishin //! Test the body object passed to a node is copied
11551c0b2f7Stbbdev //! \brief \ref interface
11651c0b2f7Stbbdev TEST_CASE("function_node and body copying"){
117*de0109beSIlya Mishin     conformance::test_copy_body_function<oneapi::tbb::flow::function_node<int, int>, conformance::copy_counting_object<int>>(oneapi::tbb::flow::unlimited);
11851c0b2f7Stbbdev }
11951c0b2f7Stbbdev 
120*de0109beSIlya Mishin //! Test function_node is a graph_node, receiver<Input>, and sender<Output>
12151c0b2f7Stbbdev //! \brief \ref interface
12251c0b2f7Stbbdev TEST_CASE("function_node superclasses"){
123*de0109beSIlya Mishin     conformance::test_inheritance<oneapi::tbb::flow::function_node<int, int>, int, int>();
124*de0109beSIlya Mishin     conformance::test_inheritance<oneapi::tbb::flow::function_node<void*, float>, void*, float>();
125*de0109beSIlya Mishin     conformance::test_inheritance<oneapi::tbb::flow::function_node<input_msg, output_msg>, input_msg, output_msg>();
12651c0b2f7Stbbdev }
12751c0b2f7Stbbdev 
128*de0109beSIlya Mishin //! Test node not buffered unsuccessful message, and try_get after rejection should not succeed.
12951c0b2f7Stbbdev //! \brief \ref requirement
13051c0b2f7Stbbdev TEST_CASE("function_node buffering"){
131*de0109beSIlya Mishin     conformance::dummy_functor<int> fun;
132*de0109beSIlya Mishin     conformance::test_buffering<oneapi::tbb::flow::function_node<input_msg, int, oneapi::tbb::flow::rejecting>, input_msg>(oneapi::tbb::flow::unlimited, fun);
133*de0109beSIlya Mishin     conformance::test_buffering<oneapi::tbb::flow::function_node<input_msg, int, oneapi::tbb::flow::queueing>, input_msg>(oneapi::tbb::flow::unlimited, fun);
13451c0b2f7Stbbdev }
13551c0b2f7Stbbdev 
136*de0109beSIlya Mishin //! Test node broadcast messages to successors
13751c0b2f7Stbbdev //! \brief \ref requirement
13851c0b2f7Stbbdev TEST_CASE("function_node broadcast"){
139*de0109beSIlya Mishin     conformance::counting_functor<int> fun(conformance::expected);
140*de0109beSIlya Mishin     conformance::test_forwarding<oneapi::tbb::flow::function_node<input_msg, int>, input_msg, int>(1, oneapi::tbb::flow::unlimited, fun);
14151c0b2f7Stbbdev }
14251c0b2f7Stbbdev 
14351c0b2f7Stbbdev //! Test deduction guides
14451c0b2f7Stbbdev //! \brief \ref interface \ref requirement
14551c0b2f7Stbbdev TEST_CASE("Deduction guides"){
14651c0b2f7Stbbdev #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
14751c0b2f7Stbbdev     test_deduction_guides();
14851c0b2f7Stbbdev #endif
14951c0b2f7Stbbdev }
15051c0b2f7Stbbdev 
15151c0b2f7Stbbdev //! Test priorities work in single-threaded configuration
15251c0b2f7Stbbdev //! \brief \ref requirement
15351c0b2f7Stbbdev TEST_CASE("function_node priority support"){
154*de0109beSIlya Mishin     conformance::test_priority<oneapi::tbb::flow::function_node<input_msg, int>, input_msg>(oneapi::tbb::flow::unlimited);
15551c0b2f7Stbbdev }
15651c0b2f7Stbbdev 
157*de0109beSIlya Mishin //! Test function_node has a user-settable concurrency limit. It can be set to one of predefined values.
158*de0109beSIlya Mishin //! The user can also provide a value of type std::size_t to limit concurrency.
159*de0109beSIlya Mishin //! Test that not more than limited threads works in parallel.
16051c0b2f7Stbbdev //! \brief \ref requirement
16151c0b2f7Stbbdev TEST_CASE("concurrency follows set limits"){
162*de0109beSIlya Mishin     conformance::test_concurrency<oneapi::tbb::flow::function_node<int, int>>();
16351c0b2f7Stbbdev }
16451c0b2f7Stbbdev 
165*de0109beSIlya Mishin //! Test node Input class meet the DefaultConstructible and CopyConstructible requirements and Output class meet the CopyConstructible requirements.
16651c0b2f7Stbbdev //! \brief \ref interface \ref requirement
167*de0109beSIlya Mishin TEST_CASE("Test function_node Output and Input class") {
168*de0109beSIlya Mishin     using Body = conformance::copy_counting_object<int>;
169*de0109beSIlya Mishin     conformance::test_output_input_class<oneapi::tbb::flow::function_node<Body, Body>, Body>();
17051c0b2f7Stbbdev }
171