From dcae699323c8bda7d648a2e1303afaa4f6e19913 Mon Sep 17 00:00:00 2001 From: jochen Date: Fri, 23 Oct 2026 22:26:29 +0200 Subject: [PATCH] mesh-build-go: a clipped failure starts with its cause, not the marker, for an older checker (issue 1901/AC3) --- .../cmd/mesh-build-go/failure_words_test.go | 38 ++++++++++++++++++- .../mesh-build-go/cmd/mesh-build-go/levels.go | 17 +++++++-- 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/modules/mesh-build-go/cmd/mesh-build-go/failure_words_test.go b/modules/mesh-build-go/cmd/mesh-build-go/failure_words_test.go index 7a061993..9f82aa72 100644 --- a/modules/mesh-build-go/cmd/mesh-build-go/failure_words_test.go +++ b/modules/mesh-build-go/cmd/mesh-build-go/failure_words_test.go @@ -39,11 +39,11 @@ func TestAFailureLongerThanTheBoundKeepsItsLastLines(t *testing.T) { lines = append(lines, " x_test.go:1: log line "+strings.Repeat("y", 40)) } lines = append(lines, " x_test.go:9: the real cause", "--- FAIL: TestX (0.00s)") - out := clip(lines) + out := clip(lines, "") if len(out) > outputBytes+100 { t.Errorf("1901/AC1: kept %d bytes, bound is %d", len(out), outputBytes) } - if !strings.HasSuffix(out, "the real cause\n--- FAIL: TestX (0.00s)") || !strings.HasPrefix(out, "... (") { + if !strings.HasSuffix(out, "the real cause\n--- FAIL: TestX (0.00s)") || !strings.Contains(out, "\n... (") { t.Errorf("1901/AC1: out = %q...%q", out[:40], out[len(out)-60:]) } } @@ -76,3 +76,37 @@ func TestAnOlderCheckerReadsTheNewFailureAndGetsAtLeastWhatItKept(t *testing.T) t.Errorf("1901/AC3: older checker's output = %q", old[0].Output) } } + +// A long failure, whose earlier lines are left out, still starts with a real line for an older checker, which keeps only the +// first non-empty line of the output cut to 120 characters, and not with the marker. +func TestALongFailureStillStartsWithARealLineForAnOlderChecker(t *testing.T) { // 1901/AC3 + var lines []string + for i := 0; i < 400; i++ { + lines = append(lines, " x_test.go:1: log line "+strings.Repeat("y", 40)) + } + lines = append(lines, " x_test.go:9: the real cause", "--- FAIL: TestX (0.00s)") + oldFirst := func(out string) string { // the older checker's rule (judge.go firstLine) + for _, l := range strings.Split(out, "\n") { + if l = strings.TrimSpace(l); l != "" { + if len(l) > 120 { + l = l[:120] + } + return l + } + } + return "" + } + for _, cause := range []string{"the real cause", ""} { + out := clip(lines, cause) + got := oldFirst(out) + if strings.HasPrefix(got, "... (") || got == "" { + t.Errorf("1901/AC3: cause %q: an older checker would read %q", cause, got) + } + if cause != "" && got != cause { + t.Errorf("1901/AC3: older checker reads %q, want the cause", got) + } + if !strings.HasSuffix(out, "--- FAIL: TestX (0.00s)") { + t.Errorf("1901/AC3: the last lines are lost: %q", out[len(out)-40:]) + } + } +} diff --git a/modules/mesh-build-go/cmd/mesh-build-go/levels.go b/modules/mesh-build-go/cmd/mesh-build-go/levels.go index 3d921649..d247f1a9 100644 --- a/modules/mesh-build-go/cmd/mesh-build-go/levels.go +++ b/modules/mesh-build-go/cmd/mesh-build-go/levels.go @@ -207,15 +207,17 @@ func (r *reader) event(ev event) { r.times = append(r.times, TestTime{Package: ev.Package, Test: ev.Test, Elapsed: ev.Elapsed}) if ev.Action == "fail" { r.failedIn[ev.Package] = true - r.res.Failed = append(r.res.Failed, Failure{Package: ev.Package, Test: ev.Test, Output: clip(r.testOut[key]), Cause: r.causes[key]}) + r.res.Failed = append(r.res.Failed, Failure{Package: ev.Package, Test: ev.Test, Output: clip(r.testOut[key], r.causes[key]), Cause: r.causes[key]}) } } } } // clip joins the last lines of a failure's output that fit outputBytes, each cut to outputLineBytes, and says how many -// earlier lines it left out. -func clip(lines []string) string { +// earlier lines it left out. **When it leaves lines out, its first line is still a real one** (issue 1901/AC3): the failure's +// cause, or failing that the first non-empty line of the output, then the marker. An older checker takes only the first +// non-empty line of the output, and a marker there would be less than the older pair kept. +func clip(lines []string, cause string) string { size, from := 0, len(lines) for from > 0 { n := len(cutLine(lines[from-1])) + 1 @@ -227,6 +229,13 @@ func clip(lines []string) string { } kept := make([]string, 0, len(lines)-from+1) if from > 0 { + head := strings.TrimSpace(cause) + for i := 0; head == "" && i < from; i++ { + head = strings.TrimSpace(lines[i]) + } + if head != "" { + kept = append(kept, cutLine(head)) + } kept = append(kept, fmt.Sprintf("... (%d earlier lines)", from)) } for _, l := range lines[from:] { @@ -256,7 +265,7 @@ func (r *reader) finish() { for _, name := range r.order { p := r.pkgs[name] if !p.Passed && !r.failedIn[name] { - r.res.Failed = append(r.res.Failed, Failure{Package: name, Output: clip(r.pkgOut[name])}) + r.res.Failed = append(r.res.Failed, Failure{Package: name, Output: clip(r.pkgOut[name], "")}) } if !p.NoTests && p.Elapsed > r.res.Elapsed { r.res.Elapsed = p.Elapsed