test(parse-coverage): free the extraction results in the #1610 tests

LeakSanitizer on CI caught all five new tests leaking their CBMFileResult:

    Indirect leak of 24 byte(s) ... ts_tree_new
      cbm_extract_file_ex cbm.c:1256
      do_extract test_parse_coverage.c:39
      test_dockerfile_missing_final_newline_not_flagged_issue1610:272
    SUMMARY: AddressSanitizer: 706504 byte(s) leaked in 189 allocation(s)

Every pre-existing test in this suite calls cbm_free_result before PASS; the new
ones did not. The local run could not have found it - LeakSanitizer reports
"detect_leaks is not supported on this platform" on macOS arm64, so this class
of defect is CI-only here.

Each test now captures what it asserts, frees, and only then decides, so the
early-FAIL paths do not leak either. The cross-grammar loop prints its
diagnostic before freeing so the failure message keeps naming the grammar.

While correcting the guard, a first attempt left ASSERT_TRUE(flagged ||
has_ranges || true) in real_error_before_eof_still_flagged - always true, and it
would have silently disarmed the guard that stops the EOF suppression from being
over-broad. Removed. The guard is re-proven binding: forcing
cbm_is_eof_terminator_miss to return true makes EIGHT tests fail, including both
guards, and restoring it returns the suite to green.

parse_coverage 14 passed.
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
This commit is contained in:
Martin Vogel committed 2026-08-15 17:22:59 +02:00
1 parent 8669ba8f9e
commit 63f0a6c0e7
1 file changed
+15 -8
+15 -8
View File
@@ -272,11 +272,10 @@ TEST(dockerfile_missing_final_newline_not_flagged_issue1610) {
CBMFileResult *r = do_extract(src, CBM_LANG_DOCKERFILE, "Dockerfile");
ASSERT_NOT_NULL(r);
bool flagged = r->parse_incomplete;
const char *ranges = r->error_ranges;
cbm_free_result(r);
if (flagged) {
FAIL("a Dockerfile lacking only its final newline must not be parse_partial");
}
(void)ranges;
PASS();
}
@@ -288,7 +287,9 @@ TEST(dockerfile_with_final_newline_still_clean_issue1610) {
"ENTRYPOINT [\"dotnet\", \"App.dll\"]\n";
CBMFileResult *r = do_extract(src, CBM_LANG_DOCKERFILE, "Dockerfile");
ASSERT_NOT_NULL(r);
if (r->parse_incomplete) {
bool flagged = r->parse_incomplete;
cbm_free_result(r);
if (flagged) {
FAIL("a terminated Dockerfile must not be parse_partial");
}
PASS();
@@ -310,9 +311,13 @@ TEST(missing_final_newline_not_flagged_across_grammars_issue1610) {
for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
CBMFileResult *r = do_extract(cases[i].src, cases[i].lang, cases[i].path);
ASSERT_NOT_NULL(r);
if (r->parse_incomplete) {
bool flagged = r->parse_incomplete;
if (flagged) {
fprintf(stderr, " %s flagged: ranges=%s\n", cases[i].path,
r->error_ranges ? r->error_ranges : "(none)");
}
cbm_free_result(r);
if (flagged) {
FAIL("an unterminated final line must not be parse_partial in any grammar");
}
}
@@ -335,11 +340,11 @@ TEST(real_error_before_eof_still_flagged_without_final_newline_issue1610) {
unterminated[n - 1] = '\0'; /* drop the final newline */
CBMFileResult *r = do_extract(unterminated, CBM_LANG_C, "split.c");
bool flagged = r && r->parse_incomplete;
bool has_ranges = r && r->error_ranges != NULL;
free(unterminated);
ASSERT_NOT_NULL(r);
bool flagged = r->parse_incomplete;
bool has_ranges = r->error_ranges != NULL;
cbm_free_result(r);
if (!flagged) {
FAIL("a real mid-file parse failure must still be reported when the file also lacks its final newline");
}
@@ -356,7 +361,9 @@ TEST(width_bearing_error_at_eof_still_flagged_issue1610) {
const char *src = "all:\n\techo hi"; /* no trailing newline; recipe is lost */
CBMFileResult *r = do_extract(src, CBM_LANG_MAKEFILE, "Makefile");
ASSERT_NOT_NULL(r);
if (!r->parse_incomplete) {
bool flagged = r->parse_incomplete;
cbm_free_result(r);
if (!flagged) {
FAIL("a width-bearing parse failure at EOF must still be reported");
}
PASS();