Skip to content

Commit 05c3829

Browse files
bluestreak01claude
andcommitted
test(ilp): wrap SF cursor tests in assertMemoryLeak; PR-17 regression tests
Test-only commit; production fixes are in the previous commit so the new red-then-green tests below land green under git bisect. assertMemoryLeak wrapping (C2). Every @test method across the SF cursor test surface (15 files, 75 tests) is now wrapped in TestUtils.assertMemoryLeak(() -> { ... }), so any native-memory leak introduced anywhere in the cursor codepaths (mmap segment lifecycle, slot lock fd, drainer pool, native Files calls) surfaces in CI instead of accumulating silently. Test method signatures changed to declare throws Exception where needed. New regression tests: * MemoryOrderingFindingsTest — pins MmapSegment.frameCount and CursorSendEngine.closed as volatile via reflection. Reflection is used because x86's strong memory model masks plain-long staleness in practice; a stress test would be flaky, the modifier check is deterministic. * SegmentManagerTotalBytesRaceTest — concurrent stress with eight producer threads doing register/spin/deregister cycles while the manager's worker polls at 1us. Reads totalBytes via reflection after every ring is deregistered; the field must read 0 (no accounting drift). Produced 50-60 KB of drift on the failing run pre-fix. * EngineCloseSlotLockReleaseTest — opens an engine, reflectively nulls the ring field to inject an NPE on engine.close(), then asserts a fresh SlotLock.acquire on the same dir succeeds. Pre-fix the close-path NPE skipped slotLock.close() and the kernel-held flock blocked the second acquire. * EmptyOrphanSlotChurnTest — opens-and-closes a CursorSendEngine on a fresh slot without writing, asserts no .sfa file remains. Re-opens and asserts the same. Pre-fix sf-initial.sfa survived close because unlinkAllSegmentFiles was gated only on publishedFsn>=0. * FilesFindFirstErrorTest — pins the post-fix contract: Files.findFirst on a missing path must return a negative sentinel so callers can distinguish "opendir failed" from "directory empty". Test cleanups: * Migrate ~25 test cleanup blocks from `if (find != 0)` / `if (find == 0)` to `if (find > 0)` / `if (find <= 0)` so the new Files.findFirst -1L sentinel is handled correctly and findClose is never called on -1. * BackgroundDrainerPoolRaceTest switches its leak check from java.util.List.contains to indexed ObjList.getQuick iteration to match the new BackgroundDrainerPool.snapshot() contract. * ReconnectTest class doc — drop the connectionGeneration mention (refs were removed alongside the dead retry loop). * Delete ConnectionGenerationTest — every hook it tested (bumpConnectionGenerationForTest, getConnectionGenerationForTest, onWireReconnect bump on disk recovery) was removed alongside the dead retry loop in the previous commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 07b930a commit 05c3829

26 files changed

Lines changed: 2596 additions & 1955 deletions

core/src/test/java/io/questdb/client/test/cutlass/qwp/client/CleanShutdownNoReplayTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public void testFullyAckedActiveDoesNotReplayAfterCleanRestart() throws Exceptio
133133
private static void rmDirRec(String dir) {
134134
if (!Files.exists(dir)) return;
135135
long find = Files.findFirst(dir);
136-
if (find != 0) {
136+
if (find > 0) {
137137
try {
138138
int rc = 1;
139139
while (rc > 0) {

core/src/test/java/io/questdb/client/test/cutlass/qwp/client/ConnectionGenerationTest.java

Lines changed: 0 additions & 251 deletions
This file was deleted.

core/src/test/java/io/questdb/client/test/cutlass/qwp/client/ReconnectTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,10 @@
5050
* The cursor I/O loop used to treat any wire failure as terminal — first
5151
* disconnect = sender broken, every subsequent batch threw. Reconnect
5252
* machinery now handles transient drops: detect, build a fresh client
53-
* via the registered factory, reset wire state, reposition the replay
54-
* cursor at {@code engine.ackedFsn() + 1}, and notify the producer thread
55-
* (via {@code connectionGeneration} bump) so the next encode emits full
56-
* schema definitions.
53+
* via the registered factory, reset wire state, and reposition the replay
54+
* cursor at {@code engine.ackedFsn() + 1}. Cursor frames are self-sufficient
55+
* (every frame carries full schema + full symbol-dict delta), so post-reconnect
56+
* replay needs no producer-side schema-reset signal.
5757
* <p>
5858
* This commit covers the mechanics with a single-attempt retry; backoff,
5959
* per-outage time cap, and auth-failure detection follow.

core/src/test/java/io/questdb/client/test/cutlass/qwp/client/RecoveryReplayTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ public void testRestartReplaysSealedSegmentsAgainstFreshServer() throws Exceptio
141141
private static int countSegmentFiles(String dir) {
142142
if (!Files.exists(dir)) return 0;
143143
long find = Files.findFirst(dir);
144-
if (find == 0) return 0;
144+
if (find <= 0) return 0;
145145
int n = 0;
146146
try {
147147
int rc = 1;
@@ -166,7 +166,7 @@ private static int countSegmentFiles(String dir) {
166166
private static int countPopulatedSegmentFiles(String dir) {
167167
if (!Files.exists(dir)) return 0;
168168
long find = Files.findFirst(dir);
169-
if (find == 0) return 0;
169+
if (find <= 0) return 0;
170170
int n = 0;
171171
try {
172172
int rc = 1;
@@ -203,7 +203,7 @@ private static String repeat(String c, int n) {
203203
private static void rmDirRec(String dir) {
204204
if (!Files.exists(dir)) return;
205205
long find = Files.findFirst(dir);
206-
if (find != 0) {
206+
if (find > 0) {
207207
try {
208208
int rc = 1;
209209
while (rc > 0) {

0 commit comments

Comments
 (0)