From 081688443d12de12d7b66b44630e4c7e0681fabe Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Sun, 1 Mar 2020 12:06:23 +0100 Subject: new_type: restructure iterable tests --- include/newtype/impl/type_traits_extensions.hpp | 4 +- test/src/iterable_suite.cpp | 790 ++++++++++++++---------- 2 files changed, 477 insertions(+), 317 deletions(-) diff --git a/include/newtype/impl/type_traits_extensions.hpp b/include/newtype/impl/type_traits_extensions.hpp index 121e2c0..dc41649 100644 --- a/include/newtype/impl/type_traits_extensions.hpp +++ b/include/newtype/impl/type_traits_extensions.hpp @@ -587,7 +587,7 @@ namespace nt::impl template struct has_free_rbegin()))>> - : std::is_same()))>> + : std::is_same()))>> { }; @@ -767,7 +767,7 @@ namespace nt::impl template struct has_free_rend()))>> - : std::is_same()))>> + : std::is_same()))>> { }; diff --git a/test/src/iterable_suite.cpp b/test/src/iterable_suite.cpp index a75ab19..3b46024 100644 --- a/test/src/iterable_suite.cpp +++ b/test/src/iterable_suite.cpp @@ -8,18 +8,20 @@ #include +#include #include #include +#include namespace { struct with_member { - using iterator = void *; - using const_iterator = void const *; - using reverse_iterator = void *; - using const_reverse_iterator = void const *; + using iterator = char *; + using const_iterator = char const *; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; auto begin() -> iterator; auto begin() const -> const_iterator; @@ -36,9 +38,77 @@ namespace auto crend() const -> const_reverse_iterator; }; + struct with_free + { + using iterator = char *; + using const_iterator = char const *; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + }; + + auto begin(with_free &) -> with_free::iterator + { + return {}; + } + + auto begin(with_free const &) -> with_free::const_iterator + { + return {}; + } + + auto cbegin(with_free const &) -> with_free::const_iterator + { + return {}; + } + + auto rbegin(with_free &) -> with_free::reverse_iterator + { + return {}; + } + + auto rbegin(with_free const &) -> with_free::const_reverse_iterator + { + return {}; + } + + auto crbegin(with_free const &) -> with_free::const_reverse_iterator + { + return {}; + } + + auto end(with_free &) -> with_free::iterator + { + return {}; + } + + auto end(with_free const &) -> with_free::const_iterator + { + return {}; + } + + auto cend(with_free const &) -> with_free::const_iterator + { + return {}; + } + + auto rend(with_free &) -> with_free::reverse_iterator + { + return {}; + } + + auto rend(with_free const &) -> with_free::const_reverse_iterator + { + return {}; + } + + auto crend(with_free const &) -> with_free::const_reverse_iterator + { + return {}; + } + } // namespace -inline namespace begin_tests +inline namespace combined_enablement_tests { auto a_new__type_not_deriving_iterable_has_no_begin() -> void @@ -47,513 +117,603 @@ inline namespace begin_tests ASSERT(!(nt::impl::has_begin_v)); } - auto a_new__type_based_on_a_non_iterable_type_deriving_iterable_has_no_begin() -> void + auto a_new__type_not_deriving_iterable_has_no_constant_begin() -> void { - static_assert(!nt::impl::has_begin_v); - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_begin_v)); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_begin_v)); } - auto a_new__type_based_on_an_iterable_type_with_member_begin_deriving_iterable_has_member_begin() -> void + auto a_new__type_not_deriving_iterable_has_no_cbegin() -> void { - static_assert(nt::impl::has_member_begin_v); - using type_alias = nt::new_type; - ASSERT(nt::impl::has_member_begin_v); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_cbegin_v)); } - auto a_new__type_based_on_an_iterable_type_with_constant_member_begin_deriving_iterable_has_constant_member_begin() -> void + auto a_new__type_not_deriving_iterable_has_no_rbegin() -> void { - static_assert(nt::impl::has_member_begin_v); - using type_alias = nt::new_type; - ASSERT(nt::impl::has_member_begin_v); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_rbegin_v)); } - auto a_new__type_based_on_an_iterable_type_without_free_begin_deriving_iterable_has_no_free_begin() -> void + auto a_new__type_not_deriving_iterable_has_no_constant_rbegin() -> void { - static_assert(!nt::impl::has_free_begin_v); - using type_alias = nt::new_type; - ASSERT(!nt::impl::has_free_begin_v); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_rbegin_v)); } - auto a_new__type_based_on_an_iterable_type_without_constant_free_begin_deriving_iterable_has_no_constant_free_begin() -> void + auto a_new__type_not_deriving_iterable_has_no_crbegin() -> void { - static_assert(!nt::impl::has_free_begin_v); - using type_alias = nt::new_type; - ASSERT(!nt::impl::has_free_begin_v); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_crbegin_v)); } - auto accessing_the_first_element_of_an_iterator_on_a_new__type_yields_the_same_value_as_accessing_it_through_an_unwrapped_type() -> void + auto a_new__type_not_deriving_iterable_has_no_end() -> void { - using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; - auto weak = std::array{42, 21, 10}; - auto strong = type_alias{{42, 21, 10}}; - ASSERT_EQUAL(*weak.begin(), *strong.begin()); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_end_v)); } - auto an_iterator_obtained_via_member_begin_compares_equal_to_an_iterator_obtained_via_free_begin() -> void + auto a_new__type_not_deriving_iterable_has_no_constant_end() -> void { - using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; - auto instance = type_alias{{42, 21, 10}}; - ASSERT_EQUAL(begin(instance), instance.begin()); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_end_v)); } -} // namespace begin_tests + auto a_new__type_not_deriving_iterable_has_no_cend() -> void + { + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_cend_v)); + } -inline namespace cbegin_tests -{ + auto a_new__type_not_deriving_iterable_has_no_rend() -> void + { + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_rend_v)); + } - auto a_new__type_not_deriving_iterable_has_no_cbegin() -> void + auto a_new__type_not_deriving_iterable_has_no_constant_rend() -> void { using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_cbegin_v)); + ASSERT(!(nt::impl::has_rend_v)); + } + + auto a_new__type_not_deriving_iterable_has_no_crend() -> void + { + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_crend_v)); + } + + auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_begin() -> void + { + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_begin_v)); + } + + auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_constant_begin() -> void + { + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_begin_v)); } - auto a_new__type_based_on_a_non_iterable_type_deriving_iterable_has_no_cbegin() -> void + auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_cbegin() -> void { - static_assert(!nt::impl::has_cbegin_v); using type_alias = nt::new_type; ASSERT(!(nt::impl::has_cbegin_v)); } - auto a_new__type_based_on_an_iterable_type_with_member_cbegin_deriving_iterable_has_member_cbegin() -> void + auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_rbegin() -> void { - static_assert(nt::impl::has_member_cbegin_v); - using type_alias = nt::new_type; - ASSERT(nt::impl::has_member_cbegin_v); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_rbegin_v)); } - auto a_new__type_based_on_an_iterable_type_without_free_cbegin_deriving_iterable_has_no_free_cbegin() -> void + auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_constant_rbegin() -> void { - static_assert(!nt::impl::has_free_cbegin_v); - using type_alias = nt::new_type; - ASSERT(!nt::impl::has_free_cbegin_v); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_rbegin_v)); } - auto accessing_the_first_element_of_a_constant_iterator_on_a_new__type_yields_the_same_value_as_accessing_it_through_an_unwrapped_type() - -> void + auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_crbegin() -> void { - using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; - auto weak = std::array{42, 21, 10}; - auto strong = type_alias{{42, 21, 10}}; - ASSERT_EQUAL(*weak.cbegin(), *strong.cbegin()); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_crbegin_v)); } - auto an_iterator_obtained_via_member_cbegin_compares_equal_to_an_iterator_obtained_via_free_cbegin() -> void + auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_end() -> void { - using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; - auto instance = type_alias{{42, 21, 10}}; - ASSERT_EQUAL(cbegin(instance), instance.cbegin()); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_end_v)); } -} // namespace cbegin_tests + auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_constant_end() -> void + { + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_end_v)); + } -inline namespace rbegin_tests -{ + auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_cend() -> void + { + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_cend_v)); + } - auto a_new__type_not_deriving_iterable_has_no_rbegin() -> void + auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_rend() -> void { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_rbegin_v)); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_rend_v)); } - auto a_new__type_based_on_a_non_iterable_type_deriving_iterable_has_no_rbegin() -> void + auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_constant_rend() -> void { - static_assert(!nt::impl::has_rbegin_v); using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_rbegin_v)); + ASSERT(!(nt::impl::has_rend_v)); } - auto a_new__type_based_on_an_iterable_type_with_member_rbegin_deriving_iterable_has_member_rbegin() -> void + auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_crend() -> void { - static_assert(nt::impl::has_member_rbegin_v); - using type_alias = nt::new_type; - ASSERT(nt::impl::has_member_rbegin_v); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_crend_v)); } - auto a_new__type_based_on_an_iterable_type_with_constant_member_rbegin_deriving_iterable_has_constant_member_rbegin() -> void +} // namespace combined_enablement_tests + +inline namespace member_enablement_tests +{ + + auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_begin() -> void { - static_assert(nt::impl::has_member_rbegin_v); - using type_alias = nt::new_type; - ASSERT(nt::impl::has_member_rbegin_v); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_member_begin_v)); } - auto a_new__type_based_on_an_iterable_type_without_free_rbegin_deriving_iterable_has_no_free_rbegin() -> void + auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_constant_begin() -> void { - static_assert(!nt::impl::has_free_rbegin_v); - using type_alias = nt::new_type; - ASSERT(!nt::impl::has_free_rbegin_v); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_member_begin_v)); } - auto a_new__type_based_on_an_iterable_type_without_constant_free_rbegin_deriving_iterable_has_no_constant_free_rbegin() -> void + auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_cbegin() -> void { - static_assert(!nt::impl::has_free_rbegin_v); - using type_alias = nt::new_type; - ASSERT(!nt::impl::has_free_rbegin_v); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_member_cbegin_v)); } - auto accessing_the_first_element_of_a_reverse_iterator_on_a_new__type_yields_the_same_value_as_accessing_it_through_an_unwrapped_type() - -> void + auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_rbegin() -> void { - using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; - auto weak = std::array{42, 21, 10}; - auto strong = type_alias{{42, 21, 10}}; - ASSERT_EQUAL(*weak.rbegin(), *strong.rbegin()); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_member_rbegin_v)); } - auto an_iterator_obtained_via_member_rbegin_compares_equal_to_an_iterator_obtained_via_free_rbegin() -> void + auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_constant_rbegin() -> void { - using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; - auto instance = type_alias{{42, 21, 10}}; - ASSERT_EQUAL(rbegin(instance), instance.rbegin()); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_member_rbegin_v)); } -} // namespace rbegin_tests + auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_crbegin() -> void + { + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_member_crbegin_v)); + } -inline namespace crbegin_tests -{ + auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_end() -> void + { + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_member_end_v)); + } - auto a_new__type_not_deriving_iterable_has_no_crbegin() -> void + auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_constant_end() -> void { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_crbegin_v)); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_member_end_v)); } - auto a_new__type_based_on_a_non_iterable_type_deriving_iterable_has_no_crbegin() -> void + auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_cend() -> void { - static_assert(!nt::impl::has_crbegin_v); - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_crbegin_v)); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_member_cend_v)); } - auto a_new__type_based_on_an_iterable_type_with_member_crbegin_deriving_iterable_has_member_crbegin() -> void + auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_rend() -> void { - static_assert(nt::impl::has_member_crbegin_v); - using type_alias = nt::new_type; - ASSERT(nt::impl::has_member_crbegin_v); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_member_rend_v)); } - auto a_new__type_based_on_an_iterable_type_without_free_crbegin_deriving_iterable_has_no_free_crbegin() -> void + auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_constant_rend() -> void { - static_assert(!nt::impl::has_free_crbegin_v); - using type_alias = nt::new_type; - ASSERT(!nt::impl::has_free_crbegin_v); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_member_rend_v)); } - auto - accessing_the_first_element_of_a_constant_reverse_iterator_on_a_new__type_yields_the_same_value_as_accessing_it_through_an_unwrapped_type() - -> void + auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_crend() -> void { - using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; - auto weak = std::array{42, 21, 10}; - auto strong = type_alias{{42, 21, 10}}; - ASSERT_EQUAL(*weak.crbegin(), *strong.crbegin()); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_member_crend_v)); } - auto an_iterator_obtained_via_member_crbegin_compares_equal_to_an_iterator_obtained_via_free_crbegin() -> void + auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_begin() -> void { - using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; - auto instance = type_alias{{42, 21, 10}}; - ASSERT_EQUAL(crbegin(instance), instance.crbegin()); + using type_alias = nt::new_type; + ASSERT(nt::impl::has_member_begin_v); } -} // namespace crbegin_tests + auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_constant_begin() -> void + { + using type_alias = nt::new_type; + ASSERT(nt::impl::has_member_begin_v); + } -inline namespace end_tests -{ + auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_cbegin() -> void + { + using type_alias = nt::new_type; + ASSERT(nt::impl::has_member_cbegin_v); + } - auto a_new__type_not_deriving_iterable_has_no_end() -> void + auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_rbegin() -> void { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_end_v)); + using type_alias = nt::new_type; + ASSERT(nt::impl::has_member_rbegin_v); } - auto a_new__type_based_on_a_non_iterable_type_deriving_iterable_has_no_end() -> void + auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_constant_rbegin() -> void { - static_assert(!nt::impl::has_end_v); - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_end_v)); + using type_alias = nt::new_type; + ASSERT(nt::impl::has_member_rbegin_v); } - auto a_new__type_based_on_an_iterable_type_with_member_end_deriving_iterable_has_member_end() -> void + auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_crbegin() -> void + { + using type_alias = nt::new_type; + ASSERT(nt::impl::has_member_crbegin_v); + } + + auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_end() -> void { - static_assert(nt::impl::has_member_end_v); using type_alias = nt::new_type; ASSERT(nt::impl::has_member_end_v); } - auto a_new__type_based_on_an_iterable_type_with_constant_member_end_deriving_iterable_has_constant_member_end() -> void + auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_constant_end() -> void { - static_assert(nt::impl::has_member_end_v); using type_alias = nt::new_type; ASSERT(nt::impl::has_member_end_v); } - auto a_new__type_based_on_an_iterable_type_without_free_end_deriving_iterable_has_no_free_end() -> void + auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_cend() -> void { - static_assert(!nt::impl::has_free_end_v); using type_alias = nt::new_type; - ASSERT(!nt::impl::has_free_end_v); + ASSERT(nt::impl::has_member_cend_v); } - auto a_new__type_based_on_an_iterable_type_without_constant_free_end_deriving_iterable_has_no_constant_free_end() -> void + auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_rend() -> void { - static_assert(!nt::impl::has_free_end_v); using type_alias = nt::new_type; - ASSERT(!nt::impl::has_free_end_v); + ASSERT(nt::impl::has_member_rend_v); } - auto accessing_the_last_element_of_an_iterator_on_a_new__type_yields_the_same_value_as_accessing_it_through_an_unwrapped_type() -> void + auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_constant_rend() -> void { - using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; - auto weak = std::array{42, 21, 10}; - auto strong = type_alias{{42, 21, 10}}; - ASSERT_EQUAL(*(weak.end() - 1), *(strong.end() - 1)); + using type_alias = nt::new_type; + ASSERT(nt::impl::has_member_rend_v); } - auto an_iterator_obtained_via_member_end_compares_equal_to_an_iterator_obtained_via_free_end() -> void + auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_crend() -> void { - using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; - auto instance = type_alias{{42, 21, 10}}; - ASSERT_EQUAL(end(instance), instance.end()); + using type_alias = nt::new_type; + ASSERT(nt::impl::has_member_crend_v); } -} // namespace end_tests +} // namespace member_enablement_tests -inline namespace cend_tests +inline namespace free_enablement_tests { - - auto a_new__type_not_deriving_iterable_has_no_cend() -> void + auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_begin() -> void { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_cend_v)); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_free_begin_v)); } - auto a_new__type_based_on_a_non_iterable_type_deriving_iterable_has_no_cend() -> void + auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_constant_begin() -> void { - static_assert(!nt::impl::has_cend_v); - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_cend_v)); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_free_begin_v)); } - auto a_new__type_based_on_an_iterable_type_with_member_cend_deriving_iterable_has_member_cend() -> void + auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_cbegin() -> void { - static_assert(nt::impl::has_member_cend_v); using type_alias = nt::new_type; - ASSERT(nt::impl::has_member_cend_v); + ASSERT(!(nt::impl::has_free_cbegin_v)); } - auto a_new__type_based_on_an_iterable_type_without_free_cend_deriving_iterable_has_no_free_cend() -> void + auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_rbegin() -> void { - static_assert(!nt::impl::has_free_cend_v); using type_alias = nt::new_type; - ASSERT(!nt::impl::has_free_cend_v); + ASSERT(!(nt::impl::has_free_rbegin_v)); } - auto accessing_the_last_element_of_a_constant_iterator_on_a_new__type_yields_the_same_value_as_accessing_it_through_an_unwrapped_type() - -> void + auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_constant_rbegin() -> void { - using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; - auto weak = std::array{42, 21, 10}; - auto strong = type_alias{{42, 21, 10}}; - ASSERT_EQUAL(*(weak.cend() - 1), *(strong.cend() - 1)); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_free_rbegin_v)); } - auto an_iterator_obtained_via_member_cend_compares_equal_to_an_iterator_obtained_via_free_cend() -> void + auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_crbegin() -> void { - using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; - auto instance = type_alias{{42, 21, 10}}; - ASSERT_EQUAL(cend(instance), instance.cend()); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_free_crbegin_v)); } -} // namespace cend_tests - -inline namespace rend_tests -{ - - auto a_new__type_not_deriving_iterable_has_no_rend() -> void + auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_end() -> void { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_rend_v)); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_free_end_v)); } - auto a_new__type_based_on_a_non_iterable_type_deriving_iterable_has_no_rend() -> void + auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_constant_end() -> void { - static_assert(!nt::impl::has_rend_v); - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_rend_v)); + using type_alias = nt::new_type; + ASSERT(!(nt::impl::has_free_end_v)); } - auto a_new__type_based_on_an_iterable_type_with_member_rend_deriving_iterable_has_member_rend() -> void + auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_cend() -> void { - static_assert(nt::impl::has_member_rend_v); using type_alias = nt::new_type; - ASSERT(nt::impl::has_member_rend_v); + ASSERT(!(nt::impl::has_free_cend_v)); } - auto a_new__type_based_on_an_iterable_type_with_constant_member_rend_deriving_iterable_has_constant_member_rend() -> void + auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_rend() -> void { - static_assert(nt::impl::has_member_rend_v); using type_alias = nt::new_type; - ASSERT(nt::impl::has_member_rend_v); + ASSERT(!(nt::impl::has_free_rend_v)); } - auto a_new__type_based_on_an_iterable_type_without_free_rend_deriving_iterable_has_no_free_rend() -> void + auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_constant_rend() -> void { - static_assert(!nt::impl::has_free_rend_v); using type_alias = nt::new_type; - ASSERT(!nt::impl::has_free_rend_v); + ASSERT(!(nt::impl::has_free_rend_v)); } - auto a_new__type_based_on_an_iterable_type_without_constant_free_rend_deriving_iterable_has_no_constant_free_rend() -> void + auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_crend() -> void { - static_assert(!nt::impl::has_free_rend_v); using type_alias = nt::new_type; - ASSERT(!nt::impl::has_free_rend_v); + ASSERT(!(nt::impl::has_free_crend_v)); } - auto accessing_the_last_element_of_a_reverse_iterator_on_a_new__type_yields_the_same_value_as_accessing_it_through_an_unwrapped_type() -> void + auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_begin() -> void { - using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; - auto weak = std::array{42, 21, 10}; - auto strong = type_alias{{42, 21, 10}}; - ASSERT_EQUAL(*(weak.rend() - 1), *(strong.rend() - 1)); + using type_alias = nt::new_type; + ASSERT(nt::impl::has_free_begin_v); } - auto an_iterator_obtained_via_member_rend_compares_equal_to_an_iterator_obtained_via_free_rend() -> void + auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_constant_begin() -> void { - using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; - auto instance = type_alias{{42, 21, 10}}; - ASSERT_EQUAL(rend(instance), instance.rend()); + using type_alias = nt::new_type; + ASSERT(nt::impl::has_free_begin_v); + } + + auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_cbegin() -> void + { + using type_alias = nt::new_type; + ASSERT(nt::impl::has_free_cbegin_v); + } + + auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_rbegin() -> void + { + using type_alias = nt::new_type; + ASSERT(nt::impl::has_free_rbegin_v); + } + + auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_constant_rbegin() -> void + { + using type_alias = nt::new_type; + ASSERT(nt::impl::has_free_rbegin_v); + } + + auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_crbegin() -> void + { + using type_alias = nt::new_type; + ASSERT(nt::impl::has_free_crbegin_v); + } + + auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_end() -> void + { + using type_alias = nt::new_type; + ASSERT(nt::impl::has_free_end_v); + } + + auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_constant_end() -> void + { + using type_alias = nt::new_type; + ASSERT(nt::impl::has_free_end_v); + } + + auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_cend() -> void + { + using type_alias = nt::new_type; + ASSERT(nt::impl::has_free_cend_v); + } + + auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_rend() -> void + { + using type_alias = nt::new_type; + ASSERT(nt::impl::has_free_rend_v); + } + + auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_constant_rend() -> void + { + using type_alias = nt::new_type; + ASSERT(nt::impl::has_free_rend_v); + } + + auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_crend() -> void + { + using type_alias = nt::new_type; + ASSERT(nt::impl::has_free_crend_v); } -} // namespace rend_tests +} // namespace free_enablement_tests -inline namespace crend_tests +inline namespace semantic_tests { - auto a_new__type_not_deriving_iterable_has_no_crend() -> void + auto a_non_const_object_of_iterable_new__type_can_be_used_in_value_range_for() -> void { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_crend_v)); + using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; + auto object = type_alias{{1, 2, 3}}; + for (auto e : object) + { + (void)e; + } + ASSERT(true); } - auto a_new__type_based_on_a_non_iterable_type_deriving_iterable_has_no_crend() -> void + auto a_const_object_of_iterable_new__type_can_be_used_in_value_range_for() -> void { - static_assert(!nt::impl::has_crend_v); - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_crend_v)); + using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; + auto const object = type_alias{{1, 2, 3}}; + for (auto e : object) + { + (void)e; + } + ASSERT(true); } - auto a_new__type_based_on_an_iterable_type_with_member_crend_deriving_iterable_has_member_crend() -> void + auto a_non_const_object_of_iterable_new__type_can_be_used_in_reference_range_for() -> void { - static_assert(nt::impl::has_member_crend_v); - using type_alias = nt::new_type; - ASSERT(nt::impl::has_member_crend_v); + using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; + auto object = type_alias{{1, 2, 3}}; + for (auto & e : object) + { + (void)e; + } + ASSERT(true); } - auto a_new__type_based_on_an_iterable_type_without_free_crend_deriving_iterable_has_no_free_crend() -> void + auto a_const_object_of_iterable_new__type_can_be_used_in_const_reference_range_for() -> void { - static_assert(!nt::impl::has_free_crend_v); - using type_alias = nt::new_type; - ASSERT(!nt::impl::has_free_crend_v); + using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; + auto const object = type_alias{{1, 2, 3}}; + for (auto const & e : object) + { + (void)e; + } + ASSERT(true); } - auto - accessing_the_last_element_of_a_constant_reverse_iterator_on_a_new__type_yields_the_same_value_as_accessing_it_through_an_unwrapped_type() - -> void + auto applying_accumulate_to_an_interable_new__type_yields_the_same_result_as_when_applied_to_the_base_type() -> void { using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; - auto weak = std::array{42, 21, 10}; - auto strong = type_alias{{42, 21, 10}}; - ASSERT_EQUAL(*(weak.crend() - 1), *(strong.crend() - 1)); + auto const nt_object = type_alias{{1, 2, 3}}; + auto const bt_object = type_alias::base_type{1, 2, 3}; + + auto nt_result = std::accumulate(std::cbegin(nt_object), std::cend(nt_object), 0); + auto bt_result = std::accumulate(std::cbegin(bt_object), std::cend(bt_object), 0); + + ASSERT_EQUAL(bt_result, nt_result); } - auto an_iterator_obtained_via_member_crend_compares_equal_to_an_iterator_obtained_via_free_crend() -> void + auto iterating_over_an_iterable_new__type_yields_the_elements_in_the_same_order_as_when_iterating_the_base_type() -> void { + using std::cbegin, std::cend, std::equal; using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; - auto instance = type_alias{{42, 21, 10}}; - ASSERT_EQUAL(crend(instance), instance.crend()); + auto const nt_object = type_alias{{1, 2, 3}}; + auto const bt_object = type_alias::base_type{1, 2, 3}; + + ASSERT(equal(cbegin(nt_object), cend(nt_object), cbegin(bt_object), cend(bt_object))); } -} // namespace crend_tests +} // namespace semantic_tests auto iterable_suite() -> std::pair { - return { - { - // clang-format off - /// 'begin' Tests - KAWAII(a_new__type_not_deriving_iterable_has_no_begin), - KAWAII(a_new__type_based_on_a_non_iterable_type_deriving_iterable_has_no_begin), - KAWAII(a_new__type_based_on_an_iterable_type_with_member_begin_deriving_iterable_has_member_begin), - KAWAII(a_new__type_based_on_an_iterable_type_with_constant_member_begin_deriving_iterable_has_constant_member_begin), - KAWAII(a_new__type_based_on_an_iterable_type_without_free_begin_deriving_iterable_has_no_free_begin), - KAWAII(a_new__type_based_on_an_iterable_type_without_constant_free_begin_deriving_iterable_has_no_constant_free_begin), - KAWAII(accessing_the_first_element_of_an_iterator_on_a_new__type_yields_the_same_value_as_accessing_it_through_an_unwrapped_type), - KAWAII(an_iterator_obtained_via_member_begin_compares_equal_to_an_iterator_obtained_via_free_begin), - - /// 'cbegin' Tests - KAWAII(a_new__type_not_deriving_iterable_has_no_cbegin), - KAWAII(a_new__type_based_on_a_non_iterable_type_deriving_iterable_has_no_cbegin), - KAWAII(a_new__type_based_on_an_iterable_type_with_member_cbegin_deriving_iterable_has_member_cbegin), - KAWAII(a_new__type_based_on_an_iterable_type_without_free_cbegin_deriving_iterable_has_no_free_cbegin), - KAWAII(accessing_the_first_element_of_a_constant_iterator_on_a_new__type_yields_the_same_value_as_accessing_it_through_an_unwrapped_type), - KAWAII(an_iterator_obtained_via_member_cbegin_compares_equal_to_an_iterator_obtained_via_free_cbegin), - - /// 'rbegin' Tests - KAWAII(a_new__type_not_deriving_iterable_has_no_rbegin), - KAWAII(a_new__type_based_on_a_non_iterable_type_deriving_iterable_has_no_rbegin), - KAWAII(a_new__type_based_on_an_iterable_type_with_member_rbegin_deriving_iterable_has_member_rbegin), - KAWAII(a_new__type_based_on_an_iterable_type_with_constant_member_rbegin_deriving_iterable_has_constant_member_rbegin), - KAWAII(a_new__type_based_on_an_iterable_type_without_free_rbegin_deriving_iterable_has_no_free_rbegin), - KAWAII(a_new__type_based_on_an_iterable_type_without_constant_free_rbegin_deriving_iterable_has_no_constant_free_rbegin), - KAWAII(accessing_the_first_element_of_a_reverse_iterator_on_a_new__type_yields_the_same_value_as_accessing_it_through_an_unwrapped_type), - KAWAII(an_iterator_obtained_via_member_rbegin_compares_equal_to_an_iterator_obtained_via_free_rbegin), - - /// 'crbegin' Tests - KAWAII(a_new__type_not_deriving_iterable_has_no_crbegin), - KAWAII(a_new__type_based_on_a_non_iterable_type_deriving_iterable_has_no_crbegin), - KAWAII(a_new__type_based_on_an_iterable_type_with_member_crbegin_deriving_iterable_has_member_crbegin), - KAWAII(a_new__type_based_on_an_iterable_type_without_free_crbegin_deriving_iterable_has_no_free_crbegin), - KAWAII(accessing_the_first_element_of_a_constant_reverse_iterator_on_a_new__type_yields_the_same_value_as_accessing_it_through_an_unwrapped_type), - KAWAII(an_iterator_obtained_via_member_crbegin_compares_equal_to_an_iterator_obtained_via_free_crbegin), - - /// 'end' Tests - KAWAII(a_new__type_not_deriving_iterable_has_no_end), - KAWAII(a_new__type_based_on_a_non_iterable_type_deriving_iterable_has_no_end), - KAWAII(a_new__type_based_on_an_iterable_type_with_member_end_deriving_iterable_has_member_end), - KAWAII(a_new__type_based_on_an_iterable_type_with_constant_member_end_deriving_iterable_has_constant_member_end), - KAWAII(a_new__type_based_on_an_iterable_type_without_free_end_deriving_iterable_has_no_free_end), - KAWAII(a_new__type_based_on_an_iterable_type_without_constant_free_end_deriving_iterable_has_no_constant_free_end), - KAWAII(accessing_the_last_element_of_an_iterator_on_a_new__type_yields_the_same_value_as_accessing_it_through_an_unwrapped_type), - KAWAII(an_iterator_obtained_via_member_end_compares_equal_to_an_iterator_obtained_via_free_end), - - /// 'cend' Tests - KAWAII(a_new__type_not_deriving_iterable_has_no_cend), - KAWAII(a_new__type_based_on_a_non_iterable_type_deriving_iterable_has_no_cend), - KAWAII(a_new__type_based_on_an_iterable_type_with_member_cend_deriving_iterable_has_member_cend), - KAWAII(a_new__type_based_on_an_iterable_type_without_free_cend_deriving_iterable_has_no_free_cend), - KAWAII(accessing_the_last_element_of_a_constant_iterator_on_a_new__type_yields_the_same_value_as_accessing_it_through_an_unwrapped_type), - KAWAII(an_iterator_obtained_via_member_cend_compares_equal_to_an_iterator_obtained_via_free_cend), - - /// 'rend' Tests - KAWAII(a_new__type_not_deriving_iterable_has_no_rend), - KAWAII(a_new__type_based_on_a_non_iterable_type_deriving_iterable_has_no_rend), - KAWAII(a_new__type_based_on_an_iterable_type_with_member_rend_deriving_iterable_has_member_rend), - KAWAII(a_new__type_based_on_an_iterable_type_with_constant_member_rend_deriving_iterable_has_constant_member_rend), - KAWAII(a_new__type_based_on_an_iterable_type_without_free_rend_deriving_iterable_has_no_free_rend), - KAWAII(a_new__type_based_on_an_iterable_type_without_constant_free_rend_deriving_iterable_has_no_constant_free_rend), - KAWAII(accessing_the_last_element_of_a_reverse_iterator_on_a_new__type_yields_the_same_value_as_accessing_it_through_an_unwrapped_type), - KAWAII(an_iterator_obtained_via_member_rend_compares_equal_to_an_iterator_obtained_via_free_rend), - - /// 'crend' Tests - KAWAII(a_new__type_not_deriving_iterable_has_no_crend), - KAWAII(a_new__type_based_on_a_non_iterable_type_deriving_iterable_has_no_crend), - KAWAII(a_new__type_based_on_an_iterable_type_with_member_crend_deriving_iterable_has_member_crend), - KAWAII(a_new__type_based_on_an_iterable_type_without_free_crend_deriving_iterable_has_no_free_crend), - KAWAII(accessing_the_last_element_of_a_constant_reverse_iterator_on_a_new__type_yields_the_same_value_as_accessing_it_through_an_unwrapped_type), - KAWAII(an_iterator_obtained_via_member_crend_compares_equal_to_an_iterator_obtained_via_free_crend), - // clang-format on - }, - "Iterable Tests"}; + return {{ + /// Combined Enablement Tests + KAWAII(a_new__type_not_deriving_iterable_has_no_begin), + KAWAII(a_new__type_not_deriving_iterable_has_no_constant_begin), + KAWAII(a_new__type_not_deriving_iterable_has_no_cbegin), + KAWAII(a_new__type_not_deriving_iterable_has_no_rbegin), + KAWAII(a_new__type_not_deriving_iterable_has_no_constant_rbegin), + KAWAII(a_new__type_not_deriving_iterable_has_no_crbegin), + KAWAII(a_new__type_not_deriving_iterable_has_no_end), + KAWAII(a_new__type_not_deriving_iterable_has_no_constant_end), + KAWAII(a_new__type_not_deriving_iterable_has_no_cend), + KAWAII(a_new__type_not_deriving_iterable_has_no_rend), + KAWAII(a_new__type_not_deriving_iterable_has_no_constant_rend), + KAWAII(a_new__type_not_deriving_iterable_has_no_crend), + KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_begin), + KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_constant_begin), + KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_cbegin), + KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_rbegin), + KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_constant_rbegin), + KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_crbegin), + KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_end), + KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_constant_end), + KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_cend), + KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_rend), + KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_constant_rend), + KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_crend), + + /// Member Enablement Tests + KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_begin), + KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_constant_begin), + KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_cbegin), + KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_rbegin), + KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_constant_rbegin), + KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_crbegin), + KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_end), + KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_constant_end), + KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_cend), + KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_rend), + KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_constant_rend), + KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_crend), + KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_begin), + KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_constant_begin), + KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_cbegin), + KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_rbegin), + KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_constant_rbegin), + KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_crbegin), + KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_end), + KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_constant_end), + KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_cend), + KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_rend), + KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_constant_rend), + KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_crend), + + /// Free Enablement Tests + KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_begin), + KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_constant_begin), + KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_cbegin), + KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_rbegin), + KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_constant_rbegin), + KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_crbegin), + KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_end), + KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_constant_end), + KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_cend), + KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_rend), + KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_constant_rend), + KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_crend), + KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_begin), + KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_constant_begin), + KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_cbegin), + KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_rbegin), + KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_constant_rbegin), + KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_crbegin), + KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_end), + KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_constant_end), + KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_cend), + KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_rend), + KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_constant_rend), + KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_crend), + + /// Semantic Tests + KAWAII(a_non_const_object_of_iterable_new__type_can_be_used_in_value_range_for), + KAWAII(a_const_object_of_iterable_new__type_can_be_used_in_value_range_for), + KAWAII(a_non_const_object_of_iterable_new__type_can_be_used_in_reference_range_for), + KAWAII(a_const_object_of_iterable_new__type_can_be_used_in_const_reference_range_for), + KAWAII(applying_accumulate_to_an_interable_new__type_yields_the_same_result_as_when_applied_to_the_base_type), + KAWAII(iterating_over_an_iterable_new__type_yields_the_elements_in_the_same_order_as_when_iterating_the_base_type), + }, + + "Iterable Tests"}; } \ No newline at end of file -- cgit v1.2.3