Compare commits

...

4 commits

Author SHA1 Message Date
d9229ad912 build: test executable target not having private include dirs of target lib
Some checks reported errors
continuous-integration/drone/push Build was killed
2025-07-25 15:07:43 +03:30
6a814bd177 style: minor fixes 2025-07-25 15:07:13 +03:30
2d019878a5 tests: add missing test cases for test/expects 2025-07-25 15:06:44 +03:30
b0ad9ff964 feat(test): expect_unreachable
feat(test): expect_throw
2025-07-25 15:06:14 +03:30
7 changed files with 235 additions and 38 deletions

View file

@ -12,7 +12,6 @@ struct FailedAssertion: std::exception
}
};
template<typename Expression_T, typename... Args>
constexpr void ensure(Expression_T &&expression, std::format_string<Args...> fmt, Args &&...args)
{

View file

@ -1,36 +1,199 @@
#include <test/test.hpp>
lt::test::Suite meta = []() {
using lt::test::expect_eq;
using lt::test::Case;
using lt::test::Suite;
Suite expects = []() {
using lt::test::expect_unreachable;
using lt::test::expect_true;
using lt::test::expect_false;
using lt::test::expect_eq;
using lt::test::expect_ne;
using lt::test::expect_le;
using lt::test::expect_throw;
lt::test::Case { "test_1" } = [] {
Case { "" } = [] {
};
Case { "expect_unreachable" } = [] {
auto unhappy = false;
// clang-format off
try { expect_unreachable(); }
catch (const std::exception &exp) { unhappy = true; }
// clang-format on
if (!unhappy)
{
throw std::runtime_error { "expect_unreachable" };
}
};
Case { "expect_true - happy" } = [] {
auto oongaboonga = int {};
auto *oongaboonga_ptr_here = &oongaboonga;
expect_true(oongaboonga_ptr_here);
expect_true(true);
expect_true(1); // NOLINT
};
Case { "expect_true - unhappy" } = [] {
auto unhappy_counter = 0u;
auto *where_oongaboonga_ptr = (int *)nullptr;
// clang-format off
try { expect_true(where_oongaboonga_ptr); }
catch (const std::exception& exp) { ++unhappy_counter; }
try { expect_true(!true); }
catch (const std::exception& exp) { ++unhappy_counter; }
try { expect_true(false); }
catch (const std::exception& exp) { ++unhappy_counter; }
try { expect_true(0); } // NOLINT
catch (const std::exception& exp) { ++unhappy_counter; }
// clang-format on
};
Case { "expect_false - happy" } = [] {
auto *oongaboonga_is_slacking = (int *)nullptr;
expect_false(oongaboonga_is_slacking);
expect_false(false);
expect_false(0); // NOLINT
};
Case { "expect_false - unhappy" } = [] {
auto oongaboonga = int {};
auto *oonga_oonga_can_rest_now = (int *)nullptr;
auto unhappy_counter = 0u;
// clang-format off
try { expect_false(oonga_oonga_can_rest_now); }
catch (const std::exception& exp) { ++unhappy_counter; }
try { expect_false(true); }
catch (const std::exception& exp) { ++unhappy_counter; }
try { expect_false(!false); }
catch (const std::exception& exp) { ++unhappy_counter; }
try { expect_false(1); } // NOLINT
catch (const std::exception& exp) { ++unhappy_counter; }
// clang-format on
};
Case { "expect_true - unhappy" } = [] {
auto unhappy_counter = 0u;
auto *where_oongaboonga_ptr = (int *)nullptr;
// clang-format off
try { expect_true(where_oongaboonga_ptr); }
catch (const std::exception& exp) { ++unhappy_counter; }
try { expect_true(!true); }
catch (const std::exception& exp) { ++unhappy_counter; }
try { expect_true(false); }
catch (const std::exception& exp) { ++unhappy_counter; }
try { expect_true(0); } // NOLINT
catch (const std::exception& exp) { ++unhappy_counter; }
// clang-format on
};
Case { "expect_eq - happy" } = [] {
expect_eq(5, 5);
};
lt::test::Case { "test_2" } = [] {
expect_eq(20.0, 20.0);
};
lt::test::Case { "test_3" } = [] {
auto exception_thrown = false;
try
{
expect_eq(true, false);
}
catch (const std::exception &exp)
{
exception_thrown = true;
}
expect_true(exception_thrown);
};
lt::test::Case { "test_4" } = [] {
expect_eq(true, 1);
};
lt::test::Case { "test_5" } = [] {
Case { "expect_eq - unhappy" } = [] {
auto unhappy = false;
// clang-format off
try { expect_eq(true, false); }
catch (const std::exception &exp) { unhappy = true; }
// clang-format on
if (!unhappy)
{
throw std::runtime_error { "expect_eq unhappy" };
}
};
Case { "expect_ne - happy " } = [] {
expect_ne(5, 5.0000001);
expect_ne(20.0, 69.0);
expect_ne(true, 0);
};
Case { "expect_ne - unhappy" } = [] {
auto unhappy_counter = 0u;
// clang-format off
try { expect_ne(5, 5); }
catch (const std::exception &exp) { ++unhappy_counter; }
try { expect_ne(20.0, 20.0); }
catch (const std::exception &exp) { ++unhappy_counter; }
try { expect_ne(true, 1); }
catch (const std::exception &exp) { ++unhappy_counter; }
// clang-format on
if (unhappy_counter != 3)
{
throw std::runtime_error { "expect_ne unhappy" };
}
};
Case { "expect_throw - happy" } = [] {
expect_throw([] { throw std::runtime_error { "nonsense" }; });
};
Case { "expect_throw - unhappy" } = [] {
auto unhappy = false;
// clang-format off
try { expect_throw([] {}); }
catch (const std::exception &exp) { unhappy = true; }
// clang-format on
if (!unhappy)
{
throw std::runtime_error { "expect_throw - unhappy" };
}
};
Case { "expect_le - happy" } = [] {
expect_le(69, 420);
expect_le(19.694206942069420, 20.0);
expect_le(false, 1);
};
Case { "expect_le - unhappy" } = [] {
auto unhappy_counter = 0u;
// clang-format off
try { expect_le(20020619 + 23, 20020619 ); }
catch (const std::exception &exp) { ++unhappy_counter; }
try { expect_le(420, 69); }
catch (const std::exception &exp) { ++unhappy_counter; }
try { expect_le(20.0, 19.694206942069420); }
catch (const std::exception &exp) { ++unhappy_counter; }
try { expect_le(1, false); }
catch (const std::exception &exp) { ++unhappy_counter; }
// clang-format on
if (unhappy_counter != 4)
{
throw std::runtime_error { "expect_le - unhappy" };
}
};
};

View file

@ -14,6 +14,44 @@ concept Printable = requires(std::ostream &os, T t) {
template<typename T>
concept Testable = Printable<T> && std::equality_comparable<T>;
constexpr void expect_unreachable(
std::source_location source_location = std::source_location::current()
)
{
throw std::runtime_error {
std::format(
"Failed unreachable expectation:\n"
"\tlocation: {}:{}",
source_location.file_name(),
source_location.line()
),
};
};
constexpr void expect_throw(
std::invocable auto invocable,
std::source_location source_location = std::source_location::current()
)
{
try
{
invocable();
}
catch (const std::exception &exp)
{
return;
}
throw std::runtime_error {
std::format(
"Failed throwing expectation:\n"
"\tlocation: {}:{}",
source_location.file_name(),
source_location.line()
),
};
}
constexpr void expect_eq(
Testable auto lhs,
Testable auto rhs,

View file

@ -12,23 +12,18 @@ concept printable = requires(std::ostream &os, T t) {
{ os << t } -> std::same_as<std::ostream &>;
};
template<
class T,
auto expr =
[] {
}>
// clang-format off
template<class T, auto expr = []{}>
concept test = requires(T test) {
{ test.name } -> printable;
{ test = expr } -> std::same_as<void>;
};
// clang-format on
} // namespace concepts
namespace details {
class Registry
{
public:

View file

@ -23,7 +23,7 @@ lt::test::Suite raii = [] {
};
lt::test::Case { "plenty" } = [] {
for (auto i : std::views::iota(0, 100'001))
for (auto idx : std::views::iota(0, 100'001))
{
Timer {};
}

View file

@ -6,7 +6,6 @@ namespace lt {
class Event;
class Window
{
public:

View file

@ -101,13 +101,16 @@ function (add_test_module target_lib_name)
file(MAKE_DIRECTORY "${PRIVATE_INCLUDE_DIR}")
file(CREATE_LINK
"${CMAKE_CURRENT_SOURCE_DIR}/private/"
"${PRIVATE_INCLUDE_DIR}${target_lib_name}"
"${PRIVATE_INCLUDE_DIR}/${target_lib_name}"
SYMBOLIC
)
add_executable(${target_lib_name}_tests ${source_files})
target_link_libraries(${target_lib_name}_tests PRIVATE ${target_lib_name} base test)
target_include_directories(${target_lib_name}_tests
PRIVATE ${PUBLIC_INCLUDE_DIR}
PRIVATE ${PRIVATE_INCLUDE_DIR}
)
endfunction ()
function (add_option option help)