github.com/F4RD1N/gomobile@v1.0.1/bind/java/seq_test.go (about) 1 // Copyright 2015 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 java 6 7 import ( 8 "fmt" 9 "io" 10 "io/ioutil" 11 "log" 12 "os" 13 "os/exec" 14 "path/filepath" 15 "runtime" 16 "strings" 17 "testing" 18 19 "github.com/F4RD1N/gomobile/internal/importers/java" 20 ) 21 22 var gomobileBin string 23 24 func TestMain(m *testing.M) { 25 os.Exit(testMain(m)) 26 } 27 28 func testMain(m *testing.M) int { 29 // Build gomobile and gobind and put them into PATH. 30 binDir, err := ioutil.TempDir("", "bind-java-test-") 31 if err != nil { 32 log.Fatal(err) 33 } 34 defer os.RemoveAll(binDir) 35 exe := "" 36 if runtime.GOOS == "windows" { 37 exe = ".exe" 38 } 39 if runtime.GOOS != "android" { 40 gocmd := filepath.Join(runtime.GOROOT(), "bin", "go") 41 gomobileBin = filepath.Join(binDir, "gomobile"+exe) 42 gobindBin := filepath.Join(binDir, "gobind"+exe) 43 if out, err := exec.Command(gocmd, "build", "-o", gomobileBin, "github.com/F4RD1N/gomobile/cmd/gomobile").CombinedOutput(); err != nil { 44 log.Fatalf("gomobile build failed: %v: %s", err, out) 45 } 46 if out, err := exec.Command(gocmd, "build", "-o", gobindBin, "github.com/F4RD1N/gomobile/cmd/gobind").CombinedOutput(); err != nil { 47 log.Fatalf("gobind build failed: %v: %s", err, out) 48 } 49 path := binDir 50 if oldPath := os.Getenv("PATH"); oldPath != "" { 51 path += string(filepath.ListSeparator) + oldPath 52 } 53 os.Setenv("PATH", path) 54 } 55 return m.Run() 56 } 57 58 func TestClasses(t *testing.T) { 59 if !java.IsAvailable() { 60 t.Skipf("java importer is not available") 61 } 62 runTest(t, []string{ 63 "github.com/F4RD1N/gomobile/bind/testdata/testpkg/javapkg", 64 }, "", "ClassesTest") 65 } 66 67 func TestCustomPkg(t *testing.T) { 68 runTest(t, []string{ 69 "github.com/F4RD1N/gomobile/bind/testdata/testpkg", 70 }, "org.golang.custompkg", "CustomPkgTest") 71 } 72 73 func TestJavaSeqTest(t *testing.T) { 74 runTest(t, []string{ 75 "github.com/F4RD1N/gomobile/bind/testdata/testpkg", 76 "github.com/F4RD1N/gomobile/bind/testdata/testpkg/secondpkg", 77 "github.com/F4RD1N/gomobile/bind/testdata/testpkg/simplepkg", 78 }, "", "SeqTest") 79 } 80 81 // TestJavaSeqBench runs java test SeqBench.java, with the same 82 // environment requirements as TestJavaSeqTest. 83 // 84 // The benchmarks runs on the phone, so the benchmarkpkg implements 85 // rudimentary timing logic and outputs benchcmp compatible runtimes 86 // to logcat. Use 87 // 88 // adb logcat -v raw GoLog:* *:S 89 // 90 // while running the benchmark to see the results. 91 func TestJavaSeqBench(t *testing.T) { 92 if testing.Short() { 93 t.Skip("skipping benchmark in short mode.") 94 } 95 runTest(t, []string{"github.com/F4RD1N/gomobile/bind/testdata/benchmark"}, "", "SeqBench") 96 } 97 98 // runTest runs the Android java test class specified with javaCls. If javaPkg is 99 // set, it is passed with the -javapkg flag to gomobile. The pkgNames lists the Go 100 // packages to bind for the test. 101 // This requires the gradle command in PATH and 102 // the Android SDK whose path is available through ANDROID_HOME environment variable. 103 func runTest(t *testing.T, pkgNames []string, javaPkg, javaCls string) { 104 if gomobileBin == "" { 105 t.Skipf("no gomobile on %s", runtime.GOOS) 106 } 107 gradle, err := exec.LookPath("gradle") 108 if err != nil { 109 t.Skip("command gradle not found, skipping") 110 } 111 if sdk := os.Getenv("ANDROID_HOME"); sdk == "" { 112 t.Skip("ANDROID_HOME environment var not set, skipping") 113 } 114 115 cwd, err := os.Getwd() 116 if err != nil { 117 t.Fatalf("failed pwd: %v", err) 118 } 119 tmpdir, err := ioutil.TempDir("", "bind-java-seq-test-") 120 if err != nil { 121 t.Fatalf("failed to prepare temp dir: %v", err) 122 } 123 defer os.RemoveAll(tmpdir) 124 t.Logf("tmpdir = %s", tmpdir) 125 126 if err := os.Chdir(tmpdir); err != nil { 127 t.Fatalf("failed chdir: %v", err) 128 } 129 defer os.Chdir(cwd) 130 131 for _, d := range []string{"src/main", "src/androidTest/java/go", "libs", "src/main/res/values"} { 132 err = os.MkdirAll(filepath.Join(tmpdir, d), 0700) 133 if err != nil { 134 t.Fatal(err) 135 } 136 } 137 138 args := []string{"bind", "-tags", "aaa bbb", "-o", "pkg.aar"} 139 if javaPkg != "" { 140 args = append(args, "-javapkg", javaPkg) 141 } 142 args = append(args, pkgNames...) 143 cmd := exec.Command(gomobileBin, args...) 144 // Reverse binding doesn't work with Go module since imports starting with Java or ObjC are not valid FQDNs. 145 // Disable Go module explicitly until this problem is solved. See golang/go#27234. 146 cmd.Env = append(os.Environ(), "GO111MODULE=off") 147 buf, err := cmd.CombinedOutput() 148 if err != nil { 149 t.Logf("%s", buf) 150 t.Fatalf("failed to run gomobile bind: %v", err) 151 } 152 153 fname := filepath.Join(tmpdir, "libs", "pkg.aar") 154 err = cp(fname, filepath.Join(tmpdir, "pkg.aar")) 155 if err != nil { 156 t.Fatalf("failed to copy pkg.aar: %v", err) 157 } 158 159 fname = filepath.Join(tmpdir, "src/androidTest/java/go/"+javaCls+".java") 160 err = cp(fname, filepath.Join(cwd, javaCls+".java")) 161 if err != nil { 162 t.Fatalf("failed to copy SeqTest.java: %v", err) 163 } 164 165 fname = filepath.Join(tmpdir, "src/main/AndroidManifest.xml") 166 err = ioutil.WriteFile(fname, []byte(androidmanifest), 0700) 167 if err != nil { 168 t.Fatalf("failed to write android manifest file: %v", err) 169 } 170 171 // Add a dummy string resource to avoid errors from the Android build system. 172 fname = filepath.Join(tmpdir, "src/main/res/values/strings.xml") 173 err = ioutil.WriteFile(fname, []byte(stringsxml), 0700) 174 if err != nil { 175 t.Fatalf("failed to write strings.xml file: %v", err) 176 } 177 178 fname = filepath.Join(tmpdir, "build.gradle") 179 err = ioutil.WriteFile(fname, []byte(buildgradle), 0700) 180 if err != nil { 181 t.Fatalf("failed to write build.gradle file: %v", err) 182 } 183 184 if buf, err := run(gradle + " connectedAndroidTest"); err != nil { 185 t.Logf("%s", buf) 186 t.Errorf("failed to run gradle test: %v", err) 187 } 188 } 189 190 func run(cmd string) ([]byte, error) { 191 c := strings.Split(cmd, " ") 192 return exec.Command(c[0], c[1:]...).CombinedOutput() 193 } 194 195 func cp(dst, src string) error { 196 r, err := os.Open(src) 197 if err != nil { 198 return fmt.Errorf("failed to read source: %v", err) 199 } 200 defer r.Close() 201 w, err := os.Create(dst) 202 if err != nil { 203 return fmt.Errorf("failed to open destination: %v", err) 204 } 205 _, err = io.Copy(w, r) 206 cerr := w.Close() 207 if err != nil { 208 return err 209 } 210 return cerr 211 } 212 213 const androidmanifest = `<?xml version="1.0" encoding="utf-8"?> 214 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 215 package="com.example.BindTest" 216 android:versionCode="1" 217 android:versionName="1.0"> 218 </manifest>` 219 220 const buildgradle = `buildscript { 221 repositories { 222 google() 223 jcenter() 224 } 225 dependencies { 226 classpath 'com.android.tools.build:gradle:3.1.0' 227 } 228 } 229 230 allprojects { 231 repositories { 232 google() 233 jcenter() 234 } 235 } 236 237 apply plugin: 'com.android.library' 238 239 android { 240 compileSdkVersion 'android-19' 241 defaultConfig { minSdkVersion 16 } 242 } 243 244 repositories { 245 flatDir { dirs 'libs' } 246 } 247 248 dependencies { 249 implementation(name: "pkg", ext: "aar") 250 } 251 ` 252 253 const stringsxml = `<?xml version="1.0" encoding="utf-8"?> 254 <resources> 255 <string name="dummy">dummy</string> 256 </resources>`