blob: 4cbf2d3a826cb356e3915f5b02c84b487c09286a [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 Lesinskice5e56e2016-10-21 17:56:45 -070018
Adam Lesinski6a008172016-02-02 17:02:58 -080019#include "filter/ConfigFilter.h"
Adam Lesinskia6fe3452015-12-09 15:20:52 -080020#include "io/FileSystem.h"
Adam Lesinskice5e56e2016-10-21 17:56:45 -070021#include "test/Test.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070022
Adam Lesinski5924d8c2017-05-30 15:15:58 -070023using ::aapt::test::ValueEq;
24using ::testing::Contains;
Adam Lesinski5924d8c2017-05-30 15:15:58 -070025using ::testing::Eq;
Adam Lesinski8780eb62017-10-31 17:44:39 -070026using ::testing::Field;
27using ::testing::NotNull;
28using ::testing::Pointee;
29using ::testing::StrEq;
30using ::testing::UnorderedElementsAreArray;
Adam Lesinski5924d8c2017-05-30 15:15:58 -070031
Winson62ac8b52019-12-04 08:36:48 -080032using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
33
Adam Lesinski1ab598f2015-08-14 14:26:04 -070034namespace aapt {
35
36struct TableMergerTest : public ::testing::Test {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070037 std::unique_ptr<IAaptContext> context_;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070038
Adam Lesinskicacb28f2016-10-19 12:18:14 -070039 void SetUp() override {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070040 context_ =
Adam Lesinskicacb28f2016-10-19 12:18:14 -070041 test::ContextBuilder()
42 // We are compiling this package.
Adam Lesinskice5e56e2016-10-21 17:56:45 -070043 .SetCompilationPackage("com.app.a")
Adam Lesinski1ab598f2015-08-14 14:26:04 -070044
Adam Lesinskicacb28f2016-10-19 12:18:14 -070045 // Merge all packages that have this package ID.
Adam Lesinskice5e56e2016-10-21 17:56:45 -070046 .SetPackageId(0x7f)
Adam Lesinski1ab598f2015-08-14 14:26:04 -070047
Adam Lesinskicacb28f2016-10-19 12:18:14 -070048 // Mangle all packages that do not have this package name.
Adam Lesinskice5e56e2016-10-21 17:56:45 -070049 .SetNameManglerPolicy(NameManglerPolicy{"com.app.a", {"com.app.b"}})
Adam Lesinski1ab598f2015-08-14 14:26:04 -070050
Adam Lesinskice5e56e2016-10-21 17:56:45 -070051 .Build();
Adam Lesinskicacb28f2016-10-19 12:18:14 -070052 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -070053};
54
55TEST_F(TableMergerTest, SimpleMerge) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070056 std::unique_ptr<ResourceTable> table_a =
Adam Lesinskicacb28f2016-10-19 12:18:14 -070057 test::ResourceTableBuilder()
Adam Lesinskice5e56e2016-10-21 17:56:45 -070058 .AddReference("com.app.a:id/foo", "com.app.a:id/bar")
59 .AddReference("com.app.a:id/bar", "com.app.b:id/foo")
Ryan Mitchell1d008d12021-03-19 14:54:17 -070060 .AddValue("com.app.a:styleable/view",
61 test::StyleableBuilder().AddItem("com.app.b:id/foo").Build())
Adam Lesinskice5e56e2016-10-21 17:56:45 -070062 .Build();
Adam Lesinski1ab598f2015-08-14 14:26:04 -070063
Adam Lesinskice5e56e2016-10-21 17:56:45 -070064 std::unique_ptr<ResourceTable> table_b = test::ResourceTableBuilder()
Adam Lesinskice5e56e2016-10-21 17:56:45 -070065 .AddSimple("com.app.b:id/foo")
66 .Build();
Adam Lesinski1ab598f2015-08-14 14:26:04 -070067
Adam Lesinskice5e56e2016-10-21 17:56:45 -070068 ResourceTable final_table;
69 TableMerger merger(context_.get(), &final_table, TableMergerOptions{});
Adam Lesinski1ab598f2015-08-14 14:26:04 -070070
Adam Lesinski00451162017-10-03 07:44:08 -070071 ASSERT_TRUE(merger.Merge({}, table_a.get(), false /*overlay*/));
Adam Lesinski8780eb62017-10-31 17:44:39 -070072 ASSERT_TRUE(merger.MergeAndMangle({}, "com.app.b", table_b.get()));
Adam Lesinski1ab598f2015-08-14 14:26:04 -070073
Adam Lesinskice5e56e2016-10-21 17:56:45 -070074 EXPECT_TRUE(merger.merged_packages().count("com.app.b") != 0);
Adam Lesinski1ab598f2015-08-14 14:26:04 -070075
Adam Lesinskicacb28f2016-10-19 12:18:14 -070076 // Entries from com.app.a should not be mangled.
Adam Lesinski5924d8c2017-05-30 15:15:58 -070077 EXPECT_TRUE(final_table.FindResource(test::ParseNameOrDie("com.app.a:id/foo")));
78 EXPECT_TRUE(final_table.FindResource(test::ParseNameOrDie("com.app.a:id/bar")));
79 EXPECT_TRUE(final_table.FindResource(test::ParseNameOrDie("com.app.a:styleable/view")));
Adam Lesinski1ab598f2015-08-14 14:26:04 -070080
Adam Lesinskicacb28f2016-10-19 12:18:14 -070081 // The unmangled name should not be present.
Adam Lesinski5924d8c2017-05-30 15:15:58 -070082 EXPECT_FALSE(final_table.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.
Adam Lesinski5924d8c2017-05-30 15:15:58 -070085 EXPECT_TRUE(final_table.FindResource(test::ParseNameOrDie("com.app.a:id/com.app.b$foo")));
Adam Lesinski1ab598f2015-08-14 14:26:04 -070086}
87
Adam Lesinskia6fe3452015-12-09 15:20:52 -080088TEST_F(TableMergerTest, MergeFile) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070089 ResourceTable final_table;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070090 TableMergerOptions options;
Adam Lesinskice5e56e2016-10-21 17:56:45 -070091 options.auto_add_overlay = false;
92 TableMerger merger(context_.get(), &final_table, options);
Adam Lesinskia6fe3452015-12-09 15:20:52 -080093
Adam Lesinskice5e56e2016-10-21 17:56:45 -070094 ResourceFile file_desc;
95 file_desc.config = test::ParseConfigOrDie("hdpi-v4");
96 file_desc.name = test::ParseNameOrDie("layout/main");
97 file_desc.source = Source("res/layout-hdpi/main.xml");
98 test::TestFile test_file("path/to/res/layout-hdpi/main.xml.flat");
Adam Lesinskia6fe3452015-12-09 15:20:52 -080099
Adam Lesinski00451162017-10-03 07:44:08 -0700100 ASSERT_TRUE(merger.MergeFile(file_desc, false /*overlay*/, &test_file));
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800101
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700102 FileReference* file = test::GetValueForConfig<FileReference>(
103 &final_table, "com.app.a:layout/main", test::ParseConfigOrDie("hdpi-v4"));
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700104 ASSERT_THAT(file, NotNull());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700105 EXPECT_EQ(std::string("res/layout-hdpi-v4/main.xml"), *file->path);
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800106}
107
108TEST_F(TableMergerTest, MergeFileOverlay) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700109 ResourceTable final_table;
110 TableMergerOptions options;
111 options.auto_add_overlay = false;
112 TableMerger merger(context_.get(), &final_table, options);
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800113
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700114 ResourceFile file_desc;
115 file_desc.name = test::ParseNameOrDie("xml/foo");
116 test::TestFile file_a("path/to/fileA.xml.flat");
117 test::TestFile file_b("path/to/fileB.xml.flat");
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800118
Adam Lesinski00451162017-10-03 07:44:08 -0700119 ASSERT_TRUE(merger.MergeFile(file_desc, false /*overlay*/, &file_a));
120 ASSERT_TRUE(merger.MergeFile(file_desc, true /*overlay*/, &file_b));
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800121}
122
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700123TEST_F(TableMergerTest, MergeFileReferences) {
Adam Lesinski8780eb62017-10-31 17:44:39 -0700124 test::TestFile file_a("res/xml/file.xml");
125 test::TestFile file_b("res/xml/file.xml");
126
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700127 std::unique_ptr<ResourceTable> table_a =
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700128 test::ResourceTableBuilder()
Adam Lesinski8780eb62017-10-31 17:44:39 -0700129 .AddFileReference("com.app.a:xml/file", "res/xml/file.xml", &file_a)
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700130 .Build();
131 std::unique_ptr<ResourceTable> table_b =
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700132 test::ResourceTableBuilder()
Adam Lesinski8780eb62017-10-31 17:44:39 -0700133 .AddFileReference("com.app.b:xml/file", "res/xml/file.xml", &file_b)
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700134 .Build();
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700135
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700136 ResourceTable final_table;
137 TableMerger merger(context_.get(), &final_table, TableMergerOptions{});
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700138
Adam Lesinski00451162017-10-03 07:44:08 -0700139 ASSERT_TRUE(merger.Merge({}, table_a.get(), false /*overlay*/));
Adam Lesinski8780eb62017-10-31 17:44:39 -0700140 ASSERT_TRUE(merger.MergeAndMangle({}, "com.app.b", table_b.get()));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700141
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700142 FileReference* f = test::GetValue<FileReference>(&final_table, "com.app.a:xml/file");
143 ASSERT_THAT(f, NotNull());
Adam Lesinski8780eb62017-10-31 17:44:39 -0700144 EXPECT_THAT(*f->path, StrEq("res/xml/file.xml"));
145 EXPECT_THAT(f->file, Eq(&file_a));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700146
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700147 f = test::GetValue<FileReference>(&final_table, "com.app.a:xml/com.app.b$file");
148 ASSERT_THAT(f, NotNull());
Adam Lesinski8780eb62017-10-31 17:44:39 -0700149 EXPECT_THAT(*f->path, StrEq("res/xml/com.app.b$file.xml"));
150 EXPECT_THAT(f->file, Eq(&file_b));
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800151}
152
153TEST_F(TableMergerTest, OverrideResourceWithOverlay) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700154 std::unique_ptr<ResourceTable> base =
155 test::ResourceTableBuilder()
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700156 .AddValue("bool/foo", ResourceUtils::TryParseBool("true"))
157 .Build();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700158 std::unique_ptr<ResourceTable> overlay =
159 test::ResourceTableBuilder()
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700160 .AddValue("bool/foo", ResourceUtils::TryParseBool("false"))
161 .Build();
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800162
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700163 ResourceTable final_table;
164 TableMergerOptions options;
165 options.auto_add_overlay = false;
166 TableMerger merger(context_.get(), &final_table, options);
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800167
Adam Lesinski00451162017-10-03 07:44:08 -0700168 ASSERT_TRUE(merger.Merge({}, base.get(), false /*overlay*/));
169 ASSERT_TRUE(merger.Merge({}, overlay.get(), true /*overlay*/));
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800170
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700171 BinaryPrimitive* foo = test::GetValue<BinaryPrimitive>(&final_table, "com.app.a:bool/foo");
172 ASSERT_THAT(foo,
173 Pointee(Field(&BinaryPrimitive::value, Field(&android::Res_value::data, Eq(0u)))));
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800174}
175
Ryan Mitchella9e31602018-06-28 16:41:38 -0700176TEST_F(TableMergerTest, DoNotOverrideResourceComment) {
177 std::unique_ptr<Value> foo_original = ResourceUtils::TryParseBool("true");
178 foo_original->SetComment(android::StringPiece("Original foo comment"));
179 std::unique_ptr<Value> bar_original = ResourceUtils::TryParseBool("true");
180
181 std::unique_ptr<Value> foo_overlay = ResourceUtils::TryParseBool("false");
182 foo_overlay->SetComment(android::StringPiece("Overlay foo comment"));
183 std::unique_ptr<Value> bar_overlay = ResourceUtils::TryParseBool("false");
184 bar_overlay->SetComment(android::StringPiece("Overlay bar comment"));
185 std::unique_ptr<Value> baz_overlay = ResourceUtils::TryParseBool("false");
186 baz_overlay->SetComment(android::StringPiece("Overlay baz comment"));
187
188 std::unique_ptr<ResourceTable> base =
189 test::ResourceTableBuilder()
Ryan Mitchella9e31602018-06-28 16:41:38 -0700190 .AddValue("bool/foo", std::move(foo_original))
191 .AddValue("bool/bar", std::move(bar_original))
192 .Build();
193
194 std::unique_ptr<ResourceTable> overlay =
195 test::ResourceTableBuilder()
Ryan Mitchella9e31602018-06-28 16:41:38 -0700196 .AddValue("bool/foo", std::move(foo_overlay))
197 .AddValue("bool/bar", std::move(bar_overlay))
198 .AddValue("bool/baz", std::move(baz_overlay))
199 .Build();
200
201 ResourceTable final_table;
202 TableMergerOptions options;
203 options.auto_add_overlay = true;
204 TableMerger merger(context_.get(), &final_table, options);
205
206 ASSERT_TRUE(merger.Merge({}, base.get(), false /*overlay*/));
207 ASSERT_TRUE(merger.Merge({}, overlay.get(), true /*overlay*/));
208
209 BinaryPrimitive* foo = test::GetValue<BinaryPrimitive>(&final_table, "com.app.a:bool/foo");
210 EXPECT_THAT(foo, Pointee(Property(&BinaryPrimitive::GetComment, StrEq("Original foo comment"))));
211 BinaryPrimitive* bar = test::GetValue<BinaryPrimitive>(&final_table, "com.app.a:bool/bar");
212 EXPECT_THAT(bar, Pointee(Property(&BinaryPrimitive::GetComment, StrEq(""))));
213 BinaryPrimitive* baz = test::GetValue<BinaryPrimitive>(&final_table, "com.app.a:bool/baz");
214 EXPECT_THAT(baz, Pointee(Property(&BinaryPrimitive::GetComment, StrEq("Overlay baz comment"))));
215}
216
Alexandria Cornwall6a1f8db2016-08-11 13:49:44 -0700217TEST_F(TableMergerTest, OverrideSameResourceIdsWithOverlay) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700218 std::unique_ptr<ResourceTable> base =
219 test::ResourceTableBuilder()
Adam Lesinski71be7052017-12-12 16:48:07 -0800220 .SetSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), Visibility::Level::kPublic)
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700221 .Build();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700222 std::unique_ptr<ResourceTable> overlay =
223 test::ResourceTableBuilder()
Adam Lesinski71be7052017-12-12 16:48:07 -0800224 .SetSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), Visibility::Level::kPublic)
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700225 .Build();
Alexandria Cornwall6a1f8db2016-08-11 13:49:44 -0700226
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700227 ResourceTable final_table;
228 TableMergerOptions options;
229 options.auto_add_overlay = false;
230 TableMerger merger(context_.get(), &final_table, options);
Alexandria Cornwall6a1f8db2016-08-11 13:49:44 -0700231
Adam Lesinski00451162017-10-03 07:44:08 -0700232 ASSERT_TRUE(merger.Merge({}, base.get(), false /*overlay*/));
233 ASSERT_TRUE(merger.Merge({}, overlay.get(), true /*overlay*/));
Alexandria Cornwall6a1f8db2016-08-11 13:49:44 -0700234}
235
236TEST_F(TableMergerTest, FailToOverrideConflictingTypeIdsWithOverlay) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700237 std::unique_ptr<ResourceTable> base =
238 test::ResourceTableBuilder()
Adam Lesinski71be7052017-12-12 16:48:07 -0800239 .SetSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), Visibility::Level::kPublic)
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700240 .Build();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700241 std::unique_ptr<ResourceTable> overlay =
242 test::ResourceTableBuilder()
Adam Lesinski71be7052017-12-12 16:48:07 -0800243 .SetSymbolState("bool/foo", ResourceId(0x7f, 0x02, 0x0001), Visibility::Level::kPublic)
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700244 .Build();
Alexandria Cornwall6a1f8db2016-08-11 13:49:44 -0700245
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700246 ResourceTable final_table;
247 TableMergerOptions options;
248 options.auto_add_overlay = false;
249 TableMerger merger(context_.get(), &final_table, options);
Alexandria Cornwall6a1f8db2016-08-11 13:49:44 -0700250
Adam Lesinski00451162017-10-03 07:44:08 -0700251 ASSERT_TRUE(merger.Merge({}, base.get(), false /*overlay*/));
252 ASSERT_FALSE(merger.Merge({}, overlay.get(), true /*overlay*/));
Alexandria Cornwall6a1f8db2016-08-11 13:49:44 -0700253}
254
255TEST_F(TableMergerTest, FailToOverrideConflictingEntryIdsWithOverlay) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700256 std::unique_ptr<ResourceTable> base =
257 test::ResourceTableBuilder()
Adam Lesinski71be7052017-12-12 16:48:07 -0800258 .SetSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), Visibility::Level::kPublic)
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700259 .Build();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700260 std::unique_ptr<ResourceTable> overlay =
261 test::ResourceTableBuilder()
Adam Lesinski71be7052017-12-12 16:48:07 -0800262 .SetSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0002), Visibility::Level::kPublic)
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700263 .Build();
Alexandria Cornwall6a1f8db2016-08-11 13:49:44 -0700264
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700265 ResourceTable final_table;
266 TableMergerOptions options;
267 options.auto_add_overlay = false;
268 TableMerger merger(context_.get(), &final_table, options);
Alexandria Cornwall6a1f8db2016-08-11 13:49:44 -0700269
Adam Lesinski00451162017-10-03 07:44:08 -0700270 ASSERT_TRUE(merger.Merge({}, base.get(), false /*overlay*/));
271 ASSERT_FALSE(merger.Merge({}, overlay.get(), true /*overlay*/));
Alexandria Cornwall6a1f8db2016-08-11 13:49:44 -0700272}
273
Izabela Orlowskad51efe82018-04-24 18:18:29 +0100274TEST_F(TableMergerTest, FailConflictingVisibility) {
275 std::unique_ptr<ResourceTable> base =
276 test::ResourceTableBuilder()
Izabela Orlowskad51efe82018-04-24 18:18:29 +0100277 .SetSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), Visibility::Level::kPublic)
278 .Build();
279 std::unique_ptr<ResourceTable> overlay =
280 test::ResourceTableBuilder()
Izabela Orlowskad51efe82018-04-24 18:18:29 +0100281 .SetSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), Visibility::Level::kPrivate)
282 .Build();
283
284 // It should fail if the "--strict-visibility" flag is set.
285 ResourceTable final_table;
286 TableMergerOptions options;
287 options.auto_add_overlay = false;
288 options.strict_visibility = true;
289 TableMerger merger(context_.get(), &final_table, options);
290
291 ASSERT_TRUE(merger.Merge({}, base.get(), false /*overlay*/));
292 ASSERT_FALSE(merger.Merge({}, overlay.get(), true /*overlay*/));
293
294 // But it should still pass if the flag is not set.
295 ResourceTable final_table2;
296 options.strict_visibility = false;
297 TableMerger merger2(context_.get(), &final_table2, options);
298
299 ASSERT_TRUE(merger2.Merge({}, base.get(), false /*overlay*/));
300 ASSERT_TRUE(merger2.Merge({}, overlay.get(), true /*overlay*/));
301}
302
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800303TEST_F(TableMergerTest, MergeAddResourceFromOverlay) {
Ryan Mitchell1d008d12021-03-19 14:54:17 -0700304 std::unique_ptr<ResourceTable> table_a = test::ResourceTableBuilder().Build();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700305 std::unique_ptr<ResourceTable> table_b =
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700306 test::ResourceTableBuilder()
Adam Lesinski71be7052017-12-12 16:48:07 -0800307 .SetSymbolState("bool/foo", {}, Visibility::Level::kUndefined, true /*allow new overlay*/)
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700308 .AddValue("bool/foo", ResourceUtils::TryParseBool("true"))
309 .Build();
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800310
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700311 ResourceTable final_table;
Adam Lesinski4488f1c2017-05-26 17:33:38 -0700312 TableMergerOptions options;
313 options.auto_add_overlay = false;
314 TableMerger merger(context_.get(), &final_table, options);
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800315
Adam Lesinski00451162017-10-03 07:44:08 -0700316 ASSERT_TRUE(merger.Merge({}, table_a.get(), false /*overlay*/));
317 ASSERT_TRUE(merger.Merge({}, table_b.get(), false /*overlay*/));
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800318}
319
320TEST_F(TableMergerTest, MergeAddResourceFromOverlayWithAutoAddOverlay) {
Ryan Mitchell1d008d12021-03-19 14:54:17 -0700321 std::unique_ptr<ResourceTable> table_a = test::ResourceTableBuilder().Build();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700322 std::unique_ptr<ResourceTable> table_b =
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700323 test::ResourceTableBuilder()
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700324 .AddValue("bool/foo", ResourceUtils::TryParseBool("true"))
325 .Build();
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800326
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700327 ResourceTable final_table;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700328 TableMergerOptions options;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700329 options.auto_add_overlay = true;
330 TableMerger merger(context_.get(), &final_table, options);
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800331
Adam Lesinski00451162017-10-03 07:44:08 -0700332 ASSERT_TRUE(merger.Merge({}, table_a.get(), false /*overlay*/));
333 ASSERT_TRUE(merger.Merge({}, table_b.get(), false /*overlay*/));
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800334}
335
336TEST_F(TableMergerTest, FailToMergeNewResourceWithoutAutoAddOverlay) {
Ryan Mitchell1d008d12021-03-19 14:54:17 -0700337 std::unique_ptr<ResourceTable> table_a = test::ResourceTableBuilder().Build();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700338 std::unique_ptr<ResourceTable> table_b =
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700339 test::ResourceTableBuilder()
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700340 .AddValue("bool/foo", ResourceUtils::TryParseBool("true"))
341 .Build();
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800342
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700343 ResourceTable final_table;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700344 TableMergerOptions options;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700345 options.auto_add_overlay = false;
346 TableMerger merger(context_.get(), &final_table, options);
Adam Lesinskia6fe3452015-12-09 15:20:52 -0800347
Adam Lesinski00451162017-10-03 07:44:08 -0700348 ASSERT_TRUE(merger.Merge({}, table_a.get(), false /*overlay*/));
349 ASSERT_FALSE(merger.Merge({}, table_b.get(), true /*overlay*/));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700350}
351
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700352TEST_F(TableMergerTest, OverlaidStyleablesAndStylesShouldBeMerged) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700353 std::unique_ptr<ResourceTable> table_a =
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700354 test::ResourceTableBuilder()
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700355 .AddValue("com.app.a:styleable/Foo",
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700356 test::StyleableBuilder()
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700357 .AddItem("com.app.a:attr/bar")
358 .AddItem("com.app.a:attr/foo", ResourceId(0x01010000))
359 .Build())
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700360 .AddValue("com.app.a:style/Theme",
361 test::StyleBuilder()
362 .SetParent("com.app.a:style/Parent")
363 .AddItem("com.app.a:attr/bar", util::make_unique<Id>())
364 .AddItem("com.app.a:attr/foo", ResourceUtils::MakeBool(false))
365 .Build())
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700366 .Build();
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700367
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700368 std::unique_ptr<ResourceTable> table_b =
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700369 test::ResourceTableBuilder()
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700370 .AddValue("com.app.a:styleable/Foo", test::StyleableBuilder()
371 .AddItem("com.app.a:attr/bat")
372 .AddItem("com.app.a:attr/foo")
373 .Build())
374 .AddValue("com.app.a:style/Theme",
375 test::StyleBuilder()
376 .SetParent("com.app.a:style/OverlayParent")
377 .AddItem("com.app.a:attr/bat", util::make_unique<Id>())
378 .AddItem("com.app.a:attr/foo", ResourceId(0x01010000),
379 ResourceUtils::MakeBool(true))
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700380 .Build())
381 .Build();
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700382
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700383 ResourceTable final_table;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700384 TableMergerOptions options;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700385 options.auto_add_overlay = true;
386 TableMerger merger(context_.get(), &final_table, options);
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700387
Adam Lesinski00451162017-10-03 07:44:08 -0700388 ASSERT_TRUE(merger.Merge({}, table_a.get(), false /*overlay*/));
389 ASSERT_TRUE(merger.Merge({}, table_b.get(), true /*overlay*/));
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700390
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700391 Styleable* styleable = test::GetValue<Styleable>(&final_table, "com.app.a:styleable/Foo");
392 ASSERT_THAT(styleable, NotNull());
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700393
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700394 std::vector<Reference> expected_refs = {
395 Reference(test::ParseNameOrDie("com.app.a:attr/bar")),
396 Reference(test::ParseNameOrDie("com.app.a:attr/bat")),
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700397 Reference(test::ParseNameOrDie("com.app.a:attr/foo"), ResourceId(0x01010000)),
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700398 };
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700399 EXPECT_THAT(styleable->entries, UnorderedElementsAreArray(expected_refs));
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700400
Adam Lesinski5924d8c2017-05-30 15:15:58 -0700401 Style* style = test::GetValue<Style>(&final_table, "com.app.a:style/Theme");
402 ASSERT_THAT(style, NotNull());
403
404 std::vector<Reference> extracted_refs;
405 for (const auto& entry : style->entries) {
406 extracted_refs.push_back(entry.key);
407 }
408 EXPECT_THAT(extracted_refs, UnorderedElementsAreArray(expected_refs));
409
410 const auto expected = ResourceUtils::MakeBool(true);
411 EXPECT_THAT(style->entries, Contains(Field(&Style::Entry::value, Pointee(ValueEq(*expected)))));
Ryan Mitchell4382e442021-07-14 12:53:01 -0700412 EXPECT_THAT(style->parent, Reference(test::ParseNameOrDie("com.app.a:style/OverlayParent")));
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700413}
414
Donald Chai121c6e82019-06-12 12:51:57 -0700415TEST_F(TableMergerTest, OverrideStyleInsteadOfOverlaying) {
416 std::unique_ptr<ResourceTable> table_a =
417 test::ResourceTableBuilder()
Donald Chai121c6e82019-06-12 12:51:57 -0700418 .AddValue(
419 "com.app.a:styleable/MyWidget",
420 test::StyleableBuilder().AddItem("com.app.a:attr/foo", ResourceId(0x1234)).Build())
421 .AddValue("com.app.a:style/Theme",
422 test::StyleBuilder()
423 .AddItem("com.app.a:attr/foo", ResourceUtils::MakeBool(false))
424 .Build())
425 .Build();
426 std::unique_ptr<ResourceTable> table_b =
427 test::ResourceTableBuilder()
Donald Chai121c6e82019-06-12 12:51:57 -0700428 .AddValue(
429 "com.app.a:styleable/MyWidget",
430 test::StyleableBuilder().AddItem("com.app.a:attr/bar", ResourceId(0x5678)).Build())
431 .AddValue(
432 "com.app.a:style/Theme",
433 test::StyleBuilder().AddItem("com.app.a:attr/bat", util::make_unique<Id>()).Build())
434 .Build();
435
436 ResourceTable final_table;
437 TableMergerOptions options;
438 options.auto_add_overlay = true;
439 options.override_styles_instead_of_overlaying = true;
440 TableMerger merger(context_.get(), &final_table, options);
441 ASSERT_TRUE(merger.Merge({}, table_a.get(), false /*overlay*/));
442 ASSERT_TRUE(merger.Merge({}, table_b.get(), true /*overlay*/));
443
444 // Styleables are always overlaid
445 std::unique_ptr<Styleable> expected_styleable = test::StyleableBuilder()
446 // The merged Styleable has its entries ordered by name.
447 .AddItem("com.app.a:attr/bar", ResourceId(0x5678))
448 .AddItem("com.app.a:attr/foo", ResourceId(0x1234))
449 .Build();
450 const Styleable* actual_styleable =
451 test::GetValue<Styleable>(&final_table, "com.app.a:styleable/MyWidget");
452 ASSERT_NE(actual_styleable, nullptr);
453 EXPECT_TRUE(actual_styleable->Equals(expected_styleable.get()));
454 // Style should be overridden
455 const Style* actual_style = test::GetValue<Style>(&final_table, "com.app.a:style/Theme");
456 ASSERT_NE(actual_style, nullptr);
457 EXPECT_TRUE(actual_style->Equals(test::GetValue<Style>(table_b.get(), "com.app.a:style/Theme")));
458}
459
Ryan Mitchell1bb1fe02018-11-16 11:21:41 -0800460TEST_F(TableMergerTest, SetOverlayable) {
Ryan Mitchell54237ff2018-12-13 15:44:29 -0800461 auto overlayable = std::make_shared<Overlayable>("CustomizableResources",
462 "overlay://customization");
463 OverlayableItem overlayable_item(overlayable);
Winson62ac8b52019-12-04 08:36:48 -0800464 overlayable_item.policies |= PolicyFlags::PRODUCT_PARTITION;
465 overlayable_item.policies |= PolicyFlags::VENDOR_PARTITION;
Ryan Mitchell1bb1fe02018-11-16 11:21:41 -0800466
Ryan Mitchelle4e989c2018-10-29 02:21:50 -0700467 std::unique_ptr<ResourceTable> table_a =
468 test::ResourceTableBuilder()
Ryan Mitchell54237ff2018-12-13 15:44:29 -0800469 .SetOverlayable("bool/foo", overlayable_item)
Ryan Mitchelle4e989c2018-10-29 02:21:50 -0700470 .Build();
471
472 std::unique_ptr<ResourceTable> table_b =
473 test::ResourceTableBuilder()
Ryan Mitchell1bb1fe02018-11-16 11:21:41 -0800474 .AddSimple("bool/foo")
Ryan Mitchelle4e989c2018-10-29 02:21:50 -0700475 .Build();
476
477 ResourceTable final_table;
478 TableMergerOptions options;
479 options.auto_add_overlay = true;
480 TableMerger merger(context_.get(), &final_table, options);
481 ASSERT_TRUE(merger.Merge({}, table_a.get(), false /*overlay*/));
482 ASSERT_TRUE(merger.Merge({}, table_b.get(), false /*overlay*/));
483
484 const ResourceName name = test::ParseNameOrDie("com.app.a:bool/foo");
Ryan Mitchell4382e442021-07-14 12:53:01 -0700485 std::optional<ResourceTable::SearchResult> search_result = final_table.FindResource(name);
Ryan Mitchell1bb1fe02018-11-16 11:21:41 -0800486 ASSERT_TRUE(search_result);
Ryan Mitchell54237ff2018-12-13 15:44:29 -0800487 ASSERT_TRUE(search_result.value().entry->overlayable_item);
488 OverlayableItem& result_overlayable_item = search_result.value().entry->overlayable_item.value();
489 EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("CustomizableResources"));
490 EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://customization"));
Winson62ac8b52019-12-04 08:36:48 -0800491 EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::PRODUCT_PARTITION
492 | PolicyFlags::VENDOR_PARTITION));
Ryan Mitchelle4e989c2018-10-29 02:21:50 -0700493}
494
Ryan Mitchell1bb1fe02018-11-16 11:21:41 -0800495TEST_F(TableMergerTest, SetOverlayableLater) {
Ryan Mitchell54237ff2018-12-13 15:44:29 -0800496 auto overlayable = std::make_shared<Overlayable>("CustomizableResources",
497 "overlay://customization");
Ryan Mitchelle4e989c2018-10-29 02:21:50 -0700498 std::unique_ptr<ResourceTable> table_a =
499 test::ResourceTableBuilder()
Ryan Mitchell1bb1fe02018-11-16 11:21:41 -0800500 .AddSimple("bool/foo")
Ryan Mitchelle4e989c2018-10-29 02:21:50 -0700501 .Build();
502
Ryan Mitchell54237ff2018-12-13 15:44:29 -0800503 OverlayableItem overlayable_item(overlayable);
Winson62ac8b52019-12-04 08:36:48 -0800504 overlayable_item.policies |= PolicyFlags::PUBLIC;
505 overlayable_item.policies |= PolicyFlags::SYSTEM_PARTITION;
Ryan Mitchelle4e989c2018-10-29 02:21:50 -0700506 std::unique_ptr<ResourceTable> table_b =
507 test::ResourceTableBuilder()
Ryan Mitchell54237ff2018-12-13 15:44:29 -0800508 .SetOverlayable("bool/foo", overlayable_item)
Ryan Mitchell1bb1fe02018-11-16 11:21:41 -0800509 .Build();
510
511 ResourceTable final_table;
512 TableMergerOptions options;
513 options.auto_add_overlay = true;
514 TableMerger merger(context_.get(), &final_table, options);
515 ASSERT_TRUE(merger.Merge({}, table_a.get(), false /*overlay*/));
516 ASSERT_TRUE(merger.Merge({}, table_b.get(), false /*overlay*/));
517
518 const ResourceName name = test::ParseNameOrDie("com.app.a:bool/foo");
Ryan Mitchell4382e442021-07-14 12:53:01 -0700519 std::optional<ResourceTable::SearchResult> search_result = final_table.FindResource(name);
Ryan Mitchell1bb1fe02018-11-16 11:21:41 -0800520 ASSERT_TRUE(search_result);
Ryan Mitchell54237ff2018-12-13 15:44:29 -0800521 ASSERT_TRUE(search_result.value().entry->overlayable_item);
522 OverlayableItem& result_overlayable_item = search_result.value().entry->overlayable_item.value();
523 EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("CustomizableResources"));
524 EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://customization"));
Winson62ac8b52019-12-04 08:36:48 -0800525 EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::PUBLIC
526 | PolicyFlags::SYSTEM_PARTITION));
Ryan Mitchell1bb1fe02018-11-16 11:21:41 -0800527}
528
Ryan Mitchell54237ff2018-12-13 15:44:29 -0800529TEST_F(TableMergerTest, SameResourceDifferentNameFail) {
530 auto overlayable_first = std::make_shared<Overlayable>("CustomizableResources",
531 "overlay://customization");
532 OverlayableItem overlayable_item_first(overlayable_first);
Winson62ac8b52019-12-04 08:36:48 -0800533 overlayable_item_first.policies |= PolicyFlags::PRODUCT_PARTITION;
Ryan Mitchell1bb1fe02018-11-16 11:21:41 -0800534 std::unique_ptr<ResourceTable> table_a =
535 test::ResourceTableBuilder()
Ryan Mitchell54237ff2018-12-13 15:44:29 -0800536 .SetOverlayable("bool/foo", overlayable_item_first)
Ryan Mitchell1bb1fe02018-11-16 11:21:41 -0800537 .Build();
538
Ryan Mitchell54237ff2018-12-13 15:44:29 -0800539 auto overlayable_second = std::make_shared<Overlayable>("ThemeResources",
Ryan Mitchellced9a5c2019-04-05 10:44:16 -0700540 "overlay://customization");
541 OverlayableItem overlayable_item_second(overlayable_second);
Winson62ac8b52019-12-04 08:36:48 -0800542 overlayable_item_second.policies |= PolicyFlags::PRODUCT_PARTITION;
Ryan Mitchellced9a5c2019-04-05 10:44:16 -0700543 std::unique_ptr<ResourceTable> table_b =
544 test::ResourceTableBuilder()
Ryan Mitchellced9a5c2019-04-05 10:44:16 -0700545 .SetOverlayable("bool/foo", overlayable_item_second)
546 .Build();
547
548 ResourceTable final_table;
549 TableMergerOptions options;
550 options.auto_add_overlay = true;
551 TableMerger merger(context_.get(), &final_table, options);
552 ASSERT_TRUE(merger.Merge({}, table_a.get(), false /*overlay*/));
553 ASSERT_FALSE(merger.Merge({}, table_b.get(), false /*overlay*/));
554}
555
556TEST_F(TableMergerTest, SameResourceDifferentActorFail) {
557 auto overlayable_first = std::make_shared<Overlayable>("CustomizableResources",
558 "overlay://customization");
559 OverlayableItem overlayable_item_first(overlayable_first);
Winson62ac8b52019-12-04 08:36:48 -0800560 overlayable_item_first.policies |= PolicyFlags::PRODUCT_PARTITION;
Ryan Mitchellced9a5c2019-04-05 10:44:16 -0700561 std::unique_ptr<ResourceTable> table_a =
562 test::ResourceTableBuilder()
Ryan Mitchellced9a5c2019-04-05 10:44:16 -0700563 .SetOverlayable("bool/foo", overlayable_item_first)
564 .Build();
565
566 auto overlayable_second = std::make_shared<Overlayable>("CustomizableResources",
Ryan Mitchell54237ff2018-12-13 15:44:29 -0800567 "overlay://theme");
568 OverlayableItem overlayable_item_second(overlayable_second);
Winson62ac8b52019-12-04 08:36:48 -0800569 overlayable_item_second.policies |= PolicyFlags::PRODUCT_PARTITION;
Ryan Mitchell1bb1fe02018-11-16 11:21:41 -0800570 std::unique_ptr<ResourceTable> table_b =
571 test::ResourceTableBuilder()
Ryan Mitchell54237ff2018-12-13 15:44:29 -0800572 .SetOverlayable("bool/foo", overlayable_item_second)
Ryan Mitchelle4e989c2018-10-29 02:21:50 -0700573 .Build();
574
575 ResourceTable final_table;
576 TableMergerOptions options;
577 options.auto_add_overlay = true;
578 TableMerger merger(context_.get(), &final_table, options);
579 ASSERT_TRUE(merger.Merge({}, table_a.get(), false /*overlay*/));
580 ASSERT_FALSE(merger.Merge({}, table_b.get(), false /*overlay*/));
581}
582
Ryan Mitchellced9a5c2019-04-05 10:44:16 -0700583TEST_F(TableMergerTest, SameResourceDifferentPoliciesFail) {
584 auto overlayable_first = std::make_shared<Overlayable>("CustomizableResources",
585 "overlay://customization");
586 OverlayableItem overlayable_item_first(overlayable_first);
Winson62ac8b52019-12-04 08:36:48 -0800587 overlayable_item_first.policies |= PolicyFlags::PRODUCT_PARTITION;
Ryan Mitchelle4e989c2018-10-29 02:21:50 -0700588 std::unique_ptr<ResourceTable> table_a =
589 test::ResourceTableBuilder()
Ryan Mitchell54237ff2018-12-13 15:44:29 -0800590 .SetOverlayable("bool/foo", overlayable_item_first)
Ryan Mitchelle4e989c2018-10-29 02:21:50 -0700591 .Build();
592
Ryan Mitchellced9a5c2019-04-05 10:44:16 -0700593 auto overlayable_second = std::make_shared<Overlayable>("CustomizableResources",
594 "overlay://customization");
595 OverlayableItem overlayable_item_second(overlayable_second);
Winson62ac8b52019-12-04 08:36:48 -0800596 overlayable_item_second.policies |= PolicyFlags::SIGNATURE;
Ryan Mitchelle4e989c2018-10-29 02:21:50 -0700597 std::unique_ptr<ResourceTable> table_b =
598 test::ResourceTableBuilder()
Ryan Mitchell54237ff2018-12-13 15:44:29 -0800599 .SetOverlayable("bool/foo", overlayable_item_second)
Ryan Mitchelle4e989c2018-10-29 02:21:50 -0700600 .Build();
601
602 ResourceTable final_table;
603 TableMergerOptions options;
604 options.auto_add_overlay = true;
605 TableMerger merger(context_.get(), &final_table, options);
606 ASSERT_TRUE(merger.Merge({}, table_a.get(), false /*overlay*/));
607 ASSERT_FALSE(merger.Merge({}, table_b.get(), false /*overlay*/));
608}
609
Ryan Mitchellced9a5c2019-04-05 10:44:16 -0700610TEST_F(TableMergerTest, SameResourceSameOverlayable) {
611 auto overlayable = std::make_shared<Overlayable>("CustomizableResources",
612 "overlay://customization");
613
614 OverlayableItem overlayable_item_first(overlayable);
Winson62ac8b52019-12-04 08:36:48 -0800615 overlayable_item_first.policies |= PolicyFlags::PRODUCT_PARTITION;
Ryan Mitchellced9a5c2019-04-05 10:44:16 -0700616 std::unique_ptr<ResourceTable> table_a =
617 test::ResourceTableBuilder()
Ryan Mitchellced9a5c2019-04-05 10:44:16 -0700618 .SetOverlayable("bool/foo", overlayable_item_first)
619 .Build();
620
621 OverlayableItem overlayable_item_second(overlayable);
Winson62ac8b52019-12-04 08:36:48 -0800622 overlayable_item_second.policies |= PolicyFlags::PRODUCT_PARTITION;
Ryan Mitchellced9a5c2019-04-05 10:44:16 -0700623 std::unique_ptr<ResourceTable> table_b =
624 test::ResourceTableBuilder()
Ryan Mitchellced9a5c2019-04-05 10:44:16 -0700625 .SetOverlayable("bool/foo", overlayable_item_second)
626 .Build();
627
628 ResourceTable final_table;
629 TableMergerOptions options;
630 options.auto_add_overlay = true;
631 TableMerger merger(context_.get(), &final_table, options);
632 ASSERT_TRUE(merger.Merge({}, table_a.get(), false /*overlay*/));
633 ASSERT_TRUE(merger.Merge({}, table_b.get(), false /*overlay*/));
634}
635
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700636} // namespace aapt