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" 25004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski#include "io/StringStream.h" 26d0f116b619feede0cfdb647157ce5ab4d50a1c46Adam Lesinski#include "test/Test.h" 27467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include "xml/XmlPullParser.h" 286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 29efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinskiusing ::aapt::io::StringInputStream; 30a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinskiusing ::aapt::test::StrValueEq; 31bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinskiusing ::aapt::test::ValueEq; 32a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinskiusing ::android::Res_value; 3371be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinskiusing ::android::ResTable_map; 34e597d68d33c76c2b830f5497ed4ba74c5193a056Adam Lesinskiusing ::android::StringPiece; 35e597d68d33c76c2b830f5497ed4ba74c5193a056Adam Lesinskiusing ::testing::Eq; 36a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinskiusing ::testing::IsEmpty; 37a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinskiusing ::testing::IsNull; 38e597d68d33c76c2b830f5497ed4ba74c5193a056Adam Lesinskiusing ::testing::NotNull; 39bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinskiusing ::testing::Pointee; 40a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinskiusing ::testing::SizeIs; 4171be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinskiusing ::testing::StrEq; 42d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski 436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskinamespace aapt { 446f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 45bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinskiconstexpr const char* kXmlPreamble = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; 466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 471ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiTEST(ResourceParserSingleTest, FailToParseWithNoRootResourcesElement) { 48ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); 49cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ResourceTable table; 50ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceParser parser(context->GetDiagnostics(), &table, Source{"test"}, {}); 51efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski 52efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski std::string input = kXmlPreamble; 53efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski input += R"(<attr name="foo"/>)"; 54efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski StringInputStream in(input); 55efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski xml::XmlPullParser xml_parser(&in); 56ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_FALSE(parser.Parse(&xml_parser)); 57769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 58769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 59ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiclass ResourceParserTest : public ::testing::Test { 60ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski public: 61bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski void SetUp() override { 62bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski context_ = test::ContextBuilder().Build(); 63bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski } 641ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 65ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ::testing::AssertionResult TestParse(const StringPiece& str) { 66ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return TestParse(str, ConfigDescription{}); 67cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 6852364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 69bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski ::testing::AssertionResult TestParse(const StringPiece& str, const ConfigDescription& config) { 70cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ResourceParserOptions parserOptions; 71bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski ResourceParser parser(context_->GetDiagnostics(), &table_, Source{"test"}, config, 72bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski parserOptions); 73efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski 74efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski std::string input = kXmlPreamble; 75efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski input += "<resources>\n"; 76efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski input.append(str.data(), str.size()); 77efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski input += "\n</resources>"; 78efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski StringInputStream in(input); 79efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski xml::XmlPullParser xmlParser(&in); 80ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (parser.Parse(&xmlParser)) { 81cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return ::testing::AssertionSuccess(); 826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 83cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return ::testing::AssertionFailure(); 84cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 85ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 86ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski protected: 87ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceTable table_; 88ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<IAaptContext> context_; 896f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}; 906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseQuotedString) { 92a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<string name="foo"> " hey there " </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(" hey there ")); 97a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(str->untranslatable_sections, IsEmpty()); 982eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski 992eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski ASSERT_TRUE(TestParse(R"(<string name="bar">Isn\'t it cool?</string>)")); 1002eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski str = test::GetValue<String>(&table_, "string/bar"); 1012eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski ASSERT_THAT(str, NotNull()); 1022eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski EXPECT_THAT(*str, StrValueEq("Isn't it cool?")); 1032eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski 1042eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski ASSERT_TRUE(TestParse(R"(<string name="baz">"Isn't it cool?"</string>)")); 1052eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski str = test::GetValue<String>(&table_, "string/baz"); 1062eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski ASSERT_THAT(str, NotNull()); 1072eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski EXPECT_THAT(*str, StrValueEq("Isn't it cool?")); 1086f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1096f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseEscapedString) { 111a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<string name="foo">\?123</string>)")); 1126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 113ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* str = test::GetValue<String>(&table_, "string/foo"); 114a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(str, NotNull()); 115a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(*str, StrValueEq("?123")); 116a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(str->untranslatable_sections, IsEmpty()); 117549e437e14f3b92f02bd3abc7d1cd68387132ce1Adam Lesinski 118549e437e14f3b92f02bd3abc7d1cd68387132ce1Adam Lesinski ASSERT_TRUE(TestParse(R"(<string name="bar">This isn\’t a bad string</string>)")); 119549e437e14f3b92f02bd3abc7d1cd68387132ce1Adam Lesinski str = test::GetValue<String>(&table_, "string/bar"); 120549e437e14f3b92f02bd3abc7d1cd68387132ce1Adam Lesinski ASSERT_THAT(str, NotNull()); 121549e437e14f3b92f02bd3abc7d1cd68387132ce1Adam Lesinski EXPECT_THAT(*str, StrValueEq("This isn’t a bad string")); 1226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1249f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam LesinskiTEST_F(ResourceParserTest, ParseFormattedString) { 125a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_FALSE(TestParse(R"(<string name="foo">%d %s</string>)")); 126a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<string name="foo">%1$d %2$s</string>)")); 1279f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski} 1289f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski 1298c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam LesinskiTEST_F(ResourceParserTest, ParseStyledString) { 130cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Use a surrogate pair unicode point so that we can verify that the span 1317542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski // indices use UTF-16 length and not UTF-8 length. 132cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string input = 1338049f3da712ea9c3154b57ce2276c97e749d1f2cAdam Lesinski "<string name=\"foo\">This is my aunt\u2019s <b>fickle <small>string</small></b></string>"; 134ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 1358c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 136ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski StyledString* str = test::GetValue<StyledString>(&table_, "string/foo"); 137a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(str, NotNull()); 1388c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 1392eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski EXPECT_THAT(str->value->value, StrEq("This is my aunt\u2019s fickle string")); 140a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(str->value->spans, SizeIs(2)); 141a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(str->untranslatable_sections, IsEmpty()); 1428c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 1432eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski EXPECT_THAT(*str->value->spans[0].name, StrEq("b")); 1442eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski EXPECT_THAT(str->value->spans[0].first_char, Eq(18u)); 145a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(str->value->spans[0].last_char, Eq(30u)); 1468049f3da712ea9c3154b57ce2276c97e749d1f2cAdam Lesinski 1472eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski EXPECT_THAT(*str->value->spans[1].name, StrEq("small")); 1482eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski EXPECT_THAT(str->value->spans[1].first_char, Eq(25u)); 149a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(str->value->spans[1].last_char, Eq(30u)); 1508c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski} 1518c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 1528c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam LesinskiTEST_F(ResourceParserTest, ParseStringWithWhitespace) { 153a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<string name="foo"> This is what I think </string>)")); 1548c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 155ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* str = test::GetValue<String>(&table_, "string/foo"); 156a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(str, NotNull()); 1572eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski EXPECT_THAT(*str->value, StrEq("This is what I think")); 158a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(str->untranslatable_sections, IsEmpty()); 1598c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 160a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<string name="foo2">" This is what I think "</string>)")); 1618c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 162ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski str = test::GetValue<String>(&table_, "string/foo2"); 163a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(str, NotNull()); 164a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(*str, StrValueEq(" This is what I think ")); 1658c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski} 1668c3f31f022f7e094fd227ef0c2987e0846cb3e43Adam Lesinski 1679beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan MitchellTEST_F(ResourceParserTest, ParseStringTruncateASCII) { 1689beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell // Tuncate leading and trailing whitespace 1699beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell EXPECT_TRUE(TestParse(R"(<string name="foo"> Hello </string>)")); 1709beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell 1719beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell String* str = test::GetValue<String>(&table_, "string/foo"); 1729beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell ASSERT_THAT(str, NotNull()); 1739beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell EXPECT_THAT(*str->value, StrEq("Hello")); 1749beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell EXPECT_THAT(str->untranslatable_sections, IsEmpty()); 1759beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell 1769beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell // AAPT does not truncate unicode whitespace 1779beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell EXPECT_TRUE(TestParse(R"(<string name="foo2">\u0020\Hello\u0020</string>)")); 1789beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell 1799beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell str = test::GetValue<String>(&table_, "string/foo2"); 1809beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell ASSERT_THAT(str, NotNull()); 1819beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell EXPECT_THAT(*str->value, StrEq(" Hello ")); 1829beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell EXPECT_THAT(str->untranslatable_sections, IsEmpty()); 1839beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell 1849beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell // Preserve non-ASCII whitespace including extended ASCII characters 1859beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell EXPECT_TRUE(TestParse(R"(<string name="foo3"> Hello </string>)")); 1869beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell 1879beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell str = test::GetValue<String>(&table_, "string/foo3"); 1889beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell ASSERT_THAT(str, NotNull()); 1899beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell EXPECT_THAT(*str->value, StrEq("\xC2\xA0Hello\xC2\xA0")); 1909beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell EXPECT_THAT(str->untranslatable_sections, IsEmpty()); 1919beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell 1929beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell EXPECT_TRUE(TestParse(R"(<string name="foo4">2005年6月1日</string>)")); 1939beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell 1949beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell str = test::GetValue<String>(&table_, "string/foo4"); 1959beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell ASSERT_THAT(str, NotNull()); 1969beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell EXPECT_THAT(*str->value, StrEq("2005年6月1日")); 1979beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell EXPECT_THAT(str->untranslatable_sections, IsEmpty()); 1989beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell} 1999beaa9cfe3bd8c7c59eed053ff6ca18951c34a86Ryan Mitchell 2002eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam LesinskiTEST_F(ResourceParserTest, ParseStyledStringWithWhitespace) { 2012eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski std::string input = R"(<string name="foo"> <b> My <i> favorite</i> string </b> </string>)"; 2022eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski ASSERT_TRUE(TestParse(input)); 2032eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski 2042eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski StyledString* str = test::GetValue<StyledString>(&table_, "string/foo"); 2052eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski ASSERT_THAT(str, NotNull()); 2062eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski EXPECT_THAT(str->value->value, StrEq(" My favorite string ")); 2072eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski EXPECT_THAT(str->untranslatable_sections, IsEmpty()); 2082eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski 2092eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski ASSERT_THAT(str->value->spans, SizeIs(2u)); 2102eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski EXPECT_THAT(*str->value->spans[0].name, StrEq("b")); 2112eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski EXPECT_THAT(str->value->spans[0].first_char, Eq(1u)); 2122eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski EXPECT_THAT(str->value->spans[0].last_char, Eq(21u)); 2132eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski 2142eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski EXPECT_THAT(*str->value->spans[1].name, StrEq("i")); 2152eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski EXPECT_THAT(str->value->spans[1].first_char, Eq(5u)); 2162eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski EXPECT_THAT(str->value->spans[1].last_char, Eq(13u)); 2172eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski} 2182eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski 2197542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam LesinskiTEST_F(ResourceParserTest, IgnoreXliffTagsOtherThanG) { 220a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 2217542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski <string name="foo" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> 222a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski There are <xliff:source>no</xliff:source> apples</string>)"; 2237542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski ASSERT_TRUE(TestParse(input)); 2247542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski 2257542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski String* str = test::GetValue<String>(&table_, "string/foo"); 226a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(str, NotNull()); 227a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(*str, StrValueEq("There are no apples")); 228a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(str->untranslatable_sections, IsEmpty()); 2297542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski} 2307542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski 2317542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam LesinskiTEST_F(ResourceParserTest, NestedXliffGTagsAreIllegal) { 232a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 2337542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski <string name="foo" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> 234a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski Do not <xliff:g>translate <xliff:g>this</xliff:g></xliff:g></string>)"; 2357542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski EXPECT_FALSE(TestParse(input)); 2367542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski} 2377542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski 2387542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam LesinskiTEST_F(ResourceParserTest, RecordUntranslateableXliffSectionsInString) { 239a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 2407542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski <string name="foo" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> 241a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski There are <xliff:g id="count">%1$d</xliff:g> apples</string>)"; 242ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 2431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 244ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* str = test::GetValue<String>(&table_, "string/foo"); 245a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(str, NotNull()); 246a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(*str, StrValueEq("There are %1$d apples")); 2477542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski 2482eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski ASSERT_THAT(str->untranslatable_sections, SizeIs(1)); 2492eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski EXPECT_THAT(str->untranslatable_sections[0].start, Eq(10u)); 250a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(str->untranslatable_sections[0].end, Eq(14u)); 2517542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski} 2527542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski 2537542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam LesinskiTEST_F(ResourceParserTest, RecordUntranslateableXliffSectionsInStyledString) { 254a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 2557542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski <string name="foo" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> 256a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski There are <b><xliff:g id="count">%1$d</xliff:g></b> apples</string>)"; 2577542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski ASSERT_TRUE(TestParse(input)); 2587542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski 2597542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski StyledString* str = test::GetValue<StyledString>(&table_, "string/foo"); 260a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(str, NotNull()); 2612eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski EXPECT_THAT(str->value->value, Eq(" There are %1$d apples")); 2622eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski 263a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(str->untranslatable_sections, SizeIs(1)); 2642eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski EXPECT_THAT(str->untranslatable_sections[0].start, Eq(11u)); 2652eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski EXPECT_THAT(str->untranslatable_sections[0].end, Eq(15u)); 2667542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski 2672eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski ASSERT_THAT(str->value->spans, SizeIs(1u)); 2682eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski EXPECT_THAT(*str->value->spans[0].name, StrEq("b")); 2692eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski EXPECT_THAT(str->value->spans[0].first_char, Eq(11u)); 2702eed52ecc0c2fa3e96530e4b5556eaa82f7c2dfcAdam Lesinski EXPECT_THAT(str->value->spans[0].last_char, Eq(14u)); 2711ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 2721ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 273dfa5e0705ff82f15e228ba076bc192893bcbe118Adam LesinskiTEST_F(ResourceParserTest, ParseNull) { 274a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"(<integer name="foo">@null</integer>)"; 275ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 276cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 277cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // The Android runtime treats a value of android::Res_value::TYPE_NULL as 278cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // a non-existing value, and this causes problems in styles when trying to 2797542162cb1b1fd2ce8a26dd7f3fedc8de8160d38Adam Lesinski // resolve an attribute. Null values must be encoded as android::Res_value::TYPE_REFERENCE 280cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // with a data value of 0. 281bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski Reference* null_ref = test::GetValue<Reference>(&table_, "integer/foo"); 282bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski ASSERT_THAT(null_ref, NotNull()); 283bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski EXPECT_FALSE(null_ref->name); 284bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski EXPECT_FALSE(null_ref->id); 285a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(null_ref->reference_type, Eq(Reference::Type::kResource)); 286dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski} 287dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski 288dfa5e0705ff82f15e228ba076bc192893bcbe118Adam LesinskiTEST_F(ResourceParserTest, ParseEmpty) { 289a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"(<integer name="foo">@empty</integer>)"; 290ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 291dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski 292bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski BinaryPrimitive* integer = test::GetValue<BinaryPrimitive>(&table_, "integer/foo"); 293a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(integer, NotNull()); 294a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(integer->value.dataType, Eq(Res_value::TYPE_NULL)); 295a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(integer->value.data, Eq(Res_value::DATA_NULL_EMPTY)); 296dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski} 297dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski 2986f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseAttr) { 299a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 300a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="foo" format="string"/> 301a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="bar"/>)"; 302ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 303cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 304ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = test::GetValue<Attribute>(&table_, "attr/foo"); 305a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(attr, NotNull()); 306a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(attr->type_mask, Eq(ResTable_map::TYPE_STRING)); 307cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 308ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr = test::GetValue<Attribute>(&table_, "attr/bar"); 309a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(attr, NotNull()); 310a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(attr->type_mask, Eq(ResTable_map::TYPE_ANY)); 311cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski} 312cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 313a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski// Old AAPT allowed attributes to be defined under different configurations, but ultimately 314a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski// stored them with the default configuration. Check that we have the same behavior. 315bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam LesinskiTEST_F(ResourceParserTest, ParseAttrAndDeclareStyleableUnderConfigButRecordAsNoConfig) { 316ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const ConfigDescription watch_config = test::ParseConfigOrDie("watch"); 317bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski std::string input = R"( 318bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski <attr name="foo" /> 319bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski <declare-styleable name="bar"> 320bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski <attr name="baz" /> 321bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski </declare-styleable>)"; 322ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input, watch_config)); 32352364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 324a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(test::GetValueForConfig<Attribute>(&table_, "attr/foo", watch_config), IsNull()); 325a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(test::GetValueForConfig<Attribute>(&table_, "attr/baz", watch_config), IsNull()); 326a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(test::GetValueForConfig<Styleable>(&table_, "styleable/bar", watch_config), IsNull()); 32752364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 328a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(test::GetValue<Attribute>(&table_, "attr/foo"), NotNull()); 329a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(test::GetValue<Attribute>(&table_, "attr/baz"), NotNull()); 330a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(test::GetValue<Styleable>(&table_, "styleable/bar"), NotNull()); 33152364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski} 33252364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 333a587065721053ad54e34f484868142407d59512dAdam LesinskiTEST_F(ResourceParserTest, ParseAttrWithMinMax) { 334a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"(<attr name="foo" min="10" max="23" format="integer"/>)"; 335ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 336a587065721053ad54e34f484868142407d59512dAdam Lesinski 337ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = test::GetValue<Attribute>(&table_, "attr/foo"); 338a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(attr, NotNull()); 339a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(attr->type_mask, Eq(ResTable_map::TYPE_INTEGER)); 340a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(attr->min_int, Eq(10)); 341a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(attr->max_int, Eq(23)); 342a587065721053ad54e34f484868142407d59512dAdam Lesinski} 343a587065721053ad54e34f484868142407d59512dAdam Lesinski 344a587065721053ad54e34f484868142407d59512dAdam LesinskiTEST_F(ResourceParserTest, FailParseAttrWithMinMaxButNotInteger) { 345a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_FALSE(TestParse(R"(<attr name="foo" min="10" max="23" format="string"/>)")); 346a587065721053ad54e34f484868142407d59512dAdam Lesinski} 347a587065721053ad54e34f484868142407d59512dAdam Lesinski 3486f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseUseAndDeclOfAttr) { 349a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 350a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <declare-styleable name="Styleable"> 351a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="foo" /> 352a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </declare-styleable> 353a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="foo" format="string"/>)"; 354ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 3556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 356ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = test::GetValue<Attribute>(&table_, "attr/foo"); 357a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(attr, NotNull()); 358a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(attr->type_mask, Eq(ResTable_map::TYPE_STRING)); 3596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseDoubleUseOfAttr) { 362a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 363a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <declare-styleable name="Theme"> 364a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="foo" /> 365a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </declare-styleable> 366a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <declare-styleable name="Window"> 367a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="foo" format="boolean"/> 368a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </declare-styleable>)"; 369ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 3706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 371ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = test::GetValue<Attribute>(&table_, "attr/foo"); 372a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(attr, NotNull()); 373a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(attr->type_mask, Eq(ResTable_map::TYPE_BOOLEAN)); 3746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3766f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseEnumAttr) { 377a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 378a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="foo"> 379a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <enum name="bar" value="0"/> 380a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <enum name="bat" value="1"/> 381a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <enum name="baz" value="2"/> 382a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </attr>)"; 383ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 3846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 385ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* enum_attr = test::GetValue<Attribute>(&table_, "attr/foo"); 386a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(enum_attr, NotNull()); 387a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(enum_attr->type_mask, Eq(ResTable_map::TYPE_ENUM)); 388a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(enum_attr->symbols, SizeIs(3)); 3896f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 390a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(enum_attr->symbols[0].symbol.name); 391a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(enum_attr->symbols[0].symbol.name.value().entry, Eq("bar")); 392a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(enum_attr->symbols[0].value, Eq(0u)); 3936f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 394a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(enum_attr->symbols[1].symbol.name); 395a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(enum_attr->symbols[1].symbol.name.value().entry, Eq("bat")); 396a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(enum_attr->symbols[1].value, Eq(1u)); 3976f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 398a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(enum_attr->symbols[2].symbol.name); 399a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(enum_attr->symbols[2].symbol.name.value().entry, Eq("baz")); 400a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(enum_attr->symbols[2].value, Eq(2u)); 4016f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 4026f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4036f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseFlagAttr) { 404a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 405a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="foo"> 406a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <flag name="bar" value="0"/> 407a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <flag name="bat" value="1"/> 408a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <flag name="baz" value="2"/> 409a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </attr>)"; 410ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 4116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 412ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* flag_attr = test::GetValue<Attribute>(&table_, "attr/foo"); 413a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(flag_attr, NotNull()); 414a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(flag_attr->type_mask, Eq(ResTable_map::TYPE_FLAGS)); 415a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(flag_attr->symbols, SizeIs(3)); 4166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 417a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(flag_attr->symbols[0].symbol.name); 418a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(flag_attr->symbols[0].symbol.name.value().entry, Eq("bar")); 419a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(flag_attr->symbols[0].value, Eq(0u)); 4206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 421a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(flag_attr->symbols[1].symbol.name); 422a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(flag_attr->symbols[1].symbol.name.value().entry, Eq("bat")); 423a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(flag_attr->symbols[1].value, Eq(1u)); 4246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 425a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(flag_attr->symbols[2].symbol.name); 426a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(flag_attr->symbols[2].symbol.name.value().entry, Eq("baz")); 427a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(flag_attr->symbols[2].value, Eq(2u)); 4286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 429ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<BinaryPrimitive> flag_value = 430ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceUtils::TryParseFlagSymbol(flag_attr, "baz|bat"); 431a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(flag_value, NotNull()); 432a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(flag_value->value.data, Eq(1u | 2u)); 4336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 4346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, FailToParseEnumAttrWithNonUniqueKeys) { 436a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 437a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="foo"> 438a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <enum name="bar" value="0"/> 439a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <enum name="bat" value="1"/> 440a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <enum name="bat" value="2"/> 441a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </attr>)"; 442ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_FALSE(TestParse(input)); 4436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 4446f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4456f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseStyle) { 446a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 447a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <style name="foo" parent="@style/fu"> 448a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <item name="bar">#ffffffff</item> 449a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <item name="bat">@string/hey</item> 450a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <item name="baz"><b>hey</b></item> 451a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </style>)"; 452ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 453cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 454ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo"); 455a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(style, NotNull()); 456a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(style->parent); 457a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(style->parent.value().name, Eq(make_value(test::ParseNameOrDie("style/fu")))); 458a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(style->entries, SizeIs(3)); 459cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 460a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(style->entries[0].key.name, Eq(make_value(test::ParseNameOrDie("attr/bar")))); 461a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(style->entries[1].key.name, Eq(make_value(test::ParseNameOrDie("attr/bat")))); 462a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(style->entries[2].key.name, Eq(make_value(test::ParseNameOrDie("attr/baz")))); 4636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 4646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 465769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithShorthandParent) { 466a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<style name="foo" parent="com.app:Theme"/>)")); 467769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 468ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo"); 469a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(style, NotNull()); 470a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(style->parent); 471a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(style->parent.value().name, Eq(make_value(test::ParseNameOrDie("com.app:style/Theme")))); 472769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 473769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 47424aad163bc88cb10d2275385e9afc3de7f342d65Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithPackageAliasedParent) { 475a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 476a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <style xmlns:app="http://schemas.android.com/apk/res/android" 477a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski name="foo" parent="app:Theme"/>)"; 478ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 47924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 480ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo"); 481a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(style, NotNull()); 482a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(style->parent); 483a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(style->parent.value().name); 484a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(style->parent.value().name, Eq(make_value(test::ParseNameOrDie("android:style/Theme")))); 48524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski} 48624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 48724aad163bc88cb10d2275385e9afc3de7f342d65Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithPackageAliasedItems) { 488a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 489a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <style xmlns:app="http://schemas.android.com/apk/res/android" name="foo"> 490a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <item name="app:bar">0</item> 491a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </style>)"; 492ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 49324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 494ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo"); 495a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(style, NotNull()); 496a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(style->entries, SizeIs(1)); 497a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(style->entries[0].key.name, Eq(make_value(test::ParseNameOrDie("android:attr/bar")))); 49824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski} 49924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 500bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithInferredParent) { 501a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<style name="foo.bar"/>)")); 502bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 503ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo.bar"); 504a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(style, NotNull()); 505a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(style->parent); 506a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(style->parent.value().name, Eq(make_value(test::ParseNameOrDie("style/foo")))); 507ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(style->parent_inferred); 508bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski} 509bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 510a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam LesinskiTEST_F(ResourceParserTest, ParseStyleWithInferredParentOverridenByEmptyParentAttribute) { 511a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<style name="foo.bar" parent=""/>)")); 512bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 513ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo.bar"); 514a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(style, NotNull()); 515a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_FALSE(style->parent); 516ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_FALSE(style->parent_inferred); 517bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski} 518bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 51924b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam LesinskiTEST_F(ResourceParserTest, ParseStyleWithPrivateParentReference) { 520a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<style name="foo" parent="*android:style/bar" />)")); 52124b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski 522ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style* style = test::GetValue<Style>(&table_, "style/foo"); 523a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(style, NotNull()); 524a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(style->parent); 525ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(style->parent.value().private_reference); 52624b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski} 52724b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski 5286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseAutoGeneratedIdReference) { 529a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<string name="foo">@+id/bar</string>)")); 530a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(test::GetValue<Id>(&table_, "id/bar"), NotNull()); 5316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 5326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 5336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseAttributesDeclareStyleable) { 534a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 535a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <declare-styleable name="foo"> 536a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="bar" /> 537a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="bat" format="string|reference"/> 538a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="baz"> 539a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <enum name="foo" value="1"/> 540a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </attr> 541a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </declare-styleable>)"; 542ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 543cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 544cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski Maybe<ResourceTable::SearchResult> result = 545ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski table_.FindResource(test::ParseNameOrDie("styleable/foo")); 546a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(result); 54771be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski EXPECT_THAT(result.value().entry->visibility.level, Eq(Visibility::Level::kPublic)); 548cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 549ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = test::GetValue<Attribute>(&table_, "attr/bar"); 550a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(attr, NotNull()); 551ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(attr->IsWeak()); 552cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 553ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr = test::GetValue<Attribute>(&table_, "attr/bat"); 554a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(attr, NotNull()); 555ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(attr->IsWeak()); 556cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 557ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr = test::GetValue<Attribute>(&table_, "attr/baz"); 558a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(attr, NotNull()); 559ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(attr->IsWeak()); 560a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(attr->symbols, SizeIs(1)); 561cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 562a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(test::GetValue<Id>(&table_, "id/foo"), NotNull()); 563cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 564ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Styleable* styleable = test::GetValue<Styleable>(&table_, "styleable/foo"); 565a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(styleable, NotNull()); 566a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(styleable->entries, SizeIs(3)); 567cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 568a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(styleable->entries[0].name, Eq(make_value(test::ParseNameOrDie("attr/bar")))); 569a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(styleable->entries[1].name, Eq(make_value(test::ParseNameOrDie("attr/bat")))); 570a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(styleable->entries[2].name, Eq(make_value(test::ParseNameOrDie("attr/baz")))); 5716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 5726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 573467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam LesinskiTEST_F(ResourceParserTest, ParsePrivateAttributesDeclareStyleable) { 574a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 575a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <declare-styleable xmlns:privAndroid="http://schemas.android.com/apk/prv/res/android" 576a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski name="foo"> 577a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="*android:bar" /> 578a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="privAndroid:bat" /> 579a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </declare-styleable>)"; 580ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 581ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Styleable* styleable = test::GetValue<Styleable>(&table_, "styleable/foo"); 582a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(styleable, NotNull()); 583a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(styleable->entries, SizeIs(2)); 584cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 585ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(styleable->entries[0].private_reference); 586a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(styleable->entries[0].name); 587a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(styleable->entries[0].name.value().package, Eq("android")); 588cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 589ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EXPECT_TRUE(styleable->entries[1].private_reference); 590a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(styleable->entries[1].name); 591a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(styleable->entries[1].name.value().package, Eq("android")); 592467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 593467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 5946f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseArray) { 595a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 596a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <array name="foo"> 597a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <item>@string/ref</item> 598a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <item>hey</item> 599a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <item>23</item> 600a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </array>)"; 601ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 6026f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 603ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Array* array = test::GetValue<Array>(&table_, "array/foo"); 604a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(array, NotNull()); 6054ffea040641d3b74ab04b6d2d3e78280bc893d5fAdam Lesinski ASSERT_THAT(array->elements, SizeIs(3)); 6066f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 6074ffea040641d3b74ab04b6d2d3e78280bc893d5fAdam Lesinski EXPECT_THAT(ValueCast<Reference>(array->elements[0].get()), NotNull()); 6084ffea040641d3b74ab04b6d2d3e78280bc893d5fAdam Lesinski EXPECT_THAT(ValueCast<String>(array->elements[1].get()), NotNull()); 6094ffea040641d3b74ab04b6d2d3e78280bc893d5fAdam Lesinski EXPECT_THAT(ValueCast<BinaryPrimitive>(array->elements[2].get()), NotNull()); 6106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 6116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 6129ba47d813075fcb05c5e1532c137c93b394631cbAdam LesinskiTEST_F(ResourceParserTest, ParseStringArray) { 613a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 614d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski <string-array name="foo"> 615d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski <item>"Werk"</item>" 616a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </string-array>)"; 617ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 618a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(test::GetValue<Array>(&table_, "array/foo"), NotNull()); 6199ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski} 6209ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 621d5fd76a2ff78400505ade936fc36e707d69ecf72Adam LesinskiTEST_F(ResourceParserTest, ParseArrayWithFormat) { 622a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 623d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski <array name="foo" format="string"> 624d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski <item>100</item> 625a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </array>)"; 626d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski ASSERT_TRUE(TestParse(input)); 627d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski 628d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski Array* array = test::GetValue<Array>(&table_, "array/foo"); 629a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(array, NotNull()); 6304ffea040641d3b74ab04b6d2d3e78280bc893d5fAdam Lesinski ASSERT_THAT(array->elements, SizeIs(1)); 631d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski 6324ffea040641d3b74ab04b6d2d3e78280bc893d5fAdam Lesinski String* str = ValueCast<String>(array->elements[0].get()); 633a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(str, NotNull()); 634a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(*str, StrValueEq("100")); 635d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski} 636d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski 637d5fd76a2ff78400505ade936fc36e707d69ecf72Adam LesinskiTEST_F(ResourceParserTest, ParseArrayWithBadFormat) { 638a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 639d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski <array name="foo" format="integer"> 640d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski <item>Hi</item> 641a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </array>)"; 642d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski ASSERT_FALSE(TestParse(input)); 643d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski} 644d5fd76a2ff78400505ade936fc36e707d69ecf72Adam Lesinski 6456f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParsePlural) { 646a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 647a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <plurals name="foo"> 648a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <item quantity="other">apples</item> 649a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <item quantity="one">apple</item> 650a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </plurals>)"; 651ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 6528f7c550e20a6edbc9af7bb48675afaf8bcb3783fAdam Lesinski 6538f7c550e20a6edbc9af7bb48675afaf8bcb3783fAdam Lesinski Plural* plural = test::GetValue<Plural>(&table_, "plurals/foo"); 654a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(plural, NotNull()); 655a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(plural->values[Plural::Zero], IsNull()); 656a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(plural->values[Plural::Two], IsNull()); 657a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(plural->values[Plural::Few], IsNull()); 658a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(plural->values[Plural::Many], IsNull()); 6598f7c550e20a6edbc9af7bb48675afaf8bcb3783fAdam Lesinski 660a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(plural->values[Plural::One], NotNull()); 661a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(plural->values[Plural::Other], NotNull()); 6626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 6636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 6646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseCommentsWithResource) { 665a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 666a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <!--This is a comment--> 667a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <string name="foo">Hi</string>)"; 668ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 6696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 670ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* value = test::GetValue<String>(&table_, "string/foo"); 671a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(value, NotNull()); 672a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(value->GetComment(), Eq("This is a comment")); 673e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski} 674e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 675e78fd617ec60139a973a01925fa7adad31febb39Adam LesinskiTEST_F(ResourceParserTest, DoNotCombineMultipleComments) { 676a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 677a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <!--One--> 678a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <!--Two--> 679a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <string name="foo">Hi</string>)"; 680e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 681ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 682e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 683ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* value = test::GetValue<String>(&table_, "string/foo"); 684a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(value, NotNull()); 685a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(value->GetComment(), Eq("Two")); 686e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski} 687e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 688e78fd617ec60139a973a01925fa7adad31febb39Adam LesinskiTEST_F(ResourceParserTest, IgnoreCommentBeforeEndTag) { 689a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 690a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <!--One--> 691a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <string name="foo"> 692a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski Hi 693a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <!--Two--> 694a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </string>)"; 695ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 6961ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 697ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski String* value = test::GetValue<String>(&table_, "string/foo"); 698a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(value, NotNull()); 699a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(value->GetComment(), Eq("One")); 7006f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 7016f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 702ca5638fd85098c3d0a699492751043545f75553aAdam LesinskiTEST_F(ResourceParserTest, ParseNestedComments) { 703cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // We only care about declare-styleable and enum/flag attributes because 704a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski // comments from those end up in R.java 705a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 706a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <declare-styleable name="foo"> 707a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <!-- The name of the bar --> 708a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="barName" format="string|reference" /> 709a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </declare-styleable> 710a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski 711a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <attr name="foo"> 712a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <!-- The very first --> 713a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <enum name="one" value="1" /> 714a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </attr>)"; 715ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 716ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 717ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Styleable* styleable = test::GetValue<Styleable>(&table_, "styleable/foo"); 718a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(styleable, NotNull()); 719a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(styleable->entries, SizeIs(1)); 720a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(styleable->entries[0].GetComment(), Eq("The name of the bar")); 721ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 722ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = test::GetValue<Attribute>(&table_, "attr/foo"); 723a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(attr, NotNull()); 724a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(attr->symbols, SizeIs(1)); 725a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(attr->symbols[0].symbol.GetComment(), Eq("The very first")); 726ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski} 727ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 728a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski// Declaring an ID as public should not require a separate definition (as an ID has no value). 7296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParsePublicIdAsDefinition) { 730a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<public type="id" name="foo"/>)")); 731a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(test::GetValue<Id>(&table_, "id/foo"), NotNull()); 7326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 7336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 734e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam LesinskiTEST_F(ResourceParserTest, KeepAllProducts) { 735a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 736a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <string name="foo" product="phone">hi</string> 737a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <string name="foo" product="no-sdcard">ho</string> 738a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <string name="bar" product="">wee</string> 739a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <string name="baz">woo</string> 740a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <string name="bit" product="phablet">hoot</string> 741a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <string name="bot" product="default">yes</string>)"; 742ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 743ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 744a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(test::GetValueForConfigAndProduct<String>(&table_, "string/foo", ConfigDescription::DefaultConfig(), "phone"), NotNull()); 745a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(test::GetValueForConfigAndProduct<String>(&table_, "string/foo",ConfigDescription::DefaultConfig(), "no-sdcard"), NotNull()); 746a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(test::GetValueForConfigAndProduct<String>(&table_, "string/bar", ConfigDescription::DefaultConfig(), ""), NotNull()); 747a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(test::GetValueForConfigAndProduct<String>(&table_, "string/baz", ConfigDescription::DefaultConfig(), ""), NotNull()); 748a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(test::GetValueForConfigAndProduct<String>(&table_, "string/bit", ConfigDescription::DefaultConfig(), "phablet"), NotNull()); 749a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(test::GetValueForConfigAndProduct<String>(&table_, "string/bot", ConfigDescription::DefaultConfig(), "default"), NotNull()); 7509ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski} 7519ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 75227afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam LesinskiTEST_F(ResourceParserTest, AutoIncrementIdsInPublicGroup) { 753a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 754a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <public-group type="attr" first-id="0x01010040"> 755a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <public name="foo" /> 756a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <public name="bar" /> 757a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </public-group>)"; 758ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ASSERT_TRUE(TestParse(input)); 759cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 760a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski Maybe<ResourceTable::SearchResult> result = table_.FindResource(test::ParseNameOrDie("attr/foo")); 761a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(result); 762cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 763a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(result.value().package->id); 764a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(result.value().type->id); 765a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(result.value().entry->id); 766ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceId actual_id(result.value().package->id.value(), 767ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result.value().type->id.value(), 768ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result.value().entry->id.value()); 769a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(actual_id, Eq(ResourceId(0x01010040))); 770cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 771ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result = table_.FindResource(test::ParseNameOrDie("attr/bar")); 772a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(result); 773cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 774a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(result.value().package->id); 775a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(result.value().type->id); 776a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(result.value().entry->id); 777ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski actual_id = ResourceId(result.value().package->id.value(), 778ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result.value().type->id.value(), 779ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski result.value().entry->id.value()); 780a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(actual_id, Eq(ResourceId(0x01010041))); 78127afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski} 78227afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski 78371be70507de9cb619b644e55eda1cc181e3f7e90Adam LesinskiTEST_F(ResourceParserTest, StrongestSymbolVisibilityWins) { 78471be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski std::string input = R"( 78571be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski <!-- private --> 78671be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski <java-symbol type="string" name="foo" /> 78771be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski <!-- public --> 78871be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski <public type="string" name="foo" id="0x01020000" /> 78971be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski <!-- private2 --> 79071be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski <java-symbol type="string" name="foo" />)"; 79171be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski ASSERT_TRUE(TestParse(input)); 79271be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski 79371be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski Maybe<ResourceTable::SearchResult> result = 79471be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski table_.FindResource(test::ParseNameOrDie("string/foo")); 79571be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski ASSERT_TRUE(result); 79671be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski 79771be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski ResourceEntry* entry = result.value().entry; 79871be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski ASSERT_THAT(entry, NotNull()); 79971be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski EXPECT_THAT(entry->visibility.level, Eq(Visibility::Level::kPublic)); 80071be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski EXPECT_THAT(entry->visibility.comment, StrEq("public")); 80171be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski} 80271be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski 803fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam LesinskiTEST_F(ResourceParserTest, ExternalTypesShouldOnlyBeReferences) { 804a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<item type="layout" name="foo">@layout/bar</item>)")); 805a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_FALSE(TestParse(R"(<item type="layout" name="bar">"this is a string"</item>)")); 806fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam Lesinski} 807fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam Lesinski 8084488f1c74a0f7df09f2b201f7caa228d729e8389Adam LesinskiTEST_F(ResourceParserTest, AddResourcesElementShouldAddEntryWithUndefinedSymbol) { 809a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<add-resource name="bar" type="string" />)")); 810a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski 811cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski Maybe<ResourceTable::SearchResult> result = 812ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski table_.FindResource(test::ParseNameOrDie("string/bar")); 813a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(result); 814cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski const ResourceEntry* entry = result.value().entry; 815a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(entry, NotNull()); 81671be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski EXPECT_THAT(entry->visibility.level, Eq(Visibility::Level::kUndefined)); 81771be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski EXPECT_TRUE(entry->allow_new); 818a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski} 819a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski 8207ff3ee19f4b831a526baf4b928d1ac172d070d82Adam LesinskiTEST_F(ResourceParserTest, ParseItemElementWithFormat) { 821a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<item name="foo" type="integer" format="float">0.3</item>)")); 8227ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski 823e597d68d33c76c2b830f5497ed4ba74c5193a056Adam Lesinski BinaryPrimitive* val = test::GetValue<BinaryPrimitive>(&table_, "integer/foo"); 824e597d68d33c76c2b830f5497ed4ba74c5193a056Adam Lesinski ASSERT_THAT(val, NotNull()); 825a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(val->value.dataType, Eq(Res_value::TYPE_FLOAT)); 826e597d68d33c76c2b830f5497ed4ba74c5193a056Adam Lesinski 827a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_FALSE(TestParse(R"(<item name="bar" type="integer" format="fraction">100</item>)")); 828e597d68d33c76c2b830f5497ed4ba74c5193a056Adam Lesinski} 829e597d68d33c76c2b830f5497ed4ba74c5193a056Adam Lesinski 830e597d68d33c76c2b830f5497ed4ba74c5193a056Adam Lesinski// An <item> without a format specifier accepts all types of values. 831e597d68d33c76c2b830f5497ed4ba74c5193a056Adam LesinskiTEST_F(ResourceParserTest, ParseItemElementWithoutFormat) { 832a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<item name="foo" type="integer">100%p</item>)")); 8337ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski 834e597d68d33c76c2b830f5497ed4ba74c5193a056Adam Lesinski BinaryPrimitive* val = test::GetValue<BinaryPrimitive>(&table_, "integer/foo"); 835e597d68d33c76c2b830f5497ed4ba74c5193a056Adam Lesinski ASSERT_THAT(val, NotNull()); 836a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(val->value.dataType, Eq(Res_value::TYPE_FRACTION)); 8377ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski} 8387ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski 83986d67df8d57b9537666f9b54a9ca563779a2288bAdam LesinskiTEST_F(ResourceParserTest, ParseConfigVaryingItem) { 840a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<item name="foo" type="configVarying">Hey</item>)")); 841a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(test::GetValue<String>(&table_, "configVarying/foo"), NotNull()); 84286d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski} 84386d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski 84486d67df8d57b9537666f9b54a9ca563779a2288bAdam LesinskiTEST_F(ResourceParserTest, ParseBagElement) { 845a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski std::string input = R"( 846a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <bag name="bag" type="configVarying"> 847a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski <item name="test">Hello!</item> 848a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski </bag>)"; 84986d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski ASSERT_TRUE(TestParse(input)); 85086d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski 85186d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski Style* val = test::GetValue<Style>(&table_, "configVarying/bag"); 852a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(val, NotNull()); 853a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(val->entries, SizeIs(1)); 85486d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski 855a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(val->entries[0].key, Eq(Reference(test::ParseNameOrDie("attr/test")))); 856a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(ValueCast<RawString>(val->entries[0].value.get()), NotNull()); 85786d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski} 85886d67df8d57b9537666f9b54a9ca563779a2288bAdam Lesinski 859bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam LesinskiTEST_F(ResourceParserTest, ParseElementWithNoValue) { 860bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski std::string input = R"( 861bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski <item type="drawable" format="reference" name="foo" /> 862bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski <string name="foo" />)"; 863bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski ASSERT_TRUE(TestParse(input)); 864bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski ASSERT_THAT(test::GetValue(&table_, "drawable/foo"), Pointee(ValueEq(Reference()))); 865bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski 866bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski String* str = test::GetValue<String>(&table_, "string/foo"); 867bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski ASSERT_THAT(str, NotNull()); 868a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_THAT(*str, StrValueEq("")); 869bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski} 870bab4ef56d7803f3a50ccfaca2729509338fcbb23Adam Lesinski 871b9f0548341f98a64a87fa35ef5f58d1daf973ca7Adam LesinskiTEST_F(ResourceParserTest, ParsePlatformIndependentNewline) { 872a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(TestParse(R"(<string name="foo">%1$s %n %2$s</string>)")); 873b9f0548341f98a64a87fa35ef5f58d1daf973ca7Adam Lesinski} 874b9f0548341f98a64a87fa35ef5f58d1daf973ca7Adam Lesinski 87546c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam LesinskiTEST_F(ResourceParserTest, ParseOverlayableTagWithSystemPolicy) { 87646c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski std::string input = R"( 87746c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski <overlayable policy="illegal_policy"> 87846c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski <item type="string" name="foo" /> 87946c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski </overlayable>)"; 88046c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski EXPECT_FALSE(TestParse(input)); 88146c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski 88246c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski input = R"( 88346c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski <overlayable policy="system"> 88446c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski <item name="foo" /> 88546c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski </overlayable>)"; 88646c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski EXPECT_FALSE(TestParse(input)); 88746c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski 88846c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski input = R"( 88946c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski <overlayable policy="system"> 89046c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski <item type="attr" /> 89146c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski </overlayable>)"; 89246c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski EXPECT_FALSE(TestParse(input)); 89346c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski 89446c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski input = R"( 89546c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski <overlayable policy="system"> 89646c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski <item type="bad_type" name="foo" /> 89746c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski </overlayable>)"; 89846c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski EXPECT_FALSE(TestParse(input)); 89946c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski 90046c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski input = R"(<overlayable policy="system" />)"; 90146c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski EXPECT_TRUE(TestParse(input)); 90246c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski 90346c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski input = R"(<overlayable />)"; 90446c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski EXPECT_TRUE(TestParse(input)); 90546c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski 90646c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski input = R"( 90746c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski <overlayable policy="system"> 90846c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski <item type="string" name="foo" /> 90946c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski <item type="dimen" name="foo" /> 91046c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski </overlayable>)"; 91146c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski ASSERT_TRUE(TestParse(input)); 91246c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski 91346c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski input = R"( 91446c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski <overlayable> 91546c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski <item type="string" name="bar" /> 91646c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski </overlayable>)"; 91746c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski ASSERT_TRUE(TestParse(input)); 91871be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski 91971be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski Maybe<ResourceTable::SearchResult> search_result = 92071be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski table_.FindResource(test::ParseNameOrDie("string/bar")); 92171be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski ASSERT_TRUE(search_result); 92271be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski ASSERT_THAT(search_result.value().entry, NotNull()); 92371be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski EXPECT_THAT(search_result.value().entry->visibility.level, Eq(Visibility::Level::kUndefined)); 92471be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski EXPECT_TRUE(search_result.value().entry->overlayable); 92571be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski} 92671be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski 92771be70507de9cb619b644e55eda1cc181e3f7e90Adam LesinskiTEST_F(ResourceParserTest, DuplicateOverlayableIsError) { 92871be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski std::string input = R"( 92971be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski <overlayable> 93071be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski <item type="string" name="foo" /> 93171be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski <item type="string" name="foo" /> 93271be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski </overlayable>)"; 93371be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski EXPECT_FALSE(TestParse(input)); 93446c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski} 93546c4d72bf0c30d3bc2071b84e2741e404c45e2b7Adam Lesinski 9369efbbef2e060cd5e05f5b652ba5c7aaf687f64d6yTEST_F(ResourceParserTest, ParseIdItem) { 9379efbbef2e060cd5e05f5b652ba5c7aaf687f64d6y std::string input = R"( 9389efbbef2e060cd5e05f5b652ba5c7aaf687f64d6y <item name="foo" type="id">@id/bar</item> 9399efbbef2e060cd5e05f5b652ba5c7aaf687f64d6y <item name="bar" type="id"/> 9409efbbef2e060cd5e05f5b652ba5c7aaf687f64d6y <item name="baz" type="id"></item>)"; 9419efbbef2e060cd5e05f5b652ba5c7aaf687f64d6y ASSERT_TRUE(TestParse(input)); 9429efbbef2e060cd5e05f5b652ba5c7aaf687f64d6y 9439efbbef2e060cd5e05f5b652ba5c7aaf687f64d6y ASSERT_THAT(test::GetValue<Reference>(&table_, "id/foo"), NotNull()); 9449efbbef2e060cd5e05f5b652ba5c7aaf687f64d6y ASSERT_THAT(test::GetValue<Id>(&table_, "id/bar"), NotNull()); 9459efbbef2e060cd5e05f5b652ba5c7aaf687f64d6y ASSERT_THAT(test::GetValue<Id>(&table_, "id/baz"), NotNull()); 9469efbbef2e060cd5e05f5b652ba5c7aaf687f64d6y 947eaf77e1d3a6ad4995ddd92a429802cffbf0f0209Ryan Mitchell input = R"( 948eaf77e1d3a6ad4995ddd92a429802cffbf0f0209Ryan Mitchell <id name="foo2">@id/bar</id> 949eaf77e1d3a6ad4995ddd92a429802cffbf0f0209Ryan Mitchell <id name="bar2"/> 950eaf77e1d3a6ad4995ddd92a429802cffbf0f0209Ryan Mitchell <id name="baz2"></id>)"; 951eaf77e1d3a6ad4995ddd92a429802cffbf0f0209Ryan Mitchell ASSERT_TRUE(TestParse(input)); 952eaf77e1d3a6ad4995ddd92a429802cffbf0f0209Ryan Mitchell 953eaf77e1d3a6ad4995ddd92a429802cffbf0f0209Ryan Mitchell ASSERT_THAT(test::GetValue<Reference>(&table_, "id/foo2"), NotNull()); 954eaf77e1d3a6ad4995ddd92a429802cffbf0f0209Ryan Mitchell ASSERT_THAT(test::GetValue<Id>(&table_, "id/bar2"), NotNull()); 955eaf77e1d3a6ad4995ddd92a429802cffbf0f0209Ryan Mitchell ASSERT_THAT(test::GetValue<Id>(&table_, "id/baz2"), NotNull()); 956eaf77e1d3a6ad4995ddd92a429802cffbf0f0209Ryan Mitchell 9579efbbef2e060cd5e05f5b652ba5c7aaf687f64d6y // Reject attribute references 958eaf77e1d3a6ad4995ddd92a429802cffbf0f0209Ryan Mitchell input = R"(<item name="foo3" type="id">?attr/bar"</item>)"; 9599efbbef2e060cd5e05f5b652ba5c7aaf687f64d6y ASSERT_FALSE(TestParse(input)); 9609efbbef2e060cd5e05f5b652ba5c7aaf687f64d6y 9619efbbef2e060cd5e05f5b652ba5c7aaf687f64d6y // Reject non-references 962eaf77e1d3a6ad4995ddd92a429802cffbf0f0209Ryan Mitchell input = R"(<item name="foo4" type="id">0x7f010001</item>)"; 9639efbbef2e060cd5e05f5b652ba5c7aaf687f64d6y ASSERT_FALSE(TestParse(input)); 964eaf77e1d3a6ad4995ddd92a429802cffbf0f0209Ryan Mitchell input = R"(<item name="foo5" type="id">@drawable/my_image</item>)"; 9659efbbef2e060cd5e05f5b652ba5c7aaf687f64d6y ASSERT_FALSE(TestParse(input)); 966eaf77e1d3a6ad4995ddd92a429802cffbf0f0209Ryan Mitchell input = R"(<item name="foo6" type="id"><string name="biz"></string></item>)"; 9679efbbef2e060cd5e05f5b652ba5c7aaf687f64d6y ASSERT_FALSE(TestParse(input)); 9689efbbef2e060cd5e05f5b652ba5c7aaf687f64d6y 9699efbbef2e060cd5e05f5b652ba5c7aaf687f64d6y // Ids that reference other resource ids cannot be public 970eaf77e1d3a6ad4995ddd92a429802cffbf0f0209Ryan Mitchell input = R"(<public name="foo7" type="id">@id/bar7</item>)"; 9719efbbef2e060cd5e05f5b652ba5c7aaf687f64d6y ASSERT_FALSE(TestParse(input)); 9729efbbef2e060cd5e05f5b652ba5c7aaf687f64d6y} 9739efbbef2e060cd5e05f5b652ba5c7aaf687f64d6y 974cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski} // namespace aapt 975