From 4244b2cd7c490dfa94ad91c8c081503fce9a3629 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Fri, 16 Jan 2026 17:02:10 -0500 Subject: [PATCH] xo-expression2: + X1Collector test for DUniqueString --- .../include/xo/expression2/DUniqueString.hpp | 2 + .../expression2_register_facets.cpp | 3 + xo-expression2/utest/CMakeLists.txt | 1 + xo-expression2/utest/X1Collector.test.cpp | 115 ++++++++++++++++++ 4 files changed, 121 insertions(+) create mode 100644 xo-expression2/utest/X1Collector.test.cpp diff --git a/xo-expression2/include/xo/expression2/DUniqueString.hpp b/xo-expression2/include/xo/expression2/DUniqueString.hpp index 32a26726..4d7dc0fd 100644 --- a/xo-expression2/include/xo/expression2/DUniqueString.hpp +++ b/xo-expression2/include/xo/expression2/DUniqueString.hpp @@ -3,6 +3,8 @@ * @author Roland Conybeare, Jan 2026 **/ +#pragma once + #include namespace xo { diff --git a/xo-expression2/src/expression2/expression2_register_facets.cpp b/xo-expression2/src/expression2/expression2_register_facets.cpp index 56ac85ae..6a0f9c80 100644 --- a/xo-expression2/src/expression2/expression2_register_facets.cpp +++ b/xo-expression2/src/expression2/expression2_register_facets.cpp @@ -14,6 +14,7 @@ namespace xo { using xo::mm::AGCObject; using xo::facet::FacetRegistry; + using xo::facet::typeseq; namespace scm { bool @@ -23,6 +24,8 @@ namespace xo { FacetRegistry::register_impl(); + log && log(xtag("DUniqueString.tseq", typeseq::id())); + return true; } } /*namespace scm*/ diff --git a/xo-expression2/utest/CMakeLists.txt b/xo-expression2/utest/CMakeLists.txt index e43fd217..2b8bceec 100644 --- a/xo-expression2/utest/CMakeLists.txt +++ b/xo-expression2/utest/CMakeLists.txt @@ -4,6 +4,7 @@ set(UTEST_EXE utest.expression2) set(UTEST_SRCS expression2_utest_main.cpp StringTable.test.cpp + X1Collector.test.cpp ) xo_add_utest_executable(${UTEST_EXE} ${UTEST_SRCS}) diff --git a/xo-expression2/utest/X1Collector.test.cpp b/xo-expression2/utest/X1Collector.test.cpp new file mode 100644 index 00000000..a664f9a2 --- /dev/null +++ b/xo-expression2/utest/X1Collector.test.cpp @@ -0,0 +1,115 @@ +/** @file X1Collector.test.cpp + * + * Minimal collector test for DUniqueString + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "init_expression2.hpp" +#include "StringTable.hpp" +#include "detail/IGCObject_DUniqueString.hpp" + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include + +#include + +namespace ut { + using xo::S_expression2_tag; + using xo::scm::StringTable; + using xo::scm::DUniqueString; + using xo::scm::DFloat; + using xo::scm::DInteger; + using xo::scm::DList; + using xo::scm::DString; + using xo::mm::CollectorTypeRegistry; + using xo::mm::AAllocator; + using xo::mm::ACollector; + using xo::mm::AGCObject; + using xo::mm::DX1Collector; + using xo::mm::CollectorConfig; + using xo::mm::ArenaConfig; + using xo::facet::with_facet; + using xo::facet::typeseq; + using xo::InitEvidence; + using xo::InitSubsys; + + // Ensure subsystem initialized before tests + static InitEvidence s_init = InitSubsys::require(); + + TEST_CASE("x1_duniquestring", "[gc][x1][expression2]") + { + REQUIRE(s_init.evidence()); + + // Create collector + CollectorConfig cfg{ + .name_ = "x1_duniquestring_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{1024, 1024}}, + .debug_flag_ = false, + }; + + DX1Collector gc(cfg); + + auto gc_o = with_facet::mkobj(&gc); + auto c_o = with_facet::mkobj(&gc); + + // Install types from CollectorTypeRegistry + bool ok = CollectorTypeRegistry::instance().install_types(c_o); + REQUIRE(ok); + + // Verify types from object2 are installed + ok = c_o.is_type_installed(typeseq::id()); + REQUIRE(ok); + ok = c_o.is_type_installed(typeseq::id()); + REQUIRE(ok); + ok = c_o.is_type_installed(typeseq::id()); + REQUIRE(ok); + ok = c_o.is_type_installed(typeseq::id()); + REQUIRE(ok); + + // Verify DUniqueString from expression2 is installed + ok = c_o.is_type_installed(typeseq::id()); + REQUIRE(ok); + + // Create DUniqueString via StringTable + StringTable table(1024); + const DUniqueString * ustr = table.intern("hello"); + REQUIRE(ustr != nullptr); + REQUIRE(ustr->size() == 5); + + // Wrap as obj + // Note: const_cast is safe here since DUniqueString is immutable by design, + // and we're only wrapping for facet access, not modification + auto ustr_o = with_facet::mkobj(const_cast(ustr)); + REQUIRE(ustr_o.iface() != nullptr); + REQUIRE(ustr_o.data() != nullptr); + + // verify unique string contents + REQUIRE(strcmp(ustr_o.data()->chars(), "hello") == 0); + + // Add as gc root + c_o.add_gc_root(&ustr_o); + + // Verify string content accessible through wrapped object + REQUIRE(ustr_o.data()->size() == 5); + REQUIRE(std::strcmp(ustr_o.data()->chars(), "hello") == 0); + } +} + +/* end X1Collector.test.cpp */