seq_test.go 6.7 KB

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