XmlFlattener_test.cpp revision e1094a2e232277a719025aa5c97c492502c34f5b
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
289e1094a2e232277a719025aa5c97c492502c34f5bAdam LesinskiTEST_F(XmlFlattenerTest, FlattenRawValueOnlyMakesCompiledValueToo) {
290e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(<element foo="bar" />)");
291e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
292e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  // Raw values are kept when encoding an attribute with no compiled value, regardless of option.
293e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  XmlFlattenerOptions options;
294e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  options.keep_raw_values = false;
295e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
296e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  android::ResXMLTree tree;
297e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  ASSERT_TRUE(Flatten(doc.get(), &tree, options));
298e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
299e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  while (tree.next() != android::ResXMLTree::START_TAG) {
300e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski    ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
301e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski    ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
302e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  }
303e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
304e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  ASSERT_THAT(tree.getAttributeCount(), Eq(1u));
305e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  EXPECT_THAT(tree.getAttributeValueStringID(0), Ge(0));
306e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  EXPECT_THAT(tree.getAttributeDataType(0), Eq(android::Res_value::TYPE_STRING));
307e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  EXPECT_THAT(tree.getAttributeValueStringID(0), Eq(tree.getAttributeData(0)));
308e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski}
309e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
310e1094a2e232277a719025aa5c97c492502c34f5bAdam LesinskiTEST_F(XmlFlattenerTest, FlattenCompiledStringValuePreservesRawValue) {
311e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(<element foo="bar" />)");
312e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  doc->root->attributes[0].compiled_value =
313e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski      util::make_unique<String>(doc->string_pool.MakeRef("bar"));
314e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
315e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  // Raw values are kept when encoding a string anyways.
316e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  XmlFlattenerOptions options;
317e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  options.keep_raw_values = false;
318e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
319e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  android::ResXMLTree tree;
320e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  ASSERT_TRUE(Flatten(doc.get(), &tree, options));
321e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
322e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  while (tree.next() != android::ResXMLTree::START_TAG) {
323e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski    ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
324e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski    ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
325e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  }
326e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
327e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  ASSERT_THAT(tree.getAttributeCount(), Eq(1u));
328e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  EXPECT_THAT(tree.getAttributeValueStringID(0), Ge(0));
329e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  EXPECT_THAT(tree.getAttributeDataType(0), Eq(android::Res_value::TYPE_STRING));
330e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  EXPECT_THAT(tree.getAttributeValueStringID(0), Eq(tree.getAttributeData(0)));
331e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski}
332e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
333e1094a2e232277a719025aa5c97c492502c34f5bAdam LesinskiTEST_F(XmlFlattenerTest, FlattenCompiledValueExcludesRawValueWithKeepRawOptionFalse) {
334e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(<element foo="true" />)");
335e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  doc->root->attributes[0].compiled_value = ResourceUtils::MakeBool(true);
336e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
337e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  XmlFlattenerOptions options;
338e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  options.keep_raw_values = false;
339e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
340e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  android::ResXMLTree tree;
341e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  ASSERT_TRUE(Flatten(doc.get(), &tree, options));
342e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
343e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  while (tree.next() != android::ResXMLTree::START_TAG) {
344e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski    ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
345e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski    ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
346e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  }
347e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
348e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  ASSERT_THAT(tree.getAttributeCount(), Eq(1u));
349e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  EXPECT_THAT(tree.getAttributeValueStringID(0), Eq(-1));
350e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  EXPECT_THAT(tree.getAttributeDataType(0), Eq(android::Res_value::TYPE_INT_BOOLEAN));
351e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski}
352e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
353e1094a2e232277a719025aa5c97c492502c34f5bAdam LesinskiTEST_F(XmlFlattenerTest, FlattenCompiledValueExcludesRawValueWithKeepRawOptionTrue) {
354e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(<element foo="true" />)");
355e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  doc->root->attributes[0].compiled_value = ResourceUtils::MakeBool(true);
356e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
357e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  XmlFlattenerOptions options;
358e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  options.keep_raw_values = true;
359e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
360e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  android::ResXMLTree tree;
361e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  ASSERT_TRUE(Flatten(doc.get(), &tree, options));
362e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
363e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  while (tree.next() != android::ResXMLTree::START_TAG) {
364e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski    ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
365e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski    ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
366e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  }
367e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
368e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  ASSERT_THAT(tree.getAttributeCount(), Eq(1u));
369e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  EXPECT_THAT(tree.getAttributeValueStringID(0), Ge(0));
370e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
371e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  size_t len;
372e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  EXPECT_THAT(tree.getAttributeStringValue(0, &len), StrEq(u"true"));
373e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
374e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  EXPECT_THAT(tree.getAttributeDataType(0), Eq(android::Res_value::TYPE_INT_BOOLEAN));
375e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski}
376e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
377cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski}  // namespace aapt
378