Home | History | Annotate | Download | only in proto
      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 
     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 
    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 
    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 
    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 
    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 
    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 
    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