aboutsummaryrefslogtreecommitdiffstats
path: root/test/MultigroupCodec.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/MultigroupCodec.cpp')
-rw-r--r--test/MultigroupCodec.cpp130
1 files changed, 0 insertions, 130 deletions
diff --git a/test/MultigroupCodec.cpp b/test/MultigroupCodec.cpp
deleted file mode 100644
index b04c405..0000000
--- a/test/MultigroupCodec.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-#include <catch2/catch_test_macros.hpp>
-
-#include "InMemoryBackend.h"
-#include "MultigroupCodec.h"
-
-#include <string>
-#include <vector>
-
-// ---------------------------------------------------------------------------
-// Multigroup snapshot — Merkle<string> tree mapping relation name → relation root.
-//
-// The codec is a thin facade over Merkle<std::string>; these tests confirm
-// the tree is order-independent (it sorts intrinsically), that mutations are
-// path-localised (sibling entries are untouched), and that snapshots can be
-// re-enumerated from a cold backend by hash alone.
-// ---------------------------------------------------------------------------
-
-namespace {
-
- // Pad a short label into a deterministic 64-char hex string so the codec can
- // decode it as a 32-byte payload.
- std::string mk_root(char c, char d = '0') {
- std::string h(64, '0');
- h[0] = c;
- h[1] = d;
- return h;
- }
-
-} // namespace
-
-TEST_CASE("Build is order-independent - tree sorts intrinsically", "[multigroup-codec]") {
- nt::InMemoryBackend a, b;
-
- std::vector<nt::MultigroupCodec::RelationEntry> in_order = {
- {"alpha", mk_root('a')},
- {"bravo", mk_root('b')},
- {"charlie", mk_root('c')},
- };
- std::vector<nt::MultigroupCodec::RelationEntry> shuffled = {
- {"charlie", mk_root('c')},
- {"alpha", mk_root('a')},
- {"bravo", mk_root('b')},
- };
-
- REQUIRE(nt::MultigroupCodec::Build(a, in_order) == nt::MultigroupCodec::Build(b, shuffled));
-}
-
-TEST_CASE("Build distinguishes content changes", "[multigroup-codec]") {
- nt::InMemoryBackend backend;
-
- std::vector<nt::MultigroupCodec::RelationEntry> base = {{"foo", mk_root('a')}};
- std::vector<nt::MultigroupCodec::RelationEntry> different_root = {{"foo", mk_root('b')}};
- std::vector<nt::MultigroupCodec::RelationEntry> different_name = {{"bar", mk_root('a')}};
- std::vector<nt::MultigroupCodec::RelationEntry> extra_member = {{"foo", mk_root('a')},
- {"bar", mk_root('b')}};
-
- const auto h_base = nt::MultigroupCodec::Build(backend, base);
- REQUIRE(h_base != nt::MultigroupCodec::Build(backend, different_root));
- REQUIRE(h_base != nt::MultigroupCodec::Build(backend, different_name));
- REQUIRE(h_base != nt::MultigroupCodec::Build(backend, extra_member));
-}
-
-TEST_CASE("Build then List round-trips entries in key-sorted order", "[multigroup-codec]") {
- nt::InMemoryBackend backend;
-
- std::vector<nt::MultigroupCodec::RelationEntry> entries = {
- {"foo", mk_root('a', '1')},
- {"bar", mk_root('b', '2')},
- {"baz", mk_root('c', '3')},
- };
- const auto root = nt::MultigroupCodec::Build(backend, entries);
-
- auto listed = nt::MultigroupCodec::List(backend, root);
- REQUIRE(listed.size() == 3);
- REQUIRE(listed[0].first == "bar");
- REQUIRE(listed[1].first == "baz");
- REQUIRE(listed[2].first == "foo");
- REQUIRE(listed[0].second == mk_root('b', '2'));
-}
-
-TEST_CASE("Lookup returns payload by name", "[multigroup-codec]") {
- nt::InMemoryBackend backend;
-
- std::vector<nt::MultigroupCodec::RelationEntry> entries = {
- {"foo", mk_root('a')},
- {"bar", mk_root('b')},
- };
- const auto root = nt::MultigroupCodec::Build(backend, entries);
-
- REQUIRE(nt::MultigroupCodec::Lookup(backend, root, "foo") == mk_root('a'));
- REQUIRE(nt::MultigroupCodec::Lookup(backend, root, "bar") == mk_root('b'));
- REQUIRE(nt::MultigroupCodec::Lookup(backend, root, "missing").empty());
-}
-
-TEST_CASE("InsertOne mutates one entry; sibling subtree is untouched", "[multigroup-codec]") {
- nt::InMemoryBackend backend;
-
- std::vector<nt::MultigroupCodec::RelationEntry> entries = {
- {"foo", mk_root('a')},
- {"bar", mk_root('b')},
- };
- const auto root0 = nt::MultigroupCodec::Build(backend, entries);
-
- // Mutate foo only; bar's payload must round-trip unchanged.
- const auto root1 = nt::MultigroupCodec::InsertOne(backend, root0, "foo", mk_root('d'));
- REQUIRE(root1 != root0);
- REQUIRE(nt::MultigroupCodec::Lookup(backend, root1, "foo") == mk_root('d'));
- REQUIRE(nt::MultigroupCodec::Lookup(backend, root1, "bar") == mk_root('b'));
-}
-
-TEST_CASE("RemoveOne deletes one entry; sibling preserved", "[multigroup-codec]") {
- nt::InMemoryBackend backend;
-
- std::vector<nt::MultigroupCodec::RelationEntry> entries = {
- {"foo", mk_root('a')},
- {"bar", mk_root('b')},
- };
- const auto root0 = nt::MultigroupCodec::Build(backend, entries);
-
- const auto root1 = nt::MultigroupCodec::RemoveOne(backend, root0, "foo");
- REQUIRE(nt::MultigroupCodec::Lookup(backend, root1, "foo").empty());
- REQUIRE(nt::MultigroupCodec::Lookup(backend, root1, "bar") == mk_root('b'));
-}
-
-TEST_CASE("Empty multigroup builds to an empty root", "[multigroup-codec]") {
- nt::InMemoryBackend backend;
- std::vector<nt::MultigroupCodec::RelationEntry> empty;
- REQUIRE(nt::MultigroupCodec::Build(backend, empty).empty());
- REQUIRE(nt::MultigroupCodec::List(backend, "").empty());
-}