template-jj/cmd/planctl/bench_test.go
Sid 3dc1273a7a feat(planctl): CI workflow + perf benchmark
* .forgejo/workflows/planctl.yml: build/test matrix across
  {ubuntu-latest, macos-latest, windows-latest} × {1.22, stable}
  per D-3 / PRD R7.4. Dedicated bench job on ubuntu+stable so
  ns/op numbers stay comparable across runs. Path filters scope
  CI to planctl-adjacent changes only.
* cmd/planctl/bench_test.go: Benchmark_Lint_BigPlan times the full
  lint pipeline on testdata/perf/big-plan/. Local M4 Pro: ~720µs,
  two orders of magnitude under M3's 100ms target.
* TestLint_BigPlan_SoftCeiling logs (via direct os.Stderr write —
  not t.Logf, which is suppressed without -v) when wall time
  exceeds 100ms. Soft check per task 8.3 — CI runner variance
  means a hard assert would be flaky; the visible stderr line is
  the regression signal.
* Windows line-ending handling already landed in parent-7's
  harness (CRLF → LF normalisation on both sides of golden
  compare), so 8.4 is satisfied by construction.

Parent task 8.0 from dev/plans/26172-planctl/tasks.md.
Codex code-review session: 019db2f3-2f80-7fc0-b7bb-9e1f677f978e (2 rounds).
2026-04-21 20:14:06 -06:00

63 lines
2.1 KiB
Go

package main
import (
"bytes"
"fmt"
"os"
"path/filepath"
"testing"
"time"
)
// spec:planctl/D§7.3
// Benchmark_Lint_BigPlan measures full-pipeline wall time on the
// testdata/perf/big-plan fixture (~90 KB across 5 files; 36 R-ids, 18
// D§ sections, 72 covered task lines). PRD success metric M3 targets
// <100 ms on a 2023-era M-series machine; this benchmark reports
// ns/op and the CI runner interprets it — see §7.3 for context.
func Benchmark_Lint_BigPlan(b *testing.B) {
fixture, err := filepath.Abs("testdata/perf/big-plan")
if err != nil {
b.Fatal(err)
}
args := []string{"lint", fixture}
b.ResetTimer()
for i := 0; i < b.N; i++ {
var stdout, stderr bytes.Buffer
exit := run(args, &stdout, &stderr)
if exit != 0 {
b.StopTimer()
b.Fatalf("unexpected exit %d on big-plan fixture: stderr=%q", exit, stderr.String())
}
}
}
// spec:planctl/D§7.3
// TestLint_BigPlan_SoftCeiling times one lint of the perf fixture and
// LOGS (not fails) when the wall time exceeds PRD M3's 100ms ceiling.
// CI runners vary substantially; a hard assertion here would produce
// flaky failures, so task 8.3 explicitly specifies log-only behavior.
// A pathological regression (e.g. O(n²) scan) still surfaces in the
// test log even if not reflected in the exit code.
func TestLint_BigPlan_SoftCeiling(t *testing.T) {
fixture, err := filepath.Abs("testdata/perf/big-plan")
if err != nil {
t.Fatalf("abs: %v", err)
}
args := []string{"lint", fixture}
var stdout, stderr bytes.Buffer
start := time.Now()
exit := run(args, &stdout, &stderr)
elapsed := time.Since(start)
if exit != 0 {
t.Fatalf("exit=%d, want 0: stderr=%q", exit, stderr.String())
}
const ceiling = 100 * time.Millisecond
if elapsed > ceiling {
// Write directly to stderr rather than t.Logf so the warning is
// visible in non-verbose CI runs (Go test suppresses t.Log output
// from passing tests without -v). Keeps the test passing so CI
// stays green; the visible warning is the signal.
fmt.Fprintf(os.Stderr, "planctl: WARNING big-plan lint took %v, PRD M3 target is <%v (CI runner variance is expected)\n", elapsed, ceiling)
}
}