Skip to content

Commit add06dc

Browse files
committed
Removed global state for reporters
1 parent f8a5ec1 commit add06dc

11 files changed

+70
-48
lines changed

CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ set(SNITCH_MAX_UNIQUE_TAGS 1024 CACHE STRING "Maximum number of unique
1515
set(SNITCH_MAX_COMMAND_LINE_ARGS 1024 CACHE STRING "Maximum number of command line arguments to a test application.")
1616
set(SNITCH_MAX_REGISTERED_REPORTERS 8 CACHE STRING "Maximum number of registered reporter that can be selected from the command line.")
1717
set(SNITCH_MAX_PATH_LENGTH 1024 CACHE STRING "Maximum length of a file path when writing output to file.")
18+
set(SNITCH_MAX_REPORTER_SIZE_BYTES 128 CACHE STRING "Maximum size (in bytes) of a reporter object.")
1819

1920
# Feature toggles.
2021
set(SNITCH_DEFINE_MAIN ON CACHE BOOL "Define main() in snitch -- disable to provide your own main() function.")
@@ -221,6 +222,7 @@ if (SNITCH_DO_TEST)
221222
SNITCH_MAX_MESSAGE_LENGTH=129
222223
SNITCH_MAX_TEST_NAME_LENGTH=130
223224
SNITCH_MAX_CAPTURE_LENGTH=131
225+
SNITCH_MAX_REPORTER_SIZE_BYTES=16
224226
SNITCH_DEFINE_MAIN=0)
225227
endfunction()
226228

include/snitch/snitch_config.hpp.config

+3
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@
4747
#if !defined(SNITCH_MAX_PATH_LENGTH)
4848
# define SNITCH_MAX_PATH_LENGTH ${SNITCH_MAX_PATH_LENGTH}
4949
#endif
50+
#if !defined(SNITCH_MAX_REPORTER_SIZE_BYTES)
51+
# define SNITCH_MAX_REPORTER_SIZE_BYTES ${SNITCH_MAX_REPORTER_SIZE_BYTES}
52+
#endif
5053
#if !defined(SNITCH_DEFINE_MAIN)
5154
#cmakedefine01 SNITCH_DEFINE_MAIN
5255
#endif

include/snitch/snitch_macros_reporter.hpp

+3-25
Original file line numberDiff line numberDiff line change
@@ -9,31 +9,9 @@
99
static const std::string_view SNITCH_MACRO_CONCAT(reporter_id_, __COUNTER__) \
1010
[[maybe_unused]] = snitch::tests.add_reporter(NAME, __VA_ARGS__)
1111

12-
#define SNITCH_REGISTER_REPORTER_IMPL(NAME, TYPE, COUNTER) \
13-
static std::optional<TYPE> SNITCH_MACRO_CONCAT(reporter_, COUNTER); \
14-
static void SNITCH_MACRO_CONCAT(reporter_init_, COUNTER)(snitch::registry & r) noexcept { \
15-
SNITCH_MACRO_CONCAT(reporter_, COUNTER).emplace(r); \
16-
} \
17-
template<typename T> \
18-
static bool SNITCH_MACRO_CONCAT(reporter_config_, COUNTER)( \
19-
snitch::registry & r, std::string_view k, std::string_view v) noexcept { \
20-
return SNITCH_MACRO_CONCAT(reporter_, COUNTER)->configure(r, k, v); \
21-
} \
22-
static void SNITCH_MACRO_CONCAT(reporter_report_, COUNTER)( \
23-
const snitch::registry& r, const snitch::event::data& e) noexcept { \
24-
SNITCH_MACRO_CONCAT(reporter_, COUNTER)->report(r, e); \
25-
} \
26-
static void SNITCH_MACRO_CONCAT(reporter_finish_, COUNTER)(snitch::registry&) noexcept { \
27-
SNITCH_MACRO_CONCAT(reporter_, COUNTER).reset(); \
28-
} \
29-
static const std::string_view SNITCH_MACRO_CONCAT(reporter_id_, COUNTER) [[maybe_unused]] = \
30-
snitch::tests.add_reporter( \
31-
NAME, &SNITCH_MACRO_CONCAT(reporter_init_, COUNTER), \
32-
&SNITCH_MACRO_CONCAT(reporter_config_, COUNTER) < TYPE >, \
33-
&SNITCH_MACRO_CONCAT(reporter_report_, COUNTER), \
34-
&SNITCH_MACRO_CONCAT(reporter_finish_, COUNTER))
35-
36-
#define SNITCH_REGISTER_REPORTER(NAME, TYPE) SNITCH_REGISTER_REPORTER_IMPL(NAME, TYPE, __COUNTER__)
12+
#define SNITCH_REGISTER_REPORTER(NAME, TYPE) \
13+
static const std::string_view SNITCH_MACRO_CONCAT(reporter_id_, __COUNTER__) \
14+
[[maybe_unused]] = snitch::tests.add_reporter<TYPE>(NAME)
3715

3816
// clang-format off
3917
#if SNITCH_WITH_SHORTHAND_MACROS

include/snitch/snitch_registry.hpp

+42-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef SNITCH_REGISTRY_HPP
22
#define SNITCH_REGISTRY_HPP
33

4+
#include "snitch/snitch_any.hpp"
45
#include "snitch/snitch_append.hpp"
56
#include "snitch/snitch_cli.hpp"
67
#include "snitch/snitch_config.hpp"
@@ -34,6 +35,8 @@ constexpr std::size_t max_tag_length = SNITCH_MAX_TAG_LENGTH;
3435
constexpr std::size_t max_unique_tags = SNITCH_MAX_UNIQUE_TAGS;
3536
// Maximum number of registered reporters to select from the command line.
3637
constexpr std::size_t max_registered_reporters = SNITCH_MAX_REGISTERED_REPORTERS;
38+
// Maximum size of a reporter instance, in bytes.
39+
constexpr std::size_t max_reporter_size_bytes = SNITCH_MAX_REPORTER_SIZE_BYTES;
3740
} // namespace snitch
3841

3942
namespace snitch::impl {
@@ -102,6 +105,13 @@ struct registered_reporter {
102105
finish_report_function finish = [](registry&) noexcept {};
103106
};
104107

108+
template<typename T>
109+
concept reporter_type =
110+
requires(registry& reg) { T{reg}; } &&
111+
requires(T& rep, registry& reg, std::string_view k, std::string_view v) {
112+
{ rep.configure(reg, k, v) } -> convertible_to<bool>;
113+
} && requires(T& rep, const registry& reg, const event::data& e) { rep.report(reg, e); };
114+
105115
class registry {
106116
// Contains all registered test cases.
107117
small_vector<impl::test_case, max_test_cases> test_list;
@@ -112,8 +122,27 @@ class registry {
112122
// Used when writing output to file.
113123
std::optional<impl::file_writer> file_writer;
114124

115-
// the default console reporter
116-
snitch::reporter::console::reporter console_reporter;
125+
// Type-erased storage for the current reporter instance.
126+
inplace_any<max_reporter_size_bytes> reporter_storage;
127+
128+
template<typename T>
129+
void initialize_reporter(registry&) noexcept {
130+
this->reporter_storage.emplace<T>(*this);
131+
}
132+
133+
template<typename T>
134+
void report(const registry&, const event::data& e) noexcept {
135+
this->reporter_storage.get<T>().report(*this, e);
136+
}
137+
138+
template<typename T>
139+
bool configure_reporter(registry&, std::string_view k, std::string_view v) noexcept {
140+
return this->reporter_storage.get<T>().configure(*this, k, v);
141+
}
142+
143+
SNITCH_EXPORT void destroy_reporter(registry&) noexcept;
144+
145+
SNITCH_EXPORT void report_default(const registry&, const event::data& e) noexcept;
117146

118147
public:
119148
enum class verbosity { quiet, normal, high, full } verbose = verbosity::normal;
@@ -125,9 +154,8 @@ class registry {
125154
using report_function = snitch::report_function;
126155
using finish_report_function = snitch::finish_report_function;
127156

128-
print_function print_callback = &snitch::impl::stdout_print;
129-
report_function report_callback = {
130-
console_reporter, snitch::constant<&snitch::reporter::console::reporter::report>{}};
157+
print_function print_callback = &snitch::impl::stdout_print;
158+
report_function report_callback = {*this, constant<&registry::report_default>{}};
131159
finish_report_function finish_callback = [](registry&) noexcept {};
132160

133161
// Internal API; do not use.
@@ -178,8 +206,15 @@ class registry {
178206
const report_function& report,
179207
const std::optional<finish_report_function>& finish);
180208

181-
// Internal API; do not use.
182-
SNITCH_EXPORT std::string_view add_console_reporter();
209+
// Requires: number of reporters + 1 <= max_registered_reporters.
210+
template<reporter_type T>
211+
std::string_view add_reporter(std::string_view name) {
212+
return this->add_reporter(
213+
name, initialize_report_function{*this, constant<&registry::initialize_reporter<T>>{}},
214+
configure_report_function{*this, constant<&registry::configure_reporter<T>>{}},
215+
report_function{*this, constant<&registry::report<T>>{}},
216+
finish_report_function{*this, constant<&registry::destroy_reporter>{}});
217+
}
183218

184219
// Internal API; do not use.
185220
// Requires: number of tests + 1 <= max_test_cases, well-formed test ID.

include/snitch/snitch_reporter_console.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ struct reporter {
1212

1313
reporter() = default;
1414

15-
SNITCH_EXPORT void init(registry& r) noexcept;
15+
SNITCH_EXPORT explicit reporter(registry& r) noexcept;
1616

1717
SNITCH_EXPORT bool configure(registry&, std::string_view, std::string_view) noexcept;
1818

meson_options.txt

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ option('max_unique_tags' ,type: 'integer' ,value: 1024, description: 'M
1111
option('max_command_line_args' ,type: 'integer' ,value: 1024, description: 'Maximum number of command line arguments to a test application.')
1212
option('max_registered_reporters' ,type: 'integer' ,value: 8 , description: 'Maximum number of registered reporter that can be selected from the command line.')
1313
option('max_path_length' ,type: 'integer' ,value: 1024, description: 'Maximum length of a file path when writing output to file.')
14+
option('max_reporter_size_bytes' ,type: 'integer' ,value: 128, description: 'Maximum size (in bytes) of a reporter object.')
1415

1516
# Feature toggles.
1617
option('define_main' ,type: 'boolean' ,value: true, description: 'Define main() in snitch -- disable to provide your own main() function.')

snitch/meson.build

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ conf_data = configuration_data({
3131
'SNITCH_MAX_COMMAND_LINE_ARGS' : get_option('max_command_line_args'),
3232
'SNITCH_MAX_REGISTERED_REPORTERS' : get_option('max_registered_reporters'),
3333
'SNITCH_MAX_PATH_LENGTH' : get_option('max_path_length'),
34+
'SNITCH_MAX_REPORTER_SIZE_BYTES' : get_option('max_reporter_size_bytes'),
3435

3536
'SNITCH_DEFINE_MAIN' : get_option('define_main').to_int(),
3637
'SNITCH_WITH_EXCEPTIONS' : get_option('with_exceptions').to_int(),

src/snitch_registry.cpp

+12-10
Original file line numberDiff line numberDiff line change
@@ -336,13 +336,18 @@ std::string_view registry::add_reporter(
336336
return name;
337337
}
338338

339-
std::string_view registry::add_console_reporter() {
340-
using reporter_type = snitch::reporter::console::reporter;
341-
return add_reporter("console",
342-
initialize_report_function{console_reporter, snitch::constant<&reporter_type::init>{}},
343-
configure_report_function{console_reporter, snitch::constant<&reporter_type::configure>{}},
344-
{console_reporter, snitch::constant<&snitch::reporter::console::reporter::report>{}},
345-
{});
339+
void registry::destroy_reporter(registry&) noexcept {
340+
reporter_storage.reset();
341+
}
342+
343+
void registry::report_default(const registry&, const event::data& e) noexcept {
344+
using default_reporter = reporter::console::reporter;
345+
346+
if (reporter_storage.type() != type_id<default_reporter>()) {
347+
reporter_storage.emplace<default_reporter>(*this);
348+
}
349+
350+
reporter_storage.get<default_reporter>().report(*this, e);
346351
}
347352

348353
const char*
@@ -1028,6 +1033,3 @@ small_vector_span<const registered_reporter> registry::reporters() const noexcep
10281033

10291034
constinit registry tests;
10301035
} // namespace snitch
1031-
1032-
static const std::string_view console_reporter_id [[maybe_unused]] =
1033-
snitch::tests.add_console_reporter();

src/snitch_reporter_console.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,7 @@ void print_message(const registry& r, const assertion_data& data) {
8686
}
8787
} // namespace
8888

89-
void reporter::init(registry&) noexcept {
90-
counter = 0;
91-
}
89+
reporter::reporter(registry&) noexcept {}
9290

9391
bool reporter::configure(registry& r, std::string_view option, std::string_view value) noexcept {
9492
if (option == "color") {
@@ -205,3 +203,5 @@ void reporter::report(const registry& r, const event::data& event) noexcept {
205203
event);
206204
}
207205
} // namespace snitch::reporter::console
206+
207+
SNITCH_REGISTER_REPORTER("console", snitch::reporter::console::reporter);

tests/approval_tests/reporter_console.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ TEST_CASE("console reporter", "[reporters]") {
1313
mock_framework framework;
1414
register_tests_for_reporters(framework.registry);
1515

16-
framework.registry.add_console_reporter();
16+
framework.registry.add_reporter<snitch::reporter::console::reporter>("console");
1717

1818
framework.registry.with_color = false;
1919

tests/testing_event.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ std::optional<snitch::source_location> get_location(const owning_event::data& e)
229229
}
230230

231231
mock_framework::mock_framework() noexcept {
232-
registry.add_console_reporter();
232+
registry.add_reporter<snitch::reporter::console::reporter>("console");
233233

234234
registry.print_callback = [](std::string_view msg) noexcept {
235235
snitch::cli::console_print(msg);

0 commit comments

Comments
 (0)