Skip to content

Commit dcc2d17

Browse files
committed
Clean up the hand-registered test type after the expectation
PredicateConstructionThrowsWhenNoMemberMatches manually inserted a MismatchedRecord entry into the process-wide reflection registry (with no member metadata, to force an offset-match miss) but never removed it. Left in place, Database::Database iterates every registered record on Initialize() and would generate "CREATE TABLE IF NOT EXISTS MismatchedRecord ();" (empty column list) for it - invalid SQL that throws and breaks every later Database::Initialize() call in the same test binary, depending on test execution order. This didn't surface in a normal sequential run, but reliably broke under --gtest_shuffle: 4 of 5 random seeds failed with 6-37 cascading test failures before this fix, and all of 10 random seeds pass after it. Added a small RAII ScopedRegistryCleanup that erases the hand-inserted entry on scope exit. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NUt3c1wdseRtRSSXfg3MCK
1 parent 398c870 commit dcc2d17

1 file changed

Lines changed: 22 additions & 1 deletion

File tree

tests/query_predicates_test.cc

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424

2525
#include <gtest/gtest.h>
2626

27+
#include <string>
28+
#include <utility>
29+
2730
#include "person.h"
2831
#include "pet.h"
2932

@@ -223,6 +226,22 @@ struct MismatchedRecord {
223226
int64_t id;
224227
int64_t value;
225228
};
229+
230+
// Erases a hand-inserted entry from the process-wide reflection registry on scope exit. Without
231+
// this, a MismatchedRecord-shaped entry with no member metadata would linger in the registry for
232+
// the rest of the test binary: Database::Database iterates every registered record and would
233+
// generate "CREATE TABLE IF NOT EXISTS MismatchedRecord ();" (empty column list) for it, failing
234+
// every later Database::Initialize() call in this process.
235+
class ScopedRegistryCleanup {
236+
public:
237+
explicit ScopedRegistryCleanup(std::string type_id) : type_id_(std::move(type_id)) {}
238+
~ScopedRegistryCleanup() {
239+
GetReflectionRegisterInstance()->records.erase(type_id_);
240+
}
241+
242+
private:
243+
std::string type_id_;
244+
};
226245
} // namespace
227246

228247
TEST(QueryPredicatesTest, PredicateConstructionThrowsForUnregisteredType) {
@@ -237,8 +256,10 @@ TEST(QueryPredicatesTest, PredicateConstructionThrowsWhenNoMemberMatches) {
237256
// pointer-to-member (here because the type was registered by hand with no members at all,
238257
// rather than via the FIELDS macro), the QueryPredicate constructor must fail fast instead
239258
// of silently leaving member_name_ empty and emitting malformed SQL like " = ?"
259+
const std::string type_id = typeid(MismatchedRecord).name();
240260
auto& instance = *GetReflectionRegisterInstance();
241-
instance.records[typeid(MismatchedRecord).name()].name = "MismatchedRecord";
261+
instance.records[type_id].name = "MismatchedRecord";
262+
const ScopedRegistryCleanup cleanup(type_id);
242263

243264
EXPECT_THROW(Equal(&MismatchedRecord::value, 42), std::runtime_error);
244265
}

0 commit comments

Comments
 (0)