1
2
3
4
5 package work
6
7 import (
8 "fmt"
9 "internal/testenv"
10 "io/fs"
11 "os"
12 "path/filepath"
13 "reflect"
14 "runtime"
15 "strings"
16 "testing"
17
18 "cmd/go/internal/base"
19 "cmd/go/internal/cfg"
20 "cmd/go/internal/load"
21 )
22
23 func TestRemoveDevNull(t *testing.T) {
24 fi, err := os.Lstat(os.DevNull)
25 if err != nil {
26 t.Skip(err)
27 }
28 if fi.Mode().IsRegular() {
29 t.Errorf("Lstat(%s).Mode().IsRegular() = true; expected false", os.DevNull)
30 }
31 mayberemovefile(os.DevNull)
32 _, err = os.Lstat(os.DevNull)
33 if err != nil {
34 t.Errorf("mayberemovefile(%s) did remove it; oops", os.DevNull)
35 }
36 }
37
38 func TestSplitPkgConfigOutput(t *testing.T) {
39 for _, test := range []struct {
40 in []byte
41 want []string
42 }{
43 {[]byte(`-r:foo -L/usr/white\ space/lib -lfoo\ bar -lbar\ baz`), []string{"-r:foo", "-L/usr/white space/lib", "-lfoo bar", "-lbar baz"}},
44 {[]byte(`-lextra\ fun\ arg\\`), []string{`-lextra fun arg\`}},
45 {[]byte("\textra whitespace\r\n"), []string{"extra", "whitespace\r"}},
46 {[]byte(" \r\n "), []string{"\r"}},
47 {[]byte(`"-r:foo" "-L/usr/white space/lib" "-lfoo bar" "-lbar baz"`), []string{"-r:foo", "-L/usr/white space/lib", "-lfoo bar", "-lbar baz"}},
48 {[]byte(`"-lextra fun arg\\"`), []string{`-lextra fun arg\`}},
49 {[]byte(`" \r\n\ "`), []string{` \r\n\ `}},
50 {[]byte(`""`), []string{""}},
51 {[]byte(``), nil},
52 {[]byte(`"\\"`), []string{`\`}},
53 {[]byte(`"\x"`), []string{`\x`}},
54 {[]byte(`"\\x"`), []string{`\x`}},
55 {[]byte(`'\\'`), []string{`\\`}},
56 {[]byte(`'\x'`), []string{`\x`}},
57 {[]byte(`"\\x"`), []string{`\x`}},
58 {[]byte("\\\n"), nil},
59 {[]byte(`-fPIC -I/test/include/foo -DQUOTED='"/test/share/doc"'`), []string{"-fPIC", "-I/test/include/foo", `-DQUOTED="/test/share/doc"`}},
60 {[]byte(`-fPIC -I/test/include/foo -DQUOTED="/test/share/doc"`), []string{"-fPIC", "-I/test/include/foo", "-DQUOTED=/test/share/doc"}},
61 {[]byte(`-fPIC -I/test/include/foo -DQUOTED=\"/test/share/doc\"`), []string{"-fPIC", "-I/test/include/foo", `-DQUOTED="/test/share/doc"`}},
62 {[]byte(`-fPIC -I/test/include/foo -DQUOTED='/test/share/doc'`), []string{"-fPIC", "-I/test/include/foo", "-DQUOTED=/test/share/doc"}},
63 {[]byte(`-DQUOTED='/te\st/share/d\oc'`), []string{`-DQUOTED=/te\st/share/d\oc`}},
64 {[]byte(`-Dhello=10 -Dworld=+32 -DDEFINED_FROM_PKG_CONFIG=hello\ world`), []string{"-Dhello=10", "-Dworld=+32", "-DDEFINED_FROM_PKG_CONFIG=hello world"}},
65 {[]byte(`"broken\"" \\\a "a"`), []string{"broken\"", "\\a", "a"}},
66 } {
67 got, err := splitPkgConfigOutput(test.in)
68 if err != nil {
69 t.Errorf("splitPkgConfigOutput on %#q failed with error %v", test.in, err)
70 continue
71 }
72 if !reflect.DeepEqual(got, test.want) {
73 t.Errorf("splitPkgConfigOutput(%#q) = %#q; want %#q", test.in, got, test.want)
74 }
75 }
76
77 for _, test := range []struct {
78 in []byte
79 want []string
80 }{
81
82 {[]byte(`" \r\n `), nil},
83 {[]byte(`"-r:foo" "-L/usr/white space/lib "-lfoo bar" "-lbar baz"`), nil},
84 {[]byte(`"-lextra fun arg\\`), nil},
85
86 {[]byte(`broken flag\`), nil},
87 {[]byte(`extra broken flag \`), nil},
88 {[]byte(`\`), nil},
89 {[]byte(`"broken\"" "extra" \`), nil},
90 } {
91 got, err := splitPkgConfigOutput(test.in)
92 if err == nil {
93 t.Errorf("splitPkgConfigOutput(%v) = %v; haven't failed with error as expected.", test.in, got)
94 }
95 if !reflect.DeepEqual(got, test.want) {
96 t.Errorf("splitPkgConfigOutput(%v) = %v; want %v", test.in, got, test.want)
97 }
98 }
99
100 }
101
102 func TestSharedLibName(t *testing.T) {
103
104 prefix := "lib"
105 suffix := ".so"
106 testData := []struct {
107 args []string
108 pkgs []*load.Package
109 expected string
110 expectErr bool
111 rootedAt string
112 }{
113 {
114 args: []string{"std"},
115 pkgs: []*load.Package{},
116 expected: "std",
117 },
118 {
119 args: []string{"std", "cmd"},
120 pkgs: []*load.Package{},
121 expected: "std,cmd",
122 },
123 {
124 args: []string{},
125 pkgs: []*load.Package{pkgImportPath("gopkg.in/somelib")},
126 expected: "gopkg.in-somelib",
127 },
128 {
129 args: []string{"./..."},
130 pkgs: []*load.Package{pkgImportPath("somelib")},
131 expected: "somelib",
132 rootedAt: "somelib",
133 },
134 {
135 args: []string{"../somelib", "../somelib"},
136 pkgs: []*load.Package{pkgImportPath("somelib")},
137 expected: "somelib",
138 },
139 {
140 args: []string{"../lib1", "../lib2"},
141 pkgs: []*load.Package{pkgImportPath("gopkg.in/lib1"), pkgImportPath("gopkg.in/lib2")},
142 expected: "gopkg.in-lib1,gopkg.in-lib2",
143 },
144 {
145 args: []string{"./..."},
146 pkgs: []*load.Package{
147 pkgImportPath("gopkg.in/dir/lib1"),
148 pkgImportPath("gopkg.in/lib2"),
149 pkgImportPath("gopkg.in/lib3"),
150 },
151 expected: "gopkg.in",
152 rootedAt: "gopkg.in",
153 },
154 {
155 args: []string{"std", "../lib2"},
156 pkgs: []*load.Package{},
157 expectErr: true,
158 },
159 {
160 args: []string{"all", "./"},
161 pkgs: []*load.Package{},
162 expectErr: true,
163 },
164 {
165 args: []string{"cmd", "fmt"},
166 pkgs: []*load.Package{},
167 expectErr: true,
168 },
169 }
170 for _, data := range testData {
171 func() {
172 if data.rootedAt != "" {
173 tmpGopath, err := os.MkdirTemp("", "gopath")
174 if err != nil {
175 t.Fatal(err)
176 }
177 cwd := base.Cwd()
178 oldGopath := cfg.BuildContext.GOPATH
179 defer func() {
180 cfg.BuildContext.GOPATH = oldGopath
181 os.Chdir(cwd)
182 err := os.RemoveAll(tmpGopath)
183 if err != nil {
184 t.Error(err)
185 }
186 }()
187 root := filepath.Join(tmpGopath, "src", data.rootedAt)
188 err = os.MkdirAll(root, 0755)
189 if err != nil {
190 t.Fatal(err)
191 }
192 cfg.BuildContext.GOPATH = tmpGopath
193 os.Chdir(root)
194 }
195 computed, err := libname(data.args, data.pkgs)
196 if err != nil {
197 if !data.expectErr {
198 t.Errorf("libname returned an error %q, expected a name", err.Error())
199 }
200 } else if data.expectErr {
201 t.Errorf("libname returned %q, expected an error", computed)
202 } else {
203 expected := prefix + data.expected + suffix
204 if expected != computed {
205 t.Errorf("libname returned %q, expected %q", computed, expected)
206 }
207 }
208 }()
209 }
210 }
211
212 func pkgImportPath(pkgpath string) *load.Package {
213 return &load.Package{
214 PackagePublic: load.PackagePublic{
215 ImportPath: pkgpath,
216 },
217 }
218 }
219
220
221
222
223
224 func TestRespectSetgidDir(t *testing.T) {
225
226
227 cfg.BuildX = true
228 var cmdBuf strings.Builder
229 sh := NewShell("", func(a ...any) (int, error) {
230 return cmdBuf.WriteString(fmt.Sprint(a...))
231 })
232
233 setgiddir := t.TempDir()
234
235
236
237
238
239 err := os.Chown(setgiddir, os.Getuid(), os.Getgid())
240 if err != nil {
241 if testenv.SyscallIsNotSupported(err) {
242 t.Skip("skipping: chown is not supported on " + runtime.GOOS)
243 }
244 t.Fatal(err)
245 }
246
247
248 if err := os.Chmod(setgiddir, 0755|fs.ModeSetgid); err != nil {
249 if testenv.SyscallIsNotSupported(err) {
250 t.Skip("skipping: chmod is not supported on " + runtime.GOOS)
251 }
252 t.Fatal(err)
253 }
254 if fi, err := os.Stat(setgiddir); err != nil {
255 t.Fatal(err)
256 } else if fi.Mode()&fs.ModeSetgid == 0 {
257 t.Skip("skipping: Chmod ignored ModeSetgid on " + runtime.GOOS)
258 }
259
260 pkgfile, err := os.CreateTemp("", "pkgfile")
261 if err != nil {
262 t.Fatalf("os.CreateTemp(\"\", \"pkgfile\"): %v", err)
263 }
264 defer os.Remove(pkgfile.Name())
265 defer pkgfile.Close()
266
267 dirGIDFile := filepath.Join(setgiddir, "setgid")
268 if err := sh.moveOrCopyFile(dirGIDFile, pkgfile.Name(), 0666, true); err != nil {
269 t.Fatalf("moveOrCopyFile: %v", err)
270 }
271
272 got := strings.TrimSpace(cmdBuf.String())
273 want := sh.fmtCmd("", "cp %s %s", pkgfile.Name(), dirGIDFile)
274 if got != want {
275 t.Fatalf("moveOrCopyFile(%q, %q): want %q, got %q", dirGIDFile, pkgfile.Name(), want, got)
276 }
277 }
278
View as plain text