Home | History | Annotate | Download | only in compile
      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 "compile/InlineXmlFormatParser.h"
     18 
     19 #include "test/Test.h"
     20 
     21 using ::testing::Eq;
     22 using ::testing::IsNull;
     23 using ::testing::Not;
     24 using ::testing::NotNull;
     25 using ::testing::SizeIs;
     26 using ::testing::StrEq;
     27 
     28 namespace aapt {
     29 
     30 TEST(InlineXmlFormatParserTest, PassThrough) {
     31   std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
     32   std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(
     33       <View xmlns:android="http://schemas.android.com/apk/res/android">
     34         <View android:text="hey">
     35           <View android:id="hi" />
     36         </View>
     37       </View>)");
     38 
     39   InlineXmlFormatParser parser;
     40   ASSERT_TRUE(parser.Consume(context.get(), doc.get()));
     41   EXPECT_THAT(parser.GetExtractedInlineXmlDocuments(), SizeIs(0u));
     42 }
     43 
     44 TEST(InlineXmlFormatParserTest, ExtractOneXmlResource) {
     45   std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
     46   std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(
     47       <View1 xmlns:android="http://schemas.android.com/apk/res/android"
     48             xmlns:aapt="http://schemas.android.com/aapt">
     49         <aapt:attr name="android:text">
     50           <View2 android:text="hey">
     51             <View3 android:id="hi" />
     52           </View2>
     53         </aapt:attr>
     54       </View1>)");
     55 
     56   doc->file.name = test::ParseNameOrDie("layout/main");
     57 
     58   InlineXmlFormatParser parser;
     59   ASSERT_TRUE(parser.Consume(context.get(), doc.get()));
     60 
     61   // One XML resource should have been extracted.
     62   EXPECT_THAT(parser.GetExtractedInlineXmlDocuments(), SizeIs(1u));
     63 
     64   xml::Element* el = doc->root.get();
     65   ASSERT_THAT(el, NotNull());
     66   EXPECT_THAT(el->name, StrEq("View1"));
     67 
     68   // The <aapt:attr> tag should be extracted.
     69   EXPECT_THAT(el->FindChild(xml::kSchemaAapt, "attr"), IsNull());
     70 
     71   // The 'android:text' attribute should be set with a reference.
     72   xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "text");
     73   ASSERT_THAT(attr, NotNull());
     74 
     75   ResourceNameRef name_ref;
     76   ASSERT_TRUE(ResourceUtils::ParseReference(attr->value, &name_ref));
     77 
     78   xml::XmlResource* extracted_doc = parser.GetExtractedInlineXmlDocuments()[0].get();
     79   ASSERT_THAT(extracted_doc, NotNull());
     80 
     81   // Make sure the generated reference is correct.
     82   EXPECT_THAT(extracted_doc->file.name, Eq(name_ref));
     83 
     84   // Verify the structure of the extracted XML.
     85   el = extracted_doc->root.get();
     86   ASSERT_THAT(el, NotNull());
     87   EXPECT_THAT(el->name, StrEq("View2"));
     88   EXPECT_THAT(el->FindChild({}, "View3"), NotNull());
     89 }
     90 
     91 TEST(InlineXmlFormatParserTest, ExtractTwoXmlResources) {
     92   std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
     93   std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(
     94       <View1 xmlns:android="http://schemas.android.com/apk/res/android"
     95             xmlns:aapt="http://schemas.android.com/aapt">
     96         <aapt:attr name="android:text">
     97           <View2 android:text="hey">
     98             <View3 android:id="hi" />
     99           </View2>
    100         </aapt:attr>
    101 
    102         <aapt:attr name="android:drawable">
    103           <vector />
    104         </aapt:attr>
    105       </View1>)");
    106 
    107   doc->file.name = test::ParseNameOrDie("layout/main");
    108 
    109   InlineXmlFormatParser parser;
    110   ASSERT_TRUE(parser.Consume(context.get(), doc.get()));
    111   ASSERT_THAT(parser.GetExtractedInlineXmlDocuments(), SizeIs(2u));
    112 
    113   xml::Element* el = doc->root.get();
    114   ASSERT_THAT(el, NotNull());
    115   EXPECT_THAT(el->name, StrEq("View1"));
    116 
    117   xml::Attribute* attr_text = el->FindAttribute(xml::kSchemaAndroid, "text");
    118   ASSERT_THAT(attr_text, NotNull());
    119 
    120   xml::Attribute* attr_drawable = el->FindAttribute(xml::kSchemaAndroid, "drawable");
    121   ASSERT_THAT(attr_drawable, NotNull());
    122 
    123   // The two extracted resources should have different names.
    124   EXPECT_THAT(attr_text->value, Not(Eq(attr_drawable->value)));
    125 
    126   // The child <aapt:attr> elements should be gone.
    127   EXPECT_THAT(el->FindChild(xml::kSchemaAapt, "attr"), IsNull());
    128 
    129   xml::XmlResource* extracted_doc_text = parser.GetExtractedInlineXmlDocuments()[0].get();
    130   ASSERT_THAT(extracted_doc_text, NotNull());
    131   ASSERT_THAT(extracted_doc_text->root, NotNull());
    132   EXPECT_THAT(extracted_doc_text->root->name, StrEq("View2"));
    133 
    134   xml::XmlResource* extracted_doc_drawable = parser.GetExtractedInlineXmlDocuments()[1].get();
    135   ASSERT_THAT(extracted_doc_drawable, NotNull());
    136   ASSERT_THAT(extracted_doc_drawable->root, NotNull());
    137   EXPECT_THAT(extracted_doc_drawable->root->name, StrEq("vector"));
    138 }
    139 
    140 TEST(InlineXmlFormatParserTest, ExtractNestedXmlResources) {
    141   std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
    142   std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(
    143       <base_root xmlns:android="http://schemas.android.com/apk/res/android"
    144             xmlns:aapt="http://schemas.android.com/aapt">
    145           <aapt:attr name="inline_xml">
    146               <inline_root>
    147                   <aapt:attr name="nested_inline_xml">
    148                       <nested_inline_root/>
    149                   </aapt:attr>
    150                   <aapt:attr name="another_nested_inline_xml">
    151                       <root/>
    152                   </aapt:attr>
    153               </inline_root>
    154           </aapt:attr>
    155           <aapt:attr name="turtles">
    156               <root1>
    157                   <aapt:attr name="all">
    158                       <root2>
    159                           <aapt:attr name="the">
    160                               <root3>
    161                                   <aapt:attr name="way">
    162                                       <root4>
    163                                           <aapt:attr name="down">
    164                                               <root5/>
    165                                           </aapt:attr>
    166                                       </root4>
    167                                   </aapt:attr>
    168                               </root3>
    169                           </aapt:attr>
    170                       </root2>
    171                   </aapt:attr>
    172               </root1>
    173           </aapt:attr>
    174       </base_root>)");
    175 
    176   doc->file.name = test::ParseNameOrDie("layout/main");
    177 
    178   InlineXmlFormatParser parser;
    179   ASSERT_TRUE(parser.Consume(context.get(), doc.get()));
    180   // Confirm that all of the nested inline xmls are parsed out.
    181   ASSERT_THAT(parser.GetExtractedInlineXmlDocuments(), SizeIs(8u));
    182 }
    183 }  // namespace aapt
    184