Skip to content

Commit 844454c

Browse files
committed
test: make assertMemoryLeak assert strict per-tag equality -- single-tag leaks passed
LeakCheck.close() absorbed any growth confined to a single memory tag into a tolerated diff (mem + diff == memAfter holds when exactly one tag grew), so a lone-tag native leak -- the common case -- passed the check. The shape was ported from upstream QuestDB, where the tolerance is scoped to NATIVE_SQL_COMPILER only; the per-tag filter was lost in the port and this client has no such tag, so no exemption applies. Proven vacuous empirically: disabling the M7 stub close under the old check stayed green; under the strict check all 18 tests fail with 'native memory leaked or over-freed under tag NATIVE_DEFAULT expected:<0> but was:<131328>' (exactly recv 64K + send 64K + control 256B per stub). Tightening surfaced 63 latent failures across 6 classes -- all root-caused and fixed in the two preceding commits (two production ctor leaks, two test free-ordering bugs, one test cleanup gap); none suppressed. MemoryTag.nameOf() added (mirrors upstream) so failures name the offending tag.
1 parent 2cb81d0 commit 844454c

2 files changed

Lines changed: 40 additions & 10 deletions

File tree

core/src/main/java/io/questdb/client/std/MemoryTag.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,31 @@ public final class MemoryTag {
3838
public static final int NATIVE_TLS_RSS = NATIVE_TEXT_PARSER_RSS + 1;
3939
public static final int NATIVE_ND_ARRAY = NATIVE_TLS_RSS + 1;
4040
public static final int SIZE = NATIVE_ND_ARRAY + 1;
41+
42+
public static String nameOf(int tag) {
43+
switch (tag) {
44+
case MMAP_DEFAULT:
45+
return "MMAP_DEFAULT";
46+
case NATIVE_PATH:
47+
return "NATIVE_PATH";
48+
case NATIVE_DEFAULT:
49+
return "NATIVE_DEFAULT";
50+
case NATIVE_DIRECT_UTF8_SINK:
51+
return "NATIVE_DIRECT_UTF8_SINK";
52+
case NATIVE_HTTP_CONN:
53+
return "NATIVE_HTTP_CONN";
54+
case NATIVE_ILP_RSS:
55+
return "NATIVE_ILP_RSS";
56+
case NATIVE_IO_DISPATCHER_RSS:
57+
return "NATIVE_IO_DISPATCHER_RSS";
58+
case NATIVE_TEXT_PARSER_RSS:
59+
return "NATIVE_TEXT_PARSER_RSS";
60+
case NATIVE_TLS_RSS:
61+
return "NATIVE_TLS_RSS";
62+
case NATIVE_ND_ARRAY:
63+
return "NATIVE_ND_ARRAY";
64+
default:
65+
return "unknown[" + tag + "]";
66+
}
67+
}
4168
}

core/src/test/java/io/questdb/client/test/tools/TestUtils.java

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -266,20 +266,23 @@ public void close() {
266266
return;
267267
}
268268

269-
// Checks that the same tag used for allocation and freeing native memory
269+
// Every tag must return to its baseline. The previous shape
270+
// (ported from upstream, which exempts NATIVE_SQL_COMPILER only)
271+
// absorbed any growth confined to a single tag into a tolerated
272+
// diff, so a lone-tag leak (e.g. NATIVE_DEFAULT) passed the check.
273+
// This client has no SQL-compiler tag, so no exemption applies:
274+
// assert strict per-tag equality, then total equality.
270275
long memAfter = Unsafe.getMemUsed();
271-
long memNativeSqlCompilerDiff = 0;
272276
Assert.assertTrue(memAfter > -1);
273-
if (mem != memAfter) {
274-
for (int i = MemoryTag.MMAP_DEFAULT; i < MemoryTag.SIZE; i++) {
275-
long actualMemByTag = Unsafe.getMemUsedByTag(i);
276-
if (memoryUsageByTag[i] != actualMemByTag) {
277-
Assert.assertTrue(actualMemByTag >= memoryUsageByTag[i]);
278-
memNativeSqlCompilerDiff = actualMemByTag - memoryUsageByTag[i];
279-
}
277+
for (int i = MemoryTag.MMAP_DEFAULT; i < MemoryTag.SIZE; i++) {
278+
long actualMemByTag = Unsafe.getMemUsedByTag(i);
279+
if (memoryUsageByTag[i] != actualMemByTag) {
280+
Assert.assertEquals(
281+
"native memory leaked or over-freed under tag " + MemoryTag.nameOf(i),
282+
memoryUsageByTag[i], actualMemByTag);
280283
}
281-
Assert.assertEquals(mem + memNativeSqlCompilerDiff, memAfter);
282284
}
285+
Assert.assertEquals("total native memory", mem, memAfter);
283286
}
284287

285288
public void skipChecks() {

0 commit comments

Comments
 (0)