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  }