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/ReferenceLinker.h"
18
19 #include "test/Test.h"
20
21 using android::ResTable_map;
22 using ::testing::NotNull;
23
24 namespace aapt {
25
TEST(ReferenceLinkerTest,LinkSimpleReferences)26 TEST(ReferenceLinkerTest, LinkSimpleReferences) {
27 std::unique_ptr<ResourceTable> table =
28 test::ResourceTableBuilder()
29 .SetPackageId("com.app.test", 0x7f)
30 .AddReference("com.app.test:string/foo", ResourceId(0x7f020000),
31 "com.app.test:string/bar")
32
33 // Test use of local reference (w/o package name).
34 .AddReference("com.app.test:string/bar", ResourceId(0x7f020001),
35 "string/baz")
36
37 .AddReference("com.app.test:string/baz", ResourceId(0x7f020002),
38 "android:string/ok")
39 .Build();
40
41 std::unique_ptr<IAaptContext> context =
42 test::ContextBuilder()
43 .SetCompilationPackage("com.app.test")
44 .SetPackageId(0x7f)
45 .SetNameManglerPolicy(NameManglerPolicy{"com.app.test"})
46 .AddSymbolSource(
47 util::make_unique<ResourceTableSymbolSource>(table.get()))
48 .AddSymbolSource(
49 test::StaticSymbolSourceBuilder()
50 .AddPublicSymbol("android:string/ok", ResourceId(0x01040034))
51 .Build())
52 .Build();
53
54 ReferenceLinker linker;
55 ASSERT_TRUE(linker.Consume(context.get(), table.get()));
56
57 Reference* ref = test::GetValue<Reference>(table.get(), "com.app.test:string/foo");
58 ASSERT_THAT(ref, NotNull());
59 ASSERT_TRUE(ref->id);
60 EXPECT_EQ(ResourceId(0x7f020001), ref->id.value());
61
62 ref = test::GetValue<Reference>(table.get(), "com.app.test:string/bar");
63 ASSERT_THAT(ref, NotNull());
64 ASSERT_TRUE(ref->id);
65 EXPECT_EQ(ResourceId(0x7f020002), ref->id.value());
66
67 ref = test::GetValue<Reference>(table.get(), "com.app.test:string/baz");
68 ASSERT_THAT(ref, NotNull());
69 ASSERT_TRUE(ref->id);
70 EXPECT_EQ(ResourceId(0x01040034), ref->id.value());
71 }
72
TEST(ReferenceLinkerTest,LinkStyleAttributes)73 TEST(ReferenceLinkerTest, LinkStyleAttributes) {
74 std::unique_ptr<ResourceTable> table =
75 test::ResourceTableBuilder()
76 .SetPackageId("com.app.test", 0x7f)
77 .AddValue("com.app.test:style/Theme",
78 test::StyleBuilder()
79 .SetParent("android:style/Theme.Material")
80 .AddItem("android:attr/foo",
81 ResourceUtils::TryParseColor("#ff00ff"))
82 .AddItem("android:attr/bar", {} /* placeholder */)
83 .Build())
84 .Build();
85
86 {
87 // We need to fill in the value for the attribute android:attr/bar after we
88 // build the table, because we need access to the string pool.
89 Style* style = test::GetValue<Style>(table.get(), "com.app.test:style/Theme");
90 ASSERT_THAT(style, NotNull());
91 style->entries.back().value =
92 util::make_unique<RawString>(table->string_pool.MakeRef("one|two"));
93 }
94
95 std::unique_ptr<IAaptContext> context =
96 test::ContextBuilder()
97 .SetCompilationPackage("com.app.test")
98 .SetPackageId(0x7f)
99 .SetNameManglerPolicy(NameManglerPolicy{"com.app.test"})
100 .AddSymbolSource(
101 test::StaticSymbolSourceBuilder()
102 .AddPublicSymbol("android:style/Theme.Material",
103 ResourceId(0x01060000))
104 .AddPublicSymbol("android:attr/foo", ResourceId(0x01010001),
105 test::AttributeBuilder()
106 .SetTypeMask(ResTable_map::TYPE_COLOR)
107 .Build())
108 .AddPublicSymbol("android:attr/bar", ResourceId(0x01010002),
109 test::AttributeBuilder()
110 .SetTypeMask(ResTable_map::TYPE_FLAGS)
111 .AddItem("one", 0x01)
112 .AddItem("two", 0x02)
113 .Build())
114 .Build())
115 .Build();
116
117 ReferenceLinker linker;
118 ASSERT_TRUE(linker.Consume(context.get(), table.get()));
119
120 Style* style = test::GetValue<Style>(table.get(), "com.app.test:style/Theme");
121 ASSERT_THAT(style, NotNull());
122 ASSERT_TRUE(style->parent);
123 ASSERT_TRUE(style->parent.value().id);
124 EXPECT_EQ(ResourceId(0x01060000), style->parent.value().id.value());
125
126 ASSERT_EQ(2u, style->entries.size());
127
128 ASSERT_TRUE(style->entries[0].key.id);
129 EXPECT_EQ(ResourceId(0x01010001), style->entries[0].key.id.value());
130 ASSERT_THAT(ValueCast<BinaryPrimitive>(style->entries[0].value.get()), NotNull());
131
132 ASSERT_TRUE(style->entries[1].key.id);
133 EXPECT_EQ(ResourceId(0x01010002), style->entries[1].key.id.value());
134 ASSERT_THAT(ValueCast<BinaryPrimitive>(style->entries[1].value.get()), NotNull());
135 }
136
TEST(ReferenceLinkerTest,LinkMangledReferencesAndAttributes)137 TEST(ReferenceLinkerTest, LinkMangledReferencesAndAttributes) {
138 std::unique_ptr<IAaptContext> context =
139 test::ContextBuilder()
140 .SetCompilationPackage("com.app.test")
141 .SetPackageId(0x7f)
142 .SetNameManglerPolicy(
143 NameManglerPolicy{"com.app.test", {"com.android.support"}})
144 .AddSymbolSource(
145 test::StaticSymbolSourceBuilder()
146 .AddPublicSymbol("com.app.test:attr/com.android.support$foo",
147 ResourceId(0x7f010000),
148 test::AttributeBuilder()
149 .SetTypeMask(ResTable_map::TYPE_COLOR)
150 .Build())
151 .Build())
152 .Build();
153
154 std::unique_ptr<ResourceTable> table =
155 test::ResourceTableBuilder()
156 .SetPackageId("com.app.test", 0x7f)
157 .AddValue("com.app.test:style/Theme", ResourceId(0x7f020000),
158 test::StyleBuilder()
159 .AddItem("com.android.support:attr/foo",
160 ResourceUtils::TryParseColor("#ff0000"))
161 .Build())
162 .Build();
163
164 ReferenceLinker linker;
165 ASSERT_TRUE(linker.Consume(context.get(), table.get()));
166
167 Style* style = test::GetValue<Style>(table.get(), "com.app.test:style/Theme");
168 ASSERT_THAT(style, NotNull());
169 ASSERT_EQ(1u, style->entries.size());
170 ASSERT_TRUE(style->entries.front().key.id);
171 EXPECT_EQ(ResourceId(0x7f010000), style->entries.front().key.id.value());
172 }
173
TEST(ReferenceLinkerTest,FailToLinkPrivateSymbols)174 TEST(ReferenceLinkerTest, FailToLinkPrivateSymbols) {
175 std::unique_ptr<ResourceTable> table =
176 test::ResourceTableBuilder()
177 .SetPackageId("com.app.test", 0x7f)
178 .AddReference("com.app.test:string/foo", ResourceId(0x7f020000),
179 "android:string/hidden")
180 .Build();
181
182 std::unique_ptr<IAaptContext> context =
183 test::ContextBuilder()
184 .SetCompilationPackage("com.app.test")
185 .SetPackageId(0x7f)
186 .SetNameManglerPolicy(NameManglerPolicy{"com.app.test"})
187 .AddSymbolSource(
188 util::make_unique<ResourceTableSymbolSource>(table.get()))
189 .AddSymbolSource(
190 test::StaticSymbolSourceBuilder()
191 .AddSymbol("android:string/hidden", ResourceId(0x01040034))
192 .Build())
193 .Build();
194
195 ReferenceLinker linker;
196 ASSERT_FALSE(linker.Consume(context.get(), table.get()));
197 }
198
TEST(ReferenceLinkerTest,FailToLinkPrivateMangledSymbols)199 TEST(ReferenceLinkerTest, FailToLinkPrivateMangledSymbols) {
200 std::unique_ptr<ResourceTable> table =
201 test::ResourceTableBuilder()
202 .SetPackageId("com.app.test", 0x7f)
203 .AddReference("com.app.test:string/foo", ResourceId(0x7f020000),
204 "com.app.lib:string/hidden")
205 .Build();
206
207 std::unique_ptr<IAaptContext> context =
208 test::ContextBuilder()
209 .SetCompilationPackage("com.app.test")
210 .SetPackageId(0x7f)
211 .SetNameManglerPolicy(
212 NameManglerPolicy{"com.app.test", {"com.app.lib"}})
213 .AddSymbolSource(
214 util::make_unique<ResourceTableSymbolSource>(table.get()))
215 .AddSymbolSource(
216 test::StaticSymbolSourceBuilder()
217 .AddSymbol("com.app.test:string/com.app.lib$hidden",
218 ResourceId(0x7f040034))
219 .Build())
220
221 .Build();
222
223 ReferenceLinker linker;
224 ASSERT_FALSE(linker.Consume(context.get(), table.get()));
225 }
226
TEST(ReferenceLinkerTest,FailToLinkPrivateStyleAttributes)227 TEST(ReferenceLinkerTest, FailToLinkPrivateStyleAttributes) {
228 std::unique_ptr<ResourceTable> table =
229 test::ResourceTableBuilder()
230 .SetPackageId("com.app.test", 0x7f)
231 .AddValue("com.app.test:style/Theme",
232 test::StyleBuilder()
233 .AddItem("android:attr/hidden",
234 ResourceUtils::TryParseColor("#ff00ff"))
235 .Build())
236 .Build();
237
238 std::unique_ptr<IAaptContext> context =
239 test::ContextBuilder()
240 .SetCompilationPackage("com.app.test")
241 .SetPackageId(0x7f)
242 .SetNameManglerPolicy(NameManglerPolicy{"com.app.test"})
243 .AddSymbolSource(
244 util::make_unique<ResourceTableSymbolSource>(table.get()))
245 .AddSymbolSource(
246 test::StaticSymbolSourceBuilder()
247 .AddSymbol("android:attr/hidden", ResourceId(0x01010001),
248 test::AttributeBuilder()
249 .SetTypeMask(android::ResTable_map::TYPE_COLOR)
250 .Build())
251 .Build())
252 .Build();
253
254 ReferenceLinker linker;
255 ASSERT_FALSE(linker.Consume(context.get(), table.get()));
256 }
257
TEST(ReferenceLinkerTest,AppsWithSamePackageButDifferentIdAreVisibleNonPublic)258 TEST(ReferenceLinkerTest, AppsWithSamePackageButDifferentIdAreVisibleNonPublic) {
259 NameMangler mangler(NameManglerPolicy{"com.app.test"});
260 SymbolTable table(&mangler);
261 table.AppendSource(test::StaticSymbolSourceBuilder()
262 .AddSymbol("com.app.test:string/foo", ResourceId(0x7f010000))
263 .Build());
264
265 std::string error;
266 const CallSite call_site{ResourceNameRef("com.app.test", ResourceType::kString, "foo")};
267 const SymbolTable::Symbol* symbol = ReferenceLinker::ResolveSymbolCheckVisibility(
268 *test::BuildReference("com.app.test:string/foo"), call_site, &table, &error);
269 ASSERT_THAT(symbol, NotNull());
270 EXPECT_TRUE(error.empty());
271 }
272
TEST(ReferenceLinkerTest,AppsWithDifferentPackageCanNotUseEachOthersAttribute)273 TEST(ReferenceLinkerTest, AppsWithDifferentPackageCanNotUseEachOthersAttribute) {
274 NameMangler mangler(NameManglerPolicy{"com.app.ext"});
275 SymbolTable table(&mangler);
276 table.AppendSource(test::StaticSymbolSourceBuilder()
277 .AddSymbol("com.app.test:attr/foo", ResourceId(0x7f010000),
278 test::AttributeBuilder().Build())
279 .AddPublicSymbol("com.app.test:attr/public_foo", ResourceId(0x7f010001),
280 test::AttributeBuilder().Build())
281 .Build());
282
283 std::string error;
284 const CallSite call_site{ResourceNameRef("com.app.ext", ResourceType::kLayout, "foo")};
285
286 EXPECT_FALSE(ReferenceLinker::CompileXmlAttribute(
287 *test::BuildReference("com.app.test:attr/foo"), call_site, &table, &error));
288 EXPECT_FALSE(error.empty());
289
290 error = "";
291 ASSERT_TRUE(ReferenceLinker::CompileXmlAttribute(
292 *test::BuildReference("com.app.test:attr/public_foo"), call_site, &table, &error));
293 EXPECT_TRUE(error.empty());
294 }
295
296 } // namespace aapt
297