xref: /aosp_15_r20/frameworks/base/tools/aapt2/ResourceTable_test.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker  *
4*d57664e9SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker  *
8*d57664e9SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker  *
10*d57664e9SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker  * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker  */
16*d57664e9SAndroid Build Coastguard Worker 
17*d57664e9SAndroid Build Coastguard Worker #include "ResourceTable.h"
18*d57664e9SAndroid Build Coastguard Worker 
19*d57664e9SAndroid Build Coastguard Worker #include <algorithm>
20*d57664e9SAndroid Build Coastguard Worker #include <ostream>
21*d57664e9SAndroid Build Coastguard Worker #include <string>
22*d57664e9SAndroid Build Coastguard Worker 
23*d57664e9SAndroid Build Coastguard Worker #include "ResourceValues.h"
24*d57664e9SAndroid Build Coastguard Worker #include "androidfw/IDiagnostics.h"
25*d57664e9SAndroid Build Coastguard Worker #include "test/Test.h"
26*d57664e9SAndroid Build Coastguard Worker #include "util/Util.h"
27*d57664e9SAndroid Build Coastguard Worker 
28*d57664e9SAndroid Build Coastguard Worker using ::android::ConfigDescription;
29*d57664e9SAndroid Build Coastguard Worker using ::android::StringPiece;
30*d57664e9SAndroid Build Coastguard Worker using ::testing::Eq;
31*d57664e9SAndroid Build Coastguard Worker using ::testing::NotNull;
32*d57664e9SAndroid Build Coastguard Worker using ::testing::StrEq;
33*d57664e9SAndroid Build Coastguard Worker 
34*d57664e9SAndroid Build Coastguard Worker using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
35*d57664e9SAndroid Build Coastguard Worker 
36*d57664e9SAndroid Build Coastguard Worker namespace aapt {
37*d57664e9SAndroid Build Coastguard Worker 
TEST(ResourceTableTest,FailToAddResourceWithBadName)38*d57664e9SAndroid Build Coastguard Worker TEST(ResourceTableTest, FailToAddResourceWithBadName) {
39*d57664e9SAndroid Build Coastguard Worker   ResourceTable table;
40*d57664e9SAndroid Build Coastguard Worker 
41*d57664e9SAndroid Build Coastguard Worker   EXPECT_FALSE(
42*d57664e9SAndroid Build Coastguard Worker       table.AddResource(NewResourceBuilder(test::ParseNameOrDie("android:id/hey,there")).Build(),
43*d57664e9SAndroid Build Coastguard Worker                         test::GetDiagnostics()));
44*d57664e9SAndroid Build Coastguard Worker 
45*d57664e9SAndroid Build Coastguard Worker   EXPECT_FALSE(
46*d57664e9SAndroid Build Coastguard Worker       table.AddResource(NewResourceBuilder(test::ParseNameOrDie("android:id/hey:there")).Build(),
47*d57664e9SAndroid Build Coastguard Worker                         test::GetDiagnostics()));
48*d57664e9SAndroid Build Coastguard Worker }
49*d57664e9SAndroid Build Coastguard Worker 
TEST(ResourceTableTest,AddResourceWithWeirdNameWhenAddingMangledResources)50*d57664e9SAndroid Build Coastguard Worker TEST(ResourceTableTest, AddResourceWithWeirdNameWhenAddingMangledResources) {
51*d57664e9SAndroid Build Coastguard Worker   ResourceTable table;
52*d57664e9SAndroid Build Coastguard Worker 
53*d57664e9SAndroid Build Coastguard Worker   EXPECT_TRUE(
54*d57664e9SAndroid Build Coastguard Worker       table.AddResource(NewResourceBuilder(test::ParseNameOrDie("android:id/heythere       "))
55*d57664e9SAndroid Build Coastguard Worker                             .SetAllowMangled(true)
56*d57664e9SAndroid Build Coastguard Worker                             .Build(),
57*d57664e9SAndroid Build Coastguard Worker                         test::GetDiagnostics()));
58*d57664e9SAndroid Build Coastguard Worker }
59*d57664e9SAndroid Build Coastguard Worker 
TEST(ResourceTableTest,AddOneResource)60*d57664e9SAndroid Build Coastguard Worker TEST(ResourceTableTest, AddOneResource) {
61*d57664e9SAndroid Build Coastguard Worker   ResourceTable table;
62*d57664e9SAndroid Build Coastguard Worker 
63*d57664e9SAndroid Build Coastguard Worker   EXPECT_TRUE(table.AddResource(
64*d57664e9SAndroid Build Coastguard Worker       NewResourceBuilder(test::ParseNameOrDie("android:attr/id"))
65*d57664e9SAndroid Build Coastguard Worker           .SetValue(test::ValueBuilder<Id>().SetSource("test/path/file.xml", 23u).Build())
66*d57664e9SAndroid Build Coastguard Worker           .Build(),
67*d57664e9SAndroid Build Coastguard Worker       test::GetDiagnostics()));
68*d57664e9SAndroid Build Coastguard Worker 
69*d57664e9SAndroid Build Coastguard Worker   EXPECT_THAT(test::GetValue<Id>(&table, "android:attr/id"), NotNull());
70*d57664e9SAndroid Build Coastguard Worker }
71*d57664e9SAndroid Build Coastguard Worker 
TEST(ResourceTableTest,AddMultipleResources)72*d57664e9SAndroid Build Coastguard Worker TEST(ResourceTableTest, AddMultipleResources) {
73*d57664e9SAndroid Build Coastguard Worker   ResourceTable table;
74*d57664e9SAndroid Build Coastguard Worker 
75*d57664e9SAndroid Build Coastguard Worker   ConfigDescription language_config;
76*d57664e9SAndroid Build Coastguard Worker   memcpy(language_config.language, "pl", sizeof(language_config.language));
77*d57664e9SAndroid Build Coastguard Worker 
78*d57664e9SAndroid Build Coastguard Worker   EXPECT_TRUE(table.AddResource(
79*d57664e9SAndroid Build Coastguard Worker       NewResourceBuilder(test::ParseNameOrDie("android:attr/layout_width"))
80*d57664e9SAndroid Build Coastguard Worker           .SetValue(test::ValueBuilder<Id>().SetSource("test/path/file.xml", 10u).Build())
81*d57664e9SAndroid Build Coastguard Worker           .Build(),
82*d57664e9SAndroid Build Coastguard Worker       test::GetDiagnostics()));
83*d57664e9SAndroid Build Coastguard Worker 
84*d57664e9SAndroid Build Coastguard Worker   EXPECT_TRUE(table.AddResource(
85*d57664e9SAndroid Build Coastguard Worker       NewResourceBuilder(test::ParseNameOrDie("android:attr/id"))
86*d57664e9SAndroid Build Coastguard Worker           .SetValue(test::ValueBuilder<Id>().SetSource("test/path/file.xml", 12u).Build())
87*d57664e9SAndroid Build Coastguard Worker           .Build(),
88*d57664e9SAndroid Build Coastguard Worker       test::GetDiagnostics()));
89*d57664e9SAndroid Build Coastguard Worker 
90*d57664e9SAndroid Build Coastguard Worker   EXPECT_TRUE(table.AddResource(
91*d57664e9SAndroid Build Coastguard Worker       NewResourceBuilder(test::ParseNameOrDie("android:string/ok"))
92*d57664e9SAndroid Build Coastguard Worker           .SetValue(test::ValueBuilder<Id>().SetSource("test/path/file.xml", 14u).Build())
93*d57664e9SAndroid Build Coastguard Worker           .Build(),
94*d57664e9SAndroid Build Coastguard Worker       test::GetDiagnostics()));
95*d57664e9SAndroid Build Coastguard Worker 
96*d57664e9SAndroid Build Coastguard Worker   EXPECT_TRUE(
97*d57664e9SAndroid Build Coastguard Worker       table.AddResource(NewResourceBuilder(test::ParseNameOrDie("android:string/ok"))
98*d57664e9SAndroid Build Coastguard Worker                             .SetValue(test::ValueBuilder<BinaryPrimitive>(android::Res_value{})
99*d57664e9SAndroid Build Coastguard Worker                                           .SetSource("test/path/file.xml", 20u)
100*d57664e9SAndroid Build Coastguard Worker                                           .Build(),
101*d57664e9SAndroid Build Coastguard Worker                                       language_config)
102*d57664e9SAndroid Build Coastguard Worker                             .Build(),
103*d57664e9SAndroid Build Coastguard Worker                         test::GetDiagnostics()));
104*d57664e9SAndroid Build Coastguard Worker 
105*d57664e9SAndroid Build Coastguard Worker   EXPECT_THAT(test::GetValue<Id>(&table, "android:attr/layout_width"), NotNull());
106*d57664e9SAndroid Build Coastguard Worker   EXPECT_THAT(test::GetValue<Id>(&table, "android:attr/id"), NotNull());
107*d57664e9SAndroid Build Coastguard Worker   EXPECT_THAT(test::GetValue<Id>(&table, "android:string/ok"), NotNull());
108*d57664e9SAndroid Build Coastguard Worker   EXPECT_THAT(test::GetValueForConfig<BinaryPrimitive>(&table, "android:string/ok", language_config), NotNull());
109*d57664e9SAndroid Build Coastguard Worker }
110*d57664e9SAndroid Build Coastguard Worker 
TEST(ResourceTableTest,OverrideWeakResourceValue)111*d57664e9SAndroid Build Coastguard Worker TEST(ResourceTableTest, OverrideWeakResourceValue) {
112*d57664e9SAndroid Build Coastguard Worker   ResourceTable table;
113*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(table.AddResource(NewResourceBuilder(test::ParseNameOrDie("android:attr/foo"))
114*d57664e9SAndroid Build Coastguard Worker                                     .SetValue(test::AttributeBuilder().SetWeak(true).Build())
115*d57664e9SAndroid Build Coastguard Worker                                     .Build(),
116*d57664e9SAndroid Build Coastguard Worker                                 test::GetDiagnostics()));
117*d57664e9SAndroid Build Coastguard Worker 
118*d57664e9SAndroid Build Coastguard Worker   Attribute* attr = test::GetValue<Attribute>(&table, "android:attr/foo");
119*d57664e9SAndroid Build Coastguard Worker   ASSERT_THAT(attr, NotNull());
120*d57664e9SAndroid Build Coastguard Worker   EXPECT_TRUE(attr->IsWeak());
121*d57664e9SAndroid Build Coastguard Worker 
122*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(table.AddResource(NewResourceBuilder(test::ParseNameOrDie("android:attr/foo"))
123*d57664e9SAndroid Build Coastguard Worker                                     .SetValue(util::make_unique<Attribute>())
124*d57664e9SAndroid Build Coastguard Worker                                     .Build(),
125*d57664e9SAndroid Build Coastguard Worker                                 test::GetDiagnostics()));
126*d57664e9SAndroid Build Coastguard Worker 
127*d57664e9SAndroid Build Coastguard Worker   attr = test::GetValue<Attribute>(&table, "android:attr/foo");
128*d57664e9SAndroid Build Coastguard Worker   ASSERT_THAT(attr, NotNull());
129*d57664e9SAndroid Build Coastguard Worker   EXPECT_FALSE(attr->IsWeak());
130*d57664e9SAndroid Build Coastguard Worker }
131*d57664e9SAndroid Build Coastguard Worker 
TEST(ResourceTableTest,AllowCompatibleDuplicateAttributes)132*d57664e9SAndroid Build Coastguard Worker TEST(ResourceTableTest, AllowCompatibleDuplicateAttributes) {
133*d57664e9SAndroid Build Coastguard Worker   ResourceTable table;
134*d57664e9SAndroid Build Coastguard Worker 
135*d57664e9SAndroid Build Coastguard Worker   const ResourceName name = test::ParseNameOrDie("android:attr/foo");
136*d57664e9SAndroid Build Coastguard Worker   Attribute attr_one(android::ResTable_map::TYPE_STRING);
137*d57664e9SAndroid Build Coastguard Worker   attr_one.SetWeak(true);
138*d57664e9SAndroid Build Coastguard Worker   Attribute attr_two(android::ResTable_map::TYPE_STRING | android::ResTable_map::TYPE_REFERENCE);
139*d57664e9SAndroid Build Coastguard Worker   attr_two.SetWeak(true);
140*d57664e9SAndroid Build Coastguard Worker 
141*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(table.AddResource(
142*d57664e9SAndroid Build Coastguard Worker       NewResourceBuilder(name).SetValue(util::make_unique<Attribute>(attr_one)).Build(),
143*d57664e9SAndroid Build Coastguard Worker       test::GetDiagnostics()));
144*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(table.AddResource(
145*d57664e9SAndroid Build Coastguard Worker       NewResourceBuilder(name).SetValue(util::make_unique<Attribute>(attr_two)).Build(),
146*d57664e9SAndroid Build Coastguard Worker       test::GetDiagnostics()));
147*d57664e9SAndroid Build Coastguard Worker }
148*d57664e9SAndroid Build Coastguard Worker 
TEST(ResourceTableTest,ProductVaryingValues)149*d57664e9SAndroid Build Coastguard Worker TEST(ResourceTableTest, ProductVaryingValues) {
150*d57664e9SAndroid Build Coastguard Worker   ResourceTable table;
151*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(table.AddResource(
152*d57664e9SAndroid Build Coastguard Worker       NewResourceBuilder(test::ParseNameOrDie("android:string/foo"))
153*d57664e9SAndroid Build Coastguard Worker           .SetValue(util::make_unique<Id>(), test::ParseConfigOrDie("land"), "tablet")
154*d57664e9SAndroid Build Coastguard Worker           .Build(),
155*d57664e9SAndroid Build Coastguard Worker       test::GetDiagnostics()));
156*d57664e9SAndroid Build Coastguard Worker 
157*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(table.AddResource(
158*d57664e9SAndroid Build Coastguard Worker       NewResourceBuilder(test::ParseNameOrDie("android:string/foo"))
159*d57664e9SAndroid Build Coastguard Worker           .SetValue(util::make_unique<Id>(), test::ParseConfigOrDie("land"), "phone")
160*d57664e9SAndroid Build Coastguard Worker           .Build(),
161*d57664e9SAndroid Build Coastguard Worker       test::GetDiagnostics()));
162*d57664e9SAndroid Build Coastguard Worker 
163*d57664e9SAndroid Build Coastguard Worker   EXPECT_THAT(test::GetValueForConfigAndProduct<Id>(&table, "android:string/foo",test::ParseConfigOrDie("land"), "tablet"), NotNull());
164*d57664e9SAndroid Build Coastguard Worker   EXPECT_THAT(test::GetValueForConfigAndProduct<Id>(&table, "android:string/foo",test::ParseConfigOrDie("land"), "phone"), NotNull());
165*d57664e9SAndroid Build Coastguard Worker 
166*d57664e9SAndroid Build Coastguard Worker   std::optional<ResourceTable::SearchResult> sr =
167*d57664e9SAndroid Build Coastguard Worker       table.FindResource(test::ParseNameOrDie("android:string/foo"));
168*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(sr);
169*d57664e9SAndroid Build Coastguard Worker   std::vector<ResourceConfigValue*> values =
170*d57664e9SAndroid Build Coastguard Worker       sr.value().entry->FindAllValues(test::ParseConfigOrDie("land"));
171*d57664e9SAndroid Build Coastguard Worker   ASSERT_EQ(2u, values.size());
172*d57664e9SAndroid Build Coastguard Worker   EXPECT_EQ(std::string("phone"), values[0]->product);
173*d57664e9SAndroid Build Coastguard Worker   EXPECT_EQ(std::string("tablet"), values[1]->product);
174*d57664e9SAndroid Build Coastguard Worker }
175*d57664e9SAndroid Build Coastguard Worker 
LevelToString(Visibility::Level level)176*d57664e9SAndroid Build Coastguard Worker static StringPiece LevelToString(Visibility::Level level) {
177*d57664e9SAndroid Build Coastguard Worker   switch (level) {
178*d57664e9SAndroid Build Coastguard Worker     case Visibility::Level::kPrivate:
179*d57664e9SAndroid Build Coastguard Worker       return "private";
180*d57664e9SAndroid Build Coastguard Worker     case Visibility::Level::kPublic:
181*d57664e9SAndroid Build Coastguard Worker       return "private";
182*d57664e9SAndroid Build Coastguard Worker     default:
183*d57664e9SAndroid Build Coastguard Worker       return "undefined";
184*d57664e9SAndroid Build Coastguard Worker   }
185*d57664e9SAndroid Build Coastguard Worker }
186*d57664e9SAndroid Build Coastguard Worker 
VisibilityOfResource(const ResourceTable & table,const ResourceNameRef & name,Visibility::Level level,StringPiece comment)187*d57664e9SAndroid Build Coastguard Worker static ::testing::AssertionResult VisibilityOfResource(const ResourceTable& table,
188*d57664e9SAndroid Build Coastguard Worker                                                        const ResourceNameRef& name,
189*d57664e9SAndroid Build Coastguard Worker                                                        Visibility::Level level,
190*d57664e9SAndroid Build Coastguard Worker                                                        StringPiece comment) {
191*d57664e9SAndroid Build Coastguard Worker   std::optional<ResourceTable::SearchResult> result = table.FindResource(name);
192*d57664e9SAndroid Build Coastguard Worker   if (!result) {
193*d57664e9SAndroid Build Coastguard Worker     return ::testing::AssertionFailure() << "no resource '" << name << "' found in table";
194*d57664e9SAndroid Build Coastguard Worker   }
195*d57664e9SAndroid Build Coastguard Worker 
196*d57664e9SAndroid Build Coastguard Worker   const Visibility& visibility = result.value().entry->visibility;
197*d57664e9SAndroid Build Coastguard Worker   if (visibility.level != level) {
198*d57664e9SAndroid Build Coastguard Worker     return ::testing::AssertionFailure() << "expected visibility " << LevelToString(level)
199*d57664e9SAndroid Build Coastguard Worker                                          << " but got " << LevelToString(visibility.level);
200*d57664e9SAndroid Build Coastguard Worker   }
201*d57664e9SAndroid Build Coastguard Worker 
202*d57664e9SAndroid Build Coastguard Worker   if (visibility.comment != comment) {
203*d57664e9SAndroid Build Coastguard Worker     return ::testing::AssertionFailure() << "expected visibility comment '" << comment
204*d57664e9SAndroid Build Coastguard Worker                                          << "' but got '" << visibility.comment << "'";
205*d57664e9SAndroid Build Coastguard Worker   }
206*d57664e9SAndroid Build Coastguard Worker   return ::testing::AssertionSuccess();
207*d57664e9SAndroid Build Coastguard Worker }
208*d57664e9SAndroid Build Coastguard Worker 
TEST(ResourceTableTest,SetVisibility)209*d57664e9SAndroid Build Coastguard Worker TEST(ResourceTableTest, SetVisibility) {
210*d57664e9SAndroid Build Coastguard Worker   using Level = Visibility::Level;
211*d57664e9SAndroid Build Coastguard Worker 
212*d57664e9SAndroid Build Coastguard Worker   ResourceTable table;
213*d57664e9SAndroid Build Coastguard Worker   const ResourceName name = test::ParseNameOrDie("android:string/foo");
214*d57664e9SAndroid Build Coastguard Worker 
215*d57664e9SAndroid Build Coastguard Worker   Visibility visibility;
216*d57664e9SAndroid Build Coastguard Worker   visibility.level = Visibility::Level::kPrivate;
217*d57664e9SAndroid Build Coastguard Worker   visibility.comment = "private";
218*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetVisibility(visibility).Build(),
219*d57664e9SAndroid Build Coastguard Worker                                 test::GetDiagnostics()));
220*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(VisibilityOfResource(table, name, Level::kPrivate, "private"));
221*d57664e9SAndroid Build Coastguard Worker 
222*d57664e9SAndroid Build Coastguard Worker   visibility.level = Visibility::Level::kUndefined;
223*d57664e9SAndroid Build Coastguard Worker   visibility.comment = "undefined";
224*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetVisibility(visibility).Build(),
225*d57664e9SAndroid Build Coastguard Worker                                 test::GetDiagnostics()));
226*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(VisibilityOfResource(table, name, Level::kPrivate, "private"));
227*d57664e9SAndroid Build Coastguard Worker 
228*d57664e9SAndroid Build Coastguard Worker   visibility.level = Visibility::Level::kPublic;
229*d57664e9SAndroid Build Coastguard Worker   visibility.comment = "public";
230*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetVisibility(visibility).Build(),
231*d57664e9SAndroid Build Coastguard Worker                                 test::GetDiagnostics()));
232*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(VisibilityOfResource(table, name, Level::kPublic, "public"));
233*d57664e9SAndroid Build Coastguard Worker 
234*d57664e9SAndroid Build Coastguard Worker   visibility.level = Visibility::Level::kPrivate;
235*d57664e9SAndroid Build Coastguard Worker   visibility.comment = "private";
236*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetVisibility(visibility).Build(),
237*d57664e9SAndroid Build Coastguard Worker                                 test::GetDiagnostics()));
238*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(VisibilityOfResource(table, name, Level::kPublic, "public"));
239*d57664e9SAndroid Build Coastguard Worker }
240*d57664e9SAndroid Build Coastguard Worker 
TEST(ResourceTableTest,SetAllowNew)241*d57664e9SAndroid Build Coastguard Worker TEST(ResourceTableTest, SetAllowNew) {
242*d57664e9SAndroid Build Coastguard Worker   ResourceTable table;
243*d57664e9SAndroid Build Coastguard Worker   const ResourceName name = test::ParseNameOrDie("android:string/foo");
244*d57664e9SAndroid Build Coastguard Worker 
245*d57664e9SAndroid Build Coastguard Worker   AllowNew allow_new;
246*d57664e9SAndroid Build Coastguard Worker   std::optional<ResourceTable::SearchResult> result;
247*d57664e9SAndroid Build Coastguard Worker 
248*d57664e9SAndroid Build Coastguard Worker   allow_new.comment = "first";
249*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetAllowNew(allow_new).Build(),
250*d57664e9SAndroid Build Coastguard Worker                                 test::GetDiagnostics()));
251*d57664e9SAndroid Build Coastguard Worker   result = table.FindResource(name);
252*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(result);
253*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(result.value().entry->allow_new);
254*d57664e9SAndroid Build Coastguard Worker   ASSERT_THAT(result.value().entry->allow_new.value().comment, StrEq("first"));
255*d57664e9SAndroid Build Coastguard Worker 
256*d57664e9SAndroid Build Coastguard Worker   allow_new.comment = "second";
257*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetAllowNew(allow_new).Build(),
258*d57664e9SAndroid Build Coastguard Worker                                 test::GetDiagnostics()));
259*d57664e9SAndroid Build Coastguard Worker   result = table.FindResource(name);
260*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(result);
261*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(result.value().entry->allow_new);
262*d57664e9SAndroid Build Coastguard Worker   ASSERT_THAT(result.value().entry->allow_new.value().comment, StrEq("second"));
263*d57664e9SAndroid Build Coastguard Worker }
264*d57664e9SAndroid Build Coastguard Worker 
TEST(ResourceTableTest,SetOverlayable)265*d57664e9SAndroid Build Coastguard Worker TEST(ResourceTableTest, SetOverlayable) {
266*d57664e9SAndroid Build Coastguard Worker   ResourceTable table;
267*d57664e9SAndroid Build Coastguard Worker   auto overlayable = std::make_shared<Overlayable>(
268*d57664e9SAndroid Build Coastguard Worker       "Name", "overlay://theme", android::Source("res/values/overlayable.xml", 40));
269*d57664e9SAndroid Build Coastguard Worker   OverlayableItem overlayable_item(overlayable);
270*d57664e9SAndroid Build Coastguard Worker   overlayable_item.policies |= PolicyFlags::PRODUCT_PARTITION;
271*d57664e9SAndroid Build Coastguard Worker   overlayable_item.policies |= PolicyFlags::VENDOR_PARTITION;
272*d57664e9SAndroid Build Coastguard Worker   overlayable_item.comment = "comment";
273*d57664e9SAndroid Build Coastguard Worker   overlayable_item.source = android::Source("res/values/overlayable.xml", 42);
274*d57664e9SAndroid Build Coastguard Worker 
275*d57664e9SAndroid Build Coastguard Worker   const ResourceName name = test::ParseNameOrDie("android:string/foo");
276*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetOverlayable(overlayable_item).Build(),
277*d57664e9SAndroid Build Coastguard Worker                                 test::GetDiagnostics()));
278*d57664e9SAndroid Build Coastguard Worker   std::optional<ResourceTable::SearchResult> search_result = table.FindResource(name);
279*d57664e9SAndroid Build Coastguard Worker 
280*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(search_result);
281*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(search_result.value().entry->overlayable_item);
282*d57664e9SAndroid Build Coastguard Worker 
283*d57664e9SAndroid Build Coastguard Worker   OverlayableItem& result_overlayable_item = search_result.value().entry->overlayable_item.value();
284*d57664e9SAndroid Build Coastguard Worker   EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name"));
285*d57664e9SAndroid Build Coastguard Worker   EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://theme"));
286*d57664e9SAndroid Build Coastguard Worker   EXPECT_THAT(result_overlayable_item.overlayable->source.path, Eq("res/values/overlayable.xml"));
287*d57664e9SAndroid Build Coastguard Worker   EXPECT_THAT(result_overlayable_item.overlayable->source.line, 40);
288*d57664e9SAndroid Build Coastguard Worker   EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::PRODUCT_PARTITION
289*d57664e9SAndroid Build Coastguard Worker                                                    | PolicyFlags::VENDOR_PARTITION));
290*d57664e9SAndroid Build Coastguard Worker   ASSERT_THAT(result_overlayable_item.comment, StrEq("comment"));
291*d57664e9SAndroid Build Coastguard Worker   EXPECT_THAT(result_overlayable_item.source.path, Eq("res/values/overlayable.xml"));
292*d57664e9SAndroid Build Coastguard Worker   EXPECT_THAT(result_overlayable_item.source.line, 42);
293*d57664e9SAndroid Build Coastguard Worker }
294*d57664e9SAndroid Build Coastguard Worker 
TEST(ResourceTableTest,SetMultipleOverlayableResources)295*d57664e9SAndroid Build Coastguard Worker TEST(ResourceTableTest, SetMultipleOverlayableResources) {
296*d57664e9SAndroid Build Coastguard Worker   ResourceTable table;
297*d57664e9SAndroid Build Coastguard Worker 
298*d57664e9SAndroid Build Coastguard Worker   const ResourceName foo = test::ParseNameOrDie("android:string/foo");
299*d57664e9SAndroid Build Coastguard Worker   auto group = std::make_shared<Overlayable>("Name", "overlay://theme");
300*d57664e9SAndroid Build Coastguard Worker   OverlayableItem overlayable(group);
301*d57664e9SAndroid Build Coastguard Worker   overlayable.policies = PolicyFlags::PRODUCT_PARTITION;
302*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(table.AddResource(NewResourceBuilder(foo).SetOverlayable(overlayable).Build(),
303*d57664e9SAndroid Build Coastguard Worker                                 test::GetDiagnostics()));
304*d57664e9SAndroid Build Coastguard Worker 
305*d57664e9SAndroid Build Coastguard Worker   const ResourceName bar = test::ParseNameOrDie("android:string/bar");
306*d57664e9SAndroid Build Coastguard Worker   OverlayableItem overlayable2(group);
307*d57664e9SAndroid Build Coastguard Worker   overlayable2.policies = PolicyFlags::PRODUCT_PARTITION;
308*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(table.AddResource(NewResourceBuilder(bar).SetOverlayable(overlayable2).Build(),
309*d57664e9SAndroid Build Coastguard Worker                                 test::GetDiagnostics()));
310*d57664e9SAndroid Build Coastguard Worker 
311*d57664e9SAndroid Build Coastguard Worker   const ResourceName baz = test::ParseNameOrDie("android:string/baz");
312*d57664e9SAndroid Build Coastguard Worker   OverlayableItem overlayable3(group);
313*d57664e9SAndroid Build Coastguard Worker   overlayable3.policies = PolicyFlags::VENDOR_PARTITION;
314*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(table.AddResource(NewResourceBuilder(baz).SetOverlayable(overlayable3).Build(),
315*d57664e9SAndroid Build Coastguard Worker                                 test::GetDiagnostics()));
316*d57664e9SAndroid Build Coastguard Worker }
317*d57664e9SAndroid Build Coastguard Worker 
TEST(ResourceTableTest,SetOverlayableDifferentResourcesDifferentName)318*d57664e9SAndroid Build Coastguard Worker TEST(ResourceTableTest, SetOverlayableDifferentResourcesDifferentName) {
319*d57664e9SAndroid Build Coastguard Worker   ResourceTable table;
320*d57664e9SAndroid Build Coastguard Worker 
321*d57664e9SAndroid Build Coastguard Worker   const ResourceName foo = test::ParseNameOrDie("android:string/foo");
322*d57664e9SAndroid Build Coastguard Worker   OverlayableItem overlayable_item(std::make_shared<Overlayable>("Name", "overlay://theme"));
323*d57664e9SAndroid Build Coastguard Worker   overlayable_item.policies = PolicyFlags::PRODUCT_PARTITION;
324*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(table.AddResource(NewResourceBuilder(foo).SetOverlayable(overlayable_item).Build(),
325*d57664e9SAndroid Build Coastguard Worker                                 test::GetDiagnostics()));
326*d57664e9SAndroid Build Coastguard Worker 
327*d57664e9SAndroid Build Coastguard Worker   const ResourceName bar = test::ParseNameOrDie("android:string/bar");
328*d57664e9SAndroid Build Coastguard Worker   OverlayableItem overlayable_item2(std::make_shared<Overlayable>("Name2",  "overlay://theme"));
329*d57664e9SAndroid Build Coastguard Worker   overlayable_item2.policies = PolicyFlags::PRODUCT_PARTITION;
330*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(table.AddResource(NewResourceBuilder(bar).SetOverlayable(overlayable_item2).Build(),
331*d57664e9SAndroid Build Coastguard Worker                                 test::GetDiagnostics()));
332*d57664e9SAndroid Build Coastguard Worker }
333*d57664e9SAndroid Build Coastguard Worker 
TEST(ResourceTableTest,SetOverlayableSameResourcesFail)334*d57664e9SAndroid Build Coastguard Worker TEST(ResourceTableTest, SetOverlayableSameResourcesFail) {
335*d57664e9SAndroid Build Coastguard Worker   ResourceTable table;
336*d57664e9SAndroid Build Coastguard Worker   const ResourceName name = test::ParseNameOrDie("android:string/foo");
337*d57664e9SAndroid Build Coastguard Worker 
338*d57664e9SAndroid Build Coastguard Worker   auto overlayable = std::make_shared<Overlayable>("Name", "overlay://theme");
339*d57664e9SAndroid Build Coastguard Worker   OverlayableItem overlayable_item(overlayable);
340*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetOverlayable(overlayable_item).Build(),
341*d57664e9SAndroid Build Coastguard Worker                                 test::GetDiagnostics()));
342*d57664e9SAndroid Build Coastguard Worker 
343*d57664e9SAndroid Build Coastguard Worker   OverlayableItem overlayable_item2(overlayable);
344*d57664e9SAndroid Build Coastguard Worker   ASSERT_FALSE(table.AddResource(NewResourceBuilder(name).SetOverlayable(overlayable_item2).Build(),
345*d57664e9SAndroid Build Coastguard Worker                                  test::GetDiagnostics()));
346*d57664e9SAndroid Build Coastguard Worker }
347*d57664e9SAndroid Build Coastguard Worker 
TEST(ResourceTableTest,SetOverlayableSameResourcesDifferentNameFail)348*d57664e9SAndroid Build Coastguard Worker TEST(ResourceTableTest,  SetOverlayableSameResourcesDifferentNameFail) {
349*d57664e9SAndroid Build Coastguard Worker   ResourceTable table;
350*d57664e9SAndroid Build Coastguard Worker   const ResourceName name = test::ParseNameOrDie("android:string/foo");
351*d57664e9SAndroid Build Coastguard Worker 
352*d57664e9SAndroid Build Coastguard Worker   auto overlayable = std::make_shared<Overlayable>("Name", "overlay://theme");
353*d57664e9SAndroid Build Coastguard Worker   OverlayableItem overlayable_item(overlayable);
354*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetOverlayable(overlayable_item).Build(),
355*d57664e9SAndroid Build Coastguard Worker                                 test::GetDiagnostics()));
356*d57664e9SAndroid Build Coastguard Worker 
357*d57664e9SAndroid Build Coastguard Worker   auto overlayable2 = std::make_shared<Overlayable>("Other", "overlay://theme");
358*d57664e9SAndroid Build Coastguard Worker   OverlayableItem overlayable_item2(overlayable2);
359*d57664e9SAndroid Build Coastguard Worker   ASSERT_FALSE(table.AddResource(NewResourceBuilder(name).SetOverlayable(overlayable_item2).Build(),
360*d57664e9SAndroid Build Coastguard Worker                                  test::GetDiagnostics()));
361*d57664e9SAndroid Build Coastguard Worker }
362*d57664e9SAndroid Build Coastguard Worker 
TEST(ResourceTableTest,ConflictingIds)363*d57664e9SAndroid Build Coastguard Worker TEST(ResourceTableTest, ConflictingIds) {
364*d57664e9SAndroid Build Coastguard Worker   ResourceTable table;
365*d57664e9SAndroid Build Coastguard Worker   const ResourceName name = test::ParseNameOrDie("android:string/foo");
366*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(table.AddResource(NewResourceBuilder(name).SetId(0x01010000).Build(),
367*d57664e9SAndroid Build Coastguard Worker                                 test::GetDiagnostics()));
368*d57664e9SAndroid Build Coastguard Worker   ASSERT_FALSE(table.AddResource(NewResourceBuilder(name).SetId(0x01010001).Build(),
369*d57664e9SAndroid Build Coastguard Worker                                  test::GetDiagnostics()));
370*d57664e9SAndroid Build Coastguard Worker }
371*d57664e9SAndroid Build Coastguard Worker 
TEST(ResourceTableTest,ConflictingIdsCreateEntry)372*d57664e9SAndroid Build Coastguard Worker TEST(ResourceTableTest, ConflictingIdsCreateEntry) {
373*d57664e9SAndroid Build Coastguard Worker   ResourceTable table;
374*d57664e9SAndroid Build Coastguard Worker   const ResourceName name = test::ParseNameOrDie("android:string/foo");
375*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(table.AddResource(
376*d57664e9SAndroid Build Coastguard Worker       NewResourceBuilder(name).SetId(0x01010000, OnIdConflict::CREATE_ENTRY).Build(),
377*d57664e9SAndroid Build Coastguard Worker       test::GetDiagnostics()));
378*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(table.AddResource(
379*d57664e9SAndroid Build Coastguard Worker       NewResourceBuilder(name).SetId(0x01010001, OnIdConflict::CREATE_ENTRY).Build(),
380*d57664e9SAndroid Build Coastguard Worker       test::GetDiagnostics()));
381*d57664e9SAndroid Build Coastguard Worker 
382*d57664e9SAndroid Build Coastguard Worker   // Non-ambiguous query
383*d57664e9SAndroid Build Coastguard Worker   ASSERT_TRUE(table.AddResource(
384*d57664e9SAndroid Build Coastguard Worker       NewResourceBuilder(name).SetId(0x01010001).SetValue(std::make_unique<Id>()).Build(),
385*d57664e9SAndroid Build Coastguard Worker       test::GetDiagnostics()));
386*d57664e9SAndroid Build Coastguard Worker }
387*d57664e9SAndroid Build Coastguard Worker 
388*d57664e9SAndroid Build Coastguard Worker }  // namespace aapt
389