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