diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml index dd7c8ad..3102197 100644 --- a/.gitea/workflows/test.yml +++ b/.gitea/workflows/test.yml @@ -51,10 +51,9 @@ jobs: go-version-file: go.mod cache: true - - name: Install Perl - # The runner images are minimal and Perl is not guaranteed. The install is a - # no-op where it is already present; drop this step once verified on the box. - run: dnf install -y perl + # No Install Perl step: the fedora image carries perl (verified by run + # 76: the install degraded into a package upgrade costing ~50 s), and a + # dnf on the push path is network work the budget does not need. # The steps follow the `gates` order of the justfile contract: build, format, # vet, test. The vet gate is go vet and go fix -diff, two steps here. diff --git a/asm/goobj_resolve_test.go b/asm/goobj_resolve_test.go index 7a7280a..303c74d 100644 --- a/asm/goobj_resolve_test.go +++ b/asm/goobj_resolve_test.go @@ -45,6 +45,9 @@ func TestReadRuntimeSymbols(t *testing.T) { // TestResolveExternalSymbols verifies end-to-end resolution of external // symbol references. func TestResolveExternalSymbols(t *testing.T) { + if testing.Short() { + t.Skip("resolves through a live go list -export: skipped in -short mode") + } if _, err := exec.LookPath("go"); err != nil { t.Skip("go toolchain not available") } diff --git a/asm/goobj_test.go b/asm/goobj_test.go index 8639e2e..f4ba430 100644 --- a/asm/goobj_test.go +++ b/asm/goobj_test.go @@ -564,6 +564,14 @@ func parseBuildLog(t *testing.T, log []byte, asmFile string) buildLogSteps { func substituteAndRelink(t *testing.T, goBin, dir string, st buildLogSteps, outBin string, gasmObj []byte, extraEnv ...string) { t.Helper() + // The deliberate-run boundary: this path drives a real `go build` and + // cmd/link per invocation, minutes-scale work on the small single-core + // CI runner. Under -short (the push pipeline's mode) it skips; the + // local test gate and the dispatched workflows run it in full. + if testing.Short() { + t.Skip("end-to-end go build and link: skipped in -short mode") + } + // Extract the archive, overwrite the assembler's member with the gasm // object and repack (go tool pack has no replace-in-place). membersDir := filepath.Join(dir, "members") @@ -655,6 +663,9 @@ func substituteAndRelink(t *testing.T, goBin, dir string, st buildLogSteps, outB // failed. The binary is not run: morestack returns to the call site's // stack check, which a hand-written caller has none of. func TestGOObjectExternalPackageLink(t *testing.T) { + if testing.Short() { + t.Skip("end-to-end go build and link: skipped in -short mode") + } goBin, err := exec.LookPath("go") if err != nil { t.Skip("no Go toolchain available") diff --git a/asm/kernels_differential_test.go b/asm/kernels_differential_test.go index 7cf2c75..e7809c7 100644 --- a/asm/kernels_differential_test.go +++ b/asm/kernels_differential_test.go @@ -23,9 +23,18 @@ import ( // bytes must agree with the relocation sites masked on both sides. // toolAsmObject assembles path with the installed toolchain's assembler for -// goarch ("" = the host) and returns the object bytes. +// goarch ("" = the host) and returns the object bytes. Every live-oracle +// comparison funnels through here, so this is also where the deliberate-run +// boundary sits: under -short (the push pipeline's mode) the comparisons +// skip, because each spawns a go tool asm subprocess and the small single- +// core runner pays seconds per spawn. The encodings stay pinned by the +// golden-byte tests in every mode; the live oracle runs in the local test +// gate and the dispatched workflows. func toolAsmObject(t *testing.T, path, goarch string) []byte { t.Helper() + if testing.Short() { + t.Skip("live go tool asm oracle: skipped in -short mode") + } goBin, err := exec.LookPath("go") if err != nil { t.Skip("no Go toolchain available") diff --git a/parser/fuzz_test.go b/parser/fuzz_test.go index b0803f0..42ccfa6 100644 --- a/parser/fuzz_test.go +++ b/parser/fuzz_test.go @@ -46,11 +46,13 @@ func FuzzParse(f *testing.F) { f.Add("TEXT ·f(SB), $0\n\tMOVD $(1<<0|1<<9), R0\n\tRET\n") // constant expression f.Add("TEXT ·f(SB), $0\n\tADD $-8, R10; SUB $~63, R11\n\tRET\n") // Constant-expression nesting: an immediate and a displacement read - // through the recursive folder, so deep parenthesis groups probe its - // depth handling on every plain run. The immediate seed is deep enough - // that, before the folder carried a depth bound, it grew the goroutine - // stack past its limit with a fatal error. - f.Add("TEXT ·f(SB), $0\n\tMOVD $" + strings.Repeat("(", 4_000_000) + "1" + strings.Repeat(")", 4_000_000) + ", R0\n\tRET\n") + // through the recursive folder, so parenthesis groups past the folder's + // depth bound probe its fallback on every plain run. The seeds sit just + // above the bound (maxFoldDepth), not in the millions: a seed corpus + // runs on every `go test` including the small-memory CI runner, and an + // eight-million-token seed costs the process close to a gigabyte before + // the bound even engages. The megascale belongs to the fuzz timebox. + f.Add("TEXT ·f(SB), $0\n\tMOVD $" + strings.Repeat("(", 1500) + "1" + strings.Repeat(")", 1500) + ", R0\n\tRET\n") f.Add("TEXT ·f(SB), $0\n\tMOVQ " + strings.Repeat("(", 2000) + "1" + strings.Repeat(")", 2000) + "(AX), BX\n\tRET\n") f.Add("TEXT ·f(SB), $0\n\tMOVD $" + strings.Repeat("~", 5000) + "1, R0\n\tRET\n")