diff --git a/test/unit/meson.build b/test/unit/meson.build
index 5086fca..9fa0534 100644
--- a/test/unit/meson.build
+++ b/test/unit/meson.build
@@ -11,6 +11,7 @@ unit_test_prog = executable(meson.project_name(),
'tiger_test.cpp',
'infix_iterator.cpp',
'tree_iterator_test.cpp',
+ 'small_object_allocator_test.cpp',
install: false,
dependencies: [sprout_dep, catch2_dep],
include_directories: [public_incl],
diff --git a/test/unit/small_object_allocator_test.cpp b/test/unit/small_object_allocator_test.cpp
new file mode 100644
index 0000000..a7258ab
--- /dev/null
+++ b/test/unit/small_object_allocator_test.cpp
@@ -0,0 +1,75 @@
+/* Copyright 2016-2024 Michele Santullo
+ * This file is part of "duckhandy".
+ *
+ * "duckhandy" is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * "duckhandy" is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with "duckhandy". If not, see .
+ */
+
+#include "catch2/catch_test_macros.hpp"
+#include "duckhandy/small_object_allocator.hpp"
+#include
+
+namespace {
+static const void* g_alloc_last{nullptr};
+static std::size_t g_alloc_count{0};
+
+template
+struct TestAlloc {
+ std::unique_ptr operator()() {
+ auto ret = std::make_unique();
+ g_alloc_last = ret.get();
+ ++g_alloc_count;
+ return ret;
+ }
+};
+} //unnamed namespace
+
+TEST_CASE("Check SmallObjectAllocator", "[SmallObjectAllocator][containers][memory][allocators]") {
+ dhandy::SmallObjectAllocator soa;
+ CHECK(g_alloc_last == nullptr);
+ CHECK(g_alloc_count == 0u);
+
+ int* const int01 = soa.allocate(sizeof(int));
+ const void* old_block = g_alloc_last;
+ REQUIRE(int01 != nullptr);
+ CHECK(g_alloc_last != nullptr);
+ CHECK(g_alloc_count == 1);
+
+ int* const int02 = soa.allocate(sizeof(int));
+ REQUIRE(int02 != nullptr);
+ CHECK(int01 != int02);
+ CHECK(g_alloc_last == old_block);
+ CHECK(g_alloc_count == 1);
+
+ int* prev_int = int02;
+ for (std::size_t z = 2; z < dhandy::SmallObjectAllocator::objects_per_block; ++z) {
+ int* const new_int = soa.allocate(sizeof(int));
+ REQUIRE(new_int != nullptr);
+ CHECK(new_int != int01);
+ CHECK(new_int != prev_int);
+ prev_int = new_int;
+ CHECK(g_alloc_last == old_block);
+ CHECK(g_alloc_count == 1);
+ CHECK(reinterpret_cast(new_int) % alignof(int) == 0);
+ }
+
+ int* const int03 = soa.allocate(sizeof(int));
+ REQUIRE(int03 != nullptr);
+ CHECK(int03 != int02);
+ CHECK(int03 != int01);
+ CHECK(g_alloc_last != old_block);
+ old_block = g_alloc_last;
+ CHECK(g_alloc_count == 2);
+
+ soa.deallocate(int02, sizeof(int));
+}