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(const StringPiece& str) {
65 return VerifyWithOptions(str, {});
66 }
67
VerifyWithOptionsaapt::ManifestFixerTest68 std::unique_ptr<xml::XmlResource> VerifyWithOptions(
69 const StringPiece& str, 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, UseDefaultVersionNameAndCode) {
329 ManifestFixerOptions options;
330 options.version_name_default = std::string("Beta");
331 options.version_code_default = std::string("0x10000000");
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" />)EOF",
336 options);
337 ASSERT_THAT(doc, NotNull());
338
339 xml::Element* manifest_el = doc->root.get();
340 ASSERT_THAT(manifest_el, NotNull());
341
342 xml::Attribute* attr =
343 manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
344 ASSERT_THAT(attr, NotNull());
345 EXPECT_THAT(attr->value, StrEq("Beta"));
346
347 attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
348 ASSERT_THAT(attr, NotNull());
349 EXPECT_THAT(attr->value, StrEq("0x10000000"));
350 }
351
352 TEST_F(ManifestFixerTest, EnsureManifestAttributesAreTyped) {
353 EXPECT_THAT(Verify("<manifest package=\"android\" coreApp=\"hello\" />"), IsNull());
354 EXPECT_THAT(Verify("<manifest package=\"android\" coreApp=\"1dp\" />"), IsNull());
355
356 std::unique_ptr<xml::XmlResource> doc =
357 Verify("<manifest package=\"android\" coreApp=\"true\" />");
358 ASSERT_THAT(doc, NotNull());
359
360 xml::Element* el = doc->root.get();
361 ASSERT_THAT(el, NotNull());
362
363 EXPECT_THAT(el->name, StrEq("manifest"));
364
365 xml::Attribute* attr = el->FindAttribute("", "coreApp");
366 ASSERT_THAT(attr, NotNull());
367
368 EXPECT_THAT(attr->compiled_value, NotNull());
369 EXPECT_THAT(ValueCast<BinaryPrimitive>(attr->compiled_value.get()), NotNull());
370 }
371
TEST_F(ManifestFixerTest,UsesFeatureMustHaveNameOrGlEsVersion)372 TEST_F(ManifestFixerTest, UsesFeatureMustHaveNameOrGlEsVersion) {
373 std::string input = R"EOF(
374 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
375 package="android">
376 <uses-feature android:name="feature" />
377 <uses-feature android:glEsVersion="1" />
378 <feature-group />
379 <feature-group>
380 <uses-feature android:name="feature_in_group" />
381 <uses-feature android:glEsVersion="2" />
382 </feature-group>
383 </manifest>)EOF";
384 EXPECT_THAT(Verify(input), NotNull());
385
386 input = R"EOF(
387 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
388 package="android">
389 <uses-feature android:name="feature" android:glEsVersion="1" />
390 </manifest>)EOF";
391 EXPECT_THAT(Verify(input), IsNull());
392
393 input = R"EOF(
394 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
395 package="android">
396 <uses-feature />
397 </manifest>)EOF";
398 EXPECT_THAT(Verify(input), IsNull());
399
400 input = R"EOF(
401 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
402 package="android">
403 <feature-group>
404 <uses-feature android:name="feature" android:glEsVersion="1" />
405 </feature-group>
406 </manifest>)EOF";
407 EXPECT_THAT(Verify(input), IsNull());
408
409 input = R"EOF(
410 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
411 package="android">
412 <feature-group>
413 <uses-feature />
414 </feature-group>
415 </manifest>)EOF";
416 EXPECT_THAT(Verify(input), IsNull());
417 }
418
419 TEST_F(ManifestFixerTest, ApplicationInjectDebuggable) {
420 ManifestFixerOptions options;
421 options.debug_mode = true;
422
423 std::string no_d = R"(
424 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
425 package="android">
426 <application>
427 </application>
428 </manifest>)";
429
430 std::string false_d = R"(
431 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
432 package="android">
433 <application android:debuggable="false">
434 </application>
435 </manifest>)";
436
437 std::string true_d = R"(
438 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
439 package="android">
440 <application android:debuggable="true">
441 </application>
442 </manifest>)";
443
444 // Inject the debuggable attribute when the attribute is not present and the
445 // flag is present
446 std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(no_d, options);
447 EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
448 {}, "application", xml::kSchemaAndroid, "debuggable", "true"), NotNull());
449
450 // Set the debuggable flag to true if the attribute is false and the flag is
451 // present
452 manifest = VerifyWithOptions(false_d, options);
453 EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
454 {}, "application", xml::kSchemaAndroid, "debuggable", "true"), NotNull());
455
456 // Keep debuggable flag true if the attribute is true and the flag is present
457 manifest = VerifyWithOptions(true_d, options);
458 EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
459 {}, "application", xml::kSchemaAndroid, "debuggable", "true"), NotNull());
460
461 // Do not inject the debuggable attribute when the attribute is not present
462 // and the flag is not present
463 manifest = Verify(no_d);
464 EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
465 {}, "application", xml::kSchemaAndroid, "debuggable", "true"), IsNull());
466
467 // Do not set the debuggable flag to true if the attribute is false and the
468 // flag is not present
469 manifest = Verify(false_d);
470 EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
471 {}, "application", xml::kSchemaAndroid, "debuggable", "true"), IsNull());
472
473 // Keep debuggable flag true if the attribute is true and the flag is not
474 // present
475 manifest = Verify(true_d);
476 EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
477 {}, "application", xml::kSchemaAndroid, "debuggable", "true"), NotNull());
478 }
479
480
481 TEST_F(ManifestFixerTest, IgnoreNamespacedElements) {
482 std::string input = R"EOF(
483 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
484 package="android">
485 <special:tag whoo="true" xmlns:special="http://google.com" />
486 </manifest>)EOF";
487 EXPECT_THAT(Verify(input), NotNull());
488 }
489
490 TEST_F(ManifestFixerTest, DoNotIgnoreNonNamespacedElements) {
491 std::string input = R"EOF(
492 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
493 package="android">
494 <tag whoo="true" />
495 </manifest>)EOF";
496 EXPECT_THAT(Verify(input), IsNull());
497 }
498
499 TEST_F(ManifestFixerTest, SupportKeySets) {
500 std::string input = R"(
501 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
502 package="android">
503 <key-sets>
504 <key-set android:name="old-set">
505 <public-key android:name="old-key" android:value="some+old+key" />
506 </key-set>
507 <key-set android:name="new-set">
508 <public-key android:name="new-key" android:value="some+new+key" />
509 </key-set>
510 <upgrade-key-set android:name="old-set" />
511 <upgrade-key-set android:name="new-set" />
512 </key-sets>
513 </manifest>)";
514 EXPECT_THAT(Verify(input), NotNull());
515 }
516
517 TEST_F(ManifestFixerTest, InsertCompileSdkVersions) {
518 std::string input = R"(
519 <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android" />)";
520 ManifestFixerOptions options;
521 options.compile_sdk_version = {"28"};
522 options.compile_sdk_version_codename = {"P"};
523
524 std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
525 ASSERT_THAT(manifest, NotNull());
526
527 xml::Attribute* attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersion");
528 ASSERT_THAT(attr, NotNull());
529 EXPECT_THAT(attr->value, StrEq("28"));
530
531 attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
532 ASSERT_THAT(attr, NotNull());
533 EXPECT_THAT(attr->value, StrEq("P"));
534 }
535
536 TEST_F(ManifestFixerTest, UnexpectedElementsInManifest) {
537 std::string input = R"(
538 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
539 package="android">
540 <beep/>
541 </manifest>)";
542 ManifestFixerOptions options;
543 options.warn_validation = true;
544
545 // Unexpected element should result in a warning if the flag is set to 'true'.
546 std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
547 ASSERT_THAT(manifest, NotNull());
548
549 // Unexpected element should result in an error if the flag is set to 'false'.
550 options.warn_validation = false;
551 manifest = VerifyWithOptions(input, options);
552 ASSERT_THAT(manifest, IsNull());
553
554 // By default the flag should be set to 'false'.
555 manifest = Verify(input);
556 ASSERT_THAT(manifest, IsNull());
557 }
558
559 TEST_F(ManifestFixerTest, InsertPlatformBuildVersions) {
560 // Test for insertion when versionCode and versionName are included in the manifest
561 {
562 std::string input = R"(
563 <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"
564 android:versionCode="27" android:versionName="O"/>)";
565 std::unique_ptr<xml::XmlResource> manifest = Verify(input);
566 ASSERT_THAT(manifest, NotNull());
567
568 xml::Attribute* attr = manifest->root->FindAttribute("", "platformBuildVersionCode");
569 ASSERT_THAT(attr, NotNull());
570 EXPECT_THAT(attr->value, StrEq("27"));
571 attr = manifest->root->FindAttribute("", "platformBuildVersionName");
572 ASSERT_THAT(attr, NotNull());
573 EXPECT_THAT(attr->value, StrEq("O"));
574 }
575
576 // Test for insertion when versionCode and versionName defaults are specified
577 {
578 std::string input = R"(
579 <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"/>)";
580 ManifestFixerOptions options;
581 options.version_code_default = {"27"};
582 options.version_name_default = {"O"};
583 std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
584 ASSERT_THAT(manifest, NotNull());
585
586 xml::Attribute* attr = manifest->root->FindAttribute("", "platformBuildVersionCode");
587 ASSERT_THAT(attr, NotNull());
588 EXPECT_THAT(attr->value, StrEq("27"));
589 attr = manifest->root->FindAttribute("", "platformBuildVersionName");
590 ASSERT_THAT(attr, NotNull());
591 EXPECT_THAT(attr->value, StrEq("O"));
592 }
593
594 // Test that the platform build version attributes are not changed if they are currently present
595 {
596 std::string input = R"(
597 <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"
598 android:versionCode="28" android:versionName="P"
599 platformBuildVersionCode="27" platformBuildVersionName="O"/>)";
600 std::unique_ptr<xml::XmlResource> manifest = Verify(input);
601 ASSERT_THAT(manifest, NotNull());
602
603 xml::Attribute* attr = manifest->root->FindAttribute("", "platformBuildVersionCode");
604 ASSERT_THAT(attr, NotNull());
605 EXPECT_THAT(attr->value, StrEq("27"));
606 attr = manifest->root->FindAttribute("", "platformBuildVersionName");
607 ASSERT_THAT(attr, NotNull());
608 EXPECT_THAT(attr->value, StrEq("O"));
609 }
610 }
611
612 TEST_F(ManifestFixerTest, UsesLibraryMustHaveNonEmptyName) {
613 std::string input = R"(
614 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
615 package="android">
616 <application>
617 <uses-library android:name="" />
618 </application>
619 </manifest>)";
620 EXPECT_THAT(Verify(input), IsNull());
621
622 input = R"(
623 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
624 package="android">
625 <application>
626 <uses-library />
627 </application>
628 </manifest>)";
629 EXPECT_THAT(Verify(input), IsNull());
630
631 input = R"(
632 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
633 package="android">
634 <application>
635 <uses-library android:name="blahhh" />
636 </application>
637 </manifest>)";
638 EXPECT_THAT(Verify(input), NotNull());
639 }
640
641 } // namespace aapt
642