• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::Eq;
23 using ::testing::IsNull;
24 using ::testing::NotNull;
25 
26 namespace aapt {
27 
TEST(ReferenceLinkerTest,LinkSimpleReferences)28 TEST(ReferenceLinkerTest, LinkSimpleReferences) {
29   std::unique_ptr<ResourceTable> table =
30       test::ResourceTableBuilder()
31           .AddReference("com.app.test:string/foo", ResourceId(0x7f020000),
32                         "com.app.test:string/bar")
33 
34           // Test use of local reference (w/o package name).
35           .AddReference("com.app.test:string/bar", ResourceId(0x7f020001),
36                         "string/baz")
37 
38           .AddReference("com.app.test:string/baz", ResourceId(0x7f020002),
39                         "android:string/ok")
40           .Build();
41 
42   std::unique_ptr<IAaptContext> context =
43       test::ContextBuilder()
44           .SetCompilationPackage("com.app.test")
45           .SetPackageId(0x7f)
46           .SetNameManglerPolicy(NameManglerPolicy{"com.app.test"})
47           .AddSymbolSource(
48               util::make_unique<ResourceTableSymbolSource>(table.get()))
49           .AddSymbolSource(
50               test::StaticSymbolSourceBuilder()
51                   .AddPublicSymbol("android:string/ok", ResourceId(0x01040034))
52                   .Build())
53           .Build();
54 
55   ReferenceLinker linker;
56   ASSERT_TRUE(linker.Consume(context.get(), table.get()));
57 
58   Reference* ref = test::GetValue<Reference>(table.get(), "com.app.test:string/foo");
59   ASSERT_THAT(ref, NotNull());
60   ASSERT_TRUE(ref->id);
61   EXPECT_EQ(ResourceId(0x7f020001), ref->id.value());
62 
63   ref = test::GetValue<Reference>(table.get(), "com.app.test:string/bar");
64   ASSERT_THAT(ref, NotNull());
65   ASSERT_TRUE(ref->id);
66   EXPECT_EQ(ResourceId(0x7f020002), ref->id.value());
67 
68   ref = test::GetValue<Reference>(table.get(), "com.app.test:string/baz");
69   ASSERT_THAT(ref, NotNull());
70   ASSERT_TRUE(ref->id);
71   EXPECT_EQ(ResourceId(0x01040034), ref->id.value());
72 }
73 
TEST(ReferenceLinkerTest,LinkStyleAttributes)74 TEST(ReferenceLinkerTest, LinkStyleAttributes) {
75   std::unique_ptr<ResourceTable> table =
76       test::ResourceTableBuilder()
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           .AddValue("com.app.test:style/Theme", ResourceId(0x7f020000),
157                     test::StyleBuilder()
158                         .AddItem("com.android.support:attr/foo",
159                                  ResourceUtils::TryParseColor("#ff0000"))
160                         .Build())
161           .Build();
162 
163   ReferenceLinker linker;
164   ASSERT_TRUE(linker.Consume(context.get(), table.get()));
165 
166   Style* style = test::GetValue<Style>(table.get(), "com.app.test:style/Theme");
167   ASSERT_THAT(style, NotNull());
168   ASSERT_EQ(1u, style->entries.size());
169   ASSERT_TRUE(style->entries.front().key.id);
170   EXPECT_EQ(ResourceId(0x7f010000), style->entries.front().key.id.value());
171 }
172 
TEST(ReferenceLinkerTest,FailToLinkPrivateSymbols)173 TEST(ReferenceLinkerTest, FailToLinkPrivateSymbols) {
174   std::unique_ptr<ResourceTable> table =
175       test::ResourceTableBuilder()
176           .AddReference("com.app.test:string/foo", ResourceId(0x7f020000),
177                         "android:string/hidden")
178           .Build();
179 
180   std::unique_ptr<IAaptContext> context =
181       test::ContextBuilder()
182           .SetCompilationPackage("com.app.test")
183           .SetPackageId(0x7f)
184           .SetNameManglerPolicy(NameManglerPolicy{"com.app.test"})
185           .AddSymbolSource(
186               util::make_unique<ResourceTableSymbolSource>(table.get()))
187           .AddSymbolSource(
188               test::StaticSymbolSourceBuilder()
189                   .AddSymbol("android:string/hidden", ResourceId(0x01040034))
190                   .Build())
191           .Build();
192 
193   ReferenceLinker linker;
194   ASSERT_FALSE(linker.Consume(context.get(), table.get()));
195 }
196 
TEST(ReferenceLinkerTest,FailToLinkPrivateMangledSymbols)197 TEST(ReferenceLinkerTest, FailToLinkPrivateMangledSymbols) {
198   std::unique_ptr<ResourceTable> table =
199       test::ResourceTableBuilder()
200           .AddReference("com.app.test:string/foo", ResourceId(0x7f020000),
201                         "com.app.lib:string/hidden")
202           .Build();
203 
204   std::unique_ptr<IAaptContext> context =
205       test::ContextBuilder()
206           .SetCompilationPackage("com.app.test")
207           .SetPackageId(0x7f)
208           .SetNameManglerPolicy(
209               NameManglerPolicy{"com.app.test", {"com.app.lib"}})
210           .AddSymbolSource(
211               util::make_unique<ResourceTableSymbolSource>(table.get()))
212           .AddSymbolSource(
213               test::StaticSymbolSourceBuilder()
214                   .AddSymbol("com.app.test:string/com.app.lib$hidden",
215                              ResourceId(0x7f040034))
216                   .Build())
217 
218           .Build();
219 
220   ReferenceLinker linker;
221   ASSERT_FALSE(linker.Consume(context.get(), table.get()));
222 }
223 
TEST(ReferenceLinkerTest,FailToLinkPrivateStyleAttributes)224 TEST(ReferenceLinkerTest, FailToLinkPrivateStyleAttributes) {
225   std::unique_ptr<ResourceTable> table =
226       test::ResourceTableBuilder()
227           .AddValue("com.app.test:style/Theme",
228                     test::StyleBuilder()
229                         .AddItem("android:attr/hidden",
230                                  ResourceUtils::TryParseColor("#ff00ff"))
231                         .Build())
232           .Build();
233 
234   std::unique_ptr<IAaptContext> context =
235       test::ContextBuilder()
236           .SetCompilationPackage("com.app.test")
237           .SetPackageId(0x7f)
238           .SetNameManglerPolicy(NameManglerPolicy{"com.app.test"})
239           .AddSymbolSource(
240               util::make_unique<ResourceTableSymbolSource>(table.get()))
241           .AddSymbolSource(
242               test::StaticSymbolSourceBuilder()
243                   .AddSymbol("android:attr/hidden", ResourceId(0x01010001),
244                              test::AttributeBuilder()
245                                  .SetTypeMask(android::ResTable_map::TYPE_COLOR)
246                                  .Build())
247                   .Build())
248           .Build();
249 
250   ReferenceLinker linker;
251   ASSERT_FALSE(linker.Consume(context.get(), table.get()));
252 }
253 
TEST(ReferenceLinkerTest,AppsWithSamePackageButDifferentIdAreVisibleNonPublic)254 TEST(ReferenceLinkerTest, AppsWithSamePackageButDifferentIdAreVisibleNonPublic) {
255   NameMangler mangler(NameManglerPolicy{"com.app.test"});
256   SymbolTable table(&mangler);
257   table.AppendSource(test::StaticSymbolSourceBuilder()
258                          .AddSymbol("com.app.test:string/foo", ResourceId(0x7f010000))
259                          .Build());
260 
261   std::string error;
262   const CallSite call_site{"com.app.test"};
263   std::unique_ptr<IAaptContext> context =
264     test::ContextBuilder()
265         .SetCompilationPackage("com.app.test")
266         .SetPackageId(0x7f)
267         .Build();
268   const SymbolTable::Symbol* symbol = ReferenceLinker::ResolveSymbolCheckVisibility(
269       *test::BuildReference("com.app.test:string/foo"), call_site, context.get(), &table, &error);
270   ASSERT_THAT(symbol, NotNull());
271   EXPECT_TRUE(error.empty());
272 }
273 
TEST(ReferenceLinkerTest,AppsWithDifferentPackageCanNotUseEachOthersAttribute)274 TEST(ReferenceLinkerTest, AppsWithDifferentPackageCanNotUseEachOthersAttribute) {
275   NameMangler mangler(NameManglerPolicy{"com.app.ext"});
276   SymbolTable table(&mangler);
277   table.AppendSource(test::StaticSymbolSourceBuilder()
278                          .AddSymbol("com.app.test:attr/foo", ResourceId(0x7f010000),
279                                     test::AttributeBuilder().Build())
280                          .AddPublicSymbol("com.app.test:attr/public_foo", ResourceId(0x7f010001),
281                                           test::AttributeBuilder().Build())
282                          .Build());
283   std::unique_ptr<IAaptContext> context =
284     test::ContextBuilder()
285         .SetCompilationPackage("com.app.ext")
286         .SetPackageId(0x7f)
287         .Build();
288 
289   std::string error;
290   const CallSite call_site{"com.app.ext"};
291 
292   EXPECT_FALSE(ReferenceLinker::CompileXmlAttribute(
293       *test::BuildReference("com.app.test:attr/foo"), call_site, context.get(), &table, &error));
294   EXPECT_FALSE(error.empty());
295 
296   error = "";
297   ASSERT_TRUE(ReferenceLinker::CompileXmlAttribute(
298       *test::BuildReference("com.app.test:attr/public_foo"), call_site, context.get(), &table,
299       &error));
300   EXPECT_TRUE(error.empty());
301 }
302 
TEST(ReferenceLinkerTest,ReferenceWithNoPackageUsesCallSitePackage)303 TEST(ReferenceLinkerTest, ReferenceWithNoPackageUsesCallSitePackage) {
304   NameMangler mangler(NameManglerPolicy{"com.app.test"});
305   SymbolTable table(&mangler);
306   table.AppendSource(test::StaticSymbolSourceBuilder()
307                          .AddSymbol("com.app.test:string/foo", ResourceId(0x7f010000))
308                          .AddSymbol("com.app.lib:string/foo", ResourceId(0x7f010001))
309                          .Build());
310   std::unique_ptr<IAaptContext> context =
311     test::ContextBuilder()
312         .SetCompilationPackage("com.app.test")
313         .SetPackageId(0x7f)
314         .Build();
315 
316   const SymbolTable::Symbol* s = ReferenceLinker::ResolveSymbol(*test::BuildReference("string/foo"),
317                                                                 CallSite{"com.app.test"},
318                                                                 context.get(), &table);
319   ASSERT_THAT(s, NotNull());
320   EXPECT_THAT(s->id, Eq(make_value<ResourceId>(0x7f010000)));
321 
322   s = ReferenceLinker::ResolveSymbol(*test::BuildReference("string/foo"), CallSite{"com.app.lib"},
323                                      context.get(), &table);
324   ASSERT_THAT(s, NotNull());
325   EXPECT_THAT(s->id, Eq(make_value<ResourceId>(0x7f010001)));
326 
327   EXPECT_THAT(ReferenceLinker::ResolveSymbol(*test::BuildReference("string/foo"),
328                                              CallSite{"com.app.bad"}, context.get(), &table),
329               IsNull());
330 }
331 
TEST(ReferenceLinkerTest,ReferenceSymbolFromOtherSplit)332 TEST(ReferenceLinkerTest, ReferenceSymbolFromOtherSplit) {
333   NameMangler mangler(NameManglerPolicy{"com.app.test"});
334   SymbolTable table(&mangler);
335   table.AppendSource(test::StaticSymbolSourceBuilder()
336                          .AddSymbol("com.app.test.feature:string/bar", ResourceId(0x80010000))
337                          .Build());
338   std::set<std::string> split_name_dependencies;
339   split_name_dependencies.insert("feature");
340   std::unique_ptr<IAaptContext> context =
341       test::ContextBuilder()
342           .SetCompilationPackage("com.app.test")
343           .SetPackageId(0x81)
344           .SetSplitNameDependencies(split_name_dependencies)
345           .Build();
346 
347   const SymbolTable::Symbol* s = ReferenceLinker::ResolveSymbol(*test::BuildReference("string/bar"),
348                                                                 CallSite{"com.app.test"},
349                                                                 context.get(), &table);
350   ASSERT_THAT(s, NotNull());
351   EXPECT_THAT(s->id, Eq(make_value<ResourceId>(0x80010000)));
352 
353   s = ReferenceLinker::ResolveSymbol(*test::BuildReference("string/foo"), CallSite{"com.app.lib"},
354                                      context.get(), &table);
355   EXPECT_THAT(s, IsNull());
356 
357   context =
358     test::ContextBuilder()
359         .SetCompilationPackage("com.app.test")
360         .SetPackageId(0x81)
361         .Build();
362   s = ReferenceLinker::ResolveSymbol(*test::BuildReference("string/bar"),CallSite{"com.app.test"},
363                                      context.get(), &table);
364 
365   EXPECT_THAT(s, IsNull());
366 }
367 
TEST(ReferenceLinkerTest,MacroFailToFindDefinition)368 TEST(ReferenceLinkerTest, MacroFailToFindDefinition) {
369   std::unique_ptr<ResourceTable> table =
370       test::ResourceTableBuilder()
371           .AddReference("com.app.test:string/foo", ResourceId(0x7f020000), "com.app.test:macro/bar")
372           .Build();
373 
374   std::unique_ptr<IAaptContext> context =
375       test::ContextBuilder()
376           .SetCompilationPackage("com.app.test")
377           .SetPackageId(0x7f)
378           .SetNameManglerPolicy(NameManglerPolicy{"com.app.test"})
379           .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
380           .Build();
381 
382   ReferenceLinker linker;
383   ASSERT_FALSE(linker.Consume(context.get(), table.get()));
384 }
385 
386 }  // namespace aapt
387