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