ResourceParser_test.cpp revision 8f7c550e20a6edbc9af7bb48675afaf8bcb3783f
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 28d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinskiusing android::StringPiece; 29d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski 306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskinamespace aapt { 316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 32cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinskiconstexpr const char* kXmlPreamble = 33cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; 346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 351ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiTEST(ResourceParserSingleTest, FailToParseWithNoRootResourcesElement) { 36ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); 37cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::stringstream input(kXmlPreamble); 38cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski input << "<attr name=\"foo\"/>" << std::endl; 39cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ResourceTable table; 40ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceParser parser(context->GetDiagnostics(), &table, Source{"test"}, {}); 41ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski xml::XmlPullParser xml_parser(input); 42ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_FALSE(parser.Parse(&xml_parser)); 43769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 44769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 45ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiclass ResourceParserTest : public ::testing::Test { 46ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski public: 47ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski void SetUp() override { context_ = test::ContextBuilder().Build(); } 481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 49ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ::testing::AssertionResult TestParse(const StringPiece& str) { 50ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return TestParse(str, ConfigDescription{}); 51cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 5252364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 53ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ::testing::AssertionResult TestParse(const StringPiece& str, 54cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const ConfigDescription& config) { 55cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::stringstream input(kXmlPreamble); 56cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski input << "<resources>\n" << str << "\n</resources>" << std::endl; 57cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ResourceParserOptions parserOptions; 58ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceParser parser(context_->GetDiagnostics(), &table_, Source{"test"}, 59cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski config, parserOptions); 60cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski xml::XmlPullParser xmlParser(input); 61ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (parser.Parse(&xmlParser)) { 62cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return ::testing::AssertionSuccess(); 636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 64cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return ::testing::AssertionFailure(); 65cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 66ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 67ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski protected: 68ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceTable table_; 69ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<IAaptContext> context_; 706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}; 716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseQuotedString) { 73cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = "<string name=\"foo\"> \" hey there \" </string>"; 74ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 76ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* str = test::GetValue<String>(&table_, "string/foo"); 77cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, str); 78cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(std::string(" hey there "), *str->value); 797542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski EXPECT_TRUE(str->untranslatable_sections.empty()); 806f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseEscapedString) { 83cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = "<string name=\"foo\">\\?123</string>"; 84ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 856f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 86ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* str = test::GetValue<String>(&table_, "string/foo"); 87cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, str); 88cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(std::string("?123"), *str->value); 897542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski EXPECT_TRUE(str->untranslatable_sections.empty()); 906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 929f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam LesinskiTEST_F(ResourceParserTest, ParseFormattedString) { 93cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = "<string name=\"foo\">%d %s</string>"; 94ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_FALSE(TestParse(input)); 959f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski 96cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski input = "<string name=\"foo\">%1$d %2$s</string>"; 97ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 989f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski} 999f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski 1008c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam LesinskiTEST_F(ResourceParserTest, ParseStyledString) { 101cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Use a surrogate pair unicode point so that we can verify that the span 1027542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski // indices use UTF-16 length and not UTF-8 length. 103cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 104cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<string name=\"foo\">This is my aunt\u2019s <b>string</b></string>"; 105ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 1068c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 107ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski StyledString* str = test::GetValue<StyledString>(&table_, "string/foo"); 108cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, str); 1098c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 110ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const std::string expected_str = "This is my aunt\u2019s string"; 111ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(expected_str, *str->value->str); 112cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(1u, str->value->spans.size()); 1137542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski EXPECT_TRUE(str->untranslatable_sections.empty()); 1148c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 115cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(std::string("b"), *str->value->spans[0].name); 116ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(17u, str->value->spans[0].first_char); 117ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(23u, str->value->spans[0].last_char); 1188c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski} 1198c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 1208c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam LesinskiTEST_F(ResourceParserTest, ParseStringWithWhitespace) { 121cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = "<string name=\"foo\"> This is what I think </string>"; 122ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 1238c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 124ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* str = test::GetValue<String>(&table_, "string/foo"); 125cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, str); 126cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(std::string("This is what I think"), *str->value); 1277542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski EXPECT_TRUE(str->untranslatable_sections.empty()); 1288c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 129cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski input = "<string name=\"foo2\">\" This is what I think \"</string>"; 130ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 1318c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 132ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski str = test::GetValue<String>(&table_, "string/foo2"); 133cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, str); 134cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(std::string(" This is what I think "), *str->value); 1358c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski} 1368c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 1377542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam LesinskiTEST_F(ResourceParserTest, IgnoreXliffTagsOtherThanG) { 1387542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski std::string input = R"EOF( 1397542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski <string name="foo" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> 1407542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski There are <xliff:source>no</xliff:source> apples</string>)EOF"; 1417542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski ASSERT_TRUE(TestParse(input)); 1427542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski 1437542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski String* str = test::GetValue<String>(&table_, "string/foo"); 1447542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski ASSERT_NE(nullptr, str); 1457542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski EXPECT_EQ(StringPiece("There are no apples"), StringPiece(*str->value)); 1467542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski EXPECT_TRUE(str->untranslatable_sections.empty()); 1477542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski} 1487542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski 1497542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam LesinskiTEST_F(ResourceParserTest, NestedXliffGTagsAreIllegal) { 1507542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski std::string input = R"EOF( 1517542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski <string name="foo" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> 1527542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski Do not <xliff:g>translate <xliff:g>this</xliff:g></xliff:g></string>)EOF"; 1537542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski EXPECT_FALSE(TestParse(input)); 1547542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski} 1557542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski 1567542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam LesinskiTEST_F(ResourceParserTest, RecordUntranslateableXliffSectionsInString) { 1577542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski std::string input = R"EOF( 1587542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski <string name="foo" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> 1597542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski There are <xliff:g id="count">%1$d</xliff:g> apples</string>)EOF"; 160ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 1611ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 162ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* str = test::GetValue<String>(&table_, "string/foo"); 163cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, str); 164cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(StringPiece("There are %1$d apples"), StringPiece(*str->value)); 1657542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski 1667542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski ASSERT_EQ(1u, str->untranslatable_sections.size()); 1677542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski 1687542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski // We expect indices and lengths that span to include the whitespace 1697542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski // before %1$d. This is due to how the StringBuilder withholds whitespace unless 1707542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski // needed (to deal with line breaks, etc.). 1717542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski EXPECT_EQ(9u, str->untranslatable_sections[0].start); 1727542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski EXPECT_EQ(14u, str->untranslatable_sections[0].end); 1737542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski} 1747542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski 1757542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam LesinskiTEST_F(ResourceParserTest, RecordUntranslateableXliffSectionsInStyledString) { 1767542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski std::string input = R"EOF( 1777542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski <string name="foo" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> 1787542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski There are <b><xliff:g id="count">%1$d</xliff:g></b> apples</string>)EOF"; 1797542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski ASSERT_TRUE(TestParse(input)); 1807542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski 1817542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski StyledString* str = test::GetValue<StyledString>(&table_, "string/foo"); 1827542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski ASSERT_NE(nullptr, str); 1837542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski EXPECT_EQ(StringPiece("There are %1$d apples"), StringPiece(*str->value->str)); 1847542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski 1857542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski ASSERT_EQ(1u, str->untranslatable_sections.size()); 1867542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski 1877542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski // We expect indices and lengths that span to include the whitespace 1887542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski // before %1$d. This is due to how the StringBuilder withholds whitespace unless 1897542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski // needed (to deal with line breaks, etc.). 1907542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski EXPECT_EQ(9u, str->untranslatable_sections[0].start); 1917542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski EXPECT_EQ(14u, str->untranslatable_sections[0].end); 1921ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 1931ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 194dfa5e0705ff82f15e228ba076bc192893bcbe118Adam LesinskiTEST_F(ResourceParserTest, ParseNull) { 195cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = "<integer name=\"foo\">@null</integer>"; 196ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 197cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 198cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // The Android runtime treats a value of android::Res_value::TYPE_NULL as 199cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // a non-existing value, and this causes problems in styles when trying to 2007542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski // resolve an attribute. Null values must be encoded as android::Res_value::TYPE_REFERENCE 201cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // with a data value of 0. 2027542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski BinaryPrimitive* integer = test::GetValue<BinaryPrimitive>(&table_, "integer/foo"); 203cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, integer); 2047542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski EXPECT_EQ(uint16_t(android::Res_value::TYPE_REFERENCE), integer->value.dataType); 205cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(0u, integer->value.data); 206dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski} 207dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski 208dfa5e0705ff82f15e228ba076bc192893bcbe118Adam LesinskiTEST_F(ResourceParserTest, ParseEmpty) { 209cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = "<integer name=\"foo\">@empty</integer>"; 210ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 211dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski 212cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski BinaryPrimitive* integer = 213ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski test::GetValue<BinaryPrimitive>(&table_, "integer/foo"); 214cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, integer); 215cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(uint16_t(android::Res_value::TYPE_NULL), integer->value.dataType); 216cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(uint32_t(android::Res_value::DATA_NULL_EMPTY), integer->value.data); 217dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski} 218dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski 2196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseAttr) { 220cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 221cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<attr name=\"foo\" format=\"string\"/>\n" 222cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<attr name=\"bar\"/>"; 223ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 224cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 225ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = test::GetValue<Attribute>(&table_, "attr/foo"); 226cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, attr); 227ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_STRING), attr->type_mask); 228cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 229ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr = test::GetValue<Attribute>(&table_, "attr/bar"); 230cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, attr); 231ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_ANY), attr->type_mask); 232cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski} 233cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 234cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski// Old AAPT allowed attributes to be defined under different configurations, but 235cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski// ultimately 236cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski// stored them with the default configuration. Check that we have the same 237cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski// behavior. 238cacb28f2d60858106e2819cc7d95a65e8bda890bAdam LesinskiTEST_F(ResourceParserTest, 239cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ParseAttrAndDeclareStyleableUnderConfigButRecordAsNoConfig) { 240ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const ConfigDescription watch_config = test::ParseConfigOrDie("watch"); 241cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = R"EOF( 24252364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski <attr name="foo" /> 24352364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski <declare-styleable name="bar"> 24452364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski <attr name="baz" /> 24552364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski </declare-styleable>)EOF"; 246ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input, watch_config)); 24752364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 248ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(nullptr, test::GetValueForConfig<Attribute>(&table_, "attr/foo", 249ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski watch_config)); 250ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(nullptr, test::GetValueForConfig<Attribute>(&table_, "attr/baz", 251ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski watch_config)); 252ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(nullptr, test::GetValueForConfig<Styleable>( 253ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &table_, "styleable/bar", watch_config)); 25452364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 255ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_NE(nullptr, test::GetValue<Attribute>(&table_, "attr/foo")); 256ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_NE(nullptr, test::GetValue<Attribute>(&table_, "attr/baz")); 257ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_NE(nullptr, test::GetValue<Styleable>(&table_, "styleable/bar")); 25852364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski} 25952364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 260a587065721053ad54e34f484868142407d59512dAdam LesinskiTEST_F(ResourceParserTest, ParseAttrWithMinMax) { 261cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 262cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<attr name=\"foo\" min=\"10\" max=\"23\" format=\"integer\"/>"; 263ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 264a587065721053ad54e34f484868142407d59512dAdam Lesinski 265ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = test::GetValue<Attribute>(&table_, "attr/foo"); 266cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, attr); 267ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_INTEGER), attr->type_mask); 268ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(10, attr->min_int); 269ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(23, attr->max_int); 270a587065721053ad54e34f484868142407d59512dAdam Lesinski} 271a587065721053ad54e34f484868142407d59512dAdam Lesinski 272a587065721053ad54e34f484868142407d59512dAdam LesinskiTEST_F(ResourceParserTest, FailParseAttrWithMinMaxButNotInteger) { 273cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 274cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<attr name=\"foo\" min=\"10\" max=\"23\" format=\"string\"/>"; 275ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_FALSE(TestParse(input)); 276a587065721053ad54e34f484868142407d59512dAdam Lesinski} 277a587065721053ad54e34f484868142407d59512dAdam Lesinski 2786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseUseAndDeclOfAttr) { 279cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 280cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<declare-styleable name=\"Styleable\">\n" 281cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <attr name=\"foo\" />\n" 282cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</declare-styleable>\n" 283cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<attr name=\"foo\" format=\"string\"/>"; 284ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 2856f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 286ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = test::GetValue<Attribute>(&table_, "attr/foo"); 287cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, attr); 288ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_STRING), attr->type_mask); 2896f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseDoubleUseOfAttr) { 292cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 293cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<declare-styleable name=\"Theme\">" 294cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <attr name=\"foo\" />\n" 295cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</declare-styleable>\n" 296cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<declare-styleable name=\"Window\">\n" 297cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <attr name=\"foo\" format=\"boolean\"/>\n" 298cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</declare-styleable>"; 299ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 3006f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 301ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = test::GetValue<Attribute>(&table_, "attr/foo"); 302cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, attr); 303ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_BOOLEAN), attr->type_mask); 3046f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3056f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3066f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseEnumAttr) { 307cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 308cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<attr name=\"foo\">\n" 309cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <enum name=\"bar\" value=\"0\"/>\n" 310cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <enum name=\"bat\" value=\"1\"/>\n" 311cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <enum name=\"baz\" value=\"2\"/>\n" 312cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</attr>"; 313ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 3146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 315ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* enum_attr = test::GetValue<Attribute>(&table_, "attr/foo"); 316ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_NE(enum_attr, nullptr); 317ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(enum_attr->type_mask, android::ResTable_map::TYPE_ENUM); 318ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_EQ(enum_attr->symbols.size(), 3u); 3196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 320ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski AAPT_ASSERT_TRUE(enum_attr->symbols[0].symbol.name); 321ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(enum_attr->symbols[0].symbol.name.value().entry, "bar"); 322ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(enum_attr->symbols[0].value, 0u); 3236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 324ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski AAPT_ASSERT_TRUE(enum_attr->symbols[1].symbol.name); 325ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(enum_attr->symbols[1].symbol.name.value().entry, "bat"); 326ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(enum_attr->symbols[1].value, 1u); 3276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 328ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski AAPT_ASSERT_TRUE(enum_attr->symbols[2].symbol.name); 329ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(enum_attr->symbols[2].symbol.name.value().entry, "baz"); 330ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(enum_attr->symbols[2].value, 2u); 3316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseFlagAttr) { 334cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 335cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<attr name=\"foo\">\n" 336cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <flag name=\"bar\" value=\"0\"/>\n" 337cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <flag name=\"bat\" value=\"1\"/>\n" 338cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <flag name=\"baz\" value=\"2\"/>\n" 339cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</attr>"; 340ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 3416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 342ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* flag_attr = test::GetValue<Attribute>(&table_, "attr/foo"); 343ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_NE(nullptr, flag_attr); 344ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(flag_attr->type_mask, android::ResTable_map::TYPE_FLAGS); 345ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_EQ(flag_attr->symbols.size(), 3u); 3466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 347ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski AAPT_ASSERT_TRUE(flag_attr->symbols[0].symbol.name); 348ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(flag_attr->symbols[0].symbol.name.value().entry, "bar"); 349ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(flag_attr->symbols[0].value, 0u); 3506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 351ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski AAPT_ASSERT_TRUE(flag_attr->symbols[1].symbol.name); 352ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(flag_attr->symbols[1].symbol.name.value().entry, "bat"); 353ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(flag_attr->symbols[1].value, 1u); 3546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 355ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski AAPT_ASSERT_TRUE(flag_attr->symbols[2].symbol.name); 356ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(flag_attr->symbols[2].symbol.name.value().entry, "baz"); 357ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(flag_attr->symbols[2].value, 2u); 3586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 359ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<BinaryPrimitive> flag_value = 360ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceUtils::TryParseFlagSymbol(flag_attr, "baz|bat"); 361ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_NE(nullptr, flag_value); 362ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(flag_value->value.data, 1u | 2u); 3636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, FailToParseEnumAttrWithNonUniqueKeys) { 366cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 367cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<attr name=\"foo\">\n" 368cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <enum name=\"bar\" value=\"0\"/>\n" 369cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <enum name=\"bat\" value=\"1\"/>\n" 370cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <enum name=\"bat\" value=\"2\"/>\n" 371cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</attr>"; 372ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_FALSE(TestParse(input)); 3736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseStyle) { 376cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 377cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<style name=\"foo\" parent=\"@style/fu\">\n" 378cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <item name=\"bar\">#ffffffff</item>\n" 379cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <item name=\"bat\">@string/hey</item>\n" 380cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <item name=\"baz\"><b>hey</b></item>\n" 381cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</style>"; 382ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 383cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 384ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo"); 385cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, style); 386cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(style->parent); 387cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(style->parent.value().name); 388ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(test::ParseNameOrDie("style/fu"), 389cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski style->parent.value().name.value()); 390cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_EQ(3u, style->entries.size()); 391cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 392cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(style->entries[0].key.name); 393ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(test::ParseNameOrDie("attr/bar"), 394cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski style->entries[0].key.name.value()); 395cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 396cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(style->entries[1].key.name); 397ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(test::ParseNameOrDie("attr/bat"), 398cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski style->entries[1].key.name.value()); 399cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 400cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(style->entries[2].key.name); 401ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(test::ParseNameOrDie("attr/baz"), 402cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski style->entries[2].key.name.value()); 4036f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 4046f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 405769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithShorthandParent) { 406cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = "<style name=\"foo\" parent=\"com.app:Theme\"/>"; 407ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 408769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 409ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo"); 410cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, style); 411cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(style->parent); 412cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(style->parent.value().name); 413ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(test::ParseNameOrDie("com.app:style/Theme"), 414cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski style->parent.value().name.value()); 415769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 416769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 41724aad163bc88cb10d2275385e9afc3de7f342d65Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithPackageAliasedParent) { 418cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 419cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<style xmlns:app=\"http://schemas.android.com/apk/res/android\"\n" 420cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " name=\"foo\" parent=\"app:Theme\"/>"; 421ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 42224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 423ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo"); 424cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, style); 425cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(style->parent); 426cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(style->parent.value().name); 427ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(test::ParseNameOrDie("android:style/Theme"), 428cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski style->parent.value().name.value()); 42924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski} 43024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 43124aad163bc88cb10d2275385e9afc3de7f342d65Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithPackageAliasedItems) { 432cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 433cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<style xmlns:app=\"http://schemas.android.com/apk/res/android\" " 434cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "name=\"foo\">\n" 435cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <item name=\"app:bar\">0</item>\n" 436cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</style>"; 437ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 43824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 439ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo"); 440cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, style); 441cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_EQ(1u, style->entries.size()); 442ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(test::ParseNameOrDie("android:attr/bar"), 443cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski style->entries[0].key.name.value()); 44424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski} 44524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 446bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithInferredParent) { 447cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = "<style name=\"foo.bar\"/>"; 448ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 449bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 450ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo.bar"); 451cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, style); 452cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(style->parent); 453cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(style->parent.value().name); 454cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(style->parent.value().name.value(), 455ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski test::ParseNameOrDie("style/foo")); 456ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(style->parent_inferred); 457bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski} 458bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 459cacb28f2d60858106e2819cc7d95a65e8bda890bAdam LesinskiTEST_F(ResourceParserTest, 460cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ParseStyleWithInferredParentOverridenByEmptyParentAttribute) { 461cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = "<style name=\"foo.bar\" parent=\"\"/>"; 462ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 463bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 464ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo.bar"); 465cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, style); 466cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_EXPECT_FALSE(style->parent); 467ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_FALSE(style->parent_inferred); 468bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski} 469bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 47024b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam LesinskiTEST_F(ResourceParserTest, ParseStyleWithPrivateParentReference) { 471cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 472cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski R"EOF(<style name="foo" parent="*android:style/bar" />)EOF"; 473ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 47424b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski 475ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo"); 476cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, style); 477cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(style->parent); 478ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(style->parent.value().private_reference); 47924b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski} 48024b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski 4816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseAutoGeneratedIdReference) { 482cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = "<string name=\"foo\">@+id/bar</string>"; 483ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 4846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 485ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Id* id = test::GetValue<Id>(&table_, "id/bar"); 486cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(id, nullptr); 4876f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 4886f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4896f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseAttributesDeclareStyleable) { 490cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 491cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<declare-styleable name=\"foo\">\n" 492cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <attr name=\"bar\" />\n" 493cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <attr name=\"bat\" format=\"string|reference\"/>\n" 494cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <attr name=\"baz\">\n" 495cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <enum name=\"foo\" value=\"1\"/>\n" 496cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " </attr>\n" 497cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</declare-styleable>"; 498ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 499cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 500cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski Maybe<ResourceTable::SearchResult> result = 501ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski table_.FindResource(test::ParseNameOrDie("styleable/foo")); 502cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(result); 503ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(SymbolState::kPublic, result.value().entry->symbol_status.state); 504cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 505ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = test::GetValue<Attribute>(&table_, "attr/bar"); 506cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(attr, nullptr); 507ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(attr->IsWeak()); 508cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 509ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr = test::GetValue<Attribute>(&table_, "attr/bat"); 510cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(attr, nullptr); 511ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(attr->IsWeak()); 512cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 513ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr = test::GetValue<Attribute>(&table_, "attr/baz"); 514cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(attr, nullptr); 515ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(attr->IsWeak()); 516cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(1u, attr->symbols.size()); 517cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 518ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_NE(nullptr, test::GetValue<Id>(&table_, "id/foo")); 519cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 520ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Styleable* styleable = test::GetValue<Styleable>(&table_, "styleable/foo"); 521cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(styleable, nullptr); 522cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_EQ(3u, styleable->entries.size()); 523cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 524ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(test::ParseNameOrDie("attr/bar"), 525cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski styleable->entries[0].name.value()); 526ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(test::ParseNameOrDie("attr/bat"), 527cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski styleable->entries[1].name.value()); 5286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 5296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 530467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam LesinskiTEST_F(ResourceParserTest, ParsePrivateAttributesDeclareStyleable) { 531cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 532cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<declare-styleable name=\"foo\" " 533cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "xmlns:privAndroid=\"http://schemas.android.com/apk/prv/res/android\">\n" 534cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <attr name=\"*android:bar\" />\n" 535cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <attr name=\"privAndroid:bat\" />\n" 536cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</declare-styleable>"; 537ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 538ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Styleable* styleable = test::GetValue<Styleable>(&table_, "styleable/foo"); 539cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, styleable); 540cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_EQ(2u, styleable->entries.size()); 541cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 542ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(styleable->entries[0].private_reference); 543cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(styleable->entries[0].name); 544cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(std::string("android"), styleable->entries[0].name.value().package); 545cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 546ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(styleable->entries[1].private_reference); 547cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(styleable->entries[1].name); 548cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(std::string("android"), styleable->entries[1].name.value().package); 549467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 550467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 5516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseArray) { 552cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 553cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<array name=\"foo\">\n" 554cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <item>@string/ref</item>\n" 555cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <item>hey</item>\n" 556cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <item>23</item>\n" 557cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</array>"; 558ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 5596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 560ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Array* array = test::GetValue<Array>(&table_, "array/foo"); 561cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(array, nullptr); 562cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_EQ(3u, array->items.size()); 5636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 564ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_NE(nullptr, ValueCast<Reference>(array->items[0].get())); 565ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_NE(nullptr, ValueCast<String>(array->items[1].get())); 566ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_NE(nullptr, ValueCast<BinaryPrimitive>(array->items[2].get())); 5676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 5686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 5699ba47d813075fcb05c5e1532c137c93b394631cbAdam LesinskiTEST_F(ResourceParserTest, ParseStringArray) { 570cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 571cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<string-array name=\"foo\">\n" 572cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <item>\"Werk\"</item>\n" 573cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</string-array>\n"; 574ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 575ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_NE(nullptr, test::GetValue<Array>(&table_, "array/foo")); 5769ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski} 5779ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 5786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParsePlural) { 579cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 580cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<plurals name=\"foo\">\n" 581cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <item quantity=\"other\">apples</item>\n" 582cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " <item quantity=\"one\">apple</item>\n" 583cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</plurals>"; 584ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 5858f7c550e20a6edbc9af7bb48675afaf8bcb3783fAdam Lesinski 5868f7c550e20a6edbc9af7bb48675afaf8bcb3783fAdam Lesinski Plural* plural = test::GetValue<Plural>(&table_, "plurals/foo"); 5878f7c550e20a6edbc9af7bb48675afaf8bcb3783fAdam Lesinski ASSERT_NE(nullptr, plural); 5888f7c550e20a6edbc9af7bb48675afaf8bcb3783fAdam Lesinski EXPECT_EQ(nullptr, plural->values[Plural::Zero]); 5898f7c550e20a6edbc9af7bb48675afaf8bcb3783fAdam Lesinski EXPECT_EQ(nullptr, plural->values[Plural::Two]); 5908f7c550e20a6edbc9af7bb48675afaf8bcb3783fAdam Lesinski EXPECT_EQ(nullptr, plural->values[Plural::Few]); 5918f7c550e20a6edbc9af7bb48675afaf8bcb3783fAdam Lesinski EXPECT_EQ(nullptr, plural->values[Plural::Many]); 5928f7c550e20a6edbc9af7bb48675afaf8bcb3783fAdam Lesinski 5938f7c550e20a6edbc9af7bb48675afaf8bcb3783fAdam Lesinski EXPECT_NE(nullptr, plural->values[Plural::One]); 5948f7c550e20a6edbc9af7bb48675afaf8bcb3783fAdam Lesinski EXPECT_NE(nullptr, plural->values[Plural::Other]); 5956f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 5966f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 5976f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseCommentsWithResource) { 598cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 599cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<!--This is a comment-->\n" 600cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<string name=\"foo\">Hi</string>"; 601ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 6026f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 603ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* value = test::GetValue<String>(&table_, "string/foo"); 604cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, value); 605ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(value->GetComment(), "This is a comment"); 606e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski} 607e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 608e78fd617ec60139a973a01925fa7adad31febb39Adam LesinskiTEST_F(ResourceParserTest, DoNotCombineMultipleComments) { 609cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 610cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<!--One-->\n" 611cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<!--Two-->\n" 612cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<string name=\"foo\">Hi</string>"; 613e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 614ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 615e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 616ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* value = test::GetValue<String>(&table_, "string/foo"); 617cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, value); 618ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(value->GetComment(), "Two"); 619e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski} 620e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 621e78fd617ec60139a973a01925fa7adad31febb39Adam LesinskiTEST_F(ResourceParserTest, IgnoreCommentBeforeEndTag) { 622cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 623cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<!--One-->\n" 624cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<string name=\"foo\">\n" 625cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski " Hi\n" 626cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "<!--Two-->\n" 627cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski "</string>"; 628e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 629ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 6301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 631ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* value = test::GetValue<String>(&table_, "string/foo"); 632cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, value); 633ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(value->GetComment(), "One"); 6346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 6356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 636ca5638fd85098c3d0a699492751043545f75553aAdam LesinskiTEST_F(ResourceParserTest, ParseNestedComments) { 637cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // We only care about declare-styleable and enum/flag attributes because 638cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // comments 639cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // from those end up in R.java 640cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = R"EOF( 641ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <declare-styleable name="foo"> 642ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <!-- The name of the bar --> 643ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <attr name="barName" format="string|reference" /> 644ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski </declare-styleable> 645ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 646ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <attr name="foo"> 647ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <!-- The very first --> 648ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <enum name="one" value="1" /> 649ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski </attr>)EOF"; 650ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 651ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 652ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Styleable* styleable = test::GetValue<Styleable>(&table_, "styleable/foo"); 653cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, styleable); 654cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_EQ(1u, styleable->entries.size()); 655ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 656cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(StringPiece("The name of the bar"), 657ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski styleable->entries.front().GetComment()); 658ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 659ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = test::GetValue<Attribute>(&table_, "attr/foo"); 660cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, attr); 661cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_EQ(1u, attr->symbols.size()); 662ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 663cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(StringPiece("The very first"), 664ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr->symbols.front().symbol.GetComment()); 665ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski} 666ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 6676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/* 6686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Declaring an ID as public should not require a separate definition 6696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * (as an ID has no value). 6706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 6716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParsePublicIdAsDefinition) { 672cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = "<public type=\"id\" name=\"foo\"/>"; 673ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 6746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 675ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Id* id = test::GetValue<Id>(&table_, "id/foo"); 676cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, id); 6776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 6786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 679e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam LesinskiTEST_F(ResourceParserTest, KeepAllProducts) { 680cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = R"EOF( 6817751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski <string name="foo" product="phone">hi</string> 6827751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski <string name="foo" product="no-sdcard">ho</string> 6837751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski <string name="bar" product="">wee</string> 6847751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski <string name="baz">woo</string> 6857751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski <string name="bit" product="phablet">hoot</string> 6867751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski <string name="bot" product="default">yes</string> 6877751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski )EOF"; 688ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 689ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 690ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_NE(nullptr, test::GetValueForConfigAndProduct<String>( 691ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &table_, "string/foo", 692ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ConfigDescription::DefaultConfig(), "phone")); 693ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_NE(nullptr, test::GetValueForConfigAndProduct<String>( 694ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &table_, "string/foo", 695ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ConfigDescription::DefaultConfig(), "no-sdcard")); 696cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_NE(nullptr, 697ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski test::GetValueForConfigAndProduct<String>( 698ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &table_, "string/bar", ConfigDescription::DefaultConfig(), "")); 699cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_NE(nullptr, 700ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski test::GetValueForConfigAndProduct<String>( 701ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &table_, "string/baz", ConfigDescription::DefaultConfig(), "")); 702ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_NE(nullptr, test::GetValueForConfigAndProduct<String>( 703ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &table_, "string/bit", 704ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ConfigDescription::DefaultConfig(), "phablet")); 705ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_NE(nullptr, test::GetValueForConfigAndProduct<String>( 706ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski &table_, "string/bot", 707ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ConfigDescription::DefaultConfig(), "default")); 7089ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski} 7099ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 71027afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam LesinskiTEST_F(ResourceParserTest, AutoIncrementIdsInPublicGroup) { 711cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = R"EOF( 71227afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski <public-group type="attr" first-id="0x01010040"> 71327afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski <public name="foo" /> 71427afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski <public name="bar" /> 71527afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski </public-group>)EOF"; 716ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 717cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 718cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski Maybe<ResourceTable::SearchResult> result = 719ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski table_.FindResource(test::ParseNameOrDie("attr/foo")); 720cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(result); 721cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 722cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(result.value().package->id); 723cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(result.value().type->id); 724cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(result.value().entry->id); 725ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceId actual_id(result.value().package->id.value(), 726ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result.value().type->id.value(), 727ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result.value().entry->id.value()); 728ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(ResourceId(0x01010040), actual_id); 729cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 730ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result = table_.FindResource(test::ParseNameOrDie("attr/bar")); 731cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(result); 732cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 733cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(result.value().package->id); 734cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(result.value().type->id); 735cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(result.value().entry->id); 736ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski actual_id = ResourceId(result.value().package->id.value(), 737ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result.value().type->id.value(), 738ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result.value().entry->id.value()); 739ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(ResourceId(0x01010041), actual_id); 74027afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski} 74127afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski 742fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam LesinskiTEST_F(ResourceParserTest, ExternalTypesShouldOnlyBeReferences) { 743cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 744cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski R"EOF(<item type="layout" name="foo">@layout/bar</item>)EOF"; 745ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 746fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam Lesinski 747cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski input = R"EOF(<item type="layout" name="bar">"this is a string"</item>)EOF"; 748ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_FALSE(TestParse(input)); 749fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam Lesinski} 750fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam Lesinski 751cacb28f2d60858106e2819cc7d95a65e8bda890bAdam LesinskiTEST_F(ResourceParserTest, 752cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AddResourcesElementShouldAddEntryWithUndefinedSymbol) { 753cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = R"EOF(<add-resource name="bar" type="string" />)EOF"; 754ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 755a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski 756cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski Maybe<ResourceTable::SearchResult> result = 757ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski table_.FindResource(test::ParseNameOrDie("string/bar")); 758cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski AAPT_ASSERT_TRUE(result); 759cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const ResourceEntry* entry = result.value().entry; 760cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, entry); 761ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_EQ(SymbolState::kUndefined, entry->symbol_status.state); 762a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski} 763a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski 7647ff3ee19f4b831a526baf4b928d1ac172d070d82Adam LesinskiTEST_F(ResourceParserTest, ParseItemElementWithFormat) { 765cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 766cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski R"EOF(<item name="foo" type="integer" format="float">0.3</item>)EOF"; 767ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 7687ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski 769cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski BinaryPrimitive* val = 770ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski test::GetValue<BinaryPrimitive>(&table_, "integer/foo"); 771cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_NE(nullptr, val); 7727ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski 773cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski EXPECT_EQ(uint32_t(android::Res_value::TYPE_FLOAT), val->value.dataType); 7747ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski} 7757ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski 77686d67df8d57b9537666f9b54a9ca563779a2288bAdam LesinskiTEST_F(ResourceParserTest, ParseConfigVaryingItem) { 77786d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski std::string input = R"EOF(<item name="foo" type="configVarying">Hey</item>)EOF"; 77886d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski ASSERT_TRUE(TestParse(input)); 77986d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski ASSERT_NE(nullptr, test::GetValue<String>(&table_, "configVarying/foo")); 78086d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski} 78186d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski 78286d67df8d57b9537666f9b54a9ca563779a2288bAdam LesinskiTEST_F(ResourceParserTest, ParseBagElement) { 78386d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski std::string input = 78486d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski R"EOF(<bag name="bag" type="configVarying"><item name="test">Hello!</item></bag>)EOF"; 78586d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski ASSERT_TRUE(TestParse(input)); 78686d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski 78786d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski Style* val = test::GetValue<Style>(&table_, "configVarying/bag"); 78886d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski ASSERT_NE(nullptr, val); 78986d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski 79086d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski ASSERT_EQ(1u, val->entries.size()); 79186d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski EXPECT_EQ(Reference(test::ParseNameOrDie("attr/test")), val->entries[0].key); 79286d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski EXPECT_NE(nullptr, ValueCast<RawString>(val->entries[0].value.get())); 79386d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski} 79486d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski 795cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski} // namespace aapt 796