Skip to content

Commit

Permalink
test(core): cover ArrayTrait
Browse files Browse the repository at this point in the history
  • Loading branch information
RiscadoA committed Sep 19, 2023
1 parent fd352f5 commit 0eb9b1e
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 0 deletions.
1 change: 1 addition & 0 deletions core/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ add_executable(
reflection/type.cpp
reflection/traits/constructible.cpp
reflection/external/primitives.cpp
reflection/external/vector.cpp

data/fs/embedded_archive.cpp
data/fs/standard_archive.cpp
Expand Down
22 changes: 22 additions & 0 deletions core/tests/reflection/external/vector.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <doctest/doctest.h>

#include <cubos/core/reflection/external/primitives.hpp>
#include <cubos/core/reflection/external/vector.hpp>

#include "../traits/array.hpp"
#include "../traits/constructible.hpp"

template <typename T>
static void test(const char* name, std::vector<T> vec, T inserted)
{
CHECK(reflect<std::vector<T>>().name() == name);
testArray<std::vector<T>, T>(vec, vec.size(), &inserted);
testConstructible<std::vector<T>>(&vec);
}

TEST_CASE("reflection::reflect<std::vector<T>>()")
{
test<int32_t>("std::vector<int32_t>", {5, 4, 1}, 1);
test<std::vector<std::vector<char>>>("std::vector<std::vector<std::vector<char>>>", {{{'H'}, {'e'}}, {{'y', '!'}}},
{{'o'}});
}
87 changes: 87 additions & 0 deletions core/tests/reflection/traits/array.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#include <doctest/doctest.h>

#include <cubos/core/reflection/external/primitives.hpp>
#include <cubos/core/reflection/traits/array.hpp>
#include <cubos/core/reflection/type.hpp>

#include "../../utils.hpp"

using cubos::core::reflection::ArrayTrait;
using cubos::core::reflection::reflect;

TEST_CASE("reflection::ArrayTrait")
{
auto trait = ArrayTrait(
reflect<int>(), [](const void*) -> std::size_t { return 2; },
[](const void* array, std::size_t index) { return reinterpret_cast<uintptr_t>(array) + sizeof(int) * index; });

SUBCASE("without any resizing operations")
{
int instance[2];
CHECK(trait.elementType().is<int>());
CHECK(trait.length(&instance) == 2);
CHECK(trait.get(&instance, 0) == &instance[0]);
CHECK(trait.get(static_cast<const void*>(&instance), 1) == &instance[1]);

// No insert or erase operations were provided
CHECK_FALSE(trait.hasInsertDefault());
CHECK_FALSE(trait.hasInsertCopy());
CHECK_FALSE(trait.hasInsertMove());
CHECK_FALSE(trait.hasErase());
CHECK_FALSE(trait.insertDefault(&instance, 0));
CHECK_FALSE(trait.insertCopy(&instance, 0, &instance[1]));
CHECK_FALSE(trait.insertMove(&instance, 0, &instance[1]));
CHECK_FALSE(trait.erase(&instance, 0));
}

// These subcases below are not really inserting or erasing anything, but they are testing that
// the insert and erase methods are called correctly.

SUBCASE("with default-constructing inserts")
{
trait.insertDefault([](void* array, std::size_t index) { static_cast<int*>(array)[index] = 42; });

int instance[2] = {1, 2};
CHECK(trait.hasInsertDefault());
CHECK(trait.insertDefault(&instance, 0));
CHECK(instance[0] == 42);
CHECK(instance[1] == 2);
}

SUBCASE("with copy-constructing inserts")
{
trait.insertCopy([](void* array, std::size_t index, const void* value) {
static_cast<int*>(array)[index] = *static_cast<const int*>(value);
});

int instance[2] = {1, 2};
CHECK(trait.hasInsertCopy());
CHECK(trait.insertCopy(&instance, 0, &instance[1]));
CHECK(instance[0] == 2);
CHECK(instance[1] == 2);
}

SUBCASE("with move-constructing inserts")
{
trait.insertMove([](void* array, std::size_t index, void* value) {
static_cast<int*>(array)[index] = *static_cast<int*>(value);
});

int instance[2] = {1, 2};
CHECK(trait.hasInsertMove());
CHECK(trait.insertMove(&instance, 1, &instance[0]));
CHECK(instance[0] == 1);
CHECK(instance[1] == 1);
}

SUBCASE("with erases")
{
trait.erase([](void* array, std::size_t index) { static_cast<int*>(array)[index] = 0; });

int instance[2] = {1, 2};
CHECK(trait.hasErase());
CHECK(trait.erase(&instance, 1));
CHECK(instance[0] == 1);
CHECK(instance[1] == 0);
}
}
73 changes: 73 additions & 0 deletions core/tests/reflection/traits/array.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include <concepts>

#include <doctest/doctest.h>

#include <cubos/core/reflection/traits/array.hpp>
#include <cubos/core/reflection/type.hpp>

using cubos::core::reflection::ArrayTrait;
using cubos::core::reflection::reflect;
using cubos::core::reflection::Type;

/// @brief Checks if a type's ArrayTrait works as expected.
/// @tparam T Type.
/// @tparam E Element type.
/// @param value Value to test.
/// @param length Initial length.
/// @param inserted Optional value to insert.
template <typename T, typename E>
void testArray(T& value, std::size_t length, E* inserted = nullptr)
{
const Type& type = reflect<T>();
REQUIRE(type.has<ArrayTrait>());
const ArrayTrait& trait = type.get<ArrayTrait>();

REQUIRE(trait.length(&value) == length);
REQUIRE(trait.elementType().is<E>());

if (trait.hasInsertDefault())
{
trait.insertDefault(&value, length);
CHECK(trait.length(&value) == length + 1);
trait.insertDefault(&value, 0);
CHECK(trait.length(&value) == length + 2);
length += 2;

if constexpr (std::equality_comparable<E> && std::default_initializable<E>)
{
CHECK(*reinterpret_cast<E*>(trait.get(&value, 0)) == E{});
CHECK(*reinterpret_cast<const E*>(trait.get(static_cast<const void*>(&value), length - 1)) == E{});
}
}

if (trait.hasErase())
{
for (; length > 0; --length)
{
trait.erase(&value, length - 1);
CHECK(trait.length(&value) == length - 1);
}
}

if (inserted)
{
if (trait.hasInsertCopy())
{
trait.insertCopy(&value, 0, inserted);
CHECK(trait.length(&value) == length + 1);
length += 1;

if constexpr (std::equality_comparable<E>)
{
CHECK(*reinterpret_cast<E*>(trait.get(&value, 0)) == *inserted);
}
}

if (trait.hasInsertMove())
{
trait.insertMove(&value, (length + 1) / 2, inserted);
CHECK(trait.length(&value) == length + 1);
length += 1;
}
}
}

0 comments on commit 0eb9b1e

Please sign in to comment.