basedOpinionated utility library |
git clone git://git.dimitrijedobrota.com/based.git |
Log | Files | Refs | README | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING |
commit | 7387b8bdd6f937ba2d48bf3878ddca9feba39b31 |
parent | fdf5dc326745b5c66b5d075ce4fd7be4ab0494b2 |
author | Dimitrije Dobrota <mail@dimitrijedobrota.com> |
date | Thu, 3 Apr 2025 21:41:09 +0200 |
Test list
Diffstat:M | include/based/list.hpp | | | ++++++++++++-- |
M | test/CMakeLists.txt | | | +++ |
A | test/source/list_test.cpp | | | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
3 files changed, 149 insertions(+), 2 deletions(-)
diff --git a/include/based/list.hpp b/include/based/list.hpp
@@ -1,5 +1,6 @@
#pragma once
#include <cassert>
#include <functional>
#include <utility>
#include <vector>
@@ -26,8 +27,17 @@ private:
std::vector<node_t> m_pool;
list_type m_free_list;
const node_t& node(list_type x) const { return m_pool[x - 1]; }
node_t& node(list_type x) { return m_pool[x - 1]; }
const node_t& node(list_type x) const
{
assert(x != 0);
return m_pool[x - 1];
}
node_t& node(list_type x)
{
assert(x != 0);
return m_pool[x - 1];
}
list_type new_node()
{
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
@@ -28,6 +28,9 @@ add_test(max_test)
add_test(max_element_test)
add_test(minmax_element_test)
# ---- List ----
add_test(list_test)
# ---- End-of-file commands ----
add_folders(Test)
diff --git a/test/source/list_test.cpp b/test/source/list_test.cpp
@@ -0,0 +1,134 @@
#include <numeric>
#include "based/list.hpp"
#include <catch2/catch_test_macros.hpp>
TEST_CASE("list_pool", "[list/list_pool]")
{
using list_pool = based::list_pool<std::uint8_t, std::uint8_t>;
auto pool = list_pool();
auto head = pool.node_empty();
SECTION("node_empty is empty")
{
REQUIRE(pool.is_empty(head) == true);
REQUIRE(pool.node_empty() == head);
}
SECTION("add one node")
{
head = pool.allocate(1, head);
REQUIRE(pool.is_empty(head) == false);
REQUIRE(pool.value(head) == 1);
REQUIRE(pool.next(head) == pool.node_empty());
SECTION("add two nodes")
{
head = pool.allocate(2, head);
REQUIRE(pool.is_empty(head) == false);
REQUIRE(pool.value(head) == 2);
REQUIRE(pool.value(pool.next(head)) == 1);
REQUIRE(pool.next(pool.next(head)) == pool.node_empty());
head = pool.free(head);
}
SECTION("alloc after free")
{
head = pool.allocate(2, head);
head = pool.free(head);
head = pool.allocate(3, head);
REQUIRE(pool.is_empty(head) == false);
REQUIRE(pool.value(head) == 3);
head = pool.free(head);
}
head = pool.free(head);
}
REQUIRE(pool.is_empty(head) == true);
REQUIRE(pool.node_empty() == head);
}
TEST_CASE("list_pool iterator", "[list/list_pool/iterator]")
{
using list_pool = based::list_pool<std::uint8_t, std::uint8_t>;
using iter = list_pool::iterator;
auto pool = list_pool();
auto head = pool.node_empty();
for (std::uint8_t i = 0; i < 0xFF; i++) {
head = pool.allocate(i, head);
}
SECTION("for-loop")
{
std::uint64_t sum = 0;
for (auto it = iter(pool, head); it != iter(pool); ++it) {
sum += *it;
}
REQUIRE(sum == 0xFF * 0xFE / 2);
}
SECTION("accumulate")
{
const auto sum = std::accumulate(iter(pool, head),
iter(pool),
std::uint64_t {0},
[](auto a, auto b) { return a + b; });
REQUIRE(sum == 0xFF * 0xFE / 2);
}
based::free_list(pool, head);
}
TEST_CASE("list_pool queue", "[list/list_pool/queue]")
{
using list_pool = based::list_pool<std::uint8_t, std::uint8_t>;
using iter = list_pool::iterator;
auto pool = list_pool();
auto queue = pool.queue_empty();
SECTION("free(empty, empty)")
{
REQUIRE(pool.free(queue.first, queue.second) == pool.node_empty());
}
SECTION("pop_front(empty)")
{
REQUIRE(pool.pop_front(queue) == queue);
}
for (std::uint8_t i = 0; i < 0xFF; i++) {
if (i % 2 == 0) {
queue = pool.push_front(queue, i);
} else {
queue = pool.push_back(queue, i);
}
if (i % 3 == 0) {
queue = pool.pop_front(queue);
}
}
std::uint64_t sum = 0;
for (auto it = iter(pool, queue.first); it != iter(pool); ++it) {
sum += *it;
}
pool.free(queue);
REQUIRE(sum == 21717);
}