Compare commits
4 Commits
be204dd4fb
...
221eac7cd4
| Author | SHA1 | Date |
|---|---|---|
|
|
221eac7cd4 | |
|
|
3b11ead3f5 | |
|
|
fb22b54960 | |
|
|
fd849ecfa4 |
|
|
@ -358,7 +358,7 @@ namespace cc {
|
|||
template<typename T, std::size_t N>
|
||||
constexpr void const_vector<T, N>::assign(std::initializer_list<value_type> values)
|
||||
{
|
||||
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));
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@
|
|||
#define _EXPAND_MACRO(s) _EXPAND_STR(s)
|
||||
#define _LOCATION " (at " _EXPAND_MACRO(__FILE__) ":" _EXPAND_MACRO(__LINE__) ")"
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
consteval std::size_t c_array_len(T (&arr)[N]) { return N; }
|
||||
|
||||
#define ADD_TYPE_HINT(type) template <> constexpr const char* const to_type_hint_str::value<type> = #type
|
||||
|
||||
#define TEST_FAIL(msg) ret_val_s { "", ReturnCode::FAILED, msg }
|
||||
|
|
@ -121,10 +124,20 @@ struct quick_test_def;
|
|||
inline std::ostream& operator<<(std::ostream& os, ReturnCode rc);
|
||||
|
||||
|
||||
template<std::size_t N>
|
||||
struct tstring {
|
||||
char value[N];
|
||||
|
||||
constexpr tstring(const char (&str)[N]) { std::copy_n(str, N, value); }
|
||||
|
||||
constexpr operator const char *() { return value; }
|
||||
};
|
||||
|
||||
|
||||
struct ret_val_s {
|
||||
const char *test_name = "";
|
||||
ReturnCode val = ReturnCode::FAILED;
|
||||
const char *msg = "";
|
||||
const char *msg = nullptr;
|
||||
const char *type_hint = nullptr;
|
||||
std::size_t param_nr = -1;
|
||||
};
|
||||
|
|
@ -140,6 +153,26 @@ struct ret_val {
|
|||
constexpr inline const ret_val_s& operator[](std::size_t i) const { return vals[i]; }
|
||||
};
|
||||
|
||||
struct empty_param {};
|
||||
|
||||
struct test_params {
|
||||
template<tstring var_name>
|
||||
constexpr static auto value = empty_param{};
|
||||
};
|
||||
|
||||
template<typename T, std::size_t Nr = 0>
|
||||
struct test_context_params {
|
||||
using type = T;
|
||||
constexpr static std::size_t nr = Nr;
|
||||
|
||||
template<tstring var_name>
|
||||
constexpr static auto value = empty_param{};
|
||||
};
|
||||
|
||||
#define CONTEXT_PARAM(type, name, ...) template<> template<> constexpr type test_context_params<__VA_ARGS__>::value< #name >
|
||||
#define CONTEXT_PARAM_ARR(type, name, ...) template<> template<> constexpr type test_context_params<__VA_ARGS__>::value< #name >[]
|
||||
|
||||
|
||||
class test_definition {
|
||||
public:
|
||||
[[nodiscard]] virtual constexpr ret_val_s evaluate() const = 0;
|
||||
|
|
@ -183,6 +216,26 @@ class test_definition_impl : public test_definition {
|
|||
ret_val_s _c_res;
|
||||
};
|
||||
|
||||
class _has_been_const_evaluated_test : public test_definition {
|
||||
public:
|
||||
constexpr _has_been_const_evaluated_test()
|
||||
: _res(_name, ReturnCode::FAILED, "Could not be evaluated at compile time") {
|
||||
if consteval {
|
||||
_res = ret_val_s { _name, ReturnCode::PASSED };
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr ret_val_s evaluate() const override { return _res; }
|
||||
|
||||
[[nodiscard]] const char *name() const override { return _name; }
|
||||
[[nodiscard]] EvalFlag evalFlag() const override { return EvalFlag::CONSTEVAL; }
|
||||
[[nodiscard]] const ret_val_s &c_res() const override { return _res; }
|
||||
|
||||
private:
|
||||
const char *_name = "Constant evaluation check";
|
||||
ret_val_s _res;
|
||||
};
|
||||
|
||||
template<typename ...TestDefs>
|
||||
requires (sizeof...(TestDefs) == 0 || (std::derived_from<TestDefs, test_definition> && ...))
|
||||
class test_suite {
|
||||
|
|
@ -190,7 +243,8 @@ class test_suite {
|
|||
public:
|
||||
static constexpr std::size_t TEST_NR = sizeof...(TestDefs);
|
||||
|
||||
constexpr test_suite(const char *name, std::tuple<TestDefs...> tests) : _name(name), _tests(tests) {}
|
||||
constexpr test_suite(const char *name, std::tuple<TestDefs...> tests)
|
||||
: _name(name), _tests(tests), _c_test(_has_been_const_evaluated_test()) {}
|
||||
|
||||
int run() const {
|
||||
|
||||
|
|
@ -267,7 +321,8 @@ class test_suite {
|
|||
<< correct << "/" << num_tests << " tests evaluated correctly" << "\n"
|
||||
<< failed << "/" << num_tests << " tests failed" << "\n"
|
||||
<< full_skipped << "/" << num_tests << " tests skipped" << "\n"
|
||||
<< part_skipped << "/" << num_tests << " tests have been partially skipped" << "\n";
|
||||
<< part_skipped << "/" << num_tests << " tests have been partially skipped" << "\n"
|
||||
<< (_c_test.c_res().val == ReturnCode::PASSED ? "Results of constant evaluation are valid" : "---Results of constant evaluation are invalid---") << "\n";
|
||||
|
||||
return -failed;
|
||||
}
|
||||
|
|
@ -275,6 +330,7 @@ class test_suite {
|
|||
private:
|
||||
const char *_name;
|
||||
std::tuple<TestDefs...> _tests;
|
||||
_has_been_const_evaluated_test _c_test;
|
||||
|
||||
template<std::size_t ...Is>
|
||||
static constexpr auto expand_test_tuple(const auto &tests, std::index_sequence<Is...>) {
|
||||
|
|
@ -340,7 +396,7 @@ 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>()... };
|
||||
return std::array { f.template operator()<T, Ns, test_context_params<T, Ns>>()... };
|
||||
}.template operator()<Ts>(std::make_index_sequence<N>())...
|
||||
};
|
||||
// Clion does not accept this as a constant expression
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.26)
|
|||
set(CMAKE_CXX_STANDARD 23)
|
||||
|
||||
add_executable(test_const_vector_constructor const_vector_constructor.test.cpp
|
||||
test_args.h)
|
||||
test_args.h
|
||||
test_params.h)
|
||||
target_link_libraries(test_const_vector_constructor const_container test_common)
|
||||
add_test(NAME "const_vector constructor" COMMAND test_const_vector_constructor)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include <const_vector.hpp>
|
||||
|
||||
#include "test.hpp"
|
||||
#include "test_params.h"
|
||||
#include "test_args.h"
|
||||
|
||||
#include <vector>
|
||||
|
|
@ -1156,8 +1157,8 @@ constexpr test_suite tests = define_tests("Tests")
|
|||
}, EvalFlag::RUNTIME_CONSTEVAL)
|
||||
("const_vector::assign(InputIt first, InputIt last)", []() constexpr {
|
||||
|
||||
REPEAT_FOR_TYPES_N(([]<typename T, std::size_t N>() constexpr {
|
||||
|
||||
REPEAT_FOR_TYPES_N(([]<typename T, std::size_t n, typename params>() constexpr {
|
||||
constexpr std::size_t N = n+1;
|
||||
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;
|
||||
|
|
@ -1187,23 +1188,29 @@ constexpr test_suite tests = define_tests("Tests")
|
|||
}, EvalFlag::RUNTIME_CONSTEVAL)
|
||||
("const_vector::assign(std::initializer_list<value_type> values)", []() constexpr {
|
||||
|
||||
REPEAT_FOR_TYPES_N(([]<typename T, std::size_t N>() constexpr {
|
||||
REPEAT_FOR_TYPES_N(([]<typename T, std::size_t N, typename params>() 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;
|
||||
cc::const_vector<T, (params::template value<"ilist">).size()> v1;
|
||||
cc::const_vector<T, (params::template value<"ilist">).size() - 1> v2;
|
||||
|
||||
v1.assign(test_defs::get<T>::template i_list<N>);
|
||||
v1.assign(params::template value<"ilist">);
|
||||
|
||||
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_VEC_ARR_EQ(v1, params::template value<"ilist">, T, N);
|
||||
ASSERT_TYPE_NUM(v1.size() == params::template value<"ilist">.size(), T, N);
|
||||
|
||||
ASSERT_TYPE_NUM_THROWS(v2.assign(test_defs::get<T>::template i_list<N>), std::invalid_argument, T, N);
|
||||
ASSERT_TYPE_NUM_THROWS(v2.assign(params::template value<"ilist">), std::invalid_argument, T, N);
|
||||
|
||||
return TEST_PASS();
|
||||
}), 2, int, char, const char *, TestStruct);
|
||||
}), 2, int, char, const char *, TestObj);
|
||||
|
||||
return TEST_PASS();
|
||||
}, EvalFlag::RUNTIME_CONSTEVAL)
|
||||
|
||||
("const_vector::at(size_type pos)", []() constexpr {
|
||||
|
||||
return TEST_PASS();
|
||||
}, EvalFlag::RUNTIME_CONSTEVAL)
|
||||
|
||||
/*("const_vector", []() constexpr {
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
#ifndef CONST_CONTAINER_TEST_ARGS_H
|
||||
#define CONST_CONTAINER_TEST_ARGS_H
|
||||
|
||||
#include "test.hpp"
|
||||
|
||||
#define GEN_TEST_OBJ_FROM_ARR(nr, i) TestObj(test_context_params<int, nr>::value<"arr">[i], test_context_params<char, nr>::value<"arr">[i], test_context_params<const char *, nr>::value<"arr">[i])
|
||||
|
||||
struct TestObj {
|
||||
int x = 0;
|
||||
char c = 0;
|
||||
const char * s = "This is a string";
|
||||
|
||||
constexpr bool operator==(const TestObj &other) const { return x == other.x && c == other.c && std::string_view(s) == other.s; }
|
||||
};
|
||||
ADD_TYPE_HINT(TestObj);
|
||||
|
||||
template<> template<> constexpr int test_context_params<int, 0>::value<"arr">[] = { 1, 2, 3, 4 };
|
||||
template<> template<> constexpr int test_context_params<int, 1>::value<"arr">[] = { 5, 6, 7, 8, 9, 10, 11, 12 };
|
||||
template<> template<> constexpr char test_context_params<char, 0>::value<"arr">[] = { 'a', 'B', 'c', 'D' };
|
||||
template<> template<> constexpr char test_context_params<char, 1>::value<"arr">[] = { 'e', 'F', 'g', 'H', 'i', 'J', '\n', '\0' };
|
||||
template<> template<> constexpr const char * test_context_params<const char *, 0>::value<"arr">[] = { "Lorem", "ipsum", "dolor", "sit" };
|
||||
template<> template<> constexpr const char * test_context_params<const char *, 1>::value<"arr">[] = { "amet", "consetetur", "sadipscing", "elitr", "sed", "diam", "nonumy", "eirmod", "tempor", "\0" };
|
||||
template<> template<> constexpr TestObj test_context_params<TestObj, 0>::value<"arr">[] = {
|
||||
GEN_TEST_OBJ_FROM_ARR(0, 0),
|
||||
GEN_TEST_OBJ_FROM_ARR(0, 1),
|
||||
GEN_TEST_OBJ_FROM_ARR(0, 2),
|
||||
GEN_TEST_OBJ_FROM_ARR(0, 3) };
|
||||
template<> template<> constexpr TestObj test_context_params<TestObj, 1>::value<"arr">[] = {
|
||||
GEN_TEST_OBJ_FROM_ARR(1, 0),
|
||||
GEN_TEST_OBJ_FROM_ARR(1, 1),
|
||||
GEN_TEST_OBJ_FROM_ARR(1, 2),
|
||||
GEN_TEST_OBJ_FROM_ARR(1, 3),
|
||||
GEN_TEST_OBJ_FROM_ARR(1, 4),
|
||||
GEN_TEST_OBJ_FROM_ARR(1, 5),
|
||||
GEN_TEST_OBJ_FROM_ARR(1, 6),
|
||||
GEN_TEST_OBJ_FROM_ARR(1, 7) };
|
||||
|
||||
template<> template<> constexpr std::initializer_list<int> test_context_params<int, 0>::value<"ilist"> = { 1, 2, 3, 4 };
|
||||
template<> template<> constexpr std::initializer_list<int> test_context_params<int, 1>::value<"ilist"> = { 5, 6, 7, 8, 9, 10, 11, 12 };
|
||||
template<> template<> constexpr std::initializer_list<char> test_context_params<char, 0>::value<"ilist"> = { 'a', 'B', 'c', 'D' };
|
||||
template<> template<> constexpr std::initializer_list<char> test_context_params<char, 1>::value<"ilist"> = { 'e', 'F', 'g', 'H', 'i', 'J', '\n', '\0' };
|
||||
template<> template<> constexpr std::initializer_list<const char *> test_context_params<const char *, 0>::value<"ilist"> = { "Lorem", "ipsum", "dolor", "sit" };
|
||||
template<> template<> constexpr std::initializer_list<const char *> test_context_params<const char *, 1>::value<"ilist"> = { "amet", "consetetur", "sadipscing", "elitr", "sed", "diam", "nonumy", "eirmod", "tempor", "\0" };
|
||||
template<> template<> constexpr std::initializer_list<TestObj> test_context_params<TestObj, 0>::value<"ilist"> = {
|
||||
GEN_TEST_OBJ_FROM_ARR(0, 0),
|
||||
GEN_TEST_OBJ_FROM_ARR(0, 1),
|
||||
GEN_TEST_OBJ_FROM_ARR(0, 2),
|
||||
GEN_TEST_OBJ_FROM_ARR(0, 3) };
|
||||
template<> template<> constexpr std::initializer_list<TestObj> test_context_params<TestObj, 1>::value<"ilist"> = {
|
||||
GEN_TEST_OBJ_FROM_ARR(1, 0),
|
||||
GEN_TEST_OBJ_FROM_ARR(1, 1),
|
||||
GEN_TEST_OBJ_FROM_ARR(1, 2),
|
||||
GEN_TEST_OBJ_FROM_ARR(1, 3),
|
||||
GEN_TEST_OBJ_FROM_ARR(1, 4),
|
||||
GEN_TEST_OBJ_FROM_ARR(1, 5),
|
||||
GEN_TEST_OBJ_FROM_ARR(1, 6),
|
||||
GEN_TEST_OBJ_FROM_ARR(1, 7) };
|
||||
|
||||
template<> template<> constexpr std::size_t test_context_params<int, 1>::value<"capacity"> = 10;
|
||||
template<> template<> constexpr std::size_t test_context_params<char, 1>::value<"capacity"> = 10;
|
||||
template<> template<> constexpr std::size_t test_context_params<const char *, 1>::value<"capacity"> = 10;
|
||||
template<> template<> constexpr std::size_t test_context_params<TestObj, 1>::value<"capacity"> = 10;
|
||||
template<> template<> constexpr std::size_t test_context_params<int, 2>::value<"capacity"> = 200;
|
||||
template<> template<> constexpr std::size_t test_context_params<char, 2>::value<"capacity"> = 200;
|
||||
template<> template<> constexpr std::size_t test_context_params<const char *, 2>::value<"capacity"> = 200;
|
||||
template<> template<> constexpr std::size_t test_context_params<TestObj, 2>::value<"capacity"> = 200;
|
||||
|
||||
template<> template<> constexpr std::size_t test_context_params<int, 0>::value<"size"> = 25;
|
||||
template<> template<> constexpr std::size_t test_context_params<char, 0>::value<"size"> = 25;
|
||||
template<> template<> constexpr std::size_t test_context_params<const char *, 0>::value<"size"> = 25;
|
||||
template<> template<> constexpr std::size_t test_context_params<TestObj, 0>::value<"size"> = 25;
|
||||
template<> template<> constexpr std::size_t test_context_params<int, 1>::value<"size"> = 50;
|
||||
template<> template<> constexpr std::size_t test_context_params<char, 1>::value<"size"> = 50;
|
||||
template<> template<> constexpr std::size_t test_context_params<const char *, 1>::value<"size"> = 50;
|
||||
template<> template<> constexpr std::size_t test_context_params<TestObj, 1>::value<"size"> = 50;
|
||||
|
||||
template<> template<> constexpr int test_context_params<int, 0>::value<"value"> = 5;
|
||||
template<> template<> constexpr int test_context_params<int, 1>::value<"value"> = INT_MIN;
|
||||
template<> template<> constexpr char test_context_params<char, 0>::value<"value"> = 'P';
|
||||
template<> template<> constexpr char test_context_params<char, 1>::value<"value"> = CHAR_MAX;
|
||||
template<> template<> constexpr const char * test_context_params<const char *, 0>::value<"value"> = "Test string 1";
|
||||
template<> template<> constexpr const char * test_context_params<const char *, 1>::value<"value"> = "Test string 2";
|
||||
template<> template<> constexpr TestObj test_context_params<TestObj, 0>::value<"value"> = TestObj(5, 'P', "Object String 1");
|
||||
template<> template<> constexpr TestObj test_context_params<TestObj, 1>::value<"value"> = TestObj(INT_MAX, 'p', "2 Object String");
|
||||
|
||||
#endif //CONST_CONTAINER_TEST_ARGS_H
|
||||
Loading…
Reference in New Issue