Use UnitTest-Cpp library for testing
This commit is contained in:
parent
79d018ffb4
commit
b8bcf58a29
53 changed files with 1046 additions and 1383 deletions
|
|
@ -11,5 +11,5 @@ target_link_libraries(${PROJECT_NAME} PUBLIC Modules)
|
|||
enable_testing()
|
||||
file(GLOB TEST_SOURCES "./tests/*.cpp")
|
||||
add_executable(${PROJECT_NAME}Tests ${TEST_SOURCES})
|
||||
target_link_libraries(${PROJECT_NAME}Tests ${PROJECT_NAME} Allocators)
|
||||
target_link_libraries(${PROJECT_NAME}Tests ${PROJECT_NAME} Allocators UnitTest++)
|
||||
add_test(NAME ${PROJECT_NAME}Tests COMMAND ${PROJECT_NAME}Tests)
|
||||
|
|
@ -245,6 +245,7 @@ namespace tp {
|
|||
}
|
||||
removeAll();
|
||||
mNSlots = in.mNSlots;
|
||||
deleteTable(mTable);
|
||||
mTable = newTable(mNSlots);
|
||||
for (alni i = 0; i < mNSlots; i++) {
|
||||
if (in.mTable[i] && !isDeletedNode(in.mTable[i])) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#include "Buffer2D.hpp"
|
||||
#include "Testing.hpp"
|
||||
#include "Tests.hpp"
|
||||
|
||||
#include "HeapAllocator.hpp"
|
||||
|
|
@ -8,18 +7,15 @@ using namespace tp;
|
|||
|
||||
const ualni size = 1000;
|
||||
|
||||
TEST_DEF_STATIC(Simple1) {
|
||||
Buffer2D<int, tp::HeapAlloc> buff;
|
||||
buff.reserve({ 4, 4 });
|
||||
buff.set({ 2, 2 }, 5);
|
||||
TEST(buff.get({ 2, 2 }) == 5);
|
||||
}
|
||||
SUITE(Buffer2D) {
|
||||
TEST(Simple) {
|
||||
Buffer2D<int, tp::HeapAlloc> buff;
|
||||
buff.reserve({ 4, 4 });
|
||||
buff.set({ 2, 2 }, 5);
|
||||
CHECK(buff.get({ 2, 2 }) == 5);
|
||||
}
|
||||
|
||||
TEST_DEF_STATIC(Simple2) {
|
||||
// TEST(false);
|
||||
}
|
||||
|
||||
TEST_DEF(Buffer2d) {
|
||||
testSimple1();
|
||||
testSimple2();
|
||||
TEST(NO_TESTS) {
|
||||
CHECK(false);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,35 +1,33 @@
|
|||
#include "Buffer.hpp"
|
||||
#include "Testing.hpp"
|
||||
#include "Tests.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
const ualni size = 1000;
|
||||
|
||||
TEST_DEF_STATIC(Simple1) {
|
||||
Buffer<TestClass, tp::HeapAlloc> buff;
|
||||
TEST(buff.size() == 0);
|
||||
for (auto i : Range(size * 10)) {
|
||||
buff.append(TestClass(i));
|
||||
SUITE(Buffer) {
|
||||
TEST(Simple1) {
|
||||
Buffer<TestClass, tp::HeapAlloc> buff;
|
||||
CHECK(buff.size() == 0);
|
||||
for (auto i : Range(size * 10)) {
|
||||
buff.append(TestClass(i));
|
||||
}
|
||||
CHECK(buff.size() == size * 10);
|
||||
while (buff.size())
|
||||
buff.pop();
|
||||
CHECK(buff.size() == 0);
|
||||
}
|
||||
TEST(buff.size() == size * 10);
|
||||
while (buff.size())
|
||||
buff.pop();
|
||||
TEST(buff.size() == 0);
|
||||
}
|
||||
|
||||
TEST_DEF_STATIC(Simple2) {
|
||||
Buffer<TestClass, tp::HeapAlloc> buff(size);
|
||||
TEST(buff.size() == size);
|
||||
for (auto i : Range(size * 10))
|
||||
buff.append(TestClass(i));
|
||||
TEST(buff.size() == size + size * 10);
|
||||
while (buff.size())
|
||||
buff.pop();
|
||||
TEST(buff.size() == 0);
|
||||
}
|
||||
TEST(Simple2) {
|
||||
Buffer<TestClass, tp::HeapAlloc> buff(size);
|
||||
CHECK(buff.size() == size);
|
||||
for (auto i : Range(size * 10))
|
||||
buff.append(TestClass(i));
|
||||
CHECK(buff.size() == size + size * 10);
|
||||
while (buff.size())
|
||||
buff.pop();
|
||||
CHECK(buff.size() == 0);
|
||||
}
|
||||
|
||||
TEST_DEF(Buffer) {
|
||||
testSimple1();
|
||||
testSimple2();
|
||||
}
|
||||
TEST(NO_TEST) { CHECK(false); }
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
#include "IntervalTree.hpp"
|
||||
#include "Testing.hpp"
|
||||
#include "Tests.hpp"
|
||||
|
||||
#include "Buffer.hpp"
|
||||
|
|
@ -34,246 +33,242 @@ struct Interval {
|
|||
}
|
||||
};
|
||||
|
||||
TEST_DEF_STATIC(FunctionalitySimple) {
|
||||
SUITE(IntervalTree) {
|
||||
TEST(FunctionalitySimple) {
|
||||
|
||||
IntervalTree<ualni, ualni> intervalTree;
|
||||
IntervalTree<ualni, ualni> intervalTree;
|
||||
|
||||
intervalTree.insert({ 0, 10 }, 1);
|
||||
intervalTree.insert({ 3, 6 }, 2);
|
||||
intervalTree.insert({ 8, 12 }, 3);
|
||||
intervalTree.insert({ 0, 10 }, 1);
|
||||
intervalTree.insert({ 3, 6 }, 2);
|
||||
intervalTree.insert({ 8, 12 }, 3);
|
||||
|
||||
intervalTree.forEachIntersection(4, 5, [](alni start, ualni end, ualni data) {
|
||||
printf("%i", int(data));
|
||||
printf("\n");
|
||||
});
|
||||
}
|
||||
|
||||
TEST_DEF_STATIC(FunctionalityScale) {
|
||||
|
||||
const int NUM_TEST_INTERVALS = 1000;
|
||||
const halnf SPAN = 100;
|
||||
|
||||
Buffer<Interval> pool;
|
||||
IntervalTree<halnf, ualni> intervalTree;
|
||||
|
||||
Buffer<Interval> testIntervals;
|
||||
|
||||
auto test = [&]() {
|
||||
for (auto testInterval : testIntervals) {
|
||||
|
||||
Buffer<ualni> correct;
|
||||
Buffer<ualni> result;
|
||||
|
||||
ualni idx = 0;
|
||||
for (auto interval : pool) {
|
||||
if (!interval->ignore && interval->overlaps(testInterval.data())) {
|
||||
correct.append(idx);
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
intervalTree.forEachIntersection(testInterval->start, testInterval->end, [&](alni start, ualni end, ualni data) {
|
||||
result.append(data);
|
||||
});
|
||||
|
||||
TEST(correct.size() == result.size());
|
||||
|
||||
if (!(correct.size() == result.size())) {
|
||||
printf("intersections - \n");
|
||||
|
||||
for (auto i : correct) {
|
||||
printf(" %i", (int) i.data());
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
for (auto i : result) {
|
||||
printf(" %i", (int) i.data());
|
||||
}
|
||||
printf("\n\n");
|
||||
}
|
||||
// todo compare containers
|
||||
}
|
||||
};
|
||||
|
||||
// initialize
|
||||
for (auto i : Range<ualni>(NUM_TEST_INTERVALS)) {
|
||||
auto interval = Interval();
|
||||
interval.random(SPAN);
|
||||
|
||||
pool.append(interval);
|
||||
intervalTree.insert({ interval.start, interval.end }, i);
|
||||
|
||||
interval.random(SPAN * 2.f, (halnf) randomFloat());
|
||||
|
||||
testIntervals.append(interval);
|
||||
intervalTree.forEachIntersection(4, 5, [](alni start, ualni end, ualni data) {
|
||||
printf("%i", int(data));
|
||||
printf("\n");
|
||||
});
|
||||
}
|
||||
|
||||
test();
|
||||
TEST(FunctionalityScale) {
|
||||
|
||||
// remove some
|
||||
for (auto i : Range<ualni>(NUM_TEST_INTERVALS / 2)) {
|
||||
auto idx = ualni(randomFloat() * (alnf) pool.size());
|
||||
pool[idx].ignore = true;
|
||||
intervalTree.remove({ pool[idx].start, pool[idx].end });
|
||||
}
|
||||
|
||||
test();
|
||||
}
|
||||
|
||||
TEST_DEF_STATIC(Efficency) {
|
||||
|
||||
struct Stat {
|
||||
halnf numItems = 0;
|
||||
halnf avgFound = 0;
|
||||
halnf avgChecks = 0;
|
||||
};
|
||||
|
||||
auto test = [&](ualni NUM_TEST_INTERVALS, ualni NUM_CHECKS) {
|
||||
const auto SPAN = (halnf) (halnf(NUM_TEST_INTERVALS));
|
||||
const auto SCALE = (halnf) (2.f);
|
||||
const int NUM_TEST_INTERVALS = 1000;
|
||||
const halnf SPAN = 100;
|
||||
|
||||
Buffer<Interval> pool;
|
||||
IntervalTree<halnf, ualni> intervalTree;
|
||||
|
||||
Buffer<Interval> testIntervals;
|
||||
|
||||
auto WOBBLE = SPAN * 0;
|
||||
auto test = [&]() {
|
||||
for (auto testInterval : testIntervals) {
|
||||
|
||||
Buffer<ualni> correct;
|
||||
Buffer<ualni> result;
|
||||
|
||||
ualni idx = 0;
|
||||
for (auto interval : pool) {
|
||||
if (!interval->ignore && interval->overlaps(testInterval.data())) {
|
||||
correct.append(idx);
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
intervalTree.forEachIntersection(testInterval->start, testInterval->end, [&](alni start, ualni end, ualni data) {
|
||||
result.append(data);
|
||||
});
|
||||
|
||||
CHECK(correct.size() == result.size());
|
||||
|
||||
if (!(correct.size() == result.size())) {
|
||||
printf("intersections - \n");
|
||||
|
||||
for (auto i : correct) {
|
||||
printf(" %i", (int) i.data());
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
for (auto i : result) {
|
||||
printf(" %i", (int) i.data());
|
||||
}
|
||||
printf("\n\n");
|
||||
}
|
||||
// todo compare containers
|
||||
}
|
||||
};
|
||||
|
||||
// initialize
|
||||
for (auto i : Range<ualni>(NUM_TEST_INTERVALS)) {
|
||||
auto interval = Interval();
|
||||
interval.randomSized(SPAN, SCALE, WOBBLE);
|
||||
interval.random(SPAN);
|
||||
|
||||
pool.append(interval);
|
||||
intervalTree.insert({ interval.start, interval.end }, i);
|
||||
// WOBBLE -= 1.f;
|
||||
}
|
||||
|
||||
for (auto i : Range(0))
|
||||
intervalTree.insert({ (halnf) i * 0.01f, SPAN }, 0);
|
||||
interval.random(SPAN * 2.f, (halnf) randomFloat());
|
||||
|
||||
WOBBLE = 0;
|
||||
for (auto i : Range<ualni>(NUM_CHECKS)) {
|
||||
auto interval = Interval();
|
||||
interval.randomSized(SPAN, SCALE, WOBBLE);
|
||||
testIntervals.append(interval);
|
||||
}
|
||||
|
||||
ualni debugMaxChecks = 0;
|
||||
ualni debugMaxFound = 0;
|
||||
halnf debugAvgChecks = 0;
|
||||
halnf debugAvgFound = 0;
|
||||
test();
|
||||
|
||||
for (auto testInterval : testIntervals) {
|
||||
ualni debugFound = 0;
|
||||
ualni debug = intervalTree.forEachIntersection(
|
||||
testInterval->start,
|
||||
testInterval->end,
|
||||
[&](ualni start, ualni end, ualni data) {
|
||||
debugFound++;
|
||||
//
|
||||
}
|
||||
);
|
||||
|
||||
if (debug > debugMaxChecks) {
|
||||
debugMaxChecks = debug;
|
||||
debugMaxFound = debugFound;
|
||||
}
|
||||
|
||||
debugMaxChecks = max(debug, debugMaxChecks);
|
||||
debugAvgChecks += (halnf) debug;
|
||||
debugAvgFound += (halnf) debugFound;
|
||||
// remove some
|
||||
for (auto i : Range<ualni>(NUM_TEST_INTERVALS / 2)) {
|
||||
auto idx = ualni(randomFloat() * (alnf) pool.size());
|
||||
pool[idx].ignore = true;
|
||||
intervalTree.remove({ pool[idx].start, pool[idx].end });
|
||||
}
|
||||
|
||||
debugAvgChecks /= (halnf) testIntervals.size();
|
||||
debugAvgFound /= (halnf) testIntervals.size();
|
||||
|
||||
printf("\nItems : %llu\n", NUM_TEST_INTERVALS);
|
||||
printf("Avg(checks) : %f\n", debugAvgChecks);
|
||||
printf("Avg(found) : %f\n", debugAvgFound);
|
||||
printf("Max checks : %llu\n", debugMaxChecks);
|
||||
printf("Max checks found : %llu\n", debugMaxFound);
|
||||
printf("N(Avg(checks) / Avg(N(items)) : %f\n", debugAvgChecks / (halnf) intervalTree.size());
|
||||
printf("N(Avg(found)) / Avg(N(items)) : %f\n", debugAvgFound / (halnf) intervalTree.size());
|
||||
printf("Avg(found) / Avg(checks) : %f\n", debugAvgFound / debugAvgChecks);
|
||||
|
||||
return Stat{ (halnf) NUM_TEST_INTERVALS,
|
||||
debugAvgFound / (halnf) intervalTree.size(),
|
||||
debugAvgChecks / (halnf) intervalTree.size() };
|
||||
};
|
||||
|
||||
Buffer<Stat> stats;
|
||||
for (auto i : Range(2, 5)) {
|
||||
Stat stat = test(pow(10, i), 100);
|
||||
stats.append(stat);
|
||||
test();
|
||||
}
|
||||
|
||||
printf("\nChecks: ");
|
||||
for (auto stat : stats)
|
||||
printf("%e ", stat->avgChecks);
|
||||
TEST(Efficency) {
|
||||
|
||||
printf("\nHits: ");
|
||||
for (auto stat : stats)
|
||||
printf("%e ", stat->avgFound);
|
||||
struct Stat {
|
||||
halnf numItems = 0;
|
||||
halnf avgFound = 0;
|
||||
halnf avgChecks = 0;
|
||||
};
|
||||
|
||||
printf("\nItems: ");
|
||||
for (auto stat : stats)
|
||||
printf("%e ", stat->numItems);
|
||||
auto test = [&](ualni NUM_TEST_INTERVALS, ualni NUM_CHECKS) {
|
||||
const auto SPAN = (halnf) (halnf(NUM_TEST_INTERVALS));
|
||||
const auto SCALE = (halnf) (2.f);
|
||||
|
||||
printf("\n\n");
|
||||
}
|
||||
IntervalTree<halnf, ualni> intervalTree;
|
||||
Buffer<Interval> testIntervals;
|
||||
|
||||
TEST_DEF_STATIC(FunctionalityComplex) {
|
||||
IntervalTree<ualni, ualni> intervals;
|
||||
auto WOBBLE = SPAN * 0;
|
||||
for (auto i : Range<ualni>(NUM_TEST_INTERVALS)) {
|
||||
auto interval = Interval();
|
||||
interval.randomSized(SPAN, SCALE, WOBBLE);
|
||||
intervalTree.insert({ interval.start, interval.end }, i);
|
||||
// WOBBLE -= 1.f;
|
||||
}
|
||||
|
||||
struct QueryResult {
|
||||
ualni numFound = 0;
|
||||
ualni lastDataFound = 0;
|
||||
for (auto i : Range(0))
|
||||
intervalTree.insert({ (halnf) i * 0.01f, SPAN }, 0);
|
||||
|
||||
[[nodiscard]] bool isSingleData(ualni aData) const { return numFound == 1 & lastDataFound == aData; }
|
||||
[[nodiscard]] bool notFound() const { return numFound == 0; }
|
||||
[[nodiscard]] bool found(ualni num) const { return numFound == num; }
|
||||
};
|
||||
WOBBLE = 0;
|
||||
for (auto i : Range<ualni>(NUM_CHECKS)) {
|
||||
auto interval = Interval();
|
||||
interval.randomSized(SPAN, SCALE, WOBBLE);
|
||||
testIntervals.append(interval);
|
||||
}
|
||||
|
||||
auto makeQuery = [&](ualni aStart, ualni aEnd) {
|
||||
QueryResult out;
|
||||
intervals.forEachIntersection(aStart, aEnd, [&](alni start, ualni end, ualni data) {
|
||||
out.numFound++;
|
||||
out.lastDataFound = data;
|
||||
});
|
||||
return out;
|
||||
};
|
||||
ualni debugMaxChecks = 0;
|
||||
ualni debugMaxFound = 0;
|
||||
halnf debugAvgChecks = 0;
|
||||
halnf debugAvgFound = 0;
|
||||
|
||||
intervals.insert({ 2, 5 }, 1);
|
||||
intervals.insert({ 12, 15 }, 2);
|
||||
intervals.insert({ 22, 25 }, 3);
|
||||
for (auto testInterval : testIntervals) {
|
||||
ualni debugFound = 0;
|
||||
ualni debug = intervalTree.forEachIntersection(
|
||||
testInterval->start,
|
||||
testInterval->end,
|
||||
[&](ualni start, ualni end, ualni data) {
|
||||
debugFound++;
|
||||
//
|
||||
}
|
||||
);
|
||||
|
||||
TEST(makeQuery(1, 6).isSingleData(1));
|
||||
TEST(makeQuery(1, 3).isSingleData(1));
|
||||
TEST(makeQuery(3, 6).isSingleData(1));
|
||||
if (debug > debugMaxChecks) {
|
||||
debugMaxChecks = debug;
|
||||
debugMaxFound = debugFound;
|
||||
}
|
||||
|
||||
TEST(makeQuery(0, 1).notFound());
|
||||
TEST(makeQuery(7, 8).notFound());
|
||||
debugMaxChecks = max(debug, debugMaxChecks);
|
||||
debugAvgChecks += (halnf) debug;
|
||||
debugAvgFound += (halnf) debugFound;
|
||||
}
|
||||
|
||||
TEST(makeQuery(3, 4).isSingleData(1));
|
||||
debugAvgChecks /= (halnf) testIntervals.size();
|
||||
debugAvgFound /= (halnf) testIntervals.size();
|
||||
|
||||
TEST(makeQuery(13, 14).isSingleData(2));
|
||||
printf("\nItems : %llu\n", NUM_TEST_INTERVALS);
|
||||
printf("Avg(checks) : %f\n", debugAvgChecks);
|
||||
printf("Avg(found) : %f\n", debugAvgFound);
|
||||
printf("Max checks : %llu\n", debugMaxChecks);
|
||||
printf("Max checks found : %llu\n", debugMaxFound);
|
||||
printf("N(Avg(checks) / Avg(N(items)) : %f\n", debugAvgChecks / (halnf) intervalTree.size());
|
||||
printf("N(Avg(found)) / Avg(N(items)) : %f\n", debugAvgFound / (halnf) intervalTree.size());
|
||||
printf("Avg(found) / Avg(checks) : %f\n", debugAvgFound / debugAvgChecks);
|
||||
|
||||
TEST(makeQuery(1, 35).found(3));
|
||||
TEST(makeQuery(11, 35).found(2));
|
||||
return Stat{ (halnf) NUM_TEST_INTERVALS,
|
||||
debugAvgFound / (halnf) intervalTree.size(),
|
||||
debugAvgChecks / (halnf) intervalTree.size() };
|
||||
};
|
||||
|
||||
// check opened
|
||||
TEST(makeQuery(5, 12).found(2));
|
||||
TEST(makeQuery(15, 22).found(2));
|
||||
Buffer<Stat> stats;
|
||||
for (auto i : Range(2, 5)) {
|
||||
Stat stat = test(pow(10, i), 100);
|
||||
stats.append(stat);
|
||||
}
|
||||
|
||||
TEST(makeQuery(1, 2).isSingleData(1));
|
||||
TEST(makeQuery(25, 35).isSingleData(3));
|
||||
printf("\nChecks: ");
|
||||
for (auto stat : stats)
|
||||
printf("%e ", stat->avgChecks);
|
||||
|
||||
intervals.removeAll();
|
||||
printf("\nHits: ");
|
||||
for (auto stat : stats)
|
||||
printf("%e ", stat->avgFound);
|
||||
|
||||
intervals.insert({ 0, 3 }, 1);
|
||||
intervals.insert({ 0, 13 }, 2);
|
||||
printf("\nItems: ");
|
||||
for (auto stat : stats)
|
||||
printf("%e ", stat->numItems);
|
||||
|
||||
TEST(makeQuery(0, 1).found(2));
|
||||
}
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
TEST_DEF(IntervalTree) {
|
||||
testFunctionalitySimple();
|
||||
testFunctionalityScale();
|
||||
testEfficency();
|
||||
testFunctionalityComplex();
|
||||
}
|
||||
TEST(FunctionalityComplex) {
|
||||
IntervalTree<ualni, ualni> intervals;
|
||||
|
||||
struct QueryResult {
|
||||
ualni numFound = 0;
|
||||
ualni lastDataFound = 0;
|
||||
|
||||
[[nodiscard]] bool isSingleData(ualni aData) const { return numFound == 1 & lastDataFound == aData; }
|
||||
[[nodiscard]] bool notFound() const { return numFound == 0; }
|
||||
[[nodiscard]] bool found(ualni num) const { return numFound == num; }
|
||||
};
|
||||
|
||||
auto makeQuery = [&](ualni aStart, ualni aEnd) {
|
||||
QueryResult out;
|
||||
intervals.forEachIntersection(aStart, aEnd, [&](alni start, ualni end, ualni data) {
|
||||
out.numFound++;
|
||||
out.lastDataFound = data;
|
||||
});
|
||||
return out;
|
||||
};
|
||||
|
||||
intervals.insert({ 2, 5 }, 1);
|
||||
intervals.insert({ 12, 15 }, 2);
|
||||
intervals.insert({ 22, 25 }, 3);
|
||||
|
||||
CHECK(makeQuery(1, 6).isSingleData(1));
|
||||
CHECK(makeQuery(1, 3).isSingleData(1));
|
||||
CHECK(makeQuery(3, 6).isSingleData(1));
|
||||
|
||||
CHECK(makeQuery(0, 1).notFound());
|
||||
CHECK(makeQuery(7, 8).notFound());
|
||||
|
||||
CHECK(makeQuery(3, 4).isSingleData(1));
|
||||
|
||||
CHECK(makeQuery(13, 14).isSingleData(2));
|
||||
|
||||
CHECK(makeQuery(1, 35).found(3));
|
||||
CHECK(makeQuery(11, 35).found(2));
|
||||
|
||||
// check opened
|
||||
CHECK(makeQuery(5, 12).found(2));
|
||||
CHECK(makeQuery(15, 22).found(2));
|
||||
|
||||
CHECK(makeQuery(1, 2).isSingleData(1));
|
||||
CHECK(makeQuery(25, 35).isSingleData(3));
|
||||
|
||||
intervals.removeAll();
|
||||
|
||||
intervals.insert({ 0, 3 }, 1);
|
||||
intervals.insert({ 0, 13 }, 2);
|
||||
|
||||
CHECK(makeQuery(0, 1).found(2));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,83 +1,80 @@
|
|||
#include "Archiver.hpp"
|
||||
#include "Testing.hpp"
|
||||
#include "Tests.hpp"
|
||||
#include "List.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
TEST_DEF_STATIC(SimpleReference) {
|
||||
tp::List<TestClass, tp::HeapAlloc> list = { TestClass(1), TestClass(2), TestClass(3), TestClass(4) };
|
||||
SUITE(DoubleLinkedList) {
|
||||
|
||||
list.pushBack(TestClass(5));
|
||||
list.pushFront(TestClass(0));
|
||||
TEST(SimpleReference) {
|
||||
tp::List<TestClass, tp::HeapAlloc> list = { TestClass(1), TestClass(2), TestClass(3), TestClass(4) };
|
||||
|
||||
ualni i = -1;
|
||||
for (auto iter : list) {
|
||||
i++;
|
||||
TEST_EQUAL(iter->getVal(), i);
|
||||
list.pushBack(TestClass(5));
|
||||
list.pushFront(TestClass(0));
|
||||
|
||||
ualni i = -1;
|
||||
for (auto iter : list) {
|
||||
i++;
|
||||
CHECK_EQUAL(iter->getVal(), i);
|
||||
}
|
||||
|
||||
CHECK(i == 5);
|
||||
|
||||
list.removeAll();
|
||||
}
|
||||
|
||||
TEST(i == 5);
|
||||
TEST(SimplePointer) {
|
||||
tp::List<TestClass*, tp::HeapAlloc> list = { new TestClass(1), new TestClass(2), new TestClass(3), new TestClass(4) };
|
||||
|
||||
list.removeAll();
|
||||
}
|
||||
list.pushBack(new TestClass(5));
|
||||
list.pushFront(new TestClass(0));
|
||||
|
||||
TEST_DEF_STATIC(SimplePointer) {
|
||||
tp::List<TestClass*, tp::HeapAlloc> list = { new TestClass(1), new TestClass(2), new TestClass(3), new TestClass(4) };
|
||||
ualni i = -1;
|
||||
for (auto iter : list) {
|
||||
i++;
|
||||
CHECK_EQUAL(iter->getVal(), i);
|
||||
}
|
||||
|
||||
list.pushBack(new TestClass(5));
|
||||
list.pushFront(new TestClass(0));
|
||||
CHECK(i == 5);
|
||||
|
||||
ualni i = -1;
|
||||
for (auto iter : list) {
|
||||
i++;
|
||||
TEST_EQUAL(iter->getVal(), i);
|
||||
for (auto iter : list) {
|
||||
delete iter.data();
|
||||
}
|
||||
|
||||
list.removeAll();
|
||||
}
|
||||
|
||||
TEST(i == 5);
|
||||
TEST(Copy) {
|
||||
tp::List<TestClass, tp::HeapAlloc> list = { TestClass(1), TestClass(2), TestClass(3), TestClass(4) };
|
||||
tp::List<TestClass, tp::HeapAlloc> list2 = list;
|
||||
|
||||
for (auto iter : list) {
|
||||
delete iter.data();
|
||||
CHECK(list == list2);
|
||||
|
||||
list.removeAll();
|
||||
list2.removeAll();
|
||||
}
|
||||
|
||||
list.removeAll();
|
||||
}
|
||||
TEST(Serialization) {
|
||||
tp::List<TestClass, tp::HeapAlloc> list = { TestClass(1), TestClass(2), TestClass(3), TestClass(4) };
|
||||
|
||||
TEST_DEF_STATIC(Copy) {
|
||||
tp::List<TestClass, tp::HeapAlloc> list = { TestClass(1), TestClass(2), TestClass(3), TestClass(4) };
|
||||
tp::List<TestClass, tp::HeapAlloc> list2 = list;
|
||||
ArchiverExample<1024, false> write;
|
||||
ArchiverExample<1024, true> read;
|
||||
|
||||
TEST_EQUAL(list, list2);
|
||||
write % list;
|
||||
|
||||
list.removeAll();
|
||||
list2.removeAll();
|
||||
}
|
||||
list.removeAll();
|
||||
|
||||
TEST_DEF_STATIC(Serialization) {
|
||||
tp::List<TestClass, tp::HeapAlloc> list = { TestClass(1), TestClass(2), TestClass(3), TestClass(4) };
|
||||
memCopy(read.mBuff, write.mBuff, sizeof(write.mBuff));
|
||||
|
||||
ArchiverExample<1024, false> write;
|
||||
ArchiverExample<1024, true> read;
|
||||
read % list;
|
||||
|
||||
write % list;
|
||||
ualni i = 0;
|
||||
for (auto iter : list) {
|
||||
i++;
|
||||
CHECK(iter->getVal() == i);
|
||||
}
|
||||
CHECK(i == 4);
|
||||
|
||||
list.removeAll();
|
||||
|
||||
memCopy(read.mBuff, write.mBuff, sizeof(write.mBuff));
|
||||
|
||||
read % list;
|
||||
|
||||
ualni i = 0;
|
||||
for (auto iter : list) {
|
||||
i++;
|
||||
TEST_EQUAL(iter->getVal(), i);
|
||||
list.removeAll();
|
||||
}
|
||||
TEST(i == 4);
|
||||
|
||||
list.removeAll();
|
||||
}
|
||||
|
||||
TEST_DEF(List) {
|
||||
testSimplePointer();
|
||||
testSimpleReference();
|
||||
testSerialization();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,129 +1,124 @@
|
|||
#include "Archiver.hpp"
|
||||
#include "Map.hpp"
|
||||
#include "Testing.hpp"
|
||||
#include "Tests.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
TEST_DEF_STATIC(SimpleReference) {
|
||||
tp::Map<tp::ualni, TestClass, tp::HeapAlloc> map;
|
||||
SUITE(HashTable) {
|
||||
TEST(SimpleReference) {
|
||||
tp::Map<tp::ualni, TestClass, tp::HeapAlloc> map;
|
||||
|
||||
for (auto i : Range(1000, 100000)) {
|
||||
map.put(i, TestClass(i));
|
||||
for (auto i : Range(1000, 100000)) {
|
||||
map.put(i, TestClass(i));
|
||||
}
|
||||
|
||||
for (auto i : Range(1000, 100000)) {
|
||||
CHECK(map.presents(i));
|
||||
CHECK_EQUAL((tp::ualni) map.get(i).getVal(), (tp::ualni) i);
|
||||
}
|
||||
|
||||
for (auto i : Range(1000, 100000)) {
|
||||
map.put(i, TestClass(i));
|
||||
}
|
||||
|
||||
for (auto i : Range(1000, 2000)) {
|
||||
CHECK(map.presents(i));
|
||||
map.remove(i);
|
||||
CHECK(!map.presents(i));
|
||||
}
|
||||
|
||||
for (auto i : Range(2000, 100000)) {
|
||||
CHECK(map.presents(i));
|
||||
CHECK_EQUAL((tp::ualni) map.get(i).getVal(), (tp::ualni) i);
|
||||
}
|
||||
|
||||
for (auto i : map) {
|
||||
i->val.setVal(3);
|
||||
}
|
||||
|
||||
map.removeAll();
|
||||
}
|
||||
|
||||
for (auto i : Range(1000, 100000)) {
|
||||
TEST(map.presents(i));
|
||||
TEST_EQUAL(map.get(i).getVal(), i);
|
||||
TEST(SimplePointer) {
|
||||
tp::Map<tp::ualni, TestClass*, tp::HeapAlloc> map;
|
||||
|
||||
for (auto i : Range(1000)) {
|
||||
map.put(i, new TestClass(i));
|
||||
}
|
||||
|
||||
for (auto i : Range(1000)) {
|
||||
CHECK(map.presents(i));
|
||||
CHECK_EQUAL((tp::ualni) map.get(i)->getVal(), (tp::ualni) i);
|
||||
}
|
||||
|
||||
for (auto i : Range(1000)) {
|
||||
auto del = map.get(i);
|
||||
map.put(i, new TestClass(i));
|
||||
delete del;
|
||||
}
|
||||
|
||||
for (auto i : Range(900, 1000)) {
|
||||
CHECK(map.presents(i));
|
||||
delete map.get(i);
|
||||
map.remove(i);
|
||||
CHECK(!map.presents(i));
|
||||
}
|
||||
|
||||
for (auto i : Range(900)) {
|
||||
CHECK(map.presents(i));
|
||||
CHECK_EQUAL((tp::ualni) map.get(i)->getVal(), (tp::ualni) i);
|
||||
}
|
||||
|
||||
for (auto i : map) {
|
||||
i->val->setVal(3);
|
||||
delete i->val;
|
||||
}
|
||||
|
||||
map.removeAll();
|
||||
}
|
||||
|
||||
for (auto i : Range(1000, 100000)) {
|
||||
map.put(i, TestClass(i));
|
||||
TEST(Copy) {
|
||||
tp::Map<tp::ualni, TestClass, tp::HeapAlloc> map;
|
||||
|
||||
for (auto i : Range(10)) {
|
||||
map.put(i, TestClass(i));
|
||||
}
|
||||
|
||||
tp::Map<tp::ualni, TestClass, tp::HeapAlloc> map2 = map;
|
||||
|
||||
CHECK(map == map2);
|
||||
|
||||
map.removeAll();
|
||||
map2.removeAll();
|
||||
}
|
||||
|
||||
for (auto i : Range(1000, 2000)) {
|
||||
TEST(map.presents(i));
|
||||
map.remove(i);
|
||||
TEST(!map.presents(i));
|
||||
TEST(SaveLoad) {
|
||||
tp::Map<tp::ualni, TestClass, tp::HeapAlloc> map;
|
||||
|
||||
for (auto i : Range(10)) {
|
||||
map.put(i, TestClass(i));
|
||||
}
|
||||
|
||||
ArchiverExample<1024, false> write;
|
||||
ArchiverExample<1024, true> read;
|
||||
|
||||
write % map;
|
||||
|
||||
map.removeAll();
|
||||
|
||||
CHECK(map.size() == 0);
|
||||
|
||||
memCopy(read.mBuff, write.mBuff, sizeof(write.mBuff));
|
||||
|
||||
read % map;
|
||||
|
||||
CHECK(map.size() == 10);
|
||||
|
||||
for (auto i : Range(10)) {
|
||||
CHECK(map.presents(i));
|
||||
CHECK_EQUAL(map.get(i).getVal(), i);
|
||||
}
|
||||
|
||||
map.removeAll();
|
||||
}
|
||||
|
||||
for (auto i : Range(2000, 100000)) {
|
||||
TEST(map.presents(i));
|
||||
TEST_EQUAL(map.get(i).getVal(), i);
|
||||
}
|
||||
|
||||
for (auto i : map) {
|
||||
i->val.setVal(3);
|
||||
}
|
||||
|
||||
map.removeAll();
|
||||
}
|
||||
|
||||
TEST_DEF_STATIC(SimplePointer) {
|
||||
tp::Map<tp::ualni, TestClass*, tp::HeapAlloc> map;
|
||||
|
||||
for (auto i : Range(1000)) {
|
||||
map.put(i, new TestClass(i));
|
||||
}
|
||||
|
||||
for (auto i : Range(1000)) {
|
||||
TEST(map.presents(i));
|
||||
TEST_EQUAL(map.get(i)->getVal(), i);
|
||||
}
|
||||
|
||||
for (auto i : Range(1000)) {
|
||||
auto del = map.get(i);
|
||||
map.put(i, new TestClass(i));
|
||||
delete del;
|
||||
}
|
||||
|
||||
for (auto i : Range(900, 1000)) {
|
||||
TEST(map.presents(i));
|
||||
delete map.get(i);
|
||||
map.remove(i);
|
||||
TEST(!map.presents(i));
|
||||
}
|
||||
|
||||
for (auto i : Range(900)) {
|
||||
TEST(map.presents(i));
|
||||
TEST_EQUAL(map.get(i)->getVal(), i);
|
||||
}
|
||||
|
||||
for (auto i : map) {
|
||||
i->val->setVal(3);
|
||||
delete i->val;
|
||||
}
|
||||
|
||||
map.removeAll();
|
||||
}
|
||||
|
||||
TEST_DEF_STATIC(Copy) {
|
||||
tp::Map<tp::ualni, TestClass, tp::HeapAlloc> map;
|
||||
|
||||
for (auto i : Range(10)) {
|
||||
map.put(i, TestClass(i));
|
||||
}
|
||||
|
||||
tp::Map<tp::ualni, TestClass, tp::HeapAlloc> map2 = map;
|
||||
|
||||
TEST_EQUAL(map, map2);
|
||||
|
||||
map.removeAll();
|
||||
map2.removeAll();
|
||||
}
|
||||
|
||||
TEST_DEF_STATIC(SaveLoad) {
|
||||
tp::Map<tp::ualni, TestClass, tp::HeapAlloc> map;
|
||||
|
||||
for (auto i : Range(10)) {
|
||||
map.put(i, TestClass(i));
|
||||
}
|
||||
|
||||
ArchiverExample<1024, false> write;
|
||||
ArchiverExample<1024, true> read;
|
||||
|
||||
write % map;
|
||||
|
||||
map.removeAll();
|
||||
|
||||
TEST(map.size() == 0);
|
||||
|
||||
memCopy(read.mBuff, write.mBuff, sizeof(write.mBuff));
|
||||
|
||||
read % map;
|
||||
|
||||
TEST(map.size() == 10);
|
||||
|
||||
for (auto i : Range(10)) {
|
||||
TEST(map.presents(i));
|
||||
TEST_EQUAL(map.get(i).getVal(), i);
|
||||
}
|
||||
|
||||
map.removeAll();
|
||||
}
|
||||
|
||||
TEST_DEF(Map) {
|
||||
testSimplePointer();
|
||||
testSimpleReference();
|
||||
testSaveLoad();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +1,19 @@
|
|||
|
||||
#include "Tests.hpp"
|
||||
#include "Testing.hpp"
|
||||
|
||||
static bool init(const tp::ModuleManifest* self) {
|
||||
tp::gTesting.setRootName(self->getName());
|
||||
return true;
|
||||
}
|
||||
#include "UnitTest++/UnitTest++.h"
|
||||
|
||||
int main() {
|
||||
|
||||
tp::ModuleManifest* deps[] = { &tp::gModuleUtils, &tp::gModuleAllocators, nullptr };
|
||||
tp::ModuleManifest testModule("ContainersTest", init, nullptr, deps);
|
||||
tp::ModuleManifest testModule("ContainersTest", nullptr, nullptr, deps);
|
||||
|
||||
if (!testModule.initialize()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
testIntervalTree();
|
||||
testList();
|
||||
testMap();
|
||||
testAvl();
|
||||
testBuffer();
|
||||
testBuffer2d();
|
||||
bool res = UnitTest::RunAllTests();
|
||||
|
||||
testModule.deinitialize();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "UnitTest++/UnitTest++.h"
|
||||
|
||||
#include "Allocators.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
|
|
@ -27,11 +29,4 @@ public:
|
|||
|
||||
[[nodiscard]] tp::ualni getVal() const { return val1; }
|
||||
void setVal(tp::ualni val) { val1 = val; }
|
||||
};
|
||||
|
||||
void testList();
|
||||
void testMap();
|
||||
void testAvl();
|
||||
void testBuffer();
|
||||
void testBuffer2d();
|
||||
void testIntervalTree();
|
||||
};
|
||||
|
|
@ -1,127 +1,124 @@
|
|||
#include "Testing.hpp"
|
||||
#include "Tests.hpp"
|
||||
#include "Tree.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
TEST_DEF_STATIC(Simple) {
|
||||
AvlTree<AvlNumericKey<alni>, TestClass, tp::HeapAlloc> tree;
|
||||
SUITE(AvlTree) {
|
||||
TEST(Simple) {
|
||||
AvlTree<AvlNumericKey<alni>, TestClass, tp::HeapAlloc> tree;
|
||||
|
||||
TEST(tree.size() == 0);
|
||||
TEST(tree.head() == nullptr);
|
||||
CHECK(tree.size() == 0);
|
||||
CHECK(tree.head() == nullptr);
|
||||
|
||||
tree.insert(6, TestClass(6));
|
||||
TEST(tree.isValid());
|
||||
TEST(tree.size() == 1);
|
||||
TEST(tree.head()->data == TestClass(6));
|
||||
tree.insert(6, TestClass(6));
|
||||
CHECK(tree.isValid());
|
||||
CHECK(tree.size() == 1);
|
||||
CHECK(tree.head()->data == TestClass(6));
|
||||
|
||||
tree.remove(6);
|
||||
TEST(tree.isValid());
|
||||
TEST(tree.size() == 0);
|
||||
TEST(tree.head() == nullptr);
|
||||
}
|
||||
|
||||
TEST_DEF_STATIC(Persistance) {
|
||||
AvlTree<AvlNumericKey<alni>, TestClass, tp::HeapAlloc> tree;
|
||||
|
||||
const auto size = 1000;
|
||||
|
||||
struct Item {
|
||||
Item() :
|
||||
data(0) {}
|
||||
bool presents = false;
|
||||
TestClass data;
|
||||
};
|
||||
|
||||
Item buff[size];
|
||||
|
||||
for (auto i : Range(size)) {
|
||||
buff[i].data.setVal(i);
|
||||
tree.remove(6);
|
||||
CHECK(tree.isValid());
|
||||
CHECK(tree.size() == 0);
|
||||
CHECK(tree.head() == nullptr);
|
||||
}
|
||||
|
||||
// random load
|
||||
ualni loadSize = 0;
|
||||
while (loadSize < size / 2) {
|
||||
auto idx = ualni(randomFloat() * (size - 1));
|
||||
DEBUG_ASSERT(idx < size)
|
||||
if (!buff[idx].presents) {
|
||||
tree.insert((alni) buff[idx].data.getVal(), buff[idx].data);
|
||||
loadSize++;
|
||||
buff[idx].presents = true;
|
||||
TEST(Persistance) {
|
||||
AvlTree<AvlNumericKey<alni>, TestClass, tp::HeapAlloc> tree;
|
||||
|
||||
TEST(tree.isValid());
|
||||
TEST(tree.size() == loadSize);
|
||||
const auto size = 1000;
|
||||
|
||||
struct Item {
|
||||
Item() :
|
||||
data(0) {}
|
||||
bool presents = false;
|
||||
TestClass data;
|
||||
};
|
||||
|
||||
Item buff[size];
|
||||
|
||||
for (auto i : Range(size)) {
|
||||
buff[i].data.setVal(i);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& item : buff) {
|
||||
if (item.presents) continue;
|
||||
tree.insert((alni) item.data.getVal(), item.data);
|
||||
loadSize++;
|
||||
item.presents = true;
|
||||
// random load
|
||||
ualni loadSize = 0;
|
||||
while (loadSize < size / 2) {
|
||||
auto idx = ualni(randomFloat() * (size - 1));
|
||||
DEBUG_ASSERT(idx < size)
|
||||
if (!buff[idx].presents) {
|
||||
tree.insert((alni) buff[idx].data.getVal(), buff[idx].data);
|
||||
loadSize++;
|
||||
buff[idx].presents = true;
|
||||
|
||||
TEST(tree.isValid());
|
||||
TEST(tree.size() == loadSize);
|
||||
}
|
||||
|
||||
TEST(tree.size() == size);
|
||||
TEST(tree.maxNode(tree.head())->data.getVal() == size - 1);
|
||||
TEST(tree.minNode(tree.head())->data.getVal() == 0);
|
||||
|
||||
// find
|
||||
for (auto item : buff) {
|
||||
auto node = tree.find((alni) item.data.getVal());
|
||||
TEST(node);
|
||||
if (!node) continue;
|
||||
TEST(node->data.getVal() == item.data.getVal());
|
||||
}
|
||||
|
||||
TEST(!tree.find(size + 1));
|
||||
TEST(!tree.find(-1));
|
||||
|
||||
// random unload
|
||||
ualni unloadSize = 0;
|
||||
while (unloadSize < size / 2) {
|
||||
auto idx = ualni(randomFloat() * (size - 1));
|
||||
if (buff[idx].presents) {
|
||||
|
||||
tree.remove((alni) buff[idx].data.getVal());
|
||||
|
||||
unloadSize++;
|
||||
buff[idx].presents = false;
|
||||
|
||||
// find
|
||||
for (auto item : buff) {
|
||||
if (!item.presents) continue;
|
||||
auto node = tree.find((alni) item.data.getVal());
|
||||
TEST(node);
|
||||
if (!node) continue;
|
||||
TEST(node->data.getVal() == item.data.getVal());
|
||||
CHECK(tree.isValid());
|
||||
CHECK(tree.size() == loadSize);
|
||||
}
|
||||
|
||||
TEST(tree.isValid());
|
||||
TEST(tree.size() == size - unloadSize);
|
||||
}
|
||||
|
||||
for (auto& item : buff) {
|
||||
if (item.presents) continue;
|
||||
tree.insert((alni) item.data.getVal(), item.data);
|
||||
loadSize++;
|
||||
item.presents = true;
|
||||
|
||||
CHECK(tree.isValid());
|
||||
CHECK(tree.size() == loadSize);
|
||||
}
|
||||
|
||||
CHECK(tree.size() == size);
|
||||
CHECK(tree.maxNode(tree.head())->data.getVal() == size - 1);
|
||||
CHECK(tree.minNode(tree.head())->data.getVal() == 0);
|
||||
|
||||
// find
|
||||
for (auto item : buff) {
|
||||
auto node = tree.find((alni) item.data.getVal());
|
||||
CHECK(node);
|
||||
if (!node) continue;
|
||||
CHECK(node->data.getVal() == item.data.getVal());
|
||||
}
|
||||
|
||||
CHECK(!tree.find(size + 1));
|
||||
CHECK(!tree.find(-1));
|
||||
|
||||
// random unload
|
||||
ualni unloadSize = 0;
|
||||
while (unloadSize < size / 2) {
|
||||
auto idx = ualni(randomFloat() * (size - 1));
|
||||
if (buff[idx].presents) {
|
||||
|
||||
tree.remove((alni) buff[idx].data.getVal());
|
||||
|
||||
unloadSize++;
|
||||
buff[idx].presents = false;
|
||||
|
||||
// find
|
||||
for (auto item : buff) {
|
||||
if (!item.presents) continue;
|
||||
auto node = tree.find((alni) item.data.getVal());
|
||||
CHECK(node);
|
||||
if (!node) continue;
|
||||
CHECK(node->data.getVal() == item.data.getVal());
|
||||
}
|
||||
|
||||
CHECK(tree.isValid());
|
||||
CHECK(tree.size() == size - unloadSize);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& item : buff) {
|
||||
if (item.presents) {
|
||||
tree.remove((alni) item.data.getVal());
|
||||
unloadSize++;
|
||||
item.presents = false;
|
||||
|
||||
CHECK(tree.isValid());
|
||||
CHECK(tree.size() == size - unloadSize);
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(tree.size() == 0);
|
||||
CHECK(tree.head() == nullptr);
|
||||
CHECK(tree.maxNode(tree.head()) == nullptr);
|
||||
CHECK(tree.minNode(tree.head()) == nullptr);
|
||||
}
|
||||
|
||||
for (auto& item : buff) {
|
||||
if (item.presents) {
|
||||
tree.remove((alni) item.data.getVal());
|
||||
unloadSize++;
|
||||
item.presents = false;
|
||||
|
||||
TEST(tree.isValid());
|
||||
TEST(tree.size() == size - unloadSize);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(tree.size() == 0);
|
||||
TEST(tree.head() == nullptr);
|
||||
TEST(tree.maxNode(tree.head()) == nullptr);
|
||||
TEST(tree.minNode(tree.head()) == nullptr);
|
||||
}
|
||||
|
||||
TEST_DEF(Avl) {
|
||||
testSimple();
|
||||
testPersistance();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue