Skip to content

Commit 5f7a6ad

Browse files
committed
🎨 Separate flow tests
Problem: - Flow tests are all in one file. They mix together the tests for regular flows, logging, and flows in separate translation units. - GCC 12 has a constexpr bug that prevents flow steps from compiling. This is worked around in code, but ought to be called out in CMake. Solution: - Separate regular, separate TU, and logging tests for flows. - Control GCC 12 compilation in CMake.
1 parent a342e76 commit 5f7a6ad

File tree

5 files changed

+135
-67
lines changed

5 files changed

+135
-67
lines changed

include/flow/step.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ struct ct_node : rt_node {
5151
}
5252
};
5353

54-
constexpr ct_node() : rt_node{run_func, log_func} {}
54+
constexpr ct_node() : rt_node{+run_func, +log_func} {}
5555

5656
constexpr auto operator*() const {
5757
if constexpr (Identity == subgraph_identity::REFERENCE) {

test/flow/CMakeLists.txt

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
1-
add_unit_test(
2-
"flow_flow_test"
3-
CATCH2
4-
FILES
5-
"flow.cpp"
6-
"flow_cib_func.cpp"
7-
LIBRARIES
8-
warnings
9-
cib)
1+
if(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" AND ${CMAKE_CXX_COMPILER_VERSION}
2+
VERSION_LESS 13)
3+
message(
4+
WARNING
5+
"GCC has a constexpr bug before version 13 that prevents flow steps from compiling. Not adding flow tests."
6+
)
7+
else()
8+
add_unit_test(
9+
"flow_separate_actions_test"
10+
CATCH2
11+
FILES
12+
"flow_cib_func.cpp"
13+
"separate_actions.cpp"
14+
LIBRARIES
15+
warnings
16+
cib)
17+
18+
add_tests(flow logging)
19+
endif()
1020

1121
add_tests(graph graph_builder)
1222

test/flow/flow.cpp

Lines changed: 2 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,14 @@
66

77
#include <catch2/catch_test_macros.hpp>
88

9-
#include <iterator>
109
#include <string>
10+
#include <string_view>
1111

1212
std::string actual = {};
1313

1414
namespace {
1515
using namespace flow::literals;
1616

17-
std::string log_buffer{};
18-
1917
constexpr auto a = flow::action<"a">([] { actual += "a"; });
2018
constexpr auto b = flow::action<"b">([] { actual += "b"; });
2119
constexpr auto c = flow::action<"c">([] { actual += "c"; });
@@ -38,7 +36,6 @@ template <auto... Cs> struct wrapper {
3836
template <typename S, auto... Cs>
3937
constexpr auto check_flow = [](std::string_view expected) -> void {
4038
actual.clear();
41-
log_buffer.clear();
4239
wrapper<Cs...>::template run<S>();
4340
CHECK(actual == expected);
4441
};
@@ -65,7 +62,7 @@ struct VizConfig {
6562
};
6663
} // namespace
6764

68-
TEST_CASE("vizualize flow", "[flow]") {
65+
TEST_CASE("visualize flow", "[flow]") {
6966
cib::nexus<VizConfig> nexus{};
7067
auto viz = nexus.service<VizFlow>();
7168
auto expected = std::string{
@@ -76,9 +73,6 @@ a -> end
7673
CHECK(viz == expected);
7774
}
7875

79-
#if defined(__GNUC__) && __GNUC__ == 12
80-
#else
81-
8276
TEST_CASE("add single action through cib::nexus", "[flow]") {
8377
check_flow<TestFlowAlpha, cib::exports<TestFlowAlpha>,
8478
cib::extend<TestFlowAlpha>(*a)>("a");
@@ -198,52 +192,3 @@ TEST_CASE("add multi action through cib::nexus, run through cib::service",
198192
cib::service<TestFlowBeta>();
199193
CHECK(actual == "abcd");
200194
}
201-
202-
TEST_CASE("add actions using func_decl through cib::nexus", "[flow]") {
203-
check_flow<TestFlowAlpha, cib::exports<TestFlowAlpha>,
204-
cib::extend<TestFlowAlpha>(*"e"_action >> *"f"_action)>("ef");
205-
}
206-
207-
namespace {
208-
struct NamedTestFlow : public flow::service<"TestFlow"> {};
209-
} // namespace
210-
211-
template <>
212-
inline auto logging::config<> =
213-
logging::fmt::config{std::back_inserter(log_buffer)};
214-
215-
TEST_CASE("unnamed flow does not log start/end", "[flow]") {
216-
check_flow<TestFlowAlpha, cib::exports<TestFlowAlpha>>("");
217-
218-
CHECK(std::empty(log_buffer));
219-
}
220-
221-
TEST_CASE("empty flow logs start/end", "[flow]") {
222-
check_flow<NamedTestFlow, cib::exports<NamedTestFlow>>("");
223-
224-
CHECK(log_buffer.find("flow.start(TestFlow)") != std::string::npos);
225-
CHECK(log_buffer.find("flow.end(TestFlow)") != std::string::npos);
226-
}
227-
228-
TEST_CASE("unnamed flow does not log actions", "[flow]") {
229-
check_flow<TestFlowAlpha, cib::exports<TestFlowAlpha>,
230-
cib::extend<TestFlowAlpha>(*a)>("a");
231-
232-
CHECK(log_buffer.find("flow.action(a)") == std::string::npos);
233-
}
234-
235-
TEST_CASE("named flow logs actions", "[flow]") {
236-
check_flow<NamedTestFlow, cib::exports<NamedTestFlow>,
237-
cib::extend<NamedTestFlow>(*a)>("a");
238-
239-
CHECK(log_buffer.find("flow.action(a)") != std::string::npos);
240-
}
241-
242-
TEST_CASE("named flow logs milestones", "[flow]") {
243-
check_flow<NamedTestFlow, cib::exports<NamedTestFlow>,
244-
cib::extend<NamedTestFlow>(*"ms"_milestone)>("");
245-
246-
CHECK(log_buffer.find("flow.milestone(ms)") != std::string::npos);
247-
}
248-
249-
#endif

test/flow/logging.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#include <cib/cib.hpp>
2+
#include <flow/flow.hpp>
3+
#include <log/fmt/logger.hpp>
4+
5+
#include <catch2/catch_test_macros.hpp>
6+
7+
#include <iterator>
8+
#include <string>
9+
10+
namespace {
11+
using namespace flow::literals;
12+
13+
std::string log_buffer{};
14+
15+
template <auto... Cs> struct wrapper {
16+
struct inner {
17+
constexpr static auto config = cib::config(Cs...);
18+
};
19+
constexpr static auto n = cib::nexus<inner>{};
20+
21+
wrapper() { n.init(); }
22+
23+
template <typename S> static auto run() -> void { n.template service<S>(); }
24+
};
25+
26+
template <typename S, auto... Cs>
27+
constexpr auto run_flow = [] {
28+
log_buffer.clear();
29+
wrapper<Cs...>::template run<S>();
30+
};
31+
32+
struct TestFlowAlpha : public flow::service<> {};
33+
struct NamedTestFlow : public flow::service<"TestFlow"> {};
34+
35+
constexpr auto a = flow::action<"a">([] {});
36+
} // namespace
37+
38+
template <>
39+
inline auto logging::config<> =
40+
logging::fmt::config{std::back_inserter(log_buffer)};
41+
42+
TEST_CASE("unnamed flow does not log start/end", "[flow_logging]") {
43+
run_flow<TestFlowAlpha, cib::exports<TestFlowAlpha>>();
44+
45+
CHECK(std::empty(log_buffer));
46+
}
47+
48+
TEST_CASE("empty flow logs start/end", "[flow_logging]") {
49+
run_flow<NamedTestFlow, cib::exports<NamedTestFlow>>();
50+
51+
CHECK(log_buffer.find("flow.start(TestFlow)") != std::string::npos);
52+
CHECK(log_buffer.find("flow.end(TestFlow)") != std::string::npos);
53+
}
54+
55+
TEST_CASE("unnamed flow does not log actions", "[flow_logging]") {
56+
run_flow<TestFlowAlpha, cib::exports<TestFlowAlpha>,
57+
cib::extend<TestFlowAlpha>(*a)>();
58+
59+
CHECK(log_buffer.find("flow.action(a)") == std::string::npos);
60+
}
61+
62+
TEST_CASE("named flow logs actions", "[flow_logging]") {
63+
run_flow<NamedTestFlow, cib::exports<NamedTestFlow>,
64+
cib::extend<NamedTestFlow>(*a)>();
65+
66+
CHECK(log_buffer.find("flow.action(a)") != std::string::npos);
67+
}
68+
69+
TEST_CASE("named flow logs milestones", "[flow_logging]") {
70+
run_flow<NamedTestFlow, cib::exports<NamedTestFlow>,
71+
cib::extend<NamedTestFlow>(*"ms"_milestone)>();
72+
73+
CHECK(log_buffer.find("flow.milestone(ms)") != std::string::npos);
74+
}

test/flow/separate_actions.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#include <cib/cib.hpp>
2+
#include <flow/flow.hpp>
3+
4+
#include <catch2/catch_test_macros.hpp>
5+
6+
#include <string>
7+
#include <string_view>
8+
9+
std::string actual = {};
10+
11+
namespace {
12+
using namespace flow::literals;
13+
14+
struct TestFlowAlpha : public flow::service<> {};
15+
16+
template <auto... Cs> struct wrapper {
17+
struct inner {
18+
constexpr static auto config = cib::config(Cs...);
19+
};
20+
constexpr static auto n = cib::nexus<inner>{};
21+
22+
wrapper() { n.init(); }
23+
24+
template <typename S> static auto run() -> void { n.template service<S>(); }
25+
};
26+
27+
template <typename S, auto... Cs>
28+
constexpr auto check_flow = [](std::string_view expected) -> void {
29+
actual.clear();
30+
wrapper<Cs...>::template run<S>();
31+
CHECK(actual == expected);
32+
};
33+
} // namespace
34+
35+
TEST_CASE("add actions using func_decl through cib::nexus",
36+
"[flow_separate_actions]") {
37+
check_flow<TestFlowAlpha, cib::exports<TestFlowAlpha>,
38+
cib::extend<TestFlowAlpha>(*"e"_action >> *"f"_action)>("ef");
39+
}

0 commit comments

Comments
 (0)