github.com/shranet/mobile@v0.0.0-20200814083559-5702cdcd481b/cmd/gomobile/build_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 main 6 7 import ( 8 "bytes" 9 "io/ioutil" 10 "os" 11 "os/exec" 12 "path/filepath" 13 "runtime" 14 "strings" 15 "testing" 16 "text/template" 17 ) 18 19 func TestRFC1034Label(t *testing.T) { 20 tests := []struct { 21 in, want string 22 }{ 23 {"a", "a"}, 24 {"123", "-23"}, 25 {"a.b.c", "a-b-c"}, 26 {"a-b", "a-b"}, 27 {"a:b", "a-b"}, 28 {"a?b", "a-b"}, 29 {"αβγ", "---"}, 30 {"💩", "--"}, 31 {"My App", "My-App"}, 32 {"...", ""}, 33 {".-.", "--"}, 34 } 35 36 for _, tc := range tests { 37 if got := rfc1034Label(tc.in); got != tc.want { 38 t.Errorf("rfc1034Label(%q) = %q, want %q", tc.in, got, tc.want) 39 } 40 } 41 } 42 43 func TestAndroidPkgName(t *testing.T) { 44 tests := []struct { 45 in, want string 46 }{ 47 {"a", "a"}, 48 {"a123", "a123"}, 49 {"a.b.c", "a_b_c"}, 50 {"a-b", "a_b"}, 51 {"a:b", "a_b"}, 52 {"a?b", "a_b"}, 53 {"αβγ", "go___"}, 54 {"💩", "go_"}, 55 {"My App", "My_App"}, 56 {"...", "go___"}, 57 {".-.", "go___"}, 58 {"abstract", "abstract_"}, 59 {"Abstract", "Abstract"}, 60 {"12345", "go12345"}, 61 } 62 63 for _, tc := range tests { 64 if got := androidPkgName(tc.in); got != tc.want { 65 t.Errorf("len %d", len(tc.in)) 66 t.Errorf("androidPkgName(%q) = %q, want %q", tc.in, got, tc.want) 67 } 68 } 69 } 70 71 func TestAndroidBuild(t *testing.T) { 72 if runtime.GOOS == "android" { 73 t.Skip("not available on Android") 74 } 75 buf := new(bytes.Buffer) 76 defer func() { 77 xout = os.Stderr 78 buildN = false 79 buildX = false 80 }() 81 xout = buf 82 buildN = true 83 buildX = true 84 buildO = "basic.apk" 85 buildTarget = "android/arm" 86 gopath = filepath.ToSlash(filepath.SplitList(goEnv("GOPATH"))[0]) 87 if goos == "windows" { 88 os.Setenv("HOMEDRIVE", "C:") 89 } 90 cmdBuild.flag.Parse([]string{"github.com/shranet/mobile/example/basic"}) 91 oldTags := buildTags 92 buildTags = []string{"tag1"} 93 defer func() { 94 buildTags = oldTags 95 }() 96 err := runBuild(cmdBuild) 97 if err != nil { 98 t.Log(buf.String()) 99 t.Fatal(err) 100 } 101 102 diff, err := diffOutput(buf.String(), androidBuildTmpl) 103 if err != nil { 104 t.Fatalf("computing diff failed: %v", err) 105 } 106 if diff != "" { 107 t.Errorf("unexpected output:\n%s", diff) 108 } 109 } 110 111 var androidBuildTmpl = template.Must(template.New("output").Parse(`GOMOBILE={{.GOPATH}}/pkg/gomobile 112 WORK=$WORK 113 mkdir -p $WORK/lib/armeabi-v7a 114 GOOS=android GOARCH=arm CC=$NDK_PATH/toolchains/llvm/prebuilt/{{.NDKARCH}}/bin/armv7a-linux-androideabi16-clang CXX=$NDK_PATH/toolchains/llvm/prebuilt/{{.NDKARCH}}/bin/armv7a-linux-androideabi16-clang++ CGO_ENABLED=1 GOARM=7 go build -tags tag1 -x -buildmode=c-shared -o $WORK/lib/armeabi-v7a/libbasic.so github.com/shranet/mobile/example/basic 115 `)) 116 117 func TestParseBuildTargetFlag(t *testing.T) { 118 androidArchs := strings.Join(allArchs("android"), ",") 119 iosArchs := strings.Join(allArchs("ios"), ",") 120 121 tests := []struct { 122 in string 123 wantErr bool 124 wantOS string 125 wantArchs string 126 }{ 127 {"android", false, "android", androidArchs}, 128 {"android,android/arm", false, "android", androidArchs}, 129 {"android/arm", false, "android", "arm"}, 130 131 {"ios", false, "darwin", iosArchs}, 132 {"ios,ios/arm64", false, "darwin", iosArchs}, 133 {"ios/arm64", false, "darwin", "arm64"}, 134 {"ios/amd64", false, "darwin", "amd64"}, 135 136 {"", true, "", ""}, 137 {"linux", true, "", ""}, 138 {"android/x86", true, "", ""}, 139 {"android/arm5", true, "", ""}, 140 {"ios/mips", true, "", ""}, 141 {"android,ios", true, "", ""}, 142 {"ios,android", true, "", ""}, 143 } 144 145 for _, tc := range tests { 146 gotOS, gotArchs, err := parseBuildTarget(tc.in) 147 if tc.wantErr { 148 if err == nil { 149 t.Errorf("-target=%q; want error, got (%q, %q, nil)", tc.in, gotOS, gotArchs) 150 } 151 continue 152 } 153 if err != nil || gotOS != tc.wantOS || strings.Join(gotArchs, ",") != tc.wantArchs { 154 t.Errorf("-target=%q; want (%v, [%v], nil), got (%q, %q, %v)", 155 tc.in, tc.wantOS, tc.wantArchs, gotOS, gotArchs, err) 156 } 157 } 158 } 159 160 func TestRegexImportGolangXPackage(t *testing.T) { 161 tests := []struct { 162 in string 163 want string 164 wantLen int 165 }{ 166 {"ffffffff t github.com/shranet/mobile", "github.com/shranet/mobile", 2}, 167 {"ffffffff t github.com/example/repo/vendor/github.com/shranet/mobile", "github.com/shranet/mobile", 2}, 168 {"ffffffff t github.com/example/github.com/shranet/mobile", "", 0}, 169 {"ffffffff t github.com/example/repo", "", 0}, 170 {"ffffffff t github.com/example/repo/vendor", "", 0}, 171 } 172 173 for _, tc := range tests { 174 res := nmRE.FindStringSubmatch(tc.in) 175 if len(res) != tc.wantLen { 176 t.Errorf("nmRE returned unexpected result for %q: want len(res) = %d, got %d", 177 tc.in, tc.wantLen, len(res)) 178 continue 179 } 180 if tc.wantLen == 0 { 181 continue 182 } 183 if res[1] != tc.want { 184 t.Errorf("nmRE returned unexpected result. want (%v), got (%v)", 185 tc.want, res[1]) 186 } 187 } 188 } 189 190 func TestBuildWithGoModules(t *testing.T) { 191 if runtime.GOOS == "android" { 192 t.Skipf("gomobile are not available on %s", runtime.GOOS) 193 } 194 195 dir, err := ioutil.TempDir("", "gomobile-test") 196 if err != nil { 197 t.Fatal(err) 198 } 199 defer os.RemoveAll(dir) 200 201 if out, err := exec.Command("go", "build", "-o="+dir, "github.com/shranet/mobile/cmd/gomobile").CombinedOutput(); err != nil { 202 t.Fatalf("%v: %s", err, string(out)) 203 } 204 path := dir 205 if p := os.Getenv("PATH"); p != "" { 206 path += string(filepath.ListSeparator) + p 207 } 208 209 for _, target := range []string{"android", "ios"} { 210 t.Run(target, func(t *testing.T) { 211 if target == "ios" { 212 t.Skip("gomobile-build doesn't work for iOS. see https://golang.org/issue/32963") 213 } 214 215 switch target { 216 case "android": 217 androidHome := os.Getenv("ANDROID_HOME") 218 if androidHome == "" { 219 t.Skip("ANDROID_HOME not found, skipping bind") 220 } 221 if _, err := androidAPIPath(); err != nil { 222 t.Skip("No android API platform found in $ANDROID_HOME, skipping bind") 223 } 224 case "ios": 225 if !xcodeAvailable() { 226 t.Skip("Xcode is missing") 227 } 228 } 229 230 var out string 231 switch target { 232 case "android": 233 out = filepath.Join(dir, "basic.apk") 234 case "ios": 235 out = filepath.Join(dir, "Basic.app") 236 } 237 238 tests := []struct { 239 Name string 240 Path string 241 Dir string 242 }{ 243 { 244 Name: "Absolute Path", 245 Path: "github.com/shranet/mobile/example/basic", 246 }, 247 { 248 Name: "Relative Path", 249 Path: "./example/basic", 250 Dir: filepath.Join("..", ".."), 251 }, 252 } 253 254 for _, tc := range tests { 255 tc := tc 256 t.Run(tc.Name, func(t *testing.T) { 257 args := []string{"build", "-target=" + target, "-o=" + out} 258 if target == "ios" { 259 args = append(args, "-bundleid=org.golang.gomobiletest") 260 } 261 args = append(args, tc.Path) 262 cmd := exec.Command(filepath.Join(dir, "gomobile"), args...) 263 cmd.Env = append(os.Environ(), "PATH="+path, "GO111MODULE=on") 264 cmd.Dir = tc.Dir 265 if out, err := cmd.CombinedOutput(); err != nil { 266 t.Errorf("gomobile build failed: %v\n%s", err, string(out)) 267 } 268 }) 269 } 270 }) 271 } 272 }