Skip to content

Commit

Permalink
Do not hard-code std::tuple for #25
Browse files Browse the repository at this point in the history
  • Loading branch information
cschreib committed Nov 29, 2022
1 parent 457d66e commit c223246
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 84 deletions.
36 changes: 26 additions & 10 deletions include/snatch/snatch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include <initializer_list> // for std::initializer_list
#include <optional> // for cli
#include <string_view> // for all strings
#include <tuple> // for typed tests
#include <type_traits> // for std::is_nothrow_*
#include <variant> // for events

Expand Down Expand Up @@ -102,6 +101,9 @@ namespace snatch {
template<typename T>
constexpr std::string_view type_name = impl::get_type_name<T>();

template<typename... Args>
struct type_list {};

[[noreturn]] void terminate_with(std::string_view msg) noexcept;
} // namespace snatch

Expand Down Expand Up @@ -715,11 +717,8 @@ class small_function<Ret(Args...) noexcept> {
// -----------------------

namespace snatch::impl {
template<typename T>
struct proxy;

template<typename... Args>
struct proxy<std::tuple<Args...>> {
struct proxy {
registry* tests = nullptr;
std::string_view name;
std::string_view tags;
Expand All @@ -728,6 +727,17 @@ struct proxy<std::tuple<Args...>> {
const char* operator=(const F& func) noexcept;
};

template<typename T>
struct proxy_from_list_t;

template<template<typename...> typename T, typename... Args>
struct proxy_from_list_t<T<Args...>> {
using type = proxy<Args...>;
};

template<typename T>
using proxy_from_list = typename proxy_from_list_t<T>::type;

struct test_run;

using test_ptr = void (*)(test_run&);
Expand Down Expand Up @@ -1113,12 +1123,18 @@ class registry {
this->print_callback(message);
}

impl::proxy<std::tuple<>> add(std::string_view name, std::string_view tags) noexcept {
impl::proxy<> add(std::string_view name, std::string_view tags) noexcept {
return {this, name, tags};
}

template<typename... Args>
impl::proxy<Args...> add_with_types(std::string_view name, std::string_view tags) noexcept {
return {this, name, tags};
}

template<typename T>
impl::proxy<T> add_with_types(std::string_view name, std::string_view tags) noexcept {
impl::proxy_from_list<T>
add_with_type_list(std::string_view name, std::string_view tags) noexcept {
return {this, name, tags};
}

Expand Down Expand Up @@ -1182,7 +1198,7 @@ extern constinit registry tests;
namespace snatch::impl {
template<typename... Args>
template<typename F>
const char* proxy<std::tuple<Args...>>::operator=(const F& func) noexcept {
const char* proxy<Args...>::operator=(const F& func) noexcept {
if constexpr (sizeof...(Args) > 0) {
tests->template register_typed_tests<Args...>(name, tags, func);
} else {
Expand Down Expand Up @@ -1330,12 +1346,12 @@ bool operator==(const M& m, const T& value) noexcept {

#define SNATCH_TEMPLATE_LIST_TEST_CASE(NAME, TAGS, TYPES) \
static const char* SNATCH_MACRO_CONCAT(test_id_, __COUNTER__) [[maybe_unused]] = \
snatch::tests.add_with_types<TYPES>(NAME, TAGS) = []<typename TestType>( \
snatch::tests.add_with_type_list<TYPES>(NAME, TAGS) = []<typename TestType>( \
snatch::impl::test_run & SNATCH_CURRENT_TEST [[maybe_unused]]) -> void

#define SNATCH_TEMPLATE_TEST_CASE(NAME, TAGS, ...) \
static const char* SNATCH_MACRO_CONCAT(test_id_, __COUNTER__) [[maybe_unused]] = \
snatch::tests.add_with_types<std::tuple<__VA_ARGS__>>(NAME, TAGS) = []<typename TestType>( \
snatch::tests.add_with_types<__VA_ARGS__>(NAME, TAGS) = []<typename TestType>( \
snatch::impl::test_run & SNATCH_CURRENT_TEST [[maybe_unused]]) -> void

#define SNATCH_SECTION1(NAME) \
Expand Down
161 changes: 89 additions & 72 deletions tests/runtime_tests/registry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,85 +54,102 @@ TEST_CASE("add regular test", "[registry]") {
};

TEST_CASE("add template test", "[registry]") {
mock_framework framework;

test_called = false;
test_called_int = false;
test_called_float = false;

framework.registry.add_with_types<std::tuple<int, float>>("how many lights", "[tag]") =
[]<typename T>(snatch::impl::test_run&) {
if constexpr (std::is_same_v<T, int>) {
test_called_int = true;
} else if constexpr (std::is_same_v<T, float>) {
test_called_float = true;
} else {
test_called = true;
}
};

REQUIRE(framework.get_num_registered_tests() == 2u);

auto& test1 = *framework.registry.begin();
CHECK(test1.id.name == "how many lights"sv);
CHECK(test1.id.tags == "[tag]"sv);
CHECK(test1.id.type == "int"sv);
REQUIRE(test1.func != nullptr);
for (bool with_type_list : {false, true}) {
mock_framework framework;

test_called = false;
test_called_int = false;
test_called_float = false;

CAPTURE(with_type_list);

if (with_type_list) {
framework.registry.add_with_type_list<snatch::type_list<int, float>>(
"how many lights", "[tag]") = []<typename T>(snatch::impl::test_run&) {
if constexpr (std::is_same_v<T, int>) {
test_called_int = true;
} else if constexpr (std::is_same_v<T, float>) {
test_called_float = true;
} else {
test_called = true;
}
};
} else {
framework.registry.add_with_types<int, float>("how many lights", "[tag]") =
[]<typename T>(snatch::impl::test_run&) {
if constexpr (std::is_same_v<T, int>) {
test_called_int = true;
} else if constexpr (std::is_same_v<T, float>) {
test_called_float = true;
} else {
test_called = true;
}
};
}

auto& test2 = *(framework.registry.begin() + 1);
CHECK(test2.id.name == "how many lights"sv);
CHECK(test2.id.tags == "[tag]"sv);
CHECK(test2.id.type == "float"sv);
REQUIRE(test2.func != nullptr);
REQUIRE(framework.get_num_registered_tests() == 2u);

SECTION("run int default reporter") {
framework.setup_print();
framework.registry.run(test1);
auto& test1 = *framework.registry.begin();
CHECK(test1.id.name == "how many lights"sv);
CHECK(test1.id.tags == "[tag]"sv);
CHECK(test1.id.type == "int"sv);
REQUIRE(test1.func != nullptr);

CHECK(test_called == false);
CHECK(test_called_int == true);
CHECK(test_called_float == false);
CHECK(framework.messages == contains_substring("starting: how many lights [int]"));
CHECK(framework.messages == contains_substring("finished: how many lights [int]"));
}
auto& test2 = *(framework.registry.begin() + 1);
CHECK(test2.id.name == "how many lights"sv);
CHECK(test2.id.tags == "[tag]"sv);
CHECK(test2.id.type == "float"sv);
REQUIRE(test2.func != nullptr);

SECTION("run float default reporter") {
framework.setup_print();
framework.registry.run(test2);
SECTION("run int default reporter") {
framework.setup_print();
framework.registry.run(test1);

CHECK(test_called == false);
CHECK(test_called_int == false);
CHECK(test_called_float == true);
CHECK(framework.messages == contains_substring("starting: how many lights [float]"));
CHECK(framework.messages == contains_substring("finished: how many lights [float]"));
}
CHECK(test_called == false);
CHECK(test_called_int == true);
CHECK(test_called_float == false);
CHECK(framework.messages == contains_substring("starting: how many lights [int]"));
CHECK(framework.messages == contains_substring("finished: how many lights [int]"));
}

SECTION("run int custom reporter") {
framework.setup_reporter();
framework.registry.run(test1);
SECTION("run float default reporter") {
framework.setup_print();
framework.registry.run(test2);

CHECK(test_called == false);
CHECK(test_called_int == true);
CHECK(test_called_float == false);
REQUIRE(framework.events.size() == 2u);
CHECK(framework.events[0].event_type == event_deep_copy::type::test_case_started);
CHECK(framework.events[1].event_type == event_deep_copy::type::test_case_ended);
CHECK_EVENT_TEST_ID(framework.events[0], test1.id);
CHECK_EVENT_TEST_ID(framework.events[1], test1.id);
}
CHECK(test_called == false);
CHECK(test_called_int == false);
CHECK(test_called_float == true);
CHECK(framework.messages == contains_substring("starting: how many lights [float]"));
CHECK(framework.messages == contains_substring("finished: how many lights [float]"));
}

SECTION("run float custom reporter") {
framework.setup_reporter();
framework.registry.run(test2);
SECTION("run int custom reporter") {
framework.setup_reporter();
framework.registry.run(test1);

CHECK(test_called == false);
CHECK(test_called_int == true);
CHECK(test_called_float == false);
REQUIRE(framework.events.size() == 2u);
CHECK(framework.events[0].event_type == event_deep_copy::type::test_case_started);
CHECK(framework.events[1].event_type == event_deep_copy::type::test_case_ended);
CHECK_EVENT_TEST_ID(framework.events[0], test1.id);
CHECK_EVENT_TEST_ID(framework.events[1], test1.id);
}

CHECK(test_called == false);
CHECK(test_called_int == false);
CHECK(test_called_float == true);
REQUIRE(framework.events.size() == 2u);
CHECK(framework.events[0].event_type == event_deep_copy::type::test_case_started);
CHECK(framework.events[1].event_type == event_deep_copy::type::test_case_ended);
CHECK_EVENT_TEST_ID(framework.events[0], test2.id);
CHECK_EVENT_TEST_ID(framework.events[1], test2.id);
SECTION("run float custom reporter") {
framework.setup_reporter();
framework.registry.run(test2);

CHECK(test_called == false);
CHECK(test_called_int == false);
CHECK(test_called_float == true);
REQUIRE(framework.events.size() == 2u);
CHECK(framework.events[0].event_type == event_deep_copy::type::test_case_started);
CHECK(framework.events[1].event_type == event_deep_copy::type::test_case_ended);
CHECK_EVENT_TEST_ID(framework.events[0], test2.id);
CHECK_EVENT_TEST_ID(framework.events[1], test2.id);
}
}
};

Expand Down Expand Up @@ -179,7 +196,7 @@ TEST_CASE("report FAIL template", "[registry]") {
mock_framework framework;

#define SNATCH_CURRENT_TEST mock_test
framework.registry.add_with_types<std::tuple<int>>("how many lights", "[tag]") =
framework.registry.add_with_types<int>("how many lights", "[tag]") =
[]<typename TestType>(snatch::impl::test_run& mock_test) {
// clang-format off
failure_line = __LINE__; SNATCH_FAIL("there are four lights");
Expand Down Expand Up @@ -414,7 +431,7 @@ void register_tests(mock_framework& framework) {
SNATCH_SKIP("not thirsty");
};

framework.registry.add_with_types<std::tuple<int, float>>(
framework.registry.add_with_types<int, float>(
"how many templated lights",
"[tag][tag with spaces]") = []<typename T>(snatch::impl::test_run& mock_test) {
if constexpr (std::is_same_v<T, int>) {
Expand Down
5 changes: 3 additions & 2 deletions tests/runtime_tests/small_function.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "testing.hpp"

#include <tuple>

std::size_t test_object_instances = 0u;
bool function_called = false;
int return_value = 0u;
Expand Down Expand Up @@ -165,6 +167,5 @@ TEMPLATE_TEST_CASE(
}
CHECK(test_object_instances <= expected_instances);
}
}
(type_holder<TestType>{});
}(type_holder<TestType>{});
};

0 comments on commit c223246

Please sign in to comment.