github.com/mixinnetwork/mobile@v0.0.0-20231204065441-5f786fcd11c7/cmd/gobind/gobind_test.go (about) 1 // Copyright 2016 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 5 package main 6 7 import ( 8 "bytes" 9 "fmt" 10 "os" 11 "os/exec" 12 "runtime" 13 "strings" 14 "testing" 15 16 "golang.org/x/tools/go/packages/packagestest" 17 ) 18 19 func TestMain(m *testing.M) { 20 // To avoid recompiling the gobind command (and to support compiler options 21 // like -race and -coverage), allow the test binary itself to re-exec itself 22 // as the gobind command by setting an environment variable. 23 if os.Getenv("GOBIND_TEST_IS_GOBIND") != "" { 24 main() 25 os.Exit(0) 26 } 27 os.Setenv("GOBIND_TEST_IS_GOBIND", "1") 28 29 os.Exit(m.Run()) 30 } 31 32 var tests = []struct { 33 name string 34 lang string 35 pkg string 36 goos string 37 // reverse is true if the test needs to generate reverse bindings using 38 // external tools such as javap. 39 reverse bool 40 }{ 41 { 42 name: "ObjC-Testpkg", 43 lang: "objc", 44 pkg: "github.com/mixinnetwork/mobile/bind/testdata/testpkg", 45 }, 46 { 47 name: "Java-Testpkg", 48 lang: "java", 49 pkg: "github.com/mixinnetwork/mobile/bind/testdata/testpkg", 50 }, 51 { 52 name: "Go-Testpkg", 53 lang: "go", 54 pkg: "github.com/mixinnetwork/mobile/bind/testdata/testpkg", 55 }, 56 { 57 name: "Java-Javapkg", 58 lang: "java", 59 pkg: "github.com/mixinnetwork/mobile/bind/testdata/testpkg/javapkg", 60 goos: "android", 61 reverse: true, 62 }, 63 { 64 name: "Go-Javapkg", 65 lang: "go", 66 pkg: "github.com/mixinnetwork/mobile/bind/testdata/testpkg/javapkg", 67 goos: "android", 68 reverse: true, 69 }, 70 { 71 name: "Go-Cgopkg", 72 lang: "go,java,objc", 73 pkg: "github.com/mixinnetwork/mobile/bind/testdata/cgopkg", 74 goos: "android", 75 }, 76 } 77 78 func mustHaveBindTestdata(t testing.TB) { 79 switch runtime.GOOS { 80 case "android", "ios": 81 t.Skipf("skipping: test cannot access ../../bind/testdata on %s/%s", runtime.GOOS, runtime.GOARCH) 82 } 83 } 84 85 func gobindBin(t testing.TB) string { 86 switch runtime.GOOS { 87 case "js", "ios": 88 t.Skipf("skipping: cannot exec subprocess on %s/%s", runtime.GOOS, runtime.GOARCH) 89 } 90 91 p, err := os.Executable() 92 if err != nil { 93 t.Fatal(err) 94 } 95 return p 96 } 97 98 func runGobind(t testing.TB, lang, pkg, goos string, exported *packagestest.Exported) error { 99 cmd := exec.Command(gobindBin(t), "-lang", lang, pkg) 100 cmd.Dir = exported.Config.Dir 101 cmd.Env = exported.Config.Env 102 if goos != "" { 103 // Add CGO_ENABLED=1 explicitly since Cgo is disabled when GOOS is different from host OS. 104 cmd.Env = append(cmd.Env, "GOOS="+goos, "CGO_ENABLED=1") 105 } 106 stderr := new(strings.Builder) 107 cmd.Stderr = stderr 108 stdout := new(strings.Builder) 109 cmd.Stdout = stdout 110 err := cmd.Run() 111 if testing.Verbose() && stdout.Len() > 0 { 112 t.Logf("stdout (%v):\n%s", cmd, stderr) 113 } 114 if stderr.Len() > 0 { 115 t.Logf("stderr (%v):\n%s", cmd, stderr) 116 } 117 if err != nil { 118 return fmt.Errorf("%v: %w", cmd, err) 119 } 120 return nil 121 } 122 123 func TestGobind(t *testing.T) { packagestest.TestAll(t, testGobind) } 124 func testGobind(t *testing.T, exporter packagestest.Exporter) { 125 mustHaveBindTestdata(t) 126 127 _, javapErr := exec.LookPath("javap") 128 exported := packagestest.Export(t, exporter, []packagestest.Module{{ 129 Name: "github.com/mixinnetwork/mobile", 130 Files: packagestest.MustCopyFileTree("../.."), 131 }}) 132 defer exported.Cleanup() 133 134 for _, test := range tests { 135 t.Run(test.name, func(t *testing.T) { 136 if exporter == packagestest.Modules && test.reverse { 137 t.Skip("reverse binding does't work with Go modules") 138 } 139 if test.reverse && javapErr != nil { 140 t.Skip("reverse bind test requires javap which is not available") 141 } 142 if err := runGobind(t, test.lang, test.pkg, test.goos, exported); err != nil { 143 t.Error(err) 144 } 145 }) 146 } 147 } 148 149 func TestDocs(t *testing.T) { packagestest.TestAll(t, testDocs) } 150 func testDocs(t *testing.T, exporter packagestest.Exporter) { 151 mustHaveBindTestdata(t) 152 153 const docsrc = ` 154 package doctest 155 156 // This is a comment. 157 type Struct struct{ 158 }` 159 160 exported := packagestest.Export(t, exporter, []packagestest.Module{ 161 { 162 Name: "example.com/doctest", 163 Files: map[string]interface{}{ 164 "doc.go": docsrc, 165 }, 166 }, 167 { 168 // gobind requires golang.org/x/mobile to generate code for reverse bindings. 169 Name: "github.com/mixinnetwork/mobile", 170 Files: packagestest.MustCopyFileTree("../.."), 171 }, 172 }) 173 defer exported.Cleanup() 174 175 const comment = "This is a comment." 176 for _, lang := range []string{"java", "objc"} { 177 cmd := exec.Command(gobindBin(t), "-lang", lang, "example.com/doctest") 178 cmd.Dir = exported.Config.Dir 179 cmd.Env = exported.Config.Env 180 out, err := cmd.CombinedOutput() 181 if err != nil { 182 t.Errorf("gobind -lang %s failed: %v: %s", lang, err, out) 183 continue 184 } 185 if bytes.Index(out, []byte(comment)) == -1 { 186 t.Errorf("gobind output for language %s did not contain the comment %q", lang, comment) 187 } 188 } 189 } 190 191 func BenchmarkGobind(b *testing.B) { 192 packagestest.BenchmarkAll(b, benchmarkGobind) 193 } 194 195 func benchmarkGobind(b *testing.B, exporter packagestest.Exporter) { 196 _, javapErr := exec.LookPath("javap") 197 exported := packagestest.Export(b, exporter, []packagestest.Module{{ 198 Name: "github.com/mixinnetwork/mobile", 199 Files: packagestest.MustCopyFileTree("../.."), 200 }}) 201 defer exported.Cleanup() 202 203 for _, test := range tests { 204 b.Run(test.name, func(b *testing.B) { 205 if exporter == packagestest.Modules && test.reverse { 206 b.Skip("reverse binding does't work with Go modules") 207 } 208 if test.reverse && javapErr != nil { 209 b.Skip("reverse bind test requires javap which is not available") 210 } 211 for i := 0; i < b.N; i++ { 212 if err := runGobind(b, test.lang, test.pkg, test.goos, exported); err != nil { 213 b.Error(err) 214 } 215 } 216 }) 217 } 218 }