From 8d8bc8b92886245f403447ad4d24c6625a97022a Mon Sep 17 00:00:00 2001 From: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com> Date: Tue, 21 Jul 2026 11:41:29 +0100 Subject: [PATCH] fix(telemetry): widen death-test regex for split assert literal, skip under NDEBUG Co-Authored-By: Claude Opus 4.8 (1M context) --- .../libxrpl/telemetry/SpanGuardScope.cpp | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/tests/libxrpl/telemetry/SpanGuardScope.cpp b/src/tests/libxrpl/telemetry/SpanGuardScope.cpp index 54612057bf..9295086a3a 100644 --- a/src/tests/libxrpl/telemetry/SpanGuardScope.cpp +++ b/src/tests/libxrpl/telemetry/SpanGuardScope.cpp @@ -403,8 +403,28 @@ TEST_F(SpanGuardScopeTest, root_then_detached_is_root_and_leaves_stack_clean) // checks it dies -- observes the crash. The regex matches the assert message // substring rather than the whole line, because the file:line/function prefix // glibc prints around it is platform and compiler dependent. +// +// The test is skipped where the assertion cannot fire: under NDEBUG (Release +// builds) XRPL_ASSERT is a no-op, and under ENABLE_VOIDSTAR a failed assert +// continues instead of aborting -- in both cases the worker would not crash and +// EXPECT_DEATH would report a spurious failure. TEST_F(SpanGuardScopeTest, non_detached_cross_thread_death_asserts_at_wrong_thread_destroy) { + // XRPL_ASSERT only aborts when assertions are live. Under NDEBUG (Release + // builds) it expands to assert(), which the C standard strips to a no-op, + // so the worker thread destroys the guard without crashing. Under + // ENABLE_VOIDSTAR (Antithesis fuzzing) a failed XRPL_ASSERT continues + // execution instead of aborting. In either case the process does not die + // and EXPECT_DEATH would fail, so skip this test there. The two macros are + // mutually exclusive (instrumentation.h #errors on ENABLE_VOIDSTAR+NDEBUG), + // but both break the death check, so guard against each. +#ifdef NDEBUG + GTEST_SKIP() << "XRPL_ASSERT compiles to a no-op under NDEBUG (Release builds), so the " + "cross-thread scope-leak assertion this test exercises does not fire."; +#elif defined(ENABLE_VOIDSTAR) + GTEST_SKIP() << "ENABLE_VOIDSTAR continues past a failed XRPL_ASSERT instead of aborting, so " + "the cross-thread scope-leak assertion this test exercises does not crash."; +#else EXPECT_DEATH( { // Scoped guard is active on this (origin) thread; its Scope is @@ -417,7 +437,12 @@ TEST_F(SpanGuardScopeTest, non_detached_cross_thread_death_asserts_at_wrong_thre std::thread worker([d = std::move(guard)]() mutable {}); worker.join(); }, - ".*scoped guard destroyed on constructing thread.*"); + // The assert message is written as two adjacent string literals in + // SpanGuard.cpp; glibc's assert() stringifies the expression source via + // the preprocessor '#' operator, keeping both quoted literals with the + // "\" \"" gap between "on" and "constructing". Match across that gap. + ".*scoped guard destroyed on.*constructing thread.*"); +#endif } // detachInPlace(optional&) must detach the live guard the same way the