• 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           .SetPackageId("com.app.test", 0x7f)
32           .AddReference("com.app.test:string/foo", ResourceId(0x7f020000),
33                         "com.app.test:string/bar")
34 
35           // Test use of local reference (w/o package name).
36           .AddReference("com.app.test:string/bar", ResourceId(0x7f020001),
37                         "string/baz")
38 
39           .AddReference("com.app.test:string/baz", ResourceId(0x7f020002),
40                         "android:string/ok")
41           .Build();
42 
43   std::unique_ptr<IAaptContext> context =
44       test::ContextBuilder()
45           .SetCompilationPackage("com.app.test")
46           .SetPackageId(0x7f)
47           .SetNameManglerPolicy(NameManglerPolicy{"com.app.test"})
48           .AddSymbolSource(
49               util::make_unique<ResourceTableSymbolSource>(table.get()))
50           .AddSymbolSource(
51               test::StaticSymbolSourceBuilder()
52                   .AddPublicSymbol("android:string/ok", ResourceId(0x01040034))
53                   .Build())
54           .Build();
55 
56   ReferenceLinker linker;
57   ASSERT_TRUE(linker.Consume(context.get(), table.get()));
58 
59   Reference* ref = test::GetValue<Reference>(table.get(), "com.app.test:string/foo");
60   ASSERT_THAT(ref, NotNull());
61   ASSERT_TRUE(ref->id);
62   EXPECT_EQ(ResourceId(0x7f020001), ref->id.value());
63 
64   ref = test::GetValue<Reference>(table.get(), "com.app.test:string/bar");
65   ASSERT_THAT(ref, NotNull());
66   ASSERT_TRUE(ref->id);
67   EXPECT_EQ(ResourceId(0x7f020002), ref->id.value());
68 
69   ref = test::GetValue<Reference>(table.get(), "com.app.test:string/baz");
70   ASSERT_THAT(ref, NotNull());
71   ASSERT_TRUE(ref->id);
72   EXPECT_EQ(ResourceId(0x01040034), ref->id.value());
73 }
74 
TEST(ReferenceLinkerTest,LinkStyleAttributes)75 TEST(ReferenceLinkerTest, LinkStyleAttributes) {
76   std::unique_ptr<ResourceTable> table =
77       test::ResourceTableBuilder()
78           .SetPackageId("com.app.test", 0x7f)
79           .AddValue("com.app.test:style/Theme",
80                     test::StyleBuilder()
81                         .SetParent("android:style/Theme.Material")
82                         .AddItem("android:attr/foo",
83                                  ResourceUtils::TryParseColor("#ff00ff"))
84                         .AddItem("android:attr/bar", {} /* placeholder */)
85                         .Build())
86           .Build();
87 
88   {
89     // We need to fill in the value for the attribute android:attr/bar after we
90     // build the table, because we need access to the string pool.
91     Style* style = test::GetValue<Style>(table.get(), "com.app.test:style/Theme");
92     ASSERT_THAT(style, NotNull());
93     style->entries.back().value =
94         util::make_unique<RawString>(table->string_pool.MakeRef("one|two"));
95   }
96 
97   std::unique_ptr<IAaptContext> context =
98       test::ContextBuilder()
99           .SetCompilationPackage("com.app.test")
100           .SetPackageId(0x7f)
101           .SetNameManglerPolicy(NameManglerPolicy{"com.app.test"})
102           .AddSymbolSource(
103               test::StaticSymbolSourceBuilder()
104                   .AddPublicSymbol("android:style/Theme.Material",
105                                    ResourceId(0x01060000))
106                   .AddPublicSymbol("android:attr/foo", ResourceId(0x01010001),
107                                    test::AttributeBuilder()
108                                        .SetTypeMask(ResTable_map::TYPE_COLOR)
109                                        .Build())
110                   .AddPublicSymbol("android:attr/bar", ResourceId(0x01010002),
111                                    test::AttributeBuilder()
112                                        .SetTypeMask(ResTable_map::TYPE_FLAGS)
113                                        .AddItem("one", 0x01)
114                                        .AddItem("two", 0x02)
115                                        .Build())
116                   .Build())
117           .Build();
118 
119   ReferenceLinker linker;
120   ASSERT_TRUE(linker.Consume(context.get(), table.get()));
121 
122   Style* style = test::GetValue<Style>(table.get(), "com.app.test:style/Theme");
123   ASSERT_THAT(style, NotNull());
124   ASSERT_TRUE(style->parent);
125   ASSERT_TRUE(style->parent.value().id);
126   EXPECT_EQ(ResourceId(0x01060000), style->parent.value().id.value());
127 
128   ASSERT_EQ(2u, style->entries.size());
129 
130   ASSERT_TRUE(style->entries[0].key.id);
131   EXPECT_EQ(ResourceId(0x01010001), style->entries[0].key.id.value());
132   ASSERT_THAT(ValueCast<BinaryPrimitive>(style->entries[0].value.get()), NotNull());
133 
134   ASSERT_TRUE(style->entries[1].key.id);
135   EXPECT_EQ(ResourceId(0x01010002), style->entries[1].key.id.value());
136   ASSERT_THAT(ValueCast<BinaryPrimitive>(style->entries[1].value.get()), NotNull());
137 }
138 
TEST(ReferenceLinkerTest,LinkMangledReferencesAndAttributes)139 TEST(ReferenceLinkerTest, LinkMangledReferencesAndAttributes) {
140   std::unique_ptr<IAaptContext> context =
141       test::ContextBuilder()
142           .SetCompilationPackage("com.app.test")
143           .SetPackageId(0x7f)
144           .SetNameManglerPolicy(
145               NameManglerPolicy{"com.app.test", {"com.android.support"}})
146           .AddSymbolSource(
147               test::StaticSymbolSourceBuilder()
148                   .AddPublicSymbol("com.app.test:attr/com.android.support$foo",
149                                    ResourceId(0x7f010000),
150                                    test::AttributeBuilder()
151                                        .SetTypeMask(ResTable_map::TYPE_COLOR)
152                                        .Build())
153                   .Build())
154           .Build();
155 
156   std::unique_ptr<ResourceTable> table =
157       test::ResourceTableBuilder()
158           .SetPackageId("com.app.test", 0x7f)
159           .AddValue("com.app.test:style/Theme", ResourceId(0x7f020000),
160                     test::StyleBuilder()
161                         .AddItem("com.android.support:attr/foo",
162                                  ResourceUtils::TryParseColor("#ff0000"))
163                         .Build())
164           .Build();
165 
166   ReferenceLinker linker;
167   ASSERT_TRUE(linker.Consume(context.get(), table.get()));
168 
169   Style* style = test::GetValue<Style>(table.get(), "com.app.test:style/Theme");
170   ASSERT_THAT(style, NotNull());
171   ASSERT_EQ(1u, style->entries.size());
172   ASSERT_TRUE(style->entries.front().key.id);
173   EXPECT_EQ(ResourceId(0x7f010000), style->entries.front().key.id.value());
174 }
175 
TEST(ReferenceLinkerTest,FailToLinkPrivateSymbols)176 TEST(ReferenceLinkerTest, FailToLinkPrivateSymbols) {
177   std::unique_ptr<ResourceTable> table =
178       test::ResourceTableBuilder()
179           .SetPackageId("com.app.test", 0x7f)
180           .AddReference("com.app.test:string/foo", ResourceId(0x7f020000),
181                         "android:string/hidden")
182           .Build();
183 
184   std::unique_ptr<IAaptContext> context =
185       test::ContextBuilder()
186           .SetCompilationPackage("com.app.test")
187           .SetPackageId(0x7f)
188           .SetNameManglerPolicy(NameManglerPolicy{"com.app.test"})
189           .AddSymbolSource(
190               util::make_unique<ResourceTableSymbolSource>(table.get()))
191           .AddSymbolSource(
192               test::StaticSymbolSourceBuilder()
193                   .AddSymbol("android:string/hidden", ResourceId(0x01040034))
194                   .Build())
195           .Build();
196 
197   ReferenceLinker linker;
198   ASSERT_FALSE(linker.Consume(context.get(), table.get()));
199 }
200 
TEST(ReferenceLinkerTest,FailToLinkPrivateMangledSymbols)201 TEST(ReferenceLinkerTest, FailToLinkPrivateMangledSymbols) {
202   std::unique_ptr<ResourceTable> table =
203       test::ResourceTableBuilder()
204           .SetPackageId("com.app.test", 0x7f)
205           .AddReference("com.app.test:string/foo", ResourceId(0x7f020000),
206                         "com.app.lib:string/hidden")
207           .Build();
208 
209   std::unique_ptr<IAaptContext> context =
210       test::ContextBuilder()
211           .SetCompilationPackage("com.app.test")
212           .SetPackageId(0x7f)
213           .SetNameManglerPolicy(
214               NameManglerPolicy{"com.app.test", {"com.app.lib"}})
215           .AddSymbolSource(
216               util::make_unique<ResourceTableSymbolSource>(table.get()))
217           .AddSymbolSource(
218               test::StaticSymbolSourceBuilder()
219                   .AddSymbol("com.app.test:string/com.app.lib$hidden",
220                              ResourceId(0x7f040034))
221                   .Build())
222 
223           .Build();
224 
225   ReferenceLinker linker;
226   ASSERT_FALSE(linker.Consume(context.get(), table.get()));
227 }
228 
TEST(ReferenceLinkerTest,FailToLinkPrivateStyleAttributes)229 TEST(ReferenceLinkerTest, FailToLinkPrivateStyleAttributes) {
230   std::unique_ptr<ResourceTable> table =
231       test::ResourceTableBuilder()
232           .SetPackageId("com.app.test", 0x7f)
233           .AddValue("com.app.test:style/Theme",
234                     test::StyleBuilder()
235                         .AddItem("android:attr/hidden",
236                                  ResourceUtils::TryParseColor("#ff00ff"))
237                         .Build())
238           .Build();
239 
240   std::unique_ptr<IAaptContext> context =
241       test::ContextBuilder()
242           .SetCompilationPackage("com.app.test")
243           .SetPackageId(0x7f)
244           .SetNameManglerPolicy(NameManglerPolicy{"com.app.test"})
245           .AddSymbolSource(
246               util::make_unique<ResourceTableSymbolSource>(table.get()))
247           .AddSymbolSource(
248               test::StaticSymbolSourceBuilder()
249                   .AddSymbol("android:attr/hidden", ResourceId(0x01010001),
250                              test::AttributeBuilder()
251                                  .SetTypeMask(android::ResTable_map::TYPE_COLOR)
252                                  .Build())
253                   .Build())
254           .Build();
255 
256   ReferenceLinker linker;
257   ASSERT_FALSE(linker.Consume(context.get(), table.get()));
258 }
259 
TEST(ReferenceLinkerTest,AppsWithSamePackageButDifferentIdAreVisibleNonPublic)260 TEST(ReferenceLinkerTest, AppsWithSamePackageButDifferentIdAreVisibleNonPublic) {
261   NameMangler mangler(NameManglerPolicy{"com.app.test"});
262   SymbolTable table(&mangler);
263   table.AppendSource(test::StaticSymbolSourceBuilder()
264                          .AddSymbol("com.app.test:string/foo", ResourceId(0x7f010000))
265                          .Build());
266 
267   std::string error;
268   const CallSite call_site{"com.app.test"};
269   std::unique_ptr<IAaptContext> context =
270     test::ContextBuilder()
271         .SetCompilationPackage("com.app.test")
272         .SetPackageId(0x7f)
273         .Build();
274   const SymbolTable::Symbol* symbol = ReferenceLinker::ResolveSymbolCheckVisibility(
275       *test::BuildReference("com.app.test:string/foo"), call_site, context.get(), &table, &error);
276   ASSERT_THAT(symbol, NotNull());
277   EXPECT_TRUE(error.empty());
278 }
279 
TEST(ReferenceLinkerTest,AppsWithDifferentPackageCanNotUseEachOthersAttribute)280 TEST(ReferenceLinkerTest, AppsWithDifferentPackageCanNotUseEachOthersAttribute) {
281   NameMangler mangler(NameManglerPolicy{"com.app.ext"});
282   SymbolTable table(&mangler);
283   table.AppendSource(test::StaticSymbolSourceBuilder()
284                          .AddSymbol("com.app.test:attr/foo", ResourceId(0x7f010000),
285                                     test::AttributeBuilder().Build())
286                          .AddPublicSymbol("com.app.test:attr/public_foo", ResourceId(0x7f010001),
287                                           test::AttributeBuilder().Build())
288                          .Build());
289   std::unique_ptr<IAaptContext> context =
290     test::ContextBuilder()
291         .SetCompilationPackage("com.app.ext")
292         .SetPackageId(0x7f)
293         .Build();
294 
295   std::string error;
296   const CallSite call_site{"com.app.ext"};
297 
298   EXPECT_FALSE(ReferenceLinker::CompileXmlAttribute(
299       *test::BuildReference("com.app.test:attr/foo"), call_site, context.get(), &table, &error));
300   EXPECT_FALSE(error.empty());
301 
302   error = "";
303   ASSERT_TRUE(ReferenceLinker::CompileXmlAttribute(
304       *test::BuildReference("com.app.test:attr/public_foo"), call_site, context.get(), &table,
305       &error));
306   EXPECT_TRUE(error.empty());
307 }
308 
TEST(ReferenceLinkerTest,ReferenceWithNoPackageUsesCallSitePackage)309 TEST(ReferenceLinkerTest, ReferenceWithNoPackageUsesCallSitePackage) {
310   NameMangler mangler(NameManglerPolicy{"com.app.test"});
311   SymbolTable table(&mangler);
312   table.AppendSource(test::StaticSymbolSourceBuilder()
313                          .AddSymbol("com.app.test:string/foo", ResourceId(0x7f010000))
314                          .AddSymbol("com.app.lib:string/foo", ResourceId(0x7f010001))
315                          .Build());
316   std::unique_ptr<IAaptContext> context =
317     test::ContextBuilder()
318         .SetCompilationPackage("com.app.test")
319         .SetPackageId(0x7f)
320         .Build();
321 
322   const SymbolTable::Symbol* s = ReferenceLinker::ResolveSymbol(*test::BuildReference("string/foo"),
323                                                                 CallSite{"com.app.test"},
324                                                                 context.get(), &table);
325   ASSERT_THAT(s, NotNull());
326   EXPECT_THAT(s->id, Eq(make_value<ResourceId>(0x7f010000)));
327 
328   s = ReferenceLinker::ResolveSymbol(*test::BuildReference("string/foo"), CallSite{"com.app.lib"},
329                                      context.get(), &table);
330   ASSERT_THAT(s, NotNull());
331   EXPECT_THAT(s->id, Eq(make_value<ResourceId>(0x7f010001)));
332 
333   EXPECT_THAT(ReferenceLinker::ResolveSymbol(*test::BuildReference("string/foo"),
334                                              CallSite{"com.app.bad"}, context.get(), &table),
335               IsNull());
336 }
337 
TEST(ReferenceLinkerTest,ReferenceSymbolFromOtherSplit)338 TEST(ReferenceLinkerTest, ReferenceSymbolFromOtherSplit) {
339   NameMangler mangler(NameManglerPolicy{"com.app.test"});
340   SymbolTable table(&mangler);
341   table.AppendSource(test::StaticSymbolSourceBuilder()
342                          .AddSymbol("com.app.test.feature:string/bar", ResourceId(0x80010000))
343                          .Build());
344   std::set<std::string> split_name_dependencies;
345   split_name_dependencies.insert("feature");
346   std::unique_ptr<IAaptContext> context =
347       test::ContextBuilder()
348           .SetCompilationPackage("com.app.test")
349           .SetPackageId(0x81)
350           .SetSplitNameDependencies(split_name_dependencies)
351           .Build();
352 
353   const SymbolTable::Symbol* s = ReferenceLinker::ResolveSymbol(*test::BuildReference("string/bar"),
354                                                                 CallSite{"com.app.test"},
355                                                                 context.get(), &table);
356   ASSERT_THAT(s, NotNull());
357   EXPECT_THAT(s->id, Eq(make_value<ResourceId>(0x80010000)));
358 
359   s = ReferenceLinker::ResolveSymbol(*test::BuildReference("string/foo"), CallSite{"com.app.lib"},
360                                      context.get(), &table);
361   EXPECT_THAT(s, IsNull());
362 
363   context =
364     test::ContextBuilder()
365         .SetCompilationPackage("com.app.test")
366         .SetPackageId(0x81)
367         .Build();
368   s = ReferenceLinker::ResolveSymbol(*test::BuildReference("string/bar"),CallSite{"com.app.test"},
369                                      context.get(), &table);
370 
371   EXPECT_THAT(s, IsNull());
372 }
373 
374 }  // namespace aapt
375