]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: skip bzr tests if 'bzr help' has non-zero exit code
authorDmitri Shuralyov <dmitshur@golang.org>
Wed, 5 Feb 2025 00:54:25 +0000 (19:54 -0500)
committerGopher Robot <gobot@golang.org>
Wed, 5 Feb 2025 17:23:15 +0000 (09:23 -0800)
It appears to be quite easy to end up with a broken 'bzr' installation.
For example, if bzr was installed via a system-wide package manager and
intends to work with a system-wide Python installation, it may break if
another 'python3' binary is added to PATH.

If something as simple as 'bzr help' fails to exit with zero code,
consider it broken and skip tests that require a working bzr binary
just like if the 'bzr' binary isn't present in PATH at all.

This makes these tests more robust and capable of producing useful
signal in more environments. Separately from this, we'll want to
restore a working bzr installation on the linux-arm64 builders, but
at least there's still one on linux-amd64 builders.

For #71563.
Fixes #71504.

Change-Id: Ia147196f12b90a0731ebbfab63b5de308212ed65
Cq-Include-Trybots: luci.golang.try:gotip-linux-arm64-longtest,gotip-linux-amd64-longtest
Reviewed-on: https://go-review.googlesource.com/c/go/+/646715
Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/cmd/go/internal/vcweb/script.go
src/cmd/go/internal/vcweb/vcstest/vcstest_test.go
src/cmd/go/scriptconds_test.go
src/cmd/go/testdata/script/README
src/cmd/go/testdata/script/version_buildvcs_bzr.txt
src/cmd/go/testdata/vcstest/bzr/hello.txt

index 1ba9c0aff4f36ac8447413b7c7ca8704a916a8a0..3342ab200c6faa9f9a9a3a454c18b3cc7b16c6a0 100644 (file)
@@ -32,6 +32,17 @@ import (
 func newScriptEngine() *script.Engine {
        conds := script.DefaultConds()
 
+       add := func(name string, cond script.Cond) {
+               if _, ok := conds[name]; ok {
+                       panic(fmt.Sprintf("condition %q is already registered", name))
+               }
+               conds[name] = cond
+       }
+       lazyBool := func(summary string, f func() bool) script.Cond {
+               return script.OnceCondition(summary, func() (bool, error) { return f(), nil })
+       }
+       add("bzr", lazyBool("the 'bzr' executable exists and provides the standard CLI", hasWorkingBzr))
+
        interrupt := func(cmd *exec.Cmd) error { return cmd.Process.Signal(os.Interrupt) }
        gracePeriod := 30 * time.Second // arbitrary
 
@@ -43,6 +54,7 @@ func newScriptEngine() *script.Engine {
        cmds["hg"] = script.Program("hg", interrupt, gracePeriod)
        cmds["handle"] = scriptHandle()
        cmds["modzip"] = scriptModzip()
+       cmds["skip"] = scriptSkip()
        cmds["svnadmin"] = script.Program("svnadmin", interrupt, gracePeriod)
        cmds["svn"] = script.Program("svn", interrupt, gracePeriod)
        cmds["unquote"] = scriptUnquote()
@@ -321,6 +333,34 @@ func scriptModzip() script.Cmd {
                })
 }
 
+func scriptSkip() script.Cmd {
+       return script.Command(
+               script.CmdUsage{
+                       Summary: "skip the current test",
+                       Args:    "[msg]",
+               },
+               func(_ *script.State, args ...string) (script.WaitFunc, error) {
+                       if len(args) > 1 {
+                               return nil, script.ErrUsage
+                       }
+                       if len(args) == 0 {
+                               return nil, SkipError{""}
+                       }
+                       return nil, SkipError{args[0]}
+               })
+}
+
+type SkipError struct {
+       Msg string
+}
+
+func (s SkipError) Error() string {
+       if s.Msg == "" {
+               return "skip"
+       }
+       return s.Msg
+}
+
 func scriptUnquote() script.Cmd {
        return script.Command(
                script.CmdUsage{
@@ -343,3 +383,14 @@ func scriptUnquote() script.Cmd {
                        return wait, nil
                })
 }
+
+func hasWorkingBzr() bool {
+       bzr, err := exec.LookPath("bzr")
+       if err != nil {
+               return false
+       }
+       // Check that 'bzr help' exits with code 0.
+       // See go.dev/issue/71504 for an example where 'bzr' exists in PATH but doesn't work.
+       err = exec.Command(bzr, "help").Run()
+       return err == nil
+}
index df707d529efff57420df7e50fea466ac8a32c919..67234ac20d462871700a138fb5be57fb6380ee11 100644 (file)
@@ -158,13 +158,13 @@ func TestScripts(t *testing.T) {
                                if notInstalled := (vcweb.ServerNotInstalledError{}); errors.As(err, &notInstalled) || errors.Is(err, exec.ErrNotFound) {
                                        t.Skip(err)
                                }
-
-                               // For issue #71504 ignore an error about
-                               // bzr not being able to find dependencies.
-                               if strings.Contains(buf.String(), "brz: ERROR: Couldn't import breezy and dependencies.") {
-                                       t.Skip("skipping test due to bzr installation problem")
+                               if skip := (vcweb.SkipError{}); errors.As(err, &skip) {
+                                       if skip.Msg == "" {
+                                               t.Skip("SKIP")
+                                       } else {
+                                               t.Skipf("SKIP: %v", skip.Msg)
+                                       }
                                }
-
                                t.Error(err)
                        }
                })
index 262214f6a96c76e7bfd174656bf35e4d74f3efca..af9691ad2a4aca40ae15fadf5a1e7b455c44c39f 100644 (file)
@@ -37,6 +37,7 @@ func scriptConditions(t *testing.T) map[string]script.Cond {
        }
 
        add("abscc", script.Condition("default $CC path is absolute and exists", defaultCCIsAbsolute))
+       add("bzr", lazyBool("the 'bzr' executable exists and provides the standard CLI", hasWorkingBzr))
        add("case-sensitive", script.OnceCondition("$WORK filesystem is case-sensitive", isCaseSensitive))
        add("cc", script.PrefixCondition("go env CC = <suffix> (ignoring the go/env file)", ccIs))
        add("git", lazyBool("the 'git' executable exists and provides the standard CLI", hasWorkingGit))
@@ -151,3 +152,14 @@ func hasWorkingGit() bool {
        _, err := exec.LookPath("git")
        return err == nil
 }
+
+func hasWorkingBzr() bool {
+       bzr, err := exec.LookPath("bzr")
+       if err != nil {
+               return false
+       }
+       // Check that 'bzr help' exits with code 0.
+       // See go.dev/issue/71504 for an example where 'bzr' exists in PATH but doesn't work.
+       err = exec.Command(bzr, "help").Run()
+       return err == nil
+}
index 8c95945ebe0761a7cb0613418e154b1dd0ef076d..7724bc10ec46f0abc5d453cacbf557720d3793d5 100644 (file)
@@ -377,6 +377,8 @@ The available conditions are:
        GOOS/GOARCH supports -asan
 [buildmode:*]
        go supports -buildmode=<suffix>
+[bzr]
+       the 'bzr' executable exists and provides the standard CLI
 [case-sensitive]
        $WORK filesystem is case-sensitive
 [cc:*]
index fc80f45677799ec538ef23c0b5e6c1af010f08b1..59796d1ffa8c2dbd9483ac5273bd16b07a04d4f0 100644 (file)
@@ -2,8 +2,8 @@
 # controlled with -buildvcs. This test focuses on Bazaar specifics.
 # The Git test covers common functionality.
 
-[!exec:bzr] skip
 [short] skip
+[!bzr] skip 'requires a working bzr client'
 env GOBIN=$WORK/gopath/bin
 env oldpath=$PATH
 env HOME=$WORK
index 59315852f736521fde53fa61203bbd3b9c4721d5..68465ec553bd556985f2fcbfdb1e6a598384e945 100644 (file)
@@ -1,3 +1,4 @@
+[!bzr] skip 'requires a working bzr client'
 handle bzr
 
 env BZR_EMAIL='Russ Cox <rsc@google.com>'