Source file
src/cmd/go/scriptconds_test.go
1
2
3
4
5 package main_test
6
7 import (
8 "cmd/go/internal/cfg"
9 "cmd/internal/script"
10 "cmd/internal/script/scripttest"
11 "errors"
12 "fmt"
13 "internal/testenv"
14 "os"
15 "os/exec"
16 "path/filepath"
17 "runtime"
18 "runtime/debug"
19 "sync"
20 "testing"
21 )
22
23 func scriptConditions(t *testing.T) map[string]script.Cond {
24 conds := scripttest.DefaultConds()
25
26 scripttest.AddToolChainScriptConditions(t, conds, goHostOS, goHostArch)
27
28 add := func(name string, cond script.Cond) {
29 if _, ok := conds[name]; ok {
30 panic(fmt.Sprintf("condition %q is already registered", name))
31 }
32 conds[name] = cond
33 }
34
35 lazyBool := func(summary string, f func() bool) script.Cond {
36 return script.OnceCondition(summary, func() (bool, error) { return f(), nil })
37 }
38
39 add("abscc", script.Condition("default $CC path is absolute and exists", defaultCCIsAbsolute))
40 add("case-sensitive", script.OnceCondition("$WORK filesystem is case-sensitive", isCaseSensitive))
41 add("cc", script.PrefixCondition("go env CC = <suffix> (ignoring the go/env file)", ccIs))
42 add("git", lazyBool("the 'git' executable exists and provides the standard CLI", hasWorkingGit))
43 add("net", script.PrefixCondition("can connect to external network host <suffix>", hasNet))
44 add("trimpath", script.OnceCondition("test binary was built with -trimpath", isTrimpath))
45
46 return conds
47 }
48
49 func defaultCCIsAbsolute(s *script.State) (bool, error) {
50 GOOS, _ := s.LookupEnv("GOOS")
51 GOARCH, _ := s.LookupEnv("GOARCH")
52 defaultCC := cfg.DefaultCC(GOOS, GOARCH)
53 if filepath.IsAbs(defaultCC) {
54 if _, err := exec.LookPath(defaultCC); err == nil {
55 return true, nil
56 }
57 }
58 return false, nil
59 }
60
61 func ccIs(s *script.State, want string) (bool, error) {
62 CC, _ := s.LookupEnv("CC")
63 if CC != "" {
64 return CC == want, nil
65 }
66 GOOS, _ := s.LookupEnv("GOOS")
67 GOARCH, _ := s.LookupEnv("GOARCH")
68 return cfg.DefaultCC(GOOS, GOARCH) == want, nil
69 }
70
71 var scriptNetEnabled sync.Map
72
73 func hasNet(s *script.State, host string) (bool, error) {
74 if !testenv.HasExternalNetwork() {
75 return false, nil
76 }
77
78
79
80
81 t, ok := tbFromContext(s.Context())
82 if !ok {
83 return false, errors.New("script Context unexpectedly missing testing.TB key")
84 }
85
86 if netTestSem != nil {
87
88
89
90 _, dup := scriptNetEnabled.LoadOrStore(t, true)
91 if !dup {
92
93 netTestSem <- struct{}{}
94 t.Cleanup(func() {
95 <-netTestSem
96 scriptNetEnabled.Delete(t)
97 })
98 }
99 }
100
101
102
103 s.Setenv("TESTGONETWORK", "")
104 return true, nil
105 }
106
107 func isCaseSensitive() (bool, error) {
108 tmpdir, err := os.MkdirTemp(testTmpDir, "case-sensitive")
109 if err != nil {
110 return false, fmt.Errorf("failed to create directory to determine case-sensitivity: %w", err)
111 }
112 defer os.RemoveAll(tmpdir)
113
114 fcap := filepath.Join(tmpdir, "FILE")
115 if err := os.WriteFile(fcap, []byte{}, 0644); err != nil {
116 return false, fmt.Errorf("error writing file to determine case-sensitivity: %w", err)
117 }
118
119 flow := filepath.Join(tmpdir, "file")
120 _, err = os.ReadFile(flow)
121 switch {
122 case err == nil:
123 return false, nil
124 case os.IsNotExist(err):
125 return true, nil
126 default:
127 return false, fmt.Errorf("unexpected error reading file when determining case-sensitivity: %w", err)
128 }
129 }
130
131 func isTrimpath() (bool, error) {
132 info, _ := debug.ReadBuildInfo()
133 if info == nil {
134 return false, errors.New("missing build info")
135 }
136
137 for _, s := range info.Settings {
138 if s.Key == "-trimpath" && s.Value == "true" {
139 return true, nil
140 }
141 }
142 return false, nil
143 }
144
145 func hasWorkingGit() bool {
146 if runtime.GOOS == "plan9" {
147
148
149 return false
150 }
151 _, err := exec.LookPath("git")
152 return err == nil
153 }
154
View as plain text