Skip to content

Commit

Permalink
Improve unit tests coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
Bronek committed Feb 2, 2025
1 parent 8a40b92 commit 4ef3afd
Show file tree
Hide file tree
Showing 5 changed files with 473 additions and 261 deletions.
21 changes: 12 additions & 9 deletions include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ include(TargetGenerator)
include(CompilationOptions)

# Generate sentinel target for each individual header, as a basic sanity check
foreach(cxxrel 20 23)
foreach(mode 20 23)
foreach(source IN ITEMS ${INCLUDE_PFN_HEADERS})
string(REGEX REPLACE "^(pfn)/(detail|)/?([^\.]+)\.hpp$" "\\1_\\2\\3" root_name ${source})
set(target "sentinel_${root_name}_cxx${cxxrel}")
set(target "sentinel_${root_name}_cxx${mode}")

create_target_for_file(
NAME "${target}"
Expand All @@ -44,8 +44,8 @@ foreach(cxxrel 20 23)
DEPENDENCIES include_pfn
)
append_compilation_options(NAME "${target}" WARNINGS)
add_dependencies("cxx${cxxrel}" "${target}")
set_property(TARGET "${target}" PROPERTY CXX_STANDARD "${cxxrel}")
add_dependencies("cxx${mode}" "${target}")
set_property(TARGET "${target}" PROPERTY CXX_STANDARD "${mode}")

unset(target)
unset(root_name)
Expand Down Expand Up @@ -92,7 +92,10 @@ target_sources(include_fn INTERFACE
TYPE HEADERS
FILES ${INCLUDE_FN_HEADERS})
target_include_directories(include_fn SYSTEM INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_options(include_fn INTERFACE -Wno-missing-braces)

if(NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
target_compile_options(include_fn INTERFACE -Wno-missing-braces)
endif()
# TODO uncomment when include_pfn is ready
# target_link_libraries(include_fn INTERFACE include_pfn)

Expand All @@ -102,10 +105,10 @@ install(TARGETS include_fn

# Generate sentinel target for each individual header, as a basic sanity check
# TODO add 20 when we are compatible with C++20
foreach(cxxrel 23)
foreach(mode 23)
foreach(source IN ITEMS ${INCLUDE_FN_HEADERS})
string(REGEX REPLACE "^(fn)/(detail|)/?([^\.]+)\.hpp$" "\\1_\\2\\3" root_name ${source})
set(target "sentinel_${root_name}_cxx${cxxrel}")
set(target "sentinel_${root_name}_cxx${mode}")

create_target_for_file(
NAME "${target}"
Expand All @@ -115,8 +118,8 @@ foreach(cxxrel 23)
DEPENDENCIES include_fn
)
append_compilation_options(NAME "${target}" WARNINGS)
add_dependencies("cxx${cxxrel}" "${target}")
set_property(TARGET "${target}" PROPERTY CXX_STANDARD "${cxxrel}")
add_dependencies("cxx${mode}" "${target}")
set_property(TARGET "${target}" PROPERTY CXX_STANDARD "${mode}")

unset(target)
unset(root_name)
Expand Down
57 changes: 40 additions & 17 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,35 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Pls keep the filenames sorted
set(TESTS_UTIL_SOURCES
util/static_check.hpp
util/helper_types.hpp
)
add_library(tests_util INTERFACE ${TESTS_UTIL_SOURCES})
set_property(TARGET include_fn PROPERTY CXX_STANDARD 23)
target_include_directories(tests_util INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(tests_util INTERFACE include_fn)

# Generate sentinel target for each individual header, as a basic sanity check
foreach(mode 23)
foreach(source IN ITEMS ${TESTS_UTIL_SOURCES})
string(REGEX REPLACE "^(util)/([^\.]+)\.hpp$" "\\1_\\2" root_name ${source})
set(target "sentinel_${root_name}_cxx${mode}")

create_target_for_file(
NAME "${target}"
SOURCE "${source}"
NEW_SOURCE "#include <${source}>\nint main() {}\n"
SOURCE_ROOT "${CMAKE_BINARY_DIR}/sentinel"
DEPENDENCIES include_fn tests_util
)
append_compilation_options(NAME "${target}" WARNINGS)
add_dependencies("cxx${mode}" "${target}")
set_property(TARGET "${target}" PROPERTY CXX_STANDARD "${mode}")

unset(target)
unset(root_name)
endforeach()
endforeach()

### tests/pfn

set(TESTS_PFN_SOURCES
Expand All @@ -23,26 +46,26 @@ include(TargetGenerator)
include(CompilationOptions)

# Generate separate target for each individual test source
foreach(cxxrel 20 23)
foreach(mode 20 23)
foreach(source IN ITEMS ${TESTS_PFN_SOURCES})
string(REGEX REPLACE "^(pfn)/(detail|)/?([^\.]+)\.cpp$" "\\1_\\2\\3" root_name ${source})
set(target "tests_${root_name}_cxx${cxxrel}")
set(target "tests_${root_name}_cxx${mode}")

create_target_for_file(
NAME "${target}"
SOURCE "${source}"
DEPENDENCIES include_pfn Catch2::Catch2WithMain
DEPENDENCIES include_pfn tests_util Catch2::Catch2WithMain
)
append_compilation_options(NAME "${target}" WARNINGS OPTIMIZATION)
add_dependencies("cxx${cxxrel}" "${target}")
set_property(TARGET "${target}" PROPERTY CXX_STANDARD "${cxxrel}")
add_dependencies("cxx${mode}" "${target}")
set_property(TARGET "${target}" PROPERTY CXX_STANDARD "${mode}")

add_test(
NAME "${target}"
COMMAND "${target}" -r console
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
set_property(TEST "${target}" PROPERTY LABELS tests_pfn "cxx${cxxrel}" "${root_name}")
set_property(TEST "${target}" PROPERTY LABELS tests_pfn "cxx${mode}" "${root_name}")

unset(target)
unset(root_name)
Expand Down Expand Up @@ -79,26 +102,26 @@ set(TESTS_FN_SOURCES

# Generate separate target for each individual test source
# TODO add 20 when we are compatible with C++20
foreach(cxxrel 23)
foreach(mode 23)
foreach(source IN ITEMS ${TESTS_FN_SOURCES})
string(REGEX REPLACE "^(fn)/(detail|)/?([^\.]+)\.cpp$" "\\1_\\2\\3" root_name ${source})
set(target "tests_${root_name}_cxx${cxxrel}")
set(target "tests_${root_name}_cxx${mode}")

create_target_for_file(
NAME "${target}"
SOURCE "${source}"
DEPENDENCIES include_fn tests_util Catch2::Catch2WithMain
)
append_compilation_options(NAME "${target}" WARNINGS OPTIMIZATION)
add_dependencies("cxx${cxxrel}" "${target}")
set_property(TARGET "${target}" PROPERTY CXX_STANDARD "${cxxrel}")
add_dependencies("cxx${mode}" "${target}")
set_property(TARGET "${target}" PROPERTY CXX_STANDARD "${mode}")

add_test(
NAME "${target}"
COMMAND "${target}" -r console
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
set_property(TEST "${target}" PROPERTY LABELS tests_fn "cxx${cxxrel}" "${root_name}")
set_property(TEST "${target}" PROPERTY LABELS tests_fn "cxx${mode}" "${root_name}")

unset(target)
unset(root_name)
Expand All @@ -111,21 +134,21 @@ set(TESTS_EXAMPLES_SOURCES
)

# TODO add 20 when we are compatible with C++20
foreach(cxxrel 23)
set(target "tests_examples_cxx${cxxrel}")
foreach(mode 23)
set(target "tests_examples_cxx${mode}")

add_executable("${target}" ${TESTS_EXAMPLES_SOURCES})
target_link_libraries("${target}" include_fn Catch2::Catch2WithMain)
target_compile_options("${target}" PRIVATE -Wall -Wextra -Wpedantic)
add_dependencies("cxx${cxxrel}" "${target}")
set_property(TARGET "${target}" PROPERTY CXX_STANDARD "${cxxrel}")
append_compilation_options(NAME "${target}" WARNINGS)
add_dependencies("cxx${mode}" "${target}")
set_property(TARGET "${target}" PROPERTY CXX_STANDARD "${mode}")

add_test(
NAME "${target}"
COMMAND "${target}" -r console
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
set_property(TEST "${target}" PROPERTY LABELS tests_examples "cxx${cxxrel}")
set_property(TEST "${target}" PROPERTY LABELS tests_examples "cxx${mode}")

unset(target)
endforeach()
92 changes: 85 additions & 7 deletions tests/fn/choice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
// or copy at https://opensource.org/licenses/ISC

#include <fn/choice.hpp>

#include <fn/utility.hpp>

#include <util/helper_types.hpp>

#include <catch2/catch_all.hpp>

#include <utility>
Expand Down Expand Up @@ -40,18 +43,18 @@ TEST_CASE("choice non-monadic functionality", "[choice]")
static_assert(std::same_as<fn::sum<NonCopyable, int>, typename choice<NonCopyable, int>::value_type>);
static_assert(std::same_as<fn::sum<int>, typename choice<int>::value_type>);

using type = choice<bool, int>;
using value_type = fn::sum<bool, int>;
using type = fn::choice<bool, helper>;
using value_type = fn::sum<bool, helper>;
static_assert(std::same_as<value_type &, decltype(std::declval<type &>().value())>);
static_assert(std::same_as<value_type const &, decltype(std::declval<type const &>().value())>);
static_assert(std::same_as<value_type &&, decltype(std::declval<type &&>().value())>);
static_assert(std::same_as<value_type const &&, decltype(std::declval<type const &&>().value())>);

type s{42};
type s{helper{42}};
constexpr auto fn = fn::overload{
[](auto &&) -> int { throw 0; }, //
[](int &i) -> int { return i + 1; }, [](int const &i) -> int { return i + 2; },
[](int &&i) -> int { return i + 3; }, [](int const &&i) -> int { return i + 4; },
[](helper &o) -> int { return o.v + 1; }, [](helper const &o) -> int { return o.v + 2; },
[](helper &&o) -> int { return o.v + 3; }, [](helper const &&o) -> int { return o.v + 4; },
};
static_assert(std::same_as<int, decltype(s.value().invoke(fn))>);
CHECK((s.value().invoke(fn)) == 43);
Expand Down Expand Up @@ -146,7 +149,7 @@ TEST_CASE("choice non-monadic functionality", "[choice]")
static_assert(c.invoke([](auto &&a) -> bool { return a.size() == 3 && a[0] == 3 && a[1] == 14 && a[2] == 15; }));
}

WHEN("move from rvalue")
WHEN("constexpr move from rvalue")
{
using T = fn::choice<bool, int>;
constexpr auto fn = [](auto i) constexpr noexcept -> T { return {std::move(i)}; };
Expand All @@ -159,7 +162,22 @@ TEST_CASE("choice non-monadic functionality", "[choice]")
static_assert(b.has_value<int>());
}

WHEN("copy from lvalue")
WHEN("move from rvalue")
{
using T = fn::choice<bool, helper>;
constexpr auto fn = [](auto i) noexcept -> T { return {std::move(i)}; };
auto const before = helper::witness;
auto const a = fn(helper{12});
CHECK(helper::witness == (before + 12) * helper::from_rval);
static_assert(std::is_same_v<decltype(a), T const>);
CHECK(a.has_value<helper>());

auto b = fn(true);
static_assert(std::is_same_v<decltype(b), T>);
CHECK(b.has_value<bool>());
}

WHEN("constexpr copy from lvalue")
{
using T = fn::choice<bool, int>;
constexpr auto fn = [](auto i) constexpr noexcept -> T { return {i}; };
Expand All @@ -171,6 +189,66 @@ TEST_CASE("choice non-monadic functionality", "[choice]")
static_assert(std::is_same_v<decltype(b), T const>);
static_assert(b.has_value<int>());
}

WHEN("copy from lvalue")
{
using T = fn::choice<bool, helper>;
constexpr auto fn = [](auto i) noexcept -> T { return {i}; };
auto const a = fn(true);
static_assert(std::is_same_v<decltype(a), T const>);
CHECK(a.has_value<bool>());

auto const before = helper::witness;
auto b = fn(helper{13});
CHECK(helper::witness == (before + 13) * helper::from_lval_const);
static_assert(std::is_same_v<decltype(b), T>);
CHECK(b.has_value<helper>());
}

WHEN("copy ctor")
{
using T = fn::choice<bool, helper>;
auto const h = helper{23};
auto const a = T{h};
auto const before = helper::witness;
auto const b = a;
CHECK(helper::witness == before * helper::from_lval_const);
CHECK(b.has_value<helper>());
CHECK(b.value() == fn::sum{h});
}

WHEN("move ctor")
{
using T = fn::choice<bool, helper>;
auto const h = helper{29};
auto a = T{h};
auto const before = helper::witness;
auto const b = std::move(a);
CHECK(helper::witness == before * helper::from_rval);
CHECK(b.has_value<helper>());
CHECK(b.value() == fn::sum{h});
}
}

WHEN("constructor from sum")
{
using T = fn::choice<bool, helper>;
WHEN("move from rvalue")
{
fn::sum h{helper{17}};
auto const before = helper::witness;
T const a{std::move(h)};
CHECK(helper::witness == before * helper::from_rval);
CHECK(a == h);
}
WHEN("copy from const lvalue")
{
fn::sum h{helper{19}};
auto const before = helper::witness;
T const a{h};
CHECK(helper::witness == before * helper::from_lval_const);
CHECK(a == h);
}
}

WHEN("forwarding constructors (immovable)")
Expand Down
Loading

0 comments on commit 4ef3afd

Please sign in to comment.