blob: 25786b1659e7dc3b232fb539835b53359b1472c0 [file] [log] [blame]
Adam Lesinski1ab598f2015-08-14 14:26:04 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Adam Lesinski46708052017-09-29 14:49:15 -070017#include "format/binary/XmlFlattener.h"
Adam Lesinskice5e56e2016-10-21 17:56:45 -070018
19#include "androidfw/ResourceTypes.h"
20
Adam Lesinski1ab598f2015-08-14 14:26:04 -070021#include "link/Linkers.h"
Adam Lesinskid0f116b2016-07-08 15:00:32 -070022#include "test/Test.h"
Adam Lesinski467f1712015-11-16 17:35:44 -080023#include "util/BigBuffer.h"
24#include "util/Util.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070025
Adam Lesinskifba0cf22017-06-29 17:53:36 -070026using ::aapt::test::StrEq;
27using ::android::StringPiece16;
28using ::testing::Eq;
29using ::testing::Ge;
30using ::testing::IsNull;
31using ::testing::Ne;
32using ::testing::NotNull;
Adam Lesinskid5083f62017-01-16 15:07:21 -080033
Adam Lesinski1ab598f2015-08-14 14:26:04 -070034namespace aapt {
35
36class XmlFlattenerTest : public ::testing::Test {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070037 public:
38 void SetUp() override {
Adam Lesinskif34b6f42017-03-03 16:33:26 -080039 context_ = test::ContextBuilder()
40 .SetCompilationPackage("com.app.test")
41 .SetNameManglerPolicy(NameManglerPolicy{"com.app.test"})
42 .AddSymbolSource(
43 test::StaticSymbolSourceBuilder()
Adam Lesinski4ca56972017-04-26 21:49:53 -070044 .AddPublicSymbol("android:attr/id", ResourceId(0x010100d0),
45 test::AttributeBuilder().Build())
Adam Lesinskif34b6f42017-03-03 16:33:26 -080046 .AddSymbol("com.app.test:id/id", ResourceId(0x7f020000))
47 .AddPublicSymbol("android:attr/paddingStart", ResourceId(0x010103b3),
48 test::AttributeBuilder().Build())
49 .AddPublicSymbol("android:attr/colorAccent", ResourceId(0x01010435),
50 test::AttributeBuilder().Build())
Adam Lesinski4ca56972017-04-26 21:49:53 -070051 .AddSymbol("com.app.test.feature:id/foo", ResourceId(0x80020000))
52 .AddSymbol("com.app.test.feature:attr/foo", ResourceId(0x80010000),
53 test::AttributeBuilder().Build())
Adam Lesinskif34b6f42017-03-03 16:33:26 -080054 .Build())
55 .Build();
Adam Lesinskicacb28f2016-10-19 12:18:14 -070056 }
57
Adam Lesinski46708052017-09-29 14:49:15 -070058 ::testing::AssertionResult Flatten(xml::XmlResource* doc, android::ResXMLTree* out_tree,
Adam Lesinskicacb28f2016-10-19 12:18:14 -070059 const XmlFlattenerOptions& options = {}) {
60 using namespace android; // For NO_ERROR on windows because it is a macro.
61
62 BigBuffer buffer(1024);
63 XmlFlattener flattener(&buffer, options);
Adam Lesinskice5e56e2016-10-21 17:56:45 -070064 if (!flattener.Consume(context_.get(), doc)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070065 return ::testing::AssertionFailure() << "failed to flatten XML Tree";
Adam Lesinski1ab598f2015-08-14 14:26:04 -070066 }
67
Adam Lesinskice5e56e2016-10-21 17:56:45 -070068 std::unique_ptr<uint8_t[]> data = util::Copy(buffer);
69 if (out_tree->setTo(data.get(), buffer.size(), true) != NO_ERROR) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070070 return ::testing::AssertionFailure() << "flattened XML is corrupt";
Adam Lesinski1ab598f2015-08-14 14:26:04 -070071 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -070072 return ::testing::AssertionSuccess();
73 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -070074
Adam Lesinskicacb28f2016-10-19 12:18:14 -070075 protected:
Adam Lesinski4ca56972017-04-26 21:49:53 -070076 std::unique_ptr<test::Context> context_;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070077};
78
79TEST_F(XmlFlattenerTest, FlattenXmlWithNoCompiledAttributes) {
Adam Lesinskifba0cf22017-06-29 17:53:36 -070080 std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(
81 <View xmlns:test="http://com.test" attr="hey">
82 <Layout test:hello="hi" />
83 <Layout>Some text\\</Layout>
84 </View>)");
Adam Lesinski1ab598f2015-08-14 14:26:04 -070085
Adam Lesinskicacb28f2016-10-19 12:18:14 -070086 android::ResXMLTree tree;
Adam Lesinskice5e56e2016-10-21 17:56:45 -070087 ASSERT_TRUE(Flatten(doc.get(), &tree));
Adam Lesinskifba0cf22017-06-29 17:53:36 -070088 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_NAMESPACE));
Adam Lesinski1ab598f2015-08-14 14:26:04 -070089
Adam Lesinskicacb28f2016-10-19 12:18:14 -070090 size_t len;
Adam Lesinskifba0cf22017-06-29 17:53:36 -070091 EXPECT_THAT(tree.getNamespacePrefix(&len), StrEq(u"test"));
92 EXPECT_THAT(tree.getNamespaceUri(&len), StrEq(u"http://com.test"));
Adam Lesinski1ab598f2015-08-14 14:26:04 -070093
Adam Lesinskifba0cf22017-06-29 17:53:36 -070094 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
95 EXPECT_THAT(tree.getElementNamespace(&len), IsNull());
96 EXPECT_THAT(tree.getElementName(&len), StrEq(u"View"));
Adam Lesinski1ab598f2015-08-14 14:26:04 -070097
Adam Lesinskifba0cf22017-06-29 17:53:36 -070098 ASSERT_THAT(tree.getAttributeCount(), Eq(1u));
99 EXPECT_THAT(tree.getAttributeNamespace(0, &len), IsNull());
100 EXPECT_THAT(tree.getAttributeName(0, &len), StrEq(u"attr"));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700101
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700102 const StringPiece16 kAttr(u"attr");
103 EXPECT_THAT(tree.indexOfAttribute(nullptr, 0, kAttr.data(), kAttr.size()), Eq(0));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700104
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700105 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
106 EXPECT_THAT(tree.getElementNamespace(&len), IsNull());
107 EXPECT_THAT(tree.getElementName(&len), StrEq(u"Layout"));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700108
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700109 ASSERT_THAT(tree.getAttributeCount(), Eq(1u));
110 EXPECT_THAT(tree.getAttributeNamespace(0, &len), StrEq(u"http://com.test"));
111 EXPECT_THAT(tree.getAttributeName(0, &len), StrEq(u"hello"));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700112
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700113 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
114 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700115
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700116 EXPECT_THAT(tree.getElementNamespace(&len), IsNull());
117 EXPECT_THAT(tree.getElementName(&len), StrEq(u"Layout"));
118 ASSERT_THAT(tree.getAttributeCount(), Eq(0u));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700119
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700120 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
121 EXPECT_THAT(tree.getText(&len), StrEq(u"Some text\\"));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700122
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700123 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
124 EXPECT_THAT(tree.getElementNamespace(&len), IsNull());
125 EXPECT_THAT(tree.getElementName(&len), StrEq(u"Layout"));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700126
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700127 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
128 EXPECT_THAT(tree.getElementNamespace(&len), IsNull());
129 EXPECT_THAT(tree.getElementName(&len), StrEq(u"View"));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700130
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700131 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_NAMESPACE));
132 EXPECT_THAT(tree.getNamespacePrefix(&len), StrEq(u"test"));
133 EXPECT_THAT(tree.getNamespaceUri(&len), StrEq(u"http://com.test"));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700134
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700135 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_DOCUMENT));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700136}
137
Alexandria Cornwalla9ff1402016-08-03 09:44:10 -0700138TEST_F(XmlFlattenerTest, FlattenCompiledXmlAndStripOnlyTools) {
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700139 std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(
140 <View xmlns:tools="http://schemas.android.com/tools"
141 xmlns:foo="http://schemas.android.com/foo"
142 foo:bar="Foo"
143 tools:ignore="MissingTranslation"/>)");
Alexandria Cornwalla9ff1402016-08-03 09:44:10 -0700144
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700145 android::ResXMLTree tree;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700146 ASSERT_TRUE(Flatten(doc.get(), &tree));
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700147 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_NAMESPACE));
Alexandria Cornwalla9ff1402016-08-03 09:44:10 -0700148
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700149 size_t len;
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700150 EXPECT_THAT(tree.getNamespacePrefix(&len), StrEq(u"foo"));
151 EXPECT_THAT(tree.getNamespaceUri(&len), StrEq(u"http://schemas.android.com/foo"));
152 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
Alexandria Cornwalla9ff1402016-08-03 09:44:10 -0700153
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700154 EXPECT_THAT(tree.indexOfAttribute("http://schemas.android.com/tools", "ignore"),
155 Eq(android::NAME_NOT_FOUND));
156 EXPECT_THAT(tree.indexOfAttribute("http://schemas.android.com/foo", "bar"), Ge(0));
Alexandria Cornwalla9ff1402016-08-03 09:44:10 -0700157}
158
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700159TEST_F(XmlFlattenerTest, AssignSpecialAttributeIndices) {
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700160 std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(
161 <View xmlns:android="http://schemas.android.com/apk/res/android"
162 android:id="@id/id"
163 class="str"
164 style="@id/id"/>)");
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700165
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700166 android::ResXMLTree tree;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700167 ASSERT_TRUE(Flatten(doc.get(), &tree));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700168
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700169 while (tree.next() != android::ResXMLTree::START_TAG) {
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700170 ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
171 ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700172 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700173
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700174 EXPECT_THAT(tree.indexOfClass(), Eq(0));
175 EXPECT_THAT(tree.indexOfStyle(), Eq(1));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700176}
177
Adam Lesinski4ca56972017-04-26 21:49:53 -0700178// The device ResXMLParser in libandroidfw differentiates between empty namespace and null
179// namespace.
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700180TEST_F(XmlFlattenerTest, NoNamespaceIsNotTheSameAsEmptyNamespace) {
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700181 std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(<View package="android"/>)");
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700182
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700183 android::ResXMLTree tree;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700184 ASSERT_TRUE(Flatten(doc.get(), &tree));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700185
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700186 while (tree.next() != android::ResXMLTree::START_TAG) {
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700187 ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
188 ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700189 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700190
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700191 const StringPiece16 kPackage = u"package";
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700192 EXPECT_THAT(tree.indexOfAttribute(nullptr, 0, kPackage.data(), kPackage.size()), Ge(0));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700193}
194
Adam Lesinskie1fda9a2016-07-01 14:51:51 -0700195TEST_F(XmlFlattenerTest, EmptyStringValueInAttributeIsNotNull) {
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700196 std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(<View package=""/>)");
Adam Lesinskie1fda9a2016-07-01 14:51:51 -0700197
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700198 android::ResXMLTree tree;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700199 ASSERT_TRUE(Flatten(doc.get(), &tree));
Adam Lesinskie1fda9a2016-07-01 14:51:51 -0700200
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700201 while (tree.next() != android::ResXMLTree::START_TAG) {
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700202 ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
203 ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700204 }
Adam Lesinskie1fda9a2016-07-01 14:51:51 -0700205
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700206 const StringPiece16 kPackage = u"package";
Adam Lesinskic744ae82017-05-17 19:28:38 -0700207 ssize_t idx = tree.indexOfAttribute(nullptr, 0, kPackage.data(), kPackage.size());
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700208 ASSERT_THAT(idx, Ge(0));
Adam Lesinskie1fda9a2016-07-01 14:51:51 -0700209
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700210 size_t len;
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700211 EXPECT_THAT(tree.getAttributeStringValue(idx, &len), NotNull());
Adam Lesinskie1fda9a2016-07-01 14:51:51 -0700212}
213
Adam Lesinski4ca56972017-04-26 21:49:53 -0700214TEST_F(XmlFlattenerTest, FlattenNonStandardPackageId) {
215 context_->SetCompilationPackage("com.app.test.feature");
216 context_->SetPackageId(0x80);
217 context_->SetNameManglerPolicy({"com.app.test.feature"});
218
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700219 std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"(
Adam Lesinski4ca56972017-04-26 21:49:53 -0700220 <View xmlns:android="http://schemas.android.com/apk/res/android"
221 xmlns:app="http://schemas.android.com/apk/res-auto"
222 android:id="@id/foo"
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700223 app:foo="@id/foo" />)");
Adam Lesinski4ca56972017-04-26 21:49:53 -0700224
225 XmlReferenceLinker linker;
226 ASSERT_TRUE(linker.Consume(context_.get(), doc.get()));
227
228 // The tree needs a custom DynamicRefTable since it is not using a standard app ID (0x7f).
229 android::DynamicRefTable dynamic_ref_table;
230 dynamic_ref_table.addMapping(0x80, 0x80);
231
232 android::ResXMLTree tree(&dynamic_ref_table);
233 ASSERT_TRUE(Flatten(doc.get(), &tree));
234
235 while (tree.next() != android::ResXMLTree::START_TAG) {
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700236 ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
237 ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
Adam Lesinski4ca56972017-04-26 21:49:53 -0700238 }
239
240 ssize_t idx;
241
242 idx = tree.indexOfAttribute(xml::kSchemaAndroid, "id");
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700243 ASSERT_THAT(idx, Ge(0));
244 EXPECT_THAT(tree.indexOfID(), Eq(idx));
245 EXPECT_THAT(tree.getAttributeNameResID(idx), Eq(0x010100d0u));
Adam Lesinski4ca56972017-04-26 21:49:53 -0700246
247 idx = tree.indexOfAttribute(xml::kSchemaAuto, "foo");
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700248 ASSERT_THAT(idx, Ge(0));
249 EXPECT_THAT(tree.getAttributeNameResID(idx), Eq(0x80010000u));
250 EXPECT_THAT(tree.getAttributeDataType(idx), Eq(android::Res_value::TYPE_REFERENCE));
251 EXPECT_THAT(tree.getAttributeData(idx), Eq(int32_t(0x80020000)));
Adam Lesinski4ca56972017-04-26 21:49:53 -0700252}
253
Adam Lesinski48448e82017-04-26 15:13:52 -0700254TEST_F(XmlFlattenerTest, ProcessEscapedStrings) {
255 std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700256 R"(<element value="\?hello" pattern="\\d{5}" other="&quot;">\\d{5}</element>)");
Adam Lesinski48448e82017-04-26 15:13:52 -0700257
258 android::ResXMLTree tree;
259 ASSERT_TRUE(Flatten(doc.get(), &tree));
260
261 while (tree.next() != android::ResXMLTree::START_TAG) {
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700262 ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
263 ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
Adam Lesinski48448e82017-04-26 15:13:52 -0700264 }
265
266 const StringPiece16 kValue = u"value";
267 const StringPiece16 kPattern = u"pattern";
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700268 const StringPiece16 kOther = u"other";
Adam Lesinski48448e82017-04-26 15:13:52 -0700269
270 size_t len;
271 ssize_t idx;
Adam Lesinski48448e82017-04-26 15:13:52 -0700272
273 idx = tree.indexOfAttribute(nullptr, 0, kValue.data(), kValue.size());
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700274 ASSERT_THAT(idx, Ge(0));
275 EXPECT_THAT(tree.getAttributeStringValue(idx, &len), StrEq(u"?hello"));
Adam Lesinski48448e82017-04-26 15:13:52 -0700276
277 idx = tree.indexOfAttribute(nullptr, 0, kPattern.data(), kPattern.size());
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700278 ASSERT_THAT(idx, Ge(0));
279 EXPECT_THAT(tree.getAttributeStringValue(idx, &len), StrEq(u"\\d{5}"));
Adam Lesinski48448e82017-04-26 15:13:52 -0700280
Adam Lesinskifba0cf22017-06-29 17:53:36 -0700281 idx = tree.indexOfAttribute(nullptr, 0, kOther.data(), kOther.size());
282 ASSERT_THAT(idx, Ge(0));
283 EXPECT_THAT(tree.getAttributeStringValue(idx, &len), StrEq(u"\""));
284
285 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
286 EXPECT_THAT(tree.getText(&len), StrEq(u"\\d{5}"));
Adam Lesinski48448e82017-04-26 15:13:52 -0700287}
288
Ryan Mitchell0dcb20c2018-04-27 14:53:04 -0700289TEST_F(XmlFlattenerTest, ProcessQuotes) {
290 std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(
291 R"(<root>
292 <item>Regular text</item>
293 <item>"Text in double quotes"</item>
294 <item>'Text in single quotes'</item>
295 <item>Text containing "double quotes"</item>
296 <item>Text containing 'single quotes'</item>
297 </root>)");
298
299 size_t len;
300 android::ResXMLTree tree;
301
302 XmlFlattenerOptions options;
303 ASSERT_TRUE(Flatten(doc.get(), &tree, options));
304
305 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
306 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
307 EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
308 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
309 EXPECT_THAT(tree.getText(&len), StrEq(u"Regular text"));
310 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
311
312 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
313 EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
314 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
315 EXPECT_THAT(tree.getText(&len), StrEq(u"\"Text in double quotes\""));
316 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
317
318 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
319 EXPECT_THAT(tree.getElementNamespace(&len), IsNull());
320 EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
321 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
322 EXPECT_THAT(tree.getText(&len), StrEq(u"'Text in single quotes'"));
323 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
324
325 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
326 EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
327 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
328 EXPECT_THAT(tree.getText(&len), StrEq(u"Text containing \"double quotes\""));
329 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
330
331 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
332 EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
333 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
334 EXPECT_THAT(tree.getText(&len), StrEq(u"Text containing 'single quotes'"));
335 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
336 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
337
338 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_DOCUMENT));
339}
340
341TEST_F(XmlFlattenerTest, ProcessWhitepspace) {
342 std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(
343 R"(<root>
344 <item> Compact Spaces </item>
345 <item>
346 A
347 </item>
348 <item>B </item>
349 <item>C </item>
350 <item> D </item>
351 <item> E</item>
352 <item> F</item>
353 <item> G </item>
354 <item> H </item>
355<item>
356I
357</item>
358<item>
359
360 J
361
362</item>
363 <item>
364 </item>
365 </root>)");
366
367 size_t len;
368 android::ResXMLTree tree;
369
370 XmlFlattenerOptions options;
371 ASSERT_TRUE(Flatten(doc.get(), &tree, options));
372
373 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
374 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
375 EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
376 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
377 EXPECT_THAT(tree.getText(&len), StrEq(u" Compact Spaces "));
378 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
379
380 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
381 EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
382 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
383 EXPECT_THAT(tree.getText(&len), StrEq(u" A "));
384 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
385
386 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
387 EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
388 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
389 EXPECT_THAT(tree.getText(&len), StrEq(u"B "));
390 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
391
392 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
393 EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
394 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
395 EXPECT_THAT(tree.getText(&len), StrEq(u"C "));
396 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
397
398 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
399 EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
400 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
401 EXPECT_THAT(tree.getText(&len), StrEq(u" D "));
402 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
403
404 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
405 EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
406 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
407 EXPECT_THAT(tree.getText(&len), StrEq(u" E"));
408 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
409
410 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
411 EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
412 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
413 EXPECT_THAT(tree.getText(&len), StrEq(u" F"));
414 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
415
416 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
417 EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
418 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
419 EXPECT_THAT(tree.getText(&len), StrEq(u" G "));
420 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
421
422 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
423 EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
424 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
425 EXPECT_THAT(tree.getText(&len), StrEq(u" H "));
426 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
427
428 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
429 EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
430 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
431 EXPECT_THAT(tree.getText(&len), StrEq(u" I "));
432 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
433
434 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
435 EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
436 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
437 EXPECT_THAT(tree.getText(&len), StrEq(u" J "));
438 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
439
440 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
441 EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
442 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
443 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
444
445 ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_DOCUMENT));
446}
447
Adam Lesinskie1094a22018-02-22 17:27:17 -0800448TEST_F(XmlFlattenerTest, FlattenRawValueOnlyMakesCompiledValueToo) {
449 std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(<element foo="bar" />)");
450
451 // Raw values are kept when encoding an attribute with no compiled value, regardless of option.
452 XmlFlattenerOptions options;
453 options.keep_raw_values = false;
454
455 android::ResXMLTree tree;
456 ASSERT_TRUE(Flatten(doc.get(), &tree, options));
457
458 while (tree.next() != android::ResXMLTree::START_TAG) {
459 ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
460 ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
461 }
462
463 ASSERT_THAT(tree.getAttributeCount(), Eq(1u));
464 EXPECT_THAT(tree.getAttributeValueStringID(0), Ge(0));
465 EXPECT_THAT(tree.getAttributeDataType(0), Eq(android::Res_value::TYPE_STRING));
466 EXPECT_THAT(tree.getAttributeValueStringID(0), Eq(tree.getAttributeData(0)));
467}
468
469TEST_F(XmlFlattenerTest, FlattenCompiledStringValuePreservesRawValue) {
470 std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(<element foo="bar" />)");
471 doc->root->attributes[0].compiled_value =
472 util::make_unique<String>(doc->string_pool.MakeRef("bar"));
473
474 // Raw values are kept when encoding a string anyways.
475 XmlFlattenerOptions options;
476 options.keep_raw_values = false;
477
478 android::ResXMLTree tree;
479 ASSERT_TRUE(Flatten(doc.get(), &tree, options));
480
481 while (tree.next() != android::ResXMLTree::START_TAG) {
482 ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
483 ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
484 }
485
486 ASSERT_THAT(tree.getAttributeCount(), Eq(1u));
487 EXPECT_THAT(tree.getAttributeValueStringID(0), Ge(0));
488 EXPECT_THAT(tree.getAttributeDataType(0), Eq(android::Res_value::TYPE_STRING));
489 EXPECT_THAT(tree.getAttributeValueStringID(0), Eq(tree.getAttributeData(0)));
490}
491
492TEST_F(XmlFlattenerTest, FlattenCompiledValueExcludesRawValueWithKeepRawOptionFalse) {
493 std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(<element foo="true" />)");
494 doc->root->attributes[0].compiled_value = ResourceUtils::MakeBool(true);
495
496 XmlFlattenerOptions options;
497 options.keep_raw_values = false;
498
499 android::ResXMLTree tree;
500 ASSERT_TRUE(Flatten(doc.get(), &tree, options));
501
502 while (tree.next() != android::ResXMLTree::START_TAG) {
503 ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
504 ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
505 }
506
507 ASSERT_THAT(tree.getAttributeCount(), Eq(1u));
508 EXPECT_THAT(tree.getAttributeValueStringID(0), Eq(-1));
509 EXPECT_THAT(tree.getAttributeDataType(0), Eq(android::Res_value::TYPE_INT_BOOLEAN));
510}
511
512TEST_F(XmlFlattenerTest, FlattenCompiledValueExcludesRawValueWithKeepRawOptionTrue) {
513 std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(<element foo="true" />)");
514 doc->root->attributes[0].compiled_value = ResourceUtils::MakeBool(true);
515
516 XmlFlattenerOptions options;
517 options.keep_raw_values = true;
518
519 android::ResXMLTree tree;
520 ASSERT_TRUE(Flatten(doc.get(), &tree, options));
521
522 while (tree.next() != android::ResXMLTree::START_TAG) {
523 ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
524 ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
525 }
526
527 ASSERT_THAT(tree.getAttributeCount(), Eq(1u));
528 EXPECT_THAT(tree.getAttributeValueStringID(0), Ge(0));
529
530 size_t len;
531 EXPECT_THAT(tree.getAttributeStringValue(0, &len), StrEq(u"true"));
532
533 EXPECT_THAT(tree.getAttributeDataType(0), Eq(android::Res_value::TYPE_INT_BOOLEAN));
534}
535
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700536} // namespace aapt