1 /*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "link/ManifestFixer.h"
18 #include "test/Builders.h"
19 #include "test/Context.h"
20
21 #include <gtest/gtest.h>
22
23 namespace aapt {
24
25 struct ManifestFixerTest : public ::testing::Test {
26 std::unique_ptr<IAaptContext> mContext;
27
SetUpaapt::ManifestFixerTest28 void SetUp() override {
29 mContext = test::ContextBuilder()
30 .setCompilationPackage(u"android")
31 .setPackageId(0x01)
32 .setNameManglerPolicy(NameManglerPolicy{ u"android" })
33 .addSymbolSource(test::StaticSymbolSourceBuilder()
34 .addSymbol(u"@android:attr/package", ResourceId(0x01010000),
35 test::AttributeBuilder()
36 .setTypeMask(android::ResTable_map::TYPE_STRING)
37 .build())
38 .addSymbol(u"@android:attr/minSdkVersion", ResourceId(0x01010001),
39 test::AttributeBuilder()
40 .setTypeMask(android::ResTable_map::TYPE_STRING |
41 android::ResTable_map::TYPE_INTEGER)
42 .build())
43 .addSymbol(u"@android:attr/targetSdkVersion", ResourceId(0x01010002),
44 test::AttributeBuilder()
45 .setTypeMask(android::ResTable_map::TYPE_STRING |
46 android::ResTable_map::TYPE_INTEGER)
47 .build())
48 .addSymbol(u"@android:string/str", ResourceId(0x01060000))
49 .build())
50 .build();
51 }
52
verifyaapt::ManifestFixerTest53 std::unique_ptr<xml::XmlResource> verify(const StringPiece& str) {
54 return verifyWithOptions(str, {});
55 }
56
verifyWithOptionsaapt::ManifestFixerTest57 std::unique_ptr<xml::XmlResource> verifyWithOptions(const StringPiece& str,
58 const ManifestFixerOptions& options) {
59 std::unique_ptr<xml::XmlResource> doc = test::buildXmlDom(str);
60 ManifestFixer fixer(options);
61 if (fixer.consume(mContext.get(), doc.get())) {
62 return doc;
63 }
64 return {};
65 }
66 };
67
TEST_F(ManifestFixerTest,EnsureManifestIsRootTag)68 TEST_F(ManifestFixerTest, EnsureManifestIsRootTag) {
69 EXPECT_EQ(nullptr, verify("<other-tag />"));
70 EXPECT_EQ(nullptr, verify("<ns:manifest xmlns:ns=\"com\" />"));
71 EXPECT_NE(nullptr, verify("<manifest package=\"android\"></manifest>"));
72 }
73
TEST_F(ManifestFixerTest,EnsureManifestHasPackage)74 TEST_F(ManifestFixerTest, EnsureManifestHasPackage) {
75 EXPECT_NE(nullptr, verify("<manifest package=\"android\" />"));
76 EXPECT_NE(nullptr, verify("<manifest package=\"com.android\" />"));
77 EXPECT_NE(nullptr, verify("<manifest package=\"com.android.google\" />"));
78 EXPECT_EQ(nullptr, verify("<manifest package=\"com.android.google.Class$1\" />"));
79 EXPECT_EQ(nullptr,
80 verify("<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" "
81 "android:package=\"com.android\" />"));
82 EXPECT_EQ(nullptr, verify("<manifest package=\"@string/str\" />"));
83 }
84
TEST_F(ManifestFixerTest,UseDefaultSdkVersionsIfNonePresent)85 TEST_F(ManifestFixerTest, UseDefaultSdkVersionsIfNonePresent) {
86 ManifestFixerOptions options = { std::u16string(u"8"), std::u16string(u"22") };
87
88 std::unique_ptr<xml::XmlResource> doc = verifyWithOptions(R"EOF(
89 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
90 package="android">
91 <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="21" />
92 </manifest>)EOF", options);
93 ASSERT_NE(nullptr, doc);
94
95 xml::Element* el;
96 xml::Attribute* attr;
97
98 el = xml::findRootElement(doc.get());
99 ASSERT_NE(nullptr, el);
100 el = el->findChild({}, u"uses-sdk");
101 ASSERT_NE(nullptr, el);
102 attr = el->findAttribute(xml::kSchemaAndroid, u"minSdkVersion");
103 ASSERT_NE(nullptr, attr);
104 EXPECT_EQ(u"7", attr->value);
105 attr = el->findAttribute(xml::kSchemaAndroid, u"targetSdkVersion");
106 ASSERT_NE(nullptr, attr);
107 EXPECT_EQ(u"21", attr->value);
108
109 doc = verifyWithOptions(R"EOF(
110 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
111 package="android">
112 <uses-sdk android:targetSdkVersion="21" />
113 </manifest>)EOF", options);
114 ASSERT_NE(nullptr, doc);
115
116 el = xml::findRootElement(doc.get());
117 ASSERT_NE(nullptr, el);
118 el = el->findChild({}, u"uses-sdk");
119 ASSERT_NE(nullptr, el);
120 attr = el->findAttribute(xml::kSchemaAndroid, u"minSdkVersion");
121 ASSERT_NE(nullptr, attr);
122 EXPECT_EQ(u"8", attr->value);
123 attr = el->findAttribute(xml::kSchemaAndroid, u"targetSdkVersion");
124 ASSERT_NE(nullptr, attr);
125 EXPECT_EQ(u"21", attr->value);
126
127 doc = verifyWithOptions(R"EOF(
128 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
129 package="android">
130 <uses-sdk />
131 </manifest>)EOF", options);
132 ASSERT_NE(nullptr, doc);
133
134 el = xml::findRootElement(doc.get());
135 ASSERT_NE(nullptr, el);
136 el = el->findChild({}, u"uses-sdk");
137 ASSERT_NE(nullptr, el);
138 attr = el->findAttribute(xml::kSchemaAndroid, u"minSdkVersion");
139 ASSERT_NE(nullptr, attr);
140 EXPECT_EQ(u"8", attr->value);
141 attr = el->findAttribute(xml::kSchemaAndroid, u"targetSdkVersion");
142 ASSERT_NE(nullptr, attr);
143 EXPECT_EQ(u"22", attr->value);
144
145 doc = verifyWithOptions(R"EOF(
146 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
147 package="android" />)EOF", options);
148 ASSERT_NE(nullptr, doc);
149
150 el = xml::findRootElement(doc.get());
151 ASSERT_NE(nullptr, el);
152 el = el->findChild({}, u"uses-sdk");
153 ASSERT_NE(nullptr, el);
154 attr = el->findAttribute(xml::kSchemaAndroid, u"minSdkVersion");
155 ASSERT_NE(nullptr, attr);
156 EXPECT_EQ(u"8", attr->value);
157 attr = el->findAttribute(xml::kSchemaAndroid, u"targetSdkVersion");
158 ASSERT_NE(nullptr, attr);
159 EXPECT_EQ(u"22", attr->value);
160 }
161
162 TEST_F(ManifestFixerTest, RenameManifestPackageAndFullyQualifyClasses) {
163 ManifestFixerOptions options;
164 options.renameManifestPackage = std::u16string(u"com.android");
165
166 std::unique_ptr<xml::XmlResource> doc = verifyWithOptions(R"EOF(
167 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
168 package="android">
169 <application android:name=".MainApplication" text="hello">
170 <activity android:name=".activity.Start" />
171 <receiver android:name="com.google.android.Receiver" />
172 </application>
173 </manifest>)EOF", options);
174 ASSERT_NE(nullptr, doc);
175
176 xml::Element* manifestEl = xml::findRootElement(doc.get());
177 ASSERT_NE(nullptr, manifestEl);
178
179 xml::Attribute* attr = nullptr;
180
181 attr = manifestEl->findAttribute({}, u"package");
182 ASSERT_NE(nullptr, attr);
183 EXPECT_EQ(std::u16string(u"com.android"), attr->value);
184
185 xml::Element* applicationEl = manifestEl->findChild({}, u"application");
186 ASSERT_NE(nullptr, applicationEl);
187
188 attr = applicationEl->findAttribute(xml::kSchemaAndroid, u"name");
189 ASSERT_NE(nullptr, attr);
190 EXPECT_EQ(std::u16string(u"android.MainApplication"), attr->value);
191
192 attr = applicationEl->findAttribute({}, u"text");
193 ASSERT_NE(nullptr, attr);
194 EXPECT_EQ(std::u16string(u"hello"), attr->value);
195
196 xml::Element* el;
197 el = applicationEl->findChild({}, u"activity");
198 ASSERT_NE(nullptr, el);
199
200 attr = el->findAttribute(xml::kSchemaAndroid, u"name");
201 ASSERT_NE(nullptr, el);
202 EXPECT_EQ(std::u16string(u"android.activity.Start"), attr->value);
203
204 el = applicationEl->findChild({}, u"receiver");
205 ASSERT_NE(nullptr, el);
206
207 attr = el->findAttribute(xml::kSchemaAndroid, u"name");
208 ASSERT_NE(nullptr, el);
209 EXPECT_EQ(std::u16string(u"com.google.android.Receiver"), attr->value);
210 }
211
212 TEST_F(ManifestFixerTest, RenameManifestInstrumentationPackageAndFullyQualifyTarget) {
213 ManifestFixerOptions options;
214 options.renameInstrumentationTargetPackage = std::u16string(u"com.android");
215
216 std::unique_ptr<xml::XmlResource> doc = verifyWithOptions(R"EOF(
217 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
218 package="android">
219 <instrumentation android:targetPackage="android" />
220 </manifest>)EOF", options);
221 ASSERT_NE(nullptr, doc);
222
223 xml::Element* manifestEl = xml::findRootElement(doc.get());
224 ASSERT_NE(nullptr, manifestEl);
225
226 xml::Element* instrumentationEl = manifestEl->findChild({}, u"instrumentation");
227 ASSERT_NE(nullptr, instrumentationEl);
228
229 xml::Attribute* attr = instrumentationEl->findAttribute(xml::kSchemaAndroid, u"targetPackage");
230 ASSERT_NE(nullptr, attr);
231 EXPECT_EQ(std::u16string(u"com.android"), attr->value);
232 }
233
234 TEST_F(ManifestFixerTest, UseDefaultVersionNameAndCode) {
235 ManifestFixerOptions options;
236 options.versionNameDefault = std::u16string(u"Beta");
237 options.versionCodeDefault = std::u16string(u"0x10000000");
238
239 std::unique_ptr<xml::XmlResource> doc = verifyWithOptions(R"EOF(
240 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
241 package="android" />)EOF", options);
242 ASSERT_NE(nullptr, doc);
243
244 xml::Element* manifestEl = xml::findRootElement(doc.get());
245 ASSERT_NE(nullptr, manifestEl);
246
247 xml::Attribute* attr = manifestEl->findAttribute(xml::kSchemaAndroid, u"versionName");
248 ASSERT_NE(nullptr, attr);
249 EXPECT_EQ(std::u16string(u"Beta"), attr->value);
250
251 attr = manifestEl->findAttribute(xml::kSchemaAndroid, u"versionCode");
252 ASSERT_NE(nullptr, attr);
253 EXPECT_EQ(std::u16string(u"0x10000000"), attr->value);
254 }
255
256 } // namespace aapt
257