Home | History | Annotate | Download | only in link
      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 
     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 
     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 
    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 
    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 
    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 
    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 
    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   const SymbolTable::Symbol* symbol = ReferenceLinker::ResolveSymbolCheckVisibility(
    270       *test::BuildReference("com.app.test:string/foo"), call_site, &table, &error);
    271   ASSERT_THAT(symbol, NotNull());
    272   EXPECT_TRUE(error.empty());
    273 }
    274 
    275 TEST(ReferenceLinkerTest, AppsWithDifferentPackageCanNotUseEachOthersAttribute) {
    276   NameMangler mangler(NameManglerPolicy{"com.app.ext"});
    277   SymbolTable table(&mangler);
    278   table.AppendSource(test::StaticSymbolSourceBuilder()
    279                          .AddSymbol("com.app.test:attr/foo", ResourceId(0x7f010000),
    280                                     test::AttributeBuilder().Build())
    281                          .AddPublicSymbol("com.app.test:attr/public_foo", ResourceId(0x7f010001),
    282                                           test::AttributeBuilder().Build())
    283                          .Build());
    284 
    285   std::string error;
    286   const CallSite call_site{"com.app.ext"};
    287 
    288   EXPECT_FALSE(ReferenceLinker::CompileXmlAttribute(
    289       *test::BuildReference("com.app.test:attr/foo"), call_site, &table, &error));
    290   EXPECT_FALSE(error.empty());
    291 
    292   error = "";
    293   ASSERT_TRUE(ReferenceLinker::CompileXmlAttribute(
    294       *test::BuildReference("com.app.test:attr/public_foo"), call_site, &table, &error));
    295   EXPECT_TRUE(error.empty());
    296 }
    297 
    298 TEST(ReferenceLinkerTest, ReferenceWithNoPackageUsesCallSitePackage) {
    299   NameMangler mangler(NameManglerPolicy{"com.app.test"});
    300   SymbolTable table(&mangler);
    301   table.AppendSource(test::StaticSymbolSourceBuilder()
    302                          .AddSymbol("com.app.test:string/foo", ResourceId(0x7f010000))
    303                          .AddSymbol("com.app.lib:string/foo", ResourceId(0x7f010001))
    304                          .Build());
    305 
    306   const SymbolTable::Symbol* s = ReferenceLinker::ResolveSymbol(*test::BuildReference("string/foo"),
    307                                                                 CallSite{"com.app.test"}, &table);
    308   ASSERT_THAT(s, NotNull());
    309   EXPECT_THAT(s->id, Eq(make_value<ResourceId>(0x7f010000)));
    310 
    311   s = ReferenceLinker::ResolveSymbol(*test::BuildReference("string/foo"), CallSite{"com.app.lib"},
    312                                      &table);
    313   ASSERT_THAT(s, NotNull());
    314   EXPECT_THAT(s->id, Eq(make_value<ResourceId>(0x7f010001)));
    315 
    316   EXPECT_THAT(ReferenceLinker::ResolveSymbol(*test::BuildReference("string/foo"),
    317                                              CallSite{"com.app.bad"}, &table),
    318               IsNull());
    319 }
    320 
    321 }  // namespace aapt
    322