blob: 1a1f73fa4bb923d1c75c3cfcef0a6753120e29ae [file] [log] [blame]
Adam Lesinski6f6ceb72014-11-14 14:48:12 -08001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "ResourceTable.h"
Adam Lesinskicacb28f2016-10-19 12:18:14 -070018#include "Diagnostics.h"
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080019#include "ResourceValues.h"
Adam Lesinskid0f116b2016-07-08 15:00:32 -070020#include "test/Test.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070021#include "util/Util.h"
22
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080023#include <algorithm>
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080024#include <ostream>
25#include <string>
26
MÃ¥rten Kongstad5c541f62018-06-20 08:46:41 +020027using ::android::ConfigDescription;
Adam Lesinski71be7052017-12-12 16:48:07 -080028using ::android::StringPiece;
29using ::testing::Eq;
Adam Lesinskia45893a2017-05-30 15:19:02 -070030using ::testing::NotNull;
Adam Lesinski71be7052017-12-12 16:48:07 -080031using ::testing::StrEq;
Adam Lesinskia45893a2017-05-30 15:19:02 -070032
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080033namespace aapt {
34
Adam Lesinskicc5609d2016-04-05 12:41:07 -070035TEST(ResourceTableTest, FailToAddResourceWithBadName) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070036 ResourceTable table;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080037
Adam Lesinskice5e56e2016-10-21 17:56:45 -070038 EXPECT_FALSE(table.AddResource(
39 test::ParseNameOrDie("android:id/hey,there"), ConfigDescription{}, "",
40 test::ValueBuilder<Id>().SetSource("test.xml", 21u).Build(),
41 test::GetDiagnostics()));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080042
Adam Lesinskice5e56e2016-10-21 17:56:45 -070043 EXPECT_FALSE(table.AddResource(
44 test::ParseNameOrDie("android:id/hey:there"), ConfigDescription{}, "",
45 test::ValueBuilder<Id>().SetSource("test.xml", 21u).Build(),
46 test::GetDiagnostics()));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080047}
48
Adam Lesinskib1afa072017-03-29 13:52:38 -070049TEST(ResourceTableTest, AddResourceWithWeirdNameWhenAddingMangledResources) {
50 ResourceTable table;
51
Adam Lesinski71be7052017-12-12 16:48:07 -080052 EXPECT_TRUE(table.AddResourceMangled(
Adam Lesinskib1afa072017-03-29 13:52:38 -070053 test::ParseNameOrDie("android:id/heythere "), ConfigDescription{}, "",
54 test::ValueBuilder<Id>().SetSource("test.xml", 21u).Build(), test::GetDiagnostics()));
55}
56
Adam Lesinskicc5609d2016-04-05 12:41:07 -070057TEST(ResourceTableTest, AddOneResource) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070058 ResourceTable table;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080059
Adam Lesinskice5e56e2016-10-21 17:56:45 -070060 EXPECT_TRUE(table.AddResource(
61 test::ParseNameOrDie("android:attr/id"), ConfigDescription{}, "",
62 test::ValueBuilder<Id>().SetSource("test/path/file.xml", 23u).Build(),
63 test::GetDiagnostics()));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080064
Adam Lesinskia45893a2017-05-30 15:19:02 -070065 EXPECT_THAT(test::GetValue<Id>(&table, "android:attr/id"), NotNull());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080066}
67
Adam Lesinskicc5609d2016-04-05 12:41:07 -070068TEST(ResourceTableTest, AddMultipleResources) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070069 ResourceTable table;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080070
Adam Lesinskicacb28f2016-10-19 12:18:14 -070071 ConfigDescription config;
Adam Lesinskice5e56e2016-10-21 17:56:45 -070072 ConfigDescription language_config;
73 memcpy(language_config.language, "pl", sizeof(language_config.language));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080074
Adam Lesinskice5e56e2016-10-21 17:56:45 -070075 EXPECT_TRUE(table.AddResource(
76 test::ParseNameOrDie("android:attr/layout_width"), config, "",
77 test::ValueBuilder<Id>().SetSource("test/path/file.xml", 10u).Build(),
78 test::GetDiagnostics()));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080079
Adam Lesinskice5e56e2016-10-21 17:56:45 -070080 EXPECT_TRUE(table.AddResource(
81 test::ParseNameOrDie("android:attr/id"), config, "",
82 test::ValueBuilder<Id>().SetSource("test/path/file.xml", 12u).Build(),
83 test::GetDiagnostics()));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080084
Adam Lesinskice5e56e2016-10-21 17:56:45 -070085 EXPECT_TRUE(table.AddResource(
86 test::ParseNameOrDie("android:string/ok"), config, "",
87 test::ValueBuilder<Id>().SetSource("test/path/file.xml", 14u).Build(),
88 test::GetDiagnostics()));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080089
Adam Lesinskice5e56e2016-10-21 17:56:45 -070090 EXPECT_TRUE(table.AddResource(
91 test::ParseNameOrDie("android:string/ok"), language_config, "",
Adam Lesinskicacb28f2016-10-19 12:18:14 -070092 test::ValueBuilder<BinaryPrimitive>(android::Res_value{})
Adam Lesinskice5e56e2016-10-21 17:56:45 -070093 .SetSource("test/path/file.xml", 20u)
94 .Build(),
95 test::GetDiagnostics()));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080096
Adam Lesinskia45893a2017-05-30 15:19:02 -070097 EXPECT_THAT(test::GetValue<Id>(&table, "android:attr/layout_width"), NotNull());
98 EXPECT_THAT(test::GetValue<Id>(&table, "android:attr/id"), NotNull());
99 EXPECT_THAT(test::GetValue<Id>(&table, "android:string/ok"), NotNull());
100 EXPECT_THAT(test::GetValueForConfig<BinaryPrimitive>(&table, "android:string/ok", language_config), NotNull());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800101}
102
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700103TEST(ResourceTableTest, OverrideWeakResourceValue) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700104 ResourceTable table;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800105
Adam Lesinski73bff1e2017-12-08 16:06:10 -0800106 ASSERT_TRUE(table.AddResource(test::ParseNameOrDie("android:attr/foo"), ConfigDescription{}, "",
107 test::AttributeBuilder().SetWeak(true).Build(),
108 test::GetDiagnostics()));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800109
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700110 Attribute* attr = test::GetValue<Attribute>(&table, "android:attr/foo");
Adam Lesinskia45893a2017-05-30 15:19:02 -0700111 ASSERT_THAT(attr, NotNull());
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700112 EXPECT_TRUE(attr->IsWeak());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800113
Adam Lesinski73bff1e2017-12-08 16:06:10 -0800114 ASSERT_TRUE(table.AddResource(test::ParseNameOrDie("android:attr/foo"), ConfigDescription{}, "",
115 util::make_unique<Attribute>(), test::GetDiagnostics()));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800116
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700117 attr = test::GetValue<Attribute>(&table, "android:attr/foo");
Adam Lesinskia45893a2017-05-30 15:19:02 -0700118 ASSERT_THAT(attr, NotNull());
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700119 EXPECT_FALSE(attr->IsWeak());
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800120}
121
Adam Lesinski73bff1e2017-12-08 16:06:10 -0800122TEST(ResourceTableTest, AllowCompatibleDuplicateAttributes) {
123 ResourceTable table;
124
125 const ResourceName name = test::ParseNameOrDie("android:attr/foo");
126 Attribute attr_one(android::ResTable_map::TYPE_STRING);
127 attr_one.SetWeak(true);
128 Attribute attr_two(android::ResTable_map::TYPE_STRING | android::ResTable_map::TYPE_REFERENCE);
129 attr_two.SetWeak(true);
130
131 ASSERT_TRUE(table.AddResource(name, ConfigDescription{}, "",
132 util::make_unique<Attribute>(attr_one), test::GetDiagnostics()));
133 ASSERT_TRUE(table.AddResource(name, ConfigDescription{}, "",
134 util::make_unique<Attribute>(attr_two), test::GetDiagnostics()));
135}
136
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700137TEST(ResourceTableTest, ProductVaryingValues) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700138 ResourceTable table;
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800139
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700140 EXPECT_TRUE(table.AddResource(test::ParseNameOrDie("android:string/foo"),
141 test::ParseConfigOrDie("land"), "tablet",
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700142 util::make_unique<Id>(),
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700143 test::GetDiagnostics()));
144 EXPECT_TRUE(table.AddResource(test::ParseNameOrDie("android:string/foo"),
145 test::ParseConfigOrDie("land"), "phone",
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700146 util::make_unique<Id>(),
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700147 test::GetDiagnostics()));
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800148
Adam Lesinskia45893a2017-05-30 15:19:02 -0700149 EXPECT_THAT(test::GetValueForConfigAndProduct<Id>(&table, "android:string/foo",test::ParseConfigOrDie("land"), "tablet"), NotNull());
150 EXPECT_THAT(test::GetValueForConfigAndProduct<Id>(&table, "android:string/foo",test::ParseConfigOrDie("land"), "phone"), NotNull());
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800151
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700152 Maybe<ResourceTable::SearchResult> sr =
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700153 table.FindResource(test::ParseNameOrDie("android:string/foo"));
Adam Lesinskia45893a2017-05-30 15:19:02 -0700154 ASSERT_TRUE(sr);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700155 std::vector<ResourceConfigValue*> values =
Adam Lesinskib1afa072017-03-29 13:52:38 -0700156 sr.value().entry->FindAllValues(test::ParseConfigOrDie("land"));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700157 ASSERT_EQ(2u, values.size());
158 EXPECT_EQ(std::string("phone"), values[0]->product);
159 EXPECT_EQ(std::string("tablet"), values[1]->product);
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800160}
161
Adam Lesinski71be7052017-12-12 16:48:07 -0800162static StringPiece LevelToString(Visibility::Level level) {
163 switch (level) {
164 case Visibility::Level::kPrivate:
165 return "private";
166 case Visibility::Level::kPublic:
167 return "private";
168 default:
169 return "undefined";
170 }
171}
172
173static ::testing::AssertionResult VisibilityOfResource(const ResourceTable& table,
174 const ResourceNameRef& name,
175 Visibility::Level level,
176 const StringPiece& comment) {
177 Maybe<ResourceTable::SearchResult> result = table.FindResource(name);
178 if (!result) {
179 return ::testing::AssertionFailure() << "no resource '" << name << "' found in table";
180 }
181
182 const Visibility& visibility = result.value().entry->visibility;
183 if (visibility.level != level) {
184 return ::testing::AssertionFailure() << "expected visibility " << LevelToString(level)
185 << " but got " << LevelToString(visibility.level);
186 }
187
188 if (visibility.comment != comment) {
189 return ::testing::AssertionFailure() << "expected visibility comment '" << comment
190 << "' but got '" << visibility.comment << "'";
191 }
192 return ::testing::AssertionSuccess();
193}
194
195TEST(ResourceTableTest, SetVisibility) {
196 using Level = Visibility::Level;
197
198 ResourceTable table;
199 const ResourceName name = test::ParseNameOrDie("android:string/foo");
200
201 Visibility visibility;
202 visibility.level = Visibility::Level::kPrivate;
203 visibility.comment = "private";
204 ASSERT_TRUE(table.SetVisibility(name, visibility, test::GetDiagnostics()));
205 ASSERT_TRUE(VisibilityOfResource(table, name, Level::kPrivate, "private"));
206
207 visibility.level = Visibility::Level::kUndefined;
208 visibility.comment = "undefined";
209 ASSERT_TRUE(table.SetVisibility(name, visibility, test::GetDiagnostics()));
210 ASSERT_TRUE(VisibilityOfResource(table, name, Level::kPrivate, "private"));
211
212 visibility.level = Visibility::Level::kPublic;
213 visibility.comment = "public";
214 ASSERT_TRUE(table.SetVisibility(name, visibility, test::GetDiagnostics()));
215 ASSERT_TRUE(VisibilityOfResource(table, name, Level::kPublic, "public"));
216
217 visibility.level = Visibility::Level::kPrivate;
218 visibility.comment = "private";
219 ASSERT_TRUE(table.SetVisibility(name, visibility, test::GetDiagnostics()));
220 ASSERT_TRUE(VisibilityOfResource(table, name, Level::kPublic, "public"));
221}
222
223TEST(ResourceTableTest, SetAllowNew) {
224 ResourceTable table;
225 const ResourceName name = test::ParseNameOrDie("android:string/foo");
226
227 AllowNew allow_new;
228 Maybe<ResourceTable::SearchResult> result;
229
230 allow_new.comment = "first";
231 ASSERT_TRUE(table.SetAllowNew(name, allow_new, test::GetDiagnostics()));
232 result = table.FindResource(name);
233 ASSERT_TRUE(result);
234 ASSERT_TRUE(result.value().entry->allow_new);
235 ASSERT_THAT(result.value().entry->allow_new.value().comment, StrEq("first"));
236
237 allow_new.comment = "second";
238 ASSERT_TRUE(table.SetAllowNew(name, allow_new, test::GetDiagnostics()));
239 result = table.FindResource(name);
240 ASSERT_TRUE(result);
241 ASSERT_TRUE(result.value().entry->allow_new);
242 ASSERT_THAT(result.value().entry->allow_new.value().comment, StrEq("second"));
243}
244
245TEST(ResourceTableTest, SetOverlayable) {
246 ResourceTable table;
247 const ResourceName name = test::ParseNameOrDie("android:string/foo");
248
249 Overlayable overlayable;
250
251 overlayable.comment = "first";
252 ASSERT_TRUE(table.SetOverlayable(name, overlayable, test::GetDiagnostics()));
253 Maybe<ResourceTable::SearchResult> result = table.FindResource(name);
254 ASSERT_TRUE(result);
255 ASSERT_TRUE(result.value().entry->overlayable);
256 ASSERT_THAT(result.value().entry->overlayable.value().comment, StrEq("first"));
257
258 overlayable.comment = "second";
259 ASSERT_FALSE(table.SetOverlayable(name, overlayable, test::GetDiagnostics()));
260}
261
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700262} // namespace aapt