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 21using android::ResTable_map; 22 23namespace aapt { 24 25TEST(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 72TEST(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 137TEST(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 174TEST(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 199TEST(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 227TEST(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 258TEST(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 273TEST(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