diff options
| author | Felix Morgner <felix.morgner@gmail.com> | 2023-06-07 22:49:03 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@gmail.com> | 2023-06-07 22:49:03 +0200 |
| commit | eead590762ec67cff200a65d02a6a12c6d0a40f8 (patch) | |
| tree | c13b8981741a56e1dbc5c4ff348761e9c02beef1 | |
| parent | fc033418a95d0eae238a4e2718b6429cdc160d0d (diff) | |
| download | newtype-eead590762ec67cff200a65d02a6a12c6d0a40f8.tar.xz newtype-eead590762ec67cff200a65d02a6a12c6d0a40f8.zip | |
tests: port conversion suite to catch2
| -rw-r--r-- | .conan/profiles/default | 4 | ||||
| -rw-r--r-- | .vscode/settings.json | 12 | ||||
| -rw-r--r-- | conanfile.py | 4 | ||||
| -rw-r--r-- | source/tests/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | source/tests/src/conversion.cpp | 135 | ||||
| -rw-r--r-- | source/tests/src/conversion_suite.cpp | 201 |
6 files changed, 150 insertions, 208 deletions
diff --git a/.conan/profiles/default b/.conan/profiles/default new file mode 100644 index 0000000..dedc2a6 --- /dev/null +++ b/.conan/profiles/default @@ -0,0 +1,4 @@ +include(default) + +[settings] +compiler.cppstd=20
\ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 24f5d88..1636210 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,14 +1,18 @@ { // CMake Configuration - "cmake.configureArguments": "-DCMAKE_EXPORT_COMPILE_COMMANDS=YES", - "cmake.cpptools.intelliSenseMode": "gcc-x64", - "cmake.cpptools.guessSourceFileConfigurations": true, + "cmake.configureOnOpen": false, + "cmake.useCMakePresets": "always", + "cmake.sourceDirectory": "${workspaceFolder}/source", + "cmake.skipConfigureIfCachePresent": true, // C++ Configuration "[cpp]": { "editor.formatOnSave": true }, "C_Cpp.autoAddFileAssociations": false, + "C_Cpp.intelliSenseEngine": "default", + "C_Cpp.errorSquiggles": "enabledIfIncludesResolve", + "C_Cpp.autocomplete": "default", // RST Configuration "restructuredtext.confPath": "${workspaceFolder}/doc/src", @@ -16,4 +20,4 @@ "editor.defaultFormatter": "ms-python.black-formatter" }, "python.formatting.provider": "none" -}
\ No newline at end of file +} diff --git a/conanfile.py b/conanfile.py index 618073b..7322849 100644 --- a/conanfile.py +++ b/conanfile.py @@ -43,7 +43,7 @@ class NewtypeConan(ConanFile): cmake.test() def build_requirements(self): - self.tool_requires("cmake/[~3.25]") + self.tool_requires("cmake/[>3.25]") self.tool_requires("ninja/[~1.11]") self.test_requires("catch2/[~3.3]") @@ -55,7 +55,7 @@ class NewtypeConan(ConanFile): toolchain.generate() def layout(self): - cmake_layout(self, src_folder="source") + cmake_layout(self, generator="Ninja Multi-Config", src_folder="source") def package(self): cmake = CMake(self) diff --git a/source/tests/CMakeLists.txt b/source/tests/CMakeLists.txt index 2287a91..7840739 100644 --- a/source/tests/CMakeLists.txt +++ b/source/tests/CMakeLists.txt @@ -8,7 +8,7 @@ include("Catch") add_executable("${PROJECT_NAME}_tests" "src/arithmetic.cpp" - # "src/conversion_suite.cpp" + "src/conversion.cpp" # "src/derivation_clause_suite.cpp" # "src/equality_comparison_suite.cpp" # "src/hash_suite.cpp" diff --git a/source/tests/src/conversion.cpp b/source/tests/src/conversion.cpp new file mode 100644 index 0000000..436d951 --- /dev/null +++ b/source/tests/src/conversion.cpp @@ -0,0 +1,135 @@ +#include "newtype/derivable.hpp" +#include "newtype/deriving.hpp" +#include "newtype/newtype.hpp" + +#include <catch2/catch_template_test_macros.hpp> +#include <catch2/catch_test_macros.hpp> +#include <catch2/generators/catch_generators_all.hpp> + +#include <string> +#include <type_traits> +#include <vector> + +using test_types = std::tuple<bool, char, int, double, std::string>; + +TEMPLATE_LIST_TEST_CASE("Scenario: Implicit Conversions", "[conversion]", test_types) +{ + GIVEN("A new_type not deriving nt::ImplicitConversion") + { + using type_alias = nt::new_type<TestType, struct conversion_test>; + + THEN("it is not implicitly convertible to the base type") + { + REQUIRE(!std::is_convertible_v<type_alias, TestType>); + } + } + + GIVEN("A new_type deriving nt::ImplicitConversion") + { + using type_alias = nt::new_type<TestType, struct conversion_test, deriving(nt::ImplicitConversion)>; + + THEN("it is implicitly convertible to the base type") + { + REQUIRE(std::is_convertible_v<type_alias, TestType>); + } + } +} + +TEMPLATE_LIST_TEST_CASE("Scenario: Decay", "[conversion]", test_types) +{ + GIVEN("Any new_type") + { + using type_alias = nt::new_type<TestType, struct conversion_test>; + + THEN("it's decay() member function returns a value of the base type") + { + REQUIRE(std::is_same_v<TestType, decltype(std::declval<type_alias>().decay())>); + } + } + + GIVEN("Any new_type") + { + using type_alias = nt::new_type<TestType, struct conversion_test>; + + WHEN("an object of that type is constructed") + { + auto integral_value = GENERATE(take(64, random(0, 127))); + auto value = [integral_value] { + if constexpr (std::is_same_v<std::string, TestType>) + { + return std::to_string(integral_value); + } + else + { + return static_cast<TestType>(integral_value); + } + }(); + auto obj = type_alias{value}; + + THEN("it's decay() member function return the underlying value") + { + REQUIRE(obj.decay() == value); + } + } + } +} + +SCENARIO("Nothrow Decay") +{ + struct strange_type + { + strange_type(strange_type const &) noexcept(false) + { + } + }; + + GIVEN("A new_type over a nothrow-copyable type") + { + using type_alias = nt::new_type<int, struct conversion_test>; + + THEN("the decay member function is nothrow-invokable") + { + REQUIRE(noexcept(std::declval<type_alias>().decay())); + } + } + + GIVEN("A new_type over a non-nothrow-copyable type") + { + using type_alias = nt::new_type<strange_type, struct conversion_test>; + + THEN("the decay member function is not nothrow-invokable") + { + REQUIRE(!noexcept(std::declval<type_alias>().decay())); + } + } +} + +SCENARIO("Nothrow Conversion") +{ + struct strange_type + { + strange_type(strange_type const &) noexcept(false) + { + } + }; + + GIVEN("A new_type over a nothrow-copy-constructible type") + { + using type_alias = nt::new_type<int, struct conversion_test>; + + THEN("the decay member function is nothrow-invokable") + { + REQUIRE(noexcept(std::declval<type_alias>().operator int())); + } + } + + GIVEN("A new_type over a non-nothrow-copy-constructible type") + { + using type_alias = nt::new_type<strange_type, struct conversion_test>; + + THEN("the decay member function is not nothrow-invokable") + { + REQUIRE(!noexcept(std::declval<type_alias>().operator strange_type())); + } + } +} diff --git a/source/tests/src/conversion_suite.cpp b/source/tests/src/conversion_suite.cpp deleted file mode 100644 index cbe2463..0000000 --- a/source/tests/src/conversion_suite.cpp +++ /dev/null @@ -1,201 +0,0 @@ -#include "conversion_suite.hpp" - -#include "kawaii.hpp" -#include "newtype/derivable.hpp" -#include "newtype/deriving.hpp" -#include "newtype/newtype.hpp" - -#include <cute/cute.h> - -#include <algorithm> -#include <iterator> -#include <limits> -#include <random> -#include <string> -#include <type_traits> -#include <vector> - -inline namespace traits_extensions -{ - - template<typename To, typename From, typename = void> - struct is_implicitly_convertible : std::false_type - { - }; - - template<typename To, typename From> - struct is_implicitly_convertible<To, From, std::void_t<decltype(std::declval<To &>() = std::declval<From &>())>> : std::true_type - { - }; - - template<typename To, typename From> - auto constexpr is_implicitly_convertible_v = is_implicitly_convertible<To, From>::value; - -} // namespace traits_extensions - -inline namespace ddt_support -{ - - template<typename T> - struct datum - { - T value; - cute::test_failure failure; - }; - - template<typename ValueType> - auto generate_test_set(std::size_t size) -> std::vector<datum<ValueType>> - { - auto device = std::random_device{}; - auto generator = std::mt19937{device()}; - auto distribution = [&] { - auto min = std::numeric_limits<ValueType>::min(); - auto max = std::numeric_limits<ValueType>::max(); - if constexpr (std::is_floating_point_v<ValueType>) - { - return std::uniform_real_distribution<ValueType>(min, max); - } - else - { - return std::uniform_int_distribution<ValueType>(min, max); - } - }(); - - auto data = std::vector<datum<ValueType>>{}; - generate_n(std::back_inserter(data), size, [&] { - auto point = distribution(generator); - return datum<ValueType>{point, DDT()}; - }); - return data; - } - -} // namespace ddt_support - -inline namespace implicit_conversion_tests -{ - - template<typename T> - auto a_new__type_without_deriving_implicit_conversion_is_not_implicitly_convertible_to_the_base_type() -> void - { - using type_alias = nt::new_type<T, struct conversion_test_1_tag>; - ASSERT(!(is_implicitly_convertible_v<T, type_alias>)); - } - - template<typename T> - auto a_new__type_with_deriving_implicit_conversion_is_implicitly_convertible_to_the_base_type() -> void - { - using type_alias = nt::new_type<T, struct conversion_test_2_tag, deriving(nt::ImplicitConversion)>; - ASSERT((is_implicitly_convertible_v<T, type_alias>)); - } - -} // namespace implicit_conversion_tests - -inline namespace decay_tests -{ - - template<typename T> - auto decay_on_a_new__type_has_a_return_type_equal_to_the_base_type() -> void - { - using type_alias = nt::new_type<T, struct conversion_test_3_tag>; - ASSERT((std::is_same_v<T, decltype(std::declval<type_alias &>().decay())>)); - } - - template<typename T> - auto decay_on_a_new__type_returns_the_underlying_value() -> void - { - using type_alias = nt::new_type<T, struct conversion_test_4_tag>; - auto data = generate_test_set<T>(2 << 16); - for_each(begin(data), end(data), [](auto & test) { ASSERT_EQUAL_DDT(test.value, type_alias{test.value}.decay(), test.failure); }); - } - -} // namespace decay_tests - -inline namespace decay_noexcept_tests -{ - - auto decay_on_a_new__type_is_noexcept_if_the_base_type_can_be_copied_without_throwing() -> void - { - static_assert(std::is_nothrow_copy_constructible_v<int>, "Sanity check"); - using type_alias = nt::new_type<int, struct conversion_test_5_tag>; - ASSERT(noexcept(type_alias{}.decay())); - } - - auto decay_on_a_new__type_is_not_noexcept_if_the_base_type_can_be_not_copied_without_throwing() -> void - { - struct strange_type - { - strange_type() = default; - strange_type(strange_type const &) noexcept(false) - { - } - }; - - static_assert(!std::is_nothrow_copy_constructible_v<strange_type>, "Sanity check"); - using type_alias = nt::new_type<strange_type, struct conversion_test_6_tag>; - ASSERT(!noexcept(type_alias{}.decay())); - } - -} // namespace decay_noexcept_tests - -inline namespace conversion_operator_noexcept_tests -{ - - auto new__type_conversion_operator_is_noexcept_if_the_base_type_can_be_copied_without_throwing() -> void - { - static_assert(std::is_nothrow_copy_constructible_v<int>, "Sanity check"); - using type_alias = nt::new_type<int, struct conversion_test_5_tag>; - ASSERT(noexcept(static_cast<int>(type_alias{}))); - } - - auto new__type_conversion_operator_is_not_noexcept_if_the_base_type_can_not_be_copied_without_throwing() -> void - { - struct strange_type - { - strange_type() = default; - strange_type(strange_type const &) noexcept(false) - { - } - }; - - static_assert(!std::is_nothrow_copy_constructible_v<strange_type>, "Sanity check"); - using type_alias = nt::new_type<strange_type, struct conversion_test_5_tag>; - ASSERT(!noexcept(static_cast<strange_type>(type_alias{}))); - } - -} // namespace conversion_operator_noexcept_tests - -auto conversion_suite() -> std::pair<cute::suite, std::string> -{ - return {{ - /// Implicit Conversion Tests - KAWAII(a_new__type_without_deriving_implicit_conversion_is_not_implicitly_convertible_to_the_base_type<bool>), - KAWAII(a_new__type_without_deriving_implicit_conversion_is_not_implicitly_convertible_to_the_base_type<char>), - KAWAII(a_new__type_without_deriving_implicit_conversion_is_not_implicitly_convertible_to_the_base_type<int>), - KAWAII(a_new__type_without_deriving_implicit_conversion_is_not_implicitly_convertible_to_the_base_type<double>), - KAWAII(a_new__type_without_deriving_implicit_conversion_is_not_implicitly_convertible_to_the_base_type<std::string>), - KAWAII(a_new__type_with_deriving_implicit_conversion_is_implicitly_convertible_to_the_base_type<bool>), - KAWAII(a_new__type_with_deriving_implicit_conversion_is_implicitly_convertible_to_the_base_type<char>), - KAWAII(a_new__type_with_deriving_implicit_conversion_is_implicitly_convertible_to_the_base_type<int>), - KAWAII(a_new__type_with_deriving_implicit_conversion_is_implicitly_convertible_to_the_base_type<double>), - KAWAII(a_new__type_with_deriving_implicit_conversion_is_implicitly_convertible_to_the_base_type<std::string>), - - /// Decay Tests - KAWAII(decay_on_a_new__type_has_a_return_type_equal_to_the_base_type<bool>), - KAWAII(decay_on_a_new__type_has_a_return_type_equal_to_the_base_type<char>), - KAWAII(decay_on_a_new__type_has_a_return_type_equal_to_the_base_type<int>), - KAWAII(decay_on_a_new__type_has_a_return_type_equal_to_the_base_type<double>), - KAWAII(decay_on_a_new__type_has_a_return_type_equal_to_the_base_type<std::string>), - KAWAII(decay_on_a_new__type_returns_the_underlying_value<char>), - KAWAII(decay_on_a_new__type_returns_the_underlying_value<int>), - KAWAII(decay_on_a_new__type_returns_the_underlying_value<double>), - - /// Decay noexcept Tests - KAWAII(decay_on_a_new__type_is_noexcept_if_the_base_type_can_be_copied_without_throwing), - KAWAII(decay_on_a_new__type_is_not_noexcept_if_the_base_type_can_be_not_copied_without_throwing), - - /// Conversion Operator noexcept Tests - KAWAII(new__type_conversion_operator_is_noexcept_if_the_base_type_can_be_copied_without_throwing), - KAWAII(new__type_conversion_operator_is_not_noexcept_if_the_base_type_can_not_be_copied_without_throwing), - }, - "Conversion Tests"}; -}
\ No newline at end of file |
