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
19 #include "test/Test.h"
20
21 using ::android::StringPiece;
22 using ::testing::Eq;
23 using ::testing::Gt;
24 using ::testing::IsNull;
25 using ::testing::Ne;
26 using ::testing::NotNull;
27 using ::testing::StrEq;
28
29 namespace aapt {
30
31 struct ManifestFixerTest : public ::testing::Test {
32 std::unique_ptr<IAaptContext> mContext;
33
SetUpaapt::ManifestFixerTest34 void SetUp() override {
35 mContext =
36 test::ContextBuilder()
37 .SetCompilationPackage("android")
38 .SetPackageId(0x01)
39 .SetNameManglerPolicy(NameManglerPolicy{"android"})
40 .AddSymbolSource(
41 test::StaticSymbolSourceBuilder()
42 .AddSymbol(
43 "android:attr/package", ResourceId(0x01010000),
44 test::AttributeBuilder()
45 .SetTypeMask(android::ResTable_map::TYPE_STRING)
46 .Build())
47 .AddSymbol(
48 "android:attr/minSdkVersion", ResourceId(0x01010001),
49 test::AttributeBuilder()
50 .SetTypeMask(android::ResTable_map::TYPE_STRING |
51 android::ResTable_map::TYPE_INTEGER)
52 .Build())
53 .AddSymbol(
54 "android:attr/targetSdkVersion", ResourceId(0x01010002),
55 test::AttributeBuilder()
56 .SetTypeMask(android::ResTable_map::TYPE_STRING |
57 android::ResTable_map::TYPE_INTEGER)
58 .Build())
59 .AddSymbol("android:string/str", ResourceId(0x01060000))
60 .Build())
61 .Build();
62 }
63
Verifyaapt::ManifestFixerTest64 std::unique_ptr<xml::XmlResource> Verify(StringPiece str) {
65 return VerifyWithOptions(str, {});
66 }
67
VerifyWithOptionsaapt::ManifestFixerTest68 std::unique_ptr<xml::XmlResource> VerifyWithOptions(StringPiece str,
69 const ManifestFixerOptions& options) {
70 std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(str);
71 ManifestFixer fixer(options);
72 if (fixer.Consume(mContext.get(), doc.get())) {
73 return doc;
74 }
75 return {};
76 }
77 };
78
TEST_F(ManifestFixerTest,EnsureManifestIsRootTag)79 TEST_F(ManifestFixerTest, EnsureManifestIsRootTag) {
80 EXPECT_THAT(Verify("<other-tag />"), IsNull());
81 EXPECT_THAT(Verify("<ns:manifest xmlns:ns=\"com\" />"), IsNull());
82 EXPECT_THAT(Verify("<manifest package=\"android\"></manifest>"), NotNull());
83 }
84
TEST_F(ManifestFixerTest,EnsureManifestHasPackage)85 TEST_F(ManifestFixerTest, EnsureManifestHasPackage) {
86 EXPECT_THAT(Verify("<manifest package=\"android\" />"), NotNull());
87 EXPECT_THAT(Verify("<manifest package=\"com.android\" />"), NotNull());
88 EXPECT_THAT(Verify("<manifest package=\"com.android.google\" />"), NotNull());
89 EXPECT_THAT(Verify("<manifest package=\"com.android.google.Class$1\" />"), IsNull());
90 EXPECT_THAT(Verify("<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" "
91 "android:package=\"com.android\" />"),
92 IsNull());
93 EXPECT_THAT(Verify("<manifest package=\"@string/str\" />"), IsNull());
94 }
95
TEST_F(ManifestFixerTest,AllowMetaData)96 TEST_F(ManifestFixerTest, AllowMetaData) {
97 auto doc = Verify(R"EOF(
98 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
99 package="android">
100 <meta-data />
101 <application>
102 <meta-data />
103 <activity android:name=".Hi"><meta-data /></activity>
104 <activity-alias android:name=".Ho"><meta-data /></activity-alias>
105 <receiver android:name=".OffTo"><meta-data /></receiver>
106 <provider android:name=".Work"><meta-data /></provider>
107 <service android:name=".We"><meta-data /></service>
108 </application>
109 <instrumentation android:name=".Go"><meta-data /></instrumentation>
110 </manifest>)EOF");
111 ASSERT_THAT(doc, NotNull());
112 }
113
114 TEST_F(ManifestFixerTest, UseDefaultSdkVersionsIfNonePresent) {
115 ManifestFixerOptions options;
116 options.min_sdk_version_default = std::string("8");
117 options.target_sdk_version_default = std::string("22");
118
119 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
120 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
121 package="android">
122 <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="21" />
123 </manifest>)EOF",
124 options);
125 ASSERT_THAT(doc, NotNull());
126
127 xml::Element* el;
128 xml::Attribute* attr;
129
130 el = doc->root.get();
131 ASSERT_THAT(el, NotNull());
132 el = el->FindChild({}, "uses-sdk");
133 ASSERT_THAT(el, NotNull());
134 attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion");
135 ASSERT_THAT(attr, NotNull());
136 EXPECT_THAT(attr->value, StrEq("7"));
137 attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion");
138 ASSERT_THAT(attr, NotNull());
139 EXPECT_THAT(attr->value, StrEq("21"));
140
141 doc = VerifyWithOptions(R"EOF(
142 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
143 package="android">
144 <uses-sdk android:targetSdkVersion="21" />
145 </manifest>)EOF",
146 options);
147 ASSERT_THAT(doc, NotNull());
148
149 el = doc->root.get();
150 ASSERT_THAT(el, NotNull());
151 el = el->FindChild({}, "uses-sdk");
152 ASSERT_THAT(el, NotNull());
153 attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion");
154 ASSERT_THAT(attr, NotNull());
155 EXPECT_THAT(attr->value, StrEq("8"));
156 attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion");
157 ASSERT_THAT(attr, NotNull());
158 EXPECT_THAT(attr->value, StrEq("21"));
159
160 doc = VerifyWithOptions(R"EOF(
161 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
162 package="android">
163 <uses-sdk />
164 </manifest>)EOF",
165 options);
166 ASSERT_THAT(doc, NotNull());
167
168 el = doc->root.get();
169 ASSERT_THAT(el, NotNull());
170 el = el->FindChild({}, "uses-sdk");
171 ASSERT_THAT(el, NotNull());
172 attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion");
173 ASSERT_THAT(attr, NotNull());
174 EXPECT_THAT(attr->value, StrEq("8"));
175 attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion");
176 ASSERT_THAT(attr, NotNull());
177 EXPECT_THAT(attr->value, StrEq("22"));
178
179 doc = VerifyWithOptions(R"EOF(
180 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
181 package="android" />)EOF",
182 options);
183 ASSERT_THAT(doc, NotNull());
184
185 el = doc->root.get();
186 ASSERT_THAT(el, NotNull());
187 el = el->FindChild({}, "uses-sdk");
188 ASSERT_THAT(el, NotNull());
189 attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion");
190 ASSERT_THAT(attr, NotNull());
191 EXPECT_THAT(attr->value, StrEq("8"));
192 attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion");
193 ASSERT_THAT(attr, NotNull());
194 EXPECT_THAT(attr->value, StrEq("22"));
195 }
196
197 TEST_F(ManifestFixerTest, UsesSdkMustComeBeforeApplication) {
198 ManifestFixerOptions options;
199 options.min_sdk_version_default = std::string("8");
200 options.target_sdk_version_default = std::string("22");
201 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
202 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
203 package="android">
204 <application android:name=".MainApplication" />
205 </manifest>)EOF",
206 options);
207 ASSERT_THAT(doc, NotNull());
208
209 xml::Element* manifest_el = doc->root.get();
210 ASSERT_THAT(manifest_el, NotNull());
211 ASSERT_EQ("manifest", manifest_el->name);
212
213 xml::Element* application_el = manifest_el->FindChild("", "application");
214 ASSERT_THAT(application_el, NotNull());
215
216 xml::Element* uses_sdk_el = manifest_el->FindChild("", "uses-sdk");
217 ASSERT_THAT(uses_sdk_el, NotNull());
218
219 // Check that the uses_sdk_el comes before application_el in the children
220 // vector.
221 // Since there are no namespaces here, these children are direct descendants
222 // of manifest.
223 auto uses_sdk_iter =
224 std::find_if(manifest_el->children.begin(), manifest_el->children.end(),
225 [&](const std::unique_ptr<xml::Node>& child) {
226 return child.get() == uses_sdk_el;
227 });
228
229 auto application_iter =
230 std::find_if(manifest_el->children.begin(), manifest_el->children.end(),
231 [&](const std::unique_ptr<xml::Node>& child) {
232 return child.get() == application_el;
233 });
234
235 ASSERT_THAT(uses_sdk_iter, Ne(manifest_el->children.end()));
236 ASSERT_THAT(application_iter, Ne(manifest_el->children.end()));
237
238 // The distance should be positive, meaning uses_sdk_iter comes before
239 // application_iter.
240 EXPECT_THAT(std::distance(uses_sdk_iter, application_iter), Gt(0));
241 }
242
243 TEST_F(ManifestFixerTest, RenameManifestPackageAndFullyQualifyClasses) {
244 ManifestFixerOptions options;
245 options.rename_manifest_package = std::string("com.android");
246
247 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
248 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
249 package="android">
250 <uses-split android:name="feature_a" />
251 <application android:name=".MainApplication" text="hello">
252 <activity android:name=".activity.Start" />
253 <receiver android:name="com.google.android.Receiver" />
254 </application>
255 </manifest>)EOF",
256 options);
257 ASSERT_THAT(doc, NotNull());
258
259 xml::Element* manifest_el = doc->root.get();
260 ASSERT_THAT(manifest_el, NotNull());
261
262 xml::Attribute* attr = nullptr;
263
264 attr = manifest_el->FindAttribute({}, "package");
265 ASSERT_THAT(attr, NotNull());
266 EXPECT_THAT(attr->value, StrEq("com.android"));
267
268 xml::Element* uses_split_el = manifest_el->FindChild({}, "uses-split");
269 ASSERT_THAT(uses_split_el, NotNull());
270 attr = uses_split_el->FindAttribute(xml::kSchemaAndroid, "name");
271 ASSERT_THAT(attr, NotNull());
272 // This should NOT have been affected.
273 EXPECT_THAT(attr->value, StrEq("feature_a"));
274
275 xml::Element* application_el = manifest_el->FindChild({}, "application");
276 ASSERT_THAT(application_el, NotNull());
277
278 attr = application_el->FindAttribute(xml::kSchemaAndroid, "name");
279 ASSERT_THAT(attr, NotNull());
280 EXPECT_THAT(attr->value, StrEq("android.MainApplication"));
281
282 attr = application_el->FindAttribute({}, "text");
283 ASSERT_THAT(attr, NotNull());
284 EXPECT_THAT(attr->value, StrEq("hello"));
285
286 xml::Element* el;
287 el = application_el->FindChild({}, "activity");
288 ASSERT_THAT(el, NotNull());
289
290 attr = el->FindAttribute(xml::kSchemaAndroid, "name");
291 ASSERT_THAT(el, NotNull());
292 EXPECT_THAT(attr->value, StrEq("android.activity.Start"));
293
294 el = application_el->FindChild({}, "receiver");
295 ASSERT_THAT(el, NotNull());
296
297 attr = el->FindAttribute(xml::kSchemaAndroid, "name");
298 ASSERT_THAT(el, NotNull());
299 EXPECT_THAT(attr->value, StrEq("com.google.android.Receiver"));
300 }
301
302 TEST_F(ManifestFixerTest,
303 RenameManifestInstrumentationPackageAndFullyQualifyTarget) {
304 ManifestFixerOptions options;
305 options.rename_instrumentation_target_package = std::string("com.android");
306
307 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
308 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
309 package="android">
310 <instrumentation android:name=".TestRunner" android:targetPackage="android" />
311 </manifest>)EOF",
312 options);
313 ASSERT_THAT(doc, NotNull());
314
315 xml::Element* manifest_el = doc->root.get();
316 ASSERT_THAT(manifest_el, NotNull());
317
318 xml::Element* instrumentation_el =
319 manifest_el->FindChild({}, "instrumentation");
320 ASSERT_THAT(instrumentation_el, NotNull());
321
322 xml::Attribute* attr =
323 instrumentation_el->FindAttribute(xml::kSchemaAndroid, "targetPackage");
324 ASSERT_THAT(attr, NotNull());
325 EXPECT_THAT(attr->value, StrEq("com.android"));
326 }
327
328 TEST_F(ManifestFixerTest,
329 RenameManifestOverlayPackageAndFullyQualifyTarget) {
330 ManifestFixerOptions options;
331 options.rename_overlay_target_package = std::string("com.android");
332
333 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
334 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
335 package="android">
336 <overlay android:targetName="Customization" android:targetPackage="android" />
337 </manifest>)EOF",
338 options);
339 ASSERT_THAT(doc, NotNull());
340
341 xml::Element* manifest_el = doc->root.get();
342 ASSERT_THAT(manifest_el, NotNull());
343
344 xml::Element* overlay_el =
345 manifest_el->FindChild({}, "overlay");
346 ASSERT_THAT(overlay_el, NotNull());
347
348 xml::Attribute* attr =
349 overlay_el->FindAttribute(xml::kSchemaAndroid, "targetPackage");
350 ASSERT_THAT(attr, NotNull());
351 EXPECT_THAT(attr->value, StrEq("com.android"));
352 }
353
354 TEST_F(ManifestFixerTest, AddOverlayCategory) {
355 ManifestFixerOptions options;
356 options.rename_overlay_category = std::string("category");
357
358 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
359 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
360 package="android">
361 <overlay android:targetName="Customization" android:targetPackage="android" />
362 </manifest>)EOF",
363 options);
364 ASSERT_THAT(doc, NotNull());
365
366 xml::Element* manifest_el = doc->root.get();
367 ASSERT_THAT(manifest_el, NotNull());
368
369 xml::Element* overlay_el = manifest_el->FindChild({}, "overlay");
370 ASSERT_THAT(overlay_el, NotNull());
371
372 xml::Attribute* attr = overlay_el->FindAttribute(xml::kSchemaAndroid, "category");
373 ASSERT_THAT(attr, NotNull());
374 EXPECT_THAT(attr->value, StrEq("category"));
375 }
376
377 TEST_F(ManifestFixerTest, OverrideOverlayCategory) {
378 ManifestFixerOptions options;
379 options.rename_overlay_category = std::string("category");
380
381 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
382 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
383 package="android">
384 <overlay android:targetName="Customization"
385 android:targetPackage="android"
386 android:category="yrogetac"/>
387 </manifest>)EOF",
388 options);
389 ASSERT_THAT(doc, NotNull());
390
391 xml::Element* manifest_el = doc->root.get();
392 ASSERT_THAT(manifest_el, NotNull());
393
394 xml::Element* overlay_el = manifest_el->FindChild({}, "overlay");
395 ASSERT_THAT(overlay_el, NotNull());
396
397 xml::Attribute* attr = overlay_el->FindAttribute(xml::kSchemaAndroid, "category");
398 ASSERT_THAT(attr, NotNull());
399 EXPECT_THAT(attr->value, StrEq("category"));
400 }
401
402 TEST_F(ManifestFixerTest, UseDefaultVersionNameAndCode) {
403 ManifestFixerOptions options;
404 options.version_name_default = std::string("Beta");
405 options.version_code_default = std::string("0x10000000");
406 options.version_code_major_default = std::string("0x20000000");
407
408 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
409 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
410 package="android" />)EOF",
411 options);
412 ASSERT_THAT(doc, NotNull());
413
414 xml::Element* manifest_el = doc->root.get();
415 ASSERT_THAT(manifest_el, NotNull());
416
417 xml::Attribute* attr =
418 manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
419 ASSERT_THAT(attr, NotNull());
420 EXPECT_THAT(attr->value, StrEq("Beta"));
421
422 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
423 ASSERT_THAT(attr, NotNull());
424 EXPECT_THAT(attr->value, StrEq("0x10000000"));
425
426 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
427 ASSERT_THAT(attr, NotNull());
428 EXPECT_THAT(attr->value, StrEq("0x20000000"));
429 }
430
431 TEST_F(ManifestFixerTest, DontUseDefaultVersionNameAndCode) {
432 ManifestFixerOptions options;
433 options.version_name_default = std::string("Beta");
434 options.version_code_default = std::string("0x10000000");
435 options.version_code_major_default = std::string("0x20000000");
436
437 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
438 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
439 package="android"
440 android:versionCode="0x00000001"
441 android:versionCodeMajor="0x00000002"
442 android:versionName="Alpha" />)EOF",
443 options);
444 ASSERT_THAT(doc, NotNull());
445
446 xml::Element* manifest_el = doc->root.get();
447 ASSERT_THAT(manifest_el, NotNull());
448
449 xml::Attribute* attr =
450 manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
451 ASSERT_THAT(attr, NotNull());
452 EXPECT_THAT(attr->value, StrEq("Alpha"));
453
454 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
455 ASSERT_THAT(attr, NotNull());
456 EXPECT_THAT(attr->value, StrEq("0x00000001"));
457
458 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
459 ASSERT_THAT(attr, NotNull());
460 EXPECT_THAT(attr->value, StrEq("0x00000002"));
461 }
462
463 TEST_F(ManifestFixerTest, ReplaceVersionNameAndCode) {
464 ManifestFixerOptions options;
465 options.replace_version = true;
466 options.version_name_default = std::string("Beta");
467 options.version_code_default = std::string("0x10000000");
468 options.version_code_major_default = std::string("0x20000000");
469
470 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
471 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
472 package="android"
473 android:versionCode="0x00000001"
474 android:versionCodeMajor="0x00000002"
475 android:versionName="Alpha" />)EOF",
476 options);
477 ASSERT_THAT(doc, NotNull());
478
479 xml::Element* manifest_el = doc->root.get();
480 ASSERT_THAT(manifest_el, NotNull());
481
482 xml::Attribute* attr =
483 manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
484 ASSERT_THAT(attr, NotNull());
485 EXPECT_THAT(attr->value, StrEq("Beta"));
486
487 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
488 ASSERT_THAT(attr, NotNull());
489 EXPECT_THAT(attr->value, StrEq("0x10000000"));
490
491 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
492 ASSERT_THAT(attr, NotNull());
493 EXPECT_THAT(attr->value, StrEq("0x20000000"));
494 }
495
496 TEST_F(ManifestFixerTest, UseDefaultRevisionCode) {
497 ManifestFixerOptions options;
498 options.revision_code_default = std::string("0x10000000");
499
500 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
501 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
502 package="android"
503 android:versionCode="0x00000001" />)EOF",
504 options);
505 ASSERT_THAT(doc, NotNull());
506
507 xml::Element* manifest_el = doc->root.get();
508 ASSERT_THAT(manifest_el, NotNull());
509
510 xml::Attribute* attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "revisionCode");
511 ASSERT_THAT(attr, NotNull());
512 EXPECT_THAT(attr->value, StrEq("0x10000000"));
513 }
514
515 TEST_F(ManifestFixerTest, DontUseDefaultRevisionCode) {
516 ManifestFixerOptions options;
517 options.revision_code_default = std::string("0x10000000");
518
519 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
520 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
521 package="android"
522 android:versionCode="0x00000001"
523 android:revisionCode="0x00000002" />)EOF",
524 options);
525 ASSERT_THAT(doc, NotNull());
526
527 xml::Element* manifest_el = doc->root.get();
528 ASSERT_THAT(manifest_el, NotNull());
529
530 xml::Attribute* attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "revisionCode");
531 ASSERT_THAT(attr, NotNull());
532 EXPECT_THAT(attr->value, StrEq("0x00000002"));
533 }
534
535 TEST_F(ManifestFixerTest, ReplaceRevisionCode) {
536 ManifestFixerOptions options;
537 options.replace_version = true;
538 options.revision_code_default = std::string("0x10000000");
539
540 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
541 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
542 package="android"
543 android:versionCode="0x00000001"
544 android:revisionCode="0x00000002" />)EOF",
545 options);
546 ASSERT_THAT(doc, NotNull());
547
548 xml::Element* manifest_el = doc->root.get();
549 ASSERT_THAT(manifest_el, NotNull());
550
551 xml::Attribute* attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "revisionCode");
552 ASSERT_THAT(attr, NotNull());
553 EXPECT_THAT(attr->value, StrEq("0x10000000"));
554 }
555
556 TEST_F(ManifestFixerTest, ReplaceVersionName) {
557 ManifestFixerOptions options;
558 options.replace_version = true;
559 options.version_name_default = std::string("Beta");
560
561
562 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
563 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
564 package="android"
565 android:versionCode="0x00000001"
566 android:versionCodeMajor="0x00000002"
567 android:versionName="Alpha" />)EOF",
568 options);
569 ASSERT_THAT(doc, NotNull());
570
571 xml::Element* manifest_el = doc->root.get();
572 ASSERT_THAT(manifest_el, NotNull());
573
574 xml::Attribute* attr =
575 manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
576 ASSERT_THAT(attr, NotNull());
577 EXPECT_THAT(attr->value, StrEq("Beta"));
578
579 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
580 ASSERT_THAT(attr, NotNull());
581 EXPECT_THAT(attr->value, StrEq("0x00000001"));
582
583 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
584 ASSERT_THAT(attr, NotNull());
585 EXPECT_THAT(attr->value, StrEq("0x00000002"));
586 }
587
588 TEST_F(ManifestFixerTest, ReplaceVersionCode) {
589 ManifestFixerOptions options;
590 options.replace_version = true;
591 options.version_code_default = std::string("0x10000000");
592
593 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
594 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
595 package="android"
596 android:versionCode="0x00000001"
597 android:versionCodeMajor="0x00000002"
598 android:versionName="Alpha" />)EOF",
599 options);
600 ASSERT_THAT(doc, NotNull());
601
602 xml::Element* manifest_el = doc->root.get();
603 ASSERT_THAT(manifest_el, NotNull());
604
605 xml::Attribute* attr =
606 manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
607 ASSERT_THAT(attr, NotNull());
608 EXPECT_THAT(attr->value, StrEq("Alpha"));
609
610 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
611 ASSERT_THAT(attr, NotNull());
612 EXPECT_THAT(attr->value, StrEq("0x10000000"));
613
614 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
615 ASSERT_THAT(attr, NotNull());
616 EXPECT_THAT(attr->value, StrEq("0x00000002"));
617 }
618
619 TEST_F(ManifestFixerTest, ReplaceVersionCodeMajor) {
620 ManifestFixerOptions options;
621 options.replace_version = true;
622 options.version_code_major_default = std::string("0x20000000");
623
624 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
625 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
626 package="android"
627 android:versionCode="0x00000001"
628 android:versionCodeMajor="0x00000002"
629 android:versionName="Alpha" />)EOF",
630 options);
631 ASSERT_THAT(doc, NotNull());
632
633 xml::Element* manifest_el = doc->root.get();
634 ASSERT_THAT(manifest_el, NotNull());
635
636 xml::Attribute* attr =
637 manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
638 ASSERT_THAT(attr, NotNull());
639 EXPECT_THAT(attr->value, StrEq("Alpha"));
640
641 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
642 ASSERT_THAT(attr, NotNull());
643 EXPECT_THAT(attr->value, StrEq("0x00000001"));
644
645 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
646 ASSERT_THAT(attr, NotNull());
647 EXPECT_THAT(attr->value, StrEq("0x20000000"));
648 }
649
650 TEST_F(ManifestFixerTest, DontReplaceVersionNameOrCode) {
651 ManifestFixerOptions options;
652 options.replace_version = true;
653
654 std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
655 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
656 package="android"
657 android:versionCode="0x00000001"
658 android:versionCodeMajor="0x00000002"
659 android:versionName="Alpha" />)EOF",
660 options);
661 ASSERT_THAT(doc, NotNull());
662
663 xml::Element* manifest_el = doc->root.get();
664 ASSERT_THAT(manifest_el, NotNull());
665
666 xml::Attribute* attr =
667 manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
668 ASSERT_THAT(attr, NotNull());
669 EXPECT_THAT(attr->value, StrEq("Alpha"));
670
671 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
672 ASSERT_THAT(attr, NotNull());
673 EXPECT_THAT(attr->value, StrEq("0x00000001"));
674
675 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
676 ASSERT_THAT(attr, NotNull());
677 EXPECT_THAT(attr->value, StrEq("0x00000002"));
678 }
679
680 TEST_F(ManifestFixerTest, EnsureManifestAttributesAreTyped) {
681 EXPECT_THAT(Verify("<manifest package=\"android\" coreApp=\"hello\" />"), IsNull());
682 EXPECT_THAT(Verify("<manifest package=\"android\" coreApp=\"1dp\" />"), IsNull());
683
684 std::unique_ptr<xml::XmlResource> doc =
685 Verify("<manifest package=\"android\" coreApp=\"true\" />");
686 ASSERT_THAT(doc, NotNull());
687
688 xml::Element* el = doc->root.get();
689 ASSERT_THAT(el, NotNull());
690
691 EXPECT_THAT(el->name, StrEq("manifest"));
692
693 xml::Attribute* attr = el->FindAttribute("", "coreApp");
694 ASSERT_THAT(attr, NotNull());
695
696 EXPECT_THAT(attr->compiled_value, NotNull());
697 EXPECT_THAT(ValueCast<BinaryPrimitive>(attr->compiled_value.get()), NotNull());
698 }
699
TEST_F(ManifestFixerTest,UsesFeatureMustHaveNameOrGlEsVersion)700 TEST_F(ManifestFixerTest, UsesFeatureMustHaveNameOrGlEsVersion) {
701 std::string input = R"EOF(
702 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
703 package="android">
704 <uses-feature android:name="feature" />
705 <uses-feature android:glEsVersion="1" />
706 <feature-group />
707 <feature-group>
708 <uses-feature android:name="feature_in_group" />
709 <uses-feature android:glEsVersion="2" />
710 </feature-group>
711 </manifest>)EOF";
712 EXPECT_THAT(Verify(input), NotNull());
713
714 input = R"EOF(
715 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
716 package="android">
717 <uses-feature android:name="feature" android:glEsVersion="1" />
718 </manifest>)EOF";
719 EXPECT_THAT(Verify(input), IsNull());
720
721 input = R"EOF(
722 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
723 package="android">
724 <uses-feature />
725 </manifest>)EOF";
726 EXPECT_THAT(Verify(input), IsNull());
727
728 input = R"EOF(
729 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
730 package="android">
731 <feature-group>
732 <uses-feature android:name="feature" android:glEsVersion="1" />
733 </feature-group>
734 </manifest>)EOF";
735 EXPECT_THAT(Verify(input), IsNull());
736
737 input = R"EOF(
738 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
739 package="android">
740 <feature-group>
741 <uses-feature />
742 </feature-group>
743 </manifest>)EOF";
744 EXPECT_THAT(Verify(input), IsNull());
745 }
746
747 TEST_F(ManifestFixerTest, ApplicationInjectDebuggable) {
748 ManifestFixerOptions options;
749 options.debug_mode = true;
750
751 std::string no_d = R"(
752 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
753 package="android">
754 <application>
755 </application>
756 </manifest>)";
757
758 std::string false_d = R"(
759 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
760 package="android">
761 <application android:debuggable="false">
762 </application>
763 </manifest>)";
764
765 std::string true_d = R"(
766 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
767 package="android">
768 <application android:debuggable="true">
769 </application>
770 </manifest>)";
771
772 // Inject the debuggable attribute when the attribute is not present and the
773 // flag is present
774 std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(no_d, options);
775 EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
776 {}, "application", xml::kSchemaAndroid, "debuggable", "true"), NotNull());
777
778 // Set the debuggable flag to true if the attribute is false and the flag is
779 // present
780 manifest = VerifyWithOptions(false_d, options);
781 EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
782 {}, "application", xml::kSchemaAndroid, "debuggable", "true"), NotNull());
783
784 // Keep debuggable flag true if the attribute is true and the flag is present
785 manifest = VerifyWithOptions(true_d, options);
786 EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
787 {}, "application", xml::kSchemaAndroid, "debuggable", "true"), NotNull());
788
789 // Do not inject the debuggable attribute when the attribute is not present
790 // and the flag is not present
791 manifest = Verify(no_d);
792 EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
793 {}, "application", xml::kSchemaAndroid, "debuggable", "true"), IsNull());
794
795 // Do not set the debuggable flag to true if the attribute is false and the
796 // flag is not present
797 manifest = Verify(false_d);
798 EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
799 {}, "application", xml::kSchemaAndroid, "debuggable", "true"), IsNull());
800
801 // Keep debuggable flag true if the attribute is true and the flag is not
802 // present
803 manifest = Verify(true_d);
804 EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
805 {}, "application", xml::kSchemaAndroid, "debuggable", "true"), NotNull());
806 }
807
808 TEST_F(ManifestFixerTest, ApplicationProfileable) {
809 std::string shell = R"(
810 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
811 package="android">
812 <application>
813 <profileable android:shell="true"/>
814 </application>
815 </manifest>)";
816 EXPECT_THAT(Verify(shell), NotNull());
817 std::string noshell = R"(
818 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
819 package="android">
820 <application>
821 <profileable/>
822 </application>
823 </manifest>)";
824 EXPECT_THAT(Verify(noshell), NotNull());
825 }
826
827 TEST_F(ManifestFixerTest, IgnoreNamespacedElements) {
828 std::string input = R"EOF(
829 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
830 package="android">
831 <special:tag whoo="true" xmlns:special="http://google.com" />
832 </manifest>)EOF";
833 EXPECT_THAT(Verify(input), NotNull());
834 }
835
836 TEST_F(ManifestFixerTest, DoNotIgnoreNonNamespacedElements) {
837 std::string input = R"EOF(
838 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
839 package="android">
840 <tag whoo="true" />
841 </manifest>)EOF";
842 EXPECT_THAT(Verify(input), IsNull());
843 }
844
845 TEST_F(ManifestFixerTest, SupportKeySets) {
846 std::string input = R"(
847 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
848 package="android">
849 <key-sets>
850 <key-set android:name="old-set">
851 <public-key android:name="old-key" android:value="some+old+key" />
852 </key-set>
853 <key-set android:name="new-set">
854 <public-key android:name="new-key" android:value="some+new+key" />
855 </key-set>
856 <upgrade-key-set android:name="old-set" />
857 <upgrade-key-set android:name="new-set" />
858 </key-sets>
859 </manifest>)";
860 EXPECT_THAT(Verify(input), NotNull());
861 }
862
863 TEST_F(ManifestFixerTest, InsertCompileSdkVersions) {
864 std::string input = R"(<manifest package="com.pkg" />)";
865 ManifestFixerOptions options;
866 options.compile_sdk_version = {"28"};
867 options.compile_sdk_version_codename = {"P"};
868
869 std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
870 ASSERT_THAT(manifest, NotNull());
871
872 // There should be a declaration of kSchemaAndroid, even when the input
873 // didn't have one.
874 EXPECT_EQ(manifest->root->namespace_decls.size(), 1);
875 EXPECT_EQ(manifest->root->namespace_decls[0].prefix, "android");
876 EXPECT_EQ(manifest->root->namespace_decls[0].uri, xml::kSchemaAndroid);
877
878 xml::Attribute* attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersion");
879 ASSERT_THAT(attr, NotNull());
880 EXPECT_THAT(attr->value, StrEq("28"));
881
882 attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
883 ASSERT_THAT(attr, NotNull());
884 EXPECT_THAT(attr->value, StrEq("P"));
885
886 attr = manifest->root->FindAttribute("", "platformBuildVersionCode");
887 ASSERT_THAT(attr, NotNull());
888 EXPECT_THAT(attr->value, StrEq("28"));
889
890 attr = manifest->root->FindAttribute("", "platformBuildVersionName");
891 ASSERT_THAT(attr, NotNull());
892 EXPECT_THAT(attr->value, StrEq("P"));
893 }
894
895 TEST_F(ManifestFixerTest, DoNotInsertCompileSdkVersions) {
896 std::string input = R"(<manifest package="com.pkg" />)";
897 ManifestFixerOptions options;
898 options.no_compile_sdk_metadata = true;
899 options.compile_sdk_version = {"28"};
900 options.compile_sdk_version_codename = {"P"};
901
902 std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
903 ASSERT_THAT(manifest, NotNull());
904
905 // There should be a declaration of kSchemaAndroid, even when the input
906 // didn't have one.
907 EXPECT_EQ(manifest->root->namespace_decls.size(), 1);
908 EXPECT_EQ(manifest->root->namespace_decls[0].prefix, "android");
909 EXPECT_EQ(manifest->root->namespace_decls[0].uri, xml::kSchemaAndroid);
910
911 xml::Attribute* attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersion");
912 ASSERT_THAT(attr, IsNull());
913
914 attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
915 ASSERT_THAT(attr, IsNull());
916
917 attr = manifest->root->FindAttribute("", "platformBuildVersionCode");
918 ASSERT_THAT(attr, IsNull());
919
920 attr = manifest->root->FindAttribute("", "platformBuildVersionName");
921 ASSERT_THAT(attr, IsNull());
922 }
923
924 TEST_F(ManifestFixerTest, OverrideCompileSdkVersions) {
925 std::string input = R"(
926 <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"
927 compileSdkVersion="27" compileSdkVersionCodename="O"
928 platformBuildVersionCode="27" platformBuildVersionName="O"/>)";
929 ManifestFixerOptions options;
930 options.compile_sdk_version = {"28"};
931 options.compile_sdk_version_codename = {"P"};
932
933 std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
934 ASSERT_THAT(manifest, NotNull());
935
936 xml::Attribute* attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersion");
937 ASSERT_THAT(attr, NotNull());
938 EXPECT_THAT(attr->value, StrEq("28"));
939
940 attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
941 ASSERT_THAT(attr, NotNull());
942 EXPECT_THAT(attr->value, StrEq("P"));
943
944 attr = manifest->root->FindAttribute("", "platformBuildVersionCode");
945 ASSERT_THAT(attr, NotNull());
946 EXPECT_THAT(attr->value, StrEq("28"));
947
948 attr = manifest->root->FindAttribute("", "platformBuildVersionName");
949 ASSERT_THAT(attr, NotNull());
950 EXPECT_THAT(attr->value, StrEq("P"));
951 }
952
953 TEST_F(ManifestFixerTest, AndroidPrefixAlreadyUsed) {
954 std::string input =
955 R"(<manifest package="com.pkg"
956 xmlns:android="http://schemas.android.com/apk/prv/res/android"
957 android:private_attr="foo" />)";
958 ManifestFixerOptions options;
959 options.compile_sdk_version = {"28"};
960 options.compile_sdk_version_codename = {"P"};
961
962 std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
963 ASSERT_THAT(manifest, NotNull());
964
965 // Make sure that we don't redefine "android".
966 EXPECT_EQ(manifest->root->namespace_decls.size(), 2);
967 EXPECT_EQ(manifest->root->namespace_decls[0].prefix, "android");
968 EXPECT_EQ(manifest->root->namespace_decls[0].uri,
969 "http://schemas.android.com/apk/prv/res/android");
970 EXPECT_EQ(manifest->root->namespace_decls[1].prefix, "android0");
971 EXPECT_EQ(manifest->root->namespace_decls[1].uri, xml::kSchemaAndroid);
972 }
973
TEST_F(ManifestFixerTest,UnexpectedElementsInManifest)974 TEST_F(ManifestFixerTest, UnexpectedElementsInManifest) {
975 std::string input = R"(
976 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
977 package="android">
978 <beep/>
979 </manifest>)";
980 ManifestFixerOptions options;
981 options.warn_validation = true;
982
983 // Unexpected element should result in a warning if the flag is set to 'true'.
984 std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
985 ASSERT_THAT(manifest, NotNull());
986
987 // Unexpected element should result in an error if the flag is set to 'false'.
988 options.warn_validation = false;
989 manifest = VerifyWithOptions(input, options);
990 ASSERT_THAT(manifest, IsNull());
991
992 // By default the flag should be set to 'false'.
993 manifest = Verify(input);
994 ASSERT_THAT(manifest, IsNull());
995 }
996
997 TEST_F(ManifestFixerTest, InsertFingerprintPrefixIfNotExist) {
998 std::string input = R"(
999 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1000 package="android">
1001 </manifest>)";
1002 ManifestFixerOptions options;
1003 options.fingerprint_prefixes = {"foo", "bar"};
1004
1005 std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
1006 ASSERT_THAT(manifest, NotNull());
1007 xml::Element* install_constraints = manifest->root.get()->FindChild({}, "install-constraints");
1008 ASSERT_THAT(install_constraints, NotNull());
1009 std::vector<xml::Element*> fingerprint_prefixes = install_constraints->GetChildElements();
1010 EXPECT_EQ(fingerprint_prefixes.size(), 2);
1011 xml::Attribute* attr;
1012 EXPECT_THAT(fingerprint_prefixes[0]->name, StrEq("fingerprint-prefix"));
1013 attr = fingerprint_prefixes[0]->FindAttribute(xml::kSchemaAndroid, "value");
1014 ASSERT_THAT(attr, NotNull());
1015 EXPECT_THAT(attr->value, StrEq("foo"));
1016 EXPECT_THAT(fingerprint_prefixes[1]->name, StrEq("fingerprint-prefix"));
1017 attr = fingerprint_prefixes[1]->FindAttribute(xml::kSchemaAndroid, "value");
1018 ASSERT_THAT(attr, NotNull());
1019 EXPECT_THAT(attr->value, StrEq("bar"));
1020 }
1021
1022 TEST_F(ManifestFixerTest, AppendFingerprintPrefixIfExists) {
1023 std::string input = R"(
1024 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1025 package="android">
1026 <install-constraints>
1027 <fingerprint-prefix android:value="foo" />
1028 </install-constraints>
1029 </manifest>)";
1030 ManifestFixerOptions options;
1031 options.fingerprint_prefixes = {"bar", "baz"};
1032
1033 std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
1034 ASSERT_THAT(manifest, NotNull());
1035 xml::Element* install_constraints = manifest->root.get()->FindChild({}, "install-constraints");
1036 ASSERT_THAT(install_constraints, NotNull());
1037 std::vector<xml::Element*> fingerprint_prefixes = install_constraints->GetChildElements();
1038 EXPECT_EQ(fingerprint_prefixes.size(), 3);
1039 xml::Attribute* attr;
1040 EXPECT_THAT(fingerprint_prefixes[0]->name, StrEq("fingerprint-prefix"));
1041 attr = fingerprint_prefixes[0]->FindAttribute(xml::kSchemaAndroid, "value");
1042 ASSERT_THAT(attr, NotNull());
1043 EXPECT_THAT(attr->value, StrEq("foo"));
1044 EXPECT_THAT(fingerprint_prefixes[1]->name, StrEq("fingerprint-prefix"));
1045 attr = fingerprint_prefixes[1]->FindAttribute(xml::kSchemaAndroid, "value");
1046 ASSERT_THAT(attr, NotNull());
1047 EXPECT_THAT(attr->value, StrEq("bar"));
1048 EXPECT_THAT(fingerprint_prefixes[2]->name, StrEq("fingerprint-prefix"));
1049 attr = fingerprint_prefixes[2]->FindAttribute(xml::kSchemaAndroid, "value");
1050 ASSERT_THAT(attr, NotNull());
1051 EXPECT_THAT(attr->value, StrEq("baz"));
1052 }
1053
1054 TEST_F(ManifestFixerTest, UsesLibraryMustHaveNonEmptyName) {
1055 std::string input = R"(
1056 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1057 package="android">
1058 <application>
1059 <uses-library android:name="" />
1060 </application>
1061 </manifest>)";
1062 EXPECT_THAT(Verify(input), IsNull());
1063
1064 input = R"(
1065 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1066 package="android">
1067 <application>
1068 <uses-library />
1069 </application>
1070 </manifest>)";
1071 EXPECT_THAT(Verify(input), IsNull());
1072
1073 input = R"(
1074 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1075 package="android">
1076 <application>
1077 <uses-library android:name="blahhh" />
1078 </application>
1079 </manifest>)";
1080 EXPECT_THAT(Verify(input), NotNull());
1081 }
1082
1083 TEST_F(ManifestFixerTest, ApplicationPropertyAttributeRequired) {
1084 std::string input = R"(
1085 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1086 package="android">
1087 <application>
1088 <property android:name="" />
1089 </application>
1090 </manifest>)";
1091 EXPECT_THAT(Verify(input), IsNull());
1092 }
1093
1094 TEST_F(ManifestFixerTest, ApplicationPropertyOnlyOneAttributeDefined) {
1095 std::string input = R"(
1096 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1097 package="android">
1098 <application>
1099 <property android:name="" android:value="" android:resource="" />
1100 </application>
1101 </manifest>)";
1102 EXPECT_THAT(Verify(input), IsNull());
1103
1104 input = R"(
1105 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1106 package="android">
1107 <application>
1108 <property android:name="" android:resource="" />
1109 </application>
1110 </manifest>)";
1111 EXPECT_THAT(Verify(input), NotNull());
1112
1113 input = R"(
1114 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1115 package="android">
1116 <application>
1117 <property android:name="" android:value="" />
1118 </application>
1119 </manifest>)";
1120 EXPECT_THAT(Verify(input), NotNull());
1121 }
1122
1123 TEST_F(ManifestFixerTest, ComponentPropertyOnlyOneAttributeDefined) {
1124 std::string input = R"(
1125 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1126 package="android">
1127 <application>
1128 <activity android:name=".MyActivity">
1129 <property android:name="" android:value="" android:resource="" />
1130 </activity>
1131 </application>
1132 </manifest>)";
1133 EXPECT_THAT(Verify(input), IsNull());
1134
1135 input = R"(
1136 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1137 package="android">
1138 <application>
1139 <activity android:name=".MyActivity">
1140 <property android:name="" android:value="" />
1141 </activity>
1142 </application>
1143 </manifest>)";
1144 EXPECT_THAT(Verify(input), NotNull());
1145
1146 input = R"(
1147 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1148 package="android">
1149 <application>
1150 <activity android:name=".MyActivity">
1151 <property android:name="" android:resource="" />
1152 </activity>
1153 </application>
1154 </manifest>)";
1155 EXPECT_THAT(Verify(input), NotNull());
1156 }
1157
1158 TEST_F(ManifestFixerTest, IntentFilterActionMustHaveNonEmptyName) {
1159 std::string input = R"(
1160 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1161 package="android">
1162 <application>
1163 <activity android:name=".MainActivity">
1164 <intent-filter>
1165 <action android:name="" />
1166 </intent-filter>
1167 </activity>
1168 </application>
1169 </manifest>)";
1170 EXPECT_THAT(Verify(input), IsNull());
1171
1172 input = R"(
1173 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1174 package="android">
1175 <application>
1176 <activity android:name=".MainActivity">
1177 <intent-filter>
1178 <action />
1179 </intent-filter>
1180 </activity>
1181 </application>
1182 </manifest>)";
1183 EXPECT_THAT(Verify(input), IsNull());
1184
1185 input = R"(
1186 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1187 package="android">
1188 <application>
1189 <activity android:name=".MainActivity">
1190 <intent-filter>
1191 <action android:name="android.intent.action.MAIN" />
1192 </intent-filter>
1193 </activity>
1194 </application>
1195 </manifest>)";
1196 EXPECT_THAT(Verify(input), NotNull());
1197 }
1198
1199 TEST_F(ManifestFixerTest, IntentFilterCategoryMustHaveNonEmptyName) {
1200 std::string input = R"(
1201 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1202 package="android">
1203 <application>
1204 <activity android:name=".MainActivity">
1205 <intent-filter>
1206 <category android:name="" />
1207 </intent-filter>
1208 </activity>
1209 </application>
1210 </manifest>)";
1211 EXPECT_THAT(Verify(input), IsNull());
1212
1213 input = R"(
1214 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1215 package="android">
1216 <application>
1217 <activity android:name=".MainActivity">
1218 <intent-filter>
1219 <category />
1220 </intent-filter>
1221 </activity>
1222 </application>
1223 </manifest>)";
1224 EXPECT_THAT(Verify(input), IsNull());
1225
1226 input = R"(
1227 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1228 package="android">
1229 <application>
1230 <activity android:name=".MainActivity">
1231 <intent-filter>
1232 <category android:name="android.intent.category.LAUNCHER" />
1233 </intent-filter>
1234 </activity>
1235 </application>
1236 </manifest>)";
1237 EXPECT_THAT(Verify(input), NotNull());
1238 }
1239
1240 TEST_F(ManifestFixerTest, IntentFilterPathMustStartWithLeadingSlashOnDeepLinks) {
1241 // No DeepLink.
1242 std::string input = R"(
1243 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1244 package="android">
1245 <application>
1246 <activity android:name=".MainActivity">
1247 <intent-filter>
1248 <data />
1249 </intent-filter>
1250 </activity>
1251 </application>
1252 </manifest>)";
1253 EXPECT_THAT(Verify(input), NotNull());
1254
1255 // No DeepLink, missing ACTION_VIEW.
1256 input = R"(
1257 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1258 package="android">
1259 <application>
1260 <activity android:name=".MainActivity">
1261 <intent-filter>
1262 <category android:name="android.intent.category.DEFAULT" />
1263 <category android:name="android.intent.category.BROWSABLE" />
1264 <data android:scheme="http"
1265 android:host="www.example.com"
1266 android:pathPrefix="pathPattern" />
1267 </intent-filter>
1268 </activity>
1269 </application>
1270 </manifest>)";
1271 EXPECT_THAT(Verify(input), NotNull());
1272
1273 // DeepLink, missing DEFAULT category while DEFAULT is recommended but not required.
1274 input = R"(
1275 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1276 package="android">
1277 <application>
1278 <activity android:name=".MainActivity">
1279 <intent-filter>
1280 <action android:name="android.intent.action.VIEW" />
1281 <category android:name="android.intent.category.BROWSABLE" />
1282 <data android:scheme="http"
1283 android:host="www.example.com"
1284 android:pathPrefix="pathPattern" />
1285 </intent-filter>
1286 </activity>
1287 </application>
1288 </manifest>)";
1289 EXPECT_THAT(Verify(input), IsNull());
1290
1291 // No DeepLink, missing BROWSABLE category.
1292 input = R"(
1293 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1294 package="android">
1295 <application>
1296 <activity android:name=".MainActivity">
1297 <intent-filter>
1298 <action android:name="android.intent.action.VIEW" />
1299 <category android:name="android.intent.category.DEFAULT" />
1300 <data android:scheme="http"
1301 android:host="www.example.com"
1302 android:pathPrefix="pathPattern" />
1303 </intent-filter>
1304 </activity>
1305 </application>
1306 </manifest>)";
1307 EXPECT_THAT(Verify(input), NotNull());
1308
1309 // No DeepLink, missing 'android:scheme' in <data> tag.
1310 input = R"(
1311 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1312 package="android">
1313 <application>
1314 <activity android:name=".MainActivity">
1315 <intent-filter>
1316 <action android:name="android.intent.action.VIEW" />
1317 <category android:name="android.intent.category.DEFAULT" />
1318 <category android:name="android.intent.category.BROWSABLE" />
1319 <data android:host="www.example.com"
1320 android:pathPrefix="pathPattern" />
1321 </intent-filter>
1322 </activity>
1323 </application>
1324 </manifest>)";
1325 EXPECT_THAT(Verify(input), NotNull());
1326
1327 // No DeepLink, <action> is ACTION_MAIN not ACTION_VIEW.
1328 input = R"(
1329 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1330 package="android">
1331 <application>
1332 <activity android:name=".MainActivity">
1333 <intent-filter>
1334 <action android:name="android.intent.action.MAIN" />
1335 <category android:name="android.intent.category.DEFAULT" />
1336 <category android:name="android.intent.category.BROWSABLE" />
1337 <data android:scheme="http"
1338 android:host="www.example.com"
1339 android:pathPrefix="pathPattern" />
1340 </intent-filter>
1341 </activity>
1342 </application>
1343 </manifest>)";
1344 EXPECT_THAT(Verify(input), NotNull());
1345
1346 // DeepLink with no leading slash in android:path.
1347 input = R"(
1348 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1349 package="android">
1350 <application>
1351 <activity android:name=".MainActivity">
1352 <intent-filter>
1353 <action android:name="android.intent.action.VIEW" />
1354 <category android:name="android.intent.category.DEFAULT" />
1355 <category android:name="android.intent.category.BROWSABLE" />
1356 <data android:scheme="http"
1357 android:host="www.example.com"
1358 android:path="path" />
1359 </intent-filter>
1360 </activity>
1361 </application>
1362 </manifest>)";
1363 EXPECT_THAT(Verify(input), IsNull());
1364
1365 // DeepLink with leading slash in android:path.
1366 input = R"(
1367 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1368 package="android">
1369 <application>
1370 <activity android:name=".MainActivity">
1371 <intent-filter>
1372 <action android:name="android.intent.action.VIEW" />
1373 <category android:name="android.intent.category.DEFAULT" />
1374 <category android:name="android.intent.category.BROWSABLE" />
1375 <data android:scheme="http"
1376 android:host="www.example.com"
1377 android:path="/path" />
1378 </intent-filter>
1379 </activity>
1380 </application>
1381 </manifest>)";
1382 EXPECT_THAT(Verify(input), NotNull());
1383
1384 // DeepLink with no leading slash in android:pathPrefix.
1385 input = R"(
1386 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1387 package="android">
1388 <application>
1389 <activity android:name=".MainActivity">
1390 <intent-filter>
1391 <action android:name="android.intent.action.VIEW" />
1392 <category android:name="android.intent.category.DEFAULT" />
1393 <category android:name="android.intent.category.BROWSABLE" />
1394 <data android:scheme="http"
1395 android:host="www.example.com"
1396 android:pathPrefix="pathPrefix" />
1397 </intent-filter>
1398 </activity>
1399 </application>
1400 </manifest>)";
1401 EXPECT_THAT(Verify(input), IsNull());
1402
1403 // DeepLink with leading slash in android:pathPrefix.
1404 input = R"(
1405 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1406 package="android">
1407 <application>
1408 <activity android:name=".MainActivity">
1409 <intent-filter>
1410 <action android:name="android.intent.action.VIEW" />
1411 <category android:name="android.intent.category.DEFAULT" />
1412 <category android:name="android.intent.category.BROWSABLE" />
1413 <data android:scheme="http"
1414 android:host="www.example.com"
1415 android:pathPrefix="/pathPrefix" />
1416 </intent-filter>
1417 </activity>
1418 </application>
1419 </manifest>)";
1420 EXPECT_THAT(Verify(input), NotNull());
1421
1422 // DeepLink with no leading slash in android:pathPattern.
1423 input = R"(
1424 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1425 package="android">
1426 <application>
1427 <activity android:name=".MainActivity">
1428 <intent-filter>
1429 <action android:name="android.intent.action.VIEW" />
1430 <category android:name="android.intent.category.DEFAULT" />
1431 <category android:name="android.intent.category.BROWSABLE" />
1432 <data android:scheme="http"
1433 android:host="www.example.com"
1434 android:pathPattern="pathPattern" />
1435 </intent-filter>
1436 </activity>
1437 </application>
1438 </manifest>)";
1439 EXPECT_THAT(Verify(input), IsNull());
1440
1441 // DeepLink with leading slash in android:pathPattern.
1442 input = R"(
1443 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1444 package="android">
1445 <application>
1446 <activity android:name=".MainActivity">
1447 <intent-filter>
1448 <action android:name="android.intent.action.VIEW" />
1449 <category android:name="android.intent.category.DEFAULT" />
1450 <category android:name="android.intent.category.BROWSABLE" />
1451 <data android:scheme="http"
1452 android:host="www.example.com"
1453 android:pathPattern="/pathPattern" />
1454 </intent-filter>
1455 </activity>
1456 </application>
1457 </manifest>)";
1458 EXPECT_THAT(Verify(input), NotNull());
1459
1460 // DeepLink with '.' start in pathPattern.
1461 input = R"(
1462 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1463 package="android">
1464 <application>
1465 <activity android:name=".MainActivity">
1466 <intent-filter>
1467 <action android:name="android.intent.action.VIEW" />
1468 <category android:name="android.intent.category.DEFAULT" />
1469 <category android:name="android.intent.category.BROWSABLE" />
1470 <data android:scheme="http"
1471 android:host="www.example.com"
1472 android:pathPattern=".*\\.pathPattern" />
1473 </intent-filter>
1474 </activity>
1475 </application>
1476 </manifest>)";
1477 EXPECT_THAT(Verify(input), NotNull());
1478
1479 // DeepLink with '*' start in pathPattern.
1480 input = R"(
1481 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1482 package="android">
1483 <application>
1484 <activity android:name=".MainActivity">
1485 <intent-filter>
1486 <action android:name="android.intent.action.VIEW" />
1487 <category android:name="android.intent.category.DEFAULT" />
1488 <category android:name="android.intent.category.BROWSABLE" />
1489 <data android:scheme="http"
1490 android:host="www.example.com"
1491 android:pathPattern="*" />
1492 </intent-filter>
1493 </activity>
1494 </application>
1495 </manifest>)";
1496 EXPECT_THAT(Verify(input), NotNull());
1497
1498 // DeepLink with string reference as a path.
1499 input = R"(
1500 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1501 package="android">
1502 <application>
1503 <activity android:name=".MainActivity">
1504 <intent-filter>
1505 <action android:name="android.intent.action.VIEW" />
1506 <category android:name="android.intent.category.DEFAULT" />
1507 <category android:name="android.intent.category.BROWSABLE" />
1508 <data android:scheme="http"
1509 android:host="www.example.com"
1510 android:path="@string/startup_uri" />
1511 </intent-filter>
1512 </activity>
1513 </application>
1514 </manifest>)";
1515 EXPECT_THAT(Verify(input), NotNull());
1516 }
1517 } // namespace aapt
1518