ResourceParser_test.cpp revision 52364f7ae31716d7827ea8f8566f4a28bd30a921
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" 186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include "ResourceTable.h" 191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "ResourceUtils.h" 206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include "ResourceValues.h" 211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "test/Context.h" 22467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include "xml/XmlPullParser.h" 236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <gtest/gtest.h> 256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <sstream> 266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <string> 276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskinamespace aapt { 296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiconstexpr const char* kXmlPreamble = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; 316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 321ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiTEST(ResourceParserSingleTest, FailToParseWithNoRootResourcesElement) { 331ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::unique_ptr<IAaptContext> context = test::ContextBuilder().build(); 341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::stringstream input(kXmlPreamble); 351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski input << "<attr name=\"foo\"/>" << std::endl; 361ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ResourceTable table; 371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ResourceParser parser(context->getDiagnostics(), &table, Source{ "test" }, {}); 38467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski xml::XmlPullParser xmlParser(input); 391ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ASSERT_FALSE(parser.parse(&xmlParser)); 40769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 41769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistruct ResourceParserTest : public ::testing::Test { 431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ResourceTable mTable; 441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::unique_ptr<IAaptContext> mContext; 451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski void SetUp() override { 471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski mContext = test::ContextBuilder().build(); 486f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 496f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 5052364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski ::testing::AssertionResult testParse(const StringPiece& str) { 5152364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski return testParse(str, ConfigDescription{}, {}); 5252364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski } 5352364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 5452364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski ::testing::AssertionResult testParse(const StringPiece& str, const ConfigDescription& config) { 5552364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski return testParse(str, config, {}); 5652364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski } 5752364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 589ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski ::testing::AssertionResult testParse(const StringPiece& str, 5952364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski std::initializer_list<std::u16string> products) { 6052364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski return testParse(str, {}, std::move(products)); 6152364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski } 6252364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 6352364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski ::testing::AssertionResult testParse(const StringPiece& str, const ConfigDescription& config, 6452364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski std::initializer_list<std::u16string> products) { 656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski std::stringstream input(kXmlPreamble); 6624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski input << "<resources>\n" << str << "\n</resources>" << std::endl; 679f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski ResourceParserOptions parserOptions; 687751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski parserOptions.products = products; 6952364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski ResourceParser parser(mContext->getDiagnostics(), &mTable, Source{ "test" }, config, 709f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski parserOptions); 71467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski xml::XmlPullParser xmlParser(input); 721ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (parser.parse(&xmlParser)) { 736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return ::testing::AssertionSuccess(); 746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return ::testing::AssertionFailure(); 766f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}; 786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseQuotedString) { 8024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<string name=\"foo\"> \" hey there \" </string>"; 816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 831ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski String* str = test::getValue<String>(&mTable, u"@string/foo"); 846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(nullptr, str); 856f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(std::u16string(u" hey there "), *str->value); 866f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 876f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 886f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseEscapedString) { 8924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<string name=\"foo\">\\?123</string>"; 906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 921ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski String* str = test::getValue<String>(&mTable, u"@string/foo"); 936f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(nullptr, str); 946f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(std::u16string(u"?123"), *str->value); 956f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 966f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 979f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam LesinskiTEST_F(ResourceParserTest, ParseFormattedString) { 989f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski std::string input = "<string name=\"foo\">%d %s</string>"; 999f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski ASSERT_FALSE(testParse(input)); 1009f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski 1019f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski input = "<string name=\"foo\">%1$d %2$s</string>"; 1029f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski ASSERT_TRUE(testParse(input)); 1039f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski} 1049f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski 1051ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiTEST_F(ResourceParserTest, IgnoreXliffTags) { 1061ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::string input = "<string name=\"foo\" \n" 1071ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski " xmlns:xliff=\"urn:oasis:names:tc:xliff:document:1.2\">\n" 1081ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski " There are <xliff:g id=\"count\">%1$d</xliff:g> apples</string>"; 1091ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ASSERT_TRUE(testParse(input)); 1101ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski String* str = test::getValue<String>(&mTable, u"@string/foo"); 1121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ASSERT_NE(nullptr, str); 1131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(StringPiece16(u"There are %1$d apples"), StringPiece16(*str->value)); 1141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 1151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 116dfa5e0705ff82f15e228ba076bc192893bcbe118Adam LesinskiTEST_F(ResourceParserTest, ParseNull) { 117dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski std::string input = "<integer name=\"foo\">@null</integer>"; 118dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski ASSERT_TRUE(testParse(input)); 119dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski 120dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski // The Android runtime treats a value of android::Res_value::TYPE_NULL as 121dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski // a non-existing value, and this causes problems in styles when trying to resolve 122dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski // an attribute. Null values must be encoded as android::Res_value::TYPE_REFERENCE 123dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski // with a data value of 0. 1241ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski BinaryPrimitive* integer = test::getValue<BinaryPrimitive>(&mTable, u"@integer/foo"); 125dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski ASSERT_NE(nullptr, integer); 126dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski EXPECT_EQ(uint16_t(android::Res_value::TYPE_REFERENCE), integer->value.dataType); 127dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski EXPECT_EQ(0u, integer->value.data); 128dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski} 129dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski 130dfa5e0705ff82f15e228ba076bc192893bcbe118Adam LesinskiTEST_F(ResourceParserTest, ParseEmpty) { 131dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski std::string input = "<integer name=\"foo\">@empty</integer>"; 132dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski ASSERT_TRUE(testParse(input)); 133dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski 1341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski BinaryPrimitive* integer = test::getValue<BinaryPrimitive>(&mTable, u"@integer/foo"); 135dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski ASSERT_NE(nullptr, integer); 136dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski EXPECT_EQ(uint16_t(android::Res_value::TYPE_NULL), integer->value.dataType); 137dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski EXPECT_EQ(uint32_t(android::Res_value::DATA_NULL_EMPTY), integer->value.data); 138dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski} 139dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski 1406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseAttr) { 14124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<attr name=\"foo\" format=\"string\"/>\n" 14224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "<attr name=\"bar\"/>"; 1436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 1446f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/foo"); 1461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ASSERT_NE(nullptr, attr); 1476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_STRING), attr->typeMask); 1486f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1491ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski attr = test::getValue<Attribute>(&mTable, u"@attr/bar"); 1501ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ASSERT_NE(nullptr, attr); 1516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_ANY), attr->typeMask); 1526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1536f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 15452364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski// Old AAPT allowed attributes to be defined under different configurations, but ultimately 15552364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski// stored them with the default configuration. Check that we have the same behavior. 15652364f7ae31716d7827ea8f8566f4a28bd30a921Adam LesinskiTEST_F(ResourceParserTest, ParseAttrAndDeclareStyleableUnderConfigButRecordAsNoConfig) { 15752364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski const ConfigDescription watchConfig = test::parseConfigOrDie("watch"); 15852364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski std::string input = R"EOF( 15952364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski <attr name="foo" /> 16052364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski <declare-styleable name="bar"> 16152364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski <attr name="baz" /> 16252364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski </declare-styleable>)EOF"; 16352364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski ASSERT_TRUE(testParse(input, watchConfig)); 16452364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 16552364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski EXPECT_EQ(nullptr, test::getValueForConfig<Attribute>(&mTable, u"@attr/foo", watchConfig)); 16652364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski EXPECT_EQ(nullptr, test::getValueForConfig<Attribute>(&mTable, u"@attr/baz", watchConfig)); 16752364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski EXPECT_EQ(nullptr, test::getValueForConfig<Styleable>(&mTable, u"@styleable/bar", watchConfig)); 16852364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 16952364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski EXPECT_NE(nullptr, test::getValue<Attribute>(&mTable, u"@attr/foo")); 17052364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski EXPECT_NE(nullptr, test::getValue<Attribute>(&mTable, u"@attr/baz")); 17152364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski EXPECT_NE(nullptr, test::getValue<Styleable>(&mTable, u"@styleable/bar")); 17252364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski} 17352364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 174a587065721053ad54e34f484868142407d59512dAdam LesinskiTEST_F(ResourceParserTest, ParseAttrWithMinMax) { 175a587065721053ad54e34f484868142407d59512dAdam Lesinski std::string input = "<attr name=\"foo\" min=\"10\" max=\"23\" format=\"integer\"/>"; 176a587065721053ad54e34f484868142407d59512dAdam Lesinski ASSERT_TRUE(testParse(input)); 177a587065721053ad54e34f484868142407d59512dAdam Lesinski 178a587065721053ad54e34f484868142407d59512dAdam Lesinski Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/foo"); 179a587065721053ad54e34f484868142407d59512dAdam Lesinski ASSERT_NE(nullptr, attr); 180a587065721053ad54e34f484868142407d59512dAdam Lesinski EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_INTEGER), attr->typeMask); 181a587065721053ad54e34f484868142407d59512dAdam Lesinski EXPECT_EQ(10, attr->minInt); 182a587065721053ad54e34f484868142407d59512dAdam Lesinski EXPECT_EQ(23, attr->maxInt); 183a587065721053ad54e34f484868142407d59512dAdam Lesinski} 184a587065721053ad54e34f484868142407d59512dAdam Lesinski 185a587065721053ad54e34f484868142407d59512dAdam LesinskiTEST_F(ResourceParserTest, FailParseAttrWithMinMaxButNotInteger) { 186a587065721053ad54e34f484868142407d59512dAdam Lesinski std::string input = "<attr name=\"foo\" min=\"10\" max=\"23\" format=\"string\"/>"; 187a587065721053ad54e34f484868142407d59512dAdam Lesinski ASSERT_FALSE(testParse(input)); 188a587065721053ad54e34f484868142407d59512dAdam Lesinski} 189a587065721053ad54e34f484868142407d59512dAdam Lesinski 1906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseUseAndDeclOfAttr) { 19124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<declare-styleable name=\"Styleable\">\n" 19224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <attr name=\"foo\" />\n" 19324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</declare-styleable>\n" 19424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "<attr name=\"foo\" format=\"string\"/>"; 1956f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 1966f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1971ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/foo"); 1986f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(nullptr, attr); 1996f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_STRING), attr->typeMask); 2006f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2016f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2026f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseDoubleUseOfAttr) { 20324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<declare-styleable name=\"Theme\">" 20424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <attr name=\"foo\" />\n" 20524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</declare-styleable>\n" 20624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "<declare-styleable name=\"Window\">\n" 20724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <attr name=\"foo\" format=\"boolean\"/>\n" 20824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</declare-styleable>"; 2096f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 2106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/foo"); 2126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(nullptr, attr); 2136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_BOOLEAN), attr->typeMask); 2146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseEnumAttr) { 21724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<attr name=\"foo\">\n" 21824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <enum name=\"bar\" value=\"0\"/>\n" 21924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <enum name=\"bat\" value=\"1\"/>\n" 22024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <enum name=\"baz\" value=\"2\"/>\n" 22124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</attr>"; 2226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 2236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2241ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Attribute* enumAttr = test::getValue<Attribute>(&mTable, u"@attr/foo"); 2256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(enumAttr, nullptr); 2266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(enumAttr->typeMask, android::ResTable_map::TYPE_ENUM); 2276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_EQ(enumAttr->symbols.size(), 3u); 2286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(enumAttr->symbols[0].symbol.name); 2301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(enumAttr->symbols[0].symbol.name.value().entry, u"bar"); 2316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(enumAttr->symbols[0].value, 0u); 2326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2331ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(enumAttr->symbols[1].symbol.name); 2341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(enumAttr->symbols[1].symbol.name.value().entry, u"bat"); 2356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(enumAttr->symbols[1].value, 1u); 2366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(enumAttr->symbols[2].symbol.name); 2381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(enumAttr->symbols[2].symbol.name.value().entry, u"baz"); 2396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(enumAttr->symbols[2].value, 2u); 2406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseFlagAttr) { 24324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<attr name=\"foo\">\n" 24424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <flag name=\"bar\" value=\"0\"/>\n" 24524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <flag name=\"bat\" value=\"1\"/>\n" 24624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <flag name=\"baz\" value=\"2\"/>\n" 24724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</attr>"; 2486f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 2496f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2501ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Attribute* flagAttr = test::getValue<Attribute>(&mTable, u"@attr/foo"); 25124b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski ASSERT_NE(nullptr, flagAttr); 2526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(flagAttr->typeMask, android::ResTable_map::TYPE_FLAGS); 2536f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_EQ(flagAttr->symbols.size(), 3u); 2546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(flagAttr->symbols[0].symbol.name); 2561ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(flagAttr->symbols[0].symbol.name.value().entry, u"bar"); 2576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(flagAttr->symbols[0].value, 0u); 2586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(flagAttr->symbols[1].symbol.name); 2601ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(flagAttr->symbols[1].symbol.name.value().entry, u"bat"); 2616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(flagAttr->symbols[1].value, 1u); 2626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2631ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(flagAttr->symbols[2].symbol.name); 2641ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(flagAttr->symbols[2].symbol.name.value().entry, u"baz"); 2656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(flagAttr->symbols[2].value, 2u); 2666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2671ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::unique_ptr<BinaryPrimitive> flagValue = ResourceUtils::tryParseFlagSymbol(flagAttr, 2681ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski u"baz|bat"); 26924b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski ASSERT_NE(nullptr, flagValue); 2706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(flagValue->value.data, 1u | 2u); 2716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, FailToParseEnumAttrWithNonUniqueKeys) { 27424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<attr name=\"foo\">\n" 27524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <enum name=\"bar\" value=\"0\"/>\n" 27624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <enum name=\"bat\" value=\"1\"/>\n" 27724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <enum name=\"bat\" value=\"2\"/>\n" 27824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</attr>"; 2796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_FALSE(testParse(input)); 2806f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseStyle) { 28324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<style name=\"foo\" parent=\"@style/fu\">\n" 28424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item name=\"bar\">#ffffffff</item>\n" 28524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item name=\"bat\">@string/hey</item>\n" 28624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item name=\"baz\"><b>hey</b></item>\n" 28724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</style>"; 2886f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 2896f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2901ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Style* style = test::getValue<Style>(&mTable, u"@style/foo"); 29124b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski ASSERT_NE(nullptr, style); 2921ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->parent); 2931ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->parent.value().name); 2941ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@style/fu"), style->parent.value().name.value()); 2951ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ASSERT_EQ(3u, style->entries.size()); 2961ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 2971ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->entries[0].key.name); 2981ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@attr/bar"), style->entries[0].key.name.value()); 2991ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 3001ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->entries[1].key.name); 3011ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@attr/bat"), style->entries[1].key.name.value()); 3021ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 3031ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->entries[2].key.name); 3041ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@attr/baz"), style->entries[2].key.name.value()); 3056f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3066f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 307769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithShorthandParent) { 30824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<style name=\"foo\" parent=\"com.app:Theme\"/>"; 309769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ASSERT_TRUE(testParse(input)); 310769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 3111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Style* style = test::getValue<Style>(&mTable, u"@style/foo"); 31224b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski ASSERT_NE(nullptr, style); 3131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->parent); 3141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->parent.value().name); 3151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@com.app:style/Theme"), style->parent.value().name.value()); 316769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 317769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 31824aad163bc88cb10d2275385e9afc3de7f342d65Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithPackageAliasedParent) { 31924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<style xmlns:app=\"http://schemas.android.com/apk/res/android\"\n" 32024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " name=\"foo\" parent=\"app:Theme\"/>"; 32124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski ASSERT_TRUE(testParse(input)); 32224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 3231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Style* style = test::getValue<Style>(&mTable, u"@style/foo"); 32424b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski ASSERT_NE(nullptr, style); 3251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->parent); 3261ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->parent.value().name); 3271ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@android:style/Theme"), style->parent.value().name.value()); 32824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski} 32924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 33024aad163bc88cb10d2275385e9afc3de7f342d65Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithPackageAliasedItems) { 33124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = 33224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "<style xmlns:app=\"http://schemas.android.com/apk/res/android\" name=\"foo\">\n" 33324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item name=\"app:bar\">0</item>\n" 33424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</style>"; 33524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski ASSERT_TRUE(testParse(input)); 33624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 3371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Style* style = test::getValue<Style>(&mTable, u"@style/foo"); 33824b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski ASSERT_NE(nullptr, style); 33924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski ASSERT_EQ(1u, style->entries.size()); 3401ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@android:attr/bar"), style->entries[0].key.name.value()); 34124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski} 34224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 343bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithInferredParent) { 344bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski std::string input = "<style name=\"foo.bar\"/>"; 345bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski ASSERT_TRUE(testParse(input)); 346bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 3471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Style* style = test::getValue<Style>(&mTable, u"@style/foo.bar"); 34824b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski ASSERT_NE(nullptr, style); 3491ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->parent); 3501ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->parent.value().name); 3511ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(style->parent.value().name.value(), test::parseNameOrDie(u"@style/foo")); 352bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski EXPECT_TRUE(style->parentInferred); 353bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski} 354bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 355bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithInferredParentOverridenByEmptyParentAttribute) { 356bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski std::string input = "<style name=\"foo.bar\" parent=\"\"/>"; 357bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski ASSERT_TRUE(testParse(input)); 358bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 3591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Style* style = test::getValue<Style>(&mTable, u"@style/foo.bar"); 36024b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski ASSERT_NE(nullptr, style); 3611ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_EXPECT_FALSE(style->parent); 362bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski EXPECT_FALSE(style->parentInferred); 363bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski} 364bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 36524b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam LesinskiTEST_F(ResourceParserTest, ParseStyleWithPrivateParentReference) { 36624b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski std::string input = R"EOF(<style name="foo" parent="*android:style/bar" />)EOF"; 36724b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski ASSERT_TRUE(testParse(input)); 36824b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski 36924b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski Style* style = test::getValue<Style>(&mTable, u"@style/foo"); 37024b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski ASSERT_NE(nullptr, style); 37124b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski AAPT_ASSERT_TRUE(style->parent); 37224b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski EXPECT_TRUE(style->parent.value().privateReference); 37324b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski} 37424b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski 3756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseAutoGeneratedIdReference) { 37624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<string name=\"foo\">@+id/bar</string>"; 3776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 3786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3791ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Id* id = test::getValue<Id>(&mTable, u"@id/bar"); 3806f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(id, nullptr); 3816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3836f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseAttributesDeclareStyleable) { 38424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<declare-styleable name=\"foo\">\n" 38524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <attr name=\"bar\" />\n" 38624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <attr name=\"bat\" format=\"string|reference\"/>\n" 3879ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski " <attr name=\"baz\">\n" 3889ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski " <enum name=\"foo\" value=\"1\"/>\n" 3899ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski " </attr>\n" 39024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</declare-styleable>"; 3916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 3926f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3939f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski Maybe<ResourceTable::SearchResult> result = 3949f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski mTable.findResource(test::parseNameOrDie(u"@styleable/foo")); 3959f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski AAPT_ASSERT_TRUE(result); 3969f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski EXPECT_EQ(SymbolState::kPublic, result.value().entry->symbolStatus.state); 3979f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski 3981ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/bar"); 3996f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(attr, nullptr); 4006f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_TRUE(attr->isWeak()); 4016f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4021ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski attr = test::getValue<Attribute>(&mTable, u"@attr/bat"); 4036f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(attr, nullptr); 4046f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_TRUE(attr->isWeak()); 4056f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4069ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski attr = test::getValue<Attribute>(&mTable, u"@attr/baz"); 4079ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski ASSERT_NE(attr, nullptr); 4089ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski EXPECT_TRUE(attr->isWeak()); 4099ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski EXPECT_EQ(1u, attr->symbols.size()); 4109ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 4119ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski EXPECT_NE(nullptr, test::getValue<Id>(&mTable, u"@id/foo")); 4129ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 4131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Styleable* styleable = test::getValue<Styleable>(&mTable, u"@styleable/foo"); 4146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(styleable, nullptr); 4159ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski ASSERT_EQ(3u, styleable->entries.size()); 4166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@attr/bar"), styleable->entries[0].name.value()); 4181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@attr/bat"), styleable->entries[1].name.value()); 4196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 4206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 421467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam LesinskiTEST_F(ResourceParserTest, ParsePrivateAttributesDeclareStyleable) { 422467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski std::string input = "<declare-styleable name=\"foo\" xmlns:privAndroid=\"http://schemas.android.com/apk/prv/res/android\">\n" 423467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski " <attr name=\"*android:bar\" />\n" 424467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski " <attr name=\"privAndroid:bat\" />\n" 425467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski "</declare-styleable>"; 426467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski ASSERT_TRUE(testParse(input)); 427467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski Styleable* styleable = test::getValue<Styleable>(&mTable, u"@styleable/foo"); 428467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski ASSERT_NE(nullptr, styleable); 429467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski ASSERT_EQ(2u, styleable->entries.size()); 430467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 431467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski EXPECT_TRUE(styleable->entries[0].privateReference); 432467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski AAPT_ASSERT_TRUE(styleable->entries[0].name); 433467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski EXPECT_EQ(std::u16string(u"android"), styleable->entries[0].name.value().package); 434467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 435467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski EXPECT_TRUE(styleable->entries[1].privateReference); 436467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski AAPT_ASSERT_TRUE(styleable->entries[1].name); 437467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski EXPECT_EQ(std::u16string(u"android"), styleable->entries[1].name.value().package); 438467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 439467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 4406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseArray) { 44124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<array name=\"foo\">\n" 44224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item>@string/ref</item>\n" 44324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item>hey</item>\n" 44424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item>23</item>\n" 44524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</array>"; 4466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 4476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Array* array = test::getValue<Array>(&mTable, u"@array/foo"); 4496f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(array, nullptr); 4506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_EQ(3u, array->items.size()); 4516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4521ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_NE(nullptr, valueCast<Reference>(array->items[0].get())); 4531ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_NE(nullptr, valueCast<String>(array->items[1].get())); 4541ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_NE(nullptr, valueCast<BinaryPrimitive>(array->items[2].get())); 4556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 4566f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4579ba47d813075fcb05c5e1532c137c93b394631cbAdam LesinskiTEST_F(ResourceParserTest, ParseStringArray) { 4589ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski std::string input = "<string-array name=\"foo\">\n" 4599ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski " <item>\"Werk\"</item>\n" 4609ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski "</string-array>\n"; 4619ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski ASSERT_TRUE(testParse(input)); 4629ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski EXPECT_NE(nullptr, test::getValue<Array>(&mTable, u"@array/foo")); 4639ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski} 4649ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 4656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParsePlural) { 46624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<plurals name=\"foo\">\n" 46724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item quantity=\"other\">apples</item>\n" 46824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item quantity=\"one\">apple</item>\n" 46924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</plurals>"; 4706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 4716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 4726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseCommentsWithResource) { 474e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski std::string input = "<!--This is a comment-->\n" 47524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "<string name=\"foo\">Hi</string>"; 4766f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 4776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 478e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski String* value = test::getValue<String>(&mTable, u"@string/foo"); 479e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski ASSERT_NE(nullptr, value); 480e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski EXPECT_EQ(value->getComment(), u"This is a comment"); 481e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski} 482e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 483e78fd617ec60139a973a01925fa7adad31febb39Adam LesinskiTEST_F(ResourceParserTest, DoNotCombineMultipleComments) { 484e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski std::string input = "<!--One-->\n" 485e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski "<!--Two-->\n" 486e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski "<string name=\"foo\">Hi</string>"; 487e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 488e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski ASSERT_TRUE(testParse(input)); 489e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 490e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski String* value = test::getValue<String>(&mTable, u"@string/foo"); 491e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski ASSERT_NE(nullptr, value); 492e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski EXPECT_EQ(value->getComment(), u"Two"); 493e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski} 494e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 495e78fd617ec60139a973a01925fa7adad31febb39Adam LesinskiTEST_F(ResourceParserTest, IgnoreCommentBeforeEndTag) { 496e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski std::string input = "<!--One-->\n" 497e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski "<string name=\"foo\">\n" 498e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski " Hi\n" 499e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski "<!--Two-->\n" 500e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski "</string>"; 501e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 502e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski ASSERT_TRUE(testParse(input)); 5031ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 504e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski String* value = test::getValue<String>(&mTable, u"@string/foo"); 505e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski ASSERT_NE(nullptr, value); 506e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski EXPECT_EQ(value->getComment(), u"One"); 5076f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 5086f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 509ca5638fd85098c3d0a699492751043545f75553aAdam LesinskiTEST_F(ResourceParserTest, ParseNestedComments) { 510ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski // We only care about declare-styleable and enum/flag attributes because comments 511ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski // from those end up in R.java 512ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski std::string input = R"EOF( 513ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <declare-styleable name="foo"> 514ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <!-- The name of the bar --> 515ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <attr name="barName" format="string|reference" /> 516ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski </declare-styleable> 517ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 518ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <attr name="foo"> 519ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <!-- The very first --> 520ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <enum name="one" value="1" /> 521ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski </attr>)EOF"; 522ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski ASSERT_TRUE(testParse(input)); 523ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 524ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski Styleable* styleable = test::getValue<Styleable>(&mTable, u"@styleable/foo"); 525ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski ASSERT_NE(nullptr, styleable); 526ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski ASSERT_EQ(1u, styleable->entries.size()); 527ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 528ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski EXPECT_EQ(StringPiece16(u"The name of the bar"), styleable->entries.front().getComment()); 529ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 530ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/foo"); 531ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski ASSERT_NE(nullptr, attr); 532ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski ASSERT_EQ(1u, attr->symbols.size()); 533ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 534ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski EXPECT_EQ(StringPiece16(u"The very first"), attr->symbols.front().symbol.getComment()); 535ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski} 536ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 5376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/* 5386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Declaring an ID as public should not require a separate definition 5396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * (as an ID has no value). 5406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 5416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParsePublicIdAsDefinition) { 54224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<public type=\"id\" name=\"foo\"/>"; 5436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 5446f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 5451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Id* id = test::getValue<Id>(&mTable, u"@id/foo"); 5466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(nullptr, id); 5476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 5486f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 5499ba47d813075fcb05c5e1532c137c93b394631cbAdam LesinskiTEST_F(ResourceParserTest, FilterProductsThatDontMatch) { 5507751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski std::string input = R"EOF( 5517751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski <string name="foo" product="phone">hi</string> 5527751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski <string name="foo" product="no-sdcard">ho</string> 5537751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski <string name="bar" product="">wee</string> 5547751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski <string name="baz">woo</string> 5557751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski <string name="bit" product="phablet">hoot</string> 5567751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski <string name="bot" product="default">yes</string> 5577751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski )EOF"; 5587751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski ASSERT_TRUE(testParse(input, { std::u16string(u"no-sdcard"), std::u16string(u"phablet") })); 5599ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 5609ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski String* fooStr = test::getValue<String>(&mTable, u"@string/foo"); 5619ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski ASSERT_NE(nullptr, fooStr); 5629ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski EXPECT_EQ(StringPiece16(u"ho"), *fooStr->value); 5639ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 5649ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski EXPECT_NE(nullptr, test::getValue<String>(&mTable, u"@string/bar")); 5659ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski EXPECT_NE(nullptr, test::getValue<String>(&mTable, u"@string/baz")); 5667751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski EXPECT_NE(nullptr, test::getValue<String>(&mTable, u"@string/bit")); 5677751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski EXPECT_NE(nullptr, test::getValue<String>(&mTable, u"@string/bot")); 5687751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski} 5697751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski 5707751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam LesinskiTEST_F(ResourceParserTest, FilterProductsThatBothMatchInOrder) { 5717751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski std::string input = R"EOF( 5727751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski <string name="foo" product="phone">phone</string> 5737751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski <string name="foo" product="default">default</string> 5747751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski )EOF"; 5757751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski ASSERT_TRUE(testParse(input, { std::u16string(u"phone") })); 5767751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski 5777751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski String* foo = test::getValue<String>(&mTable, u"@string/foo"); 5787751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski ASSERT_NE(nullptr, foo); 5797751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski EXPECT_EQ(std::u16string(u"phone"), *foo->value); 5809ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski} 5819ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 5829ba47d813075fcb05c5e1532c137c93b394631cbAdam LesinskiTEST_F(ResourceParserTest, FailWhenProductFilterStripsOutAllVersionsOfResource) { 5839ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski std::string input = "<string name=\"foo\" product=\"tablet\">hello</string>\n"; 5847751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski ASSERT_FALSE(testParse(input, { std::u16string(u"phone") })); 5859ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski} 5869ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 58727afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam LesinskiTEST_F(ResourceParserTest, AutoIncrementIdsInPublicGroup) { 58827afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski std::string input = R"EOF( 58927afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski <public-group type="attr" first-id="0x01010040"> 59027afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski <public name="foo" /> 59127afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski <public name="bar" /> 59227afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski </public-group>)EOF"; 59327afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski ASSERT_TRUE(testParse(input)); 59427afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski 59527afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski Maybe<ResourceTable::SearchResult> result = mTable.findResource( 59627afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski test::parseNameOrDie(u"@attr/foo")); 59727afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski AAPT_ASSERT_TRUE(result); 59827afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski 59927afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski AAPT_ASSERT_TRUE(result.value().package->id); 60027afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski AAPT_ASSERT_TRUE(result.value().type->id); 60127afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski AAPT_ASSERT_TRUE(result.value().entry->id); 60227afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski ResourceId actualId(result.value().package->id.value(), 60327afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski result.value().type->id.value(), 60427afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski result.value().entry->id.value()); 60527afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski EXPECT_EQ(ResourceId(0x01010040), actualId); 60627afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski 60727afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski result = mTable.findResource(test::parseNameOrDie(u"@attr/bar")); 60827afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski AAPT_ASSERT_TRUE(result); 60927afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski 61027afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski AAPT_ASSERT_TRUE(result.value().package->id); 61127afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski AAPT_ASSERT_TRUE(result.value().type->id); 61227afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski AAPT_ASSERT_TRUE(result.value().entry->id); 61327afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski actualId = ResourceId(result.value().package->id.value(), 61427afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski result.value().type->id.value(), 61527afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski result.value().entry->id.value()); 61627afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski EXPECT_EQ(ResourceId(0x01010041), actualId); 61727afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski} 61827afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski 619fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam LesinskiTEST_F(ResourceParserTest, ExternalTypesShouldOnlyBeReferences) { 620fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam Lesinski std::string input = R"EOF(<item type="layout" name="foo">@layout/bar</item>)EOF"; 621fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam Lesinski ASSERT_TRUE(testParse(input)); 622fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam Lesinski 623fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam Lesinski input = R"EOF(<item type="layout" name="bar">"this is a string"</item>)EOF"; 624fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam Lesinski ASSERT_FALSE(testParse(input)); 625fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam Lesinski} 626fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam Lesinski 627a6fe345be955368a13aea76aefb4db821aad11dfAdam LesinskiTEST_F(ResourceParserTest, AddResourcesElementShouldAddEntryWithUndefinedSymbol) { 628a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski std::string input = R"EOF(<add-resource name="bar" type="string" />)EOF"; 629a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski ASSERT_TRUE(testParse(input)); 630a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski 631a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski Maybe<ResourceTable::SearchResult> result = mTable.findResource( 632a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski test::parseNameOrDie(u"@string/bar")); 633a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski AAPT_ASSERT_TRUE(result); 634a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski const ResourceEntry* entry = result.value().entry; 635a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski ASSERT_NE(nullptr, entry); 636a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski EXPECT_EQ(SymbolState::kUndefined, entry->symbolStatus.state); 637a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski} 638a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski 6397ff3ee19f4b831a526baf4b928d1ac172d070d82Adam LesinskiTEST_F(ResourceParserTest, ParseItemElementWithFormat) { 6407ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski std::string input = R"EOF(<item name="foo" type="integer" format="float">0.3</item>)EOF"; 6417ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski ASSERT_TRUE(testParse(input)); 6427ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski 6437ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski BinaryPrimitive* val = test::getValue<BinaryPrimitive>(&mTable, u"@integer/foo"); 6447ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski ASSERT_NE(nullptr, val); 6457ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski 6467ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski EXPECT_EQ(uint32_t(android::Res_value::TYPE_FLOAT), val->value.dataType); 6477ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski} 6487ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski 6496f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} // namespace aapt 650