diff --git a/tools/private-modules/main.go b/tools/private-modules/main.go index 5295fec..eb63867 100644 --- a/tools/private-modules/main.go +++ b/tools/private-modules/main.go @@ -79,7 +79,7 @@ func generate() error { if err != nil { return err } - defer os.RemoveAll(temp) + defer func() { _ = os.RemoveAll(temp) }() if err := os.WriteFile(filepath.Join(temp, "go.mod"), []byte(archiveBoundary), 0444); err != nil { return err } diff --git a/tools/private-modules/main_test.go b/tools/private-modules/main_test.go index b5f14b4..c94cd1c 100644 --- a/tools/private-modules/main_test.go +++ b/tools/private-modules/main_test.go @@ -13,31 +13,31 @@ import ( func TestBundleRejectsStaleMissingModifiedAndUnexpectedArtifacts(t *testing.T) { t.Chdir(t.TempDir()) - os.WriteFile("go.mod", []byte("module example.invalid/test\n"), 0600) - os.WriteFile("go.sum", []byte("recorded sum\n"), 0600) + mustFixture(t, os.WriteFile("go.mod", []byte("module example.invalid/test\n"), 0600)) + mustFixture(t, os.WriteFile("go.sum", []byte("recorded sum\n"), 0600)) mod, _ := inputDigest("go.mod") sum, _ := inputDigest("go.sum") m := manifest{Version: 1, GoModSHA256: mod, GoSumSHA256: sum, Modules: []module{{Path: "code.fritzlab.net/agenthub/example", Version: "v0.1.0"}}} for _, ext := range []string{".info", ".mod", ".zip"} { name := "code.fritzlab.net/agenthub/example/@v/v0.1.0" + ext b := []byte("canonical artifact " + ext) - os.MkdirAll(filepath.Dir(filepath.Join(bundleRoot, name)), 0700) - os.WriteFile(filepath.Join(bundleRoot, name), b, 0600) + mustFixture(t, os.MkdirAll(filepath.Dir(filepath.Join(bundleRoot, name)), 0700)) + mustFixture(t, os.WriteFile(filepath.Join(bundleRoot, name), b, 0600)) m.Modules[0].Files = append(m.Modules[0].Files, artifact{Path: name, Size: int64(len(b)), SHA256: digest(b)}) } b, _ := json.Marshal(m) - os.WriteFile(filepath.Join(bundleRoot, "manifest.json"), b, 0600) - os.WriteFile(filepath.Join(bundleRoot, "go.mod"), []byte(archiveBoundary), 0600) + mustFixture(t, os.WriteFile(filepath.Join(bundleRoot, "manifest.json"), b, 0600)) + mustFixture(t, os.WriteFile(filepath.Join(bundleRoot, "go.mod"), []byte(archiveBoundary), 0600)) if err := check(); err != nil { t.Fatal(err) } for _, boundary := range []string{"", "module unexpected.invalid/nested\n"} { - os.WriteFile(filepath.Join(bundleRoot, "go.mod"), []byte(boundary), 0600) + mustFixture(t, os.WriteFile(filepath.Join(bundleRoot, "go.mod"), []byte(boundary), 0600)) if check() == nil { t.Fatal("missing or changed archive boundary accepted") } } - os.WriteFile(filepath.Join(bundleRoot, "go.mod"), []byte(archiveBoundary), 0600) + mustFixture(t, os.WriteFile(filepath.Join(bundleRoot, "go.mod"), []byte(archiveBoundary), 0600)) originalPath, originalVersion := m.Modules[0].Path, m.Modules[0].Version for _, change := range []string{"path", "version"} { if change == "path" { @@ -46,36 +46,36 @@ func TestBundleRejectsStaleMissingModifiedAndUnexpectedArtifacts(t *testing.T) { m.Modules[0].Version = "v0.2.0" } changed, _ := json.Marshal(m) - os.WriteFile(filepath.Join(bundleRoot, "manifest.json"), changed, 0600) + mustFixture(t, os.WriteFile(filepath.Join(bundleRoot, "manifest.json"), changed, 0600)) if check() == nil { t.Fatal("artifact accepted under different module identity") } m.Modules[0].Path, m.Modules[0].Version = originalPath, originalVersion } - os.WriteFile(filepath.Join(bundleRoot, "manifest.json"), b, 0600) - os.WriteFile("go.mod", []byte("changed graph\n"), 0600) + mustFixture(t, os.WriteFile(filepath.Join(bundleRoot, "manifest.json"), b, 0600)) + mustFixture(t, os.WriteFile("go.mod", []byte("changed graph\n"), 0600)) if check() == nil { t.Fatal("stale dependency closure accepted") } - os.WriteFile("go.mod", []byte("module example.invalid/test\n"), 0600) + mustFixture(t, os.WriteFile("go.mod", []byte("module example.invalid/test\n"), 0600)) path := filepath.Join(bundleRoot, m.Modules[0].Files[2].Path) original, _ := os.ReadFile(path) - os.WriteFile(path, []byte("corrupted zip"), 0600) + mustFixture(t, os.WriteFile(path, []byte("corrupted zip"), 0600)) if check() == nil { t.Fatal("modified artifact accepted") } - os.Remove(path) + mustFixture(t, os.Remove(path)) if check() == nil { t.Fatal("missing artifact accepted") } - os.WriteFile(path, original, 0600) + mustFixture(t, os.WriteFile(path, original, 0600)) extra := filepath.Join(bundleRoot, "extra") - os.WriteFile(extra, []byte("unlisted"), 0600) + mustFixture(t, os.WriteFile(extra, []byte("unlisted"), 0600)) if check() == nil { t.Fatal("unlisted artifact accepted") } - os.Remove(extra) - os.Symlink("manifest.json", extra) + mustFixture(t, os.Remove(extra)) + mustFixture(t, os.Symlink("manifest.json", extra)) if check() == nil { t.Fatal("symlink accepted") } @@ -90,20 +90,22 @@ func TestNativeGoSumRejectsChangedModuleArtifact(t *testing.T) { t.Fatal(err) } mod := []byte("module " + modulePath + "\n\ngo 1.27.0\n") - os.WriteFile(base+".mod", mod, 0600) - os.WriteFile(base+".info", []byte(`{"Version":"v0.1.0","Time":"2026-01-01T00:00:00Z"}`), 0600) + mustFixture(t, os.WriteFile(base+".mod", mod, 0600)) + mustFixture(t, os.WriteFile(base+".info", []byte(`{"Version":"v0.1.0","Time":"2026-01-01T00:00:00Z"}`), 0600)) var archive bytes.Buffer zw := zip.NewWriter(&archive) entry, err := zw.Create(modulePath + "@" + version + "/go.mod") if err != nil { t.Fatal(err) } - entry.Write(mod) + if _, err := entry.Write(mod); err != nil { + t.Fatal(err) + } if err = zw.Close(); err != nil { t.Fatal(err) } - os.WriteFile(base+".zip", archive.Bytes(), 0600) - os.WriteFile(filepath.Join(root, "go.mod"), []byte("module example.invalid/checksum\n\ngo 1.27.0\n\nrequire "+modulePath+" "+version+"\n"), 0600) + mustFixture(t, os.WriteFile(base+".zip", archive.Bytes(), 0600)) + mustFixture(t, os.WriteFile(filepath.Join(root, "go.mod"), []byte("module example.invalid/checksum\n\ngo 1.27.0\n\nrequire "+modulePath+" "+version+"\n"), 0600)) run := func(cache string) ([]byte, error) { cmd := exec.Command("go", "mod", "download", modulePath+"@"+version) cmd.Dir = root @@ -113,7 +115,7 @@ func TestNativeGoSumRejectsChangedModuleArtifact(t *testing.T) { if output, err := run("original-cache"); err != nil { t.Fatalf("native fixture admission: %v: %s", err, output) } - os.WriteFile(base+".mod", append(mod, '\n'), 0600) + mustFixture(t, os.WriteFile(base+".mod", append(mod, '\n'), 0600)) output, err := run("fresh-cache") if err == nil || !bytes.Contains(output, []byte("checksum mismatch")) { t.Fatalf("native module checksum guard failed: %v: %s", err, output) @@ -123,12 +125,12 @@ func TestNativeGoSumRejectsChangedModuleArtifact(t *testing.T) { func TestGeneratorMissingPrivateMetadataNeverInvokesGit(t *testing.T) { root := t.TempDir() t.Chdir(root) - os.WriteFile("go.mod", []byte("module example.invalid/offline\n\ngo 1.27.0\n\nrequire code.fritzlab.net/agenthub/missing v0.0.1\n"), 0600) - os.WriteFile("go.sum", nil, 0600) + mustFixture(t, os.WriteFile("go.mod", []byte("module example.invalid/offline\n\ngo 1.27.0\n\nrequire code.fritzlab.net/agenthub/missing v0.0.1\n"), 0600)) + mustFixture(t, os.WriteFile("go.sum", nil, 0600)) bin := filepath.Join(root, "bin") - os.Mkdir(bin, 0700) + mustFixture(t, os.Mkdir(bin, 0700)) marker := filepath.Join(root, "git-invoked") - os.WriteFile(filepath.Join(bin, "git"), []byte("#!/bin/sh\nprintf invoked > \"$PRIVATE_GIT_PROBE\"\nexit 99\n"), 0700) + mustFixture(t, os.WriteFile(filepath.Join(bin, "git"), []byte("#!/bin/sh\nprintf invoked > \"$PRIVATE_GIT_PROBE\"\nexit 99\n"), 0700)) t.Setenv("PATH", bin+string(os.PathListSeparator)+os.Getenv("PATH")) t.Setenv("PRIVATE_GIT_PROBE", marker) t.Setenv("GOMODCACHE", filepath.Join(root, "empty-cache")) @@ -149,7 +151,7 @@ func TestGeneratorMissingPrivateMetadataNeverInvokesGit(t *testing.T) { if _, err = os.Stat(bundleRoot); !os.IsNotExist(err) { t.Fatal("failed generation published output") } - os.WriteFile("go.mod", []byte("module example.invalid/offline\n\ngo 1.999.0\n"), 0600) + mustFixture(t, os.WriteFile("go.mod", []byte("module example.invalid/offline\n\ngo 1.999.0\n"), 0600)) _, err = nativeGo("list", "-m", "-json", "all") if !errors.As(err, &failure) || !bytes.Contains(failure.Stderr, []byte("GOTOOLCHAIN=local")) { t.Fatalf("toolchain download not disabled: %v", err) @@ -186,3 +188,10 @@ func TestLazyGraphModuleCacheIdentity(t *testing.T) { } } } + +func mustFixture(t *testing.T, err error) { + t.Helper() + if err != nil { + t.Fatal(err) + } +}