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