gitlab.science.ru.nl/irma/gomobile.git@v0.0.0-20200320223732-da812b634d1f/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{"golang.org/x/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 golang.org/x/mobile/example/basic 115 `)) 116 117 func TestParseBuildTargetFlag(t *testing.T) { 118 archs := strings.Join(allArchs, ",") 119 120 tests := []struct { 121 in string 122 wantErr bool 123 wantOS string 124 wantArchs string 125 }{ 126 {"android", false, "android", archs}, 127 {"android,android/arm", false, "android", archs}, 128 {"android/arm", false, "android", "arm"}, 129 130 {"ios", false, "darwin", archs}, 131 {"ios,ios/arm", false, "darwin", archs}, 132 {"ios/arm", false, "darwin", "arm"}, 133 {"ios/amd64", false, "darwin", "amd64"}, 134 135 {"", true, "", ""}, 136 {"linux", true, "", ""}, 137 {"android/x86", true, "", ""}, 138 {"android/arm5", true, "", ""}, 139 {"ios/mips", true, "", ""}, 140 {"android,ios", true, "", ""}, 141 {"ios,android", true, "", ""}, 142 } 143 144 for _, tc := range tests { 145 gotOS, gotArchs, err := parseBuildTarget(tc.in) 146 if tc.wantErr { 147 if err == nil { 148 t.Errorf("-target=%q; want error, got (%q, %q, nil)", tc.in, gotOS, gotArchs) 149 } 150 continue 151 } 152 if err != nil || gotOS != tc.wantOS || strings.Join(gotArchs, ",") != tc.wantArchs { 153 t.Errorf("-target=%q; want (%v, [%v], nil), got (%q, %q, %v)", 154 tc.in, tc.wantOS, tc.wantArchs, gotOS, gotArchs, err) 155 } 156 } 157 } 158 159 func TestRegexImportGolangXPackage(t *testing.T) { 160 tests := []struct { 161 in string 162 want string 163 wantLen int 164 }{ 165 {"ffffffff t golang.org/x/mobile", "golang.org/x/mobile", 2}, 166 {"ffffffff t github.com/example/repo/vendor/golang.org/x/mobile", "golang.org/x/mobile", 2}, 167 {"ffffffff t github.com/example/golang.org/x/mobile", "", 0}, 168 {"ffffffff t github.com/example/repo", "", 0}, 169 {"ffffffff t github.com/example/repo/vendor", "", 0}, 170 } 171 172 for _, tc := range tests { 173 res := nmRE.FindStringSubmatch(tc.in) 174 if len(res) != tc.wantLen { 175 t.Errorf("nmRE returned unexpected result for %q: want len(res) = %d, got %d", 176 tc.in, tc.wantLen, len(res)) 177 continue 178 } 179 if tc.wantLen == 0 { 180 continue 181 } 182 if res[1] != tc.want { 183 t.Errorf("nmRE returned unexpected result. want (%v), got (%v)", 184 tc.want, res[1]) 185 } 186 } 187 } 188 189 func TestBuildWithGoModules(t *testing.T) { 190 if runtime.GOOS == "android" { 191 t.Skipf("gomobile are not available on %s", runtime.GOOS) 192 } 193 194 dir, err := ioutil.TempDir("", "gomobile-test") 195 if err != nil { 196 t.Fatal(err) 197 } 198 defer os.RemoveAll(dir) 199 200 if out, err := exec.Command("go", "build", "-o="+dir, "golang.org/x/mobile/cmd/gomobile").CombinedOutput(); err != nil { 201 t.Fatalf("%v: %s", err, string(out)) 202 } 203 path := dir 204 if p := os.Getenv("PATH"); p != "" { 205 path += string(filepath.ListSeparator) + p 206 } 207 208 for _, target := range []string{"android", "ios"} { 209 t.Run(target, func(t *testing.T) { 210 if target == "ios" { 211 t.Skip("gomobile-build doesn't work for iOS. see https://golang.org/issue/32963") 212 } 213 214 switch target { 215 case "android": 216 androidHome := os.Getenv("ANDROID_HOME") 217 if androidHome == "" { 218 t.Skip("ANDROID_HOME not found, skipping bind") 219 } 220 if _, err := androidAPIPath(); err != nil { 221 t.Skip("No android API platform found in $ANDROID_HOME, skipping bind") 222 } 223 case "ios": 224 if !xcodeAvailable() { 225 t.Skip("Xcode is missing") 226 } 227 } 228 229 var out string 230 switch target { 231 case "android": 232 out = filepath.Join(dir, "basic.apk") 233 case "ios": 234 out = filepath.Join(dir, "Basic.app") 235 } 236 237 tests := []struct { 238 Name string 239 Path string 240 Dir string 241 }{ 242 { 243 Name: "Absolute Path", 244 Path: "golang.org/x/mobile/example/basic", 245 }, 246 { 247 Name: "Relative Path", 248 Path: "./example/basic", 249 Dir: filepath.Join("..", ".."), 250 }, 251 } 252 253 for _, tc := range tests { 254 tc := tc 255 t.Run(tc.Name, func(t *testing.T) { 256 args := []string{"build", "-target=" + target, "-o=" + out} 257 if target == "ios" { 258 args = append(args, "-bundleid=org.golang.gomobiletest") 259 } 260 args = append(args, tc.Path) 261 cmd := exec.Command(filepath.Join(dir, "gomobile"), args...) 262 cmd.Env = append(os.Environ(), "PATH="+path, "GO111MODULE=on") 263 cmd.Dir = tc.Dir 264 if out, err := cmd.CombinedOutput(); err != nil { 265 t.Errorf("gomobile build failed: %v\n%s", err, string(out)) 266 } 267 }) 268 } 269 }) 270 } 271 }