11ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski/*
21ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Copyright (C) 2015 The Android Open Source Project
31ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski *
41ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
51ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * you may not use this file except in compliance with the License.
61ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * You may obtain a copy of the License at
71ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski *
81ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
91ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski *
101ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Unless required by applicable law or agreed to in writing, software
111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * See the License for the specific language governing permissions and
141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * limitations under the License.
151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski */
161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
174670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski#include "format/binary/XmlFlattener.h"
18ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
19ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "androidfw/ResourceTypes.h"
20ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "link/Linkers.h"
22d0f116b619feede0cfdb647157ce5ab4d50a1c46Adam Lesinski#include "test/Test.h"
23467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include "util/BigBuffer.h"
24467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include "util/Util.h"
251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
26fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinskiusing ::aapt::test::StrEq;
27fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinskiusing ::android::StringPiece16;
28fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinskiusing ::testing::Eq;
29fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinskiusing ::testing::Ge;
30fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinskiusing ::testing::IsNull;
31fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinskiusing ::testing::Ne;
32fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinskiusing ::testing::NotNull;
33d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski
341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskinamespace aapt {
351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
361ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskiclass XmlFlattenerTest : public ::testing::Test {
37cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public:
38cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  void SetUp() override {
39f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    context_ = test::ContextBuilder()
40f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                   .SetCompilationPackage("com.app.test")
41f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                   .SetNameManglerPolicy(NameManglerPolicy{"com.app.test"})
42f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                   .AddSymbolSource(
43f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                       test::StaticSymbolSourceBuilder()
444ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski                           .AddPublicSymbol("android:attr/id", ResourceId(0x010100d0),
454ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski                                            test::AttributeBuilder().Build())
46f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                           .AddSymbol("com.app.test:id/id", ResourceId(0x7f020000))
47f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                           .AddPublicSymbol("android:attr/paddingStart", ResourceId(0x010103b3),
48f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                            test::AttributeBuilder().Build())
49f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                           .AddPublicSymbol("android:attr/colorAccent", ResourceId(0x01010435),
50f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                            test::AttributeBuilder().Build())
514ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski                           .AddSymbol("com.app.test.feature:id/foo", ResourceId(0x80020000))
524ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski                           .AddSymbol("com.app.test.feature:attr/foo", ResourceId(0x80010000),
534ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski                                      test::AttributeBuilder().Build())
54f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                           .Build())
55f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                   .Build();
56cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
57cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
584670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski  ::testing::AssertionResult Flatten(xml::XmlResource* doc, android::ResXMLTree* out_tree,
59cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski                                     const XmlFlattenerOptions& options = {}) {
60cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    using namespace android;  // For NO_ERROR on windows because it is a macro.
61cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
62cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    BigBuffer buffer(1024);
63cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    XmlFlattener flattener(&buffer, options);
64ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!flattener.Consume(context_.get(), doc)) {
65cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return ::testing::AssertionFailure() << "failed to flatten XML Tree";
661ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
671ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
68ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::unique_ptr<uint8_t[]> data = util::Copy(buffer);
69ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (out_tree->setTo(data.get(), buffer.size(), true) != NO_ERROR) {
70cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return ::testing::AssertionFailure() << "flattened XML is corrupt";
711ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
72cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return ::testing::AssertionSuccess();
73cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
741ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
75cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski protected:
764ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski  std::unique_ptr<test::Context> context_;
771ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski};
781ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
791ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiTEST_F(XmlFlattenerTest, FlattenXmlWithNoCompiledAttributes) {
80fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(
81fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski      <View xmlns:test="http://com.test" attr="hey">
82fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski          <Layout test:hello="hi" />
83fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski          <Layout>Some text\\</Layout>
84fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski      </View>)");
851ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
86cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  android::ResXMLTree tree;
87ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_TRUE(Flatten(doc.get(), &tree));
88fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_NAMESPACE));
891ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
90cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  size_t len;
91fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getNamespacePrefix(&len), StrEq(u"test"));
92fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getNamespaceUri(&len), StrEq(u"http://com.test"));
931ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
94fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
95fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getElementNamespace(&len), IsNull());
96fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getElementName(&len), StrEq(u"View"));
971ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
98fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  ASSERT_THAT(tree.getAttributeCount(), Eq(1u));
99fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getAttributeNamespace(0, &len), IsNull());
100fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getAttributeName(0, &len), StrEq(u"attr"));
1011ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
102fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  const StringPiece16 kAttr(u"attr");
103fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.indexOfAttribute(nullptr, 0, kAttr.data(), kAttr.size()), Eq(0));
1041ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
105fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
106fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getElementNamespace(&len), IsNull());
107fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getElementName(&len), StrEq(u"Layout"));
1081ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
109fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  ASSERT_THAT(tree.getAttributeCount(), Eq(1u));
110fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getAttributeNamespace(0, &len), StrEq(u"http://com.test"));
111fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getAttributeName(0, &len), StrEq(u"hello"));
1121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
113fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
114fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
1151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
116fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getElementNamespace(&len), IsNull());
117fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getElementName(&len), StrEq(u"Layout"));
118fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  ASSERT_THAT(tree.getAttributeCount(), Eq(0u));
1191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
120fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
121fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getText(&len), StrEq(u"Some text\\"));
1221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
123fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
124fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getElementNamespace(&len), IsNull());
125fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getElementName(&len), StrEq(u"Layout"));
1261ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
127fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
128fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getElementNamespace(&len), IsNull());
129fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getElementName(&len), StrEq(u"View"));
1301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
131fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_NAMESPACE));
132fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getNamespacePrefix(&len), StrEq(u"test"));
133fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getNamespaceUri(&len), StrEq(u"http://com.test"));
1341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
135fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_DOCUMENT));
1361ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}
1371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
138a9ff14098b9d938aec86cf58abbdd3c4dc0779ccAlexandria CornwallTEST_F(XmlFlattenerTest, FlattenCompiledXmlAndStripOnlyTools) {
139fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(
140fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski      <View xmlns:tools="http://schemas.android.com/tools"
141fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski          xmlns:foo="http://schemas.android.com/foo"
142fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski          foo:bar="Foo"
143fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski          tools:ignore="MissingTranslation"/>)");
144a9ff14098b9d938aec86cf58abbdd3c4dc0779ccAlexandria Cornwall
145cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  android::ResXMLTree tree;
146ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_TRUE(Flatten(doc.get(), &tree));
147fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_NAMESPACE));
148a9ff14098b9d938aec86cf58abbdd3c4dc0779ccAlexandria Cornwall
149cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  size_t len;
150fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getNamespacePrefix(&len), StrEq(u"foo"));
151fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getNamespaceUri(&len), StrEq(u"http://schemas.android.com/foo"));
152fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
153a9ff14098b9d938aec86cf58abbdd3c4dc0779ccAlexandria Cornwall
154fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.indexOfAttribute("http://schemas.android.com/tools", "ignore"),
155fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski              Eq(android::NAME_NOT_FOUND));
156fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.indexOfAttribute("http://schemas.android.com/foo", "bar"), Ge(0));
157a9ff14098b9d938aec86cf58abbdd3c4dc0779ccAlexandria Cornwall}
158a9ff14098b9d938aec86cf58abbdd3c4dc0779ccAlexandria Cornwall
1591ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiTEST_F(XmlFlattenerTest, AssignSpecialAttributeIndices) {
160fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(
161fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski      <View xmlns:android="http://schemas.android.com/apk/res/android"
162fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski          android:id="@id/id"
163fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski          class="str"
164fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski          style="@id/id"/>)");
1651ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
166cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  android::ResXMLTree tree;
167ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_TRUE(Flatten(doc.get(), &tree));
1681ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
169cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  while (tree.next() != android::ResXMLTree::START_TAG) {
170fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski    ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
171fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski    ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
172cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1731ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
174fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.indexOfClass(), Eq(0));
175fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.indexOfStyle(), Eq(1));
1761ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}
1771ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1784ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski// The device ResXMLParser in libandroidfw differentiates between empty namespace and null
1794ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski// namespace.
1801ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiTEST_F(XmlFlattenerTest, NoNamespaceIsNotTheSameAsEmptyNamespace) {
181fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(<View package="android"/>)");
1821ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
183cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  android::ResXMLTree tree;
184ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_TRUE(Flatten(doc.get(), &tree));
1851ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
186cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  while (tree.next() != android::ResXMLTree::START_TAG) {
187fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski    ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
188fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski    ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
189cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1901ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
191cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  const StringPiece16 kPackage = u"package";
192fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.indexOfAttribute(nullptr, 0, kPackage.data(), kPackage.size()), Ge(0));
1931ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}
1941ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
195e1fda9aec4337deb93ae7675e7c4a96d3172464dAdam LesinskiTEST_F(XmlFlattenerTest, EmptyStringValueInAttributeIsNotNull) {
196fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(<View package=""/>)");
197e1fda9aec4337deb93ae7675e7c4a96d3172464dAdam Lesinski
198cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  android::ResXMLTree tree;
199ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_TRUE(Flatten(doc.get(), &tree));
200e1fda9aec4337deb93ae7675e7c4a96d3172464dAdam Lesinski
201cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  while (tree.next() != android::ResXMLTree::START_TAG) {
202fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski    ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
203fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski    ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
204cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
205e1fda9aec4337deb93ae7675e7c4a96d3172464dAdam Lesinski
206cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  const StringPiece16 kPackage = u"package";
207c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  ssize_t idx = tree.indexOfAttribute(nullptr, 0, kPackage.data(), kPackage.size());
208fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  ASSERT_THAT(idx, Ge(0));
209e1fda9aec4337deb93ae7675e7c4a96d3172464dAdam Lesinski
210cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  size_t len;
211fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getAttributeStringValue(idx, &len), NotNull());
212e1fda9aec4337deb93ae7675e7c4a96d3172464dAdam Lesinski}
213e1fda9aec4337deb93ae7675e7c4a96d3172464dAdam Lesinski
2144ca56978a9aea3f021a54ed9265de10811984d94Adam LesinskiTEST_F(XmlFlattenerTest, FlattenNonStandardPackageId) {
2154ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski  context_->SetCompilationPackage("com.app.test.feature");
2164ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski  context_->SetPackageId(0x80);
2174ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski  context_->SetNameManglerPolicy({"com.app.test.feature"});
2184ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski
219fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"(
2204ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski      <View xmlns:android="http://schemas.android.com/apk/res/android"
2214ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski            xmlns:app="http://schemas.android.com/apk/res-auto"
2224ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski            android:id="@id/foo"
223fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski            app:foo="@id/foo" />)");
2244ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski
2254ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski  XmlReferenceLinker linker;
2264ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski  ASSERT_TRUE(linker.Consume(context_.get(), doc.get()));
2274ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski
2284ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski  // The tree needs a custom DynamicRefTable since it is not using a standard app ID (0x7f).
2294ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski  android::DynamicRefTable dynamic_ref_table;
2304ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski  dynamic_ref_table.addMapping(0x80, 0x80);
2314ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski
2324ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski  android::ResXMLTree tree(&dynamic_ref_table);
2334ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski  ASSERT_TRUE(Flatten(doc.get(), &tree));
2344ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski
2354ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski  while (tree.next() != android::ResXMLTree::START_TAG) {
236fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski    ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
237fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski    ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
2384ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski  }
2394ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski
2404ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski  ssize_t idx;
2414ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski
2424ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski  idx = tree.indexOfAttribute(xml::kSchemaAndroid, "id");
243fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  ASSERT_THAT(idx, Ge(0));
244fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.indexOfID(), Eq(idx));
245fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getAttributeNameResID(idx), Eq(0x010100d0u));
2464ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski
2474ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski  idx = tree.indexOfAttribute(xml::kSchemaAuto, "foo");
248fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  ASSERT_THAT(idx, Ge(0));
249fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getAttributeNameResID(idx), Eq(0x80010000u));
250fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getAttributeDataType(idx), Eq(android::Res_value::TYPE_REFERENCE));
251fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getAttributeData(idx), Eq(int32_t(0x80020000)));
2524ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski}
2534ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski
25448448e8a310e72eb2846ad0f86672ce4f0b47e47Adam LesinskiTEST_F(XmlFlattenerTest, ProcessEscapedStrings) {
25548448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(
256fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski      R"(<element value="\?hello" pattern="\\d{5}" other="&quot;">\\d{5}</element>)");
25748448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski
25848448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski  android::ResXMLTree tree;
25948448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski  ASSERT_TRUE(Flatten(doc.get(), &tree));
26048448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski
26148448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski  while (tree.next() != android::ResXMLTree::START_TAG) {
262fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski    ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
263fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski    ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
26448448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski  }
26548448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski
26648448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski  const StringPiece16 kValue = u"value";
26748448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski  const StringPiece16 kPattern = u"pattern";
268fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  const StringPiece16 kOther = u"other";
26948448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski
27048448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski  size_t len;
27148448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski  ssize_t idx;
27248448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski
27348448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski  idx = tree.indexOfAttribute(nullptr, 0, kValue.data(), kValue.size());
274fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  ASSERT_THAT(idx, Ge(0));
275fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getAttributeStringValue(idx, &len), StrEq(u"?hello"));
27648448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski
27748448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski  idx = tree.indexOfAttribute(nullptr, 0, kPattern.data(), kPattern.size());
278fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  ASSERT_THAT(idx, Ge(0));
279fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getAttributeStringValue(idx, &len), StrEq(u"\\d{5}"));
280fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski
281fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  idx = tree.indexOfAttribute(nullptr, 0, kOther.data(), kOther.size());
282fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  ASSERT_THAT(idx, Ge(0));
283fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getAttributeStringValue(idx, &len), StrEq(u"\""));
284fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski
285fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
286fba0cf2950a91726e475fb180090cc25bcb11a7aAdam Lesinski  EXPECT_THAT(tree.getText(&len), StrEq(u"\\d{5}"));
28748448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski}
28848448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski
2890dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan MitchellTEST_F(XmlFlattenerTest, ProcessQuotes) {
2900dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(
2910dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell      R"(<root>
2920dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell          <item>Regular text</item>
2930dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell          <item>"Text in double quotes"</item>
2940dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell          <item>'Text in single quotes'</item>
2950dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell          <item>Text containing "double quotes"</item>
2960dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell          <item>Text containing 'single quotes'</item>
2970dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell      </root>)");
2980dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
2990dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  size_t len;
3000dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  android::ResXMLTree tree;
3010dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
3020dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  XmlFlattenerOptions options;
3030dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_TRUE(Flatten(doc.get(), &tree, options));
3040dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
3050dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
3060dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
3070dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
3080dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
3090dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getText(&len), StrEq(u"Regular text"));
3100dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
3110dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
3120dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
3130dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
3140dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
3150dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getText(&len), StrEq(u"\"Text in double quotes\""));
3160dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
3170dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
3180dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
3190dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getElementNamespace(&len), IsNull());
3200dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
3210dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
3220dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getText(&len), StrEq(u"'Text in single quotes'"));
3230dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
3240dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
3250dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
3260dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
3270dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
3280dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getText(&len), StrEq(u"Text containing \"double quotes\""));
3290dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
3300dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
3310dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
3320dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
3330dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
3340dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getText(&len), StrEq(u"Text containing 'single quotes'"));
3350dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
3360dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
3370dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
3380dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_DOCUMENT));
3390dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell}
3400dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
3410dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan MitchellTEST_F(XmlFlattenerTest, ProcessWhitepspace) {
3420dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(
3430dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell      R"(<root>
3440dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell          <item>   Compact   Spaces   </item>
3450dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell          <item>
3460dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell                 A
3470dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell          </item>
3480dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell          <item>B   </item>
3490dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell          <item>C </item>
3500dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell          <item> D  </item>
3510dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell          <item>   E</item>
3520dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell          <item> F</item>
3530dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell          <item>  G </item>
3540dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell          <item> H </item>
3550dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell<item>
3560dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan MitchellI
3570dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell</item>
3580dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell<item>
3590dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
3600dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell   J
3610dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
3620dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell</item>
3630dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell          <item>
3640dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell          </item>
3650dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell      </root>)");
3660dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
3670dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  size_t len;
3680dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  android::ResXMLTree tree;
3690dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
3700dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  XmlFlattenerOptions options;
3710dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_TRUE(Flatten(doc.get(), &tree, options));
3720dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
3730dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
3740dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
3750dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
3760dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
3770dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getText(&len), StrEq(u" Compact   Spaces "));
3780dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
3790dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
3800dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
3810dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
3820dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
3830dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getText(&len), StrEq(u" A "));
3840dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
3850dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
3860dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
3870dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
3880dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
3890dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getText(&len), StrEq(u"B "));
3900dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
3910dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
3920dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
3930dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
3940dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
3950dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getText(&len), StrEq(u"C "));
3960dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
3970dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
3980dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
3990dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
4000dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
4010dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getText(&len), StrEq(u" D "));
4020dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
4030dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
4040dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
4050dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
4060dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
4070dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getText(&len), StrEq(u" E"));
4080dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
4090dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
4100dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
4110dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
4120dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
4130dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getText(&len), StrEq(u" F"));
4140dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
4150dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
4160dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
4170dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
4180dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
4190dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getText(&len), StrEq(u" G "));
4200dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
4210dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
4220dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
4230dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
4240dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
4250dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getText(&len), StrEq(u" H "));
4260dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
4270dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
4280dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
4290dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
4300dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
4310dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getText(&len), StrEq(u" I "));
4320dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
4330dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
4340dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
4350dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
4360dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
4370dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getText(&len), StrEq(u" J "));
4380dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
4390dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
4400dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
4410dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
4420dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
4430dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
4440dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
4450dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_DOCUMENT));
4460dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell}
4470dcb20c72742a1de30b4984c4b8996d76cb7a428Ryan Mitchell
448e1094a2e232277a719025aa5c97c492502c34f5bAdam LesinskiTEST_F(XmlFlattenerTest, FlattenRawValueOnlyMakesCompiledValueToo) {
449e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(<element foo="bar" />)");
450e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
451e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  // Raw values are kept when encoding an attribute with no compiled value, regardless of option.
452e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  XmlFlattenerOptions options;
453e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  options.keep_raw_values = false;
454e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
455e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  android::ResXMLTree tree;
456e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  ASSERT_TRUE(Flatten(doc.get(), &tree, options));
457e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
458e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  while (tree.next() != android::ResXMLTree::START_TAG) {
459e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski    ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
460e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski    ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
461e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  }
462e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
463e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  ASSERT_THAT(tree.getAttributeCount(), Eq(1u));
464e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  EXPECT_THAT(tree.getAttributeValueStringID(0), Ge(0));
465e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  EXPECT_THAT(tree.getAttributeDataType(0), Eq(android::Res_value::TYPE_STRING));
466e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  EXPECT_THAT(tree.getAttributeValueStringID(0), Eq(tree.getAttributeData(0)));
467e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski}
468e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
469e1094a2e232277a719025aa5c97c492502c34f5bAdam LesinskiTEST_F(XmlFlattenerTest, FlattenCompiledStringValuePreservesRawValue) {
470e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(<element foo="bar" />)");
471e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  doc->root->attributes[0].compiled_value =
472e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski      util::make_unique<String>(doc->string_pool.MakeRef("bar"));
473e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
474e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  // Raw values are kept when encoding a string anyways.
475e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  XmlFlattenerOptions options;
476e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  options.keep_raw_values = false;
477e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
478e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  android::ResXMLTree tree;
479e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  ASSERT_TRUE(Flatten(doc.get(), &tree, options));
480e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
481e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  while (tree.next() != android::ResXMLTree::START_TAG) {
482e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski    ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
483e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski    ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
484e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  }
485e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
486e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  ASSERT_THAT(tree.getAttributeCount(), Eq(1u));
487e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  EXPECT_THAT(tree.getAttributeValueStringID(0), Ge(0));
488e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  EXPECT_THAT(tree.getAttributeDataType(0), Eq(android::Res_value::TYPE_STRING));
489e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  EXPECT_THAT(tree.getAttributeValueStringID(0), Eq(tree.getAttributeData(0)));
490e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski}
491e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
492e1094a2e232277a719025aa5c97c492502c34f5bAdam LesinskiTEST_F(XmlFlattenerTest, FlattenCompiledValueExcludesRawValueWithKeepRawOptionFalse) {
493e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(<element foo="true" />)");
494e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  doc->root->attributes[0].compiled_value = ResourceUtils::MakeBool(true);
495e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
496e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  XmlFlattenerOptions options;
497e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  options.keep_raw_values = false;
498e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
499e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  android::ResXMLTree tree;
500e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  ASSERT_TRUE(Flatten(doc.get(), &tree, options));
501e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
502e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  while (tree.next() != android::ResXMLTree::START_TAG) {
503e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski    ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
504e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski    ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
505e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  }
506e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
507e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  ASSERT_THAT(tree.getAttributeCount(), Eq(1u));
508e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  EXPECT_THAT(tree.getAttributeValueStringID(0), Eq(-1));
509e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  EXPECT_THAT(tree.getAttributeDataType(0), Eq(android::Res_value::TYPE_INT_BOOLEAN));
510e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski}
511e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
512e1094a2e232277a719025aa5c97c492502c34f5bAdam LesinskiTEST_F(XmlFlattenerTest, FlattenCompiledValueExcludesRawValueWithKeepRawOptionTrue) {
513e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(<element foo="true" />)");
514e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  doc->root->attributes[0].compiled_value = ResourceUtils::MakeBool(true);
515e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
516e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  XmlFlattenerOptions options;
517e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  options.keep_raw_values = true;
518e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
519e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  android::ResXMLTree tree;
520e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  ASSERT_TRUE(Flatten(doc.get(), &tree, options));
521e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
522e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  while (tree.next() != android::ResXMLTree::START_TAG) {
523e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski    ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
524e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski    ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
525e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  }
526e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
527e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  ASSERT_THAT(tree.getAttributeCount(), Eq(1u));
528e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  EXPECT_THAT(tree.getAttributeValueStringID(0), Ge(0));
529e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
530e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  size_t len;
531e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  EXPECT_THAT(tree.getAttributeStringValue(0, &len), StrEq(u"true"));
532e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
533e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  EXPECT_THAT(tree.getAttributeDataType(0), Eq(android::Res_value::TYPE_INT_BOOLEAN));
534e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski}
535e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
536cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski}  // namespace aapt
537