Split engine to packages NazaraUtils and NZSL (#375)
* Move code to NazaraUtils and NZSL packages
* Reorder includes
* Tests: Remove glslang and spirv-tools deps
* Tests: Remove glslang init
* Remove NazaraUtils tests and fix Vector4Test
* Fix Linux compilation
* Update msys2-build.yml
* Fix assimp package
* Update xmake.lua
* Update xmake.lua
* Fix shader compilation on MinGW
* Final fixes
* The final fix 2: the fix strikes back!
* Disable cache on CI
* The return of the fix™️
This commit is contained in:
@@ -9,31 +9,6 @@
|
||||
|
||||
std::filesystem::path GetResourceDir();
|
||||
|
||||
TEST_CASE("Apply", "[CORE][ALGORITHM]")
|
||||
{
|
||||
SECTION("Apply lambda to two vector2")
|
||||
{
|
||||
Nz::Vector2<int> vector = Nz::Vector2<int>::Unit();
|
||||
auto lambda = [](const Nz::Vector2<int>& vec1, const Nz::Vector2<int>& vec2)
|
||||
{
|
||||
return vec1 + vec2;
|
||||
};
|
||||
|
||||
Nz::Vector2<int> result = Nz::Apply(lambda, std::make_tuple(vector, vector));
|
||||
|
||||
REQUIRE(result == (Nz::Vector2<int>::Unit() * 2));
|
||||
}
|
||||
|
||||
/*SECTION("Apply member function to vector2")
|
||||
{
|
||||
Nz::Vector2<int> vector = Nz::Vector2<int>::Unit();
|
||||
|
||||
int result = Nz::Apply(vector, (int(Nz::Vector2<int>::*)(const Nz::Vector2<int>&)) &Nz::Vector2<int>::Distance<int>, std::make_tuple(vector));
|
||||
|
||||
REQUIRE(result == 0);
|
||||
}*/
|
||||
}
|
||||
|
||||
TEST_CASE("ComputeHash", "[CORE][ALGORITHM]")
|
||||
{
|
||||
std::filesystem::path testFilePath = GetResourceDir() / "Logo.png";
|
||||
|
||||
@@ -1,372 +0,0 @@
|
||||
#include <Nazara/Core/Algorithm.hpp>
|
||||
#include <Nazara/Core/Bitset.hpp>
|
||||
#include <catch2/catch.hpp>
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
template<typename Block> void Check(const char* title);
|
||||
template<typename Block> void CheckAppend(const char* title);
|
||||
template<typename Block> void CheckBitOps(const char* title);
|
||||
template<typename Block> void CheckBitOpsMultipleBlocks(const char* title);
|
||||
template<typename Block> void CheckConstructor(const char* title);
|
||||
template<typename Block> void CheckCopyMoveSwap(const char* title);
|
||||
template<typename Block> void CheckRead(const char* title);
|
||||
template<typename Block> void CheckReverse(const char* title);
|
||||
|
||||
SCENARIO("Bitset", "[CORE][BITSET]")
|
||||
{
|
||||
Check<Nz::UInt8>("Bitset made of 8bits blocks");
|
||||
Check<Nz::UInt16>("Bitset made of 16bits blocks");
|
||||
Check<Nz::UInt32>("Bitset made of 32bits blocks");
|
||||
Check<Nz::UInt64>("Bitset made of 64bits blocks");
|
||||
}
|
||||
|
||||
template<typename Block>
|
||||
void Check(const char* title)
|
||||
{
|
||||
CheckConstructor<Block>(title);
|
||||
CheckCopyMoveSwap<Block>(title);
|
||||
|
||||
CheckBitOps<Block>(title);
|
||||
CheckBitOpsMultipleBlocks<Block>(title);
|
||||
|
||||
CheckAppend<Block>(title);
|
||||
CheckRead<Block>(title);
|
||||
CheckReverse<Block>(title);
|
||||
}
|
||||
|
||||
template<typename Block>
|
||||
void CheckAppend(const char* title)
|
||||
{
|
||||
SECTION(title)
|
||||
{
|
||||
GIVEN("An empty bitset filled by bytes")
|
||||
{
|
||||
#define BitVal1 00110111
|
||||
#define BitVal2 11011110
|
||||
#define BitVal3 01000010
|
||||
std::array<Nz::UInt8, 3> data = {{NazaraPrefixMacro(BitVal1, 0b), NazaraPrefixMacro(BitVal2, 0b), NazaraPrefixMacro(BitVal3, 0b)}};
|
||||
const char result[] = NazaraStringifyMacro(BitVal3) NazaraStringifyMacro(BitVal2) NazaraStringifyMacro(BitVal1);
|
||||
std::size_t bitCount = data.size() * 8;
|
||||
#undef BitVal1
|
||||
#undef BitVal2
|
||||
#undef BitVal3
|
||||
|
||||
std::array<std::pair<const char*, std::size_t>, 7> tests = {
|
||||
{
|
||||
{"We append bits one by one", 1},
|
||||
{"We append bits two by two", 2},
|
||||
{"We append bits three by three", 3},
|
||||
{"We append bits four by four", 4},
|
||||
{"We append bits six by six", 6},
|
||||
{"We append bits byte by byte", 8},
|
||||
{"We append bits twelve by twelve", 12}
|
||||
}
|
||||
};
|
||||
|
||||
for (auto& pair : tests)
|
||||
{
|
||||
WHEN(pair.first)
|
||||
{
|
||||
Nz::Bitset<Block> bitset;
|
||||
|
||||
for (std::size_t i = 0; i < bitCount; i += pair.second)
|
||||
{
|
||||
Nz::UInt16 value = data[i / 8] >> (i % 8);
|
||||
if ((i % 8) + pair.second > 8 && i/8 != data.size()-1)
|
||||
value |= static_cast<Nz::UInt16>(data[i / 8 + 1]) << (8 - (i % 8));
|
||||
|
||||
bitset.AppendBits(value, pair.second);
|
||||
}
|
||||
|
||||
REQUIRE(bitset.GetSize() == bitCount);
|
||||
|
||||
Nz::Bitset<Block> expectedBitset(result);
|
||||
|
||||
CHECK(bitset == expectedBitset);
|
||||
CHECK(bitset.GetBlockCount() == (bitCount / bitset.bitsPerBlock + std::min<std::size_t>(1, bitCount % bitset.bitsPerBlock)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Block>
|
||||
void CheckBitOps(const char* title)
|
||||
{
|
||||
SECTION(title)
|
||||
{
|
||||
GIVEN("Two bitsets")
|
||||
{
|
||||
Nz::Bitset<Block> first("01001");
|
||||
Nz::Bitset<Block> second("10111");
|
||||
|
||||
WHEN("We perform operators")
|
||||
{
|
||||
Nz::Bitset<Block> andBitset = first & second;
|
||||
Nz::Bitset<Block> orBitset = first | second;
|
||||
Nz::Bitset<Block> xorBitset = first ^ second;
|
||||
|
||||
THEN("They should operate as logical operators")
|
||||
{
|
||||
CHECK(andBitset == Nz::Bitset<Block>("00001"));
|
||||
CHECK(orBitset == Nz::Bitset<Block>("11111"));
|
||||
CHECK(orBitset.TestAll());
|
||||
CHECK(xorBitset == Nz::Bitset<Block>("11110"));
|
||||
CHECK(!xorBitset.TestAll());
|
||||
CHECK((~orBitset).TestNone());
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("We perform bit shifts")
|
||||
{
|
||||
first.ShiftLeft(1);
|
||||
second.ShiftRight(2);
|
||||
|
||||
THEN("We should obtain these")
|
||||
{
|
||||
CHECK(first == Nz::Bitset<Block>("10010"));
|
||||
CHECK(second == Nz::Bitset<Block>("101"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Block>
|
||||
void CheckBitOpsMultipleBlocks(const char* title)
|
||||
{
|
||||
SECTION(title)
|
||||
{
|
||||
GIVEN("Two bitsets")
|
||||
{
|
||||
Nz::Bitset<Block> first("01001011010010101001010011010101001");
|
||||
Nz::Bitset<Block> second("10111111101101110110111101101110110");
|
||||
|
||||
WHEN("We perform operators")
|
||||
{
|
||||
Nz::Bitset<Block> andBitset = first & second;
|
||||
Nz::Bitset<Block> orBitset = first | second;
|
||||
Nz::Bitset<Block> xorBitset = first ^ second;
|
||||
|
||||
THEN("They should operate as logical operators")
|
||||
{
|
||||
CHECK(andBitset == Nz::Bitset<Block>("00001011000000100000010001000100000"));
|
||||
CHECK(orBitset == Nz::Bitset<Block>("11111111111111111111111111111111111"));
|
||||
CHECK(orBitset.TestAll());
|
||||
CHECK(xorBitset == Nz::Bitset<Block>("11110100111111011111101110111011111"));
|
||||
CHECK(!xorBitset.TestAll());
|
||||
CHECK((~orBitset).TestNone());
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("We perform bit shifts")
|
||||
{
|
||||
first.ShiftLeft(16);
|
||||
second.ShiftRight(16);
|
||||
|
||||
THEN("We should obtain these")
|
||||
{
|
||||
CHECK(first == Nz::Bitset<Block>("10010100110101010010000000000000000"));
|
||||
first.ShiftLeft(1);
|
||||
CHECK(first == Nz::Bitset<Block>("00101001101010100100000000000000000"));
|
||||
CHECK(second == Nz::Bitset<Block>("1011111110110111011"));
|
||||
second.ShiftRight(1);
|
||||
CHECK(second == Nz::Bitset<Block>("101111111011011101"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Block>
|
||||
void CheckConstructor(const char* title)
|
||||
{
|
||||
SECTION(title)
|
||||
{
|
||||
GIVEN("Allocate and constructor")
|
||||
{
|
||||
Nz::Bitset<Block> bitset(3, false);
|
||||
|
||||
THEN("Capacity is 3 and size is 3")
|
||||
{
|
||||
CHECK(bitset.GetSize() == 3);
|
||||
CHECK(bitset.GetCapacity() >= 3);
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("Iterator and default constructor")
|
||||
{
|
||||
std::string anotherDataString("0101");
|
||||
Nz::Bitset<Block> defaultByte;
|
||||
Nz::Bitset<Block> anotherData(anotherDataString.c_str());
|
||||
|
||||
WHEN("We assign 'anotherData'")
|
||||
{
|
||||
defaultByte = anotherDataString;
|
||||
CHECK(anotherData == defaultByte);
|
||||
CHECK(defaultByte.GetSize() == 4);
|
||||
CHECK(defaultByte.GetCapacity() >= 4);
|
||||
CHECK(anotherData.GetSize() == 4);
|
||||
CHECK(anotherData.GetCapacity() >= 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Block>
|
||||
void CheckCopyMoveSwap(const char* title)
|
||||
{
|
||||
SECTION(title)
|
||||
{
|
||||
GIVEN("Copy and Move constructor")
|
||||
{
|
||||
Nz::Bitset<Block> originalArray(3, true);
|
||||
|
||||
WHEN("We copy")
|
||||
{
|
||||
Nz::Bitset<Block> copyBitset(originalArray);
|
||||
|
||||
THEN("We get a copy")
|
||||
{
|
||||
CHECK(copyBitset == originalArray);
|
||||
|
||||
AND_WHEN("We modify one")
|
||||
{
|
||||
for (std::size_t i = 0; i < copyBitset.GetSize(); ++i)
|
||||
copyBitset[i] = false;
|
||||
|
||||
THEN("They are no more equal")
|
||||
{
|
||||
CHECK(copyBitset != originalArray);
|
||||
CHECK(copyBitset == Nz::Bitset<Block>(3, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("We move")
|
||||
{
|
||||
Nz::Bitset<Block> moveBitset(std::move(originalArray));
|
||||
|
||||
THEN("These results are expected")
|
||||
{
|
||||
CHECK(moveBitset == Nz::Bitset<Block>(3, true));
|
||||
CHECK(originalArray.GetCapacity() == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("Three bitsets")
|
||||
{
|
||||
Nz::Bitset<Block> first("01001");
|
||||
Nz::Bitset<Block> second("10110");
|
||||
Nz::Bitset<Block> third;
|
||||
|
||||
WHEN("We swap first and third, then second and third and finally third and first")
|
||||
{
|
||||
Nz::Bitset<Block> oldFirst(first);
|
||||
Nz::Bitset<Block> oldSecond(second);
|
||||
|
||||
first.Swap(third);
|
||||
std::swap(second, third);
|
||||
third.Swap(first);
|
||||
|
||||
THEN("First and second have been swapped and third is still empty.")
|
||||
{
|
||||
CHECK(oldFirst == second);
|
||||
CHECK(oldSecond == first);
|
||||
CHECK(third.GetSize() == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Block>
|
||||
void CheckRead(const char* title)
|
||||
{
|
||||
SECTION(title)
|
||||
{
|
||||
GIVEN("An empty bitset filled by reading")
|
||||
{
|
||||
#define BitVal1 10010101
|
||||
#define BitVal2 11010010
|
||||
#define BitVal3 01101010
|
||||
std::array<Nz::UInt8, 3> data = {{NazaraPrefixMacro(BitVal1, 0b), NazaraPrefixMacro(BitVal2, 0b), NazaraPrefixMacro(BitVal3, 0b)}};
|
||||
const char result[] = NazaraStringifyMacro(BitVal3) NazaraStringifyMacro(BitVal2) NazaraStringifyMacro(BitVal1);
|
||||
std::size_t bitCount = data.size() * 8;
|
||||
#undef BitVal1
|
||||
#undef BitVal2
|
||||
#undef BitVal3
|
||||
|
||||
std::array<std::pair<const char*, std::size_t>, 8> tests = {
|
||||
{
|
||||
{"We read bits one by one", 1},
|
||||
{"We read bits two by two", 2},
|
||||
{"We read bits three by three", 3},
|
||||
{"We read bits four by four", 4},
|
||||
{"We read bits six by six", 6},
|
||||
{"We read bits byte by byte", 8},
|
||||
{"We read bits twelve by twelve", 12},
|
||||
{"We read bits all at once", 24}
|
||||
}
|
||||
};
|
||||
|
||||
for (auto& pair : tests)
|
||||
{
|
||||
WHEN(pair.first)
|
||||
{
|
||||
Nz::Bitset<Block> bitset;
|
||||
|
||||
auto seq = bitset.Write(data.data(), pair.second);
|
||||
for (std::size_t i = pair.second; i < bitCount; i += pair.second)
|
||||
seq = bitset.Write(seq, pair.second);
|
||||
|
||||
REQUIRE(bitset.GetSize() == bitCount);
|
||||
|
||||
Nz::Bitset<Block> expectedBitset(result);
|
||||
|
||||
CHECK(bitset == expectedBitset);
|
||||
CHECK(bitset.GetBlockCount() == (bitCount / bitset.bitsPerBlock + std::min<std::size_t>(1, bitCount % bitset.bitsPerBlock)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Block>
|
||||
void CheckReverse(const char* title)
|
||||
{
|
||||
SECTION(title)
|
||||
{
|
||||
GIVEN("A bitset")
|
||||
{
|
||||
std::string bits = "010011100010001101001111";
|
||||
Nz::Bitset<Block> expected(bits);
|
||||
|
||||
WHEN("We reverse the order of bits")
|
||||
{
|
||||
Nz::Bitset<Block> bitset(bits);
|
||||
bitset.Reverse();
|
||||
|
||||
THEN("The order of bits should be reversed")
|
||||
{
|
||||
std::string reversedBits = bits;
|
||||
std::reverse(reversedBits.begin(), reversedBits.end());
|
||||
CHECK(bitset == Nz::Bitset<Block>(reversedBits));
|
||||
}
|
||||
AND_WHEN("We reverse the bit order again")
|
||||
{
|
||||
bitset.Reverse();
|
||||
|
||||
THEN("It should be back to normal")
|
||||
{
|
||||
CHECK(bitset == expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
#include <Nazara/Core/MemoryPool.hpp>
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <Nazara/Math/Vector2.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
std::size_t allocationCount = 0;
|
||||
|
||||
template<typename T>
|
||||
struct AllocatorTest : T
|
||||
{
|
||||
template<typename... Args>
|
||||
AllocatorTest(Args&&... args) :
|
||||
T(std::forward<Args>(args)...)
|
||||
{
|
||||
allocationCount++;
|
||||
}
|
||||
|
||||
AllocatorTest(const AllocatorTest&) = delete;
|
||||
AllocatorTest(AllocatorTest&&) = delete;
|
||||
|
||||
~AllocatorTest()
|
||||
{
|
||||
assert(allocationCount > 0);
|
||||
allocationCount--;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
SCENARIO("MemoryPool", "[CORE][MEMORYPOOL]")
|
||||
{
|
||||
GIVEN("A MemoryPool to contain one Nz::Vector2<int>")
|
||||
{
|
||||
using T = AllocatorTest<Nz::Vector2<int>>;
|
||||
|
||||
allocationCount = 0;
|
||||
|
||||
Nz::MemoryPool<T> memoryPool(2);
|
||||
CHECK(memoryPool.GetAllocatedEntryCount() == 0);
|
||||
CHECK(memoryPool.GetBlockCount() == 1);
|
||||
CHECK(memoryPool.GetBlockSize() == 2);
|
||||
CHECK(memoryPool.GetFreeEntryCount() == 2);
|
||||
CHECK(allocationCount == 0);
|
||||
|
||||
WHEN("We construct a Nz::Vector2<int>")
|
||||
{
|
||||
std::size_t index;
|
||||
T* vector2 = memoryPool.Allocate(index, 1, 2);
|
||||
CHECK(allocationCount == 1);
|
||||
CHECK(memoryPool.GetAllocatedEntryCount() == 1);
|
||||
CHECK(memoryPool.GetFreeEntryCount() == 1);
|
||||
CHECK(memoryPool.RetrieveEntryIndex(vector2) == index);
|
||||
|
||||
THEN("Memory is available")
|
||||
{
|
||||
vector2->x = 3;
|
||||
REQUIRE(*vector2 == Nz::Vector2<int>(3, 2));
|
||||
}
|
||||
|
||||
memoryPool.Free(index);
|
||||
CHECK(allocationCount == 0);
|
||||
CHECK(memoryPool.GetAllocatedEntryCount() == 0);
|
||||
CHECK(memoryPool.GetFreeEntryCount() == 2);
|
||||
}
|
||||
|
||||
WHEN("We construct three vectors")
|
||||
{
|
||||
CHECK(memoryPool.GetAllocatedEntryCount() == 0);
|
||||
CHECK(memoryPool.GetFreeEntryCount() == 2);
|
||||
|
||||
std::size_t index1, index2, index3;
|
||||
T* vector1 = memoryPool.Allocate(index1, 1, 2);
|
||||
CHECK(allocationCount == 1);
|
||||
CHECK(memoryPool.GetAllocatedEntryCount() == 1);
|
||||
CHECK(memoryPool.GetBlockCount() == 1);
|
||||
CHECK(memoryPool.GetFreeEntryCount() == 1);
|
||||
T* vector2 = memoryPool.Allocate(index2, 3, 4);
|
||||
CHECK(allocationCount == 2);
|
||||
CHECK(memoryPool.GetAllocatedEntryCount() == 2);
|
||||
CHECK(memoryPool.GetBlockCount() == 1);
|
||||
CHECK(memoryPool.GetFreeEntryCount() == 0);
|
||||
T* vector3 = memoryPool.Allocate(index3, 5, 6);
|
||||
CHECK(allocationCount == 3);
|
||||
CHECK(memoryPool.GetAllocatedEntryCount() == 3);
|
||||
CHECK(memoryPool.GetBlockCount() == 2);
|
||||
CHECK(memoryPool.GetFreeEntryCount() == 1); //< a new block has been allocated
|
||||
|
||||
CHECK(memoryPool.RetrieveEntryIndex(vector1) == index1);
|
||||
CHECK(memoryPool.RetrieveEntryIndex(vector2) == index2);
|
||||
CHECK(memoryPool.RetrieveEntryIndex(vector3) == index3);
|
||||
|
||||
THEN("Memory is available")
|
||||
{
|
||||
vector1->x = 3;
|
||||
vector2->y = 5;
|
||||
CHECK(*vector1 == Nz::Vector2<int>(3, 2));
|
||||
CHECK(*vector2 == Nz::Vector2<int>(3, 5));
|
||||
CHECK(vector3->GetSquaredLength() == Approx(61.f));
|
||||
|
||||
AND_THEN("We iterate on the memory pool")
|
||||
{
|
||||
std::size_t count = 0;
|
||||
int sumX = 0;
|
||||
int sumY = 0;
|
||||
for (T& vec : memoryPool)
|
||||
{
|
||||
count++;
|
||||
sumX += vec.x;
|
||||
sumY += vec.y;
|
||||
}
|
||||
|
||||
CHECK(count == 3);
|
||||
CHECK(sumX == 11);
|
||||
CHECK(sumY == 13);
|
||||
}
|
||||
}
|
||||
|
||||
memoryPool.Reset();
|
||||
CHECK(allocationCount == 0);
|
||||
CHECK(memoryPool.GetAllocatedEntryCount() == 0);
|
||||
CHECK(memoryPool.GetBlockCount() == 2);
|
||||
CHECK(memoryPool.GetFreeEntryCount() == 4);
|
||||
|
||||
bool failure = false;
|
||||
for (T& vec : memoryPool)
|
||||
{
|
||||
NazaraUnused(vec);
|
||||
failure = true;
|
||||
}
|
||||
|
||||
CHECK_FALSE(failure);
|
||||
|
||||
memoryPool.Clear();
|
||||
CHECK(allocationCount == 0);
|
||||
CHECK(memoryPool.GetAllocatedEntryCount() == 0);
|
||||
CHECK(memoryPool.GetBlockCount() == 0);
|
||||
CHECK(memoryPool.GetFreeEntryCount() == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
#include <Nazara/Core/Signal.hpp>
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
struct Incrementer
|
||||
{
|
||||
void increment(int* inc)
|
||||
{
|
||||
*inc += 1;
|
||||
}
|
||||
};
|
||||
|
||||
void increment(int* inc)
|
||||
{
|
||||
*inc += 1;
|
||||
}
|
||||
|
||||
SCENARIO("Signal", "[CORE][SIGNAL]")
|
||||
{
|
||||
GIVEN("A signal")
|
||||
{
|
||||
Nz::Signal<int*> signal;
|
||||
|
||||
WHEN("We connection different callbacks")
|
||||
{
|
||||
auto connection = signal.Connect(increment);
|
||||
signal.Connect([](int* inc){ *inc += 1; });
|
||||
Incrementer incrementer;
|
||||
signal.Connect(incrementer, &Incrementer::increment);
|
||||
|
||||
THEN("The call of signal with inc = 0 must return 3")
|
||||
{
|
||||
int inc = 0;
|
||||
signal(&inc);
|
||||
REQUIRE(inc == 3);
|
||||
}
|
||||
|
||||
AND_THEN("When we disconnect one function, there should be only two listeners")
|
||||
{
|
||||
connection.Disconnect();
|
||||
REQUIRE(!connection.IsConnected());
|
||||
|
||||
int inc = 0;
|
||||
signal(&inc);
|
||||
REQUIRE(inc == 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
#include <Nazara/Core/SparsePtr.hpp>
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <array>
|
||||
|
||||
SCENARIO("SparsePtr", "[CORE][SPARSEPTR]")
|
||||
{
|
||||
GIVEN("A sparse pointer pointing to an array with a stride of 2")
|
||||
{
|
||||
std::array<int, 5> arrays = { {0, 1, 2, 3, 4} };
|
||||
Nz::SparsePtr<int> sparsePtr(arrays.data(), 2 * sizeof(int));
|
||||
|
||||
WHEN("We use operators")
|
||||
{
|
||||
THEN("Operator[] with 2 should be 4")
|
||||
{
|
||||
CHECK(4 == sparsePtr[2]);
|
||||
}
|
||||
|
||||
THEN("Operator++ and Operator-- should be opposite")
|
||||
{
|
||||
++sparsePtr;
|
||||
CHECK(2 == *sparsePtr);
|
||||
auto old = sparsePtr++;
|
||||
CHECK(2 == *old);
|
||||
CHECK(4 == *sparsePtr);
|
||||
|
||||
--sparsePtr;
|
||||
CHECK(2 == *sparsePtr);
|
||||
auto oldMinus = sparsePtr--;
|
||||
CHECK(2 == *oldMinus);
|
||||
CHECK(0 == *sparsePtr);
|
||||
}
|
||||
|
||||
THEN("Operator+ and operator-")
|
||||
{
|
||||
auto offsetTwo = sparsePtr + 2;
|
||||
CHECK(4 == *offsetTwo);
|
||||
|
||||
auto offsetZero = offsetTwo - 2;
|
||||
CHECK(0 == *offsetZero);
|
||||
|
||||
CHECK((offsetTwo - offsetZero) == 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,350 +0,0 @@
|
||||
#include <Nazara/Core/MovablePtr.hpp>
|
||||
#include <Nazara/Core/StackVector.hpp>
|
||||
#include <catch2/catch.hpp>
|
||||
#include <array>
|
||||
#include <numeric>
|
||||
|
||||
// This is a quick way to check that checks are valid
|
||||
#define USE_STD_VECTOR 0
|
||||
|
||||
class DestructionCounter
|
||||
{
|
||||
public:
|
||||
DestructionCounter() :
|
||||
m_counter(nullptr),
|
||||
m_value(0)
|
||||
{
|
||||
}
|
||||
|
||||
DestructionCounter(std::size_t* counter, int value) :
|
||||
m_counter(counter),
|
||||
m_value(value)
|
||||
{
|
||||
if (m_counter)
|
||||
(*m_counter)++;
|
||||
}
|
||||
|
||||
DestructionCounter(const DestructionCounter& counter) :
|
||||
m_counter(counter.m_counter),
|
||||
m_value(counter.m_value)
|
||||
{
|
||||
if (m_counter)
|
||||
(*m_counter)++;
|
||||
}
|
||||
|
||||
DestructionCounter(DestructionCounter&& counter) :
|
||||
m_counter(counter.m_counter),
|
||||
m_value(counter.m_value)
|
||||
{
|
||||
if (m_counter)
|
||||
(*m_counter)++;
|
||||
}
|
||||
|
||||
~DestructionCounter()
|
||||
{
|
||||
if (m_counter)
|
||||
{
|
||||
assert(*m_counter > 0);
|
||||
(*m_counter)--;
|
||||
}
|
||||
}
|
||||
|
||||
operator int() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
DestructionCounter& operator=(const DestructionCounter& counter)
|
||||
{
|
||||
if (m_counter)
|
||||
{
|
||||
assert(*m_counter > 0);
|
||||
(*m_counter)--;
|
||||
}
|
||||
|
||||
m_counter = counter.m_counter;
|
||||
m_value = counter.m_value;
|
||||
|
||||
if (m_counter)
|
||||
(*m_counter)++;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
DestructionCounter& operator=(DestructionCounter&& counter)
|
||||
{
|
||||
if (this == &counter)
|
||||
return *this;
|
||||
|
||||
if (m_counter)
|
||||
{
|
||||
assert(*m_counter > 0);
|
||||
(*m_counter)--;
|
||||
}
|
||||
|
||||
m_counter = counter.m_counter;
|
||||
m_value = counter.m_value;
|
||||
|
||||
if (m_counter)
|
||||
(*m_counter)++;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
std::size_t* m_counter;
|
||||
int m_value;
|
||||
};
|
||||
|
||||
SCENARIO("StackVector", "[CORE][STACKVECTOR]")
|
||||
{
|
||||
GIVEN("A StackVector to contain multiple int")
|
||||
{
|
||||
std::size_t counter = 0;
|
||||
{
|
||||
volatile std::size_t capacity = 50;
|
||||
#if USE_STD_VECTOR
|
||||
std::vector<DestructionCounter> vector;
|
||||
vector.reserve(capacity);
|
||||
#else
|
||||
Nz::StackVector<DestructionCounter> vector = NazaraStackVector(DestructionCounter, capacity);
|
||||
#endif
|
||||
|
||||
WHEN("At construction, the vector is empty but has capacity")
|
||||
{
|
||||
CHECK(vector.capacity() == capacity);
|
||||
CHECK(vector.empty());
|
||||
CHECK(vector.size() == 0);
|
||||
#if !USE_STD_VECTOR
|
||||
CHECK(vector.max_size() == capacity);
|
||||
#endif
|
||||
}
|
||||
|
||||
WHEN("Resizing it changes its size and create/destroy elements")
|
||||
{
|
||||
vector.resize(vector.capacity());
|
||||
CHECK(vector.size() == vector.capacity());
|
||||
CHECK(counter == 0);
|
||||
vector.resize(0);
|
||||
CHECK(vector.empty());
|
||||
CHECK(vector.size() == 0);
|
||||
CHECK(counter == 0);
|
||||
}
|
||||
|
||||
WHEN("Resizing it allocates elements")
|
||||
{
|
||||
vector.resize(vector.capacity(), DestructionCounter(&counter, 0));
|
||||
CHECK(vector.size() == vector.capacity());
|
||||
CHECK(counter == capacity);
|
||||
vector.resize(0);
|
||||
CHECK(vector.empty());
|
||||
CHECK(vector.size() == 0);
|
||||
CHECK(counter == 0);
|
||||
}
|
||||
|
||||
WHEN("Emplacing five elements, vector size increase accordingly")
|
||||
{
|
||||
for (std::size_t i = 0; i < 5; ++i)
|
||||
{
|
||||
#if USE_STD_VECTOR
|
||||
vector.emplace_back(&counter, int(i));
|
||||
#else
|
||||
CHECK(vector.emplace_back(&counter, int(i)) == int(i));
|
||||
#endif
|
||||
}
|
||||
|
||||
CHECK(!vector.empty());
|
||||
CHECK(vector.size() == 5);
|
||||
|
||||
std::array<int, 5> expectedValues = { 0, 1, 2, 3, 4 };
|
||||
CHECK(std::equal(vector.begin(), vector.end(), expectedValues.begin(), expectedValues.end()));
|
||||
}
|
||||
|
||||
WHEN("Pushing three elements, vector size increase accordingly")
|
||||
{
|
||||
for (std::size_t i = 0; i < 3; ++i)
|
||||
{
|
||||
DestructionCounter val(&counter, int(i));
|
||||
#if USE_STD_VECTOR
|
||||
vector.push_back(val);
|
||||
#else
|
||||
CHECK(vector.push_back(val) == val);
|
||||
#endif
|
||||
}
|
||||
|
||||
CHECK(!vector.empty());
|
||||
CHECK(vector.size() == 3);
|
||||
{
|
||||
std::array<int, 3> expectedValues = { 0, 1, 2 };
|
||||
CHECK(std::equal(vector.begin(), vector.end(), expectedValues.begin(), expectedValues.end()));
|
||||
}
|
||||
|
||||
THEN("We resize to five")
|
||||
{
|
||||
vector.resize(5);
|
||||
|
||||
CHECK(!vector.empty());
|
||||
CHECK(vector.size() == 5);
|
||||
|
||||
std::array<int, 5> expectedValues = { 0, 1, 2, 0, 0 };
|
||||
CHECK(std::equal(vector.begin(), vector.end(), expectedValues.begin(), expectedValues.end()));
|
||||
|
||||
AND_THEN("We resize it back to zero")
|
||||
{
|
||||
vector.resize(0);
|
||||
|
||||
CHECK(vector.empty());
|
||||
CHECK(vector.size() == 0);
|
||||
}
|
||||
AND_THEN("We clear it")
|
||||
{
|
||||
vector.clear();
|
||||
|
||||
CHECK(vector.empty());
|
||||
CHECK(vector.size() == 0);
|
||||
CHECK(counter == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("We generate its content will iota")
|
||||
{
|
||||
vector.resize(10);
|
||||
for (std::size_t i = 0; i < vector.size(); ++i)
|
||||
vector[i] = DestructionCounter(&counter, -5 + int(i));
|
||||
|
||||
{
|
||||
std::array<int, 10> expectedValues = { -5, -4, -3, -2, -1, 0, 1, 2, 3, 4 };
|
||||
CHECK(vector.size() == expectedValues.size());
|
||||
CHECK(std::equal(vector.begin(), vector.end(), expectedValues.begin(), expectedValues.end()));
|
||||
}
|
||||
|
||||
AND_WHEN("We pop back some elements")
|
||||
{
|
||||
for (std::size_t i = 0; i < 5; ++i)
|
||||
vector.pop_back();
|
||||
|
||||
std::array<int, 5> expectedValues = { -5, -4, -3, -2, -1 };
|
||||
CHECK(vector.size() == expectedValues.size());
|
||||
CHECK(std::equal(vector.begin(), vector.end(), expectedValues.begin(), expectedValues.end()));
|
||||
}
|
||||
AND_WHEN("We erase elements at the beginning")
|
||||
{
|
||||
vector.erase(vector.begin());
|
||||
vector.erase(vector.begin());
|
||||
|
||||
std::array<int, 8> expectedValues = { -3, -2, -1, 0, 1, 2, 3, 4 };
|
||||
CHECK(vector.size() == expectedValues.size());
|
||||
CHECK(std::equal(vector.begin(), vector.end(), expectedValues.begin(), expectedValues.end()));
|
||||
}
|
||||
AND_WHEN("We erase elements in the middle")
|
||||
{
|
||||
vector.erase(vector.begin() + 2);
|
||||
vector.erase(vector.begin() + 2);
|
||||
vector.erase(vector.begin() + 6);
|
||||
|
||||
std::array<int, 7> expectedValues = { -5, -4, -1, 0, 1, 2, 4 };
|
||||
CHECK(vector.size() == expectedValues.size());
|
||||
CHECK(std::equal(vector.begin(), vector.end(), expectedValues.begin(), expectedValues.end()));
|
||||
}
|
||||
AND_WHEN("We erase elements at the end")
|
||||
{
|
||||
vector.erase(vector.end() - 1);
|
||||
vector.erase(vector.end() - 1);
|
||||
|
||||
std::array<int, 8> expectedValues = { -5, -4, -3, -2, -1, 0, 1, 2 };
|
||||
CHECK(vector.size() == expectedValues.size());
|
||||
CHECK(std::equal(vector.begin(), vector.end(), expectedValues.begin(), expectedValues.end()));
|
||||
}
|
||||
AND_WHEN("We erase a range")
|
||||
{
|
||||
vector.erase(vector.begin() + 2, vector.end() - 3);
|
||||
|
||||
std::array<int, 5> expectedValues = { -5, -4, 2, 3, 4 };
|
||||
CHECK(vector.size() == expectedValues.size());
|
||||
CHECK(std::equal(vector.begin(), vector.end(), expectedValues.begin(), expectedValues.end()));
|
||||
}
|
||||
AND_WHEN("We erase everything")
|
||||
{
|
||||
vector.erase(vector.begin(), vector.end());
|
||||
|
||||
CHECK(vector.empty());
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("We generate its content using emplace")
|
||||
{
|
||||
for (std::size_t i = 0; i < 5; ++i)
|
||||
CHECK(*vector.emplace(vector.end(), &counter, int(i)) == int(i));
|
||||
|
||||
CHECK(!vector.empty());
|
||||
CHECK(vector.size() == 5);
|
||||
|
||||
std::array<int, 5> expectedValues = { 0, 1, 2, 3, 4 };
|
||||
CHECK(std::equal(vector.begin(), vector.end(), expectedValues.begin(), expectedValues.end()));
|
||||
}
|
||||
|
||||
WHEN("We generate its content using emplace, in reverse order")
|
||||
{
|
||||
for (std::size_t i = 0; i < 5; ++i)
|
||||
CHECK(*vector.emplace(vector.begin(), &counter, int(i)) == int(i));
|
||||
|
||||
CHECK(!vector.empty());
|
||||
CHECK(vector.size() == 5);
|
||||
|
||||
std::array<int, 5> expectedValues = { 4, 3, 2, 1, 0 };
|
||||
CHECK(std::equal(vector.begin(), vector.end(), expectedValues.begin(), expectedValues.end()));
|
||||
}
|
||||
|
||||
WHEN("We generate its content using emplace, at the middle")
|
||||
{
|
||||
for (std::size_t i = 0; i < 10; ++i)
|
||||
CHECK(*vector.emplace(vector.begin() + i / 2, &counter, int(i)) == int(i));
|
||||
|
||||
CHECK(!vector.empty());
|
||||
CHECK(vector.size() == 10);
|
||||
|
||||
std::array<int, 10> expectedValues = { 1, 3, 5, 7, 9, 8, 6, 4, 2, 0 };
|
||||
CHECK(std::equal(vector.begin(), vector.end(), expectedValues.begin(), expectedValues.end()));
|
||||
}
|
||||
|
||||
WHEN("We generate its content using insert")
|
||||
{
|
||||
for (std::size_t i = 0; i < 5; ++i)
|
||||
CHECK(*vector.insert(vector.end(), DestructionCounter(&counter, int(i))) == int(i));
|
||||
|
||||
CHECK(!vector.empty());
|
||||
CHECK(vector.size() == 5);
|
||||
|
||||
std::array<int, 5> expectedValues = { 0, 1, 2, 3, 4 };
|
||||
CHECK(std::equal(vector.begin(), vector.end(), expectedValues.begin(), expectedValues.end()));
|
||||
}
|
||||
|
||||
WHEN("We generate its content using insert, in reverse order")
|
||||
{
|
||||
for (std::size_t i = 0; i < 5; ++i)
|
||||
CHECK(*vector.insert(vector.begin(), DestructionCounter(&counter, int(i))) == int(i));
|
||||
|
||||
CHECK(!vector.empty());
|
||||
CHECK(vector.size() == 5);
|
||||
|
||||
std::array<int, 5> expectedValues = { 4, 3, 2, 1, 0 };
|
||||
CHECK(std::equal(vector.begin(), vector.end(), expectedValues.begin(), expectedValues.end()));
|
||||
}
|
||||
|
||||
WHEN("We generate its content using insert, at the middle")
|
||||
{
|
||||
for (std::size_t i = 0; i < 10; ++i)
|
||||
CHECK(*vector.insert(vector.begin() + i / 2, DestructionCounter(&counter, int(i))) == int(i));
|
||||
|
||||
CHECK(!vector.empty());
|
||||
CHECK(vector.size() == 10);
|
||||
|
||||
std::array<int, 10> expectedValues = { 1, 3, 5, 7, 9, 8, 6, 4, 2, 0 };
|
||||
CHECK(std::equal(vector.begin(), vector.end(), expectedValues.begin(), expectedValues.end()));
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(counter == 0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user