1 /*
2 * Copyright (C) 2016 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 "format/proto/ProtoSerialize.h"
18
19 #include "ResourceUtils.h"
20 #include "format/proto/ProtoDeserialize.h"
21 #include "test/Test.h"
22
23 using ::android::ConfigDescription;
24 using ::android::StringPiece;
25 using ::testing::Eq;
26 using ::testing::IsEmpty;
27 using ::testing::NotNull;
28 using ::testing::SizeIs;
29 using ::testing::StrEq;
30
31 using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
32
33 namespace aapt {
34
35 class MockFileCollection : public io::IFileCollection {
36 public:
37 MOCK_METHOD1(FindFile, io::IFile*(const StringPiece& path));
38 MOCK_METHOD0(Iterator, std::unique_ptr<io::IFileCollectionIterator>());
39 MOCK_METHOD0(GetDirSeparator, char());
40 };
41
TEST(ProtoSerializeTest,SerializeSinglePackage)42 TEST(ProtoSerializeTest, SerializeSinglePackage) {
43 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
44 std::unique_ptr<ResourceTable> table =
45 test::ResourceTableBuilder()
46 .SetPackageId("com.app.a", 0x7f)
47 .AddFileReference("com.app.a:layout/main", ResourceId(0x7f020000), "res/layout/main.xml")
48 .AddReference("com.app.a:layout/other", ResourceId(0x7f020001), "com.app.a:layout/main")
49 .AddString("com.app.a:string/text", {}, "hi")
50 .AddValue("com.app.a:id/foo", {}, util::make_unique<Id>())
51 .SetSymbolState("com.app.a:bool/foo", {}, Visibility::Level::kUndefined,
52 true /*allow_new*/)
53 .Build();
54
55 Visibility public_symbol;
56 public_symbol.level = Visibility::Level::kPublic;
57 ASSERT_TRUE(table->SetVisibilityWithId(test::ParseNameOrDie("com.app.a:layout/main"),
58 public_symbol, ResourceId(0x7f020000),
59 context->GetDiagnostics()));
60
61 Id* id = test::GetValue<Id>(table.get(), "com.app.a:id/foo");
62 ASSERT_THAT(id, NotNull());
63
64 // Make a plural.
65 std::unique_ptr<Plural> plural = util::make_unique<Plural>();
66 plural->values[Plural::One] = util::make_unique<String>(table->string_pool.MakeRef("one"));
67 ASSERT_TRUE(table->AddResource(test::ParseNameOrDie("com.app.a:plurals/hey"), ConfigDescription{},
68 {}, std::move(plural), context->GetDiagnostics()));
69
70 // Make a styled string.
71 StyleString style_string;
72 style_string.str = "hello";
73 style_string.spans.push_back(Span{"b", 0u, 4u});
74 ASSERT_TRUE(
75 table->AddResource(test::ParseNameOrDie("com.app.a:string/styled"), ConfigDescription{}, {},
76 util::make_unique<StyledString>(table->string_pool.MakeRef(style_string)),
77 context->GetDiagnostics()));
78
79 // Make a resource with different products.
80 ASSERT_TRUE(table->AddResource(
81 test::ParseNameOrDie("com.app.a:integer/one"), test::ParseConfigOrDie("land"), {},
82 test::BuildPrimitive(android::Res_value::TYPE_INT_DEC, 123u), context->GetDiagnostics()));
83 ASSERT_TRUE(table->AddResource(
84 test::ParseNameOrDie("com.app.a:integer/one"), test::ParseConfigOrDie("land"), "tablet",
85 test::BuildPrimitive(android::Res_value::TYPE_INT_HEX, 321u), context->GetDiagnostics()));
86
87 // Make a reference with both resource name and resource ID.
88 // The reference should point to a resource outside of this table to test that both name and id
89 // get serialized.
90 Reference expected_ref;
91 expected_ref.name = test::ParseNameOrDie("android:layout/main");
92 expected_ref.id = ResourceId(0x01020000);
93 ASSERT_TRUE(table->AddResource(
94 test::ParseNameOrDie("com.app.a:layout/abc"), ConfigDescription::DefaultConfig(), {},
95 util::make_unique<Reference>(expected_ref), context->GetDiagnostics()));
96
97 // Make an overlayable resource.
98 OverlayableItem overlayable_item(std::make_shared<Overlayable>(
99 "OverlayableName", "overlay://theme", Source("res/values/overlayable.xml", 40)));
100 overlayable_item.source = Source("res/values/overlayable.xml", 42);
101 ASSERT_TRUE(table->SetOverlayable(test::ParseNameOrDie("com.app.a:integer/overlayable"),
102 overlayable_item, test::GetDiagnostics()));
103
104 pb::ResourceTable pb_table;
105 SerializeTableToPb(*table, &pb_table, context->GetDiagnostics());
106
107 test::TestFile file_a("res/layout/main.xml");
108 MockFileCollection files;
109 EXPECT_CALL(files, FindFile(Eq("res/layout/main.xml")))
110 .WillRepeatedly(::testing::Return(&file_a));
111
112 ResourceTable new_table;
113 std::string error;
114 ASSERT_TRUE(DeserializeTableFromPb(pb_table, &files, &new_table, &error)) << error;
115 EXPECT_THAT(error, IsEmpty());
116
117 Id* new_id = test::GetValue<Id>(&new_table, "com.app.a:id/foo");
118 ASSERT_THAT(new_id, NotNull());
119 EXPECT_THAT(new_id->IsWeak(), Eq(id->IsWeak()));
120
121 Maybe<ResourceTable::SearchResult> result =
122 new_table.FindResource(test::ParseNameOrDie("com.app.a:layout/main"));
123 ASSERT_TRUE(result);
124
125 EXPECT_THAT(result.value().type->visibility_level, Eq(Visibility::Level::kPublic));
126 EXPECT_THAT(result.value().entry->visibility.level, Eq(Visibility::Level::kPublic));
127
128 result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/foo"));
129 ASSERT_TRUE(result);
130 EXPECT_THAT(result.value().entry->visibility.level, Eq(Visibility::Level::kUndefined));
131 EXPECT_TRUE(result.value().entry->allow_new);
132
133 // Find the product-dependent values
134 BinaryPrimitive* prim = test::GetValueForConfigAndProduct<BinaryPrimitive>(
135 &new_table, "com.app.a:integer/one", test::ParseConfigOrDie("land"), "");
136 ASSERT_THAT(prim, NotNull());
137 EXPECT_THAT(prim->value.data, Eq(123u));
138 EXPECT_THAT(prim->value.dataType, Eq(0x10));
139
140 prim = test::GetValueForConfigAndProduct<BinaryPrimitive>(
141 &new_table, "com.app.a:integer/one", test::ParseConfigOrDie("land"), "tablet");
142 ASSERT_THAT(prim, NotNull());
143 EXPECT_THAT(prim->value.data, Eq(321u));
144 EXPECT_THAT(prim->value.dataType, Eq(0x11));
145
146 Reference* actual_ref = test::GetValue<Reference>(&new_table, "com.app.a:layout/abc");
147 ASSERT_THAT(actual_ref, NotNull());
148 ASSERT_TRUE(actual_ref->name);
149 ASSERT_TRUE(actual_ref->id);
150 EXPECT_THAT(*actual_ref, Eq(expected_ref));
151
152 FileReference* actual_file_ref =
153 test::GetValue<FileReference>(&new_table, "com.app.a:layout/main");
154 ASSERT_THAT(actual_file_ref, NotNull());
155 EXPECT_THAT(actual_file_ref->file, Eq(&file_a));
156
157 StyledString* actual_styled_str =
158 test::GetValue<StyledString>(&new_table, "com.app.a:string/styled");
159 ASSERT_THAT(actual_styled_str, NotNull());
160 EXPECT_THAT(actual_styled_str->value->value, Eq("hello"));
161 ASSERT_THAT(actual_styled_str->value->spans, SizeIs(1u));
162 EXPECT_THAT(*actual_styled_str->value->spans[0].name, Eq("b"));
163 EXPECT_THAT(actual_styled_str->value->spans[0].first_char, Eq(0u));
164 EXPECT_THAT(actual_styled_str->value->spans[0].last_char, Eq(4u));
165
166 Maybe<ResourceTable::SearchResult> search_result =
167 new_table.FindResource(test::ParseNameOrDie("com.app.a:integer/overlayable"));
168 ASSERT_TRUE(search_result);
169 ASSERT_THAT(search_result.value().entry, NotNull());
170 ASSERT_TRUE(search_result.value().entry->overlayable_item);
171 OverlayableItem& result_overlayable_item = search_result.value().entry->overlayable_item.value();
172 EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("OverlayableName"));
173 EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://theme"));
174 EXPECT_THAT(result_overlayable_item.overlayable->source.path, Eq("res/values/overlayable.xml"));
175 EXPECT_THAT(result_overlayable_item.overlayable->source.line, Eq(40));
176 EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::NONE));
177 EXPECT_THAT(result_overlayable_item.source.path, Eq("res/values/overlayable.xml"));
178 EXPECT_THAT(result_overlayable_item.source.line, Eq(42));
179 }
180
TEST(ProtoSerializeTest,SerializeAndDeserializeXml)181 TEST(ProtoSerializeTest, SerializeAndDeserializeXml) {
182 xml::Element element;
183 element.line_number = 22;
184 element.column_number = 23;
185 element.name = "element";
186 element.namespace_uri = "uri://";
187
188 xml::NamespaceDecl decl;
189 decl.prefix = "android";
190 decl.uri = xml::kSchemaAndroid;
191 decl.line_number = 21;
192 decl.column_number = 24;
193
194 element.namespace_decls.push_back(decl);
195
196 xml::Attribute attr;
197 attr.name = "name";
198 attr.namespace_uri = xml::kSchemaAndroid;
199 attr.value = "23dp";
200 attr.compiled_attribute = xml::AaptAttribute(Attribute{}, ResourceId(0x01010000));
201 attr.compiled_value =
202 ResourceUtils::TryParseItemForAttribute(attr.value, android::ResTable_map::TYPE_DIMENSION);
203 attr.compiled_value->SetSource(Source().WithLine(25));
204 element.attributes.push_back(std::move(attr));
205
206 std::unique_ptr<xml::Text> text = util::make_unique<xml::Text>();
207 text->line_number = 25;
208 text->column_number = 3;
209 text->text = "hey there";
210 element.AppendChild(std::move(text));
211
212 std::unique_ptr<xml::Element> child = util::make_unique<xml::Element>();
213 child->name = "child";
214
215 text = util::make_unique<xml::Text>();
216 text->text = "woah there";
217 child->AppendChild(std::move(text));
218
219 element.AppendChild(std::move(child));
220
221 pb::XmlNode pb_xml;
222 SerializeXmlToPb(element, &pb_xml);
223
224 StringPool pool;
225 xml::Element actual_el;
226 std::string error;
227 ASSERT_TRUE(DeserializeXmlFromPb(pb_xml, &actual_el, &pool, &error));
228 ASSERT_THAT(error, IsEmpty());
229
230 EXPECT_THAT(actual_el.name, StrEq("element"));
231 EXPECT_THAT(actual_el.namespace_uri, StrEq("uri://"));
232 EXPECT_THAT(actual_el.line_number, Eq(22u));
233 EXPECT_THAT(actual_el.column_number, Eq(23u));
234
235 ASSERT_THAT(actual_el.namespace_decls, SizeIs(1u));
236 const xml::NamespaceDecl& actual_decl = actual_el.namespace_decls[0];
237 EXPECT_THAT(actual_decl.prefix, StrEq("android"));
238 EXPECT_THAT(actual_decl.uri, StrEq(xml::kSchemaAndroid));
239 EXPECT_THAT(actual_decl.line_number, Eq(21u));
240 EXPECT_THAT(actual_decl.column_number, Eq(24u));
241
242 ASSERT_THAT(actual_el.attributes, SizeIs(1u));
243 const xml::Attribute& actual_attr = actual_el.attributes[0];
244 EXPECT_THAT(actual_attr.name, StrEq("name"));
245 EXPECT_THAT(actual_attr.namespace_uri, StrEq(xml::kSchemaAndroid));
246 EXPECT_THAT(actual_attr.value, StrEq("23dp"));
247
248 ASSERT_THAT(actual_attr.compiled_value, NotNull());
249 const BinaryPrimitive* prim = ValueCast<BinaryPrimitive>(actual_attr.compiled_value.get());
250 ASSERT_THAT(prim, NotNull());
251 EXPECT_THAT(prim->value.dataType, Eq(android::Res_value::TYPE_DIMENSION));
252
253 ASSERT_TRUE(actual_attr.compiled_attribute);
254 ASSERT_TRUE(actual_attr.compiled_attribute.value().id);
255
256 ASSERT_THAT(actual_el.children, SizeIs(2u));
257 const xml::Text* child_text = xml::NodeCast<xml::Text>(actual_el.children[0].get());
258 ASSERT_THAT(child_text, NotNull());
259 const xml::Element* child_el = xml::NodeCast<xml::Element>(actual_el.children[1].get());
260 ASSERT_THAT(child_el, NotNull());
261
262 EXPECT_THAT(child_text->line_number, Eq(25u));
263 EXPECT_THAT(child_text->column_number, Eq(3u));
264 EXPECT_THAT(child_text->text, StrEq("hey there"));
265
266 EXPECT_THAT(child_el->name, StrEq("child"));
267 ASSERT_THAT(child_el->children, SizeIs(1u));
268
269 child_text = xml::NodeCast<xml::Text>(child_el->children[0].get());
270 ASSERT_THAT(child_text, NotNull());
271 EXPECT_THAT(child_text->text, StrEq("woah there"));
272 }
273
TEST(ProtoSerializeTest,SerializeAndDeserializeXmlTrimEmptyWhitepsace)274 TEST(ProtoSerializeTest, SerializeAndDeserializeXmlTrimEmptyWhitepsace) {
275 xml::Element element;
276 element.line_number = 22;
277 element.column_number = 23;
278 element.name = "element";
279
280 std::unique_ptr<xml::Text> trim_text = util::make_unique<xml::Text>();
281 trim_text->line_number = 25;
282 trim_text->column_number = 3;
283 trim_text->text = " \n ";
284 element.AppendChild(std::move(trim_text));
285
286 std::unique_ptr<xml::Text> keep_text = util::make_unique<xml::Text>();
287 keep_text->line_number = 26;
288 keep_text->column_number = 3;
289 keep_text->text = " hello ";
290 element.AppendChild(std::move(keep_text));
291
292 pb::XmlNode pb_xml;
293 SerializeXmlOptions options;
294 options.remove_empty_text_nodes = true;
295 SerializeXmlToPb(element, &pb_xml, options);
296
297 StringPool pool;
298 xml::Element actual_el;
299 std::string error;
300 ASSERT_TRUE(DeserializeXmlFromPb(pb_xml, &actual_el, &pool, &error));
301 ASSERT_THAT(error, IsEmpty());
302
303 // Only the child that does not consist of only whitespace should remain
304 ASSERT_THAT(actual_el.children, SizeIs(1u));
305 const xml::Text* child_text_keep = xml::NodeCast<xml::Text>(actual_el.children[0].get());
306 ASSERT_THAT(child_text_keep, NotNull());
307 EXPECT_THAT(child_text_keep->text, StrEq( " hello "));
308 }
309
TEST(ProtoSerializeTest,SerializeAndDeserializePrimitives)310 TEST(ProtoSerializeTest, SerializeAndDeserializePrimitives) {
311 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
312 std::unique_ptr<ResourceTable> table =
313 test::ResourceTableBuilder()
314 .AddValue("android:bool/boolean_true",
315 test::BuildPrimitive(android::Res_value::TYPE_INT_BOOLEAN, true))
316 .AddValue("android:bool/boolean_false",
317 test::BuildPrimitive(android::Res_value::TYPE_INT_BOOLEAN, false))
318 .AddValue("android:color/color_rgb8", ResourceUtils::TryParseColor("#AABBCC"))
319 .AddValue("android:color/color_argb8", ResourceUtils::TryParseColor("#11223344"))
320 .AddValue("android:color/color_rgb4", ResourceUtils::TryParseColor("#DEF"))
321 .AddValue("android:color/color_argb4", ResourceUtils::TryParseColor("#5678"))
322 .AddValue("android:integer/integer_444", ResourceUtils::TryParseInt("444"))
323 .AddValue("android:integer/integer_neg_333", ResourceUtils::TryParseInt("-333"))
324 .AddValue("android:integer/hex_int_abcd", ResourceUtils::TryParseInt("0xABCD"))
325 .AddValue("android:dimen/dimen_1.39mm", ResourceUtils::TryParseFloat("1.39mm"))
326 .AddValue("android:fraction/fraction_27", ResourceUtils::TryParseFloat("27%"))
327 .AddValue("android:dimen/neg_2.3in", ResourceUtils::TryParseFloat("-2.3in"))
328 .AddValue("android:integer/null", ResourceUtils::MakeEmpty())
329 .Build();
330
331 pb::ResourceTable pb_table;
332 SerializeTableToPb(*table, &pb_table, context->GetDiagnostics());
333
334 test::TestFile file_a("res/layout/main.xml");
335 MockFileCollection files;
336 EXPECT_CALL(files, FindFile(Eq("res/layout/main.xml")))
337 .WillRepeatedly(::testing::Return(&file_a));
338
339 ResourceTable new_table;
340 std::string error;
341 ASSERT_TRUE(DeserializeTableFromPb(pb_table, &files, &new_table, &error));
342 EXPECT_THAT(error, IsEmpty());
343
344 BinaryPrimitive* bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(
345 &new_table, "android:bool/boolean_true", ConfigDescription::DefaultConfig(), "");
346 ASSERT_THAT(bp, NotNull());
347 EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_BOOLEAN));
348 EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseBool("true")->value.data));
349
350 bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:bool/boolean_false",
351 ConfigDescription::DefaultConfig(), "");
352 ASSERT_THAT(bp, NotNull());
353 EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_BOOLEAN));
354 EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseBool("false")->value.data));
355
356 bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:color/color_rgb8",
357 ConfigDescription::DefaultConfig(), "");
358 ASSERT_THAT(bp, NotNull());
359 EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_COLOR_RGB8));
360 EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseColor("#AABBCC")->value.data));
361
362 bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:color/color_argb8",
363 ConfigDescription::DefaultConfig(), "");
364 ASSERT_THAT(bp, NotNull());
365 EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_COLOR_ARGB8));
366 EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseColor("#11223344")->value.data));
367
368 bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:color/color_rgb4",
369 ConfigDescription::DefaultConfig(), "");
370 ASSERT_THAT(bp, NotNull());
371 EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_COLOR_RGB4));
372 EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseColor("#DEF")->value.data));
373
374 bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:color/color_argb4",
375 ConfigDescription::DefaultConfig(), "");
376 ASSERT_THAT(bp, NotNull());
377 EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_COLOR_ARGB4));
378 EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseColor("#5678")->value.data));
379
380 bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:integer/integer_444",
381 ConfigDescription::DefaultConfig(), "");
382 ASSERT_THAT(bp, NotNull());
383 EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_DEC));
384 EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseInt("444")->value.data));
385
386 bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(
387 &new_table, "android:integer/integer_neg_333", ConfigDescription::DefaultConfig(), "");
388 ASSERT_THAT(bp, NotNull());
389 EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_DEC));
390 EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseInt("-333")->value.data));
391
392 bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(
393 &new_table, "android:integer/hex_int_abcd", ConfigDescription::DefaultConfig(), "");
394 ASSERT_THAT(bp, NotNull());
395 EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_HEX));
396 EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseInt("0xABCD")->value.data));
397
398 bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:dimen/dimen_1.39mm",
399 ConfigDescription::DefaultConfig(), "");
400 ASSERT_THAT(bp, NotNull());
401 EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_DIMENSION));
402 EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseFloat("1.39mm")->value.data));
403
404 bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(
405 &new_table, "android:fraction/fraction_27", ConfigDescription::DefaultConfig(), "");
406 ASSERT_THAT(bp, NotNull());
407 EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_FRACTION));
408 EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseFloat("27%")->value.data));
409
410 bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:dimen/neg_2.3in",
411 ConfigDescription::DefaultConfig(), "");
412 ASSERT_THAT(bp, NotNull());
413 EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_DIMENSION));
414 EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseFloat("-2.3in")->value.data));
415
416 bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:integer/null",
417 ConfigDescription::DefaultConfig(), "");
418 ASSERT_THAT(bp, NotNull());
419 EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_NULL));
420 EXPECT_THAT(bp->value.data, Eq(ResourceUtils::MakeEmpty()->value.data));
421 }
422
ExpectConfigSerializes(const StringPiece & config_str)423 static void ExpectConfigSerializes(const StringPiece& config_str) {
424 const ConfigDescription expected_config = test::ParseConfigOrDie(config_str);
425 pb::Configuration pb_config;
426 SerializeConfig(expected_config, &pb_config);
427
428 ConfigDescription actual_config;
429 std::string error;
430 ASSERT_TRUE(DeserializeConfigFromPb(pb_config, &actual_config, &error));
431 ASSERT_THAT(error, IsEmpty());
432 EXPECT_EQ(expected_config, actual_config);
433 }
434
TEST(ProtoSerializeTest,SerializeDeserializeConfiguration)435 TEST(ProtoSerializeTest, SerializeDeserializeConfiguration) {
436 ExpectConfigSerializes("");
437
438 ExpectConfigSerializes("mcc123");
439
440 ExpectConfigSerializes("mnc123");
441
442 ExpectConfigSerializes("en");
443 ExpectConfigSerializes("en-rGB");
444 ExpectConfigSerializes("b+en+GB");
445
446 ExpectConfigSerializes("ldltr");
447 ExpectConfigSerializes("ldrtl");
448
449 ExpectConfigSerializes("sw3600dp");
450
451 ExpectConfigSerializes("w300dp");
452
453 ExpectConfigSerializes("h400dp");
454
455 ExpectConfigSerializes("small");
456 ExpectConfigSerializes("normal");
457 ExpectConfigSerializes("large");
458 ExpectConfigSerializes("xlarge");
459
460 ExpectConfigSerializes("long");
461 ExpectConfigSerializes("notlong");
462
463 ExpectConfigSerializes("round");
464 ExpectConfigSerializes("notround");
465
466 ExpectConfigSerializes("widecg");
467 ExpectConfigSerializes("nowidecg");
468
469 ExpectConfigSerializes("highdr");
470 ExpectConfigSerializes("lowdr");
471
472 ExpectConfigSerializes("port");
473 ExpectConfigSerializes("land");
474 ExpectConfigSerializes("square");
475
476 ExpectConfigSerializes("desk");
477 ExpectConfigSerializes("car");
478 ExpectConfigSerializes("television");
479 ExpectConfigSerializes("appliance");
480 ExpectConfigSerializes("watch");
481 ExpectConfigSerializes("vrheadset");
482
483 ExpectConfigSerializes("night");
484 ExpectConfigSerializes("notnight");
485
486 ExpectConfigSerializes("300dpi");
487 ExpectConfigSerializes("hdpi");
488
489 ExpectConfigSerializes("notouch");
490 ExpectConfigSerializes("stylus");
491 ExpectConfigSerializes("finger");
492
493 ExpectConfigSerializes("keysexposed");
494 ExpectConfigSerializes("keyshidden");
495 ExpectConfigSerializes("keyssoft");
496
497 ExpectConfigSerializes("nokeys");
498 ExpectConfigSerializes("qwerty");
499 ExpectConfigSerializes("12key");
500
501 ExpectConfigSerializes("navhidden");
502 ExpectConfigSerializes("navexposed");
503
504 ExpectConfigSerializes("nonav");
505 ExpectConfigSerializes("dpad");
506 ExpectConfigSerializes("trackball");
507 ExpectConfigSerializes("wheel");
508
509 ExpectConfigSerializes("300x200");
510
511 ExpectConfigSerializes("v8");
512
513 ExpectConfigSerializes(
514 "mcc123-mnc456-b+en+GB-ldltr-sw300dp-w300dp-h400dp-large-long-round-widecg-highdr-land-car-"
515 "night-xhdpi-stylus-keysexposed-qwerty-navhidden-dpad-300x200-v23");
516 }
517
TEST(ProtoSerializeTest,SerializeAndDeserializeOverlayable)518 TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) {
519 OverlayableItem overlayable_item_foo(std::make_shared<Overlayable>(
520 "CustomizableResources", "overlay://customization"));
521 overlayable_item_foo.policies |= PolicyFlags::SYSTEM_PARTITION;
522 overlayable_item_foo.policies |= PolicyFlags::PRODUCT_PARTITION;
523
524 OverlayableItem overlayable_item_bar(std::make_shared<Overlayable>(
525 "TaskBar", "overlay://theme"));
526 overlayable_item_bar.policies |= PolicyFlags::PUBLIC;
527 overlayable_item_bar.policies |= PolicyFlags::VENDOR_PARTITION;
528
529 OverlayableItem overlayable_item_baz(std::make_shared<Overlayable>(
530 "FontPack", "overlay://theme"));
531 overlayable_item_baz.policies |= PolicyFlags::PUBLIC;
532
533 OverlayableItem overlayable_item_boz(std::make_shared<Overlayable>(
534 "IconPack", "overlay://theme"));
535 overlayable_item_boz.policies |= PolicyFlags::SIGNATURE;
536 overlayable_item_boz.policies |= PolicyFlags::ODM_PARTITION;
537 overlayable_item_boz.policies |= PolicyFlags::OEM_PARTITION;
538
539 OverlayableItem overlayable_item_actor_config(std::make_shared<Overlayable>(
540 "ActorConfig", "overlay://theme"));
541 overlayable_item_actor_config.policies |= PolicyFlags::SIGNATURE;
542 overlayable_item_actor_config.policies |= PolicyFlags::ACTOR_SIGNATURE;
543
544 OverlayableItem overlayable_item_biz(std::make_shared<Overlayable>(
545 "Other", "overlay://customization"));
546 overlayable_item_biz.comment ="comment";
547
548 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
549 std::unique_ptr<ResourceTable> table =
550 test::ResourceTableBuilder()
551 .SetOverlayable("com.app.a:bool/foo", overlayable_item_foo)
552 .SetOverlayable("com.app.a:bool/bar", overlayable_item_bar)
553 .SetOverlayable("com.app.a:bool/baz", overlayable_item_baz)
554 .SetOverlayable("com.app.a:bool/boz", overlayable_item_boz)
555 .SetOverlayable("com.app.a:bool/biz", overlayable_item_biz)
556 .SetOverlayable("com.app.a:bool/actor_config", overlayable_item_actor_config)
557 .AddValue("com.app.a:bool/fiz", ResourceUtils::TryParseBool("true"))
558 .Build();
559
560 pb::ResourceTable pb_table;
561 SerializeTableToPb(*table, &pb_table, context->GetDiagnostics());
562
563 MockFileCollection files;
564 ResourceTable new_table;
565 std::string error;
566 ASSERT_TRUE(DeserializeTableFromPb(pb_table, &files, &new_table, &error));
567 EXPECT_THAT(error, IsEmpty());
568
569 Maybe<ResourceTable::SearchResult> search_result =
570 new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/foo"));
571 ASSERT_TRUE(search_result);
572 ASSERT_TRUE(search_result.value().entry->overlayable_item);
573 OverlayableItem& overlayable_item = search_result.value().entry->overlayable_item.value();
574 EXPECT_THAT(overlayable_item.overlayable->name, Eq("CustomizableResources"));
575 EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://customization"));
576 EXPECT_THAT(overlayable_item.policies, Eq(PolicyFlags::SYSTEM_PARTITION
577 | PolicyFlags::PRODUCT_PARTITION));
578
579 search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/bar"));
580 ASSERT_TRUE(search_result);
581 ASSERT_TRUE(search_result.value().entry->overlayable_item);
582 overlayable_item = search_result.value().entry->overlayable_item.value();
583 EXPECT_THAT(overlayable_item.overlayable->name, Eq("TaskBar"));
584 EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://theme"));
585 EXPECT_THAT(overlayable_item.policies, Eq(PolicyFlags::PUBLIC
586 | PolicyFlags::VENDOR_PARTITION));
587
588 search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/baz"));
589 ASSERT_TRUE(search_result);
590 ASSERT_TRUE(search_result.value().entry->overlayable_item);
591 overlayable_item = search_result.value().entry->overlayable_item.value();
592 EXPECT_THAT(overlayable_item.overlayable->name, Eq("FontPack"));
593 EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://theme"));
594 EXPECT_THAT(overlayable_item.policies, Eq(PolicyFlags::PUBLIC));
595
596 search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/boz"));
597 ASSERT_TRUE(search_result);
598 ASSERT_TRUE(search_result.value().entry->overlayable_item);
599 overlayable_item = search_result.value().entry->overlayable_item.value();
600 EXPECT_THAT(overlayable_item.overlayable->name, Eq("IconPack"));
601 EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://theme"));
602 EXPECT_THAT(overlayable_item.policies, Eq(PolicyFlags::SIGNATURE
603 | PolicyFlags::ODM_PARTITION
604 | PolicyFlags::OEM_PARTITION));
605
606 search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/actor_config"));
607 ASSERT_TRUE(search_result);
608 ASSERT_TRUE(search_result.value().entry->overlayable_item);
609 overlayable_item = search_result.value().entry->overlayable_item.value();
610 EXPECT_THAT(overlayable_item.overlayable->name, Eq("ActorConfig"));
611 EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://theme"));
612 EXPECT_THAT(overlayable_item.policies, Eq(PolicyFlags::SIGNATURE
613 | PolicyFlags::ACTOR_SIGNATURE));
614
615 search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/biz"));
616 ASSERT_TRUE(search_result);
617 ASSERT_TRUE(search_result.value().entry->overlayable_item);
618 overlayable_item = search_result.value().entry->overlayable_item.value();
619 EXPECT_THAT(overlayable_item.overlayable->name, Eq("Other"));
620 EXPECT_THAT(overlayable_item.policies, Eq(PolicyFlags::NONE));
621 EXPECT_THAT(overlayable_item.comment, Eq("comment"));
622
623 search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/fiz"));
624 ASSERT_TRUE(search_result);
625 ASSERT_FALSE(search_result.value().entry->overlayable_item);
626 }
627
TEST(ProtoSerializeTest,SerializeAndDeserializeDynamicReference)628 TEST(ProtoSerializeTest, SerializeAndDeserializeDynamicReference) {
629 Reference ref(ResourceId(0x00010001));
630 ref.is_dynamic = true;
631
632 pb::Item pb_item;
633 SerializeItemToPb(ref, &pb_item);
634
635 ASSERT_TRUE(pb_item.has_ref());
636 EXPECT_EQ(pb_item.ref().id(), ref.id.value().id);
637 EXPECT_TRUE(pb_item.ref().is_dynamic().value());
638
639 std::unique_ptr<Item> item = DeserializeItemFromPb(pb_item, android::ResStringPool(),
640 android::ConfigDescription(), nullptr,
641 nullptr, nullptr);
642 Reference* actual_ref = ValueCast<Reference>(item.get());
643 EXPECT_EQ(actual_ref->id.value().id, ref.id.value().id);
644 EXPECT_TRUE(actual_ref->is_dynamic);
645 }
646
TEST(ProtoSerializeTest,SerializeAndDeserializeNonDynamicReference)647 TEST(ProtoSerializeTest, SerializeAndDeserializeNonDynamicReference) {
648 Reference ref(ResourceId(0x00010001));
649
650 pb::Item pb_item;
651 SerializeItemToPb(ref, &pb_item);
652
653 ASSERT_TRUE(pb_item.has_ref());
654 EXPECT_EQ(pb_item.ref().id(), ref.id.value().id);
655 EXPECT_FALSE(pb_item.ref().has_is_dynamic());
656
657 std::unique_ptr<Item> item = DeserializeItemFromPb(pb_item, android::ResStringPool(),
658 android::ConfigDescription(), nullptr,
659 nullptr, nullptr);
660 Reference* actual_ref = ValueCast<Reference>(item.get());
661 EXPECT_EQ(actual_ref->id.value().id, ref.id.value().id);
662 EXPECT_FALSE(actual_ref->is_dynamic);
663 }
664
665 } // namespace aapt
666