1// Copyright 2018 The Bazel Authors. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package patch 16 17import ( 18 "bufio" 19 "bytes" 20 "encoding/xml" 21 "strings" 22 "testing" 23 24 "src/common/golang/xml2" 25 "src/tools/ak/manifestutils" 26) 27 28const ( 29 manifestWithAppClass = `<?xml version="1.0" ?> 30<manifest package="com.google.android.other" xmlns:android="http://schemas.android.com/apk/res/android"> 31 <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="21"/> 32 <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:name="android.app.OtherApplication" android:label="@string/app_name" android:theme="@style/AppTheme"> 33 <activity android:label="@string/app_name" android:name="com.google.android.test.Activity"> 34 <intent-filter> 35 <action android:name="android.intent.action.MAIN"/> 36 <category android:name="android.intent.category.LAUNCHER"/> 37 </intent-filter> 38 </activity> 39 </application> 40</manifest>` 41 42 manifestWithAppClassAtEnd = `<?xml version="1.0" ?> 43<manifest package="com.google.android.end" xmlns:android="http://schemas.android.com/apk/res/android"> 44 <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="21"/> 45 <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" android:name="android.app.EndApplication"> 46 <activity android:label="@string/app_name" android:name="com.google.android.test.Activity"> 47 <intent-filter> 48 <action android:name="android.intent.action.MAIN"/> 49 <category android:name="android.intent.category.LAUNCHER"/> 50 </intent-filter> 51 </activity> 52 </application> 53</manifest>` 54 55 manifestWithNoAppClass = `<?xml version="1.0" ?> 56<manifest package="com.google.android.test" xmlns:android="http://schemas.android.com/apk/res/android"> 57 <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="21"/> 58 <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme"> 59 <activity android:label="@string/app_name" android:name="com.google.android.test.Activity"> 60 <intent-filter> 61 <action android:name="android.intent.action.MAIN"/> 62 <category android:name="android.intent.category.LAUNCHER"/> 63 </intent-filter> 64 </activity> 65 </application> 66</manifest>` 67) 68 69func TestParsing(t *testing.T) { 70 tests := []struct { 71 name string 72 manifestXML string 73 wantPkg string 74 wantApp string 75 }{ 76 { 77 name: "withAppClass", 78 manifestXML: manifestWithAppClass, 79 wantPkg: "com.google.android.other", 80 wantApp: "android.app.OtherApplication", 81 }, 82 { 83 name: "withAppClassAtEnd", 84 manifestXML: manifestWithAppClassAtEnd, 85 wantPkg: "com.google.android.end", 86 wantApp: "android.app.EndApplication", 87 }, 88 { 89 name: "noAppClass", 90 manifestXML: manifestWithNoAppClass, 91 wantPkg: "com.google.android.test", 92 wantApp: "", 93 }, 94 } 95 for _, test := range tests { 96 t.Run(test.name, func(t *testing.T) { 97 var manifest manifestutils.Manifest 98 xml.Unmarshal([]byte(test.manifestXML), &manifest) 99 if manifest.Package != test.wantPkg { 100 t.Errorf("Parsed package name not correct: got: %q wanted: %q", manifest.Package, test.wantPkg) 101 } 102 if manifest.Application.Name != test.wantApp { 103 t.Errorf("Parsed application class name not correct: got: %q wanted: %q", manifest.Application.Name, test.wantApp) 104 } 105 }) 106 } 107} 108 109func TestSetAppName(t *testing.T) { 110 tests := []struct { 111 name string 112 manifestXML string 113 newApp string 114 wantManifestXML string 115 }{ 116 { 117 name: "withAppClass", 118 manifestXML: manifestWithAppClass, 119 newApp: "android.app.OtherTestApplication", 120 }, 121 { 122 name: "withAppClassAtEnd", 123 manifestXML: manifestWithAppClassAtEnd, 124 newApp: "android.app.EndTestApplication", 125 }, 126 { 127 name: "noAppClass", 128 manifestXML: manifestWithNoAppClass, 129 newApp: "android.app.TestApplication", 130 }, 131 } 132 elems := map[string]map[string]xml.Attr{"application": make(map[string]xml.Attr)} 133 for _, test := range tests { 134 t.Run(test.name, func(t *testing.T) { 135 elems["application"]["name"] = xml.Attr{ 136 Name: xml.Name{Space: manifestutils.NameSpace, Local: "name"}, Value: test.newApp} 137 var b bytes.Buffer 138 e := xml2.NewEncoder(bufio.NewWriter(&b)) 139 manifestutils.Patch(xml.NewDecoder(strings.NewReader(test.manifestXML)), e, elems) 140 if err := e.Flush(); err != nil { 141 t.Fatalf("Error occurred during encoder flush: %v", err) 142 } 143 var manifest manifestutils.Manifest 144 xml.Unmarshal([]byte(b.String()), &manifest) 145 if manifest.Application.Name != test.newApp { 146 t.Errorf("New application class name not correct: got: %q wanted: %q", manifest.Application.Name, test.newApp) 147 } 148 }) 149 } 150} 151 152func TestSetAppName_xmlEncoding(t *testing.T) { 153 wantManifestXML := `<?xml version="1.0" ?> 154<manifest package="com.google.android.other" xmlns:android="http://schemas.android.com/apk/res/android"> 155 <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="21"></uses-sdk> 156 <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:name="android.app.OtherApplication" android:label="@string/app_name" android:theme="@style/AppTheme"> 157 <activity android:label="@string/app_name" android:name="com.google.android.test.Activity"> 158 <intent-filter> 159 <action android:name="android.intent.action.MAIN"></action> 160 <category android:name="android.intent.category.LAUNCHER"></category> 161 </intent-filter> 162 </activity> 163 </application> 164</manifest>` 165 166 elems := map[string]map[string]xml.Attr{ 167 "application": map[string]xml.Attr{"name": xml.Attr{ 168 Name: xml.Name{Space: manifestutils.NameSpace, Local: "name"}, Value: "android.app.OtherApplication"}}} 169 var b bytes.Buffer 170 e := xml2.NewEncoder(bufio.NewWriter(&b)) 171 manifestutils.Patch(xml.NewDecoder(strings.NewReader(manifestWithAppClass)), e, elems) 172 if err := e.Flush(); err != nil { 173 t.Fatalf("Error occurred during encoder flush: %v", err) 174 } 175 if b.String() != wantManifestXML { 176 t.Errorf("got: <%s> expected: <%s>", b.String(), wantManifestXML) 177 } 178} 179