"bytes"
"context"
"errors"
+ "flag"
"fmt"
"go/build"
"internal/testenv"
"cmd/internal/sys"
)
+var testSum = flag.String("testsum", "", `may be tidy, listm, or listall. If set, TestScript generates a go.sum file at the beginning of each test and updates test files if they pass.`)
+
// TestScript runs the tests in testdata/script/*.txt.
func TestScript(t *testing.T) {
testenv.MustHaveGoBuild(t)
ts.mark = ts.log.Len()
}
+ // With -testsum, if a go.mod file is present in the test's initial
+ // working directory, run 'go mod tidy'.
+ if *testSum != "" {
+ if ts.updateSum(a) {
+ defer func() {
+ if ts.t.Failed() {
+ return
+ }
+ data := txtar.Format(a)
+ if err := os.WriteFile(ts.file, data, 0666); err != nil {
+ ts.t.Errorf("rewriting test file: %v", err)
+ }
+ }()
+ }
+ }
+
// Run script.
// See testdata/script/README for documentation of script form.
script := string(a.Comment)
return cmd
}
+// updateSum runs 'go mod tidy', 'go list -mod=mod -m all', or
+// 'go list -mod=mod all' in the test's current directory if a file named
+// "go.mod" is present after the archive has been extracted. updateSum modifies
+// archive and returns true if go.mod or go.sum were changed.
+func (ts *testScript) updateSum(archive *txtar.Archive) (rewrite bool) {
+ gomodIdx, gosumIdx := -1, -1
+ for i := range archive.Files {
+ switch archive.Files[i].Name {
+ case "go.mod":
+ gomodIdx = i
+ case "go.sum":
+ gosumIdx = i
+ }
+ }
+ if gomodIdx < 0 {
+ return false
+ }
+
+ switch *testSum {
+ case "tidy":
+ ts.cmdGo(success, []string{"mod", "tidy"})
+ case "listm":
+ ts.cmdGo(success, []string{"list", "-m", "-mod=mod", "all"})
+ case "listall":
+ ts.cmdGo(success, []string{"list", "-mod=mod", "all"})
+ default:
+ ts.t.Fatalf(`unknown value for -testsum %q; may be "tidy", "listm", or "listall"`, *testSum)
+ }
+
+ newGomodData, err := os.ReadFile(filepath.Join(ts.cd, "go.mod"))
+ if err != nil {
+ ts.t.Fatalf("reading go.mod after -testsum: %v", err)
+ }
+ if !bytes.Equal(newGomodData, archive.Files[gomodIdx].Data) {
+ archive.Files[gomodIdx].Data = newGomodData
+ rewrite = true
+ }
+
+ newGosumData, err := os.ReadFile(filepath.Join(ts.cd, "go.sum"))
+ if err != nil && !os.IsNotExist(err) {
+ ts.t.Fatalf("reading go.sum after -testsum: %v", err)
+ }
+ switch {
+ case os.IsNotExist(err) && gosumIdx >= 0:
+ // go.sum was deleted.
+ rewrite = true
+ archive.Files = append(archive.Files[:gosumIdx], archive.Files[gosumIdx+1:]...)
+ case err == nil && gosumIdx < 0:
+ // go.sum was created.
+ rewrite = true
+ gosumIdx = gomodIdx + 1
+ archive.Files = append(archive.Files, txtar.File{})
+ copy(archive.Files[gosumIdx+1:], archive.Files[gosumIdx:])
+ archive.Files[gosumIdx] = txtar.File{Name: "go.sum", Data: newGosumData}
+ case err == nil && gosumIdx >= 0 && !bytes.Equal(newGosumData, archive.Files[gosumIdx].Data):
+ // go.sum was changed.
+ rewrite = true
+ archive.Files[gosumIdx].Data = newGosumData
+ }
+ return rewrite
+}
+
// diff returns a formatted diff of the two texts,
// showing the entire text and the minimum line-level
// additions and removals to turn text1 into text2.