diff --git a/library.sh b/library.sh index d487a149..62139675 100755 --- a/library.sh +++ b/library.sh @@ -681,7 +681,7 @@ function start_knative_eventing_extension() { # Parameters: $1 - tool package for go run. # $2..$n - parameters passed to the tool. function go_run() { - local package + local package gotoolchain package="$1" if [[ "$package" != *@* ]]; then abort 'Package for "go_run" needs to have @version' @@ -696,6 +696,11 @@ function go_run() { GORUN_PATH="$(mktemp -t -d -u gopath.XXXXXXXX)" fi export GORUN_PATH + gotoolchain="$(go env GOTOOLCHAIN)" + if [[ "$package" == knative.dev/toolbox/* ]]; then + gotoolchain=auto + fi + GOTOOLCHAIN="${gotoolchain}" \ GOPATH="${GORUN_PATH}" \ GOFLAGS='' \ go run "$package" "$@" diff --git a/presubmit-tests.sh b/presubmit-tests.sh index b96ffadf..f11585d4 100755 --- a/presubmit-tests.sh +++ b/presubmit-tests.sh @@ -141,7 +141,7 @@ function __build_test_runner_for_module() { # Don't merge these two lines, or return code will always be 0. # Get all build tags in go code (ignore /vendor, /hack and /third_party) local tags - tags="$(go run knative.dev/toolbox/go-ls-tags@latest --joiner=,)" + tags="$(go_run knative.dev/toolbox/go-ls-tags@latest --joiner=,)" local go_pkg_dirs go_pkg_dirs="$(go list -tags "${tags}" ./...)" || return $? if [[ -z "${go_pkg_dirs}" ]]; then diff --git a/test/unit/codegen_test.go b/test/unit/codegen_test.go index c78aebb7..ea42d6b4 100644 --- a/test/unit/codegen_test.go +++ b/test/unit/codegen_test.go @@ -41,8 +41,8 @@ Deepcopy generation complete ), stderr: warned("Failed to determine the knative.dev/pkg package"), }} - for i := range tcs { - tc := tcs[i] + for _, tc := range tcs { + tc := tc t.Run(tc.name, tc.test(sc)) } } diff --git a/test/unit/presubmit_test.go b/test/unit/presubmit_test.go index bf002f5b..845217b6 100644 --- a/test/unit/presubmit_test.go +++ b/test/unit/presubmit_test.go @@ -43,8 +43,8 @@ func TestPresubmitTestMainFunc(t *testing.T) { header("UNIT TESTS PASSED"), }, }} - for i := range tcs { - tc := tcs[i] + for _, tc := range tcs { + tc := tc t.Run(tc.name, tc.test(sc)) } } diff --git a/test/unit/release_test.go b/test/unit/release_test.go index 07c152ad..82889d65 100644 --- a/test/unit/release_test.go +++ b/test/unit/release_test.go @@ -44,8 +44,8 @@ func TestBuildFromSource(t *testing.T) { }, stdout: append(outChecks, contains(checksumsContent)), }} - for i := range tcs { - tc := tcs[i] + for _, tc := range tcs { + tc := tc t.Run(tc.name, func(t *testing.T) { tmp := t.TempDir() sc := testReleaseShellScript( diff --git a/test/unit/report_go_test.go b/test/unit/report_go_test.go index e042c630..65f3b804 100644 --- a/test/unit/report_go_test.go +++ b/test/unit/report_go_test.go @@ -47,8 +47,8 @@ func TestReportGoTest(t *testing.T) { }, logChecks...), stderr: []check{contains("exit status 1")}, }} - for i := range tcs { - tc := tcs[i] + for _, tc := range tcs { + tc := tc t.Run(tc.name, tc.test(sc)) } } diff --git a/test/unit/sharedlib_test.go b/test/unit/sharedlib_test.go index 4ec4b25a..bd94559d 100644 --- a/test/unit/sharedlib_test.go +++ b/test/unit/sharedlib_test.go @@ -5,13 +5,15 @@ import ( "embed" "errors" "fmt" - "io" + "io/fs" "os" "os/exec" "path" + "path/filepath" "regexp" "runtime" "strings" + "syscall" "testing" "time" @@ -181,10 +183,15 @@ func retcode(code int) *returnCode { return &rc } +var errOutStripGoSwitchingRe = regexp.MustCompile( + "go: knative\\.dev/toolbox@v0\\.0\\.0-\\d+-[0-9a-f]+ requires " + + "go >= \\d\\.\\d+\\.\\d+; switching to go\\d\\.\\d+\\.\\d+\n", +) + func (tc testCase) test(sc shellScript) func(t *testing.T) { return func(t *testing.T) { t.Parallel() - code, out, err, src := sc.run(t, tc.testCommands()) + code, out, errOut, src := sc.run(t, tc.testCommands()) tc.validRetcode(t, code) checkStream := func(output string, otype outputType, checks []check) { success := true @@ -197,7 +204,9 @@ func (tc testCase) test(sc shellScript) func(t *testing.T) { } } checkStream(out, outputTypeStdout, coalesce(tc.stdout, empty())) - checkStream(err, outputTypeStderr, coalesce(tc.stderr, empty())) + // skip go switching messages from asserting + errOut = errOutStripGoSwitchingRe.ReplaceAllString(errOut, "") + checkStream(errOut, outputTypeStderr, coalesce(tc.stderr, empty())) if t.Failed() { failedScriptPath := path.Join(os.TempDir(), @@ -308,7 +317,7 @@ func (s simply) Invocations(_ string) []string { type callOriginal struct{} func (o callOriginal) Invocations(bin string) []string { - binPath, err := exec.LookPath(bin) + binPath, err := findExecutable(bin) if err != nil { panic(err) } @@ -317,6 +326,36 @@ func (o callOriginal) Invocations(bin string) []string { } } +func findExecutable(bin string) (string, error) { + goroot := runtime.GOROOT() + binPath := filepath.Join(goroot, "bin", bin) + if runtime.GOOS == "windows" { + binPath = binPath + ".exe" + } + if err := checkExecutable(binPath); err != nil { + binPath, err = exec.LookPath(bin) + if err != nil { + return "", err + } + } + return binPath, nil +} + +func checkExecutable(file string) error { + d, err := os.Stat(file) + if err != nil { + return err + } + m := d.Mode() + if m.IsDir() { + return syscall.EISDIR + } + if m&0111 != 0 { + return nil + } + return fs.ErrPermission +} + func mockBinary(name string, responses ...response) scriptlet { return fnScriptlet(func(t TestingT) string { code := make([]string, 0, len(responses)*10) @@ -464,12 +503,13 @@ func (s shellScript) run(t TestingT, commands []string) (int, string, string, st } func (s shellScript) source(t TestingT, commands []string) string { + goroot := runtime.GOROOT() source := fmt.Sprintf(` set -Eeuo pipefail export TMPPATH='%s' -export PATH="${TMPPATH}:${PATH}" +export PATH="${TMPPATH}:%s:${PATH}" export KNATIVE_HACK_SCRIPT_MANUAL_VERBOSE=true -`, t.TempDir()) +`, t.TempDir(), fmt.Sprintf("%s/bin", goroot)) bashShebang := "#!/usr/bin/env bash\n" for _, sclet := range s.scriptlets { source += "\n" + strings.TrimPrefix(sclet.scriptlet(t), bashShebang) + "\n" @@ -512,24 +552,22 @@ func (f fnPrefetcher) prefetch(t TestingT) { // and compilation messages, which go prints will not influence the test. func goRunHelpPrefetcher(tool string) prefetcher { return fnPrefetcher(func(t TestingT) { - c := exec.Command("go", "run", tool, "--help") - var ( - stdout, stderr io.ReadCloser - err error - ) - stdout, err = c.StdoutPipe() - require.NoError(t, err) - stderr, err = c.StderrPipe() + stdout := bytes.NewBuffer(make([]byte, 0, 1024)) + stderr := bytes.NewBuffer(make([]byte, 0, 1024)) + gobin, err := findExecutable("go") require.NoError(t, err) + c := exec.Command(gobin, "run", tool, "--help") + c.Env = append(os.Environ(), "GOTOOLCHAIN=auto") + c.Stdout = stdout + c.Stderr = stderr err = c.Run() if err != nil { - stdBytes, merr := io.ReadAll(stdout) - require.NoError(t, merr) - errBytes, rerr := io.ReadAll(stderr) - require.NoError(t, rerr) + errBytes := stderr.Bytes() + stdBytes := stdout.Bytes() require.NoError(t, err, - "------\nSTDOUT\n------", string(stdBytes), - "------\nSTDERR\n------", string(errBytes)) + "───── BEGIN STDOUT ─────\n%s\n────── END STDOUT ──────\n"+ + "───── BEGIN STDERR ─────\n%s\n────── END STDERR ──────", + string(stdBytes), string(errBytes)) } }) } diff --git a/test/unit/update_deps_test.go b/test/unit/update_deps_test.go index 85159236..6748c01b 100644 --- a/test/unit/update_deps_test.go +++ b/test/unit/update_deps_test.go @@ -46,8 +46,8 @@ func TestUpdateDeps(t *testing.T) { "--module-release 0.28"), }, }} - for i := range tcs { - tc := tcs[i] + for _, tc := range tcs { + tc := tc t.Run(tc.name, tc.test(sc)) } }