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 
23 namespace aapt {
24 
25 struct ManifestFixerTest : public ::testing::Test {
26     std::unique_ptr<IAaptContext> mContext;
27 
SetUpaapt::ManifestFixerTest28     void SetUp() override {
29         mContext = test::ContextBuilder()
30                 .setCompilationPackage(u"android")
31                 .setPackageId(0x01)
32                 .setNameManglerPolicy(NameManglerPolicy{ u"android" })
33                 .addSymbolSource(test::StaticSymbolSourceBuilder()
34                         .addSymbol(u"@android:attr/package", ResourceId(0x01010000),
35                                    test::AttributeBuilder()
36                                         .setTypeMask(android::ResTable_map::TYPE_STRING)
37                                         .build())
38                         .addSymbol(u"@android:attr/minSdkVersion", ResourceId(0x01010001),
39                                    test::AttributeBuilder()
40                                         .setTypeMask(android::ResTable_map::TYPE_STRING |
41                                                      android::ResTable_map::TYPE_INTEGER)
42                                         .build())
43                         .addSymbol(u"@android:attr/targetSdkVersion", ResourceId(0x01010002),
44                                    test::AttributeBuilder()
45                                         .setTypeMask(android::ResTable_map::TYPE_STRING |
46                                                      android::ResTable_map::TYPE_INTEGER)
47                                         .build())
48                         .addSymbol(u"@android:string/str", ResourceId(0x01060000))
49                         .build())
50                 .build();
51     }
52 
verifyaapt::ManifestFixerTest53     std::unique_ptr<xml::XmlResource> verify(const StringPiece& str) {
54         return verifyWithOptions(str, {});
55     }
56 
verifyWithOptionsaapt::ManifestFixerTest57     std::unique_ptr<xml::XmlResource> verifyWithOptions(const StringPiece& str,
58                                                         const ManifestFixerOptions& options) {
59         std::unique_ptr<xml::XmlResource> doc = test::buildXmlDom(str);
60         ManifestFixer fixer(options);
61         if (fixer.consume(mContext.get(), doc.get())) {
62             return doc;
63         }
64         return {};
65     }
66 };
67 
TEST_F(ManifestFixerTest,EnsureManifestIsRootTag)68 TEST_F(ManifestFixerTest, EnsureManifestIsRootTag) {
69     EXPECT_EQ(nullptr, verify("<other-tag />"));
70     EXPECT_EQ(nullptr, verify("<ns:manifest xmlns:ns=\"com\" />"));
71     EXPECT_NE(nullptr, verify("<manifest package=\"android\"></manifest>"));
72 }
73 
TEST_F(ManifestFixerTest,EnsureManifestHasPackage)74 TEST_F(ManifestFixerTest, EnsureManifestHasPackage) {
75     EXPECT_NE(nullptr, verify("<manifest package=\"android\" />"));
76     EXPECT_NE(nullptr, verify("<manifest package=\"com.android\" />"));
77     EXPECT_NE(nullptr, verify("<manifest package=\"com.android.google\" />"));
78     EXPECT_EQ(nullptr, verify("<manifest package=\"com.android.google.Class$1\" />"));
79     EXPECT_EQ(nullptr,
80               verify("<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" "
81                      "android:package=\"com.android\" />"));
82     EXPECT_EQ(nullptr, verify("<manifest package=\"@string/str\" />"));
83 }
84 
TEST_F(ManifestFixerTest,UseDefaultSdkVersionsIfNonePresent)85 TEST_F(ManifestFixerTest, UseDefaultSdkVersionsIfNonePresent) {
86     ManifestFixerOptions options = { std::u16string(u"8"), std::u16string(u"22") };
87 
88     std::unique_ptr<xml::XmlResource> doc = verifyWithOptions(R"EOF(
89       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
90                 package="android">
91         <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="21" />
92       </manifest>)EOF", options);
93     ASSERT_NE(nullptr, doc);
94 
95     xml::Element* el;
96     xml::Attribute* attr;
97 
98     el = xml::findRootElement(doc.get());
99     ASSERT_NE(nullptr, el);
100     el = el->findChild({}, u"uses-sdk");
101     ASSERT_NE(nullptr, el);
102     attr = el->findAttribute(xml::kSchemaAndroid, u"minSdkVersion");
103     ASSERT_NE(nullptr, attr);
104     EXPECT_EQ(u"7", attr->value);
105     attr = el->findAttribute(xml::kSchemaAndroid, u"targetSdkVersion");
106     ASSERT_NE(nullptr, attr);
107     EXPECT_EQ(u"21", attr->value);
108 
109     doc = verifyWithOptions(R"EOF(
110       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
111                 package="android">
112         <uses-sdk android:targetSdkVersion="21" />
113       </manifest>)EOF", options);
114     ASSERT_NE(nullptr, doc);
115 
116     el = xml::findRootElement(doc.get());
117     ASSERT_NE(nullptr, el);
118     el = el->findChild({}, u"uses-sdk");
119     ASSERT_NE(nullptr, el);
120     attr = el->findAttribute(xml::kSchemaAndroid, u"minSdkVersion");
121     ASSERT_NE(nullptr, attr);
122     EXPECT_EQ(u"8", attr->value);
123     attr = el->findAttribute(xml::kSchemaAndroid, u"targetSdkVersion");
124     ASSERT_NE(nullptr, attr);
125     EXPECT_EQ(u"21", attr->value);
126 
127     doc = verifyWithOptions(R"EOF(
128       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
129                 package="android">
130         <uses-sdk />
131       </manifest>)EOF", options);
132     ASSERT_NE(nullptr, doc);
133 
134     el = xml::findRootElement(doc.get());
135     ASSERT_NE(nullptr, el);
136     el = el->findChild({}, u"uses-sdk");
137     ASSERT_NE(nullptr, el);
138     attr = el->findAttribute(xml::kSchemaAndroid, u"minSdkVersion");
139     ASSERT_NE(nullptr, attr);
140     EXPECT_EQ(u"8", attr->value);
141     attr = el->findAttribute(xml::kSchemaAndroid, u"targetSdkVersion");
142     ASSERT_NE(nullptr, attr);
143     EXPECT_EQ(u"22", attr->value);
144 
145     doc = verifyWithOptions(R"EOF(
146       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
147                 package="android" />)EOF", options);
148     ASSERT_NE(nullptr, doc);
149 
150     el = xml::findRootElement(doc.get());
151     ASSERT_NE(nullptr, el);
152     el = el->findChild({}, u"uses-sdk");
153     ASSERT_NE(nullptr, el);
154     attr = el->findAttribute(xml::kSchemaAndroid, u"minSdkVersion");
155     ASSERT_NE(nullptr, attr);
156     EXPECT_EQ(u"8", attr->value);
157     attr = el->findAttribute(xml::kSchemaAndroid, u"targetSdkVersion");
158     ASSERT_NE(nullptr, attr);
159     EXPECT_EQ(u"22", attr->value);
160 }
161 
162 TEST_F(ManifestFixerTest, RenameManifestPackageAndFullyQualifyClasses) {
163     ManifestFixerOptions options;
164     options.renameManifestPackage = std::u16string(u"com.android");
165 
166     std::unique_ptr<xml::XmlResource> doc = verifyWithOptions(R"EOF(
167       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
168                 package="android">
169         <application android:name=".MainApplication" text="hello">
170           <activity android:name=".activity.Start" />
171           <receiver android:name="com.google.android.Receiver" />
172         </application>
173       </manifest>)EOF", options);
174     ASSERT_NE(nullptr, doc);
175 
176     xml::Element* manifestEl = xml::findRootElement(doc.get());
177     ASSERT_NE(nullptr, manifestEl);
178 
179     xml::Attribute* attr = nullptr;
180 
181     attr = manifestEl->findAttribute({}, u"package");
182     ASSERT_NE(nullptr, attr);
183     EXPECT_EQ(std::u16string(u"com.android"), attr->value);
184 
185     xml::Element* applicationEl = manifestEl->findChild({}, u"application");
186     ASSERT_NE(nullptr, applicationEl);
187 
188     attr = applicationEl->findAttribute(xml::kSchemaAndroid, u"name");
189     ASSERT_NE(nullptr, attr);
190     EXPECT_EQ(std::u16string(u"android.MainApplication"), attr->value);
191 
192     attr = applicationEl->findAttribute({}, u"text");
193     ASSERT_NE(nullptr, attr);
194     EXPECT_EQ(std::u16string(u"hello"), attr->value);
195 
196     xml::Element* el;
197     el = applicationEl->findChild({}, u"activity");
198     ASSERT_NE(nullptr, el);
199 
200     attr = el->findAttribute(xml::kSchemaAndroid, u"name");
201     ASSERT_NE(nullptr, el);
202     EXPECT_EQ(std::u16string(u"android.activity.Start"), attr->value);
203 
204     el = applicationEl->findChild({}, u"receiver");
205     ASSERT_NE(nullptr, el);
206 
207     attr = el->findAttribute(xml::kSchemaAndroid, u"name");
208     ASSERT_NE(nullptr, el);
209     EXPECT_EQ(std::u16string(u"com.google.android.Receiver"), attr->value);
210 }
211 
212 TEST_F(ManifestFixerTest, RenameManifestInstrumentationPackageAndFullyQualifyTarget) {
213     ManifestFixerOptions options;
214     options.renameInstrumentationTargetPackage = std::u16string(u"com.android");
215 
216     std::unique_ptr<xml::XmlResource> doc = verifyWithOptions(R"EOF(
217       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
218                 package="android">
219         <instrumentation android:targetPackage="android" />
220       </manifest>)EOF", options);
221     ASSERT_NE(nullptr, doc);
222 
223     xml::Element* manifestEl = xml::findRootElement(doc.get());
224     ASSERT_NE(nullptr, manifestEl);
225 
226     xml::Element* instrumentationEl = manifestEl->findChild({}, u"instrumentation");
227     ASSERT_NE(nullptr, instrumentationEl);
228 
229     xml::Attribute* attr = instrumentationEl->findAttribute(xml::kSchemaAndroid, u"targetPackage");
230     ASSERT_NE(nullptr, attr);
231     EXPECT_EQ(std::u16string(u"com.android"), attr->value);
232 }
233 
234 TEST_F(ManifestFixerTest, UseDefaultVersionNameAndCode) {
235     ManifestFixerOptions options;
236     options.versionNameDefault = std::u16string(u"Beta");
237     options.versionCodeDefault = std::u16string(u"0x10000000");
238 
239     std::unique_ptr<xml::XmlResource> doc = verifyWithOptions(R"EOF(
240       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
241                 package="android" />)EOF", options);
242     ASSERT_NE(nullptr, doc);
243 
244     xml::Element* manifestEl = xml::findRootElement(doc.get());
245     ASSERT_NE(nullptr, manifestEl);
246 
247     xml::Attribute* attr = manifestEl->findAttribute(xml::kSchemaAndroid, u"versionName");
248     ASSERT_NE(nullptr, attr);
249     EXPECT_EQ(std::u16string(u"Beta"), attr->value);
250 
251     attr = manifestEl->findAttribute(xml::kSchemaAndroid, u"versionCode");
252     ASSERT_NE(nullptr, attr);
253     EXPECT_EQ(std::u16string(u"0x10000000"), attr->value);
254 }
255 
256 } // namespace aapt
257