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 #include "test/Test.h"
19
20 using android::ResTable_map;
21
22 namespace aapt {
23
TEST(ReferenceLinkerTest,LinkSimpleReferences)24 TEST(ReferenceLinkerTest, LinkSimpleReferences) {
25 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
26 .setPackageId(u"com.app.test", 0x7f)
27 .addReference(u"@com.app.test:string/foo", ResourceId(0x7f020000),
28 u"@com.app.test:string/bar")
29
30 // Test use of local reference (w/o package name).
31 .addReference(u"@com.app.test:string/bar", ResourceId(0x7f020001), u"@string/baz")
32
33 .addReference(u"@com.app.test:string/baz", ResourceId(0x7f020002),
34 u"@android:string/ok")
35 .build();
36
37 std::unique_ptr<IAaptContext> context = test::ContextBuilder()
38 .setCompilationPackage(u"com.app.test")
39 .setPackageId(0x7f)
40 .setNameManglerPolicy(NameManglerPolicy{ u"com.app.test" })
41 .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
42 .addSymbolSource(test::StaticSymbolSourceBuilder()
43 .addPublicSymbol(u"@android:string/ok", ResourceId(0x01040034))
44 .build())
45 .build();
46
47 ReferenceLinker linker;
48 ASSERT_TRUE(linker.consume(context.get(), table.get()));
49
50 Reference* ref = test::getValue<Reference>(table.get(), u"@com.app.test:string/foo");
51 ASSERT_NE(ref, nullptr);
52 AAPT_ASSERT_TRUE(ref->id);
53 EXPECT_EQ(ref->id.value(), ResourceId(0x7f020001));
54
55 ref = test::getValue<Reference>(table.get(), u"@com.app.test:string/bar");
56 ASSERT_NE(ref, nullptr);
57 AAPT_ASSERT_TRUE(ref->id);
58 EXPECT_EQ(ref->id.value(), ResourceId(0x7f020002));
59
60 ref = test::getValue<Reference>(table.get(), u"@com.app.test:string/baz");
61 ASSERT_NE(ref, nullptr);
62 AAPT_ASSERT_TRUE(ref->id);
63 EXPECT_EQ(ref->id.value(), ResourceId(0x01040034));
64 }
65
TEST(ReferenceLinkerTest,LinkStyleAttributes)66 TEST(ReferenceLinkerTest, LinkStyleAttributes) {
67 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
68 .setPackageId(u"com.app.test", 0x7f)
69 .addValue(u"@com.app.test:style/Theme", test::StyleBuilder()
70 .setParent(u"@android:style/Theme.Material")
71 .addItem(u"@android:attr/foo", ResourceUtils::tryParseColor(u"#ff00ff"))
72 .addItem(u"@android:attr/bar", {} /* placeholder */)
73 .build())
74 .build();
75
76 {
77 // We need to fill in the value for the attribute android:attr/bar after we build the
78 // table, because we need access to the string pool.
79 Style* style = test::getValue<Style>(table.get(), u"@com.app.test:style/Theme");
80 ASSERT_NE(style, nullptr);
81 style->entries.back().value = util::make_unique<RawString>(
82 table->stringPool.makeRef(u"one|two"));
83 }
84
85 std::unique_ptr<IAaptContext> context = test::ContextBuilder()
86 .setCompilationPackage(u"com.app.test")
87 .setPackageId(0x7f)
88 .setNameManglerPolicy(NameManglerPolicy{ u"com.app.test" })
89 .addSymbolSource(test::StaticSymbolSourceBuilder()
90 .addPublicSymbol(u"@android:style/Theme.Material",
91 ResourceId(0x01060000))
92 .addPublicSymbol(u"@android:attr/foo", ResourceId(0x01010001),
93 test::AttributeBuilder()
94 .setTypeMask(ResTable_map::TYPE_COLOR)
95 .build())
96 .addPublicSymbol(u"@android:attr/bar", ResourceId(0x01010002),
97 test::AttributeBuilder()
98 .setTypeMask(ResTable_map::TYPE_FLAGS)
99 .addItem(u"one", 0x01)
100 .addItem(u"two", 0x02)
101 .build())
102 .build())
103 .build();
104
105 ReferenceLinker linker;
106 ASSERT_TRUE(linker.consume(context.get(), table.get()));
107
108 Style* style = test::getValue<Style>(table.get(), u"@com.app.test:style/Theme");
109 ASSERT_NE(style, nullptr);
110 AAPT_ASSERT_TRUE(style->parent);
111 AAPT_ASSERT_TRUE(style->parent.value().id);
112 EXPECT_EQ(style->parent.value().id.value(), ResourceId(0x01060000));
113
114 ASSERT_EQ(2u, style->entries.size());
115
116 AAPT_ASSERT_TRUE(style->entries[0].key.id);
117 EXPECT_EQ(style->entries[0].key.id.value(), ResourceId(0x01010001));
118 ASSERT_NE(valueCast<BinaryPrimitive>(style->entries[0].value.get()), nullptr);
119
120 AAPT_ASSERT_TRUE(style->entries[1].key.id);
121 EXPECT_EQ(style->entries[1].key.id.value(), ResourceId(0x01010002));
122 ASSERT_NE(valueCast<BinaryPrimitive>(style->entries[1].value.get()), nullptr);
123 }
124
TEST(ReferenceLinkerTest,LinkMangledReferencesAndAttributes)125 TEST(ReferenceLinkerTest, LinkMangledReferencesAndAttributes) {
126 std::unique_ptr<IAaptContext> context = test::ContextBuilder()
127 .setCompilationPackage(u"com.app.test")
128 .setPackageId(0x7f)
129 .setNameManglerPolicy(NameManglerPolicy{ u"com.app.test", { u"com.android.support" } })
130 .addSymbolSource(test::StaticSymbolSourceBuilder()
131 .addPublicSymbol(u"@com.app.test:attr/com.android.support$foo",
132 ResourceId(0x7f010000),
133 test::AttributeBuilder()
134 .setTypeMask(ResTable_map::TYPE_COLOR)
135 .build())
136 .build())
137 .build();
138
139 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
140 .setPackageId(u"com.app.test", 0x7f)
141 .addValue(u"@com.app.test:style/Theme", ResourceId(0x7f020000),
142 test::StyleBuilder().addItem(u"@com.android.support:attr/foo",
143 ResourceUtils::tryParseColor(u"#ff0000"))
144 .build())
145 .build();
146
147 ReferenceLinker linker;
148 ASSERT_TRUE(linker.consume(context.get(), table.get()));
149
150 Style* style = test::getValue<Style>(table.get(), u"@com.app.test:style/Theme");
151 ASSERT_NE(style, nullptr);
152 ASSERT_EQ(1u, style->entries.size());
153 AAPT_ASSERT_TRUE(style->entries.front().key.id);
154 EXPECT_EQ(style->entries.front().key.id.value(), ResourceId(0x7f010000));
155 }
156
TEST(ReferenceLinkerTest,FailToLinkPrivateSymbols)157 TEST(ReferenceLinkerTest, FailToLinkPrivateSymbols) {
158 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
159 .setPackageId(u"com.app.test", 0x7f)
160 .addReference(u"@com.app.test:string/foo", ResourceId(0x7f020000),
161 u"@android:string/hidden")
162 .build();
163
164 std::unique_ptr<IAaptContext> context = test::ContextBuilder()
165 .setCompilationPackage(u"com.app.test")
166 .setPackageId(0x7f)
167 .setNameManglerPolicy(NameManglerPolicy{ u"com.app.test" })
168 .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
169 .addSymbolSource(test::StaticSymbolSourceBuilder()
170 .addSymbol(u"@android:string/hidden", ResourceId(0x01040034))
171 .build())
172 .build();
173
174 ReferenceLinker linker;
175 ASSERT_FALSE(linker.consume(context.get(), table.get()));
176 }
177
TEST(ReferenceLinkerTest,FailToLinkPrivateMangledSymbols)178 TEST(ReferenceLinkerTest, FailToLinkPrivateMangledSymbols) {
179 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
180 .setPackageId(u"com.app.test", 0x7f)
181 .addReference(u"@com.app.test:string/foo", ResourceId(0x7f020000),
182 u"@com.app.lib:string/hidden")
183 .build();
184
185 std::unique_ptr<IAaptContext> context = test::ContextBuilder()
186 .setCompilationPackage(u"com.app.test")
187 .setPackageId(0x7f)
188 .setNameManglerPolicy(NameManglerPolicy{ u"com.app.test", { u"com.app.lib" } })
189 .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
190 .addSymbolSource(test::StaticSymbolSourceBuilder()
191 .addSymbol(u"@com.app.test:string/com.app.lib$hidden",
192 ResourceId(0x7f040034))
193 .build())
194
195 .build();
196
197 ReferenceLinker linker;
198 ASSERT_FALSE(linker.consume(context.get(), table.get()));
199 }
200
TEST(ReferenceLinkerTest,FailToLinkPrivateStyleAttributes)201 TEST(ReferenceLinkerTest, FailToLinkPrivateStyleAttributes) {
202 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
203 .setPackageId(u"com.app.test", 0x7f)
204 .addValue(u"@com.app.test:style/Theme", test::StyleBuilder()
205 .addItem(u"@android:attr/hidden", ResourceUtils::tryParseColor(u"#ff00ff"))
206 .build())
207 .build();
208
209 std::unique_ptr<IAaptContext> context = test::ContextBuilder()
210 .setCompilationPackage(u"com.app.test")
211 .setPackageId(0x7f)
212 .setNameManglerPolicy(NameManglerPolicy{ u"com.app.test" })
213 .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
214 .addSymbolSource(test::StaticSymbolSourceBuilder()
215 .addSymbol(u"@android:attr/hidden", ResourceId(0x01010001),
216 test::AttributeBuilder()
217 .setTypeMask(
218 android::ResTable_map::TYPE_COLOR)
219 .build())
220 .build())
221 .build();
222
223 ReferenceLinker linker;
224 ASSERT_FALSE(linker.consume(context.get(), table.get()));
225 }
226
227 } // namespace aapt
228