blob: 3bfaf91854bb6d4a9bb631a6814fe2c44719d3a0 [file] [log] [blame]
Adam Lesinski1ab598f2015-08-14 14:26:04 -07001/*
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/Linkers.h"
18
19#include "test/Builders.h"
20#include "test/Context.h"
21
22#include <gtest/gtest.h>
23
24namespace aapt {
25
26class XmlReferenceLinkerTest : public ::testing::Test {
27public:
28 void SetUp() override {
29 mContext = test::ContextBuilder()
30 .setCompilationPackage(u"com.app.test")
31 .setNameManglerPolicy(
32 NameManglerPolicy{ u"com.app.test", { u"com.android.support" } })
33 .setSymbolTable(test::StaticSymbolTableBuilder()
Adam Lesinski467f1712015-11-16 17:35:44 -080034 .addPublicSymbol(u"@android:attr/layout_width", ResourceId(0x01010000),
Adam Lesinski1ab598f2015-08-14 14:26:04 -070035 test::AttributeBuilder()
36 .setTypeMask(android::ResTable_map::TYPE_ENUM |
37 android::ResTable_map::TYPE_DIMENSION)
38 .addItem(u"match_parent", 0xffffffff)
39 .build())
Adam Lesinski467f1712015-11-16 17:35:44 -080040 .addPublicSymbol(u"@android:attr/background", ResourceId(0x01010001),
Adam Lesinski1ab598f2015-08-14 14:26:04 -070041 test::AttributeBuilder()
42 .setTypeMask(android::ResTable_map::TYPE_COLOR).build())
Adam Lesinski467f1712015-11-16 17:35:44 -080043 .addPublicSymbol(u"@android:attr/attr", ResourceId(0x01010002),
Adam Lesinski1ab598f2015-08-14 14:26:04 -070044 test::AttributeBuilder().build())
Adam Lesinski467f1712015-11-16 17:35:44 -080045 .addPublicSymbol(u"@android:attr/text", ResourceId(0x01010003),
Adam Lesinski1ab598f2015-08-14 14:26:04 -070046 test::AttributeBuilder()
47 .setTypeMask(android::ResTable_map::TYPE_STRING)
48 .build())
49
50 // Add one real symbol that was introduces in v21
Adam Lesinski467f1712015-11-16 17:35:44 -080051 .addPublicSymbol(u"@android:attr/colorAccent", ResourceId(0x01010435),
Adam Lesinski1ab598f2015-08-14 14:26:04 -070052 test::AttributeBuilder().build())
53
Adam Lesinski467f1712015-11-16 17:35:44 -080054 // Private symbol.
55 .addSymbol(u"@android:color/hidden", ResourceId(0x01020001))
56
57 .addPublicSymbol(u"@android:id/id", ResourceId(0x01030000))
Adam Lesinski1ab598f2015-08-14 14:26:04 -070058 .addSymbol(u"@com.app.test:id/id", ResourceId(0x7f030000))
59 .addSymbol(u"@com.app.test:color/green", ResourceId(0x7f020000))
60 .addSymbol(u"@com.app.test:color/red", ResourceId(0x7f020001))
61 .addSymbol(u"@com.app.test:attr/colorAccent", ResourceId(0x7f010000),
62 test::AttributeBuilder()
63 .setTypeMask(android::ResTable_map::TYPE_COLOR).build())
Adam Lesinski467f1712015-11-16 17:35:44 -080064 .addPublicSymbol(u"@com.app.test:attr/com.android.support$colorAccent",
Adam Lesinski1ab598f2015-08-14 14:26:04 -070065 ResourceId(0x7f010001), test::AttributeBuilder()
66 .setTypeMask(android::ResTable_map::TYPE_COLOR).build())
Adam Lesinski467f1712015-11-16 17:35:44 -080067 .addPublicSymbol(u"@com.app.test:attr/attr", ResourceId(0x7f010002),
Adam Lesinski1ab598f2015-08-14 14:26:04 -070068 test::AttributeBuilder().build())
69 .build())
70 .build();
71 }
72
73protected:
74 std::unique_ptr<IAaptContext> mContext;
75};
76
Adam Lesinski1ab598f2015-08-14 14:26:04 -070077TEST_F(XmlReferenceLinkerTest, LinkBasicAttributes) {
Adam Lesinski467f1712015-11-16 17:35:44 -080078 std::unique_ptr<xml::XmlResource> doc = test::buildXmlDomForPackageName(mContext.get(), R"EOF(
Adam Lesinski1ab598f2015-08-14 14:26:04 -070079 <View xmlns:android="http://schemas.android.com/apk/res/android"
80 android:layout_width="match_parent"
81 android:background="@color/green"
82 android:text="hello"
83 class="hello" />)EOF");
84
85 XmlReferenceLinker linker;
86 ASSERT_TRUE(linker.consume(mContext.get(), doc.get()));
87
Adam Lesinski467f1712015-11-16 17:35:44 -080088 xml::Element* viewEl = xml::findRootElement(doc.get());
Adam Lesinski1ab598f2015-08-14 14:26:04 -070089 ASSERT_NE(viewEl, nullptr);
90
91 xml::Attribute* xmlAttr = viewEl->findAttribute(u"http://schemas.android.com/apk/res/android",
92 u"layout_width");
93 ASSERT_NE(xmlAttr, nullptr);
94 AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
95 EXPECT_EQ(xmlAttr->compiledAttribute.value().id, ResourceId(0x01010000));
96 ASSERT_NE(xmlAttr->compiledValue, nullptr);
97 ASSERT_NE(valueCast<BinaryPrimitive>(xmlAttr->compiledValue.get()), nullptr);
98
99 xmlAttr = viewEl->findAttribute(u"http://schemas.android.com/apk/res/android", u"background");
100 ASSERT_NE(xmlAttr, nullptr);
101 AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
102 EXPECT_EQ(xmlAttr->compiledAttribute.value().id, ResourceId(0x01010001));
103 ASSERT_NE(xmlAttr->compiledValue, nullptr);
104 Reference* ref = valueCast<Reference>(xmlAttr->compiledValue.get());
105 ASSERT_NE(ref, nullptr);
106 AAPT_ASSERT_TRUE(ref->name);
107 EXPECT_EQ(ref->name.value(), test::parseNameOrDie(u"@color/green")); // Make sure the name
108 // didn't change.
109 AAPT_ASSERT_TRUE(ref->id);
110 EXPECT_EQ(ref->id.value(), ResourceId(0x7f020000));
111
112 xmlAttr = viewEl->findAttribute(u"http://schemas.android.com/apk/res/android", u"text");
113 ASSERT_NE(xmlAttr, nullptr);
114 AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
115 ASSERT_FALSE(xmlAttr->compiledValue); // Strings don't get compiled for memory sake.
116
117 xmlAttr = viewEl->findAttribute(u"", u"class");
118 ASSERT_NE(xmlAttr, nullptr);
119 AAPT_ASSERT_FALSE(xmlAttr->compiledAttribute);
120 ASSERT_EQ(xmlAttr->compiledValue, nullptr);
121}
122
Adam Lesinski467f1712015-11-16 17:35:44 -0800123TEST_F(XmlReferenceLinkerTest, PrivateSymbolsAreNotLinked) {
124 std::unique_ptr<xml::XmlResource> doc = test::buildXmlDomForPackageName(mContext.get(), R"EOF(
125 <View xmlns:android="http://schemas.android.com/apk/res/android"
126 android:colorAccent="@android:color/hidden" />)EOF");
127
128 XmlReferenceLinker linker;
129 ASSERT_FALSE(linker.consume(mContext.get(), doc.get()));
130}
131
132TEST_F(XmlReferenceLinkerTest, PrivateSymbolsAreLinkedWhenReferenceHasStarPrefix) {
133 std::unique_ptr<xml::XmlResource> doc = test::buildXmlDomForPackageName(mContext.get(), R"EOF(
134 <View xmlns:android="http://schemas.android.com/apk/res/android"
135 android:colorAccent="@*android:color/hidden" />)EOF");
136
137 XmlReferenceLinker linker;
138 ASSERT_TRUE(linker.consume(mContext.get(), doc.get()));
139}
140
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700141TEST_F(XmlReferenceLinkerTest, SdkLevelsAreRecorded) {
Adam Lesinski467f1712015-11-16 17:35:44 -0800142 std::unique_ptr<xml::XmlResource> doc = test::buildXmlDomForPackageName(mContext.get(), R"EOF(
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700143 <View xmlns:android="http://schemas.android.com/apk/res/android"
144 android:colorAccent="#ffffff" />)EOF");
145
146 XmlReferenceLinker linker;
147 ASSERT_TRUE(linker.consume(mContext.get(), doc.get()));
148 EXPECT_TRUE(linker.getSdkLevels().count(21) == 1);
149}
150
151TEST_F(XmlReferenceLinkerTest, LinkMangledAttributes) {
Adam Lesinski467f1712015-11-16 17:35:44 -0800152 std::unique_ptr<xml::XmlResource> doc = test::buildXmlDomForPackageName(mContext.get(), R"EOF(
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700153 <View xmlns:support="http://schemas.android.com/apk/res/com.android.support"
154 support:colorAccent="#ff0000" />)EOF");
155
156 XmlReferenceLinker linker;
157 ASSERT_TRUE(linker.consume(mContext.get(), doc.get()));
158
Adam Lesinski467f1712015-11-16 17:35:44 -0800159 xml::Element* viewEl = xml::findRootElement(doc.get());
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700160 ASSERT_NE(viewEl, nullptr);
161
162 xml::Attribute* xmlAttr = viewEl->findAttribute(
163 u"http://schemas.android.com/apk/res/com.android.support", u"colorAccent");
164 ASSERT_NE(xmlAttr, nullptr);
165 AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
166 EXPECT_EQ(xmlAttr->compiledAttribute.value().id, ResourceId(0x7f010001));
167 ASSERT_NE(valueCast<BinaryPrimitive>(xmlAttr->compiledValue.get()), nullptr);
168}
169
170TEST_F(XmlReferenceLinkerTest, LinkAutoResReference) {
Adam Lesinski467f1712015-11-16 17:35:44 -0800171 std::unique_ptr<xml::XmlResource> doc = test::buildXmlDomForPackageName(mContext.get(), R"EOF(
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700172 <View xmlns:app="http://schemas.android.com/apk/res-auto"
173 app:colorAccent="@app:color/red" />)EOF");
174
175 XmlReferenceLinker linker;
176 ASSERT_TRUE(linker.consume(mContext.get(), doc.get()));
177
Adam Lesinski467f1712015-11-16 17:35:44 -0800178 xml::Element* viewEl = xml::findRootElement(doc.get());
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700179 ASSERT_NE(viewEl, nullptr);
180
181 xml::Attribute* xmlAttr = viewEl->findAttribute(u"http://schemas.android.com/apk/res-auto",
182 u"colorAccent");
183 ASSERT_NE(xmlAttr, nullptr);
184 AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
185 EXPECT_EQ(xmlAttr->compiledAttribute.value().id, ResourceId(0x7f010000));
186 Reference* ref = valueCast<Reference>(xmlAttr->compiledValue.get());
187 ASSERT_NE(ref, nullptr);
188 AAPT_ASSERT_TRUE(ref->name);
189 AAPT_ASSERT_TRUE(ref->id);
190 EXPECT_EQ(ref->id.value(), ResourceId(0x7f020001));
191}
192
193TEST_F(XmlReferenceLinkerTest, LinkViewWithShadowedPackageAlias) {
Adam Lesinski467f1712015-11-16 17:35:44 -0800194 std::unique_ptr<xml::XmlResource> doc = test::buildXmlDomForPackageName(mContext.get(), R"EOF(
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700195 <View xmlns:app="http://schemas.android.com/apk/res/android"
196 app:attr="@app:id/id">
197 <View xmlns:app="http://schemas.android.com/apk/res/com.app.test"
198 app:attr="@app:id/id"/>
199 </View>)EOF");
200
201 XmlReferenceLinker linker;
202 ASSERT_TRUE(linker.consume(mContext.get(), doc.get()));
203
Adam Lesinski467f1712015-11-16 17:35:44 -0800204 xml::Element* viewEl = xml::findRootElement(doc.get());
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700205 ASSERT_NE(viewEl, nullptr);
206
207 // All attributes and references in this element should be referring to "android" (0x01).
208 xml::Attribute* xmlAttr = viewEl->findAttribute(u"http://schemas.android.com/apk/res/android",
209 u"attr");
210 ASSERT_NE(xmlAttr, nullptr);
211 AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
212 EXPECT_EQ(xmlAttr->compiledAttribute.value().id, ResourceId(0x01010002));
213 Reference* ref = valueCast<Reference>(xmlAttr->compiledValue.get());
214 ASSERT_NE(ref, nullptr);
215 AAPT_ASSERT_TRUE(ref->id);
216 EXPECT_EQ(ref->id.value(), ResourceId(0x01030000));
217
218 ASSERT_FALSE(viewEl->getChildElements().empty());
219 viewEl = viewEl->getChildElements().front();
220 ASSERT_NE(viewEl, nullptr);
221
222 // All attributes and references in this element should be referring to "com.app.test" (0x7f).
223 xmlAttr = viewEl->findAttribute(u"http://schemas.android.com/apk/res/com.app.test", u"attr");
224 ASSERT_NE(xmlAttr, nullptr);
225 AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
226 EXPECT_EQ(xmlAttr->compiledAttribute.value().id, ResourceId(0x7f010002));
227 ref = valueCast<Reference>(xmlAttr->compiledValue.get());
228 ASSERT_NE(ref, nullptr);
229 AAPT_ASSERT_TRUE(ref->id);
230 EXPECT_EQ(ref->id.value(), ResourceId(0x7f030000));
231}
232
233TEST_F(XmlReferenceLinkerTest, LinkViewWithLocalPackageAndAliasOfTheSameName) {
Adam Lesinski467f1712015-11-16 17:35:44 -0800234 std::unique_ptr<xml::XmlResource> doc = test::buildXmlDomForPackageName(mContext.get(), R"EOF(
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700235 <View xmlns:android="http://schemas.android.com/apk/res/com.app.test"
236 android:attr="@id/id"/>)EOF");
237
238 XmlReferenceLinker linker;
239 ASSERT_TRUE(linker.consume(mContext.get(), doc.get()));
240
Adam Lesinski467f1712015-11-16 17:35:44 -0800241 xml::Element* viewEl = xml::findRootElement(doc.get());
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700242 ASSERT_NE(viewEl, nullptr);
243
244 // All attributes and references in this element should be referring to "com.app.test" (0x7f).
245 xml::Attribute* xmlAttr = viewEl->findAttribute(
246 u"http://schemas.android.com/apk/res/com.app.test", u"attr");
247 ASSERT_NE(xmlAttr, nullptr);
248 AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
249 EXPECT_EQ(xmlAttr->compiledAttribute.value().id, ResourceId(0x7f010002));
250 Reference* ref = valueCast<Reference>(xmlAttr->compiledValue.get());
251 ASSERT_NE(ref, nullptr);
252 AAPT_ASSERT_TRUE(ref->id);
253 EXPECT_EQ(ref->id.value(), ResourceId(0x7f030000));
254}
255
256} // namespace aapt