From 109c5fcce2dda26baea33b76686c8d53779b1e4b Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Tue, 29 Oct 2024 13:41:39 +0000 Subject: [PATCH] gopls/internal/test: fix path to local go in integration tests As described in golang/go#69630, our 1.21 and 1.22 builders were not actually testing gopls' integration with the Go command, because go test modifies PATH and GOROOT when performing a toolchain switch. "Fix" this by searching PATH for a local (=non-toolchain) go command, and then mutating PATH and unsetting GOROOT to use this go command. This is very much a hack, as noted in the relevant commentary, but allows us to have much needed test coverage on the builders. In golang/go#69321, we hope to design a better solution to this problem. Many tests are updated to make their go version requirements accurate. Fixes golang/go#69630 Change-Id: I431107b97845e1e99799c2c22f33b04f85ce6dd9 Reviewed-on: https://go-review.googlesource.com/c/tools/+/623175 Reviewed-by: Alan Donovan LUCI-TryBot-Result: Go LUCI Auto-Submit: Robert Findley --- gopls/internal/licenses/licenses_test.go | 7 --- .../integration/codelens/codelens_test.go | 3 +- .../integration/codelens/gcdetails_test.go | 4 -- .../diagnostics/diagnostics_test.go | 2 +- .../internal/test/integration/fake/sandbox.go | 16 +++--- .../integration/misc/configuration_test.go | 7 --- .../test/integration/misc/formatting_test.go | 4 -- .../test/integration/misc/hover_test.go | 6 --- .../test/integration/misc/imports_test.go | 6 +-- .../test/integration/misc/staticcheck_test.go | 6 --- .../test/integration/misc/webserver_test.go | 2 +- gopls/internal/test/integration/regtest.go | 54 +++++++++++++++++++ gopls/internal/test/integration/runner.go | 2 +- .../test/integration/watch/watch_test.go | 2 +- .../test/integration/workspace/broken_test.go | 5 -- .../integration/workspace/workspace_test.go | 2 +- gopls/internal/test/integration/wrappers.go | 12 +++-- gopls/internal/test/marker/marker_test.go | 42 +++++++++------ .../codeaction/removeparam_imports.txt | 3 -- .../codeaction/removeparam_method.txt | 3 -- .../codeaction/removeparam_satisfies.txt | 3 -- .../marker/testdata/completion/append.txt | 3 -- .../marker/testdata/completion/foobarbaz.txt | 1 - .../testdata/completion/imported-std.txt | 3 +- .../marker/testdata/completion/issue62676.txt | 1 - .../testdata/completion/nested_complit.txt | 1 - .../testdata/completion/unimported-std.txt | 2 +- .../test/marker/testdata/definition/embed.txt | 1 - .../marker/testdata/definition/standalone.txt | 3 -- .../marker/testdata/diagnostics/analyzers.txt | 1 - .../testdata/diagnostics/issue60605.txt | 3 -- .../testdata/diagnostics/issue67360.txt | 3 -- .../testdata/diagnostics/stdversion.txt | 2 +- .../testdata/diagnostics/useinternal.txt | 3 -- .../marker/testdata/fixedbugs/issue66109.txt | 4 +- .../marker/testdata/fixedbugs/issue66876.txt | 2 +- .../marker/testdata/format/issue59554.txt | 5 -- .../test/marker/testdata/hover/comment.txt | 5 -- .../test/marker/testdata/hover/generics.txt | 1 - .../test/marker/testdata/hover/godef.txt | 11 ---- .../test/marker/testdata/hover/sizeoffset.txt | 1 - .../marker/testdata/inlayhints/issue67142.txt | 1 - .../test/marker/testdata/modfile/godebug.txt | 2 +- .../marker/testdata/modfile/godebug_bad.txt | 2 +- .../marker/testdata/references/issue60369.txt | 3 -- .../test/marker/testdata/rename/doclink.txt | 3 -- .../test/marker/testdata/rename/generics.txt | 3 -- .../marker/testdata/rename/issue57479.txt | 3 -- .../marker/testdata/rename/issue60752.txt | 3 -- .../test/marker/testdata/workfile/godebug.txt | 2 +- .../marker/testdata/workfile/godebug_bad.txt | 2 +- .../marker/testdata/zeroconfig/nested.txt | 3 -- internal/testenv/testenv.go | 49 +++++++++++++++++ 53 files changed, 166 insertions(+), 157 deletions(-) diff --git a/gopls/internal/licenses/licenses_test.go b/gopls/internal/licenses/licenses_test.go index 00b6b6c94f7..c31b4e9e659 100644 --- a/gopls/internal/licenses/licenses_test.go +++ b/gopls/internal/licenses/licenses_test.go @@ -10,16 +10,9 @@ import ( "os/exec" "runtime" "testing" - - "golang.org/x/tools/internal/testenv" ) func TestLicenses(t *testing.T) { - // License text differs for older Go versions because staticcheck or gofumpt - // isn't supported for those versions, and this fails for unknown, unrelated - // reasons on Kokoro legacy CI. - testenv.NeedsGo1Point(t, 21) - if runtime.GOOS != "linux" && runtime.GOOS != "darwin" { t.Skip("generating licenses only works on Unixes") } diff --git a/gopls/internal/test/integration/codelens/codelens_test.go b/gopls/internal/test/integration/codelens/codelens_test.go index c4711135dc0..bb8ad95ee19 100644 --- a/gopls/internal/test/integration/codelens/codelens_test.go +++ b/gopls/internal/test/integration/codelens/codelens_test.go @@ -252,7 +252,8 @@ func TestUpgradeCodelens_ModVendor(t *testing.T) { // This test checks the regression of golang/go#66055. The upgrade codelens // should work in a mod vendor context (the test above using a go.work file // was not broken). - testenv.NeedsGo1Point(t, 22) + testenv.NeedsGoCommand1Point(t, 22) + const shouldUpdateDep = ` -- go.mod -- module mod.com/a diff --git a/gopls/internal/test/integration/codelens/gcdetails_test.go b/gopls/internal/test/integration/codelens/gcdetails_test.go index 359a7804ec4..67750382de0 100644 --- a/gopls/internal/test/integration/codelens/gcdetails_test.go +++ b/gopls/internal/test/integration/codelens/gcdetails_test.go @@ -14,16 +14,12 @@ import ( . "golang.org/x/tools/gopls/internal/test/integration" "golang.org/x/tools/gopls/internal/test/integration/fake" "golang.org/x/tools/gopls/internal/util/bug" - "golang.org/x/tools/internal/testenv" ) func TestGCDetails_Toggle(t *testing.T) { if runtime.GOOS == "android" { t.Skipf("the gc details code lens doesn't work on Android") } - // The overlay portion of the test fails with go1.19. - // I'm not sure why and not inclined to investigate. - testenv.NeedsGo1Point(t, 20) const mod = ` -- go.mod -- diff --git a/gopls/internal/test/integration/diagnostics/diagnostics_test.go b/gopls/internal/test/integration/diagnostics/diagnostics_test.go index 2c9782a17ac..0b8895b3d31 100644 --- a/gopls/internal/test/integration/diagnostics/diagnostics_test.go +++ b/gopls/internal/test/integration/diagnostics/diagnostics_test.go @@ -335,7 +335,7 @@ func Hello() { InitialWorkspaceLoad, Diagnostics(env.AtRegexp("main.go", `"mod.com/bob"`)), ) - if err := env.Sandbox.RunGoCommand(env.Ctx, "", "mod", []string{"init", "mod.com"}, nil, true); err != nil { + if _, err := env.Sandbox.RunGoCommand(env.Ctx, "", "mod", []string{"init", "mod.com"}, nil, true); err != nil { t.Fatal(err) } env.AfterChange( diff --git a/gopls/internal/test/integration/fake/sandbox.go b/gopls/internal/test/integration/fake/sandbox.go index fcaa50f0a76..7adf3e3e4a9 100644 --- a/gopls/internal/test/integration/fake/sandbox.go +++ b/gopls/internal/test/integration/fake/sandbox.go @@ -234,10 +234,10 @@ func (sb *Sandbox) goCommandInvocation() gocommand.Invocation { return inv } -// RunGoCommand executes a go command in the sandbox. If checkForFileChanges is -// true, the sandbox scans the working directory and emits file change events -// for any file changes it finds. -func (sb *Sandbox) RunGoCommand(ctx context.Context, dir, verb string, args, env []string, checkForFileChanges bool) error { +// RunGoCommand executes a go command in the sandbox and returns its standard +// output. If checkForFileChanges is true, the sandbox scans the working +// directory and emits file change events for any file changes it finds. +func (sb *Sandbox) RunGoCommand(ctx context.Context, dir, verb string, args, env []string, checkForFileChanges bool) ([]byte, error) { inv := sb.goCommandInvocation() inv.Verb = verb inv.Args = args @@ -247,7 +247,7 @@ func (sb *Sandbox) RunGoCommand(ctx context.Context, dir, verb string, args, env } stdout, stderr, _, err := sb.goCommandRunner.RunRaw(ctx, inv) if err != nil { - return fmt.Errorf("go command failed (stdout: %s) (stderr: %s): %v", stdout.String(), stderr.String(), err) + return nil, fmt.Errorf("go command failed (stdout: %s) (stderr: %s): %v", stdout.String(), stderr.String(), err) } // Since running a go command may result in changes to workspace files, // check if we need to send any "watched" file events. @@ -256,10 +256,10 @@ func (sb *Sandbox) RunGoCommand(ctx context.Context, dir, verb string, args, env // for benchmarks. Consider refactoring. if sb.Workdir != nil && checkForFileChanges { if err := sb.Workdir.CheckForFileChanges(ctx); err != nil { - return fmt.Errorf("checking for file changes: %w", err) + return nil, fmt.Errorf("checking for file changes: %w", err) } } - return nil + return stdout.Bytes(), nil } // GoVersion checks the version of the go command. @@ -275,7 +275,7 @@ func (sb *Sandbox) Close() error { if sb.gopath != "" { // Important: run this command in RootDir so that it doesn't interact with // any toolchain downloads that may occur - goCleanErr = sb.RunGoCommand(context.Background(), sb.RootDir(), "clean", []string{"-modcache"}, nil, false) + _, goCleanErr = sb.RunGoCommand(context.Background(), sb.RootDir(), "clean", []string{"-modcache"}, nil, false) } err := robustio.RemoveAll(sb.rootdir) if err != nil || goCleanErr != nil { diff --git a/gopls/internal/test/integration/misc/configuration_test.go b/gopls/internal/test/integration/misc/configuration_test.go index e96fe5dd806..1077c21ac36 100644 --- a/gopls/internal/test/integration/misc/configuration_test.go +++ b/gopls/internal/test/integration/misc/configuration_test.go @@ -15,11 +15,6 @@ import ( // Test that enabling and disabling produces the expected results of showing // and hiding staticcheck analysis results. func TestChangeConfiguration(t *testing.T) { - // Staticcheck only supports Go versions >= 1.20. - // Note: keep this in sync with TestStaticcheckWarning. Below this version we - // should get an error when setting staticcheck configuration. - testenv.NeedsGo1Point(t, 20) - const files = ` -- go.mod -- module mod.com @@ -164,8 +159,6 @@ type B struct { // // Gopls should not get confused about buffer content when recreating the view. func TestMajorOptionsChange(t *testing.T) { - testenv.NeedsGo1Point(t, 20) // needs staticcheck - const files = ` -- go.mod -- module mod.com diff --git a/gopls/internal/test/integration/misc/formatting_test.go b/gopls/internal/test/integration/misc/formatting_test.go index 1808dbc8791..a0f86d3530c 100644 --- a/gopls/internal/test/integration/misc/formatting_test.go +++ b/gopls/internal/test/integration/misc/formatting_test.go @@ -10,7 +10,6 @@ import ( "golang.org/x/tools/gopls/internal/test/compare" . "golang.org/x/tools/gopls/internal/test/integration" - "golang.org/x/tools/internal/testenv" ) const unformattedProgram = ` @@ -303,7 +302,6 @@ func main() { } func TestGofumptFormatting(t *testing.T) { - testenv.NeedsGo1Point(t, 20) // gofumpt requires go 1.20+ // Exercise some gofumpt formatting rules: // - No empty lines following an assignment operator // - Octal integer literals should use the 0o prefix on modules using Go @@ -367,8 +365,6 @@ const Bar = 42 } func TestGofumpt_Issue61692(t *testing.T) { - testenv.NeedsGo1Point(t, 21) - const input = ` -- go.mod -- module foo diff --git a/gopls/internal/test/integration/misc/hover_test.go b/gopls/internal/test/integration/misc/hover_test.go index 9c679f02d53..47a1cb066f8 100644 --- a/gopls/internal/test/integration/misc/hover_test.go +++ b/gopls/internal/test/integration/misc/hover_test.go @@ -14,7 +14,6 @@ import ( "golang.org/x/tools/gopls/internal/protocol" . "golang.org/x/tools/gopls/internal/test/integration" "golang.org/x/tools/gopls/internal/test/integration/fake" - "golang.org/x/tools/internal/testenv" ) func TestHoverUnexported(t *testing.T) { @@ -282,7 +281,6 @@ go 1.16 } func TestHoverCompletionMarkdown(t *testing.T) { - testenv.NeedsGo1Point(t, 19) const source = ` -- go.mod -- module mod.com @@ -343,7 +341,6 @@ func Hello() string { // Test that the generated markdown contains links for Go references. // https://github.com/golang/go/issues/58352 func TestHoverLinks(t *testing.T) { - testenv.NeedsGo1Point(t, 19) const input = ` -- go.mod -- go 1.19 @@ -465,7 +462,6 @@ SKIPPED ` func TestHoverEmbedDirective(t *testing.T) { - testenv.NeedsGo1Point(t, 19) Run(t, embedHover, func(t *testing.T, env *Env) { env.OpenFile("main.go") from := env.RegexpSearch("main.go", `\*.txt`) @@ -606,8 +602,6 @@ func main() { } func TestHoverBuiltinFile(t *testing.T) { - testenv.NeedsGo1Point(t, 21) // uses 'min' - // This test verifies that hovering in the builtin file provides the same // hover content as hovering over a use of a builtin. diff --git a/gopls/internal/test/integration/misc/imports_test.go b/gopls/internal/test/integration/misc/imports_test.go index 15fbd87e0fd..30a161017dc 100644 --- a/gopls/internal/test/integration/misc/imports_test.go +++ b/gopls/internal/test/integration/misc/imports_test.go @@ -292,9 +292,9 @@ var _, _ = x.X, y.Y // inclined to undertake. func cleanModCache(t *testing.T, modcache string) { cmd := exec.Command("go", "clean", "-modcache") - cmd.Env = append(os.Environ(), "GOMODCACHE="+modcache) - if err := cmd.Run(); err != nil { - t.Errorf("cleaning modcache: %v", err) + cmd.Env = append(os.Environ(), "GOMODCACHE="+modcache, "GOTOOLCHAIN=local") + if output, err := cmd.CombinedOutput(); err != nil { + t.Errorf("cleaning modcache: %v\noutput:\n%s", err, string(output)) } } diff --git a/gopls/internal/test/integration/misc/staticcheck_test.go b/gopls/internal/test/integration/misc/staticcheck_test.go index 31302393252..5af0cb42a10 100644 --- a/gopls/internal/test/integration/misc/staticcheck_test.go +++ b/gopls/internal/test/integration/misc/staticcheck_test.go @@ -7,14 +7,10 @@ package misc import ( "testing" - "golang.org/x/tools/internal/testenv" - . "golang.org/x/tools/gopls/internal/test/integration" ) func TestStaticcheckGenerics(t *testing.T) { - testenv.NeedsGo1Point(t, 20) // staticcheck requires go1.20+ - // CL 583778 causes buildir not to run on packages that use // range-over-func, since it might otherwise crash. But nearly // all packages will soon meet this description, so the @@ -85,8 +81,6 @@ var FooErr error = errors.New("foo") // Test for golang/go#56270: an analysis with related info should not panic if // analysis.RelatedInformation.End is not set. func TestStaticcheckRelatedInfo(t *testing.T) { - testenv.NeedsGo1Point(t, 20) // staticcheck is only supported at Go 1.20+ - // CL 583778 causes buildir not to run on packages that use // range-over-func, since it might otherwise crash. But nearly // all packages will soon meet this description, so the diff --git a/gopls/internal/test/integration/misc/webserver_test.go b/gopls/internal/test/integration/misc/webserver_test.go index 24518145721..bff29e7a262 100644 --- a/gopls/internal/test/integration/misc/webserver_test.go +++ b/gopls/internal/test/integration/misc/webserver_test.go @@ -361,7 +361,7 @@ func f(buf bytes.Buffer, greeting string) { // TestAssembly is a basic test of the web-based assembly listing. func TestAssembly(t *testing.T) { - testenv.NeedsGo1Point(t, 22) // for up-to-date assembly listing + testenv.NeedsGoCommand1Point(t, 22) // for up-to-date assembly listing const files = ` -- go.mod -- diff --git a/gopls/internal/test/integration/regtest.go b/gopls/internal/test/integration/regtest.go index b676fd4c500..dc9600af7df 100644 --- a/gopls/internal/test/integration/regtest.go +++ b/gopls/internal/test/integration/regtest.go @@ -9,7 +9,10 @@ import ( "flag" "fmt" "os" + "os/exec" + "path/filepath" "runtime" + "strings" "testing" "time" @@ -189,5 +192,56 @@ func Main(m *testing.M) (code int) { } runner.tempDir = dir + FilterToolchainPathAndGOROOT() + return m.Run() } + +// FilterToolchainPathAndGOROOT updates the PATH and GOROOT environment +// variables for the current process to effectively revert the changes made by +// the go command when performing a toolchain switch in the context of `go +// test` (see golang/go#68005). +// +// It does this by looking through PATH for a go command that is NOT a +// toolchain go command, and adjusting PATH to find that go command. Then it +// unsets GOROOT in order to use the default GOROOT for that go command. +// +// TODO(rfindley): this is very much a hack, so that our 1.21 and 1.22 builders +// actually exercise integration with older go commands. In golang/go#69321, we +// hope to do better. +func FilterToolchainPathAndGOROOT() { + if localGo, first := findLocalGo(); localGo != "" && !first { + dir := filepath.Dir(localGo) + path := os.Getenv("PATH") + os.Setenv("PATH", dir+string(os.PathListSeparator)+path) + os.Unsetenv("GOROOT") // Remove the GOROOT value that was added by toolchain switch. + } +} + +// findLocalGo returns a path to a local (=non-toolchain) Go version, or the +// empty string if none is found. +// +// The second result reports if path matches the result of exec.LookPath. +func findLocalGo() (path string, first bool) { + paths := filepath.SplitList(os.Getenv("PATH")) + for _, path := range paths { + // Use a simple heuristic to filter out toolchain paths. + if strings.Contains(path, "toolchain@v0.0.1-go") && filepath.Base(path) == "bin" { + continue // toolchain path + } + fullPath := filepath.Join(path, "go") + fi, err := os.Stat(fullPath) + if err != nil { + continue + } + if fi.Mode()&0111 != 0 { + first := false + pathGo, err := exec.LookPath("go") + if err == nil { + first = fullPath == pathGo + } + return fullPath, first + } + } + return "", false +} diff --git a/gopls/internal/test/integration/runner.go b/gopls/internal/test/integration/runner.go index 7b3b757536f..6d10b16cab3 100644 --- a/gopls/internal/test/integration/runner.go +++ b/gopls/internal/test/integration/runner.go @@ -203,7 +203,7 @@ func (r *Runner) Run(t *testing.T, files string, test TestFunc, opts ...RunOptio // Write the go.sum file for the requested directories, before starting the server. for _, dir := range config.writeGoSum { - if err := sandbox.RunGoCommand(context.Background(), dir, "list", []string{"-mod=mod", "./..."}, []string{"GOWORK=off"}, true); err != nil { + if _, err := sandbox.RunGoCommand(context.Background(), dir, "list", []string{"-mod=mod", "./..."}, []string{"GOWORK=off"}, true); err != nil { t.Fatal(err) } } diff --git a/gopls/internal/test/integration/watch/watch_test.go b/gopls/internal/test/integration/watch/watch_test.go index 7f41511d140..3fb1ab546a6 100644 --- a/gopls/internal/test/integration/watch/watch_test.go +++ b/gopls/internal/test/integration/watch/watch_test.go @@ -588,7 +588,7 @@ func main() { env.AfterChange( NoDiagnostics(ForFile("main.go")), ) - if err := env.Sandbox.RunGoCommand(env.Ctx, "", "mod", []string{"init", "mod.com"}, nil, true); err != nil { + if _, err := env.Sandbox.RunGoCommand(env.Ctx, "", "mod", []string{"init", "mod.com"}, nil, true); err != nil { t.Fatal(err) } diff --git a/gopls/internal/test/integration/workspace/broken_test.go b/gopls/internal/test/integration/workspace/broken_test.go index 8f00be775e4..33b0b834eb6 100644 --- a/gopls/internal/test/integration/workspace/broken_test.go +++ b/gopls/internal/test/integration/workspace/broken_test.go @@ -10,7 +10,6 @@ import ( "golang.org/x/tools/gopls/internal/server" . "golang.org/x/tools/gopls/internal/test/integration" - "golang.org/x/tools/internal/testenv" ) // This file holds various tests for UX with respect to broken workspaces. @@ -23,10 +22,6 @@ import ( // Test for golang/go#53933 func TestBrokenWorkspace_DuplicateModules(t *testing.T) { - // The go command error message was improved in Go 1.20 to mention multiple - // modules. - testenv.NeedsGo1Point(t, 20) - // This proxy module content is replaced by the workspace, but is still // required for module resolution to function in the Go command. const proxy = ` diff --git a/gopls/internal/test/integration/workspace/workspace_test.go b/gopls/internal/test/integration/workspace/workspace_test.go index ac74e6deed5..587ac522c41 100644 --- a/gopls/internal/test/integration/workspace/workspace_test.go +++ b/gopls/internal/test/integration/workspace/workspace_test.go @@ -255,7 +255,7 @@ func TestAutomaticWorkspaceModule_Interdependent(t *testing.T) { } func TestWorkspaceVendoring(t *testing.T) { - testenv.NeedsGo1Point(t, 22) + testenv.NeedsGoCommand1Point(t, 22) WithOptions( ProxyFiles(workspaceModuleProxy), ).Run(t, multiModule, func(t *testing.T, env *Env) { diff --git a/gopls/internal/test/integration/wrappers.go b/gopls/internal/test/integration/wrappers.go index 68d23ddd222..989ae913acf 100644 --- a/gopls/internal/test/integration/wrappers.go +++ b/gopls/internal/test/integration/wrappers.go @@ -314,18 +314,20 @@ func (e *Env) RunGenerate(dir string) { // RunGoCommand runs the given command in the sandbox's default working // directory. -func (e *Env) RunGoCommand(verb string, args ...string) { +func (e *Env) RunGoCommand(verb string, args ...string) []byte { e.T.Helper() - if err := e.Sandbox.RunGoCommand(e.Ctx, "", verb, args, nil, true); err != nil { + out, err := e.Sandbox.RunGoCommand(e.Ctx, "", verb, args, nil, true) + if err != nil { e.T.Fatal(err) } + return out } // RunGoCommandInDir is like RunGoCommand, but executes in the given // relative directory of the sandbox. func (e *Env) RunGoCommandInDir(dir, verb string, args ...string) { e.T.Helper() - if err := e.Sandbox.RunGoCommand(e.Ctx, dir, verb, args, nil, true); err != nil { + if _, err := e.Sandbox.RunGoCommand(e.Ctx, dir, verb, args, nil, true); err != nil { e.T.Fatal(err) } } @@ -334,7 +336,7 @@ func (e *Env) RunGoCommandInDir(dir, verb string, args ...string) { // relative directory of the sandbox with the given additional environment variables. func (e *Env) RunGoCommandInDirWithEnv(dir string, env []string, verb string, args ...string) { e.T.Helper() - if err := e.Sandbox.RunGoCommand(e.Ctx, dir, verb, args, env, true); err != nil { + if _, err := e.Sandbox.RunGoCommand(e.Ctx, dir, verb, args, env, true); err != nil { e.T.Fatal(err) } } @@ -355,7 +357,7 @@ func (e *Env) GoVersion() int { func (e *Env) DumpGoSum(dir string) { e.T.Helper() - if err := e.Sandbox.RunGoCommand(e.Ctx, dir, "list", []string{"-mod=mod", "./..."}, nil, true); err != nil { + if _, err := e.Sandbox.RunGoCommand(e.Ctx, dir, "list", []string{"-mod=mod", "./..."}, nil, true); err != nil { e.T.Fatal(err) } sumFile := path.Join(dir, "go.sum") diff --git a/gopls/internal/test/marker/marker_test.go b/gopls/internal/test/marker/marker_test.go index 6b3957834d9..032b4e8462f 100644 --- a/gopls/internal/test/marker/marker_test.go +++ b/gopls/internal/test/marker/marker_test.go @@ -55,6 +55,7 @@ func TestMain(m *testing.M) { testenv.ExitIfSmallMachine() // Disable GOPACKAGESDRIVER, as it can cause spurious test failures. os.Setenv("GOPACKAGESDRIVER", "off") + integration.FilterToolchainPathAndGOROOT() os.Exit(m.Run()) } @@ -130,12 +131,19 @@ func Test(t *testing.T) { } testenv.NeedsGo1Point(t, go1point) } - if test.maxGoVersion != "" { + if test.minGoCommandVersion != "" { var go1point int - if _, err := fmt.Sscanf(test.maxGoVersion, "go1.%d", &go1point); err != nil { - t.Fatalf("parsing -max_go version: %v", err) + if _, err := fmt.Sscanf(test.minGoCommandVersion, "go1.%d", &go1point); err != nil { + t.Fatalf("parsing -min_go_command version: %v", err) } - testenv.SkipAfterGo1Point(t, go1point) + testenv.NeedsGoCommand1Point(t, go1point) + } + if test.maxGoCommandVersion != "" { + var go1point int + if _, err := fmt.Sscanf(test.maxGoCommandVersion, "go1.%d", &go1point); err != nil { + t.Fatalf("parsing -max_go_command version: %v", err) + } + testenv.SkipAfterGoCommand1Point(t, go1point) } if test.cgo { testenv.NeedsTool(t, "cgo") @@ -533,16 +541,17 @@ type markerTest struct { flags []string // flags extracted from the special "flags" archive file. // Parsed flags values. See the flag definitions below for documentation. - minGoVersion string - maxGoVersion string - cgo bool - writeGoSum []string - skipGOOS []string - skipGOARCH []string - ignoreExtraDiags bool - filterBuiltins bool - filterKeywords bool - errorsOK bool + minGoVersion string // minimum Go runtime version; max should never be needed + minGoCommandVersion string + maxGoCommandVersion string + cgo bool + writeGoSum []string + skipGOOS []string + skipGOARCH []string + ignoreExtraDiags bool + filterBuiltins bool + filterKeywords bool + errorsOK bool } // flagSet returns the flagset used for parsing the special "flags" file in the @@ -550,7 +559,8 @@ type markerTest struct { func (t *markerTest) flagSet() *flag.FlagSet { flags := flag.NewFlagSet(t.name, flag.ContinueOnError) flags.StringVar(&t.minGoVersion, "min_go", "", "if set, the minimum go1.X version required for this test") - flags.StringVar(&t.maxGoVersion, "max_go", "", "if set, the maximum go1.X version required for this test") + flags.StringVar(&t.minGoCommandVersion, "min_go_command", "", "if set, the minimum go1.X go command version required for this test") + flags.StringVar(&t.maxGoCommandVersion, "max_go_command", "", "if set, the maximum go1.X go command version required for this test") flags.BoolVar(&t.cgo, "cgo", false, "if set, requires cgo (both the cgo tool and CGO_ENABLED=1)") flags.Var((*stringListValue)(&t.writeGoSum), "write_sumfile", "if set, write the sumfile for these directories") flags.Var((*stringListValue)(&t.skipGOOS), "skip_goos", "if set, skip this test on these GOOS values") @@ -837,7 +847,7 @@ func newEnv(t *testing.T, cache *cache.Cache, files, proxyFiles map[string][]byt } for _, dir := range writeGoSum { - if err := sandbox.RunGoCommand(context.Background(), dir, "list", []string{"-mod=mod", "..."}, []string{"GOWORK=off"}, true); err != nil { + if _, err := sandbox.RunGoCommand(context.Background(), dir, "list", []string{"-mod=mod", "..."}, []string{"GOWORK=off"}, true); err != nil { t.Fatal(err) } } diff --git a/gopls/internal/test/marker/testdata/codeaction/removeparam_imports.txt b/gopls/internal/test/marker/testdata/codeaction/removeparam_imports.txt index 1f96d6b424c..9bad8232231 100644 --- a/gopls/internal/test/marker/testdata/codeaction/removeparam_imports.txt +++ b/gopls/internal/test/marker/testdata/codeaction/removeparam_imports.txt @@ -1,9 +1,6 @@ This test checks the behavior of removing a parameter with respect to various import scenarios. --- flags -- --min_go=go1.21 - -- go.mod -- module mod.test diff --git a/gopls/internal/test/marker/testdata/codeaction/removeparam_method.txt b/gopls/internal/test/marker/testdata/codeaction/removeparam_method.txt index 174d9061927..614c4d3147f 100644 --- a/gopls/internal/test/marker/testdata/codeaction/removeparam_method.txt +++ b/gopls/internal/test/marker/testdata/codeaction/removeparam_method.txt @@ -5,9 +5,6 @@ Specifically, check across package boundaries 2. handling of unnamed receivers --- flags -- --min_go=go1.20 - -- go.mod -- module example.com/rm diff --git a/gopls/internal/test/marker/testdata/codeaction/removeparam_satisfies.txt b/gopls/internal/test/marker/testdata/codeaction/removeparam_satisfies.txt index f35662e3dad..3b6ba360d29 100644 --- a/gopls/internal/test/marker/testdata/codeaction/removeparam_satisfies.txt +++ b/gopls/internal/test/marker/testdata/codeaction/removeparam_satisfies.txt @@ -8,9 +8,6 @@ that must be modified), in order to produce the desired outcome for our users. Doing so would be more complicated, so for now this test simply records the current behavior. --- flags -- --min_go=go1.20 - -- go.mod -- module example.com/rm diff --git a/gopls/internal/test/marker/testdata/completion/append.txt b/gopls/internal/test/marker/testdata/completion/append.txt index 96c09d7d428..89172211314 100644 --- a/gopls/internal/test/marker/testdata/completion/append.txt +++ b/gopls/internal/test/marker/testdata/completion/append.txt @@ -1,10 +1,7 @@ This test checks behavior of completion within append expressions. -It requires go1.23 as the new "structs" package appears as a completion. - -- flags -- -ignore_extra_diags --min_go=go1.23 -- go.mod -- module golang.org/lsptests/append diff --git a/gopls/internal/test/marker/testdata/completion/foobarbaz.txt b/gopls/internal/test/marker/testdata/completion/foobarbaz.txt index 1da0a405404..80ba5d1f5ee 100644 --- a/gopls/internal/test/marker/testdata/completion/foobarbaz.txt +++ b/gopls/internal/test/marker/testdata/completion/foobarbaz.txt @@ -3,7 +3,6 @@ This test ports some arbitrary tests from the old marker framework, that were -- flags -- -ignore_extra_diags --min_go=go1.20 -- settings.json -- { diff --git a/gopls/internal/test/marker/testdata/completion/imported-std.txt b/gopls/internal/test/marker/testdata/completion/imported-std.txt index bb17a07d4f8..e93de9563a8 100644 --- a/gopls/internal/test/marker/testdata/completion/imported-std.txt +++ b/gopls/internal/test/marker/testdata/completion/imported-std.txt @@ -13,7 +13,8 @@ behaves correctly in go1.22. (When go1.22 is assured, we can remove the min_go flag but leave the test inputs unchanged.) -- flags -- --ignore_extra_diags -min_go=go1.22 +-ignore_extra_diags +-min_go_command=go1.22 -- go.mod -- module example.com diff --git a/gopls/internal/test/marker/testdata/completion/issue62676.txt b/gopls/internal/test/marker/testdata/completion/issue62676.txt index 8f20c5872c2..af4c3b695ec 100644 --- a/gopls/internal/test/marker/testdata/completion/issue62676.txt +++ b/gopls/internal/test/marker/testdata/completion/issue62676.txt @@ -2,7 +2,6 @@ This test verifies that unimported completion respects the usePlaceholders setti -- flags -- -ignore_extra_diags --min_go=go1.21 -- settings.json -- { diff --git a/gopls/internal/test/marker/testdata/completion/nested_complit.txt b/gopls/internal/test/marker/testdata/completion/nested_complit.txt index 264ae77eab8..14677dfde73 100644 --- a/gopls/internal/test/marker/testdata/completion/nested_complit.txt +++ b/gopls/internal/test/marker/testdata/completion/nested_complit.txt @@ -5,7 +5,6 @@ version for consistency. -- flags -- -ignore_extra_diags --min_go=go1.20 -- nested_complit.go -- package nested_complit diff --git a/gopls/internal/test/marker/testdata/completion/unimported-std.txt b/gopls/internal/test/marker/testdata/completion/unimported-std.txt index 3bedf6bc5bd..0ad655c6a26 100644 --- a/gopls/internal/test/marker/testdata/completion/unimported-std.txt +++ b/gopls/internal/test/marker/testdata/completion/unimported-std.txt @@ -13,7 +13,7 @@ behaves correctly in go1.22. (When go1.22 is assured, we can remove the min_go flag but leave the test inputs unchanged.) -- flags -- --ignore_extra_diags -min_go=go1.22 +-ignore_extra_diags -- go.mod -- module example.com diff --git a/gopls/internal/test/marker/testdata/definition/embed.txt b/gopls/internal/test/marker/testdata/definition/embed.txt index 5dc976c8b4d..bd226a61f1b 100644 --- a/gopls/internal/test/marker/testdata/definition/embed.txt +++ b/gopls/internal/test/marker/testdata/definition/embed.txt @@ -5,7 +5,6 @@ and correct sizes information requires go1.21. -- flags -- -skip_goarch=386,arm --min_go=go1.21 -- go.mod -- module mod.com diff --git a/gopls/internal/test/marker/testdata/definition/standalone.txt b/gopls/internal/test/marker/testdata/definition/standalone.txt index 2612f43d833..6af1149184d 100644 --- a/gopls/internal/test/marker/testdata/definition/standalone.txt +++ b/gopls/internal/test/marker/testdata/definition/standalone.txt @@ -1,9 +1,6 @@ This test checks the behavior of standalone packages, in particular documenting our failure to support test files as standalone packages (golang/go#64233). --- flags -- --min_go=go1.20 - -- go.mod -- module golang.org/lsptests/a diff --git a/gopls/internal/test/marker/testdata/diagnostics/analyzers.txt b/gopls/internal/test/marker/testdata/diagnostics/analyzers.txt index 7fc3230248b..312a0c57120 100644 --- a/gopls/internal/test/marker/testdata/diagnostics/analyzers.txt +++ b/gopls/internal/test/marker/testdata/diagnostics/analyzers.txt @@ -11,7 +11,6 @@ module example.com go 1.12 -- flags -- --min_go=go1.21 -cgo -- bad_test.go -- diff --git a/gopls/internal/test/marker/testdata/diagnostics/issue60605.txt b/gopls/internal/test/marker/testdata/diagnostics/issue60605.txt index a2fb57ba0b1..f80857dcb99 100644 --- a/gopls/internal/test/marker/testdata/diagnostics/issue60605.txt +++ b/gopls/internal/test/marker/testdata/diagnostics/issue60605.txt @@ -2,9 +2,6 @@ This test verifies that we can export constants with unknown kind. Previously, the exporter would panic while attempting to convert such constants to their target type (float64, in this case). --- flags -- --min_go=go1.20 - -- go.mod -- module mod.txt/p diff --git a/gopls/internal/test/marker/testdata/diagnostics/issue67360.txt b/gopls/internal/test/marker/testdata/diagnostics/issue67360.txt index 229c99b6890..109ee53aa58 100644 --- a/gopls/internal/test/marker/testdata/diagnostics/issue67360.txt +++ b/gopls/internal/test/marker/testdata/diagnostics/issue67360.txt @@ -7,9 +7,6 @@ error to lack a column. A bug in the error parser filled in 0, not 1, for the missing information, and this is an invalid value in the 1-based UTF-8 domain, leading to a panic. --- flags -- --min_go=go1.21 - -- foo.go -- //line foo.go:1 package main //@ diag(re"package", re"internal package.*not allowed") diff --git a/gopls/internal/test/marker/testdata/diagnostics/stdversion.txt b/gopls/internal/test/marker/testdata/diagnostics/stdversion.txt index 652ddd6b56a..c6a19a77717 100644 --- a/gopls/internal/test/marker/testdata/diagnostics/stdversion.txt +++ b/gopls/internal/test/marker/testdata/diagnostics/stdversion.txt @@ -7,7 +7,7 @@ See also go/analysis/passes/stdversion/testdata/test.txtar, which runs the same test in the analysistest framework. -- flags -- --min_go=go1.22 +-min_go_command=go1.22 -- go.mod -- module example.com diff --git a/gopls/internal/test/marker/testdata/diagnostics/useinternal.txt b/gopls/internal/test/marker/testdata/diagnostics/useinternal.txt index 86010dc29c8..567d2a9d4ae 100644 --- a/gopls/internal/test/marker/testdata/diagnostics/useinternal.txt +++ b/gopls/internal/test/marker/testdata/diagnostics/useinternal.txt @@ -5,9 +5,6 @@ This list error changed in Go 1.21. See TestValidImportCheck_GoPackagesDriver for a test that no diagnostic is produced when using a GOPACKAGESDRIVER (such as for Bazel). --- flags -- --min_go=go1.21 - -- go.mod -- module bad.test diff --git a/gopls/internal/test/marker/testdata/fixedbugs/issue66109.txt b/gopls/internal/test/marker/testdata/fixedbugs/issue66109.txt index c73390066ae..3ece2f264f6 100644 --- a/gopls/internal/test/marker/testdata/fixedbugs/issue66109.txt +++ b/gopls/internal/test/marker/testdata/fixedbugs/issue66109.txt @@ -1,8 +1,10 @@ This test exercises the crash in golang/go#66109: a dangling reference due to test variants of a command-line-arguments package. +Depends on go1.22+ go list errors. + -- flags -- --min_go=go1.22 +-min_go_command=go1.22 -- go.mod -- module example.com/tools diff --git a/gopls/internal/test/marker/testdata/fixedbugs/issue66876.txt b/gopls/internal/test/marker/testdata/fixedbugs/issue66876.txt index d6edcb57a18..db3def0bd7c 100644 --- a/gopls/internal/test/marker/testdata/fixedbugs/issue66876.txt +++ b/gopls/internal/test/marker/testdata/fixedbugs/issue66876.txt @@ -4,7 +4,7 @@ when the go.mod go version is set to a 1.22 toolchain version (1.22.x). In golang/go#66876, gopls failed to handle this correctly. -- flags -- --min_go=go1.22 +-min_go_command=go1.22 -- go.mod -- module example.com/loopclosure diff --git a/gopls/internal/test/marker/testdata/format/issue59554.txt b/gopls/internal/test/marker/testdata/format/issue59554.txt index 816c9d1e06f..aa436301102 100644 --- a/gopls/internal/test/marker/testdata/format/issue59554.txt +++ b/gopls/internal/test/marker/testdata/format/issue59554.txt @@ -4,11 +4,6 @@ directives. Note that gofumpt is needed for this test case, as it reformats var decls into short var decls. -Note that gofumpt requires Go 1.20. - --- flags -- --min_go=go1.20 - -- settings.json -- { "formatting.gofumpt": true diff --git a/gopls/internal/test/marker/testdata/hover/comment.txt b/gopls/internal/test/marker/testdata/hover/comment.txt index 479aff6473f..0582b24f4db 100644 --- a/gopls/internal/test/marker/testdata/hover/comment.txt +++ b/gopls/internal/test/marker/testdata/hover/comment.txt @@ -1,10 +1,5 @@ This test checks hovering over doc links in comments. -Requires go1.20+ for the unsafe package test. - --- flags -- --min_go=go1.20 - -- go.mod -- module mod.com diff --git a/gopls/internal/test/marker/testdata/hover/generics.txt b/gopls/internal/test/marker/testdata/hover/generics.txt index 50ce49bb33f..0799f399244 100644 --- a/gopls/internal/test/marker/testdata/hover/generics.txt +++ b/gopls/internal/test/marker/testdata/hover/generics.txt @@ -6,7 +6,6 @@ that affected the formatting of constraint interfaces. Its size expectations assume a 64-bit machine. -- flags -- --min_go=go1.20 -skip_goarch=386,arm -- go.mod -- diff --git a/gopls/internal/test/marker/testdata/hover/godef.txt b/gopls/internal/test/marker/testdata/hover/godef.txt index 9b2e7ec2ce3..49cdc67cb86 100644 --- a/gopls/internal/test/marker/testdata/hover/godef.txt +++ b/gopls/internal/test/marker/testdata/hover/godef.txt @@ -1,17 +1,6 @@ This test was ported from 'godef' in the old marker tests. It tests various hover and definition requests. -Requires go1.19+ for the new go/doc/comment package. - -TODO(adonovan): figure out why this test also fails -without -min_go=go1.20. Or just wait... - --- flags -- --min_go=go1.19 - --- flags -- --min_go=go1.20 - -- go.mod -- module godef.test diff --git a/gopls/internal/test/marker/testdata/hover/sizeoffset.txt b/gopls/internal/test/marker/testdata/hover/sizeoffset.txt index 62f3b76dd60..1d1f21466f1 100644 --- a/gopls/internal/test/marker/testdata/hover/sizeoffset.txt +++ b/gopls/internal/test/marker/testdata/hover/sizeoffset.txt @@ -11,7 +11,6 @@ Notes: -- flags -- -skip_goarch=386,arm --min_go=go1.22 -- go.mod -- module example.com diff --git a/gopls/internal/test/marker/testdata/inlayhints/issue67142.txt b/gopls/internal/test/marker/testdata/inlayhints/issue67142.txt index 18e98e81acb..df25e6fb190 100644 --- a/gopls/internal/test/marker/testdata/inlayhints/issue67142.txt +++ b/gopls/internal/test/marker/testdata/inlayhints/issue67142.txt @@ -2,7 +2,6 @@ Regression test for golang/go#67142. -- flags -- -ignore_extra_diags --min_go=go1.21 -- settings.json -- { diff --git a/gopls/internal/test/marker/testdata/modfile/godebug.txt b/gopls/internal/test/marker/testdata/modfile/godebug.txt index dbee5faae01..49fab9bda7c 100644 --- a/gopls/internal/test/marker/testdata/modfile/godebug.txt +++ b/gopls/internal/test/marker/testdata/modfile/godebug.txt @@ -2,7 +2,7 @@ This test basic gopls functionality in a workspace with a godebug directive in its modfile. -- flags -- --min_go=go1.23 +-min_go_command=go1.23 -- go.mod -- module example.com/m diff --git a/gopls/internal/test/marker/testdata/modfile/godebug_bad.txt b/gopls/internal/test/marker/testdata/modfile/godebug_bad.txt index 1d06c7cf73c..1b26f607dc1 100644 --- a/gopls/internal/test/marker/testdata/modfile/godebug_bad.txt +++ b/gopls/internal/test/marker/testdata/modfile/godebug_bad.txt @@ -3,7 +3,7 @@ This test checks that we surface the error for unexpected godebug values. TODO(golang/go#67623): the diagnostic should be on the bad godebug value. -- flags -- --min_go=go1.23 +-min_go_command=go1.23 -errors_ok -- go.mod -- diff --git a/gopls/internal/test/marker/testdata/references/issue60369.txt b/gopls/internal/test/marker/testdata/references/issue60369.txt index 0d868de8a15..a6a82b54339 100644 --- a/gopls/internal/test/marker/testdata/references/issue60369.txt +++ b/gopls/internal/test/marker/testdata/references/issue60369.txt @@ -4,9 +4,6 @@ references to the package name p. The bug was fixed in release go1.21 of go/types. --- flags -- --min_go=go1.21 - -- go.mod -- module example.com go 1.12 diff --git a/gopls/internal/test/marker/testdata/rename/doclink.txt b/gopls/internal/test/marker/testdata/rename/doclink.txt index bbd9bf1287a..d4e9f96891e 100644 --- a/gopls/internal/test/marker/testdata/rename/doclink.txt +++ b/gopls/internal/test/marker/testdata/rename/doclink.txt @@ -1,8 +1,5 @@ This test checks that doc links are also handled correctly (golang/go#64495). --- flags -- --min_go=go1.21 - -- go.mod -- module example.com diff --git a/gopls/internal/test/marker/testdata/rename/generics.txt b/gopls/internal/test/marker/testdata/rename/generics.txt index 71e56dd9bc4..0f57570a5fb 100644 --- a/gopls/internal/test/marker/testdata/rename/generics.txt +++ b/gopls/internal/test/marker/testdata/rename/generics.txt @@ -9,9 +9,6 @@ Fixed bugs: - golang/go#61635: renaming type parameters did not work when they were capitalized and the package was imported by another package. --- flags -- --min_go=go1.20 - -- go.mod -- module example.com go 1.20 diff --git a/gopls/internal/test/marker/testdata/rename/issue57479.txt b/gopls/internal/test/marker/testdata/rename/issue57479.txt index 78004591398..be597fbbd29 100644 --- a/gopls/internal/test/marker/testdata/rename/issue57479.txt +++ b/gopls/internal/test/marker/testdata/rename/issue57479.txt @@ -3,9 +3,6 @@ referenced by one of the function parameters. See golang/go#57479 --- flags -- --min_go=go1.22 - -- go.mod -- module golang.org/lsptests/rename diff --git a/gopls/internal/test/marker/testdata/rename/issue60752.txt b/gopls/internal/test/marker/testdata/rename/issue60752.txt index eec24b8e9de..d3cb777d3b8 100644 --- a/gopls/internal/test/marker/testdata/rename/issue60752.txt +++ b/gopls/internal/test/marker/testdata/rename/issue60752.txt @@ -6,9 +6,6 @@ behavior of types.Scope for function parameters and results. This is a regression test for issue #60752, a bug in the type checker. --- flags -- --min_go=go1.22 - -- go.mod -- module example.com go 1.18 diff --git a/gopls/internal/test/marker/testdata/workfile/godebug.txt b/gopls/internal/test/marker/testdata/workfile/godebug.txt index fb7d7d5df2d..68fd0f2fe4b 100644 --- a/gopls/internal/test/marker/testdata/workfile/godebug.txt +++ b/gopls/internal/test/marker/testdata/workfile/godebug.txt @@ -2,7 +2,7 @@ This test basic gopls functionality in a workspace with a godebug directive in its modfile. -- flags -- --min_go=go1.23 +-min_go_command=go1.23 -- a/go.work -- go 1.23 diff --git a/gopls/internal/test/marker/testdata/workfile/godebug_bad.txt b/gopls/internal/test/marker/testdata/workfile/godebug_bad.txt index 52ad7c07d57..98a0dd250d2 100644 --- a/gopls/internal/test/marker/testdata/workfile/godebug_bad.txt +++ b/gopls/internal/test/marker/testdata/workfile/godebug_bad.txt @@ -3,7 +3,7 @@ This test checks that we surface the error for unexpected godebug values. TODO(golang/go#67623): the diagnostic should be on the bad godebug value. -- flags -- --min_go=go1.23 +-min_go_command=go1.23 -errors_ok -- go.work -- diff --git a/gopls/internal/test/marker/testdata/zeroconfig/nested.txt b/gopls/internal/test/marker/testdata/zeroconfig/nested.txt index e76bb0c6ec0..2b8a22b1389 100644 --- a/gopls/internal/test/marker/testdata/zeroconfig/nested.txt +++ b/gopls/internal/test/marker/testdata/zeroconfig/nested.txt @@ -1,9 +1,6 @@ This test checks that gopls works with nested modules, including multiple nested modules. --- flags -- --min_go=go1.20 - -- main.go -- package main diff --git a/internal/testenv/testenv.go b/internal/testenv/testenv.go index 99ae9213161..70c186b13b5 100644 --- a/internal/testenv/testenv.go +++ b/internal/testenv/testenv.go @@ -8,6 +8,7 @@ package testenv import ( "bytes" + "context" "fmt" "go/build" "os" @@ -21,6 +22,7 @@ import ( "time" "golang.org/x/mod/modfile" + "golang.org/x/tools/internal/gocommand" "golang.org/x/tools/internal/goroot" ) @@ -323,6 +325,36 @@ func Go1Point() int { panic("bad release tags") } +// NeedsGoCommand1Point skips t if the ambient go command version in the PATH +// of the current process is older than 1.x. +// +// NeedsGoCommand1Point memoizes the result of running the go command, so +// should be called after all mutations of PATH. +func NeedsGoCommand1Point(t testing.TB, x int) { + NeedsTool(t, "go") + go1point, err := goCommand1Point() + if err != nil { + panic(fmt.Sprintf("unable to determine go version: %v", err)) + } + if go1point < x { + t.Helper() + t.Skipf("go command is version 1.%d, older than required 1.%d", go1point, x) + } +} + +var ( + goCommand1PointOnce sync.Once + goCommand1Point_ int + goCommand1PointErr error +) + +func goCommand1Point() (int, error) { + goCommand1PointOnce.Do(func() { + goCommand1Point_, goCommand1PointErr = gocommand.GoVersion(context.Background(), gocommand.Invocation{}, new(gocommand.Runner)) + }) + return goCommand1Point_, goCommand1PointErr +} + // NeedsGo1Point skips t if the Go version used to run the test is older than // 1.x. func NeedsGo1Point(t testing.TB, x int) { @@ -332,6 +364,23 @@ func NeedsGo1Point(t testing.TB, x int) { } } +// SkipAfterGo1Point skips t if the ambient go command version in the PATH of +// the current process is newer than 1.x. +// +// SkipAfterGoCommand1Point memoizes the result of running the go command, so +// should be called after any mutation of PATH. +func SkipAfterGoCommand1Point(t testing.TB, x int) { + NeedsTool(t, "go") + go1point, err := goCommand1Point() + if err != nil { + panic(fmt.Sprintf("unable to determine go version: %v", err)) + } + if go1point > x { + t.Helper() + t.Skipf("go command is version 1.%d, newer than maximum 1.%d", go1point, x) + } +} + // SkipAfterGo1Point skips t if the Go version used to run the test is newer than // 1.x. func SkipAfterGo1Point(t testing.TB, x int) {