From 7ae1a34ed30b401132acfdc4d7f5c08a248351ba Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Tue, 16 Dec 2025 23:00:00 -0500 Subject: [PATCH] xo-alloc2: utest: check guard bytes --- include/xo/alloc2/alloc/AllocInfo.hpp | 4 ++ utest/Collector.test.cpp | 41 ++++++++++++++++++ utest/random_allocs.cpp | 61 ++++++++++++++++++++++++++- 3 files changed, 104 insertions(+), 2 deletions(-) diff --git a/include/xo/alloc2/alloc/AllocInfo.hpp b/include/xo/alloc2/alloc/AllocInfo.hpp index eead62c..28a1bbd 100644 --- a/include/xo/alloc2/alloc/AllocInfo.hpp +++ b/include/xo/alloc2/alloc/AllocInfo.hpp @@ -48,6 +48,10 @@ namespace xo { size_type size() const noexcept { return p_config_->size(*p_header_); } /** Guard bytes immediately following allocation **/ span_type guard_hi() const noexcept; + /** Number of guard bytes **/ + size_type guard_z() const noexcept { return p_config_->guard_z_; } + /** Value (fixed test pattern) of guard byte **/ + char guard_byte() const noexcept { return p_config_->guard_byte_; } const AllocHeaderConfig * p_config_ = nullptr; const byte * p_guard_lo_ = nullptr; diff --git a/utest/Collector.test.cpp b/utest/Collector.test.cpp index 789c149..9280e69 100644 --- a/utest/Collector.test.cpp +++ b/utest/Collector.test.cpp @@ -187,6 +187,47 @@ namespace xo { utest::AllocUtil::random_allocs(25, true, &rng, x1alloc); } + + TEST_CASE("collector-x1-alloc2", "[alloc2][gc]") + { + ArenaConfig arena_cfg = { .name_ = "_test_unused", + .size_ = 4*1024*1024, + .store_header_flag_ = true, + .header_ = AllocHeaderConfig(8 /*guard_z*/, + 0xfd /*guard-byte*/, + 0 /*tseq-bits*/, + 0 /*age-bits*/, + 16 /*size-bits*/), }; + + /* collector with one generation collapses to a non-generational copying collector */ + CollectorConfig cfg = { .arena_config_ = arena_cfg, + .n_generation_ = 1, + .gc_trigger_v_ = {{64*1024, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}} }; + + /* X1 allocator+collector */ + DX1Collector x1state = DX1Collector{cfg}; + + /* typed collector i/face */ + auto x1gc = with_facet::mkobj(&x1state); + /* typed allocator i/face */ + auto x1alloc = with_facet::mkobj(&x1state); + + REQUIRE(x1gc.iface()); + REQUIRE(x1gc.data()); + + REQUIRE(x1alloc.iface()); + REQUIRE(x1alloc.data()); + + rng::Seed seed; + std::cerr << "ratio: seed=" << seed << std::endl; + + auto rng = rng::xoshiro256ss(seed); + + utest::AllocUtil::random_allocs(25, true, &rng, x1alloc); + } } } diff --git a/utest/random_allocs.cpp b/utest/random_allocs.cpp index 58580ff..a480310 100644 --- a/utest/random_allocs.cpp +++ b/utest/random_allocs.cpp @@ -100,11 +100,68 @@ namespace utest { AllocInfo info = mm.alloc_info(mem); REQUIRE_ORFAIL(ok_flag, catch_flag, info.is_valid()); - REQUIRE_ORFAIL(ok_flag, catch_flag, info.size() == padding::with_padding(z)); + + REQUIRE_ORFAIL(ok_flag, catch_flag, + info.size() == padding::with_padding(z)); + /* age isn't configured -> 0 = sentinel */ REQUIRE_ORFAIL(ok_flag, catch_flag, info.age() == 0); - /* tseq isn't confrigured -> 0 = sentinel */ + /* tseq isn't configured -> 0 = sentinel */ REQUIRE_ORFAIL(ok_flag, catch_flag, info.tseq() == 0); + + if ((info.p_config_->guard_z_ > 0) + || info.guard_lo().first + || info.guard_lo().second + || info.guard_hi().first + || info.guard_hi().second) + { + REQUIRE_ORFAIL(ok_flag, catch_flag, + info.guard_lo().first != nullptr); + REQUIRE_ORFAIL(ok_flag, catch_flag, + info.guard_lo().second != nullptr); + REQUIRE_ORFAIL(ok_flag, catch_flag, + info.guard_lo().first + info.guard_z() + == info.guard_lo().second); + + for (const byte * p = info.guard_lo().first; + p != info.guard_lo().second; ++p) + { + REQUIRE_ORFAIL(ok_flag, catch_flag, (char)*p == info.guard_byte()); + } + + REQUIRE_ORFAIL(ok_flag, catch_flag, + info.guard_hi().first != nullptr); + REQUIRE_ORFAIL(ok_flag, catch_flag, + info.guard_hi().second != nullptr); + REQUIRE_ORFAIL(ok_flag, catch_flag, + info.guard_hi().first + info.guard_z() + == info.guard_hi().second); + + for (const byte * p = info.guard_hi().first; + p != info.guard_hi().second; ++p) + { + REQUIRE_ORFAIL(ok_flag, catch_flag, (char)*p == info.guard_byte()); + } + + + } else { + /* control here only if all of: + * - guard_z is zero + * - guard_lo empty + * - guard_hi empty + */ + + REQUIRE_ORFAIL(ok_flag, catch_flag, + info.guard_lo().first == nullptr); + REQUIRE_ORFAIL(ok_flag, catch_flag, + info.guard_lo().second == nullptr); + + REQUIRE_ORFAIL(ok_flag, catch_flag, + info.guard_hi().first == nullptr); + REQUIRE_ORFAIL(ok_flag, catch_flag, + info.guard_hi().second == nullptr); + + } } return true;