xo-alloc2 xo-gc: assorted utest-guided cleanup ++ coverage

This commit is contained in:
Roland Conybeare 2026-05-10 18:19:41 -04:00
commit 08df9a5635
6 changed files with 57 additions and 16 deletions

View file

@ -0,0 +1,11 @@
/** @file X1CollectorIterator.hpp
*
* @author Roland Conybeare, May 2026
**/
#pragma once
#include "DX1CollectorIterator.hpp"
#include "detail/IAllocIterator_DX1CollectorIterator.hpp"
/* end X1CollectorIterator.hpp */

View file

@ -5,6 +5,7 @@
#include "setup_gc.hpp"
#include "X1Collector.hpp"
#include "X1CollectorIterator.hpp"
#include "GCObjectStoreVisitor.hpp"
#include <xo/facet/FacetRegistry.hpp>
#include <xo/indentlog/scope.hpp>
@ -25,10 +26,12 @@ namespace xo {
FacetRegistry::register_impl<AAllocator, DX1Collector>();
FacetRegistry::register_impl<ACollector, DX1Collector>();
FacetRegistry::register_impl<AAllocIterator, DX1CollectorIterator>();
FacetRegistry::register_impl<AGCObjectVisitor, DGCObjectStoreVisitor>();
log && log(xtag("DX1Collector.tseq", typeseq::id<DX1Collector>()));
log && log(xtag("DX1CollectorIterator.tseq", typeseq::id<DX1CollectorIterator>()));
log && log(xtag("DGCObjectStoreVisitor.tseq", typeseq::id<DGCObjectStoreVisitor>()));
log && log(xtag("ACollector.tseq", typeseq::id<ACollector>()));

View file

@ -39,6 +39,7 @@ namespace xo {
using xo::mm::AllocHeader;
using xo::mm::Generation;
using xo::mm::c_max_generation;
using xo::facet::DVariantPlaceholder;
using xo::facet::with_facet;
using xo::reflect::typeseq;
using xo::scope;
@ -60,7 +61,7 @@ namespace xo {
REQUIRE(!gc1);
REQUIRE(gc1.iface() != nullptr);
REQUIRE(gc1.data() == nullptr);
REQUIRE(gc1._typeseq() == typeseq::id<ICollector_Any>());
REQUIRE(gc1._typeseq() == typeseq::id<DVariantPlaceholder>());
}
TEST_CASE("DX1Collector-1", "[alloc2][gc][DX1Collector]")
@ -187,6 +188,15 @@ namespace xo {
{
scope log(XO_DEBUG(false), "DX1Collector alloc test");
constexpr uint32_t c_n_alloc = 25;
constexpr uint32_t c_reserved_z = 4*1024*1024;
constexpr uint32_t c_max_alloc = c_reserved_z / c_n_alloc;
// allowance for per-alloc overhead
constexpr uint32_t c_max_alloc_payload = c_max_alloc - 32;
static_assert(c_max_alloc > 0);
static_assert(c_max_alloc_payload < c_max_alloc);
ArenaConfig arena_cfg = { .name_ = "_test_unused",
.size_ = 4*1024*1024,
.store_header_flag_ = true,
@ -226,16 +236,25 @@ namespace xo {
auto rng = rng::xoshiro256ss(seed);
bool catch_flag = false;
REQUIRE(utest::AllocUtil::random_allocs(25, catch_flag, &rng, x1alloc));
REQUIRE(utest::AllocUtil::random_allocs(c_n_alloc, c_max_alloc_payload,
catch_flag, &rng, x1alloc));
}
TEST_CASE("collector-x1-alloc2", "[alloc2][gc]")
{
scope log(XO_DEBUG(false),
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag),
"DX1Collector alloc test2");
ArenaConfig arena_cfg = { .name_ = "_test_unused",
.size_ = 4*1024*1024,
constexpr uint32_t c_n_alloc = 25;
constexpr uint32_t c_reserved_z = 4*1024*1024;
constexpr uint32_t c_max_alloc = c_reserved_z / c_n_alloc;
// allowance for per-alloc overhead
constexpr uint32_t c_max_alloc_payload = c_max_alloc - 32;
ArenaConfig arena_cfg = {
.name_ = "_test_unused",
.size_ = c_reserved_z,
.store_header_flag_ = true,
.header_ = AllocHeaderConfig(8 /*guard_z*/,
0xfd /*guard-byte*/,
@ -277,7 +296,8 @@ namespace xo {
// these are not gc-aware objects.
// just testing ability to work as a low-level allocator
REQUIRE(utest::AllocUtil::random_allocs(25, false, &rng, x1alloc));
REQUIRE(utest::AllocUtil::random_allocs(c_n_alloc, c_max_alloc_payload,
c_debug_flag, &rng, x1alloc));
}
namespace {

View file

@ -179,8 +179,8 @@ namespace xo {
obj<AAllocIterator> ix = range.begin();
obj<AAllocIterator> end_ix = range.end();
REQUIRE(ix._typeseq() == typeseq::id<DArenaIterator>());
REQUIRE(end_ix._typeseq() == typeseq::id<DArenaIterator>());
REQUIRE(ix._typeseq() == typeseq::id<DX1CollectorIterator>());
REQUIRE(end_ix._typeseq() == typeseq::id<DX1CollectorIterator>());
REQUIRE(ix.iface());
REQUIRE(ix.data());
REQUIRE(end_ix.iface());

View file

@ -39,6 +39,7 @@ namespace utest {
bool
AllocUtil::random_allocs(uint32_t n_alloc,
uint32_t max_alloc_z,
bool catch_flag,
xoshiro256ss * p_rgen,
obj<AAllocator> mm)
@ -64,6 +65,8 @@ namespace utest {
double si = ngen(*p_rgen);
double zi = ::pow(2.0, si);
std::size_t z = ::ceil(zi);
if (z > max_alloc_z)
z = max_alloc_z;
bool ok_flag = true;
@ -132,7 +135,7 @@ namespace utest {
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, (uint8_t)*p == info.guard_byte());
}
REQUIRE_ORFAIL(ok_flag, catch_flag,
@ -146,7 +149,7 @@ namespace utest {
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());
REQUIRE_ORFAIL(ok_flag, catch_flag, (uint8_t)*p == info.guard_byte());
}

View file

@ -34,8 +34,12 @@ namespace utest {
/** generate a random sequence of allocations.
* verify allocator behavior
*
* Will not alloc more than n_alloc * max_alloc_z bytes
* (not counting allocator overhead)
**/
static bool random_allocs(std::uint32_t n_alloc,
std::uint32_t max_alloc_z,
bool catch_flag,
xo::rng::xoshiro256ss * p_rgen,
xo::facet::obj<AAllocator> alloc);