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