| // Copyright 2019 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package testgodefs |
| |
| import ( |
| "bytes" |
| "internal/testenv" |
| "os" |
| "os/exec" |
| "path/filepath" |
| "runtime" |
| "strings" |
| "testing" |
| ) |
| |
| // We are testing cgo -godefs, which translates Go files that use |
| // import "C" into Go files with Go definitions of types defined in the |
| // import "C" block. Add more tests here. |
| var filePrefixes = []string{ |
| "anonunion", |
| "bitfields", |
| "issue8478", |
| "fieldtypedef", |
| "issue37479", |
| "issue37621", |
| "issue38649", |
| "issue39534", |
| "issue48396", |
| } |
| |
| func TestGoDefs(t *testing.T) { |
| testenv.MustHaveGoRun(t) |
| testenv.MustHaveCGO(t) |
| |
| testdata, err := filepath.Abs("testdata") |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| gopath, err := os.MkdirTemp("", "testgodefs-gopath") |
| if err != nil { |
| t.Fatal(err) |
| } |
| defer os.RemoveAll(gopath) |
| |
| dir := filepath.Join(gopath, "src", "testgodefs") |
| if err := os.MkdirAll(dir, 0755); err != nil { |
| t.Fatal(err) |
| } |
| |
| for _, fp := range filePrefixes { |
| cmd := exec.Command("go", "tool", "cgo", |
| "-godefs", |
| "-srcdir", testdata, |
| "-objdir", dir, |
| fp+".go") |
| cmd.Stderr = new(bytes.Buffer) |
| |
| out, err := cmd.Output() |
| if err != nil { |
| t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr) |
| } |
| |
| fn := fp + "_defs.go" |
| if err := os.WriteFile(filepath.Join(dir, fn), out, 0644); err != nil { |
| t.Fatal(err) |
| } |
| |
| // Verify that command line arguments are not rewritten in the generated comment, |
| // see go.dev/issue/52063 |
| hasGeneratedByComment := false |
| for _, line := range strings.Split(strings.TrimSpace(string(out)), "\n") { |
| cgoExe := "cgo" |
| if runtime.GOOS == "windows" { |
| cgoExe = "cgo.exe" |
| } |
| if !strings.HasPrefix(line, "// "+cgoExe+" -godefs") { |
| continue |
| } |
| if want := "// " + cgoExe + " " + strings.Join(cmd.Args[3:], " "); line != want { |
| t.Errorf("%s: got generated comment %q, want %q", fn, line, want) |
| } |
| hasGeneratedByComment = true |
| break |
| } |
| |
| if !hasGeneratedByComment { |
| t.Errorf("%s: comment with generating cgo -godefs command not found", fn) |
| } |
| } |
| |
| main, err := os.ReadFile(filepath.Join("testdata", "main.go")) |
| if err != nil { |
| t.Fatal(err) |
| } |
| if err := os.WriteFile(filepath.Join(dir, "main.go"), main, 0644); err != nil { |
| t.Fatal(err) |
| } |
| |
| if err := os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module testgodefs\ngo 1.14\n"), 0644); err != nil { |
| t.Fatal(err) |
| } |
| |
| // Use 'go run' to build and run the resulting binary in a single step, |
| // instead of invoking 'go build' and the resulting binary separately, so that |
| // this test can pass on mobile builders, which do not copy artifacts back |
| // from remote invocations. |
| cmd := exec.Command("go", "run", ".") |
| cmd.Env = append(os.Environ(), "GOPATH="+gopath) |
| cmd.Dir = dir |
| if out, err := cmd.CombinedOutput(); err != nil { |
| t.Fatalf("%s [%s]: %v\n%s", strings.Join(cmd.Args, " "), dir, err, out) |
| } |
| } |