From c260695325d33b4c83f988f31d2477065b6f5997 Mon Sep 17 00:00:00 2001 From: Dave Cheney Date: Tue, 29 Sep 2026 07:48:25 +1000 Subject: [PATCH] transform, interp: name the test fixture cache workaround `go test` only treats a file as a cache input if the test opened it through the os package. LLVM fixtures are read by llvm.NewMemoryBufferFromFile, which opens the file in C, so a fixture is never hashed and editing one leaves a stale cached pass. optimizer_internal_test.go had no os.Stat workaround, so TestBlockGlobalAllocPromotionUses did not run against its fixture: appending unparseable IR to testdata/optimizer-alloc-uses.ll did not fail it. Replace the bare os.Stat calls with ensureTestCacheFreshness, which also fails the test when the fixture is missing, and add the missing call. transform_test, transform and interp each keep a copy. A stopgap for #5780. --- interp/interp_test.go | 11 ++++++++++- transform/gc_test.go | 3 +-- transform/optimizer_internal_test.go | 11 +++++++++++ transform/transform_test.go | 11 ++++++++++- 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/interp/interp_test.go b/interp/interp_test.go index 65f8b541bb..4aa054648f 100644 --- a/interp/interp_test.go +++ b/interp/interp_test.go @@ -37,8 +37,8 @@ func runTest(t *testing.T, pathPrefix string) { // Read the input IR. ctx := llvm.NewContext() defer ctx.Dispose() + ensureTestCacheFreshness(t, pathPrefix+".ll") buf, err := llvm.NewMemoryBufferFromFile(pathPrefix + ".ll") - os.Stat(pathPrefix + ".ll") // make sure this file is tracked by `go test` caching if err != nil { t.Fatalf("could not read file %s: %v", pathPrefix+".ll", err) } @@ -153,3 +153,12 @@ func filterIrrelevantIRLines(lines []string) []string { } return out } + +// ensureTestCacheFreshness registers path as an input of the running test. +// see https://github.com/tinygo-org/tinygo/issues/5780. +func ensureTestCacheFreshness(t *testing.T, path string) { + t.Helper() + if _, err := os.Stat(path); err != nil { + t.Fatalf("could not stat test fixture %s: %v", path, err) + } +} diff --git a/transform/gc_test.go b/transform/gc_test.go index 2d5822dab9..1c6343cae4 100644 --- a/transform/gc_test.go +++ b/transform/gc_test.go @@ -2,7 +2,6 @@ package transform_test import ( "errors" - "os" "testing" "github.com/tinygo-org/tinygo/transform" @@ -37,8 +36,8 @@ func TestGCStackSlotCounts(t *testing.T) { ctx := llvm.NewContext() defer ctx.Dispose() + ensureTestCacheFreshness(t, "testdata/gc-slotcounts.ll") buf, err := llvm.NewMemoryBufferFromFile("testdata/gc-slotcounts.ll") - os.Stat("testdata/gc-slotcounts.ll") // make sure `go test` caching tracks this file if err != nil { t.Fatalf("could not read file: %v", err) } diff --git a/transform/optimizer_internal_test.go b/transform/optimizer_internal_test.go index 3358706dd0..a687e2dd46 100644 --- a/transform/optimizer_internal_test.go +++ b/transform/optimizer_internal_test.go @@ -1,6 +1,7 @@ package transform import ( + "os" "testing" "tinygo.org/x/go-llvm" @@ -9,6 +10,7 @@ import ( func TestBlockGlobalAllocPromotionUses(t *testing.T) { ctx := llvm.NewContext() defer ctx.Dispose() + ensureTestCacheFreshness(t, "testdata/optimizer-alloc-uses.ll") buf, err := llvm.NewMemoryBufferFromFile("testdata/optimizer-alloc-uses.ll") if err != nil { t.Fatal(err) @@ -31,3 +33,12 @@ func TestBlockGlobalAllocPromotionUses(t *testing.T) { t.Fatalf("got %d marker uses, want 1", len(uses)) } } + +// ensureTestCacheFreshness registers path as an input of the running test. +// see https://github.com/tinygo-org/tinygo/issues/5780. +func ensureTestCacheFreshness(t *testing.T, path string) { + t.Helper() + if _, err := os.Stat(path); err != nil { + t.Fatalf("could not stat test fixture %s: %v", path, err) + } +} diff --git a/transform/transform_test.go b/transform/transform_test.go index 743fa92e60..60deec9942 100644 --- a/transform/transform_test.go +++ b/transform/transform_test.go @@ -51,8 +51,8 @@ func testTransform(t *testing.T, pathPrefix string, transform func(mod llvm.Modu // Read the input IR. ctx := llvm.NewContext() defer ctx.Dispose() + ensureTestCacheFreshness(t, pathPrefix+".ll") buf, err := llvm.NewMemoryBufferFromFile(pathPrefix + ".ll") - os.Stat(pathPrefix + ".ll") // make sure this file is tracked by `go test` caching if err != nil { t.Fatalf("could not read file %s: %v", pathPrefix+".ll", err) } @@ -265,3 +265,12 @@ func getPosition(val llvm.Value) token.Position { return token.Position{} } } + +// ensureTestCacheFreshness registers path as an input of the running test. +// see https://github.com/tinygo-org/tinygo/issues/5780. +func ensureTestCacheFreshness(t *testing.T, path string) { + t.Helper() + if _, err := os.Stat(path); err != nil { + t.Fatalf("could not stat test fixture %s: %v", path, err) + } +}