github.com/adwpc/xmobile@v0.0.0-20231212131043-3f9720cf0e99/cmd/gomobile/writer_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 "crypto/x509" 9 "encoding/pem" 10 "io" 11 "io/ioutil" 12 "os" 13 "os/exec" 14 "testing" 15 ) 16 17 func TestWriter(t *testing.T) { 18 if os.Getenv("GO_BUILDER_NAME") == "linux-amd64-androidemu" { 19 t.Skip("skipping on linux-amd64-androidemu builder; see golang.org/issue/40290") 20 } 21 22 block, _ := pem.Decode([]byte(debugCert)) 23 if block == nil { 24 t.Fatal("no cert") 25 } 26 privKey, err := x509.ParsePKCS1PrivateKey(block.Bytes) 27 if err != nil { 28 t.Fatal(err) 29 } 30 31 f, err := ioutil.TempFile("", "testapk-") 32 if err != nil { 33 t.Fatal(err) 34 } 35 f.Close() 36 defer os.Remove(f.Name()) 37 apkPath := f.Name() + ".apk" 38 39 f, err = os.Create(apkPath) 40 if err != nil { 41 t.Fatal(err) 42 } 43 defer os.Remove(apkPath) 44 45 apkw := NewWriter(f, privKey) 46 47 w, err := apkw.Create("AndroidManifest.xml") 48 if err != nil { 49 t.Fatalf("could not create AndroidManifest.xml: %v", err) 50 } 51 if _, err := w.Write([]byte(androidManifest)); err != nil { 52 t.Errorf("could not write AndroidManifest.xml: %v", err) 53 } 54 55 w, err = apkw.Create("assets/hello_world.txt") 56 if err != nil { 57 t.Fatalf("could not create assets/hello_world.txt: %v", err) 58 } 59 if _, err := w.Write([]byte("Hello, 世界")); err != nil { 60 t.Errorf("could not write assets/hello_world.txt: %v", err) 61 } 62 63 if err := apkw.Close(); err != nil { 64 t.Fatal(err) 65 } 66 67 if exec.Command("which", "aapt").Run() != nil { 68 t.Skip("command aapt not found, skipping") 69 } 70 71 out, err := exec.Command("aapt", "list", "-a", apkPath).CombinedOutput() 72 aaptGot := string(out) 73 if err != nil { 74 t.Logf("aapt:\n%s", aaptGot) 75 t.Fatalf("aapt failed: %v", err) 76 } 77 78 if aaptGot != aaptWant { 79 t.Errorf("unexpected output from aapt") 80 d, err := diff(aaptGot, aaptWant) 81 if err != nil { 82 t.Errorf("diff failed: %v", err) 83 } else { 84 t.Logf("%s", d) 85 } 86 } 87 } 88 89 const aaptWant = `AndroidManifest.xml 90 assets/hello_world.txt 91 META-INF/MANIFEST.MF 92 META-INF/CERT.SF 93 META-INF/CERT.RSA 94 95 Resource table: 96 Package Groups (0) 97 98 Android manifest: 99 N: android=http://schemas.android.com/apk/res/android 100 E: manifest (line=2) 101 A: package="org.golang.fakeapp" (Raw: "org.golang.fakeapp") 102 A: android:versionCode(0x0101021b)=(type 0x10)0x1 103 A: android:versionName(0x0101021c)="1.0" (Raw: "1.0") 104 E: uses-sdk (line=8) 105 A: android:minSdkVersion(0x0101020c)=(type 0x10)0xf 106 E: application (line=9) 107 A: android:label(0x01010001)="FakeApp" (Raw: "FakeApp") 108 A: android:hasCode(0x0101000c)=(type 0x12)0x0 109 A: android:debuggable(0x0101000f)=(type 0x12)0xffffffff 110 E: activity (line=10) 111 A: android:name(0x01010003)="android.app.NativeActivity" (Raw: "android.app.NativeActivity") 112 A: android:label(0x01010001)="FakeApp" (Raw: "FakeApp") 113 A: android:configChanges(0x0101001f)=(type 0x11)0xa0 114 E: intent-filter (line=14) 115 E: action (line=15) 116 A: android:name(0x01010003)="android.intent.action.MAIN" (Raw: "android.intent.action.MAIN") 117 E: category (line=16) 118 A: android:name(0x01010003)="android.intent.category.LAUNCHER" (Raw: "android.intent.category.LAUNCHER") 119 ` 120 121 const androidManifest = ` 122 <manifest 123 xmlns:android="http://schemas.android.com/apk/res/android" 124 package="org.golang.fakeapp" 125 android:versionCode="1" 126 android:versionName="1.0"> 127 128 129 <application android:label="FakeApp" android:hasCode="false" android:debuggable="true"> 130 <activity android:name="android.app.NativeActivity" 131 android:label="FakeApp" 132 android:configChanges="orientation|keyboardHidden"> 133 134 <intent-filter> 135 <action android:name="android.intent.action.MAIN" /> 136 <category android:name="android.intent.category.LAUNCHER" /> 137 </intent-filter> 138 </activity> 139 </application> 140 </manifest> 141 ` 142 143 func writeTempFile(data string) (string, error) { 144 f, err := ioutil.TempFile("", "gofmt") 145 if err != nil { 146 return "", err 147 } 148 _, err = io.WriteString(f, data) 149 errc := f.Close() 150 if err == nil { 151 return f.Name(), errc 152 } 153 return f.Name(), err 154 } 155 156 func diff(got, want string) (string, error) { 157 wantPath, err := writeTempFile(want) 158 if err != nil { 159 return "", err 160 } 161 defer os.Remove(wantPath) 162 163 gotPath, err := writeTempFile(got) 164 if err != nil { 165 return "", err 166 } 167 defer os.Remove(gotPath) 168 169 data, err := exec.Command("diff", "-u", wantPath, gotPath).CombinedOutput() 170 if len(data) > 0 { 171 // diff exits with a non-zero status when the files don't match. 172 // Ignore that failure as long as we get output. 173 err = nil 174 } 175 return string(data), err 176 }