ResourceParser_test.cpp revision 549e437e14f3b92f02bd3abc7d1cd68387132ce1
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 28a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinskiusing ::aapt::test::StrValueEq; 29bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinskiusing ::aapt::test::ValueEq; 30a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinskiusing ::android::ResTable_map; 31a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinskiusing ::android::Res_value; 32e597d68d33c76c2b830f5497ed4ba74c5193a056Adam Lesinskiusing ::android::StringPiece; 33e597d68d33c76c2b830f5497ed4ba74c5193a056Adam Lesinskiusing ::testing::Eq; 34a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinskiusing ::testing::IsEmpty; 35a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinskiusing ::testing::IsNull; 36e597d68d33c76c2b830f5497ed4ba74c5193a056Adam Lesinskiusing ::testing::NotNull; 37bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinskiusing ::testing::Pointee; 38a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinskiusing ::testing::SizeIs; 39d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski 406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskinamespace aapt { 416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 42bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinskiconstexpr const char* kXmlPreamble = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; 436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 441ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiTEST(ResourceParserSingleTest, FailToParseWithNoRootResourcesElement) { 45ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); 46cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::stringstream input(kXmlPreamble); 47bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski input << R"(<attr name="foo"/>)" << std::endl; 48cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ResourceTable table; 49ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceParser parser(context->GetDiagnostics(), &table, Source{"test"}, {}); 50ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski xml::XmlPullParser xml_parser(input); 51ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_FALSE(parser.Parse(&xml_parser)); 52769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 53769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 54ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiclass ResourceParserTest : public ::testing::Test { 55ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski public: 56bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski void SetUp() override { 57bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski context_ = test::ContextBuilder().Build(); 58bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski } 591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 60ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ::testing::AssertionResult TestParse(const StringPiece& str) { 61ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return TestParse(str, ConfigDescription{}); 62cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 6352364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 64bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski ::testing::AssertionResult TestParse(const StringPiece& str, const ConfigDescription& config) { 65cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::stringstream input(kXmlPreamble); 66cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski input << "<resources>\n" << str << "\n</resources>" << std::endl; 67cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ResourceParserOptions parserOptions; 68bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski ResourceParser parser(context_->GetDiagnostics(), &table_, Source{"test"}, config, 69bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski parserOptions); 70cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski xml::XmlPullParser xmlParser(input); 71ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (parser.Parse(&xmlParser)) { 72cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return ::testing::AssertionSuccess(); 736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 74cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return ::testing::AssertionFailure(); 75cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 76ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 77ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski protected: 78ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceTable table_; 79ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<IAaptContext> context_; 806f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}; 816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseQuotedString) { 83a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<string name="foo"> " hey there " </string>)")); 846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 85ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* str = test::GetValue<String>(&table_, "string/foo"); 86a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(str, NotNull()); 87a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(*str, StrValueEq(" hey there ")); 88a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(str->untranslatable_sections, IsEmpty()); 896f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseEscapedString) { 92a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<string name="foo">\?123</string>)")); 936f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 94ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* str = test::GetValue<String>(&table_, "string/foo"); 95a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(str, NotNull()); 96a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(*str, StrValueEq("?123")); 97a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(str->untranslatable_sections, IsEmpty()); 98549e437e14f3b92f02bd3abc7d1cd68387132ce1Adam Lesinski 99549e437e14f3b92f02bd3abc7d1cd68387132ce1Adam Lesinski ASSERT_TRUE(TestParse(R"(<string name="bar">This isn\’t a bad string</string>)")); 100549e437e14f3b92f02bd3abc7d1cd68387132ce1Adam Lesinski str = test::GetValue<String>(&table_, "string/bar"); 101549e437e14f3b92f02bd3abc7d1cd68387132ce1Adam Lesinski ASSERT_THAT(str, NotNull()); 102549e437e14f3b92f02bd3abc7d1cd68387132ce1Adam Lesinski EXPECT_THAT(*str, StrValueEq("This isn’t a bad string")); 1036f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1046f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1059f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam LesinskiTEST_F(ResourceParserTest, ParseFormattedString) { 106a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_FALSE(TestParse(R"(<string name="foo">%d %s</string>)")); 107a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<string name="foo">%1$d %2$s</string>)")); 1089f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski} 1099f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski 1108c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam LesinskiTEST_F(ResourceParserTest, ParseStyledString) { 111cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Use a surrogate pair unicode point so that we can verify that the span 1127542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski // indices use UTF-16 length and not UTF-8 length. 113cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 1148049f3da712ea9c3154b57ce2276c97e749d1f2cAdam Lesinski "<string name=\"foo\">This is my aunt\u2019s <b>fickle <small>string</small></b></string>"; 115ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 1168c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 117ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski StyledString* str = test::GetValue<StyledString>(&table_, "string/foo"); 118a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(str, NotNull()); 1198c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 120a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(*str->value->str, Eq("This is my aunt\u2019s fickle string")); 121a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(str->value->spans, SizeIs(2)); 122a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(str->untranslatable_sections, IsEmpty()); 1238c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 124a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(*str->value->spans[0].name, Eq("b")); 125a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(str->value->spans[0].first_char, Eq(17u)); 126a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(str->value->spans[0].last_char, Eq(30u)); 1278049f3da712ea9c3154b57ce2276c97e749d1f2cAdam Lesinski 128a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(*str->value->spans[1].name, Eq("small")); 129a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(str->value->spans[1].first_char, Eq(24u)); 130a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(str->value->spans[1].last_char, Eq(30u)); 1318c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski} 1328c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 1338c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam LesinskiTEST_F(ResourceParserTest, ParseStringWithWhitespace) { 134a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<string name="foo"> This is what I think </string>)")); 1358c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 136ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* str = test::GetValue<String>(&table_, "string/foo"); 137a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(str, NotNull()); 138a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(*str->value, Eq("This is what I think")); 139a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(str->untranslatable_sections, IsEmpty()); 1408c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 141a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<string name="foo2">" This is what I think "</string>)")); 1428c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 143ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski str = test::GetValue<String>(&table_, "string/foo2"); 144a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(str, NotNull()); 145a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(*str, StrValueEq(" This is what I think ")); 1468c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski} 1478c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 1487542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam LesinskiTEST_F(ResourceParserTest, IgnoreXliffTagsOtherThanG) { 149a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 1507542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski <string name="foo" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> 151a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski There are <xliff:source>no</xliff:source> apples</string>)"; 1527542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski ASSERT_TRUE(TestParse(input)); 1537542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski 1547542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski String* str = test::GetValue<String>(&table_, "string/foo"); 155a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(str, NotNull()); 156a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(*str, StrValueEq("There are no apples")); 157a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(str->untranslatable_sections, IsEmpty()); 1587542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski} 1597542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski 1607542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam LesinskiTEST_F(ResourceParserTest, NestedXliffGTagsAreIllegal) { 161a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 1627542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski <string name="foo" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> 163a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski Do not <xliff:g>translate <xliff:g>this</xliff:g></xliff:g></string>)"; 1647542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski EXPECT_FALSE(TestParse(input)); 1657542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski} 1667542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski 1677542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam LesinskiTEST_F(ResourceParserTest, RecordUntranslateableXliffSectionsInString) { 168a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 1697542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski <string name="foo" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> 170a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski There are <xliff:g id="count">%1$d</xliff:g> apples</string>)"; 171ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 1721ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 173ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* str = test::GetValue<String>(&table_, "string/foo"); 174a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(str, NotNull()); 175a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(*str, StrValueEq("There are %1$d apples")); 176a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(str->untranslatable_sections, SizeIs(1)); 1777542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski 1787542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski // We expect indices and lengths that span to include the whitespace 1797542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski // before %1$d. This is due to how the StringBuilder withholds whitespace unless 1807542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski // needed (to deal with line breaks, etc.). 181a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(str->untranslatable_sections[0].start, Eq(9u)); 182a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(str->untranslatable_sections[0].end, Eq(14u)); 1837542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski} 1847542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski 1857542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam LesinskiTEST_F(ResourceParserTest, RecordUntranslateableXliffSectionsInStyledString) { 186a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 1877542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski <string name="foo" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> 188a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski There are <b><xliff:g id="count">%1$d</xliff:g></b> apples</string>)"; 1897542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski ASSERT_TRUE(TestParse(input)); 1907542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski 1917542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski StyledString* str = test::GetValue<StyledString>(&table_, "string/foo"); 192a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(str, NotNull()); 193a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(*str->value->str, Eq("There are %1$d apples")); 194a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(str->untranslatable_sections, SizeIs(1)); 1957542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski 1967542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski // We expect indices and lengths that span to include the whitespace 1977542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski // before %1$d. This is due to how the StringBuilder withholds whitespace unless 1987542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski // needed (to deal with line breaks, etc.). 199a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(str->untranslatable_sections[0].start, Eq(9u)); 200a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(str->untranslatable_sections[0].end, Eq(14u)); 2011ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 2021ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 203dfa5e0705ff82f15e228ba076bc192893bcbe118Adam LesinskiTEST_F(ResourceParserTest, ParseNull) { 204a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"(<integer name="foo">@null</integer>)"; 205ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 206cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 207cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // The Android runtime treats a value of android::Res_value::TYPE_NULL as 208cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // a non-existing value, and this causes problems in styles when trying to 2097542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski // resolve an attribute. Null values must be encoded as android::Res_value::TYPE_REFERENCE 210cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // with a data value of 0. 211bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski Reference* null_ref = test::GetValue<Reference>(&table_, "integer/foo"); 212bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski ASSERT_THAT(null_ref, NotNull()); 213bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski EXPECT_FALSE(null_ref->name); 214bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski EXPECT_FALSE(null_ref->id); 215a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(null_ref->reference_type, Eq(Reference::Type::kResource)); 216dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski} 217dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski 218dfa5e0705ff82f15e228ba076bc192893bcbe118Adam LesinskiTEST_F(ResourceParserTest, ParseEmpty) { 219a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"(<integer name="foo">@empty</integer>)"; 220ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 221dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski 222bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski BinaryPrimitive* integer = test::GetValue<BinaryPrimitive>(&table_, "integer/foo"); 223a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(integer, NotNull()); 224a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(integer->value.dataType, Eq(Res_value::TYPE_NULL)); 225a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(integer->value.data, Eq(Res_value::DATA_NULL_EMPTY)); 226dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski} 227dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski 2286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseAttr) { 229a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 230a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="foo" format="string"/> 231a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="bar"/>)"; 232ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 233cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 234ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = test::GetValue<Attribute>(&table_, "attr/foo"); 235a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(attr, NotNull()); 236a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(attr->type_mask, Eq(ResTable_map::TYPE_STRING)); 237cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 238ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr = test::GetValue<Attribute>(&table_, "attr/bar"); 239a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(attr, NotNull()); 240a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(attr->type_mask, Eq(ResTable_map::TYPE_ANY)); 241cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski} 242cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 243a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski// Old AAPT allowed attributes to be defined under different configurations, but ultimately 244a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski// stored them with the default configuration. Check that we have the same behavior. 245bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam LesinskiTEST_F(ResourceParserTest, ParseAttrAndDeclareStyleableUnderConfigButRecordAsNoConfig) { 246ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const ConfigDescription watch_config = test::ParseConfigOrDie("watch"); 247bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski std::string input = R"( 248bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski <attr name="foo" /> 249bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski <declare-styleable name="bar"> 250bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski <attr name="baz" /> 251bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski </declare-styleable>)"; 252ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input, watch_config)); 25352364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 254a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(test::GetValueForConfig<Attribute>(&table_, "attr/foo", watch_config), IsNull()); 255a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(test::GetValueForConfig<Attribute>(&table_, "attr/baz", watch_config), IsNull()); 256a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(test::GetValueForConfig<Styleable>(&table_, "styleable/bar", watch_config), IsNull()); 25752364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 258a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(test::GetValue<Attribute>(&table_, "attr/foo"), NotNull()); 259a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(test::GetValue<Attribute>(&table_, "attr/baz"), NotNull()); 260a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(test::GetValue<Styleable>(&table_, "styleable/bar"), NotNull()); 26152364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski} 26252364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 263a587065721053ad54e34f484868142407d59512dAdam LesinskiTEST_F(ResourceParserTest, ParseAttrWithMinMax) { 264a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"(<attr name="foo" min="10" max="23" format="integer"/>)"; 265ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 266a587065721053ad54e34f484868142407d59512dAdam Lesinski 267ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = test::GetValue<Attribute>(&table_, "attr/foo"); 268a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(attr, NotNull()); 269a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(attr->type_mask, Eq(ResTable_map::TYPE_INTEGER)); 270a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(attr->min_int, Eq(10)); 271a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(attr->max_int, Eq(23)); 272a587065721053ad54e34f484868142407d59512dAdam Lesinski} 273a587065721053ad54e34f484868142407d59512dAdam Lesinski 274a587065721053ad54e34f484868142407d59512dAdam LesinskiTEST_F(ResourceParserTest, FailParseAttrWithMinMaxButNotInteger) { 275a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_FALSE(TestParse(R"(<attr name="foo" min="10" max="23" format="string"/>)")); 276a587065721053ad54e34f484868142407d59512dAdam Lesinski} 277a587065721053ad54e34f484868142407d59512dAdam Lesinski 2786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseUseAndDeclOfAttr) { 279a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 280a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <declare-styleable name="Styleable"> 281a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="foo" /> 282a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </declare-styleable> 283a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="foo" format="string"/>)"; 284ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 2856f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 286ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = test::GetValue<Attribute>(&table_, "attr/foo"); 287a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(attr, NotNull()); 288a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(attr->type_mask, Eq(ResTable_map::TYPE_STRING)); 2896f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseDoubleUseOfAttr) { 292a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 293a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <declare-styleable name="Theme"> 294a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="foo" /> 295a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </declare-styleable> 296a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <declare-styleable name="Window"> 297a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="foo" format="boolean"/> 298a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </declare-styleable>)"; 299ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 3006f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 301ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = test::GetValue<Attribute>(&table_, "attr/foo"); 302a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(attr, NotNull()); 303a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(attr->type_mask, Eq(ResTable_map::TYPE_BOOLEAN)); 3046f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3056f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3066f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseEnumAttr) { 307a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 308a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="foo"> 309a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <enum name="bar" value="0"/> 310a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <enum name="bat" value="1"/> 311a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <enum name="baz" value="2"/> 312a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </attr>)"; 313ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 3146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 315ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* enum_attr = test::GetValue<Attribute>(&table_, "attr/foo"); 316a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(enum_attr, NotNull()); 317a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(enum_attr->type_mask, Eq(ResTable_map::TYPE_ENUM)); 318a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(enum_attr->symbols, SizeIs(3)); 3196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 320a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(enum_attr->symbols[0].symbol.name); 321a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(enum_attr->symbols[0].symbol.name.value().entry, Eq("bar")); 322a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(enum_attr->symbols[0].value, Eq(0u)); 3236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 324a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(enum_attr->symbols[1].symbol.name); 325a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(enum_attr->symbols[1].symbol.name.value().entry, Eq("bat")); 326a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(enum_attr->symbols[1].value, Eq(1u)); 3276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 328a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(enum_attr->symbols[2].symbol.name); 329a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(enum_attr->symbols[2].symbol.name.value().entry, Eq("baz")); 330a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(enum_attr->symbols[2].value, Eq(2u)); 3316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseFlagAttr) { 334a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 335a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="foo"> 336a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <flag name="bar" value="0"/> 337a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <flag name="bat" value="1"/> 338a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <flag name="baz" value="2"/> 339a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </attr>)"; 340ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 3416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 342ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* flag_attr = test::GetValue<Attribute>(&table_, "attr/foo"); 343a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(flag_attr, NotNull()); 344a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(flag_attr->type_mask, Eq(ResTable_map::TYPE_FLAGS)); 345a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(flag_attr->symbols, SizeIs(3)); 3466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 347a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(flag_attr->symbols[0].symbol.name); 348a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(flag_attr->symbols[0].symbol.name.value().entry, Eq("bar")); 349a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(flag_attr->symbols[0].value, Eq(0u)); 3506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 351a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(flag_attr->symbols[1].symbol.name); 352a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(flag_attr->symbols[1].symbol.name.value().entry, Eq("bat")); 353a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(flag_attr->symbols[1].value, Eq(1u)); 3546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 355a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(flag_attr->symbols[2].symbol.name); 356a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(flag_attr->symbols[2].symbol.name.value().entry, Eq("baz")); 357a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(flag_attr->symbols[2].value, Eq(2u)); 3586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 359ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<BinaryPrimitive> flag_value = 360ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceUtils::TryParseFlagSymbol(flag_attr, "baz|bat"); 361a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(flag_value, NotNull()); 362a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(flag_value->value.data, Eq(1u | 2u)); 3636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, FailToParseEnumAttrWithNonUniqueKeys) { 366a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 367a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="foo"> 368a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <enum name="bar" value="0"/> 369a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <enum name="bat" value="1"/> 370a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <enum name="bat" value="2"/> 371a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </attr>)"; 372ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_FALSE(TestParse(input)); 3736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseStyle) { 376a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 377a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <style name="foo" parent="@style/fu"> 378a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <item name="bar">#ffffffff</item> 379a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <item name="bat">@string/hey</item> 380a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <item name="baz"><b>hey</b></item> 381a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </style>)"; 382ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 383cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 384ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo"); 385a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(style, NotNull()); 386a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(style->parent); 387a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(style->parent.value().name, Eq(make_value(test::ParseNameOrDie("style/fu")))); 388a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(style->entries, SizeIs(3)); 389cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 390a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(style->entries[0].key.name, Eq(make_value(test::ParseNameOrDie("attr/bar")))); 391a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(style->entries[1].key.name, Eq(make_value(test::ParseNameOrDie("attr/bat")))); 392a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(style->entries[2].key.name, Eq(make_value(test::ParseNameOrDie("attr/baz")))); 3936f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3946f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 395769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithShorthandParent) { 396a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<style name="foo" parent="com.app:Theme"/>)")); 397769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 398ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo"); 399a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(style, NotNull()); 400a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(style->parent); 401a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(style->parent.value().name, Eq(make_value(test::ParseNameOrDie("com.app:style/Theme")))); 402769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 403769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 40424aad163bc88cb10d2275385e9afc3de7f342d65Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithPackageAliasedParent) { 405a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 406a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <style xmlns:app="http://schemas.android.com/apk/res/android" 407a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski name="foo" parent="app:Theme"/>)"; 408ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 40924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 410ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo"); 411a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(style, NotNull()); 412a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(style->parent); 413a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(style->parent.value().name); 414a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(style->parent.value().name, Eq(make_value(test::ParseNameOrDie("android:style/Theme")))); 41524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski} 41624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 41724aad163bc88cb10d2275385e9afc3de7f342d65Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithPackageAliasedItems) { 418a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 419a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <style xmlns:app="http://schemas.android.com/apk/res/android" name="foo"> 420a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <item name="app:bar">0</item> 421a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </style>)"; 422ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 42324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 424ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo"); 425a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(style, NotNull()); 426a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(style->entries, SizeIs(1)); 427a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(style->entries[0].key.name, Eq(make_value(test::ParseNameOrDie("android:attr/bar")))); 42824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski} 42924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 430bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithInferredParent) { 431a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<style name="foo.bar"/>)")); 432bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 433ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo.bar"); 434a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(style, NotNull()); 435a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(style->parent); 436a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(style->parent.value().name, Eq(make_value(test::ParseNameOrDie("style/foo")))); 437ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(style->parent_inferred); 438bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski} 439bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 440a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam LesinskiTEST_F(ResourceParserTest, ParseStyleWithInferredParentOverridenByEmptyParentAttribute) { 441a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<style name="foo.bar" parent=""/>)")); 442bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 443ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo.bar"); 444a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(style, NotNull()); 445a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_FALSE(style->parent); 446ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_FALSE(style->parent_inferred); 447bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski} 448bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 44924b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam LesinskiTEST_F(ResourceParserTest, ParseStyleWithPrivateParentReference) { 450a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<style name="foo" parent="*android:style/bar" />)")); 45124b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski 452ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo"); 453a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(style, NotNull()); 454a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(style->parent); 455ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(style->parent.value().private_reference); 45624b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski} 45724b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski 4586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseAutoGeneratedIdReference) { 459a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<string name="foo">@+id/bar</string>)")); 460a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(test::GetValue<Id>(&table_, "id/bar"), NotNull()); 4616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 4626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseAttributesDeclareStyleable) { 464a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 465a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <declare-styleable name="foo"> 466a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="bar" /> 467a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="bat" format="string|reference"/> 468a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="baz"> 469a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <enum name="foo" value="1"/> 470a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </attr> 471a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </declare-styleable>)"; 472ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 473cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 474cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski Maybe<ResourceTable::SearchResult> result = 475ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski table_.FindResource(test::ParseNameOrDie("styleable/foo")); 476a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(result); 477a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(result.value().entry->symbol_status.state, Eq(SymbolState::kPublic)); 478cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 479ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = test::GetValue<Attribute>(&table_, "attr/bar"); 480a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(attr, NotNull()); 481ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(attr->IsWeak()); 482cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 483ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr = test::GetValue<Attribute>(&table_, "attr/bat"); 484a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(attr, NotNull()); 485ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(attr->IsWeak()); 486cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 487ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr = test::GetValue<Attribute>(&table_, "attr/baz"); 488a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(attr, NotNull()); 489ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(attr->IsWeak()); 490a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(attr->symbols, SizeIs(1)); 491cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 492a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(test::GetValue<Id>(&table_, "id/foo"), NotNull()); 493cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 494ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Styleable* styleable = test::GetValue<Styleable>(&table_, "styleable/foo"); 495a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(styleable, NotNull()); 496a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(styleable->entries, SizeIs(3)); 497cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 498a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(styleable->entries[0].name, Eq(make_value(test::ParseNameOrDie("attr/bar")))); 499a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(styleable->entries[1].name, Eq(make_value(test::ParseNameOrDie("attr/bat")))); 500a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(styleable->entries[2].name, Eq(make_value(test::ParseNameOrDie("attr/baz")))); 5016f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 5026f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 503467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam LesinskiTEST_F(ResourceParserTest, ParsePrivateAttributesDeclareStyleable) { 504a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 505a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <declare-styleable xmlns:privAndroid="http://schemas.android.com/apk/prv/res/android" 506a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski name="foo"> 507a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="*android:bar" /> 508a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="privAndroid:bat" /> 509a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </declare-styleable>)"; 510ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 511ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Styleable* styleable = test::GetValue<Styleable>(&table_, "styleable/foo"); 512a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(styleable, NotNull()); 513a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(styleable->entries, SizeIs(2)); 514cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 515ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(styleable->entries[0].private_reference); 516a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(styleable->entries[0].name); 517a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(styleable->entries[0].name.value().package, Eq("android")); 518cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 519ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(styleable->entries[1].private_reference); 520a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(styleable->entries[1].name); 521a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(styleable->entries[1].name.value().package, Eq("android")); 522467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 523467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 5246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseArray) { 525a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 526a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <array name="foo"> 527a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <item>@string/ref</item> 528a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <item>hey</item> 529a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <item>23</item> 530a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </array>)"; 531ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 5326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 533ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Array* array = test::GetValue<Array>(&table_, "array/foo"); 534a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(array, NotNull()); 535a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(array->items, SizeIs(3)); 5366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 537a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(ValueCast<Reference>(array->items[0].get()), NotNull()); 538a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(ValueCast<String>(array->items[1].get()), NotNull()); 539a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(ValueCast<BinaryPrimitive>(array->items[2].get()), NotNull()); 5406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 5416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 5429ba47d813075fcb05c5e1532c137c93b394631cbAdam LesinskiTEST_F(ResourceParserTest, ParseStringArray) { 543a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 544d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski <string-array name="foo"> 545d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski <item>"Werk"</item>" 546a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </string-array>)"; 547ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 548a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(test::GetValue<Array>(&table_, "array/foo"), NotNull()); 5499ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski} 5509ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 551d5fd76a2ff78400505ade936fc36e707d69ecf72Adam LesinskiTEST_F(ResourceParserTest, ParseArrayWithFormat) { 552a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 553d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski <array name="foo" format="string"> 554d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski <item>100</item> 555a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </array>)"; 556d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski ASSERT_TRUE(TestParse(input)); 557d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski 558d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski Array* array = test::GetValue<Array>(&table_, "array/foo"); 559a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(array, NotNull()); 560a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(array->items, SizeIs(1)); 561d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski 562d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski String* str = ValueCast<String>(array->items[0].get()); 563a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(str, NotNull()); 564a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(*str, StrValueEq("100")); 565d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski} 566d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski 567d5fd76a2ff78400505ade936fc36e707d69ecf72Adam LesinskiTEST_F(ResourceParserTest, ParseArrayWithBadFormat) { 568a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 569d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski <array name="foo" format="integer"> 570d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski <item>Hi</item> 571a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </array>)"; 572d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski ASSERT_FALSE(TestParse(input)); 573d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski} 574d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski 5756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParsePlural) { 576a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 577a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <plurals name="foo"> 578a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <item quantity="other">apples</item> 579a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <item quantity="one">apple</item> 580a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </plurals>)"; 581ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 5828f7c550e20a6edbc9af7bb48675afaf8bcb3783fAdam Lesinski 5838f7c550e20a6edbc9af7bb48675afaf8bcb3783fAdam Lesinski Plural* plural = test::GetValue<Plural>(&table_, "plurals/foo"); 584a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(plural, NotNull()); 585a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(plural->values[Plural::Zero], IsNull()); 586a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(plural->values[Plural::Two], IsNull()); 587a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(plural->values[Plural::Few], IsNull()); 588a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(plural->values[Plural::Many], IsNull()); 5898f7c550e20a6edbc9af7bb48675afaf8bcb3783fAdam Lesinski 590a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(plural->values[Plural::One], NotNull()); 591a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(plural->values[Plural::Other], NotNull()); 5926f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 5936f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 5946f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseCommentsWithResource) { 595a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 596a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <!--This is a comment--> 597a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <string name="foo">Hi</string>)"; 598ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 5996f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 600ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* value = test::GetValue<String>(&table_, "string/foo"); 601a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(value, NotNull()); 602a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(value->GetComment(), Eq("This is a comment")); 603e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski} 604e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 605e78fd617ec60139a973a01925fa7adad31febb39Adam LesinskiTEST_F(ResourceParserTest, DoNotCombineMultipleComments) { 606a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 607a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <!--One--> 608a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <!--Two--> 609a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <string name="foo">Hi</string>)"; 610e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 611ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 612e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 613ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* value = test::GetValue<String>(&table_, "string/foo"); 614a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(value, NotNull()); 615a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(value->GetComment(), Eq("Two")); 616e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski} 617e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 618e78fd617ec60139a973a01925fa7adad31febb39Adam LesinskiTEST_F(ResourceParserTest, IgnoreCommentBeforeEndTag) { 619a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 620a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <!--One--> 621a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <string name="foo"> 622a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski Hi 623a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <!--Two--> 624a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </string>)"; 625ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 6261ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 627ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* value = test::GetValue<String>(&table_, "string/foo"); 628a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(value, NotNull()); 629a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(value->GetComment(), Eq("One")); 6306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 6316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 632ca5638fd85098c3d0a699492751043545f75553aAdam LesinskiTEST_F(ResourceParserTest, ParseNestedComments) { 633cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // We only care about declare-styleable and enum/flag attributes because 634a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski // comments from those end up in R.java 635a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 636a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <declare-styleable name="foo"> 637a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <!-- The name of the bar --> 638a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="barName" format="string|reference" /> 639a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </declare-styleable> 640a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski 641a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="foo"> 642a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <!-- The very first --> 643a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <enum name="one" value="1" /> 644a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </attr>)"; 645ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 646ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 647ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Styleable* styleable = test::GetValue<Styleable>(&table_, "styleable/foo"); 648a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(styleable, NotNull()); 649a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(styleable->entries, SizeIs(1)); 650a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(styleable->entries[0].GetComment(), Eq("The name of the bar")); 651ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 652ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = test::GetValue<Attribute>(&table_, "attr/foo"); 653a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(attr, NotNull()); 654a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(attr->symbols, SizeIs(1)); 655a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(attr->symbols[0].symbol.GetComment(), Eq("The very first")); 656ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski} 657ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 658a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski// Declaring an ID as public should not require a separate definition (as an ID has no value). 6596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParsePublicIdAsDefinition) { 660a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<public type="id" name="foo"/>)")); 661a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(test::GetValue<Id>(&table_, "id/foo"), NotNull()); 6626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 6636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 664e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam LesinskiTEST_F(ResourceParserTest, KeepAllProducts) { 665a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 666a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <string name="foo" product="phone">hi</string> 667a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <string name="foo" product="no-sdcard">ho</string> 668a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <string name="bar" product="">wee</string> 669a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <string name="baz">woo</string> 670a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <string name="bit" product="phablet">hoot</string> 671a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <string name="bot" product="default">yes</string>)"; 672ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 673ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 674a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(test::GetValueForConfigAndProduct<String>(&table_, "string/foo", ConfigDescription::DefaultConfig(), "phone"), NotNull()); 675a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(test::GetValueForConfigAndProduct<String>(&table_, "string/foo",ConfigDescription::DefaultConfig(), "no-sdcard"), NotNull()); 676a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(test::GetValueForConfigAndProduct<String>(&table_, "string/bar", ConfigDescription::DefaultConfig(), ""), NotNull()); 677a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(test::GetValueForConfigAndProduct<String>(&table_, "string/baz", ConfigDescription::DefaultConfig(), ""), NotNull()); 678a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(test::GetValueForConfigAndProduct<String>(&table_, "string/bit", ConfigDescription::DefaultConfig(), "phablet"), NotNull()); 679a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(test::GetValueForConfigAndProduct<String>(&table_, "string/bot", ConfigDescription::DefaultConfig(), "default"), NotNull()); 6809ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski} 6819ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 68227afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam LesinskiTEST_F(ResourceParserTest, AutoIncrementIdsInPublicGroup) { 683a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 684a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <public-group type="attr" first-id="0x01010040"> 685a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <public name="foo" /> 686a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <public name="bar" /> 687a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </public-group>)"; 688ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 689cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 690a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski Maybe<ResourceTable::SearchResult> result = table_.FindResource(test::ParseNameOrDie("attr/foo")); 691a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(result); 692cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 693a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(result.value().package->id); 694a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(result.value().type->id); 695a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(result.value().entry->id); 696ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceId actual_id(result.value().package->id.value(), 697ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result.value().type->id.value(), 698ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result.value().entry->id.value()); 699a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(actual_id, Eq(ResourceId(0x01010040))); 700cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 701ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result = table_.FindResource(test::ParseNameOrDie("attr/bar")); 702a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(result); 703cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 704a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(result.value().package->id); 705a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(result.value().type->id); 706a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(result.value().entry->id); 707ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski actual_id = ResourceId(result.value().package->id.value(), 708ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result.value().type->id.value(), 709ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result.value().entry->id.value()); 710a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(actual_id, Eq(ResourceId(0x01010041))); 71127afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski} 71227afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski 713fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam LesinskiTEST_F(ResourceParserTest, ExternalTypesShouldOnlyBeReferences) { 714a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<item type="layout" name="foo">@layout/bar</item>)")); 715a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_FALSE(TestParse(R"(<item type="layout" name="bar">"this is a string"</item>)")); 716fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam Lesinski} 717fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam Lesinski 7184488f1c74a0f7df09f2b201f7caa228d729e8389Adam LesinskiTEST_F(ResourceParserTest, AddResourcesElementShouldAddEntryWithUndefinedSymbol) { 719a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<add-resource name="bar" type="string" />)")); 720a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski 721cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski Maybe<ResourceTable::SearchResult> result = 722ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski table_.FindResource(test::ParseNameOrDie("string/bar")); 723a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(result); 724cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const ResourceEntry* entry = result.value().entry; 725a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(entry, NotNull()); 726a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(entry->symbol_status.state, Eq(SymbolState::kUndefined)); 7274488f1c74a0f7df09f2b201f7caa228d729e8389Adam Lesinski EXPECT_TRUE(entry->symbol_status.allow_new); 728a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski} 729a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski 7307ff3ee19f4b831a526baf4b928d1ac172d070d82Adam LesinskiTEST_F(ResourceParserTest, ParseItemElementWithFormat) { 731a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<item name="foo" type="integer" format="float">0.3</item>)")); 7327ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski 733e597d68d33c76c2b830f5497ed4ba74c5193a056Adam Lesinski BinaryPrimitive* val = test::GetValue<BinaryPrimitive>(&table_, "integer/foo"); 734e597d68d33c76c2b830f5497ed4ba74c5193a056Adam Lesinski ASSERT_THAT(val, NotNull()); 735a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(val->value.dataType, Eq(Res_value::TYPE_FLOAT)); 736e597d68d33c76c2b830f5497ed4ba74c5193a056Adam Lesinski 737a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_FALSE(TestParse(R"(<item name="bar" type="integer" format="fraction">100</item>)")); 738e597d68d33c76c2b830f5497ed4ba74c5193a056Adam Lesinski} 739e597d68d33c76c2b830f5497ed4ba74c5193a056Adam Lesinski 740e597d68d33c76c2b830f5497ed4ba74c5193a056Adam Lesinski// An <item> without a format specifier accepts all types of values. 741e597d68d33c76c2b830f5497ed4ba74c5193a056Adam LesinskiTEST_F(ResourceParserTest, ParseItemElementWithoutFormat) { 742a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<item name="foo" type="integer">100%p</item>)")); 7437ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski 744e597d68d33c76c2b830f5497ed4ba74c5193a056Adam Lesinski BinaryPrimitive* val = test::GetValue<BinaryPrimitive>(&table_, "integer/foo"); 745e597d68d33c76c2b830f5497ed4ba74c5193a056Adam Lesinski ASSERT_THAT(val, NotNull()); 746a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(val->value.dataType, Eq(Res_value::TYPE_FRACTION)); 7477ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski} 7487ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski 74986d67df8d57b9537666f9b54a9ca563779a2288bAdam LesinskiTEST_F(ResourceParserTest, ParseConfigVaryingItem) { 750a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<item name="foo" type="configVarying">Hey</item>)")); 751a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(test::GetValue<String>(&table_, "configVarying/foo"), NotNull()); 75286d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski} 75386d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski 75486d67df8d57b9537666f9b54a9ca563779a2288bAdam LesinskiTEST_F(ResourceParserTest, ParseBagElement) { 755a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 756a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <bag name="bag" type="configVarying"> 757a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <item name="test">Hello!</item> 758a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </bag>)"; 75986d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski ASSERT_TRUE(TestParse(input)); 76086d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski 76186d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski Style* val = test::GetValue<Style>(&table_, "configVarying/bag"); 762a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(val, NotNull()); 763a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(val->entries, SizeIs(1)); 76486d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski 765a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(val->entries[0].key, Eq(Reference(test::ParseNameOrDie("attr/test")))); 766a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(ValueCast<RawString>(val->entries[0].value.get()), NotNull()); 76786d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski} 76886d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski 769bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam LesinskiTEST_F(ResourceParserTest, ParseElementWithNoValue) { 770bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski std::string input = R"( 771bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski <item type="drawable" format="reference" name="foo" /> 772bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski <string name="foo" />)"; 773bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski ASSERT_TRUE(TestParse(input)); 774bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski ASSERT_THAT(test::GetValue(&table_, "drawable/foo"), Pointee(ValueEq(Reference()))); 775bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski 776bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski String* str = test::GetValue<String>(&table_, "string/foo"); 777bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski ASSERT_THAT(str, NotNull()); 778a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(*str, StrValueEq("")); 779bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski} 780bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski 781b9f0548341f98a64a87fa35ef5f58d1daf973ca7Adam LesinskiTEST_F(ResourceParserTest, ParsePlatformIndependentNewline) { 782a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<string name="foo">%1$s %n %2$s</string>)")); 783b9f0548341f98a64a87fa35ef5f58d1daf973ca7Adam Lesinski} 784b9f0548341f98a64a87fa35ef5f58d1daf973ca7Adam Lesinski 785cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski} // namespace aapt 786