| | |
| | |
| | |
| |
|
| | package main |
| |
|
| | import ( |
| | "bufio" |
| | "cmd/internal/archive" |
| | "fmt" |
| | "internal/testenv" |
| | "io" |
| | "io/fs" |
| | "os" |
| | "path/filepath" |
| | "runtime" |
| | "strings" |
| | "testing" |
| | "time" |
| | ) |
| |
|
| | |
| | |
| | func TestMain(m *testing.M) { |
| | if os.Getenv("GO_PACKTEST_IS_PACK") != "" { |
| | main() |
| | os.Exit(0) |
| | } |
| |
|
| | os.Setenv("GO_PACKTEST_IS_PACK", "1") |
| | os.Exit(m.Run()) |
| | } |
| |
|
| | |
| | func packPath(t testing.TB) string { |
| | return testenv.Executable(t) |
| | } |
| |
|
| | |
| | func testCreate(t *testing.T, dir string) { |
| | name := filepath.Join(dir, "pack.a") |
| | ar := openArchive(name, os.O_RDWR|os.O_CREATE, nil) |
| | |
| | ar.addFile(helloFile.Reset()) |
| | ar.a.File().Close() |
| | |
| | ar = openArchive(name, os.O_RDONLY, []string{helloFile.name}) |
| | var buf strings.Builder |
| | stdout = &buf |
| | verbose = true |
| | defer func() { |
| | stdout = os.Stdout |
| | verbose = false |
| | }() |
| | ar.scan(ar.printContents) |
| | ar.a.File().Close() |
| | result := buf.String() |
| | |
| | expect := fmt.Sprintf("%s\n%s", helloFile.name, helloFile.contents) |
| | if result != expect { |
| | t.Fatalf("expected %q got %q", expect, result) |
| | } |
| | } |
| |
|
| | |
| | |
| | func TestCreate(t *testing.T) { |
| | dir := t.TempDir() |
| | testCreate(t, dir) |
| | } |
| |
|
| | |
| | func TestCreateTwice(t *testing.T) { |
| | dir := t.TempDir() |
| | testCreate(t, dir) |
| | testCreate(t, dir) |
| | } |
| |
|
| | |
| | |
| | func TestTableOfContents(t *testing.T) { |
| | dir := t.TempDir() |
| | name := filepath.Join(dir, "pack.a") |
| | ar := openArchive(name, os.O_RDWR|os.O_CREATE, nil) |
| |
|
| | |
| | ar.addFile(helloFile.Reset()) |
| | ar.addFile(goodbyeFile.Reset()) |
| | ar.a.File().Close() |
| |
|
| | |
| | var buf strings.Builder |
| | stdout = &buf |
| | verbose = true |
| | defer func() { |
| | stdout = os.Stdout |
| | verbose = false |
| | }() |
| | ar = openArchive(name, os.O_RDONLY, nil) |
| | ar.scan(ar.tableOfContents) |
| | ar.a.File().Close() |
| | result := buf.String() |
| | |
| | expect := fmt.Sprintf("%s\n%s\n", helloFile.Entry(), goodbyeFile.Entry()) |
| | if result != expect { |
| | t.Fatalf("expected %q got %q", expect, result) |
| | } |
| |
|
| | |
| | verbose = false |
| | buf.Reset() |
| | ar = openArchive(name, os.O_RDONLY, nil) |
| | ar.scan(ar.tableOfContents) |
| | ar.a.File().Close() |
| | result = buf.String() |
| | |
| | expect = fmt.Sprintf("%s\n%s\n", helloFile.name, goodbyeFile.name) |
| | if result != expect { |
| | t.Fatalf("expected %q got %q", expect, result) |
| | } |
| |
|
| | |
| | verbose = false |
| | buf.Reset() |
| | ar = openArchive(name, os.O_RDONLY, []string{helloFile.name}) |
| | ar.scan(ar.tableOfContents) |
| | ar.a.File().Close() |
| | result = buf.String() |
| | |
| | expect = fmt.Sprintf("%s\n", helloFile.name) |
| | if result != expect { |
| | t.Fatalf("expected %q got %q", expect, result) |
| | } |
| | } |
| |
|
| | |
| | |
| | func TestExtract(t *testing.T) { |
| | dir := t.TempDir() |
| | name := filepath.Join(dir, "pack.a") |
| | ar := openArchive(name, os.O_RDWR|os.O_CREATE, nil) |
| | |
| | ar.addFile(helloFile.Reset()) |
| | ar.addFile(goodbyeFile.Reset()) |
| | ar.a.File().Close() |
| | |
| | t.Chdir(dir) |
| | ar = openArchive(name, os.O_RDONLY, []string{goodbyeFile.name}) |
| | ar.scan(ar.extractContents) |
| | ar.a.File().Close() |
| | data, err := os.ReadFile(goodbyeFile.name) |
| | if err != nil { |
| | t.Fatal(err) |
| | } |
| | |
| | result := string(data) |
| | expect := goodbyeFile.contents |
| | if result != expect { |
| | t.Fatalf("expected %q got %q", expect, result) |
| | } |
| | } |
| |
|
| | |
| | func TestHello(t *testing.T) { |
| | testenv.MustHaveGoBuild(t) |
| | |
| | |
| | testenv.MustInternalLink(t, testenv.NoSpecialBuildTypes) |
| |
|
| | dir := t.TempDir() |
| | hello := filepath.Join(dir, "hello.go") |
| | prog := ` |
| | package main |
| | func main() { |
| | println("hello world") |
| | } |
| | ` |
| | err := os.WriteFile(hello, []byte(prog), 0666) |
| | if err != nil { |
| | t.Fatal(err) |
| | } |
| |
|
| | run := func(args ...string) string { |
| | return doRun(t, dir, args...) |
| | } |
| |
|
| | importcfgfile := filepath.Join(dir, "hello.importcfg") |
| | testenv.WriteImportcfg(t, importcfgfile, nil, hello) |
| |
|
| | goBin := testenv.GoToolPath(t) |
| | run(goBin, "tool", "compile", "-importcfg="+importcfgfile, "-p=main", "hello.go") |
| | run(packPath(t), "grc", "hello.a", "hello.o") |
| | run(goBin, "tool", "link", "-importcfg="+importcfgfile, "-o", "a.out", "hello.a") |
| | out := run("./a.out") |
| | if out != "hello world\n" { |
| | t.Fatalf("incorrect output: %q, want %q", out, "hello world\n") |
| | } |
| | } |
| |
|
| | |
| | func TestLargeDefs(t *testing.T) { |
| | if testing.Short() { |
| | t.Skip("skipping in -short mode") |
| | } |
| | testenv.MustHaveGoBuild(t) |
| |
|
| | dir := t.TempDir() |
| | large := filepath.Join(dir, "large.go") |
| | f, err := os.Create(large) |
| | if err != nil { |
| | t.Fatal(err) |
| | } |
| | b := bufio.NewWriter(f) |
| |
|
| | printf := func(format string, args ...any) { |
| | _, err := fmt.Fprintf(b, format, args...) |
| | if err != nil { |
| | t.Fatalf("Writing to %s: %v", large, err) |
| | } |
| | } |
| |
|
| | printf("package large\n\ntype T struct {\n") |
| | for i := 0; i < 1000; i++ { |
| | printf("f%d int `tag:\"", i) |
| | for j := 0; j < 100; j++ { |
| | printf("t%d=%d,", j, j) |
| | } |
| | printf("\"`\n") |
| | } |
| | printf("}\n") |
| | if err = b.Flush(); err != nil { |
| | t.Fatal(err) |
| | } |
| | if err = f.Close(); err != nil { |
| | t.Fatal(err) |
| | } |
| |
|
| | main := filepath.Join(dir, "main.go") |
| | prog := ` |
| | package main |
| | import "large" |
| | var V large.T |
| | func main() { |
| | println("ok") |
| | } |
| | ` |
| | err = os.WriteFile(main, []byte(prog), 0666) |
| | if err != nil { |
| | t.Fatal(err) |
| | } |
| |
|
| | run := func(args ...string) string { |
| | return doRun(t, dir, args...) |
| | } |
| |
|
| | importcfgfile := filepath.Join(dir, "hello.importcfg") |
| | testenv.WriteImportcfg(t, importcfgfile, nil) |
| |
|
| | goBin := testenv.GoToolPath(t) |
| | run(goBin, "tool", "compile", "-importcfg="+importcfgfile, "-p=large", "large.go") |
| | run(packPath(t), "grc", "large.a", "large.o") |
| | testenv.WriteImportcfg(t, importcfgfile, map[string]string{"large": filepath.Join(dir, "large.o")}, "runtime") |
| | run(goBin, "tool", "compile", "-importcfg="+importcfgfile, "-p=main", "main.go") |
| | run(goBin, "tool", "link", "-importcfg="+importcfgfile, "-L", ".", "-o", "a.out", "main.o") |
| | out := run("./a.out") |
| | if out != "ok\n" { |
| | t.Fatalf("incorrect output: %q, want %q", out, "ok\n") |
| | } |
| | } |
| |
|
| | |
| | |
| | func TestIssue21703(t *testing.T) { |
| | testenv.MustHaveGoBuild(t) |
| |
|
| | dir := t.TempDir() |
| |
|
| | const aSrc = `package a; const X = "\n!\n"` |
| | err := os.WriteFile(filepath.Join(dir, "a.go"), []byte(aSrc), 0666) |
| | if err != nil { |
| | t.Fatal(err) |
| | } |
| |
|
| | const bSrc = `package b; import _ "a"` |
| | err = os.WriteFile(filepath.Join(dir, "b.go"), []byte(bSrc), 0666) |
| | if err != nil { |
| | t.Fatal(err) |
| | } |
| |
|
| | run := func(args ...string) string { |
| | return doRun(t, dir, args...) |
| | } |
| |
|
| | goBin := testenv.GoToolPath(t) |
| | run(goBin, "tool", "compile", "-p=a", "a.go") |
| | run(packPath(t), "c", "a.a", "a.o") |
| | run(goBin, "tool", "compile", "-p=b", "-I", ".", "b.go") |
| | } |
| |
|
| | |
| | |
| | func TestCreateWithCompilerObj(t *testing.T) { |
| | testenv.MustHaveGoBuild(t) |
| |
|
| | dir := t.TempDir() |
| | src := filepath.Join(dir, "p.go") |
| | prog := "package p; var X = 42\n" |
| | err := os.WriteFile(src, []byte(prog), 0666) |
| | if err != nil { |
| | t.Fatal(err) |
| | } |
| |
|
| | run := func(args ...string) string { |
| | return doRun(t, dir, args...) |
| | } |
| |
|
| | goBin := testenv.GoToolPath(t) |
| | run(goBin, "tool", "compile", "-pack", "-p=p", "-o", "p.a", "p.go") |
| | run(packPath(t), "c", "packed.a", "p.a") |
| | fi, err := os.Stat(filepath.Join(dir, "p.a")) |
| | if err != nil { |
| | t.Fatalf("stat p.a failed: %v", err) |
| | } |
| | fi2, err := os.Stat(filepath.Join(dir, "packed.a")) |
| | if err != nil { |
| | t.Fatalf("stat packed.a failed: %v", err) |
| | } |
| | |
| | |
| | |
| | if want, got := fi.Size(), fi2.Size(); want != got { |
| | t.Errorf("packed file with different size: want %d, got %d", want, got) |
| | } |
| |
|
| | |
| | run(goBin, "tool", "compile", "-p=p", "-linkobj", "p2.a", "-o", "p.x", "p.go") |
| | run(packPath(t), "c", "packed2.a", "p2.a") |
| | fi, err = os.Stat(filepath.Join(dir, "p2.a")) |
| | if err != nil { |
| | t.Fatalf("stat p2.a failed: %v", err) |
| | } |
| | fi2, err = os.Stat(filepath.Join(dir, "packed2.a")) |
| | if err != nil { |
| | t.Fatalf("stat packed2.a failed: %v", err) |
| | } |
| | if want, got := fi.Size(), fi2.Size(); want != got { |
| | t.Errorf("packed file with different size: want %d, got %d", want, got) |
| | } |
| |
|
| | run(packPath(t), "c", "packed3.a", "p.x") |
| | fi, err = os.Stat(filepath.Join(dir, "p.x")) |
| | if err != nil { |
| | t.Fatalf("stat p.x failed: %v", err) |
| | } |
| | fi2, err = os.Stat(filepath.Join(dir, "packed3.a")) |
| | if err != nil { |
| | t.Fatalf("stat packed3.a failed: %v", err) |
| | } |
| | if want, got := fi.Size(), fi2.Size(); want != got { |
| | t.Errorf("packed file with different size: want %d, got %d", want, got) |
| | } |
| | } |
| |
|
| | |
| | func TestRWithNonexistentFile(t *testing.T) { |
| | testenv.MustHaveGoBuild(t) |
| |
|
| | dir := t.TempDir() |
| | src := filepath.Join(dir, "p.go") |
| | prog := "package p; var X = 42\n" |
| | err := os.WriteFile(src, []byte(prog), 0666) |
| | if err != nil { |
| | t.Fatal(err) |
| | } |
| |
|
| | run := func(args ...string) string { |
| | return doRun(t, dir, args...) |
| | } |
| |
|
| | goBin := testenv.GoToolPath(t) |
| | run(goBin, "tool", "compile", "-p=p", "-o", "p.o", "p.go") |
| | run(packPath(t), "r", "p.a", "p.o") |
| | } |
| |
|
| | |
| | func doRun(t *testing.T, dir string, args ...string) string { |
| | cmd := testenv.Command(t, args[0], args[1:]...) |
| | cmd.Dir = dir |
| | out, err := cmd.CombinedOutput() |
| | if err != nil { |
| | if t.Name() == "TestHello" && runtime.GOOS == "android" && runtime.GOARCH == "arm64" { |
| | testenv.SkipFlaky(t, 58806) |
| | } |
| | t.Fatalf("%v: %v\n%s", args, err, string(out)) |
| | } |
| | return string(out) |
| | } |
| |
|
| | |
| |
|
| | var helloFile = &FakeFile{ |
| | name: "hello", |
| | contents: "hello world", |
| | mode: 0644, |
| | } |
| |
|
| | var goodbyeFile = &FakeFile{ |
| | name: "goodbye", |
| | contents: "Sayonara, Jim", |
| | mode: 0644, |
| | } |
| |
|
| | |
| | type FakeFile struct { |
| | name string |
| | contents string |
| | mode fs.FileMode |
| | offset int |
| | } |
| |
|
| | |
| | func (f *FakeFile) Reset() *FakeFile { |
| | f.offset = 0 |
| | return f |
| | } |
| |
|
| | |
| |
|
| | func (f *FakeFile) Name() string { |
| | |
| | return f.name |
| | } |
| |
|
| | func (f *FakeFile) Stat() (fs.FileInfo, error) { |
| | return f, nil |
| | } |
| |
|
| | func (f *FakeFile) Read(p []byte) (int, error) { |
| | if f.offset >= len(f.contents) { |
| | return 0, io.EOF |
| | } |
| | n := copy(p, f.contents[f.offset:]) |
| | f.offset += n |
| | return n, nil |
| | } |
| |
|
| | func (f *FakeFile) Close() error { |
| | return nil |
| | } |
| |
|
| | |
| |
|
| | func (f *FakeFile) Size() int64 { |
| | return int64(len(f.contents)) |
| | } |
| |
|
| | func (f *FakeFile) Mode() fs.FileMode { |
| | return f.mode |
| | } |
| |
|
| | func (f *FakeFile) ModTime() time.Time { |
| | return time.Time{} |
| | } |
| |
|
| | func (f *FakeFile) IsDir() bool { |
| | return false |
| | } |
| |
|
| | func (f *FakeFile) Sys() any { |
| | return nil |
| | } |
| |
|
| | func (f *FakeFile) String() string { |
| | return fs.FormatFileInfo(f) |
| | } |
| |
|
| | |
| |
|
| | func (f *FakeFile) Entry() *archive.Entry { |
| | return &archive.Entry{ |
| | Name: f.name, |
| | Mtime: 0, |
| | Uid: 0, |
| | Gid: 0, |
| | Mode: f.mode, |
| | Data: archive.Data{Size: int64(len(f.contents))}, |
| | } |
| | } |
| |
|