Source file
src/cmd/pack/pack_test.go
1
2
3
4
5 package main
6
7 import (
8 "bufio"
9 "bytes"
10 "cmd/internal/archive"
11 "fmt"
12 "internal/testenv"
13 "io"
14 "io/fs"
15 "os"
16 "os/exec"
17 "path/filepath"
18 "testing"
19 "time"
20 )
21
22
23 func testCreate(t *testing.T, dir string) {
24 name := filepath.Join(dir, "pack.a")
25 ar := openArchive(name, os.O_RDWR|os.O_CREATE, nil)
26
27 ar.addFile(helloFile.Reset())
28 ar.a.File().Close()
29
30 ar = openArchive(name, os.O_RDONLY, []string{helloFile.name})
31 var buf bytes.Buffer
32 stdout = &buf
33 verbose = true
34 defer func() {
35 stdout = os.Stdout
36 verbose = false
37 }()
38 ar.scan(ar.printContents)
39 ar.a.File().Close()
40 result := buf.String()
41
42 expect := fmt.Sprintf("%s\n%s", helloFile.name, helloFile.contents)
43 if result != expect {
44 t.Fatalf("expected %q got %q", expect, result)
45 }
46 }
47
48
49
50 func TestCreate(t *testing.T) {
51 dir := t.TempDir()
52 testCreate(t, dir)
53 }
54
55
56 func TestCreateTwice(t *testing.T) {
57 dir := t.TempDir()
58 testCreate(t, dir)
59 testCreate(t, dir)
60 }
61
62
63
64 func TestTableOfContents(t *testing.T) {
65 dir := t.TempDir()
66 name := filepath.Join(dir, "pack.a")
67 ar := openArchive(name, os.O_RDWR|os.O_CREATE, nil)
68
69
70 ar.addFile(helloFile.Reset())
71 ar.addFile(goodbyeFile.Reset())
72 ar.a.File().Close()
73
74
75 var buf bytes.Buffer
76 stdout = &buf
77 verbose = true
78 defer func() {
79 stdout = os.Stdout
80 verbose = false
81 }()
82 ar = openArchive(name, os.O_RDONLY, nil)
83 ar.scan(ar.tableOfContents)
84 ar.a.File().Close()
85 result := buf.String()
86
87 expect := fmt.Sprintf("%s\n%s\n", helloFile.Entry(), goodbyeFile.Entry())
88 if result != expect {
89 t.Fatalf("expected %q got %q", expect, result)
90 }
91
92
93 verbose = false
94 buf.Reset()
95 ar = openArchive(name, os.O_RDONLY, nil)
96 ar.scan(ar.tableOfContents)
97 ar.a.File().Close()
98 result = buf.String()
99
100 expect = fmt.Sprintf("%s\n%s\n", helloFile.name, goodbyeFile.name)
101 if result != expect {
102 t.Fatalf("expected %q got %q", expect, result)
103 }
104
105
106 verbose = false
107 buf.Reset()
108 ar = openArchive(name, os.O_RDONLY, []string{helloFile.name})
109 ar.scan(ar.tableOfContents)
110 ar.a.File().Close()
111 result = buf.String()
112
113 expect = fmt.Sprintf("%s\n", helloFile.name)
114 if result != expect {
115 t.Fatalf("expected %q got %q", expect, result)
116 }
117 }
118
119
120
121 func TestExtract(t *testing.T) {
122 dir := t.TempDir()
123 name := filepath.Join(dir, "pack.a")
124 ar := openArchive(name, os.O_RDWR|os.O_CREATE, nil)
125
126 ar.addFile(helloFile.Reset())
127 ar.addFile(goodbyeFile.Reset())
128 ar.a.File().Close()
129
130 pwd, err := os.Getwd()
131 if err != nil {
132 t.Fatal("os.Getwd: ", err)
133 }
134 err = os.Chdir(dir)
135 if err != nil {
136 t.Fatal("os.Chdir: ", err)
137 }
138 defer func() {
139 err := os.Chdir(pwd)
140 if err != nil {
141 t.Fatal("os.Chdir: ", err)
142 }
143 }()
144 ar = openArchive(name, os.O_RDONLY, []string{goodbyeFile.name})
145 ar.scan(ar.extractContents)
146 ar.a.File().Close()
147 data, err := os.ReadFile(goodbyeFile.name)
148 if err != nil {
149 t.Fatal(err)
150 }
151
152 result := string(data)
153 expect := goodbyeFile.contents
154 if result != expect {
155 t.Fatalf("expected %q got %q", expect, result)
156 }
157 }
158
159
160 func TestHello(t *testing.T) {
161 testenv.MustHaveGoBuild(t)
162
163 dir := t.TempDir()
164 hello := filepath.Join(dir, "hello.go")
165 prog := `
166 package main
167 func main() {
168 println("hello world")
169 }
170 `
171 err := os.WriteFile(hello, []byte(prog), 0666)
172 if err != nil {
173 t.Fatal(err)
174 }
175
176 run := func(args ...string) string {
177 return doRun(t, dir, args...)
178 }
179
180 goBin := testenv.GoToolPath(t)
181 run(goBin, "build", "cmd/pack")
182 run(goBin, "tool", "compile", "hello.go")
183 run("./pack", "grc", "hello.a", "hello.o")
184 run(goBin, "tool", "link", "-o", "a.out", "hello.a")
185 out := run("./a.out")
186 if out != "hello world\n" {
187 t.Fatalf("incorrect output: %q, want %q", out, "hello world\n")
188 }
189 }
190
191
192 func TestLargeDefs(t *testing.T) {
193 if testing.Short() {
194 t.Skip("skipping in -short mode")
195 }
196 testenv.MustHaveGoBuild(t)
197
198 dir := t.TempDir()
199 large := filepath.Join(dir, "large.go")
200 f, err := os.Create(large)
201 if err != nil {
202 t.Fatal(err)
203 }
204 b := bufio.NewWriter(f)
205
206 printf := func(format string, args ...any) {
207 _, err := fmt.Fprintf(b, format, args...)
208 if err != nil {
209 t.Fatalf("Writing to %s: %v", large, err)
210 }
211 }
212
213 printf("package large\n\ntype T struct {\n")
214 for i := 0; i < 1000; i++ {
215 printf("f%d int `tag:\"", i)
216 for j := 0; j < 100; j++ {
217 printf("t%d=%d,", j, j)
218 }
219 printf("\"`\n")
220 }
221 printf("}\n")
222 if err = b.Flush(); err != nil {
223 t.Fatal(err)
224 }
225 if err = f.Close(); err != nil {
226 t.Fatal(err)
227 }
228
229 main := filepath.Join(dir, "main.go")
230 prog := `
231 package main
232 import "large"
233 var V large.T
234 func main() {
235 println("ok")
236 }
237 `
238 err = os.WriteFile(main, []byte(prog), 0666)
239 if err != nil {
240 t.Fatal(err)
241 }
242
243 run := func(args ...string) string {
244 return doRun(t, dir, args...)
245 }
246
247 goBin := testenv.GoToolPath(t)
248 run(goBin, "build", "cmd/pack")
249 run(goBin, "tool", "compile", "large.go")
250 run("./pack", "grc", "large.a", "large.o")
251 run(goBin, "tool", "compile", "-I", ".", "main.go")
252 run(goBin, "tool", "link", "-L", ".", "-o", "a.out", "main.o")
253 out := run("./a.out")
254 if out != "ok\n" {
255 t.Fatalf("incorrect output: %q, want %q", out, "ok\n")
256 }
257 }
258
259
260
261 func TestIssue21703(t *testing.T) {
262 testenv.MustHaveGoBuild(t)
263
264 dir := t.TempDir()
265
266 const aSrc = `package a; const X = "\n!\n"`
267 err := os.WriteFile(filepath.Join(dir, "a.go"), []byte(aSrc), 0666)
268 if err != nil {
269 t.Fatal(err)
270 }
271
272 const bSrc = `package b; import _ "a"`
273 err = os.WriteFile(filepath.Join(dir, "b.go"), []byte(bSrc), 0666)
274 if err != nil {
275 t.Fatal(err)
276 }
277
278 run := func(args ...string) string {
279 return doRun(t, dir, args...)
280 }
281
282 goBin := testenv.GoToolPath(t)
283 run(goBin, "build", "cmd/pack")
284 run(goBin, "tool", "compile", "a.go")
285 run("./pack", "c", "a.a", "a.o")
286 run(goBin, "tool", "compile", "-I", ".", "b.go")
287 }
288
289
290
291 func TestCreateWithCompilerObj(t *testing.T) {
292 testenv.MustHaveGoBuild(t)
293
294 dir := t.TempDir()
295 src := filepath.Join(dir, "p.go")
296 prog := "package p; var X = 42\n"
297 err := os.WriteFile(src, []byte(prog), 0666)
298 if err != nil {
299 t.Fatal(err)
300 }
301
302 run := func(args ...string) string {
303 return doRun(t, dir, args...)
304 }
305
306 goBin := testenv.GoToolPath(t)
307 run(goBin, "build", "cmd/pack")
308 run(goBin, "tool", "compile", "-pack", "-o", "p.a", "p.go")
309 run("./pack", "c", "packed.a", "p.a")
310 fi, err := os.Stat(filepath.Join(dir, "p.a"))
311 if err != nil {
312 t.Fatalf("stat p.a failed: %v", err)
313 }
314 fi2, err := os.Stat(filepath.Join(dir, "packed.a"))
315 if err != nil {
316 t.Fatalf("stat packed.a failed: %v", err)
317 }
318
319
320
321 if want, got := fi.Size(), fi2.Size(); want != got {
322 t.Errorf("packed file with different size: want %d, got %d", want, got)
323 }
324
325
326 run(goBin, "tool", "compile", "-linkobj", "p2.a", "-o", "p.x", "p.go")
327 run("./pack", "c", "packed2.a", "p2.a")
328 fi, err = os.Stat(filepath.Join(dir, "p2.a"))
329 if err != nil {
330 t.Fatalf("stat p2.a failed: %v", err)
331 }
332 fi2, err = os.Stat(filepath.Join(dir, "packed2.a"))
333 if err != nil {
334 t.Fatalf("stat packed2.a failed: %v", err)
335 }
336 if want, got := fi.Size(), fi2.Size(); want != got {
337 t.Errorf("packed file with different size: want %d, got %d", want, got)
338 }
339
340 run("./pack", "c", "packed3.a", "p.x")
341 fi, err = os.Stat(filepath.Join(dir, "p.x"))
342 if err != nil {
343 t.Fatalf("stat p.x failed: %v", err)
344 }
345 fi2, err = os.Stat(filepath.Join(dir, "packed3.a"))
346 if err != nil {
347 t.Fatalf("stat packed3.a failed: %v", err)
348 }
349 if want, got := fi.Size(), fi2.Size(); want != got {
350 t.Errorf("packed file with different size: want %d, got %d", want, got)
351 }
352 }
353
354
355 func TestRWithNonexistentFile(t *testing.T) {
356 testenv.MustHaveGoBuild(t)
357
358 dir := t.TempDir()
359 src := filepath.Join(dir, "p.go")
360 prog := "package p; var X = 42\n"
361 err := os.WriteFile(src, []byte(prog), 0666)
362 if err != nil {
363 t.Fatal(err)
364 }
365
366 run := func(args ...string) string {
367 return doRun(t, dir, args...)
368 }
369
370 goBin := testenv.GoToolPath(t)
371 run(goBin, "build", "cmd/pack")
372 run(goBin, "tool", "compile", "-o", "p.o", "p.go")
373 run("./pack", "r", "p.a", "p.o")
374 }
375
376
377 func doRun(t *testing.T, dir string, args ...string) string {
378 cmd := exec.Command(args[0], args[1:]...)
379 cmd.Dir = dir
380 out, err := cmd.CombinedOutput()
381 if err != nil {
382 t.Fatalf("%v: %v\n%s", args, err, string(out))
383 }
384 return string(out)
385 }
386
387
388
389 var helloFile = &FakeFile{
390 name: "hello",
391 contents: "hello world",
392 mode: 0644,
393 }
394
395 var goodbyeFile = &FakeFile{
396 name: "goodbye",
397 contents: "Sayonara, Jim",
398 mode: 0644,
399 }
400
401
402 type FakeFile struct {
403 name string
404 contents string
405 mode fs.FileMode
406 offset int
407 }
408
409
410 func (f *FakeFile) Reset() *FakeFile {
411 f.offset = 0
412 return f
413 }
414
415
416
417 func (f *FakeFile) Name() string {
418
419 return f.name
420 }
421
422 func (f *FakeFile) Stat() (fs.FileInfo, error) {
423 return f, nil
424 }
425
426 func (f *FakeFile) Read(p []byte) (int, error) {
427 if f.offset >= len(f.contents) {
428 return 0, io.EOF
429 }
430 n := copy(p, f.contents[f.offset:])
431 f.offset += n
432 return n, nil
433 }
434
435 func (f *FakeFile) Close() error {
436 return nil
437 }
438
439
440
441 func (f *FakeFile) Size() int64 {
442 return int64(len(f.contents))
443 }
444
445 func (f *FakeFile) Mode() fs.FileMode {
446 return f.mode
447 }
448
449 func (f *FakeFile) ModTime() time.Time {
450 return time.Time{}
451 }
452
453 func (f *FakeFile) IsDir() bool {
454 return false
455 }
456
457 func (f *FakeFile) Sys() any {
458 return nil
459 }
460
461
462
463 func (f *FakeFile) Entry() *archive.Entry {
464 return &archive.Entry{
465 Name: f.name,
466 Mtime: 0,
467 Uid: 0,
468 Gid: 0,
469 Mode: f.mode,
470 Data: archive.Data{Size: int64(len(f.contents))},
471 }
472 }
473
View as plain text