XmlFlattener_test.cpp revision f34b6f4f2b969b47a3f371eb9549e92ef1680d91
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
171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "flatten/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
26d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinskiusing android::StringPiece16;
27d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski
281ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskinamespace aapt {
291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskiclass XmlFlattenerTest : public ::testing::Test {
31cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public:
32cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  void SetUp() override {
33f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    context_ = test::ContextBuilder()
34f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                   .SetCompilationPackage("com.app.test")
35f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                   .SetNameManglerPolicy(NameManglerPolicy{"com.app.test"})
36f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                   .AddSymbolSource(
37f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                       test::StaticSymbolSourceBuilder()
38f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                           .AddSymbol("android:attr/id", ResourceId(0x010100d0),
39f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                      test::AttributeBuilder().Build())
40f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                           .AddSymbol("com.app.test:id/id", ResourceId(0x7f020000))
41f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                           .AddPublicSymbol("android:attr/paddingStart", ResourceId(0x010103b3),
42f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                            test::AttributeBuilder().Build())
43f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                           .AddPublicSymbol("android:attr/colorAccent", ResourceId(0x01010435),
44f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                            test::AttributeBuilder().Build())
45f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                           .Build())
46f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                   .Build();
47cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
48cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
49ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ::testing::AssertionResult Flatten(xml::XmlResource* doc,
50ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                     android::ResXMLTree* out_tree,
51cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski                                     const XmlFlattenerOptions& options = {}) {
52cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    using namespace android;  // For NO_ERROR on windows because it is a macro.
53cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
54cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    BigBuffer buffer(1024);
55cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    XmlFlattener flattener(&buffer, options);
56ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!flattener.Consume(context_.get(), doc)) {
57cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return ::testing::AssertionFailure() << "failed to flatten XML Tree";
581ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
60ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::unique_ptr<uint8_t[]> data = util::Copy(buffer);
61ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (out_tree->setTo(data.get(), buffer.size(), true) != NO_ERROR) {
62cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return ::testing::AssertionFailure() << "flattened XML is corrupt";
631ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
64cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return ::testing::AssertionSuccess();
65cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
661ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
67cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski protected:
68ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<IAaptContext> context_;
691ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski};
701ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
711ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiTEST_F(XmlFlattenerTest, FlattenXmlWithNoCompiledAttributes) {
72ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"EOF(
731ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            <View xmlns:test="http://com.test"
741ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                  attr="hey">
751ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski              <Layout test:hello="hi" />
76ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski              <Layout>Some text\\</Layout>
771ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            </View>)EOF");
781ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
79cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  android::ResXMLTree tree;
80ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_TRUE(Flatten(doc.get(), &tree));
811ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
82cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_EQ(tree.next(), android::ResXMLTree::START_NAMESPACE);
831ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
84cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  size_t len;
85ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const char16_t* namespace_prefix = tree.getNamespacePrefix(&len);
86ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_EQ(StringPiece16(namespace_prefix, len), u"test");
871ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
88ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const char16_t* namespace_uri = tree.getNamespaceUri(&len);
89ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_EQ(StringPiece16(namespace_uri, len), u"http://com.test");
901ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
91cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_EQ(tree.next(), android::ResXMLTree::START_TAG);
921ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
93cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_EQ(tree.getElementNamespace(&len), nullptr);
94ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const char16_t* tag_name = tree.getElementName(&len);
95ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_EQ(StringPiece16(tag_name, len), u"View");
961ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
97cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_EQ(1u, tree.getAttributeCount());
98cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_EQ(tree.getAttributeNamespace(0, &len), nullptr);
99ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const char16_t* attr_name = tree.getAttributeName(0, &len);
100ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_EQ(StringPiece16(attr_name, len), u"attr");
1011ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
102cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  EXPECT_EQ(0, tree.indexOfAttribute(nullptr, 0, u"attr",
103cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski                                     StringPiece16(u"attr").size()));
1041ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
105cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_EQ(tree.next(), android::ResXMLTree::START_TAG);
1061ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
107cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_EQ(tree.getElementNamespace(&len), nullptr);
108ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  tag_name = tree.getElementName(&len);
109ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_EQ(StringPiece16(tag_name, len), u"Layout");
1101ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
111cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_EQ(1u, tree.getAttributeCount());
112ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const char16_t* attr_namespace = tree.getAttributeNamespace(0, &len);
113ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_EQ(StringPiece16(attr_namespace, len), u"http://com.test");
1141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
115ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  attr_name = tree.getAttributeName(0, &len);
116ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_EQ(StringPiece16(attr_name, len), u"hello");
1171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
118cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_EQ(tree.next(), android::ResXMLTree::END_TAG);
119cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_EQ(tree.next(), android::ResXMLTree::START_TAG);
1201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
121cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_EQ(tree.getElementNamespace(&len), nullptr);
122ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  tag_name = tree.getElementName(&len);
123ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_EQ(StringPiece16(tag_name, len), u"Layout");
124cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_EQ(0u, tree.getAttributeCount());
1251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
126cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_EQ(tree.next(), android::ResXMLTree::TEXT);
127cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  const char16_t* text = tree.getText(&len);
128ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  EXPECT_EQ(StringPiece16(text, len), u"Some text\\");
1291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
130cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_EQ(tree.next(), android::ResXMLTree::END_TAG);
131cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_EQ(tree.getElementNamespace(&len), nullptr);
132ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  tag_name = tree.getElementName(&len);
133ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_EQ(StringPiece16(tag_name, len), u"Layout");
1341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
135cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_EQ(tree.next(), android::ResXMLTree::END_TAG);
136cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_EQ(tree.getElementNamespace(&len), nullptr);
137ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  tag_name = tree.getElementName(&len);
138ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_EQ(StringPiece16(tag_name, len), u"View");
1391ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
140cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_EQ(tree.next(), android::ResXMLTree::END_NAMESPACE);
141ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  namespace_prefix = tree.getNamespacePrefix(&len);
142ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_EQ(StringPiece16(namespace_prefix, len), u"test");
1431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
144ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  namespace_uri = tree.getNamespaceUri(&len);
145ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_EQ(StringPiece16(namespace_uri, len), u"http://com.test");
1461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
147cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_EQ(tree.next(), android::ResXMLTree::END_DOCUMENT);
1481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}
1491ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1501ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiTEST_F(XmlFlattenerTest, FlattenCompiledXmlAndStripSdk21) {
151ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"EOF(
1521ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            <View xmlns:android="http://schemas.android.com/apk/res/android"
1531ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                android:paddingStart="1dp"
1541ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                android:colorAccent="#ffffff"/>)EOF");
1551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
156cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  XmlReferenceLinker linker;
157ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_TRUE(linker.Consume(context_.get(), doc.get()));
158ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_TRUE(linker.sdk_levels().count(17) == 1);
159ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_TRUE(linker.sdk_levels().count(21) == 1);
1601ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
161cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  android::ResXMLTree tree;
162cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  XmlFlattenerOptions options;
163ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  options.max_sdk_level = 17;
164ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_TRUE(Flatten(doc.get(), &tree, options));
1651ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
166cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  while (tree.next() != android::ResXMLTree::START_TAG) {
167cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    ASSERT_NE(tree.getEventType(), android::ResXMLTree::BAD_DOCUMENT);
168cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    ASSERT_NE(tree.getEventType(), android::ResXMLTree::END_DOCUMENT);
169cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1701ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
171cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_EQ(1u, tree.getAttributeCount());
172cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  EXPECT_EQ(uint32_t(0x010103b3), tree.getAttributeNameResID(0));
1731ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}
1741ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
175a9ff14098b9d938aec86cf58abbdd3c4dc0779ccAlexandria CornwallTEST_F(XmlFlattenerTest, FlattenCompiledXmlAndStripOnlyTools) {
176ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"EOF(
177a9ff14098b9d938aec86cf58abbdd3c4dc0779ccAlexandria Cornwall            <View xmlns:tools="http://schemas.android.com/tools"
178a9ff14098b9d938aec86cf58abbdd3c4dc0779ccAlexandria Cornwall                xmlns:foo="http://schemas.android.com/foo"
179a9ff14098b9d938aec86cf58abbdd3c4dc0779ccAlexandria Cornwall                foo:bar="Foo"
180a9ff14098b9d938aec86cf58abbdd3c4dc0779ccAlexandria Cornwall                tools:ignore="MissingTranslation"/>)EOF");
181a9ff14098b9d938aec86cf58abbdd3c4dc0779ccAlexandria Cornwall
182cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  android::ResXMLTree tree;
183ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_TRUE(Flatten(doc.get(), &tree));
184a9ff14098b9d938aec86cf58abbdd3c4dc0779ccAlexandria Cornwall
185cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_EQ(tree.next(), android::ResXMLTree::START_NAMESPACE);
186a9ff14098b9d938aec86cf58abbdd3c4dc0779ccAlexandria Cornwall
187cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  size_t len;
188ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const char16_t* namespace_prefix = tree.getNamespacePrefix(&len);
189ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_EQ(StringPiece16(namespace_prefix, len), u"foo");
190a9ff14098b9d938aec86cf58abbdd3c4dc0779ccAlexandria Cornwall
191ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const char16_t* namespace_uri = tree.getNamespaceUri(&len);
192ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_EQ(StringPiece16(namespace_uri, len),
193cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            u"http://schemas.android.com/foo");
194a9ff14098b9d938aec86cf58abbdd3c4dc0779ccAlexandria Cornwall
195cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_EQ(tree.next(), android::ResXMLTree::START_TAG);
196a9ff14098b9d938aec86cf58abbdd3c4dc0779ccAlexandria Cornwall
197cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  EXPECT_EQ(tree.indexOfAttribute("http://schemas.android.com/tools", "ignore"),
198a9ff14098b9d938aec86cf58abbdd3c4dc0779ccAlexandria Cornwall            android::NAME_NOT_FOUND);
199cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  EXPECT_GE(tree.indexOfAttribute("http://schemas.android.com/foo", "bar"), 0);
200a9ff14098b9d938aec86cf58abbdd3c4dc0779ccAlexandria Cornwall}
201a9ff14098b9d938aec86cf58abbdd3c4dc0779ccAlexandria Cornwall
2021ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiTEST_F(XmlFlattenerTest, AssignSpecialAttributeIndices) {
203ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"EOF(
2041ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            <View xmlns:android="http://schemas.android.com/apk/res/android"
2051ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                  android:id="@id/id"
2061ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                  class="str"
2071ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                  style="@id/id"/>)EOF");
2081ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
209cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  android::ResXMLTree tree;
210ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_TRUE(Flatten(doc.get(), &tree));
2111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
212cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  while (tree.next() != android::ResXMLTree::START_TAG) {
213cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    ASSERT_NE(tree.getEventType(), android::ResXMLTree::BAD_DOCUMENT);
214cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    ASSERT_NE(tree.getEventType(), android::ResXMLTree::END_DOCUMENT);
215cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
2161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
217cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  EXPECT_EQ(tree.indexOfClass(), 0);
218cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  EXPECT_EQ(tree.indexOfStyle(), 1);
2191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}
2201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
2211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski/*
222cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * The device ResXMLParser in libandroidfw differentiates between empty
223cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * namespace and null
2241ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * namespace.
2251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski */
2261ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiTEST_F(XmlFlattenerTest, NoNamespaceIsNotTheSameAsEmptyNamespace) {
227cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  std::unique_ptr<xml::XmlResource> doc =
228ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      test::BuildXmlDom("<View package=\"android\"/>");
2291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
230cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  android::ResXMLTree tree;
231ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_TRUE(Flatten(doc.get(), &tree));
2321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
233cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  while (tree.next() != android::ResXMLTree::START_TAG) {
234cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    ASSERT_NE(tree.getEventType(), android::ResXMLTree::BAD_DOCUMENT);
235cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    ASSERT_NE(tree.getEventType(), android::ResXMLTree::END_DOCUMENT);
236cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
2371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
238cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  const StringPiece16 kPackage = u"package";
239cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  EXPECT_GE(tree.indexOfAttribute(nullptr, 0, kPackage.data(), kPackage.size()),
240cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            0);
2411ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}
2421ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
243e1fda9aec4337deb93ae7675e7c4a96d3172464dAdam LesinskiTEST_F(XmlFlattenerTest, EmptyStringValueInAttributeIsNotNull) {
244cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  std::unique_ptr<xml::XmlResource> doc =
245ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      test::BuildXmlDom("<View package=\"\"/>");
246e1fda9aec4337deb93ae7675e7c4a96d3172464dAdam Lesinski
247cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  android::ResXMLTree tree;
248ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_TRUE(Flatten(doc.get(), &tree));
249e1fda9aec4337deb93ae7675e7c4a96d3172464dAdam Lesinski
250cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  while (tree.next() != android::ResXMLTree::START_TAG) {
251cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    ASSERT_NE(tree.getEventType(), android::ResXMLTree::BAD_DOCUMENT);
252cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    ASSERT_NE(tree.getEventType(), android::ResXMLTree::END_DOCUMENT);
253cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
254e1fda9aec4337deb93ae7675e7c4a96d3172464dAdam Lesinski
255cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  const StringPiece16 kPackage = u"package";
256cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ssize_t idx =
257cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      tree.indexOfAttribute(nullptr, 0, kPackage.data(), kPackage.size());
258cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ASSERT_GE(idx, 0);
259e1fda9aec4337deb93ae7675e7c4a96d3172464dAdam Lesinski
260cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  size_t len;
261cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  EXPECT_NE(nullptr, tree.getAttributeStringValue(idx, &len));
262e1fda9aec4337deb93ae7675e7c4a96d3172464dAdam Lesinski}
263e1fda9aec4337deb93ae7675e7c4a96d3172464dAdam Lesinski
264cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski}  // namespace aapt
265