github.com/adwpc/xmobile@v0.0.0-20231212131043-3f9720cf0e99/cmd/gomobile/env_test.go (about) 1 // Copyright 2019 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 "fmt" 9 "io/ioutil" 10 "os" 11 "path/filepath" 12 "testing" 13 ) 14 15 func TestNdkRoot(t *testing.T) { 16 home, err := ioutil.TempDir("", "gomobile-test-") 17 if err != nil { 18 t.Fatal(err) 19 } 20 21 homeorig := os.Getenv("ANDROID_HOME") 22 os.Unsetenv("ANDROID_HOME") 23 ndkhomeorig := os.Getenv("ANDROID_NDK_HOME") 24 os.Unsetenv("ANDROID_NDK_HOME") 25 26 defer func() { 27 os.Setenv("ANDROID_HOME", homeorig) 28 os.Setenv("ANDROID_NDK_HOME", ndkhomeorig) 29 os.RemoveAll(home) 30 }() 31 32 makeMockNDK := func(path, version, platforms, abis string) string { 33 dir := filepath.Join(home, path) 34 if err := os.Mkdir(dir, 0755); err != nil { 35 t.Fatalf("couldn't mkdir %q", dir) 36 } 37 propertiesPath := filepath.Join(dir, "source.properties") 38 propertiesData := []byte("Pkg.Revision = " + version) 39 if err := os.WriteFile(propertiesPath, propertiesData, 0644); err != nil { 40 t.Fatalf("couldn't write source.properties: %v", err) 41 } 42 metaDir := filepath.Join(dir, "meta") 43 if err := os.Mkdir(metaDir, 0755); err != nil { 44 t.Fatalf("couldn't mkdir %q", metaDir) 45 } 46 platformsPath := filepath.Join(metaDir, "platforms.json") 47 platformsData := []byte(platforms) 48 if err := os.WriteFile(platformsPath, platformsData, 0644); err != nil { 49 t.Fatalf("couldn't write platforms.json: %v", err) 50 } 51 abisPath := filepath.Join(metaDir, "abis.json") 52 abisData := []byte(abis) 53 if err := os.WriteFile(abisPath, abisData, 0644); err != nil { 54 t.Fatalf("couldn't populate abis.json: %v", err) 55 } 56 return dir 57 } 58 59 t.Run("no NDK in the default location", func(t *testing.T) { 60 os.Setenv("ANDROID_HOME", home) 61 defer os.Unsetenv("ANDROID_HOME") 62 if ndk, err := ndkRoot(); err == nil { 63 t.Errorf("expected error but got %q", ndk) 64 } 65 }) 66 67 t.Run("NDK location is set but is wrong", func(t *testing.T) { 68 os.Setenv("ANDROID_NDK_HOME", filepath.Join(home, "no-such-path")) 69 defer os.Unsetenv("ANDROID_NDK_HOME") 70 if ndk, err := ndkRoot(); err == nil { 71 t.Errorf("expected error but got %q", ndk) 72 } 73 }) 74 75 t.Run("Two NDKs installed", func(t *testing.T) { 76 // Default path for pre-side-by-side NDKs. 77 sdkNDK := makeMockNDK("ndk-bundle", "fake-version", `{"min":16,"max":32}`, "{}") 78 defer os.RemoveAll(sdkNDK) 79 // Arbitrary location for testing ANDROID_NDK_HOME. 80 envNDK := makeMockNDK("custom-location", "fake-version", `{"min":16,"max":32}`, "{}") 81 82 // ANDROID_NDK_HOME is sufficient. 83 os.Setenv("ANDROID_NDK_HOME", envNDK) 84 if ndk, err := ndkRoot(); ndk != envNDK { 85 t.Errorf("got (%q, %v) want (%q, nil)", ndk, err, envNDK) 86 } 87 88 // ANDROID_NDK_HOME takes precedence over ANDROID_HOME. 89 os.Setenv("ANDROID_HOME", home) 90 if ndk, err := ndkRoot(); ndk != envNDK { 91 t.Errorf("got (%q, %v) want (%q, nil)", ndk, err, envNDK) 92 } 93 94 // ANDROID_NDK_HOME is respected even if there is no NDK there. 95 os.RemoveAll(envNDK) 96 if ndk, err := ndkRoot(); err == nil { 97 t.Errorf("expected error but got %q", ndk) 98 } 99 100 // ANDROID_HOME is used if ANDROID_NDK_HOME is not set. 101 os.Unsetenv("ANDROID_NDK_HOME") 102 if ndk, err := ndkRoot(); ndk != sdkNDK { 103 t.Errorf("got (%q, %v) want (%q, nil)", ndk, err, envNDK) 104 } 105 }) 106 107 t.Run("Modern 'side-by-side' NDK selection", func(t *testing.T) { 108 defer func() { 109 buildAndroidAPI = minAndroidAPI 110 }() 111 112 ndkForest := filepath.Join(home, "ndk") 113 if err := os.Mkdir(ndkForest, 0755); err != nil { 114 t.Fatalf("couldn't mkdir %q", ndkForest) 115 } 116 117 path := filepath.Join("ndk", "newer") 118 platforms := `{"min":19,"max":32}` 119 abis := `{"arm64-v8a": {}, "armeabi-v7a": {}, "x86_64": {}}` 120 version := "17.2.0" 121 newerNDK := makeMockNDK(path, version, platforms, abis) 122 123 path = filepath.Join("ndk", "older") 124 platforms = `{"min":16,"max":31}` 125 abis = `{"arm64-v8a": {}, "armeabi-v7a": {}, "x86": {}}` 126 version = "17.1.0" 127 olderNDK := makeMockNDK(path, version, platforms, abis) 128 129 testCases := []struct { 130 api int 131 targets []targetInfo 132 wantNDKRoot string 133 }{ 134 {15, nil, ""}, 135 {16, nil, olderNDK}, 136 {16, []targetInfo{{"android", "arm"}}, olderNDK}, 137 {16, []targetInfo{{"android", "arm"}, {"android", "arm64"}}, olderNDK}, 138 {16, []targetInfo{{"android", "x86_64"}}, ""}, 139 {19, nil, newerNDK}, 140 {19, []targetInfo{{"android", "arm"}}, newerNDK}, 141 {19, []targetInfo{{"android", "arm"}, {"android", "arm64"}, {"android", "386"}}, olderNDK}, 142 {32, nil, newerNDK}, 143 {32, []targetInfo{{"android", "arm"}}, newerNDK}, 144 {32, []targetInfo{{"android", "386"}}, ""}, 145 } 146 147 for i, tc := range testCases { 148 t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { 149 buildAndroidAPI = tc.api 150 ndk, err := ndkRoot(tc.targets...) 151 if len(tc.wantNDKRoot) != 0 { 152 if ndk != tc.wantNDKRoot || err != nil { 153 t.Errorf("got (%q, %v), want (%q, nil)", ndk, err, tc.wantNDKRoot) 154 } 155 } else if err == nil { 156 t.Error("expected error") 157 } 158 }) 159 } 160 }) 161 }