Compare commits
7 Commits
fce50dc9b0
...
be204dd4fb
| Author | SHA1 | Date |
|---|---|---|
|
|
be204dd4fb | |
|
|
a046aa7bfb | |
|
|
13113ce484 | |
|
|
96554418e0 | |
|
|
0d4b15c266 | |
|
|
dde9be29fc | |
|
|
3413dadfae |
|
|
@ -358,9 +358,8 @@ namespace cc {
|
|||
template<typename T, std::size_t N>
|
||||
constexpr void const_vector<T, N>::assign(std::initializer_list<value_type> values)
|
||||
{
|
||||
auto values_size = std::distance(values.begin(), values.end());
|
||||
if (values_size > N) throw std::invalid_argument("Initializer list in assign has more elements than size" + std::to_string(values_size) + ">=" + std::to_string(N));
|
||||
_size = values_size;
|
||||
if (values.size() > N) throw std::invalid_argument("Initializer list in assign has more elements than size" + std::to_string(values_size) + ">=" + std::to_string(N));
|
||||
_size = values.size();
|
||||
std::copy(values.begin(), values.end(), _arr);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,37 +29,74 @@
|
|||
#define TEST_PASS_MSG_TYPE(msg, type_hint) ret_val_s { "", ReturnCode::PASSED, msg, to_type_hint_str::value<type_hint> }
|
||||
#define TEST_SKIP_TYPE(type_hint) ret_val_s { "", ReturnCode::SKIPPED, nullptr, to_type_hint_str::value<type_hint> }
|
||||
|
||||
#define ASSERT_TYPE(condition, type) ASSERT_TYPE_MSG(condition, #condition "" _LOCATION, type)
|
||||
#define ASSERT_TYPE_MSG(condition, msg, type) { if (!(condition)) return TEST_FAIL_TYPE(msg, type); } static_assert(true, "")
|
||||
#define ASSERT_TYPE_ALL_EQ(first, last, eq, type) ASSERT_TYPE_MSG(std::all_of(first, last, all_eq_arr_elem_test_func(eq)), "Not all elements in (" #first ", " #last ") equal " #eq "" _LOCATION, type)
|
||||
#define ASSERT_TYPE_C_ARR_EQ(first, last, eq, type) ASSERT_TYPE_MSG(std::equal(first, last, eq, all_eq_arr_arr_test_func<decltype(eq)>()), "Elements in (" #first ", " #last ") and " #eq " differ" _LOCATION, type)
|
||||
#define ASSERT_TYPE_ITER_EQ(first, last, eq, type) ASSERT_TYPE_MSG(std::equal(first, last, (eq).begin(), all_eq_arr_arr_test_func<std::iterator_traits<decltype(eq)::iterator>::value_type>()), "Elements in (" #first ", " #last ") and " #eq " differ" _LOCATION, type)
|
||||
#define TEST_FAIL_TYPE_NUM(msg, type_hint, num) ret_val_s { "", ReturnCode::FAILED, msg, to_type_hint_str::value<type_hint>, num }
|
||||
#define TEST_PASS_TYPE_NUM(type_hint, num) ret_val_s { "", ReturnCode::PASSED, nullptr, to_type_hint_str::value<type_hint>, num }
|
||||
#define TEST_PASS_MSG_TYPE_NUM(msg, type_hint, num) ret_val_s { "", ReturnCode::PASSED, msg, to_type_hint_str::value<type_hint>, num }
|
||||
#define TEST_SKIP_TYPE_NUM(type_hint, num) ret_val_s { "", ReturnCode::SKIPPED, nullptr, to_type_hint_str::value<type_hint>, num }
|
||||
|
||||
#define ASSERT_TYPE_NUM(condition, type, num) ASSERT_TYPE_NUM_MSG(condition, #condition "" _LOCATION, type, num)
|
||||
#define ASSERT_TYPE_NUM_MSG(condition, msg, type, num) { if (!(condition)) return TEST_FAIL_TYPE_NUM(msg, type, num); } static_assert(true, "")
|
||||
#define ASSERT_TYPE_NUM_ALL_EQ(first, last, eq, type, num) ASSERT_TYPE_NUM_MSG(all_eq_to(first, last, eq), "Not all elements in (" #first ", " #last ") equal " #eq "" _LOCATION, type, num)
|
||||
#define ASSERT_TYPE_NUM_C_ARR_EQ(first, last, eq, type, num) ASSERT_TYPE_NUM_MSG(equal_to(first, last, eq), "Elements in (" #first ", " #last ") and " #eq " differ" _LOCATION, type, num)
|
||||
|
||||
#define ASSERT_TYPE(condition, type) ASSERT_TYPE_NUM(condition, type, -1ULL)
|
||||
#define ASSERT_TYPE_MSG(condition, msg, type) ASSERT_TYPE_NUM_MSG(condition, msg, type -1ULL)
|
||||
#define ASSERT_TYPE_ALL_EQ(first, last, eq, type) ASSERT_TYPE_NUM_ALL_EQ(first, last, eq, type, -1ULL)
|
||||
#define ASSERT_TYPE_C_ARR_EQ(first, last, eq, type) ASSERT_TYPE_NUM_C_ARR_EQ(first, last, eq, type, -1ULL)
|
||||
|
||||
#define ASSERT(condition) ASSERT_TYPE(condition, std::nullptr_t)
|
||||
#define ASSERT_MSG(condition, msg) ASSERT_TYPE_MSG(condition, msg, std::nullptr_t)
|
||||
#define ASSERT_ALL_EQ(first, last, eq) ASSERT_TYPE_ALL_EQ(first, last, eq, std::nullptr_t)
|
||||
#define ASSERT_C_ARR_EQ(first, last, eq) ASSERT_TYPE_C_ARR_EQ(first, last, eq, std::nullptr_t)
|
||||
#define ASSERT_ITER_EQ(first, last, eq) ASSERT_TYPE_ITER_EQ(first, last, eq, std::nullptr_t)
|
||||
|
||||
#define ASSERT_TYPE_THROWS(operation, exception_type, type) if not consteval { try { operation; ASSERT_TYPE_MSG(false, #operation " did not throw " #exception_type _LOCATION, type); } catch (exception_type &e) {} } static_assert(true, "")
|
||||
#define ASSERT_TYPE_NUM_THROWS(operation, exception_type, type, num) if not consteval { try { operation; ASSERT_TYPE_NUM_MSG(false, #operation " did not throw " #exception_type _LOCATION, type, num); } catch (exception_type &e) {} } static_assert(true, "")
|
||||
#define ASSERT_TYPE_THROWS(operation, exception_type, type) ASSERT_TYPE_NUM_THROWS(operation, exception_type, type, -1ULL)
|
||||
#define ASSERT_THROWS(operation, exception_type) ASSERT_TYPE_THROWS(operation, exception_type, std::nullptr_t)
|
||||
|
||||
template<typename T>
|
||||
constexpr auto all_eq_arr_elem_test_func(T&& eq) {
|
||||
return [=] (auto&& e) constexpr { return e == eq; };
|
||||
}
|
||||
template<const char *>
|
||||
constexpr auto all_eq_arr_elem_test_func(const char* eq) {
|
||||
return [=] (auto&& e) constexpr { return std::string_view(e) == eq; };
|
||||
concept StringLike = std::is_convertible_v<T, std::string_view>;
|
||||
|
||||
template<std::input_iterator I, std::sentinel_for<I> S, StringLike T>
|
||||
constexpr bool all_eq_to(I first, S last, T t) {
|
||||
auto r1 = std::ranges::subrange(first, last);
|
||||
auto r2 = std::ranges::views::repeat(std::string_view(t), std::ranges::distance(first, last));
|
||||
return std::ranges::equal(r1, r2);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr auto all_eq_arr_arr_test_func() {
|
||||
return [] (auto&& a, auto&& b) constexpr { return a == b; };
|
||||
template<std::input_iterator I, std::sentinel_for<I> S, typename T>
|
||||
constexpr bool all_eq_to(I first, S last, T t) {
|
||||
auto r1 = std::ranges::subrange(first, last);
|
||||
auto r2 = std::ranges::views::repeat(t, std::ranges::distance(first, last));
|
||||
return std::ranges::equal(r1, r2);
|
||||
}
|
||||
template<const char *>
|
||||
constexpr auto all_eq_arr_arr_test_func() {
|
||||
return [] (auto&& a, auto&& b) constexpr { return std::string_view(a) == b; };
|
||||
|
||||
template<std::input_iterator I, std::sentinel_for<I> S, std::ranges::range R>
|
||||
requires StringLike<std::ranges::range_value_t<R>>
|
||||
constexpr bool equal_to(I first, S last, R r) {
|
||||
auto r1 = std::ranges::subrange(first, last);
|
||||
auto r2 = r | std::ranges::views::transform([](auto&& e) constexpr { return std::string_view(e); });
|
||||
return std::ranges::equal(r1, r2);
|
||||
}
|
||||
|
||||
template<std::input_iterator I, std::sentinel_for<I> S, std::ranges::range R>
|
||||
constexpr bool equal_to(I first, S last, R r) {
|
||||
return std::ranges::equal(std::ranges::subrange(first, last), r);
|
||||
}
|
||||
|
||||
template<std::input_iterator I1, std::sentinel_for<I1> S1, std::input_iterator I2>
|
||||
requires StringLike<typename std::iterator_traits<I2>::value_type>
|
||||
constexpr bool equal_to(I1 first1, S1 last1, I2 first2) {
|
||||
auto r1 = std::ranges::subrange(first1, last1);
|
||||
auto r2 = std::ranges::subrange(first2, std::next(first2, std::distance(first1, last1)))
|
||||
| std::ranges::views::transform([](auto&& e) constexpr { return std::string_view(e); });
|
||||
return std::ranges::equal(r1, r2);
|
||||
}
|
||||
|
||||
template<std::input_iterator I1, std::sentinel_for<I1> S1, std::input_iterator I2>
|
||||
constexpr bool equal_to(I1 first1, S1 last1, I2 first2) {
|
||||
auto r1 = std::ranges::subrange(first1, last1);
|
||||
auto r2 = std::ranges::subrange(first2, std::next(first2, std::distance(first1, last1)));
|
||||
return std::ranges::equal(r1, r2);
|
||||
}
|
||||
|
||||
enum class EvalFlag { RUNTIME, CONSTEVAL, RUNTIME_CONSTEVAL };
|
||||
|
|
@ -89,6 +126,7 @@ struct ret_val_s {
|
|||
ReturnCode val = ReturnCode::FAILED;
|
||||
const char *msg = "";
|
||||
const char *type_hint = nullptr;
|
||||
std::size_t param_nr = -1;
|
||||
};
|
||||
|
||||
template<std::size_t Nr>
|
||||
|
|
@ -183,6 +221,9 @@ class test_suite {
|
|||
if (ret.type_hint != nullptr) {
|
||||
std::cout << "\n\t" << "with type '" << ret.type_hint << "'";
|
||||
}
|
||||
if (ret.param_nr != -1) {
|
||||
std::cout << "\n\t" << "with parameter param_nr: " << ret.param_nr;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
ret_vals[i][0] = ret.val;
|
||||
|
|
@ -197,6 +238,9 @@ class test_suite {
|
|||
if (ret.type_hint != nullptr) {
|
||||
std::cout << "\n\t" << "with type '" << ret.type_hint << "'";
|
||||
}
|
||||
if (ret.param_nr != -1) {
|
||||
std::cout << "\n\t" << "with parameter param_nr: " << ret.param_nr;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
ret_vals[i][1] = ret.val;
|
||||
|
|
@ -292,14 +336,41 @@ constexpr auto _repeat_for_types(auto f) {
|
|||
return rets;
|
||||
}
|
||||
|
||||
template <std::size_t _N, typename ...Ts, std::size_t N = _N - 1>
|
||||
constexpr auto _repeat_for_types_n(auto f) {
|
||||
std::array rets = {
|
||||
[&]<typename T, std::size_t ...Ns>(std::index_sequence<Ns...>) constexpr {
|
||||
return std::array { f.template operator()<T, Ns+1>()... };
|
||||
}.template operator()<Ts>(std::make_index_sequence<N>())...
|
||||
};
|
||||
// Clion does not accept this as a constant expression
|
||||
// even though it compiles and works as intended
|
||||
//return rets | std::ranges::views::join;
|
||||
std::array<ret_val_s, sizeof...(Ts) * N> arr;
|
||||
auto arr_it = std::begin(arr);
|
||||
for (auto&& rp : rets) {
|
||||
for (ret_val_s& r : rp) {
|
||||
*(arr_it++) = r;
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
#define REPEAT_FOR_TYPES(func, ...) { \
|
||||
auto r = _repeat_for_types<__VA_ARGS__>(func); \
|
||||
auto it = std::ranges::find_if(r, [](auto&& e) { return e.val == ReturnCode::FAILED; }); \
|
||||
auto it = std::ranges::find_if(r, [](auto&& e) constexpr { return e.val == ReturnCode::FAILED; }); \
|
||||
if (it != std::ranges::end(r)) { \
|
||||
return *it; \
|
||||
} \
|
||||
}
|
||||
} static_assert(true, "")
|
||||
|
||||
#define REPEAT_FOR_TYPES_N(func, N, ...) { \
|
||||
auto r = _repeat_for_types_n<N, __VA_ARGS__>(func); \
|
||||
auto it = std::ranges::find_if(r, [](auto&& e) constexpr { return e.val == ReturnCode::FAILED; }); \
|
||||
if (it != std::ranges::end(r)) { \
|
||||
return *it; \
|
||||
} \
|
||||
} static_assert(true, "")
|
||||
|
||||
#define CREATE_FROM_IL(type, il, len) \
|
||||
([]<std::size_t N, typename ArgType>(std::initializer_list<ArgType> args) { \
|
||||
|
|
|
|||
|
|
@ -3,14 +3,21 @@
|
|||
#include <const_vector.hpp>
|
||||
|
||||
#include "test.hpp"
|
||||
|
||||
#include "test_args.h"
|
||||
|
||||
#define ASSERT_TYPE_ALL_VEC_EQ(vec, eq, type) ASSERT_ALL_EQ((vec).begin(), (vec).end(), eq)
|
||||
#define ASSERT_TYPE_RANGE_VEC_EQ(vec, startI, endI, eq, type) ASSERT_ALL_EQ(((vec).data() + startI), ((vec).data() + endI), eq)
|
||||
#define ASSERT_TYPE_VEC_ARR_EQ(vec, eq, type) ASSERT_C_ARR_EQ((vec).data(), (vec).data() + (vec).size(), std::begin(eq))
|
||||
#define ASSERT_TYPE_VEC_EQ(vec1, vec2, type) ASSERT_C_ARR_EQ((vec1).data(), (vec1).data() + (vec1).size(), (vec2).data())
|
||||
#define ASSERT_TYPE_RANGE_VEC_ARR_EQ(vec, startI, endI, eq, type) ASSERT_C_ARR_EQ(((vec).begin() + startI), ((vec).begin() + endI), std::begin(eq))
|
||||
#include <vector>
|
||||
|
||||
#define ASSERT_TYPE_NUM_ALL_VEC_EQ(vec, eq, type, num) ASSERT_TYPE_NUM_ALL_EQ((vec).begin(), (vec).end(), eq, type, num)
|
||||
#define ASSERT_TYPE_NUM_RANGE_VEC_EQ(vec, startI, endI, eq, type, num) ASSERT_TYPE_NUM_ALL_EQ(((vec).data() + startI), ((vec).data() + endI), eq, type, num)
|
||||
#define ASSERT_TYPE_NUM_VEC_ARR_EQ(vec, eq, type, num) ASSERT_TYPE_NUM_C_ARR_EQ((vec).data(), (vec).data() + (vec).size(), std::begin(eq), type, num)
|
||||
#define ASSERT_TYPE_NUM_VEC_EQ(vec1, vec2, type, num) ASSERT_TYPE_NUM_C_ARR_EQ((vec1).data(), (vec1).data() + (vec1).size(), (vec2).data(), type, num)
|
||||
#define ASSERT_TYPE_NUM_RANGE_VEC_ARR_EQ(vec, startI, endI, eq, type, num) ASSERT_TYPE_NUM_C_ARR_EQ(((vec).begin() + startI), ((vec).begin() + endI), std::begin(eq), type, num)
|
||||
|
||||
#define ASSERT_TYPE_ALL_VEC_EQ(vec, eq, type) ASSERT_TYPE_ALL_EQ((vec).begin(), (vec).end(), eq, type)
|
||||
#define ASSERT_TYPE_RANGE_VEC_EQ(vec, startI, endI, eq, type) ASSERT_TYPE_ALL_EQ(((vec).data() + startI), ((vec).data() + endI), eq, type)
|
||||
#define ASSERT_TYPE_VEC_ARR_EQ(vec, eq, type) ASSERT_TYPE_C_ARR_EQ((vec).data(), (vec).data() + (vec).size(), std::begin(eq), type)
|
||||
#define ASSERT_TYPE_VEC_EQ(vec1, vec2, type) ASSERT_TYPE_C_ARR_EQ((vec1).data(), (vec1).data() + (vec1).size(), (vec2).data(), type)
|
||||
#define ASSERT_TYPE_RANGE_VEC_ARR_EQ(vec, startI, endI, eq, type) ASSERT_TYPE_C_ARR_EQ(((vec).begin() + startI), ((vec).begin() + endI), std::begin(eq), type)
|
||||
|
||||
#define ASSERT_ALL_VEC_EQ(vec, eq) ASSERT_TYPE_ALL_VEC_EQ(vec, eq, std::nullptr_t)
|
||||
#define ASSERT_RANGE_VEC_EQ(vec, startI, endI, eq) ASSERT_TYPE_RANGE_VEC_EQ(vec, startI, endI, eq, std::nullptr_t)
|
||||
|
|
@ -18,6 +25,7 @@
|
|||
#define ASSERT_VEC_EQ(vec1, vec2) ASSERT_TYPE_VEC_EQ(vec1, vec2, std::nullptr_t)
|
||||
#define ASSERT_RANGE_VEC_ARR_EQ(vec, startI, endI, eq) ASSERT_TYPE_RANGE_VEC_ARR_EQ(vec, startI, endI, eq, std::nullptr_t)
|
||||
|
||||
|
||||
constexpr test_suite tests = define_tests("Tests")
|
||||
("const_vector()", []() constexpr {
|
||||
|
||||
|
|
@ -1142,10 +1150,65 @@ constexpr test_suite tests = define_tests("Tests")
|
|||
ASSERT_TYPE_ALL_VEC_EQ(v1, test_defs::get<T>::template value<1>(), T);
|
||||
|
||||
return TEST_PASS();
|
||||
}), int, char, const char*, TestStruct)
|
||||
}), int, char, const char*, TestStruct);
|
||||
|
||||
return TEST_PASS();
|
||||
}, EvalFlag::RUNTIME_CONSTEVAL)
|
||||
("const_vector::assign(InputIt first, InputIt last)", []() constexpr {
|
||||
|
||||
REPEAT_FOR_TYPES_N(([]<typename T, std::size_t N>() constexpr {
|
||||
|
||||
cc::const_vector<T, test_defs::get<T>::template arr_len<N>()> v1;
|
||||
cc::const_vector<T, test_defs::get<T>::template il_len<N>()> v2;
|
||||
cc::const_vector<T, test_defs::get<T>::template il_len<N>()> v3;
|
||||
cc::const_vector<T, test_defs::get<T>::template arr_len<N>() - 1> v4;
|
||||
|
||||
std::vector<T> container = test_defs::get<T>::template i_list<N>;
|
||||
|
||||
v1.assign(std::begin(test_defs::get<T>::template arr<N>), std::end(test_defs::get<T>::template arr<N>));
|
||||
v2.assign(container.begin(), container.end());
|
||||
v3.assign(container.begin(), std::next(container.begin(), test_defs::get<T>::template il_len<N>() / 2));
|
||||
|
||||
ASSERT_TYPE_NUM_THROWS(
|
||||
(v4.assign(std::begin(test_defs::get<T>::template arr<N>),
|
||||
std::end(test_defs::get<T>::template arr<N>))), std::invalid_argument, T, N);
|
||||
|
||||
ASSERT_TYPE_NUM_VEC_ARR_EQ(v1, test_defs::get<T>::template arr<N>, T, N);
|
||||
ASSERT_TYPE_NUM(v1.size() == test_defs::get<T>::template arr_len<N>(), T, N);
|
||||
ASSERT_TYPE_NUM_VEC_ARR_EQ(v2, container, T, N);
|
||||
ASSERT_TYPE_NUM(v2.size() == container.size(), T, N);
|
||||
ASSERT_TYPE_NUM_VEC_ARR_EQ(v3, container, T, N);
|
||||
ASSERT_TYPE_NUM(v3.size() == container.size() / 2, T, N);
|
||||
|
||||
return TEST_PASS();
|
||||
}), 3, int, char, const char *, TestStruct);
|
||||
|
||||
return TEST_PASS();
|
||||
}, EvalFlag::RUNTIME_CONSTEVAL)
|
||||
("const_vector::assign(std::initializer_list<value_type> values)", []() constexpr {
|
||||
|
||||
REPEAT_FOR_TYPES_N(([]<typename T, std::size_t N>() constexpr {
|
||||
|
||||
cc::const_vector<T, test_defs::get<T>::template il_len<N>()> v1;
|
||||
cc::const_vector<T, test_defs::get<T>::template il_len<N>() - 1> v2;
|
||||
|
||||
v1.assign(test_defs::get<T>::template i_list<N>);
|
||||
|
||||
ASSERT_TYPE_NUM_VEC_ARR_EQ(v1, test_defs::get<T>::template i_list<N>, T, N);
|
||||
ASSERT_TYPE_NUM(v1.size() == test_defs::get<T>::template il_len<N>(), T, N);
|
||||
|
||||
ASSERT_TYPE_NUM_THROWS(v2.assign(test_defs::get<T>::template i_list<N>), std::invalid_argument, T, N);
|
||||
|
||||
return TEST_PASS();
|
||||
}), 2, int, char, const char *, TestStruct);
|
||||
|
||||
return TEST_PASS();
|
||||
}, EvalFlag::RUNTIME_CONSTEVAL)
|
||||
/*("const_vector", []() constexpr {
|
||||
|
||||
|
||||
return TEST_PASS();
|
||||
}, EvalFlag::RUNTIME_CONSTEVAL)*/
|
||||
/*("const_vector(const_vector&& other)", []() constexpr {
|
||||
|
||||
return TEST_PASS();
|
||||
|
|
@ -1155,4 +1218,5 @@ constexpr test_suite tests = define_tests("Tests")
|
|||
int main() {
|
||||
return tests.run();
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
Loading…
Reference in New Issue