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
21using ::android::StringPiece;
22using ::testing::Eq;
23using ::testing::Gt;
24using ::testing::IsNull;
25using ::testing::Ne;
26using ::testing::NotNull;
27using ::testing::StrEq;
28
29namespace aapt {
30
31struct ManifestFixerTest : public ::testing::Test {
32  std::unique_ptr<IAaptContext> mContext;
33
34  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
64  std::unique_ptr<xml::XmlResource> Verify(const StringPiece& str) {
65    return VerifyWithOptions(str, {});
66  }
67
68  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
79TEST_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
85TEST_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
96TEST_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
114TEST_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
197TEST_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
243TEST_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
302TEST_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
328TEST_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
352TEST_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
372TEST_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
419TEST_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
481TEST_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
490TEST_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
499TEST_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
517TEST_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
536TEST_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
559TEST_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
612TEST_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