Skip to content

Commit

Permalink
Split tbb::flow::join_node testing into separate test files (uxlfound…
Browse files Browse the repository at this point in the history
…ation#741)

In order to reduce GOT size on MIPS that leads to linkage errors (relocation truncated to fit: R_MIPS_GOT_PAGE) in debug, tbb::flow::join_node testing was split into separate files.

Signed-off-by: Ilya Isaev <ilya.isaev@intel.com>
  • Loading branch information
isaevil authored Jan 24, 2022
1 parent 35e0f55 commit e0cc518
Show file tree
Hide file tree
Showing 9 changed files with 294 additions and 206 deletions.
5 changes: 3 additions & 2 deletions cmake/compilers/GNU.cmake
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2020-2021 Intel Corporation
# Copyright (c) 2020-2022 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -56,7 +56,8 @@ endif()

# Workaround for heavy tests and too many symbols in debug (rellocation truncated to fit: R_MIPS_CALL16)
if ("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "mips")
set(TBB_TEST_COMPILE_FLAGS ${TBB_TEST_COMPILE_FLAGS} -DTBB_TEST_LOW_WORKLOAD $<$<CONFIG:DEBUG>:-mxgot>)
set(TBB_TEST_COMPILE_FLAGS ${TBB_TEST_COMPILE_FLAGS} -DTBB_TEST_LOW_WORKLOAD $<$<CONFIG:DEBUG>:-fPIE -mxgot>)
set(TBB_TEST_LINK_FLAGS ${TBB_TEST_LINK_FLAGS} $<$<CONFIG:DEBUG>:-pie>)
endif()

set(TBB_IPO_COMPILE_FLAGS $<$<NOT:$<CONFIG:Debug>>:-flto>)
Expand Down
8 changes: 5 additions & 3 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2020-2021 Intel Corporation
# Copyright (c) 2020-2022 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -64,9 +64,9 @@ function(tbb_add_test)
# Prefer using target_link_options instead of target_link_libraries to specify link options because
# target_link_libraries may incorrectly handle some options (on Windows, for example).
if (COMMAND target_link_options)
target_link_options(${_tbb_test_TARGET_NAME} PRIVATE ${TBB_COMMON_LINK_FLAGS})
target_link_options(${_tbb_test_TARGET_NAME} PRIVATE ${TBB_COMMON_LINK_FLAGS} ${TBB_TEST_LINK_FLAGS})
else()
target_link_libraries(${_tbb_test_TARGET_NAME} PRIVATE ${TBB_COMMON_LINK_FLAGS})
target_link_libraries(${_tbb_test_TARGET_NAME} PRIVATE ${TBB_COMMON_LINK_FLAGS} ${TBB_TEST_LINK_FLAGS})
endif()

target_compile_definitions(${_tbb_test_TARGET_NAME} PRIVATE
Expand Down Expand Up @@ -408,6 +408,8 @@ if (TARGET TBB::tbb)
tbb_add_test(SUBDIR tbb NAME test_join_node DEPENDENCIES TBB::tbb)
tbb_add_test(SUBDIR tbb NAME test_join_node_key_matching DEPENDENCIES TBB::tbb)
tbb_add_test(SUBDIR tbb NAME test_join_node_msg_key_matching DEPENDENCIES TBB::tbb)
tbb_add_test(SUBDIR tbb NAME test_join_node_msg_key_matching_n_args DEPENDENCIES TBB::tbb)
tbb_add_test(SUBDIR tbb NAME test_join_node_preview DEPENDENCIES TBB::tbb)
tbb_add_test(SUBDIR tbb NAME test_limiter_node DEPENDENCIES TBB::tbb)
tbb_add_test(SUBDIR tbb NAME test_priority_queue_node DEPENDENCIES TBB::tbb)
tbb_add_test(SUBDIR tbb NAME test_queue_node DEPENDENCIES TBB::tbb)
Expand Down
117 changes: 117 additions & 0 deletions test/common/test_join_node_multiple_predecessors.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
Copyright (c) 2022 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#ifndef __TBB_test_common_test_join_node_multiple_predecessors_H_
#define __TBB_test_common_test_join_node_multiple_predecessors_H_

#include "config.h"
#include "oneapi/tbb/flow_graph.h"

namespace multiple_predecessors {

using namespace tbb::flow;

using join_node_t = join_node<std::tuple<continue_msg, continue_msg, continue_msg>, reserving>;
using queue_node_t = queue_node<std::tuple<continue_msg, continue_msg, continue_msg>>;

void twist_join_connections(
buffer_node<continue_msg>& bn1, buffer_node<continue_msg>& bn2, buffer_node<continue_msg>& bn3,
join_node_t& jn)
{
// order, in which edges are created/destroyed, is important
make_edge(bn1, input_port<0>(jn));
make_edge(bn2, input_port<0>(jn));
make_edge(bn3, input_port<0>(jn));

remove_edge(bn3, input_port<0>(jn));
make_edge (bn3, input_port<2>(jn));

remove_edge(bn2, input_port<0>(jn));
make_edge (bn2, input_port<1>(jn));
}

std::unique_ptr<join_node_t> connect_join_via_make_edge(
graph& g, buffer_node<continue_msg>& bn1, buffer_node<continue_msg>& bn2,
buffer_node<continue_msg>& bn3, queue_node_t& qn)
{
std::unique_ptr<join_node_t> jn( new join_node_t(g) );
twist_join_connections( bn1, bn2, bn3, *jn );
make_edge(*jn, qn);
return jn;
}

#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
std::unique_ptr<join_node_t> connect_join_via_follows(
graph&, buffer_node<continue_msg>& bn1, buffer_node<continue_msg>& bn2,
buffer_node<continue_msg>& bn3, queue_node_t& qn)
{
auto bn_set = make_node_set(bn1, bn2, bn3);
std::unique_ptr<join_node_t> jn( new join_node_t(follows(bn_set)) );
make_edge(*jn, qn);
return jn;
}

std::unique_ptr<join_node_t> connect_join_via_precedes(
graph&, buffer_node<continue_msg>& bn1, buffer_node<continue_msg>& bn2,
buffer_node<continue_msg>& bn3, queue_node_t& qn)
{
auto qn_set = make_node_set(qn);
auto qn_copy_set = qn_set;
std::unique_ptr<join_node_t> jn( new join_node_t(precedes(qn_copy_set)) );
twist_join_connections( bn1, bn2, bn3, *jn );
return jn;
}
#endif // TBB_PREVIEW_FLOW_GRAPH_FEATURES

void run_and_check(
graph& g, buffer_node<continue_msg>& bn1, buffer_node<continue_msg>& bn2,
buffer_node<continue_msg>& bn3, queue_node_t& qn, bool expected)
{
std::tuple<continue_msg, continue_msg, continue_msg> msg;

bn1.try_put(continue_msg());
bn2.try_put(continue_msg());
bn3.try_put(continue_msg());
g.wait_for_all();

CHECK_MESSAGE(
(qn.try_get(msg) == expected),
"Unexpected message absence/existence at the end of the graph."
);
}

template<typename ConnectJoinNodeFunc>
void test(ConnectJoinNodeFunc&& connect_join_node) {
graph g;
buffer_node<continue_msg> bn1(g);
buffer_node<continue_msg> bn2(g);
buffer_node<continue_msg> bn3(g);
queue_node_t qn(g);

auto jn = connect_join_node(g, bn1, bn2, bn3, qn);

run_and_check(g, bn1, bn2, bn3, qn, /*expected=*/true);

remove_edge(bn3, input_port<2>(*jn));
remove_edge(bn2, input_port<1>(*jn));
remove_edge(bn1, *jn); //Removes an edge between a sender and port 0 of a multi-input successor.
remove_edge(*jn, qn);

run_and_check(g, bn1, bn2, bn3, qn, /*expected=*/false);
}
} // namespace multiple_predecessors

#endif // __TBB_test_common_test_join_node_multiple_predecessors_H_
154 changes: 7 additions & 147 deletions test/tbb/test_join_node.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Copyright (c) 2005-2022 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -22,11 +22,11 @@
#include "common/config.h"

#include "test_join_node.h"
#include "common/test_join_node_multiple_predecessors.h"

//! \file test_join_node.cpp
//! \brief Test for [flow_graph.join_node] specification


static std::atomic<int> output_count;

// get the tag from the output tuple and emit it.
Expand Down Expand Up @@ -122,147 +122,6 @@ class generate_recirc_test {
}
};

#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
#include <array>
#include <vector>
void test_follows_and_precedes_api() {
using msg_t = tbb::flow::continue_msg;
using JoinOutputType = std::tuple<msg_t, msg_t, msg_t>;

std::array<msg_t, 3> messages_for_follows = { {msg_t(), msg_t(), msg_t()} };
std::vector<msg_t> messages_for_precedes = {msg_t(), msg_t(), msg_t()};

follows_and_precedes_testing::test_follows
<msg_t, tbb::flow::join_node<JoinOutputType>, tbb::flow::buffer_node<msg_t>>(messages_for_follows);
follows_and_precedes_testing::test_follows
<msg_t, tbb::flow::join_node<JoinOutputType, tbb::flow::queueing>>(messages_for_follows);
follows_and_precedes_testing::test_follows
<msg_t, tbb::flow::join_node<JoinOutputType, tbb::flow::reserving>, tbb::flow::buffer_node<msg_t>>(messages_for_follows);
auto b = [](msg_t) { return msg_t(); };
class hash_compare {
public:
std::size_t hash(msg_t) const { return 0; }
bool equal(msg_t, msg_t) const { return true; }
};
follows_and_precedes_testing::test_follows
<msg_t, tbb::flow::join_node<JoinOutputType, tbb::flow::key_matching<msg_t, hash_compare>>, tbb::flow::buffer_node<msg_t>>
(messages_for_follows, b, b, b);

follows_and_precedes_testing::test_precedes
<msg_t, tbb::flow::join_node<JoinOutputType>>(messages_for_precedes);
follows_and_precedes_testing::test_precedes
<msg_t, tbb::flow::join_node<JoinOutputType, tbb::flow::queueing>>(messages_for_precedes);
follows_and_precedes_testing::test_precedes
<msg_t, tbb::flow::join_node<JoinOutputType, tbb::flow::reserving>>(messages_for_precedes);
follows_and_precedes_testing::test_precedes
<msg_t, tbb::flow::join_node<JoinOutputType, tbb::flow::key_matching<msg_t, hash_compare>>>
(messages_for_precedes, b, b, b);
}
#endif

namespace multiple_predecessors {

using namespace tbb::flow;

using join_node_t = join_node<std::tuple<continue_msg, continue_msg, continue_msg>, reserving>;
using queue_node_t = queue_node<std::tuple<continue_msg, continue_msg, continue_msg>>;

void twist_join_connections(
buffer_node<continue_msg>& bn1, buffer_node<continue_msg>& bn2, buffer_node<continue_msg>& bn3,
join_node_t& jn)
{
// order, in which edges are created/destroyed, is important
make_edge(bn1, input_port<0>(jn));
make_edge(bn2, input_port<0>(jn));
make_edge(bn3, input_port<0>(jn));

remove_edge(bn3, input_port<0>(jn));
make_edge (bn3, input_port<2>(jn));

remove_edge(bn2, input_port<0>(jn));
make_edge (bn2, input_port<1>(jn));
}

std::unique_ptr<join_node_t> connect_join_via_make_edge(
graph& g, buffer_node<continue_msg>& bn1, buffer_node<continue_msg>& bn2,
buffer_node<continue_msg>& bn3, queue_node_t& qn)
{
std::unique_ptr<join_node_t> jn( new join_node_t(g) );
twist_join_connections( bn1, bn2, bn3, *jn );
make_edge(*jn, qn);
return jn;
}

#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
std::unique_ptr<join_node_t> connect_join_via_follows(
graph&, buffer_node<continue_msg>& bn1, buffer_node<continue_msg>& bn2,
buffer_node<continue_msg>& bn3, queue_node_t& qn)
{
auto bn_set = make_node_set(bn1, bn2, bn3);
std::unique_ptr<join_node_t> jn( new join_node_t(follows(bn_set)) );
make_edge(*jn, qn);
return jn;
}

std::unique_ptr<join_node_t> connect_join_via_precedes(
graph&, buffer_node<continue_msg>& bn1, buffer_node<continue_msg>& bn2,
buffer_node<continue_msg>& bn3, queue_node_t& qn)
{
auto qn_set = make_node_set(qn);
auto qn_copy_set = qn_set;
std::unique_ptr<join_node_t> jn( new join_node_t(precedes(qn_copy_set)) );
twist_join_connections( bn1, bn2, bn3, *jn );
return jn;
}
#endif // TBB_PREVIEW_FLOW_GRAPH_FEATURES

void run_and_check(
graph& g, buffer_node<continue_msg>& bn1, buffer_node<continue_msg>& bn2,
buffer_node<continue_msg>& bn3, queue_node_t& qn, bool expected)
{
std::tuple<continue_msg, continue_msg, continue_msg> msg;

bn1.try_put(continue_msg());
bn2.try_put(continue_msg());
bn3.try_put(continue_msg());
g.wait_for_all();

CHECK_MESSAGE(
(qn.try_get(msg) == expected),
"Unexpected message absence/existence at the end of the graph."
);
}

template<typename ConnectJoinNodeFunc>
void test(ConnectJoinNodeFunc&& connect_join_node) {
graph g;
buffer_node<continue_msg> bn1(g);
buffer_node<continue_msg> bn2(g);
buffer_node<continue_msg> bn3(g);
queue_node_t qn(g);

auto jn = connect_join_node(g, bn1, bn2, bn3, qn);

run_and_check(g, bn1, bn2, bn3, qn, /*expected=*/true);

remove_edge(bn3, input_port<2>(*jn));
remove_edge(bn2, input_port<1>(*jn));
remove_edge(bn1, *jn); //Removes an edge between a sender and port 0 of a multi-input successor.
remove_edge(*jn, qn);

run_and_check(g, bn1, bn2, bn3, qn, /*expected=*/false);
}
} // namespace multiple_predecessors


#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
//! Test follows and precedes API
//! \brief \ref error_guessing
TEST_CASE("Test follows and preceedes API"){
test_follows_and_precedes_api();
}
#endif

//! Test hash buffers behavior
//! \brief \ref error_guessing
TEST_CASE("Tagged buffers test"){
Expand All @@ -283,14 +142,15 @@ TEST_CASE("Recirculation test"){
generate_recirc_test<std::tuple<int,float> >::do_test();
}

// TODO: Look deeper into this test to see if it has the right name
// and if it actually tests some kind of regression. It is possible
// that `connect_join_via_follows` and `connect_join_via_precedes`
// functions are redundant.

//! Test maintaining correct count of ports without input
//! \brief \ref error_guessing
TEST_CASE("Test removal of the predecessor while having none") {
using namespace multiple_predecessors;

test(connect_join_via_make_edge);
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
test(connect_join_via_follows);
test(connect_join_via_precedes);
#endif
}
1 change: 0 additions & 1 deletion test/tbb/test_join_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
#include "common/utils.h"
#include "common/checktype.h"
#include "common/graph_utils.h"
#include "common/test_follows_and_precedes_api.h"

#include <type_traits>

Expand Down
2 changes: 1 addition & 1 deletion test/tbb/test_join_node_key_matching.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Copyright (c) 2005-2022 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
Loading

0 comments on commit e0cc518

Please sign in to comment.