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 
     23 namespace aapt {
     24 
     25 TEST(ReferenceLinkerTest, LinkSimpleReferences) {
     26   std::unique_ptr<ResourceTable> table =
     27       test::ResourceTableBuilder()
     28           .SetPackageId("com.app.test", 0x7f)
     29           .AddReference("com.app.test:string/foo", ResourceId(0x7f020000),
     30                         "com.app.test:string/bar")
     31 
     32           // Test use of local reference (w/o package name).
     33           .AddReference("com.app.test:string/bar", ResourceId(0x7f020001),
     34                         "string/baz")
     35 
     36           .AddReference("com.app.test:string/baz", ResourceId(0x7f020002),
     37                         "android:string/ok")
     38           .Build();
     39 
     40   std::unique_ptr<IAaptContext> context =
     41       test::ContextBuilder()
     42           .SetCompilationPackage("com.app.test")
     43           .SetPackageId(0x7f)
     44           .SetNameManglerPolicy(NameManglerPolicy{"com.app.test"})
     45           .AddSymbolSource(
     46               util::make_unique<ResourceTableSymbolSource>(table.get()))
     47           .AddSymbolSource(
     48               test::StaticSymbolSourceBuilder()
     49                   .AddPublicSymbol("android:string/ok", ResourceId(0x01040034))
     50                   .Build())
     51           .Build();
     52 
     53   ReferenceLinker linker;
     54   ASSERT_TRUE(linker.Consume(context.get(), table.get()));
     55 
     56   Reference* ref = test::GetValue<Reference>(table.get(), "com.app.test:string/foo");
     57   ASSERT_NE(nullptr, ref);
     58   AAPT_ASSERT_TRUE(ref->id);
     59   EXPECT_EQ(ResourceId(0x7f020001), ref->id.value());
     60 
     61   ref = test::GetValue<Reference>(table.get(), "com.app.test:string/bar");
     62   ASSERT_NE(nullptr, ref);
     63   AAPT_ASSERT_TRUE(ref->id);
     64   EXPECT_EQ(ResourceId(0x7f020002), ref->id.value());
     65 
     66   ref = test::GetValue<Reference>(table.get(), "com.app.test:string/baz");
     67   ASSERT_NE(nullptr, ref);
     68   AAPT_ASSERT_TRUE(ref->id);
     69   EXPECT_EQ(ResourceId(0x01040034), ref->id.value());
     70 }
     71 
     72 TEST(ReferenceLinkerTest, LinkStyleAttributes) {
     73   std::unique_ptr<ResourceTable> table =
     74       test::ResourceTableBuilder()
     75           .SetPackageId("com.app.test", 0x7f)
     76           .AddValue("com.app.test:style/Theme",
     77                     test::StyleBuilder()
     78                         .SetParent("android:style/Theme.Material")
     79                         .AddItem("android:attr/foo",
     80                                  ResourceUtils::TryParseColor("#ff00ff"))
     81                         .AddItem("android:attr/bar", {} /* placeholder */)
     82                         .Build())
     83           .Build();
     84 
     85   {
     86     // We need to fill in the value for the attribute android:attr/bar after we
     87     // build the
     88     // table, because we need access to the string pool.
     89     Style* style = test::GetValue<Style>(table.get(), "com.app.test:style/Theme");
     90     ASSERT_NE(nullptr, style);
     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_NE(nullptr, style);
    122   AAPT_ASSERT_TRUE(style->parent);
    123   AAPT_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   AAPT_ASSERT_TRUE(style->entries[0].key.id);
    129   EXPECT_EQ(ResourceId(0x01010001), style->entries[0].key.id.value());
    130   ASSERT_NE(nullptr, ValueCast<BinaryPrimitive>(style->entries[0].value.get()));
    131 
    132   AAPT_ASSERT_TRUE(style->entries[1].key.id);
    133   EXPECT_EQ(ResourceId(0x01010002), style->entries[1].key.id.value());
    134   ASSERT_NE(nullptr, ValueCast<BinaryPrimitive>(style->entries[1].value.get()));
    135 }
    136 
    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_NE(nullptr, style);
    169   ASSERT_EQ(1u, style->entries.size());
    170   AAPT_ASSERT_TRUE(style->entries.front().key.id);
    171   EXPECT_EQ(ResourceId(0x7f010000), style->entries.front().key.id.value());
    172 }
    173 
    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 
    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 
    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 
    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_NE(nullptr, symbol);
    270   EXPECT_TRUE(error.empty());
    271 }
    272 
    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   AAPT_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   AAPT_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