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