blob: fb1cb21dde9261efb94fa21b28eeebbc2475340e [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 Lesinski6a008172016-02-02 17:02:58 -080017#include "filter/ConfigFilter.h"
Adam Lesinskia6fe3452015-12-09 15:20:52 -080018#include "io/FileSystem.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070019#include "link/TableMerger.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 {
28 std::unique_ptr<IAaptContext> mContext;
29
30 void SetUp() override {
31 mContext = test::ContextBuilder()
32 // We are compiling this package.
Adam Lesinskid0f116b2016-07-08 15:00:32 -070033 .setCompilationPackage("com.app.a")
Adam Lesinski1ab598f2015-08-14 14:26:04 -070034
35 // Merge all packages that have this package ID.
36 .setPackageId(0x7f)
37
38 // Mangle all packages that do not have this package name.
Adam Lesinskid0f116b2016-07-08 15:00:32 -070039 .setNameManglerPolicy(NameManglerPolicy{ "com.app.a", { "com.app.b" } })
Adam Lesinski1ab598f2015-08-14 14:26:04 -070040
41 .build();
42 }
43};
44
45TEST_F(TableMergerTest, SimpleMerge) {
46 std::unique_ptr<ResourceTable> tableA = test::ResourceTableBuilder()
Adam Lesinskid0f116b2016-07-08 15:00:32 -070047 .setPackageId("com.app.a", 0x7f)
Adam Lesinski58a20a62016-07-25 17:56:58 -070048 .addReference("com.app.a:id/foo", "com.app.a:id/bar")
49 .addReference("com.app.a:id/bar", "com.app.b:id/foo")
50 .addValue("com.app.a:styleable/view", test::StyleableBuilder()
51 .addItem("com.app.b:id/foo")
Adam Lesinski1ab598f2015-08-14 14:26:04 -070052 .build())
53 .build();
54
55 std::unique_ptr<ResourceTable> tableB = test::ResourceTableBuilder()
Adam Lesinskid0f116b2016-07-08 15:00:32 -070056 .setPackageId("com.app.b", 0x7f)
Adam Lesinski58a20a62016-07-25 17:56:58 -070057 .addSimple("com.app.b:id/foo")
Adam Lesinski1ab598f2015-08-14 14:26:04 -070058 .build();
59
60 ResourceTable finalTable;
Adam Lesinskia6fe3452015-12-09 15:20:52 -080061 TableMerger merger(mContext.get(), &finalTable, TableMergerOptions{});
62 io::FileCollection collection;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070063
Adam Lesinskia6fe3452015-12-09 15:20:52 -080064 ASSERT_TRUE(merger.merge({}, tableA.get()));
Adam Lesinskid0f116b2016-07-08 15:00:32 -070065 ASSERT_TRUE(merger.mergeAndMangle({}, "com.app.b", tableB.get(), &collection));
Adam Lesinski1ab598f2015-08-14 14:26:04 -070066
Adam Lesinskid0f116b2016-07-08 15:00:32 -070067 EXPECT_TRUE(merger.getMergedPackages().count("com.app.b") != 0);
Adam Lesinski1ab598f2015-08-14 14:26:04 -070068
69 // Entries from com.app.a should not be mangled.
Adam Lesinski58a20a62016-07-25 17:56:58 -070070 AAPT_EXPECT_TRUE(finalTable.findResource(test::parseNameOrDie("com.app.a:id/foo")));
71 AAPT_EXPECT_TRUE(finalTable.findResource(test::parseNameOrDie("com.app.a:id/bar")));
72 AAPT_EXPECT_TRUE(finalTable.findResource(test::parseNameOrDie("com.app.a:styleable/view")));
Adam Lesinski1ab598f2015-08-14 14:26:04 -070073
74 // The unmangled name should not be present.
Adam Lesinski58a20a62016-07-25 17:56:58 -070075 AAPT_EXPECT_FALSE(finalTable.findResource(test::parseNameOrDie("com.app.b:id/foo")));
Adam Lesinski1ab598f2015-08-14 14:26:04 -070076
77 // Look for the mangled name.
Adam Lesinski58a20a62016-07-25 17:56:58 -070078 AAPT_EXPECT_TRUE(finalTable.findResource(test::parseNameOrDie("com.app.a:id/com.app.b$foo")));
Adam Lesinski1ab598f2015-08-14 14:26:04 -070079}
80
Adam Lesinskia6fe3452015-12-09 15:20:52 -080081TEST_F(TableMergerTest, MergeFile) {
82 ResourceTable finalTable;
83 TableMergerOptions options;
84 options.autoAddOverlay = false;
85 TableMerger merger(mContext.get(), &finalTable, options);
86
87 ResourceFile fileDesc;
88 fileDesc.config = test::parseConfigOrDie("hdpi-v4");
Adam Lesinski58a20a62016-07-25 17:56:58 -070089 fileDesc.name = test::parseNameOrDie("layout/main");
Adam Lesinskia6fe3452015-12-09 15:20:52 -080090 fileDesc.source = Source("res/layout-hdpi/main.xml");
91 test::TestFile testFile("path/to/res/layout-hdpi/main.xml.flat");
92
93 ASSERT_TRUE(merger.mergeFile(fileDesc, &testFile));
94
95 FileReference* file = test::getValueForConfig<FileReference>(&finalTable,
Adam Lesinski58a20a62016-07-25 17:56:58 -070096 "com.app.a:layout/main",
Adam Lesinskia6fe3452015-12-09 15:20:52 -080097 test::parseConfigOrDie("hdpi-v4"));
98 ASSERT_NE(nullptr, file);
Adam Lesinskid0f116b2016-07-08 15:00:32 -070099 EXPECT_EQ(std::string("res/layout-hdpi-v4/main.xml"), *file->path);
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800100}
101
102TEST_F(TableMergerTest, MergeFileOverlay) {
103 ResourceTable finalTable;
104 TableMergerOptions tableMergerOptions;
105 tableMergerOptions.autoAddOverlay = false;
106 TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
107
108 ResourceFile fileDesc;
Adam Lesinski58a20a62016-07-25 17:56:58 -0700109 fileDesc.name = test::parseNameOrDie("xml/foo");
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800110 test::TestFile fileA("path/to/fileA.xml.flat");
111 test::TestFile fileB("path/to/fileB.xml.flat");
112
113 ASSERT_TRUE(merger.mergeFile(fileDesc, &fileA));
114 ASSERT_TRUE(merger.mergeFileOverlay(fileDesc, &fileB));
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800115}
116
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700117TEST_F(TableMergerTest, MergeFileReferences) {
118 std::unique_ptr<ResourceTable> tableA = test::ResourceTableBuilder()
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700119 .setPackageId("com.app.a", 0x7f)
Adam Lesinski58a20a62016-07-25 17:56:58 -0700120 .addFileReference("com.app.a:xml/file", "res/xml/file.xml")
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700121 .build();
122 std::unique_ptr<ResourceTable> tableB = test::ResourceTableBuilder()
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700123 .setPackageId("com.app.b", 0x7f)
Adam Lesinski58a20a62016-07-25 17:56:58 -0700124 .addFileReference("com.app.b:xml/file", "res/xml/file.xml")
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700125 .build();
126
127 ResourceTable finalTable;
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800128 TableMerger merger(mContext.get(), &finalTable, TableMergerOptions{});
129 io::FileCollection collection;
130 collection.insertFile("res/xml/file.xml");
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700131
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800132 ASSERT_TRUE(merger.merge({}, tableA.get()));
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700133 ASSERT_TRUE(merger.mergeAndMangle({}, "com.app.b", tableB.get(), &collection));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700134
Adam Lesinski58a20a62016-07-25 17:56:58 -0700135 FileReference* f = test::getValue<FileReference>(&finalTable, "com.app.a:xml/file");
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700136 ASSERT_NE(f, nullptr);
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700137 EXPECT_EQ(std::string("res/xml/file.xml"), *f->path);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700138
Adam Lesinski58a20a62016-07-25 17:56:58 -0700139 f = test::getValue<FileReference>(&finalTable, "com.app.a:xml/com.app.b$file");
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700140 ASSERT_NE(f, nullptr);
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700141 EXPECT_EQ(std::string("res/xml/com.app.b$file.xml"), *f->path);
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800142}
143
144TEST_F(TableMergerTest, OverrideResourceWithOverlay) {
145 std::unique_ptr<ResourceTable> base = test::ResourceTableBuilder()
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700146 .setPackageId("", 0x00)
Adam Lesinski58a20a62016-07-25 17:56:58 -0700147 .addValue("bool/foo", ResourceUtils::tryParseBool("true"))
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800148 .build();
149 std::unique_ptr<ResourceTable> overlay = test::ResourceTableBuilder()
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700150 .setPackageId("", 0x00)
Adam Lesinski58a20a62016-07-25 17:56:58 -0700151 .addValue("bool/foo", ResourceUtils::tryParseBool("false"))
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800152 .build();
153
154 ResourceTable finalTable;
155 TableMergerOptions tableMergerOptions;
156 tableMergerOptions.autoAddOverlay = false;
157 TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
158
159 ASSERT_TRUE(merger.merge({}, base.get()));
160 ASSERT_TRUE(merger.mergeOverlay({}, overlay.get()));
161
Adam Lesinski58a20a62016-07-25 17:56:58 -0700162 BinaryPrimitive* foo = test::getValue<BinaryPrimitive>(&finalTable, "com.app.a:bool/foo");
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800163 ASSERT_NE(nullptr, foo);
164 EXPECT_EQ(0x0u, foo->value.data);
165}
166
Alexandria Cornwall6a1f8db2016-08-11 13:49:44 -0700167TEST_F(TableMergerTest, OverrideSameResourceIdsWithOverlay) {
168 std::unique_ptr<ResourceTable> base = test::ResourceTableBuilder()
169 .setPackageId("", 0x7f)
170 .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), SymbolState::kPublic)
171 .build();
172 std::unique_ptr<ResourceTable> overlay = test::ResourceTableBuilder()
173 .setPackageId("", 0x7f)
174 .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), SymbolState::kPublic)
175 .build();
176
177 ResourceTable finalTable;
178 TableMergerOptions tableMergerOptions;
179 tableMergerOptions.autoAddOverlay = false;
180 TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
181
182 ASSERT_TRUE(merger.merge({}, base.get()));
183 ASSERT_TRUE(merger.mergeOverlay({}, overlay.get()));
184}
185
186TEST_F(TableMergerTest, FailToOverrideConflictingTypeIdsWithOverlay) {
187 std::unique_ptr<ResourceTable> base = test::ResourceTableBuilder()
188 .setPackageId("", 0x7f)
189 .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), SymbolState::kPublic)
190 .build();
191 std::unique_ptr<ResourceTable> overlay = test::ResourceTableBuilder()
192 .setPackageId("", 0x7f)
193 .setSymbolState("bool/foo", ResourceId(0x7f, 0x02, 0x0001), SymbolState::kPublic)
194 .build();
195
196 ResourceTable finalTable;
197 TableMergerOptions tableMergerOptions;
198 tableMergerOptions.autoAddOverlay = false;
199 TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
200
201 ASSERT_TRUE(merger.merge({}, base.get()));
202 ASSERT_FALSE(merger.mergeOverlay({}, overlay.get()));
203}
204
205TEST_F(TableMergerTest, FailToOverrideConflictingEntryIdsWithOverlay) {
206 std::unique_ptr<ResourceTable> base = test::ResourceTableBuilder()
207 .setPackageId("", 0x7f)
208 .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), SymbolState::kPublic)
209 .build();
210 std::unique_ptr<ResourceTable> overlay = test::ResourceTableBuilder()
211 .setPackageId("", 0x7f)
212 .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0002), SymbolState::kPublic)
213 .build();
214
215 ResourceTable finalTable;
216 TableMergerOptions tableMergerOptions;
217 tableMergerOptions.autoAddOverlay = false;
218 TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
219
220 ASSERT_TRUE(merger.merge({}, base.get()));
221 ASSERT_FALSE(merger.mergeOverlay({}, overlay.get()));
222}
223
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800224TEST_F(TableMergerTest, MergeAddResourceFromOverlay) {
225 std::unique_ptr<ResourceTable> tableA = test::ResourceTableBuilder()
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700226 .setPackageId("", 0x7f)
Adam Lesinski58a20a62016-07-25 17:56:58 -0700227 .setSymbolState("bool/foo", {}, SymbolState::kUndefined)
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800228 .build();
229 std::unique_ptr<ResourceTable> tableB = test::ResourceTableBuilder()
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700230 .setPackageId("", 0x7f)
Adam Lesinski58a20a62016-07-25 17:56:58 -0700231 .addValue("bool/foo", ResourceUtils::tryParseBool("true"))
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800232 .build();
233
234 ResourceTable finalTable;
235 TableMerger merger(mContext.get(), &finalTable, TableMergerOptions{});
236
237 ASSERT_TRUE(merger.merge({}, tableA.get()));
238 ASSERT_TRUE(merger.mergeOverlay({}, tableB.get()));
239}
240
241TEST_F(TableMergerTest, MergeAddResourceFromOverlayWithAutoAddOverlay) {
242 std::unique_ptr<ResourceTable> tableA = test::ResourceTableBuilder()
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700243 .setPackageId("", 0x7f)
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800244 .build();
245 std::unique_ptr<ResourceTable> tableB = test::ResourceTableBuilder()
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700246 .setPackageId("", 0x7f)
Adam Lesinski58a20a62016-07-25 17:56:58 -0700247 .addValue("bool/foo", ResourceUtils::tryParseBool("true"))
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800248 .build();
249
250 ResourceTable finalTable;
251 TableMergerOptions options;
252 options.autoAddOverlay = true;
253 TableMerger merger(mContext.get(), &finalTable, options);
254
255 ASSERT_TRUE(merger.merge({}, tableA.get()));
256 ASSERT_TRUE(merger.mergeOverlay({}, tableB.get()));
257}
258
259TEST_F(TableMergerTest, FailToMergeNewResourceWithoutAutoAddOverlay) {
260 std::unique_ptr<ResourceTable> tableA = test::ResourceTableBuilder()
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700261 .setPackageId("", 0x7f)
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800262 .build();
263 std::unique_ptr<ResourceTable> tableB = test::ResourceTableBuilder()
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700264 .setPackageId("", 0x7f)
Adam Lesinski58a20a62016-07-25 17:56:58 -0700265 .addValue("bool/foo", ResourceUtils::tryParseBool("true"))
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800266 .build();
267
268 ResourceTable finalTable;
269 TableMergerOptions options;
270 options.autoAddOverlay = false;
271 TableMerger merger(mContext.get(), &finalTable, options);
272
273 ASSERT_TRUE(merger.merge({}, tableA.get()));
274 ASSERT_FALSE(merger.mergeOverlay({}, tableB.get()));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700275}
276
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700277TEST_F(TableMergerTest, OverlaidStyleablesShouldBeMerged) {
278 std::unique_ptr<ResourceTable> tableA = test::ResourceTableBuilder()
279 .setPackageId("com.app.a", 0x7f)
280 .addValue("com.app.a:styleable/Foo", test::StyleableBuilder()
281 .addItem("com.app.a:attr/bar")
282 .addItem("com.app.a:attr/foo", ResourceId(0x01010000))
283 .build())
284 .build();
285
286 std::unique_ptr<ResourceTable> tableB = test::ResourceTableBuilder()
287 .setPackageId("com.app.a", 0x7f)
288 .addValue("com.app.a:styleable/Foo", test::StyleableBuilder()
289 .addItem("com.app.a:attr/bat")
290 .addItem("com.app.a:attr/foo")
291 .build())
292 .build();
293
294 ResourceTable finalTable;
295 TableMergerOptions options;
296 options.autoAddOverlay = true;
297 TableMerger merger(mContext.get(), &finalTable, options);
298
299 ASSERT_TRUE(merger.merge({}, tableA.get()));
300 ASSERT_TRUE(merger.mergeOverlay({}, tableB.get()));
301
302 Debug::printTable(&finalTable, {});
303
304 Styleable* styleable = test::getValue<Styleable>(&finalTable, "com.app.a:styleable/Foo");
305 ASSERT_NE(nullptr, styleable);
306
307 std::vector<Reference> expectedRefs = {
308 Reference(test::parseNameOrDie("com.app.a:attr/bar")),
309 Reference(test::parseNameOrDie("com.app.a:attr/bat")),
310 Reference(test::parseNameOrDie("com.app.a:attr/foo"), ResourceId(0x01010000)),
311 };
312
313 EXPECT_EQ(expectedRefs, styleable->entries);
314}
315
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700316} // namespace aapt