blob: e0b2b6615d288ae9556ca692229f1fafa3d4bc0c [file] [log] [blame]
Adam Lesinski1ab598f2015-08-14 14:26:04 -07001/*
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
Adam Lesinskicacb28f2016-10-19 12:18:14 -070017#include "link/TableMerger.h"
Adam Lesinski6a008172016-02-02 17:02:58 -080018#include "filter/ConfigFilter.h"
Adam Lesinskia6fe3452015-12-09 15:20:52 -080019#include "io/FileSystem.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070020#include "test/Builders.h"
21#include "test/Context.h"
22
23#include <gtest/gtest.h>
24
25namespace aapt {
26
27struct TableMergerTest : public ::testing::Test {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070028 std::unique_ptr<IAaptContext> mContext;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070029
Adam Lesinskicacb28f2016-10-19 12:18:14 -070030 void SetUp() override {
31 mContext =
32 test::ContextBuilder()
33 // We are compiling this package.
34 .setCompilationPackage("com.app.a")
Adam Lesinski1ab598f2015-08-14 14:26:04 -070035
Adam Lesinskicacb28f2016-10-19 12:18:14 -070036 // Merge all packages that have this package ID.
37 .setPackageId(0x7f)
Adam Lesinski1ab598f2015-08-14 14:26:04 -070038
Adam Lesinskicacb28f2016-10-19 12:18:14 -070039 // Mangle all packages that do not have this package name.
40 .setNameManglerPolicy(NameManglerPolicy{"com.app.a", {"com.app.b"}})
Adam Lesinski1ab598f2015-08-14 14:26:04 -070041
Adam Lesinskicacb28f2016-10-19 12:18:14 -070042 .build();
43 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -070044};
45
46TEST_F(TableMergerTest, SimpleMerge) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070047 std::unique_ptr<ResourceTable> tableA =
48 test::ResourceTableBuilder()
49 .setPackageId("com.app.a", 0x7f)
50 .addReference("com.app.a:id/foo", "com.app.a:id/bar")
51 .addReference("com.app.a:id/bar", "com.app.b:id/foo")
52 .addValue(
53 "com.app.a:styleable/view",
54 test::StyleableBuilder().addItem("com.app.b:id/foo").build())
55 .build();
Adam Lesinski1ab598f2015-08-14 14:26:04 -070056
Adam Lesinskicacb28f2016-10-19 12:18:14 -070057 std::unique_ptr<ResourceTable> tableB = test::ResourceTableBuilder()
58 .setPackageId("com.app.b", 0x7f)
59 .addSimple("com.app.b:id/foo")
60 .build();
Adam Lesinski1ab598f2015-08-14 14:26:04 -070061
Adam Lesinskicacb28f2016-10-19 12:18:14 -070062 ResourceTable finalTable;
63 TableMerger merger(mContext.get(), &finalTable, TableMergerOptions{});
64 io::FileCollection collection;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070065
Adam Lesinskicacb28f2016-10-19 12:18:14 -070066 ASSERT_TRUE(merger.merge({}, tableA.get()));
67 ASSERT_TRUE(
68 merger.mergeAndMangle({}, "com.app.b", tableB.get(), &collection));
Adam Lesinski1ab598f2015-08-14 14:26:04 -070069
Adam Lesinskicacb28f2016-10-19 12:18:14 -070070 EXPECT_TRUE(merger.getMergedPackages().count("com.app.b") != 0);
Adam Lesinski1ab598f2015-08-14 14:26:04 -070071
Adam Lesinskicacb28f2016-10-19 12:18:14 -070072 // Entries from com.app.a should not be mangled.
73 AAPT_EXPECT_TRUE(
74 finalTable.findResource(test::parseNameOrDie("com.app.a:id/foo")));
75 AAPT_EXPECT_TRUE(
76 finalTable.findResource(test::parseNameOrDie("com.app.a:id/bar")));
77 AAPT_EXPECT_TRUE(finalTable.findResource(
78 test::parseNameOrDie("com.app.a:styleable/view")));
Adam Lesinski1ab598f2015-08-14 14:26:04 -070079
Adam Lesinskicacb28f2016-10-19 12:18:14 -070080 // The unmangled name should not be present.
81 AAPT_EXPECT_FALSE(
82 finalTable.findResource(test::parseNameOrDie("com.app.b:id/foo")));
Adam Lesinski1ab598f2015-08-14 14:26:04 -070083
Adam Lesinskicacb28f2016-10-19 12:18:14 -070084 // Look for the mangled name.
85 AAPT_EXPECT_TRUE(finalTable.findResource(
86 test::parseNameOrDie("com.app.a:id/com.app.b$foo")));
Adam Lesinski1ab598f2015-08-14 14:26:04 -070087}
88
Adam Lesinskia6fe3452015-12-09 15:20:52 -080089TEST_F(TableMergerTest, MergeFile) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070090 ResourceTable finalTable;
91 TableMergerOptions options;
92 options.autoAddOverlay = false;
93 TableMerger merger(mContext.get(), &finalTable, options);
Adam Lesinskia6fe3452015-12-09 15:20:52 -080094
Adam Lesinskicacb28f2016-10-19 12:18:14 -070095 ResourceFile fileDesc;
96 fileDesc.config = test::parseConfigOrDie("hdpi-v4");
97 fileDesc.name = test::parseNameOrDie("layout/main");
98 fileDesc.source = Source("res/layout-hdpi/main.xml");
99 test::TestFile testFile("path/to/res/layout-hdpi/main.xml.flat");
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800100
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700101 ASSERT_TRUE(merger.mergeFile(fileDesc, &testFile));
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800102
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700103 FileReference* file = test::getValueForConfig<FileReference>(
104 &finalTable, "com.app.a:layout/main", test::parseConfigOrDie("hdpi-v4"));
105 ASSERT_NE(nullptr, file);
106 EXPECT_EQ(std::string("res/layout-hdpi-v4/main.xml"), *file->path);
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800107}
108
109TEST_F(TableMergerTest, MergeFileOverlay) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700110 ResourceTable finalTable;
111 TableMergerOptions tableMergerOptions;
112 tableMergerOptions.autoAddOverlay = false;
113 TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800114
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700115 ResourceFile fileDesc;
116 fileDesc.name = test::parseNameOrDie("xml/foo");
117 test::TestFile fileA("path/to/fileA.xml.flat");
118 test::TestFile fileB("path/to/fileB.xml.flat");
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800119
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700120 ASSERT_TRUE(merger.mergeFile(fileDesc, &fileA));
121 ASSERT_TRUE(merger.mergeFileOverlay(fileDesc, &fileB));
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800122}
123
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700124TEST_F(TableMergerTest, MergeFileReferences) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700125 std::unique_ptr<ResourceTable> tableA =
126 test::ResourceTableBuilder()
127 .setPackageId("com.app.a", 0x7f)
128 .addFileReference("com.app.a:xml/file", "res/xml/file.xml")
129 .build();
130 std::unique_ptr<ResourceTable> tableB =
131 test::ResourceTableBuilder()
132 .setPackageId("com.app.b", 0x7f)
133 .addFileReference("com.app.b:xml/file", "res/xml/file.xml")
134 .build();
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700135
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700136 ResourceTable finalTable;
137 TableMerger merger(mContext.get(), &finalTable, TableMergerOptions{});
138 io::FileCollection collection;
139 collection.insertFile("res/xml/file.xml");
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700140
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700141 ASSERT_TRUE(merger.merge({}, tableA.get()));
142 ASSERT_TRUE(
143 merger.mergeAndMangle({}, "com.app.b", tableB.get(), &collection));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700144
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700145 FileReference* f =
146 test::getValue<FileReference>(&finalTable, "com.app.a:xml/file");
147 ASSERT_NE(f, nullptr);
148 EXPECT_EQ(std::string("res/xml/file.xml"), *f->path);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700149
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700150 f = test::getValue<FileReference>(&finalTable,
151 "com.app.a:xml/com.app.b$file");
152 ASSERT_NE(f, nullptr);
153 EXPECT_EQ(std::string("res/xml/com.app.b$file.xml"), *f->path);
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800154}
155
156TEST_F(TableMergerTest, OverrideResourceWithOverlay) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700157 std::unique_ptr<ResourceTable> base =
158 test::ResourceTableBuilder()
159 .setPackageId("", 0x00)
160 .addValue("bool/foo", ResourceUtils::tryParseBool("true"))
161 .build();
162 std::unique_ptr<ResourceTable> overlay =
163 test::ResourceTableBuilder()
164 .setPackageId("", 0x00)
165 .addValue("bool/foo", ResourceUtils::tryParseBool("false"))
166 .build();
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800167
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700168 ResourceTable finalTable;
169 TableMergerOptions tableMergerOptions;
170 tableMergerOptions.autoAddOverlay = false;
171 TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800172
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700173 ASSERT_TRUE(merger.merge({}, base.get()));
174 ASSERT_TRUE(merger.mergeOverlay({}, overlay.get()));
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800175
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700176 BinaryPrimitive* foo =
177 test::getValue<BinaryPrimitive>(&finalTable, "com.app.a:bool/foo");
178 ASSERT_NE(nullptr, foo);
179 EXPECT_EQ(0x0u, foo->value.data);
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800180}
181
Alexandria Cornwall6a1f8db2016-08-11 13:49:44 -0700182TEST_F(TableMergerTest, OverrideSameResourceIdsWithOverlay) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700183 std::unique_ptr<ResourceTable> base =
184 test::ResourceTableBuilder()
185 .setPackageId("", 0x7f)
186 .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001),
187 SymbolState::kPublic)
188 .build();
189 std::unique_ptr<ResourceTable> overlay =
190 test::ResourceTableBuilder()
191 .setPackageId("", 0x7f)
192 .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001),
193 SymbolState::kPublic)
194 .build();
Alexandria Cornwall6a1f8db2016-08-11 13:49:44 -0700195
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700196 ResourceTable finalTable;
197 TableMergerOptions tableMergerOptions;
198 tableMergerOptions.autoAddOverlay = false;
199 TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
Alexandria Cornwall6a1f8db2016-08-11 13:49:44 -0700200
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700201 ASSERT_TRUE(merger.merge({}, base.get()));
202 ASSERT_TRUE(merger.mergeOverlay({}, overlay.get()));
Alexandria Cornwall6a1f8db2016-08-11 13:49:44 -0700203}
204
205TEST_F(TableMergerTest, FailToOverrideConflictingTypeIdsWithOverlay) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700206 std::unique_ptr<ResourceTable> base =
207 test::ResourceTableBuilder()
208 .setPackageId("", 0x7f)
209 .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001),
210 SymbolState::kPublic)
211 .build();
212 std::unique_ptr<ResourceTable> overlay =
213 test::ResourceTableBuilder()
214 .setPackageId("", 0x7f)
215 .setSymbolState("bool/foo", ResourceId(0x7f, 0x02, 0x0001),
216 SymbolState::kPublic)
217 .build();
Alexandria Cornwall6a1f8db2016-08-11 13:49:44 -0700218
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700219 ResourceTable finalTable;
220 TableMergerOptions tableMergerOptions;
221 tableMergerOptions.autoAddOverlay = false;
222 TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
Alexandria Cornwall6a1f8db2016-08-11 13:49:44 -0700223
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700224 ASSERT_TRUE(merger.merge({}, base.get()));
225 ASSERT_FALSE(merger.mergeOverlay({}, overlay.get()));
Alexandria Cornwall6a1f8db2016-08-11 13:49:44 -0700226}
227
228TEST_F(TableMergerTest, FailToOverrideConflictingEntryIdsWithOverlay) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700229 std::unique_ptr<ResourceTable> base =
230 test::ResourceTableBuilder()
231 .setPackageId("", 0x7f)
232 .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001),
233 SymbolState::kPublic)
234 .build();
235 std::unique_ptr<ResourceTable> overlay =
236 test::ResourceTableBuilder()
237 .setPackageId("", 0x7f)
238 .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0002),
239 SymbolState::kPublic)
240 .build();
Alexandria Cornwall6a1f8db2016-08-11 13:49:44 -0700241
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700242 ResourceTable finalTable;
243 TableMergerOptions tableMergerOptions;
244 tableMergerOptions.autoAddOverlay = false;
245 TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
Alexandria Cornwall6a1f8db2016-08-11 13:49:44 -0700246
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700247 ASSERT_TRUE(merger.merge({}, base.get()));
248 ASSERT_FALSE(merger.mergeOverlay({}, overlay.get()));
Alexandria Cornwall6a1f8db2016-08-11 13:49:44 -0700249}
250
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800251TEST_F(TableMergerTest, MergeAddResourceFromOverlay) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700252 std::unique_ptr<ResourceTable> tableA =
253 test::ResourceTableBuilder()
254 .setPackageId("", 0x7f)
255 .setSymbolState("bool/foo", {}, SymbolState::kUndefined)
256 .build();
257 std::unique_ptr<ResourceTable> tableB =
258 test::ResourceTableBuilder()
259 .setPackageId("", 0x7f)
260 .addValue("bool/foo", ResourceUtils::tryParseBool("true"))
261 .build();
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800262
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700263 ResourceTable finalTable;
264 TableMerger merger(mContext.get(), &finalTable, TableMergerOptions{});
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800265
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700266 ASSERT_TRUE(merger.merge({}, tableA.get()));
267 ASSERT_TRUE(merger.mergeOverlay({}, tableB.get()));
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800268}
269
270TEST_F(TableMergerTest, MergeAddResourceFromOverlayWithAutoAddOverlay) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700271 std::unique_ptr<ResourceTable> tableA =
272 test::ResourceTableBuilder().setPackageId("", 0x7f).build();
273 std::unique_ptr<ResourceTable> tableB =
274 test::ResourceTableBuilder()
275 .setPackageId("", 0x7f)
276 .addValue("bool/foo", ResourceUtils::tryParseBool("true"))
277 .build();
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800278
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700279 ResourceTable finalTable;
280 TableMergerOptions options;
281 options.autoAddOverlay = true;
282 TableMerger merger(mContext.get(), &finalTable, options);
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800283
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700284 ASSERT_TRUE(merger.merge({}, tableA.get()));
285 ASSERT_TRUE(merger.mergeOverlay({}, tableB.get()));
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800286}
287
288TEST_F(TableMergerTest, FailToMergeNewResourceWithoutAutoAddOverlay) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700289 std::unique_ptr<ResourceTable> tableA =
290 test::ResourceTableBuilder().setPackageId("", 0x7f).build();
291 std::unique_ptr<ResourceTable> tableB =
292 test::ResourceTableBuilder()
293 .setPackageId("", 0x7f)
294 .addValue("bool/foo", ResourceUtils::tryParseBool("true"))
295 .build();
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800296
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700297 ResourceTable finalTable;
298 TableMergerOptions options;
299 options.autoAddOverlay = false;
300 TableMerger merger(mContext.get(), &finalTable, options);
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800301
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700302 ASSERT_TRUE(merger.merge({}, tableA.get()));
303 ASSERT_FALSE(merger.mergeOverlay({}, tableB.get()));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700304}
305
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700306TEST_F(TableMergerTest, OverlaidStyleablesShouldBeMerged) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700307 std::unique_ptr<ResourceTable> tableA =
308 test::ResourceTableBuilder()
309 .setPackageId("com.app.a", 0x7f)
310 .addValue("com.app.a:styleable/Foo",
311 test::StyleableBuilder()
312 .addItem("com.app.a:attr/bar")
313 .addItem("com.app.a:attr/foo", ResourceId(0x01010000))
314 .build())
315 .build();
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700316
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700317 std::unique_ptr<ResourceTable> tableB =
318 test::ResourceTableBuilder()
319 .setPackageId("com.app.a", 0x7f)
320 .addValue("com.app.a:styleable/Foo",
321 test::StyleableBuilder()
322 .addItem("com.app.a:attr/bat")
323 .addItem("com.app.a:attr/foo")
324 .build())
325 .build();
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700326
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700327 ResourceTable finalTable;
328 TableMergerOptions options;
329 options.autoAddOverlay = true;
330 TableMerger merger(mContext.get(), &finalTable, options);
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700331
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700332 ASSERT_TRUE(merger.merge({}, tableA.get()));
333 ASSERT_TRUE(merger.mergeOverlay({}, tableB.get()));
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700334
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700335 Debug::printTable(&finalTable, {});
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700336
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700337 Styleable* styleable =
338 test::getValue<Styleable>(&finalTable, "com.app.a:styleable/Foo");
339 ASSERT_NE(nullptr, styleable);
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700340
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700341 std::vector<Reference> expectedRefs = {
342 Reference(test::parseNameOrDie("com.app.a:attr/bar")),
343 Reference(test::parseNameOrDie("com.app.a:attr/bat")),
344 Reference(test::parseNameOrDie("com.app.a:attr/foo"),
345 ResourceId(0x01010000)),
346 };
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700347
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700348 EXPECT_EQ(expectedRefs, styleable->entries);
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700349}
350
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700351} // namespace aapt