ResourceParser_test.cpp revision ce5e56e243d262a9b65459c3bd0bb9eaadd40628
16f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/* 26f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Copyright (C) 2015 The Android Open Source Project 36f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * 46f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 56f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * you may not use this file except in compliance with the License. 66f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * You may obtain a copy of the License at 76f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * 86f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 96f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * 106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Unless required by applicable law or agreed to in writing, software 116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * See the License for the specific language governing permissions and 146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * limitations under the License. 156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include "ResourceParser.h" 18ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 19ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <sstream> 20ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <string> 21ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include "ResourceTable.h" 231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "ResourceUtils.h" 246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include "ResourceValues.h" 25d0f116b619feede0cfdb647157ce5ab4d50a1c46Adam Lesinski#include "test/Test.h" 26467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include "xml/XmlPullParser.h" 276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskinamespace aapt { 296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 30cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinskiconstexpr const char* kXmlPreamble = 31cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; 326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 331ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiTEST(ResourceParserSingleTest, FailToParseWithNoRootResourcesElement) { 34ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); 35cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::stringstream input(kXmlPreamble); 36cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski input << "<attr name=\"foo\"/>" << std::endl; 37cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ResourceTable table; 38ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceParser parser(context->GetDiagnostics(), &table, Source{"test"}, {}); 39ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski xml::XmlPullParser xml_parser(input); 40ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_FALSE(parser.Parse(&xml_parser)); 41769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 42769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 43ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiclass ResourceParserTest : public ::testing::Test { 44ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski public: 45ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski void SetUp() override { context_ = test::ContextBuilder().Build(); } 461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 47ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ::testing::AssertionResult TestParse(const StringPiece& str) { 48ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return TestParse(str, ConfigDescription{}); 49cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 5052364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 51ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ::testing::AssertionResult TestParse(const StringPiece& str, 52cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const ConfigDescription& config) { 53cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::stringstream input(kXmlPreamble); 54cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski input << "<resources>\n" << str << "\n</resources>" << std::endl; 55cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ResourceParserOptions parserOptions; 56ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceParser parser(context_->GetDiagnostics(), &table_, Source{"test"}, 57cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski config, parserOptions); 58cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski xml::XmlPullParser xmlParser(input); 59ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (parser.Parse(&xmlParser)) { 60cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return ::testing::AssertionSuccess(); 616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 62cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return ::testing::AssertionFailure(); 63cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 64ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 65ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski protected: 66ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceTable table_; 67ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<IAaptContext> context_; 686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}; 696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseQuotedString) { 71cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = "<string name=\"foo\"> \" hey there \" </string>"; 72ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 74ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* str = test::GetValue<String>(&table_, "string/foo"); 75cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, str); 76cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(std::string(" hey there "), *str->value); 776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseEscapedString) { 80cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = "<string name=\"foo\">\\?123</string>"; 81ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 83ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* str = test::GetValue<String>(&table_, "string/foo"); 84cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, str); 85cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(std::string("?123"), *str->value); 866f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 876f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 889f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam LesinskiTEST_F(ResourceParserTest, ParseFormattedString) { 89cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = "<string name=\"foo\">%d %s</string>"; 90ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_FALSE(TestParse(input)); 919f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski 92cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski input = "<string name=\"foo\">%1$d %2$s</string>"; 93ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 949f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski} 959f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski 968c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam LesinskiTEST_F(ResourceParserTest, ParseStyledString) { 97cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Use a surrogate pair unicode point so that we can verify that the span 98cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // indices 99cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // use UTF-16 length and not UTF-18 length. 100cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 101cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<string name=\"foo\">This is my aunt\u2019s <b>string</b></string>"; 102ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 1038c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 104ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski StyledString* str = test::GetValue<StyledString>(&table_, "string/foo"); 105cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, str); 1068c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 107ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const std::string expected_str = "This is my aunt\u2019s string"; 108ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(expected_str, *str->value->str); 109cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(1u, str->value->spans.size()); 1108c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 111cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(std::string("b"), *str->value->spans[0].name); 112ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(17u, str->value->spans[0].first_char); 113ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(23u, str->value->spans[0].last_char); 1148c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski} 1158c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 1168c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam LesinskiTEST_F(ResourceParserTest, ParseStringWithWhitespace) { 117cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = "<string name=\"foo\"> This is what I think </string>"; 118ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 1198c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 120ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* str = test::GetValue<String>(&table_, "string/foo"); 121cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, str); 122cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(std::string("This is what I think"), *str->value); 1238c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 124cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski input = "<string name=\"foo2\">\" This is what I think \"</string>"; 125ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 1268c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 127ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski str = test::GetValue<String>(&table_, "string/foo2"); 128cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, str); 129cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(std::string(" This is what I think "), *str->value); 1308c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski} 1318c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 1321ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiTEST_F(ResourceParserTest, IgnoreXliffTags) { 133cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 134cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<string name=\"foo\" \n" 135cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " xmlns:xliff=\"urn:oasis:names:tc:xliff:document:1.2\">\n" 136cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " There are <xliff:g id=\"count\">%1$d</xliff:g> apples</string>"; 137ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 1381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 139ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* str = test::GetValue<String>(&table_, "string/foo"); 140cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, str); 141cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(StringPiece("There are %1$d apples"), StringPiece(*str->value)); 1421ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 1431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 144dfa5e0705ff82f15e228ba076bc192893bcbe118Adam LesinskiTEST_F(ResourceParserTest, ParseNull) { 145cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = "<integer name=\"foo\">@null</integer>"; 146ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 147cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 148cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // The Android runtime treats a value of android::Res_value::TYPE_NULL as 149cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // a non-existing value, and this causes problems in styles when trying to 150cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // resolve 151cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // an attribute. Null values must be encoded as 152cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // android::Res_value::TYPE_REFERENCE 153cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // with a data value of 0. 154cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski BinaryPrimitive* integer = 155ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski test::GetValue<BinaryPrimitive>(&table_, "integer/foo"); 156cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, integer); 157cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(uint16_t(android::Res_value::TYPE_REFERENCE), 158cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski integer->value.dataType); 159cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(0u, integer->value.data); 160dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski} 161dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski 162dfa5e0705ff82f15e228ba076bc192893bcbe118Adam LesinskiTEST_F(ResourceParserTest, ParseEmpty) { 163cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = "<integer name=\"foo\">@empty</integer>"; 164ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 165dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski 166cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski BinaryPrimitive* integer = 167ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski test::GetValue<BinaryPrimitive>(&table_, "integer/foo"); 168cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, integer); 169cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(uint16_t(android::Res_value::TYPE_NULL), integer->value.dataType); 170cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(uint32_t(android::Res_value::DATA_NULL_EMPTY), integer->value.data); 171dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski} 172dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski 1736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseAttr) { 174cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 175cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<attr name=\"foo\" format=\"string\"/>\n" 176cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<attr name=\"bar\"/>"; 177ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 178cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 179ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = test::GetValue<Attribute>(&table_, "attr/foo"); 180cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, attr); 181ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_STRING), attr->type_mask); 182cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 183ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr = test::GetValue<Attribute>(&table_, "attr/bar"); 184cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, attr); 185ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_ANY), attr->type_mask); 186cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski} 187cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 188cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski// Old AAPT allowed attributes to be defined under different configurations, but 189cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski// ultimately 190cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski// stored them with the default configuration. Check that we have the same 191cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski// behavior. 192cacb28f2d60858106e2819cc7d95a65e8bda890bAdam LesinskiTEST_F(ResourceParserTest, 193cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ParseAttrAndDeclareStyleableUnderConfigButRecordAsNoConfig) { 194ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const ConfigDescription watch_config = test::ParseConfigOrDie("watch"); 195cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = R"EOF( 19652364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski <attr name="foo" /> 19752364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski <declare-styleable name="bar"> 19852364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski <attr name="baz" /> 19952364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski </declare-styleable>)EOF"; 200ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input, watch_config)); 20152364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 202ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(nullptr, test::GetValueForConfig<Attribute>(&table_, "attr/foo", 203ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski watch_config)); 204ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(nullptr, test::GetValueForConfig<Attribute>(&table_, "attr/baz", 205ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski watch_config)); 206ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(nullptr, test::GetValueForConfig<Styleable>( 207ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &table_, "styleable/bar", watch_config)); 20852364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 209ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_NE(nullptr, test::GetValue<Attribute>(&table_, "attr/foo")); 210ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_NE(nullptr, test::GetValue<Attribute>(&table_, "attr/baz")); 211ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_NE(nullptr, test::GetValue<Styleable>(&table_, "styleable/bar")); 21252364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski} 21352364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 214a587065721053ad54e34f484868142407d59512dAdam LesinskiTEST_F(ResourceParserTest, ParseAttrWithMinMax) { 215cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 216cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<attr name=\"foo\" min=\"10\" max=\"23\" format=\"integer\"/>"; 217ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 218a587065721053ad54e34f484868142407d59512dAdam Lesinski 219ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = test::GetValue<Attribute>(&table_, "attr/foo"); 220cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, attr); 221ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_INTEGER), attr->type_mask); 222ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(10, attr->min_int); 223ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(23, attr->max_int); 224a587065721053ad54e34f484868142407d59512dAdam Lesinski} 225a587065721053ad54e34f484868142407d59512dAdam Lesinski 226a587065721053ad54e34f484868142407d59512dAdam LesinskiTEST_F(ResourceParserTest, FailParseAttrWithMinMaxButNotInteger) { 227cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 228cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<attr name=\"foo\" min=\"10\" max=\"23\" format=\"string\"/>"; 229ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_FALSE(TestParse(input)); 230a587065721053ad54e34f484868142407d59512dAdam Lesinski} 231a587065721053ad54e34f484868142407d59512dAdam Lesinski 2326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseUseAndDeclOfAttr) { 233cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 234cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<declare-styleable name=\"Styleable\">\n" 235cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <attr name=\"foo\" />\n" 236cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</declare-styleable>\n" 237cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<attr name=\"foo\" format=\"string\"/>"; 238ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 2396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 240ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = test::GetValue<Attribute>(&table_, "attr/foo"); 241cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, attr); 242ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_STRING), attr->type_mask); 2436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2446f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2456f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseDoubleUseOfAttr) { 246cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 247cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<declare-styleable name=\"Theme\">" 248cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <attr name=\"foo\" />\n" 249cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</declare-styleable>\n" 250cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<declare-styleable name=\"Window\">\n" 251cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <attr name=\"foo\" format=\"boolean\"/>\n" 252cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</declare-styleable>"; 253ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 2546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 255ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = test::GetValue<Attribute>(&table_, "attr/foo"); 256cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, attr); 257ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_BOOLEAN), attr->type_mask); 2586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseEnumAttr) { 261cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 262cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<attr name=\"foo\">\n" 263cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <enum name=\"bar\" value=\"0\"/>\n" 264cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <enum name=\"bat\" value=\"1\"/>\n" 265cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <enum name=\"baz\" value=\"2\"/>\n" 266cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</attr>"; 267ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 2686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 269ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* enum_attr = test::GetValue<Attribute>(&table_, "attr/foo"); 270ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_NE(enum_attr, nullptr); 271ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(enum_attr->type_mask, android::ResTable_map::TYPE_ENUM); 272ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_EQ(enum_attr->symbols.size(), 3u); 2736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 274ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski AAPT_ASSERT_TRUE(enum_attr->symbols[0].symbol.name); 275ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(enum_attr->symbols[0].symbol.name.value().entry, "bar"); 276ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(enum_attr->symbols[0].value, 0u); 2776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 278ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski AAPT_ASSERT_TRUE(enum_attr->symbols[1].symbol.name); 279ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(enum_attr->symbols[1].symbol.name.value().entry, "bat"); 280ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(enum_attr->symbols[1].value, 1u); 2816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 282ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski AAPT_ASSERT_TRUE(enum_attr->symbols[2].symbol.name); 283ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(enum_attr->symbols[2].symbol.name.value().entry, "baz"); 284ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(enum_attr->symbols[2].value, 2u); 2856f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2866f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2876f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseFlagAttr) { 288cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 289cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<attr name=\"foo\">\n" 290cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <flag name=\"bar\" value=\"0\"/>\n" 291cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <flag name=\"bat\" value=\"1\"/>\n" 292cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <flag name=\"baz\" value=\"2\"/>\n" 293cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</attr>"; 294ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 2956f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 296ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* flag_attr = test::GetValue<Attribute>(&table_, "attr/foo"); 297ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_NE(nullptr, flag_attr); 298ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(flag_attr->type_mask, android::ResTable_map::TYPE_FLAGS); 299ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_EQ(flag_attr->symbols.size(), 3u); 3006f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 301ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski AAPT_ASSERT_TRUE(flag_attr->symbols[0].symbol.name); 302ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(flag_attr->symbols[0].symbol.name.value().entry, "bar"); 303ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(flag_attr->symbols[0].value, 0u); 3046f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 305ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski AAPT_ASSERT_TRUE(flag_attr->symbols[1].symbol.name); 306ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(flag_attr->symbols[1].symbol.name.value().entry, "bat"); 307ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(flag_attr->symbols[1].value, 1u); 3086f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 309ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski AAPT_ASSERT_TRUE(flag_attr->symbols[2].symbol.name); 310ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(flag_attr->symbols[2].symbol.name.value().entry, "baz"); 311ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(flag_attr->symbols[2].value, 2u); 3126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 313ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<BinaryPrimitive> flag_value = 314ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceUtils::TryParseFlagSymbol(flag_attr, "baz|bat"); 315ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_NE(nullptr, flag_value); 316ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(flag_value->value.data, 1u | 2u); 3176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, FailToParseEnumAttrWithNonUniqueKeys) { 320cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 321cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<attr name=\"foo\">\n" 322cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <enum name=\"bar\" value=\"0\"/>\n" 323cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <enum name=\"bat\" value=\"1\"/>\n" 324cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <enum name=\"bat\" value=\"2\"/>\n" 325cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</attr>"; 326ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_FALSE(TestParse(input)); 3276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseStyle) { 330cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 331cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<style name=\"foo\" parent=\"@style/fu\">\n" 332cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <item name=\"bar\">#ffffffff</item>\n" 333cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <item name=\"bat\">@string/hey</item>\n" 334cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <item name=\"baz\"><b>hey</b></item>\n" 335cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</style>"; 336ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 337cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 338ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo"); 339cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, style); 340cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(style->parent); 341cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(style->parent.value().name); 342ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(test::ParseNameOrDie("style/fu"), 343cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski style->parent.value().name.value()); 344cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_EQ(3u, style->entries.size()); 345cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 346cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(style->entries[0].key.name); 347ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(test::ParseNameOrDie("attr/bar"), 348cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski style->entries[0].key.name.value()); 349cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 350cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(style->entries[1].key.name); 351ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(test::ParseNameOrDie("attr/bat"), 352cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski style->entries[1].key.name.value()); 353cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 354cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(style->entries[2].key.name); 355ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(test::ParseNameOrDie("attr/baz"), 356cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski style->entries[2].key.name.value()); 3576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 359769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithShorthandParent) { 360cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = "<style name=\"foo\" parent=\"com.app:Theme\"/>"; 361ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 362769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 363ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo"); 364cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, style); 365cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(style->parent); 366cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(style->parent.value().name); 367ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(test::ParseNameOrDie("com.app:style/Theme"), 368cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski style->parent.value().name.value()); 369769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 370769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 37124aad163bc88cb10d2275385e9afc3de7f342d65Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithPackageAliasedParent) { 372cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 373cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<style xmlns:app=\"http://schemas.android.com/apk/res/android\"\n" 374cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " name=\"foo\" parent=\"app:Theme\"/>"; 375ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 37624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 377ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo"); 378cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, style); 379cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(style->parent); 380cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(style->parent.value().name); 381ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(test::ParseNameOrDie("android:style/Theme"), 382cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski style->parent.value().name.value()); 38324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski} 38424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 38524aad163bc88cb10d2275385e9afc3de7f342d65Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithPackageAliasedItems) { 386cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 387cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<style xmlns:app=\"http://schemas.android.com/apk/res/android\" " 388cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "name=\"foo\">\n" 389cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <item name=\"app:bar\">0</item>\n" 390cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</style>"; 391ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 39224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 393ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo"); 394cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, style); 395cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_EQ(1u, style->entries.size()); 396ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(test::ParseNameOrDie("android:attr/bar"), 397cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski style->entries[0].key.name.value()); 39824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski} 39924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 400bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithInferredParent) { 401cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = "<style name=\"foo.bar\"/>"; 402ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 403bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 404ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo.bar"); 405cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, style); 406cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(style->parent); 407cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(style->parent.value().name); 408cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(style->parent.value().name.value(), 409ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski test::ParseNameOrDie("style/foo")); 410ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(style->parent_inferred); 411bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski} 412bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 413cacb28f2d60858106e2819cc7d95a65e8bda890bAdam LesinskiTEST_F(ResourceParserTest, 414cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ParseStyleWithInferredParentOverridenByEmptyParentAttribute) { 415cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = "<style name=\"foo.bar\" parent=\"\"/>"; 416ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 417bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 418ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo.bar"); 419cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, style); 420cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_EXPECT_FALSE(style->parent); 421ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_FALSE(style->parent_inferred); 422bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski} 423bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 42424b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam LesinskiTEST_F(ResourceParserTest, ParseStyleWithPrivateParentReference) { 425cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 426cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski R"EOF(<style name="foo" parent="*android:style/bar" />)EOF"; 427ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 42824b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski 429ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo"); 430cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, style); 431cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(style->parent); 432ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(style->parent.value().private_reference); 43324b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski} 43424b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski 4356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseAutoGeneratedIdReference) { 436cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = "<string name=\"foo\">@+id/bar</string>"; 437ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 4386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 439ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Id* id = test::GetValue<Id>(&table_, "id/bar"); 440cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(id, nullptr); 4416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 4426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseAttributesDeclareStyleable) { 444cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 445cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<declare-styleable name=\"foo\">\n" 446cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <attr name=\"bar\" />\n" 447cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <attr name=\"bat\" format=\"string|reference\"/>\n" 448cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <attr name=\"baz\">\n" 449cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <enum name=\"foo\" value=\"1\"/>\n" 450cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " </attr>\n" 451cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</declare-styleable>"; 452ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 453cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 454cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski Maybe<ResourceTable::SearchResult> result = 455ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski table_.FindResource(test::ParseNameOrDie("styleable/foo")); 456cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(result); 457ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(SymbolState::kPublic, result.value().entry->symbol_status.state); 458cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 459ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = test::GetValue<Attribute>(&table_, "attr/bar"); 460cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(attr, nullptr); 461ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(attr->IsWeak()); 462cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 463ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr = test::GetValue<Attribute>(&table_, "attr/bat"); 464cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(attr, nullptr); 465ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(attr->IsWeak()); 466cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 467ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr = test::GetValue<Attribute>(&table_, "attr/baz"); 468cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(attr, nullptr); 469ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(attr->IsWeak()); 470cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(1u, attr->symbols.size()); 471cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 472ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_NE(nullptr, test::GetValue<Id>(&table_, "id/foo")); 473cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 474ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Styleable* styleable = test::GetValue<Styleable>(&table_, "styleable/foo"); 475cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(styleable, nullptr); 476cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_EQ(3u, styleable->entries.size()); 477cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 478ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(test::ParseNameOrDie("attr/bar"), 479cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski styleable->entries[0].name.value()); 480ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(test::ParseNameOrDie("attr/bat"), 481cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski styleable->entries[1].name.value()); 4826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 4836f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 484467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam LesinskiTEST_F(ResourceParserTest, ParsePrivateAttributesDeclareStyleable) { 485cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 486cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<declare-styleable name=\"foo\" " 487cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "xmlns:privAndroid=\"http://schemas.android.com/apk/prv/res/android\">\n" 488cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <attr name=\"*android:bar\" />\n" 489cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <attr name=\"privAndroid:bat\" />\n" 490cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</declare-styleable>"; 491ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 492ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Styleable* styleable = test::GetValue<Styleable>(&table_, "styleable/foo"); 493cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, styleable); 494cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_EQ(2u, styleable->entries.size()); 495cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 496ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(styleable->entries[0].private_reference); 497cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(styleable->entries[0].name); 498cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(std::string("android"), styleable->entries[0].name.value().package); 499cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 500ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(styleable->entries[1].private_reference); 501cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(styleable->entries[1].name); 502cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(std::string("android"), styleable->entries[1].name.value().package); 503467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 504467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 5056f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseArray) { 506cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 507cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<array name=\"foo\">\n" 508cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <item>@string/ref</item>\n" 509cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <item>hey</item>\n" 510cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <item>23</item>\n" 511cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</array>"; 512ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 5136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 514ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Array* array = test::GetValue<Array>(&table_, "array/foo"); 515cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(array, nullptr); 516cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_EQ(3u, array->items.size()); 5176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 518ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_NE(nullptr, ValueCast<Reference>(array->items[0].get())); 519ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_NE(nullptr, ValueCast<String>(array->items[1].get())); 520ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_NE(nullptr, ValueCast<BinaryPrimitive>(array->items[2].get())); 5216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 5226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 5239ba47d813075fcb05c5e1532c137c93b394631cbAdam LesinskiTEST_F(ResourceParserTest, ParseStringArray) { 524cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 525cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<string-array name=\"foo\">\n" 526cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <item>\"Werk\"</item>\n" 527cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</string-array>\n"; 528ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 529ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_NE(nullptr, test::GetValue<Array>(&table_, "array/foo")); 5309ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski} 5319ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 5326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParsePlural) { 533cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 534cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<plurals name=\"foo\">\n" 535cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <item quantity=\"other\">apples</item>\n" 536cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <item quantity=\"one\">apple</item>\n" 537cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</plurals>"; 538ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 5396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 5406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 5416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseCommentsWithResource) { 542cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 543cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<!--This is a comment-->\n" 544cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<string name=\"foo\">Hi</string>"; 545ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 5466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 547ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* value = test::GetValue<String>(&table_, "string/foo"); 548cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, value); 549ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(value->GetComment(), "This is a comment"); 550e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski} 551e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 552e78fd617ec60139a973a01925fa7adad31febb39Adam LesinskiTEST_F(ResourceParserTest, DoNotCombineMultipleComments) { 553cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 554cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<!--One-->\n" 555cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<!--Two-->\n" 556cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<string name=\"foo\">Hi</string>"; 557e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 558ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 559e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 560ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* value = test::GetValue<String>(&table_, "string/foo"); 561cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, value); 562ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(value->GetComment(), "Two"); 563e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski} 564e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 565e78fd617ec60139a973a01925fa7adad31febb39Adam LesinskiTEST_F(ResourceParserTest, IgnoreCommentBeforeEndTag) { 566cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 567cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<!--One-->\n" 568cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<string name=\"foo\">\n" 569cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " Hi\n" 570cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<!--Two-->\n" 571cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</string>"; 572e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 573ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 5741ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 575ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* value = test::GetValue<String>(&table_, "string/foo"); 576cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, value); 577ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(value->GetComment(), "One"); 5786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 5796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 580ca5638fd85098c3d0a699492751043545f75553aAdam LesinskiTEST_F(ResourceParserTest, ParseNestedComments) { 581cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // We only care about declare-styleable and enum/flag attributes because 582cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // comments 583cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // from those end up in R.java 584cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = R"EOF( 585ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <declare-styleable name="foo"> 586ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <!-- The name of the bar --> 587ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <attr name="barName" format="string|reference" /> 588ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski </declare-styleable> 589ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 590ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <attr name="foo"> 591ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <!-- The very first --> 592ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <enum name="one" value="1" /> 593ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski </attr>)EOF"; 594ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 595ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 596ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Styleable* styleable = test::GetValue<Styleable>(&table_, "styleable/foo"); 597cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, styleable); 598cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_EQ(1u, styleable->entries.size()); 599ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 600cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(StringPiece("The name of the bar"), 601ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski styleable->entries.front().GetComment()); 602ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 603ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = test::GetValue<Attribute>(&table_, "attr/foo"); 604cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, attr); 605cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_EQ(1u, attr->symbols.size()); 606ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 607cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(StringPiece("The very first"), 608ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr->symbols.front().symbol.GetComment()); 609ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski} 610ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 6116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/* 6126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Declaring an ID as public should not require a separate definition 6136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * (as an ID has no value). 6146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 6156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParsePublicIdAsDefinition) { 616cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = "<public type=\"id\" name=\"foo\"/>"; 617ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 6186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 619ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Id* id = test::GetValue<Id>(&table_, "id/foo"); 620cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, id); 6216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 6226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 623e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam LesinskiTEST_F(ResourceParserTest, KeepAllProducts) { 624cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = R"EOF( 6257751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski <string name="foo" product="phone">hi</string> 6267751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski <string name="foo" product="no-sdcard">ho</string> 6277751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski <string name="bar" product="">wee</string> 6287751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski <string name="baz">woo</string> 6297751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski <string name="bit" product="phablet">hoot</string> 6307751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski <string name="bot" product="default">yes</string> 6317751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski )EOF"; 632ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 633ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 634ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_NE(nullptr, test::GetValueForConfigAndProduct<String>( 635ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &table_, "string/foo", 636ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ConfigDescription::DefaultConfig(), "phone")); 637ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_NE(nullptr, test::GetValueForConfigAndProduct<String>( 638ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &table_, "string/foo", 639ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ConfigDescription::DefaultConfig(), "no-sdcard")); 640cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_NE(nullptr, 641ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski test::GetValueForConfigAndProduct<String>( 642ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &table_, "string/bar", ConfigDescription::DefaultConfig(), "")); 643cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_NE(nullptr, 644ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski test::GetValueForConfigAndProduct<String>( 645ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &table_, "string/baz", ConfigDescription::DefaultConfig(), "")); 646ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_NE(nullptr, test::GetValueForConfigAndProduct<String>( 647ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &table_, "string/bit", 648ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ConfigDescription::DefaultConfig(), "phablet")); 649ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_NE(nullptr, test::GetValueForConfigAndProduct<String>( 650ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &table_, "string/bot", 651ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ConfigDescription::DefaultConfig(), "default")); 6529ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski} 6539ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 65427afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam LesinskiTEST_F(ResourceParserTest, AutoIncrementIdsInPublicGroup) { 655cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = R"EOF( 65627afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski <public-group type="attr" first-id="0x01010040"> 65727afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski <public name="foo" /> 65827afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski <public name="bar" /> 65927afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski </public-group>)EOF"; 660ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 661cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 662cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski Maybe<ResourceTable::SearchResult> result = 663ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski table_.FindResource(test::ParseNameOrDie("attr/foo")); 664cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(result); 665cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 666cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(result.value().package->id); 667cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(result.value().type->id); 668cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(result.value().entry->id); 669ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceId actual_id(result.value().package->id.value(), 670ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result.value().type->id.value(), 671ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result.value().entry->id.value()); 672ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(ResourceId(0x01010040), actual_id); 673cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 674ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result = table_.FindResource(test::ParseNameOrDie("attr/bar")); 675cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(result); 676cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 677cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(result.value().package->id); 678cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(result.value().type->id); 679cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(result.value().entry->id); 680ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski actual_id = ResourceId(result.value().package->id.value(), 681ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result.value().type->id.value(), 682ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result.value().entry->id.value()); 683ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(ResourceId(0x01010041), actual_id); 68427afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski} 68527afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski 686fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam LesinskiTEST_F(ResourceParserTest, ExternalTypesShouldOnlyBeReferences) { 687cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 688cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski R"EOF(<item type="layout" name="foo">@layout/bar</item>)EOF"; 689ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 690fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam Lesinski 691cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski input = R"EOF(<item type="layout" name="bar">"this is a string"</item>)EOF"; 692ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_FALSE(TestParse(input)); 693fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam Lesinski} 694fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam Lesinski 695cacb28f2d60858106e2819cc7d95a65e8bda890bAdam LesinskiTEST_F(ResourceParserTest, 696cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AddResourcesElementShouldAddEntryWithUndefinedSymbol) { 697cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = R"EOF(<add-resource name="bar" type="string" />)EOF"; 698ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 699a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski 700cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski Maybe<ResourceTable::SearchResult> result = 701ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski table_.FindResource(test::ParseNameOrDie("string/bar")); 702cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(result); 703cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const ResourceEntry* entry = result.value().entry; 704cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, entry); 705ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(SymbolState::kUndefined, entry->symbol_status.state); 706a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski} 707a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski 7087ff3ee19f4b831a526baf4b928d1ac172d070d82Adam LesinskiTEST_F(ResourceParserTest, ParseItemElementWithFormat) { 709cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 710cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski R"EOF(<item name="foo" type="integer" format="float">0.3</item>)EOF"; 711ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 7127ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski 713cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski BinaryPrimitive* val = 714ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski test::GetValue<BinaryPrimitive>(&table_, "integer/foo"); 715cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, val); 7167ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski 717cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(uint32_t(android::Res_value::TYPE_FLOAT), val->value.dataType); 7187ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski} 7197ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski 720cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski} // namespace aapt 721