]> Cypherpunks.ru repositories - gostls13.git/blob - src/internal/testenv/testenv_test.go
internal/testenv: use cmd.Environ in CleanCmdEnv
[gostls13.git] / src / internal / testenv / testenv_test.go
1 // Copyright 2022 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package testenv_test
6
7 import (
8         "internal/platform"
9         "internal/testenv"
10         "os"
11         "path/filepath"
12         "runtime"
13         "strings"
14         "testing"
15 )
16
17 func TestGoToolLocation(t *testing.T) {
18         testenv.MustHaveGoBuild(t)
19
20         var exeSuffix string
21         if runtime.GOOS == "windows" {
22                 exeSuffix = ".exe"
23         }
24
25         // Tests are defined to run within their package source directory,
26         // and this package's source directory is $GOROOT/src/internal/testenv.
27         // The 'go' command is installed at $GOROOT/bin/go, so if the environment
28         // is correct then testenv.GoTool() should be identical to ../../../bin/go.
29
30         relWant := "../../../bin/go" + exeSuffix
31         absWant, err := filepath.Abs(relWant)
32         if err != nil {
33                 t.Fatal(err)
34         }
35
36         wantInfo, err := os.Stat(absWant)
37         if err != nil {
38                 t.Fatal(err)
39         }
40         t.Logf("found go tool at %q (%q)", relWant, absWant)
41
42         goTool, err := testenv.GoTool()
43         if err != nil {
44                 t.Fatalf("testenv.GoTool(): %v", err)
45         }
46         t.Logf("testenv.GoTool() = %q", goTool)
47
48         gotInfo, err := os.Stat(goTool)
49         if err != nil {
50                 t.Fatal(err)
51         }
52         if !os.SameFile(wantInfo, gotInfo) {
53                 t.Fatalf("%q is not the same file as %q", absWant, goTool)
54         }
55 }
56
57 func TestHasGoBuild(t *testing.T) {
58         if !testenv.HasGoBuild() {
59                 switch runtime.GOOS {
60                 case "js", "wasip1":
61                         // No exec syscall, so these shouldn't be able to 'go build'.
62                         t.Logf("HasGoBuild is false on %s", runtime.GOOS)
63                         return
64                 }
65
66                 b := testenv.Builder()
67                 if b == "" {
68                         // We shouldn't make assumptions about what kind of sandbox or build
69                         // environment external Go users may be running in.
70                         t.Skipf("skipping: 'go build' unavailable")
71                 }
72
73                 // Since we control the Go builders, we know which ones ought
74                 // to be able to run 'go build'. Check that they can.
75                 //
76                 // (Note that we don't verify that any builders *can't* run 'go build'.
77                 // If a builder starts running 'go build' tests when it shouldn't,
78                 // we will presumably find out about it when those tests fail.)
79                 switch runtime.GOOS {
80                 case "ios":
81                         if strings.HasSuffix(b, "-corellium") {
82                                 // The corellium environment is self-hosting, so it should be able
83                                 // to build even though real "ios" devices can't exec.
84                         } else {
85                                 // The usual iOS sandbox does not allow the app to start another
86                                 // process. If we add builders on stock iOS devices, they presumably
87                                 // will not be able to exec, so we may as well allow that now.
88                                 t.Logf("HasGoBuild is false on %s", b)
89                                 return
90                         }
91                 case "android":
92                         if strings.HasSuffix(b, "-emu") && platform.MustLinkExternal(runtime.GOOS, runtime.GOARCH, false) {
93                                 // As of 2023-05-02, the test environment on the emulated builders is
94                                 // missing a C linker.
95                                 t.Logf("HasGoBuild is false on %s", b)
96                                 return
97                         }
98                 }
99
100                 if strings.HasSuffix(b, "-noopt") {
101                         // The -noopt builder sets GO_GCFLAGS, which causes tests of 'go build' to
102                         // be skipped.
103                         t.Logf("HasGoBuild is false on %s", b)
104                         return
105                 }
106
107                 t.Fatalf("HasGoBuild unexpectedly false on %s", b)
108         }
109
110         t.Logf("HasGoBuild is true; checking consistency with other functions")
111
112         hasExec := false
113         hasExecGo := false
114         t.Run("MustHaveExec", func(t *testing.T) {
115                 testenv.MustHaveExec(t)
116                 hasExec = true
117         })
118         t.Run("MustHaveExecPath", func(t *testing.T) {
119                 testenv.MustHaveExecPath(t, "go")
120                 hasExecGo = true
121         })
122         if !hasExec {
123                 t.Errorf(`MustHaveExec(t) skipped unexpectedly`)
124         }
125         if !hasExecGo {
126                 t.Errorf(`MustHaveExecPath(t, "go") skipped unexpectedly`)
127         }
128
129         dir := t.TempDir()
130         mainGo := filepath.Join(dir, "main.go")
131         if err := os.WriteFile(mainGo, []byte("package main\nfunc main() {}\n"), 0644); err != nil {
132                 t.Fatal(err)
133         }
134         cmd := testenv.Command(t, "go", "build", "-o", os.DevNull, mainGo)
135         out, err := cmd.CombinedOutput()
136         if err != nil {
137                 t.Fatalf("%v: %v\n%s", cmd, err, out)
138         }
139 }
140
141 func TestMustHaveExec(t *testing.T) {
142         hasExec := false
143         t.Run("MustHaveExec", func(t *testing.T) {
144                 testenv.MustHaveExec(t)
145                 t.Logf("MustHaveExec did not skip")
146                 hasExec = true
147         })
148
149         switch runtime.GOOS {
150         case "js", "wasip1":
151                 if hasExec {
152                         // js and wasip1 lack an “exec” syscall.
153                         t.Errorf("expected MustHaveExec to skip on %v", runtime.GOOS)
154                 }
155         case "ios":
156                 if b := testenv.Builder(); strings.HasSuffix(b, "-corellium") && !hasExec {
157                         // Most ios environments can't exec, but the corellium builder can.
158                         t.Errorf("expected MustHaveExec not to skip on %v", b)
159                 }
160         default:
161                 if b := testenv.Builder(); b != "" && !hasExec {
162                         t.Errorf("expected MustHaveExec not to skip on %v", b)
163                 }
164         }
165 }
166
167 func TestCleanCmdEnvPWD(t *testing.T) {
168         // Test that CleanCmdEnv sets PWD if cmd.Dir is set.
169         switch runtime.GOOS {
170         case "plan9", "windows":
171                 t.Skipf("PWD is not used on %s", runtime.GOOS)
172         }
173         dir := t.TempDir()
174         cmd := testenv.Command(t, testenv.GoToolPath(t), "help")
175         cmd.Dir = dir
176         cmd = testenv.CleanCmdEnv(cmd)
177
178         for _, env := range cmd.Env {
179                 if strings.HasPrefix(env, "PWD=") {
180                         pwd := strings.TrimPrefix(env, "PWD=")
181                         if pwd != dir {
182                                 t.Errorf("unexpected PWD: want %s, got %s", dir, pwd)
183                         }
184                         return
185                 }
186         }
187         t.Error("PWD not set in cmd.Env")
188 }