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