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