Skip to content

Commit c52ff55

Browse files
committed
use unforgettable reporter registration
1 parent ee630dc commit c52ff55

File tree

8 files changed

+73
-53
lines changed

8 files changed

+73
-53
lines changed

CMakeLists.txt

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,10 @@ add_library(rsltest SHARED)
99

1010
set_target_properties(rsltest PROPERTIES OUTPUT_NAME rsltest)
1111
target_compile_options(rsltest PUBLIC
12-
"-stdlib=libc++"
13-
"-freflection"
14-
"-fannotation-attributes"
15-
"-fparameter-reflection"
16-
"-fexpansion-statements"
17-
# "-Wno-c++26-extensions"
12+
"-freflection-latest"
1813
# "-ftime-trace"
1914
# "-fconstexpr-steps=10000000" # required to scan the global namespace
2015
)
21-
target_link_options(rsltest PUBLIC "-stdlib=libc++" "-lc++abi")
2216
target_include_directories(rsltest PUBLIC
2317
$<INSTALL_INTERFACE:include>
2418
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>)
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#pragma once
2+
#include <memory>
3+
#include <string>
4+
#include <string_view>
5+
#include <meta>
6+
#include <unordered_map>
7+
8+
#include "../annotations.hpp"
9+
10+
namespace rsl::testing::_impl {
11+
template <class Base, class... Args>
12+
class Factory {
13+
public:
14+
template <class... T>
15+
static std::unique_ptr<Base> make(const std::string& s, T&&... args) {
16+
return data().at(s)(std::forward<T>(args)...);
17+
}
18+
19+
template <class T>
20+
struct Registrar : Base {
21+
friend T;
22+
23+
static consteval std::string_view get_name() {
24+
auto annotations = annotations_of(^^T, ^^annotations::Rename);
25+
if (annotations.size() == 1) {
26+
auto opt = extract<annotations::Rename>(constant_of(annotations[0]));
27+
return opt.value;
28+
}
29+
return identifier_of(^^T);
30+
}
31+
32+
static bool registerT() {
33+
static constexpr std::string_view name = define_static_string(get_name());
34+
Factory::data()[name] = [](Args... args) -> std::unique_ptr<Base> {
35+
return std::make_unique<T>(std::forward<Args>(args)...);
36+
};
37+
return true;
38+
}
39+
inline static const std::nullptr_t registration = (registerT(), nullptr);
40+
static constexpr std::integral_constant<std::nullptr_t const*, &registration>
41+
registration_helper{};
42+
43+
private:
44+
Registrar() : Base(Key{}) { (void)registration; }
45+
};
46+
47+
friend Base;
48+
49+
private:
50+
class Key {
51+
Key() {};
52+
template <class T>
53+
friend struct Registrar;
54+
};
55+
using FuncType = std::unique_ptr<Base> (*)(Args...);
56+
Factory() = default;
57+
58+
static auto& data() {
59+
static std::unordered_map<std::string_view, FuncType> s;
60+
return s;
61+
}
62+
};
63+
} // namespace rsl::testing::_impl

include/rsl/testing/output.hpp

Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ struct Output {
1818
}
1919
};
2020

21-
struct Reporter {
21+
struct Reporter : _impl::Factory<Reporter> {
22+
explicit Reporter(Key) {}
23+
2224
virtual ~Reporter() = default;
2325
virtual void before_run(TestNamespace const& tests) {}
2426
virtual void after_run(std::span<TestResult> results) {}
@@ -36,31 +38,4 @@ struct Reporter {
3638

3739
virtual void finalize(Output& output) {}
3840
};
39-
40-
namespace _reporter_impl {
41-
consteval std::string_view get_name(std::meta::info R) {
42-
auto annotations = annotations_of(R, ^^annotations::Rename);
43-
if (annotations.size() == 1) {
44-
auto opt = extract<annotations::Rename>(constant_of(annotations[0]));
45-
return opt.value;
46-
}
47-
return identifier_of(R);
48-
}
49-
} // namespace _reporter_impl
50-
51-
using ReporterDef = std::unique_ptr<Reporter> (*)();
52-
std::unordered_map<std::string_view, ReporterDef>& reporter_registry();
53-
54-
template <typename T>
55-
bool register_reporter() {
56-
reporter_registry()[_reporter_impl::get_name(^^T)] =
57-
+[] -> std::unique_ptr<Reporter> { return std::make_unique<T>(); };
58-
return true;
59-
}
60-
} // namespace rsl::testing
61-
62-
#define REGISTER_REPORTER(classname) \
63-
namespace { \
64-
[[maybe_unused]] static bool const _reporter_registered = \
65-
rsl::testing::register_reporter<classname>(); \
66-
}
41+
} // namespace rsl::testing

src/discovery.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,4 @@ std::set<TestDef>& _testing_impl::registry() {
77
static std::set<TestDef> data;
88
return data;
99
}
10-
11-
std::unordered_map<std::string_view, ReporterDef>& reporter_registry() {
12-
static std::unordered_map<std::string_view, ReporterDef> data;
13-
return data;
14-
}
15-
1610
} // namespace rsl::testing

src/main.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,9 @@ class[[= rsl::cli::description("rsl::test (in Catch2 v3.8.1 compatibility mode)"
101101
void run() {
102102
std::unique_ptr<rsl::testing::Reporter> selected_reporter;
103103
if (reporter.empty()) {
104-
selected_reporter = rsl::testing::reporter_registry().at("plain")();
104+
selected_reporter = rsl::testing::Reporter::make("plain");
105105
} else {
106-
selected_reporter = rsl::testing::reporter_registry().at(reporter)();
106+
selected_reporter = rsl::testing::Reporter::make(reporter);
107107
}
108108

109109
if (list_tests) {

src/reporters/catch2xml.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ struct MatchingTests {
111111
[[=xml::node]] std::vector<MatchingTests::TestCase> tests;
112112
};
113113

114-
class[[= annotations::rename("xml")]] Catch2XmlReporter : public Reporter {
114+
class[[= annotations::rename("xml")]] Catch2XmlReporter : public Reporter::Registrar<Catch2XmlReporter> {
115115
Catch2TestRun report;
116116

117117
public:
@@ -178,6 +178,4 @@ class[[= annotations::rename("xml")]] Catch2XmlReporter : public Reporter {
178178
}
179179
}
180180
};
181-
182-
REGISTER_REPORTER(Catch2XmlReporter);
183181
} // namespace rsl::testing::_xml_impl

src/reporters/terminal.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#include <libassert/assert.hpp>
66

77
namespace rsl::testing::_impl {
8-
class [[=annotations::rename("plain")]] ConsoleReporter : public Reporter {
8+
class [[=annotations::rename("plain")]] ConsoleReporter : public Reporter::Registrar<ConsoleReporter> {
99
public:
1010
void before_run(TestNamespace const& tests) override { std::print("Running {} tests...\n", tests.count()); }
1111
void before_test(Test::TestRun const& test) override { std::print("[ RUN ] {}\n", test.name); }
@@ -38,6 +38,4 @@ class [[=annotations::rename("plain")]] ConsoleReporter : public Reporter {
3838
// return libassert::isatty(libassert::stderr_fileno);
3939
// }
4040
};
41-
42-
REGISTER_REPORTER(ConsoleReporter);
4341
} // namespace rsl::_impl

src/reporters/xml.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ struct testsuite {
1616
std::vector<testcase> tests;
1717
};
1818

19-
class [[=annotations::rename("junit")]] JUnitXmlReporter : public Reporter {
19+
class [[=annotations::rename("junit")]] JUnitXmlReporter : public Reporter::Registrar<JUnitXmlReporter> {
2020
testsuite suite;
2121
public:
2222
void before_run(TestNamespace const&) override {}
@@ -35,6 +35,4 @@ class [[=annotations::rename("junit")]] JUnitXmlReporter : public Reporter {
3535

3636
void finalize(Output& target) override { target.print(rsl::to_xml(suite)); }
3737
};
38-
39-
REGISTER_REPORTER(JUnitXmlReporter);
4038
} // namespace rsl::testing::_impl

0 commit comments

Comments
 (0)