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::NotNull;
     23 
     24 namespace aapt {
     25 
     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 
     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 
    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 
    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_THAT(symbol, NotNull());
    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   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