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