15eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski/*
25eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski * Copyright (C) 2016 The Android Open Source Project
35eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski *
45eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
55eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski * you may not use this file except in compliance with the License.
65eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski * You may obtain a copy of the License at
75eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski *
85eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
95eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski *
105eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski * Unless required by applicable law or agreed to in writing, software
115eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
125eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski * See the License for the specific language governing permissions and
145eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski * limitations under the License.
155eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski */
165eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
175eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski#include "compile/InlineXmlFormatParser.h"
18ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
195eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski#include "test/Test.h"
205eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
215eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskinamespace aapt {
225eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
235eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam LesinskiTEST(InlineXmlFormatParserTest, PassThrough) {
24ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
25ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"EOF(
265eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski      <View xmlns:android="http://schemas.android.com/apk/res/android">
275eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski        <View android:text="hey">
285eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski          <View android:id="hi" />
295eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski        </View>
305eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski      </View>)EOF");
315eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
32cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  InlineXmlFormatParser parser;
33ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_TRUE(parser.Consume(context.get(), doc.get()));
34ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_EQ(0u, parser.GetExtractedInlineXmlDocuments().size());
355eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski}
365eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
375eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam LesinskiTEST(InlineXmlFormatParserTest, ExtractOneXmlResource) {
38ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
39ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"EOF(
405eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski      <View1 xmlns:android="http://schemas.android.com/apk/res/android"
415eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski            xmlns:aapt="http://schemas.android.com/aapt">
425eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski        <aapt:attr name="android:text">
435eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski          <View2 android:text="hey">
445eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski            <View3 android:id="hi" />
455eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski          </View2>
465eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski        </aapt:attr>
475eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski      </View1>)EOF");
485eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
49ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  doc->file.name = test::ParseNameOrDie("layout/main");
505eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
51cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  InlineXmlFormatParser parser;
52ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_TRUE(parser.Consume(context.get(), doc.get()));
535eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
54cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // One XML resource should have been extracted.
55ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_EQ(1u, parser.GetExtractedInlineXmlDocuments().size());
565eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
57ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  xml::Element* el = xml::FindRootElement(doc.get());
58cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_NE(nullptr, el);
595eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
60cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  EXPECT_EQ("View1", el->name);
615eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
62cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // The <aapt:attr> tag should be extracted.
63ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_EQ(nullptr, el->FindChild(xml::kSchemaAapt, "attr"));
645eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
65cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // The 'android:text' attribute should be set with a reference.
66ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "text");
67cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_NE(nullptr, attr);
685eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
69ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ResourceNameRef name_ref;
70ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_TRUE(ResourceUtils::ParseReference(attr->value, &name_ref));
715eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
72ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  xml::XmlResource* extracted_doc =
73ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      parser.GetExtractedInlineXmlDocuments()[0].get();
74ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_NE(nullptr, extracted_doc);
755eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
76cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // Make sure the generated reference is correct.
77ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_EQ(name_ref.package, extracted_doc->file.name.package);
78ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_EQ(name_ref.type, extracted_doc->file.name.type);
79ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_EQ(name_ref.entry, extracted_doc->file.name.entry);
805eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
81cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // Verify the structure of the extracted XML.
82ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el = xml::FindRootElement(extracted_doc);
83cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_NE(nullptr, el);
84cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  EXPECT_EQ("View2", el->name);
85ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_NE(nullptr, el->FindChild({}, "View3"));
865eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski}
875eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
885eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam LesinskiTEST(InlineXmlFormatParserTest, ExtractTwoXmlResources) {
89ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
90ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"EOF(
915eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski      <View1 xmlns:android="http://schemas.android.com/apk/res/android"
925eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski            xmlns:aapt="http://schemas.android.com/aapt">
935eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski        <aapt:attr name="android:text">
945eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski          <View2 android:text="hey">
955eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski            <View3 android:id="hi" />
965eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski          </View2>
975eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski        </aapt:attr>
985eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
995eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski        <aapt:attr name="android:drawable">
1005eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski          <vector />
1015eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski        </aapt:attr>
1025eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski      </View1>)EOF");
1035eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
104ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  doc->file.name = test::ParseNameOrDie("layout/main");
1055eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
106cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  InlineXmlFormatParser parser;
107ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_TRUE(parser.Consume(context.get(), doc.get()));
108ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_EQ(2u, parser.GetExtractedInlineXmlDocuments().size());
1095eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
110ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  xml::Element* el = xml::FindRootElement(doc.get());
111cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_NE(nullptr, el);
1125eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
113cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  EXPECT_EQ("View1", el->name);
1145eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
115ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  xml::Attribute* attr_text = el->FindAttribute(xml::kSchemaAndroid, "text");
116ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_NE(nullptr, attr_text);
1175eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
118ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  xml::Attribute* attr_drawable =
119ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      el->FindAttribute(xml::kSchemaAndroid, "drawable");
120ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_NE(nullptr, attr_drawable);
1215eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
122cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // The two extracted resources should have different names.
123ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_NE(attr_text->value, attr_drawable->value);
1245eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
125cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // The child <aapt:attr> elements should be gone.
126ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_EQ(nullptr, el->FindChild(xml::kSchemaAapt, "attr"));
1275eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
128ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  xml::XmlResource* extracted_doc_text =
129ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      parser.GetExtractedInlineXmlDocuments()[0].get();
130ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_NE(nullptr, extracted_doc_text);
131ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el = xml::FindRootElement(extracted_doc_text);
132cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_NE(nullptr, el);
133cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  EXPECT_EQ("View2", el->name);
1345eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
135ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  xml::XmlResource* extracted_doc_drawable =
136ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      parser.GetExtractedInlineXmlDocuments()[1].get();
137ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_NE(nullptr, extracted_doc_drawable);
138ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el = xml::FindRootElement(extracted_doc_drawable);
139cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_NE(nullptr, el);
140cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  EXPECT_EQ("vector", el->name);
1415eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski}
1425eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
143cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski}  // namespace aapt
144