]> Cypherpunks repositories - gostls13.git/commitdiff
internal/testenv: in HasExec, try to actually exec on ios and wasm platforms
authorBryan C. Mills <bcmills@google.com>
Wed, 19 Apr 2023 14:46:26 +0000 (10:46 -0400)
committerGopher Robot <gobot@golang.org>
Sat, 22 Apr 2023 00:41:24 +0000 (00:41 +0000)
Some iOS environments may support exec. wasip1 and js do not, but
trying to exec on those platforms is inexpensive anyway and gives
better test coverage for the ios path.

Change-Id: I4baffb2ef5dc7d81e6a260f69033bfb229f13d92
Reviewed-on: https://go-review.googlesource.com/c/go/+/486275
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Bryan Mills <bcmills@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Auto-Submit: Bryan Mills <bcmills@google.com>

src/internal/testenv/exec.go

index ec2f2e295ce412af6f4b7e50b80c241cdc837350..948e0f29f8f831a64b725b2c51b9ea8ab7989ecd 100644 (file)
@@ -19,11 +19,65 @@ import (
 // HasExec reports whether the current system can start new processes
 // using os.StartProcess or (more commonly) exec.Command.
 func HasExec() bool {
+       tryExecOnce.Do(func() {
+               tryExecOk = tryExec()
+       })
+       return tryExecOk
+}
+
+var (
+       tryExec     = func() bool { return true }
+       tryExecOnce sync.Once
+       tryExecOk   bool
+)
+
+func init() {
        switch runtime.GOOS {
        case "wasip1", "js", "ios":
+       default:
+               // Assume that exec always works on non-mobile platforms and Android.
+               return
+       }
+
+       // ios has an exec syscall but on real iOS devices it might return a
+       // permission error. In an emulated environment (such as a Corellium host)
+       // it might succeed, so if we need to exec we'll just have to try it and
+       // find out.
+       //
+       // As of 2023-04-19 wasip1 and js don't have exec syscalls at all, but we
+       // may as well use the same path so that this branch can be tested without
+       // an ios environment.
+
+       if !testing.Testing() {
+               // This isn't a standard 'go test' binary, so we don't know how to
+               // self-exec in a way that should succeed without side effects.
+               // Just forget it.
+               tryExec = func() bool { return false }
+               return
+       }
+
+       // We know that this is a test executable.
+       // We should be able to run it with a no-op flag and the original test
+       // execution environment to check for overall exec support.
+
+       // Save the original environment during init for use in the check. A test
+       // binary may modify its environment before calling HasExec to change its
+       // behavior// (such as mimicking a command-line tool), and that modified
+       // environment might cause our self-test to behave unpredictably.
+       origEnv := os.Environ()
+
+       tryExec = func() bool {
+               exe, err := os.Executable()
+               if err != nil {
+                       return false
+               }
+               cmd := exec.Command(exe, "-test.list=^$")
+               cmd.Env = origEnv
+               if err := cmd.Run(); err == nil {
+                       tryExecOk = true
+               }
                return false
        }
-       return true
 }
 
 // MustHaveExec checks that the current system can start new processes