1// Copyright 2019 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package testgodefs 6 7import ( 8 "bytes" 9 "internal/testenv" 10 "os" 11 "os/exec" 12 "path/filepath" 13 "runtime" 14 "strings" 15 "testing" 16) 17 18// We are testing cgo -godefs, which translates Go files that use 19// import "C" into Go files with Go definitions of types defined in the 20// import "C" block. Add more tests here. 21var filePrefixes = []string{ 22 "anonunion", 23 "bitfields", 24 "issue8478", 25 "fieldtypedef", 26 "issue37479", 27 "issue37621", 28 "issue38649", 29 "issue39534", 30 "issue48396", 31} 32 33func TestGoDefs(t *testing.T) { 34 testenv.MustHaveGoRun(t) 35 testenv.MustHaveCGO(t) 36 37 testdata, err := filepath.Abs("testdata") 38 if err != nil { 39 t.Fatal(err) 40 } 41 42 gopath, err := os.MkdirTemp("", "testgodefs-gopath") 43 if err != nil { 44 t.Fatal(err) 45 } 46 defer os.RemoveAll(gopath) 47 48 dir := filepath.Join(gopath, "src", "testgodefs") 49 if err := os.MkdirAll(dir, 0755); err != nil { 50 t.Fatal(err) 51 } 52 53 for _, fp := range filePrefixes { 54 cmd := exec.Command("go", "tool", "cgo", 55 "-godefs", 56 "-srcdir", testdata, 57 "-objdir", dir, 58 fp+".go") 59 cmd.Stderr = new(bytes.Buffer) 60 61 out, err := cmd.Output() 62 if err != nil { 63 t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr) 64 } 65 66 fn := fp + "_defs.go" 67 if err := os.WriteFile(filepath.Join(dir, fn), out, 0644); err != nil { 68 t.Fatal(err) 69 } 70 71 // Verify that command line arguments are not rewritten in the generated comment, 72 // see go.dev/issue/52063 73 hasGeneratedByComment := false 74 for _, line := range strings.Split(strings.TrimSpace(string(out)), "\n") { 75 cgoExe := "cgo" 76 if runtime.GOOS == "windows" { 77 cgoExe = "cgo.exe" 78 } 79 if !strings.HasPrefix(line, "// "+cgoExe+" -godefs") { 80 continue 81 } 82 if want := "// " + cgoExe + " " + strings.Join(cmd.Args[3:], " "); line != want { 83 t.Errorf("%s: got generated comment %q, want %q", fn, line, want) 84 } 85 hasGeneratedByComment = true 86 break 87 } 88 89 if !hasGeneratedByComment { 90 t.Errorf("%s: comment with generating cgo -godefs command not found", fn) 91 } 92 } 93 94 main, err := os.ReadFile(filepath.Join("testdata", "main.go")) 95 if err != nil { 96 t.Fatal(err) 97 } 98 if err := os.WriteFile(filepath.Join(dir, "main.go"), main, 0644); err != nil { 99 t.Fatal(err) 100 } 101 102 if err := os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module testgodefs\ngo 1.14\n"), 0644); err != nil { 103 t.Fatal(err) 104 } 105 106 // Use 'go run' to build and run the resulting binary in a single step, 107 // instead of invoking 'go build' and the resulting binary separately, so that 108 // this test can pass on mobile builders, which do not copy artifacts back 109 // from remote invocations. 110 cmd := exec.Command("go", "run", ".") 111 cmd.Env = append(os.Environ(), "GOPATH="+gopath) 112 cmd.Dir = dir 113 if out, err := cmd.CombinedOutput(); err != nil { 114 t.Fatalf("%s [%s]: %v\n%s", strings.Join(cmd.Args, " "), dir, err, out) 115 } 116} 117