ResourceParser_test.cpp revision e4bb9eb5af5b0899dc0921d5580220b20e15bd5a
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) { 51e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski return testParse(str, ConfigDescription{}); 5252364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski } 5352364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 5452364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski ::testing::AssertionResult testParse(const StringPiece& str, const ConfigDescription& config) { 556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski std::stringstream input(kXmlPreamble); 5624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski input << "<resources>\n" << str << "\n</resources>" << std::endl; 579f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski ResourceParserOptions parserOptions; 5852364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski ResourceParser parser(mContext->getDiagnostics(), &mTable, Source{ "test" }, config, 599f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski parserOptions); 60467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski xml::XmlPullParser xmlParser(input); 611ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (parser.parse(&xmlParser)) { 626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return ::testing::AssertionSuccess(); 636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return ::testing::AssertionFailure(); 656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}; 676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseQuotedString) { 6924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<string name=\"foo\"> \" hey there \" </string>"; 706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 721ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski String* str = test::getValue<String>(&mTable, u"@string/foo"); 736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(nullptr, str); 746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(std::u16string(u" hey there "), *str->value); 756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 766f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseEscapedString) { 7824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<string name=\"foo\">\\?123</string>"; 796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 806f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 811ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski String* str = test::getValue<String>(&mTable, u"@string/foo"); 826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(nullptr, str); 836f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(std::u16string(u"?123"), *str->value); 846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 856f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 869f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam LesinskiTEST_F(ResourceParserTest, ParseFormattedString) { 879f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski std::string input = "<string name=\"foo\">%d %s</string>"; 889f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski ASSERT_FALSE(testParse(input)); 899f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski 909f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski input = "<string name=\"foo\">%1$d %2$s</string>"; 919f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski ASSERT_TRUE(testParse(input)); 929f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski} 939f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski 941ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiTEST_F(ResourceParserTest, IgnoreXliffTags) { 951ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::string input = "<string name=\"foo\" \n" 961ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski " xmlns:xliff=\"urn:oasis:names:tc:xliff:document:1.2\">\n" 971ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski " There are <xliff:g id=\"count\">%1$d</xliff:g> apples</string>"; 981ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ASSERT_TRUE(testParse(input)); 991ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1001ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski String* str = test::getValue<String>(&mTable, u"@string/foo"); 1011ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ASSERT_NE(nullptr, str); 1021ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(StringPiece16(u"There are %1$d apples"), StringPiece16(*str->value)); 1031ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 1041ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 105dfa5e0705ff82f15e228ba076bc192893bcbe118Adam LesinskiTEST_F(ResourceParserTest, ParseNull) { 106dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski std::string input = "<integer name=\"foo\">@null</integer>"; 107dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski ASSERT_TRUE(testParse(input)); 108dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski 109dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski // The Android runtime treats a value of android::Res_value::TYPE_NULL as 110dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski // a non-existing value, and this causes problems in styles when trying to resolve 111dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski // an attribute. Null values must be encoded as android::Res_value::TYPE_REFERENCE 112dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski // with a data value of 0. 1131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski BinaryPrimitive* integer = test::getValue<BinaryPrimitive>(&mTable, u"@integer/foo"); 114dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski ASSERT_NE(nullptr, integer); 115dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski EXPECT_EQ(uint16_t(android::Res_value::TYPE_REFERENCE), integer->value.dataType); 116dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski EXPECT_EQ(0u, integer->value.data); 117dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski} 118dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski 119dfa5e0705ff82f15e228ba076bc192893bcbe118Adam LesinskiTEST_F(ResourceParserTest, ParseEmpty) { 120dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski std::string input = "<integer name=\"foo\">@empty</integer>"; 121dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski ASSERT_TRUE(testParse(input)); 122dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski 1231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski BinaryPrimitive* integer = test::getValue<BinaryPrimitive>(&mTable, u"@integer/foo"); 124dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski ASSERT_NE(nullptr, integer); 125dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski EXPECT_EQ(uint16_t(android::Res_value::TYPE_NULL), integer->value.dataType); 126dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski EXPECT_EQ(uint32_t(android::Res_value::DATA_NULL_EMPTY), integer->value.data); 127dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski} 128dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski 1296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseAttr) { 13024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<attr name=\"foo\" format=\"string\"/>\n" 13124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "<attr name=\"bar\"/>"; 1326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 1336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/foo"); 1351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ASSERT_NE(nullptr, attr); 1366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_STRING), attr->typeMask); 1376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski attr = test::getValue<Attribute>(&mTable, u"@attr/bar"); 1391ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ASSERT_NE(nullptr, attr); 1406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_ANY), attr->typeMask); 1416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 14352364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski// Old AAPT allowed attributes to be defined under different configurations, but ultimately 14452364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski// stored them with the default configuration. Check that we have the same behavior. 14552364f7ae31716d7827ea8f8566f4a28bd30a921Adam LesinskiTEST_F(ResourceParserTest, ParseAttrAndDeclareStyleableUnderConfigButRecordAsNoConfig) { 14652364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski const ConfigDescription watchConfig = test::parseConfigOrDie("watch"); 14752364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski std::string input = R"EOF( 14852364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski <attr name="foo" /> 14952364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski <declare-styleable name="bar"> 15052364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski <attr name="baz" /> 15152364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski </declare-styleable>)EOF"; 15252364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski ASSERT_TRUE(testParse(input, watchConfig)); 15352364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 15452364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski EXPECT_EQ(nullptr, test::getValueForConfig<Attribute>(&mTable, u"@attr/foo", watchConfig)); 15552364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski EXPECT_EQ(nullptr, test::getValueForConfig<Attribute>(&mTable, u"@attr/baz", watchConfig)); 15652364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski EXPECT_EQ(nullptr, test::getValueForConfig<Styleable>(&mTable, u"@styleable/bar", watchConfig)); 15752364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 15852364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski EXPECT_NE(nullptr, test::getValue<Attribute>(&mTable, u"@attr/foo")); 15952364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski EXPECT_NE(nullptr, test::getValue<Attribute>(&mTable, u"@attr/baz")); 16052364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski EXPECT_NE(nullptr, test::getValue<Styleable>(&mTable, u"@styleable/bar")); 16152364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski} 16252364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 163a587065721053ad54e34f484868142407d59512dAdam LesinskiTEST_F(ResourceParserTest, ParseAttrWithMinMax) { 164a587065721053ad54e34f484868142407d59512dAdam Lesinski std::string input = "<attr name=\"foo\" min=\"10\" max=\"23\" format=\"integer\"/>"; 165a587065721053ad54e34f484868142407d59512dAdam Lesinski ASSERT_TRUE(testParse(input)); 166a587065721053ad54e34f484868142407d59512dAdam Lesinski 167a587065721053ad54e34f484868142407d59512dAdam Lesinski Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/foo"); 168a587065721053ad54e34f484868142407d59512dAdam Lesinski ASSERT_NE(nullptr, attr); 169a587065721053ad54e34f484868142407d59512dAdam Lesinski EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_INTEGER), attr->typeMask); 170a587065721053ad54e34f484868142407d59512dAdam Lesinski EXPECT_EQ(10, attr->minInt); 171a587065721053ad54e34f484868142407d59512dAdam Lesinski EXPECT_EQ(23, attr->maxInt); 172a587065721053ad54e34f484868142407d59512dAdam Lesinski} 173a587065721053ad54e34f484868142407d59512dAdam Lesinski 174a587065721053ad54e34f484868142407d59512dAdam LesinskiTEST_F(ResourceParserTest, FailParseAttrWithMinMaxButNotInteger) { 175a587065721053ad54e34f484868142407d59512dAdam Lesinski std::string input = "<attr name=\"foo\" min=\"10\" max=\"23\" format=\"string\"/>"; 176a587065721053ad54e34f484868142407d59512dAdam Lesinski ASSERT_FALSE(testParse(input)); 177a587065721053ad54e34f484868142407d59512dAdam Lesinski} 178a587065721053ad54e34f484868142407d59512dAdam Lesinski 1796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseUseAndDeclOfAttr) { 18024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<declare-styleable name=\"Styleable\">\n" 18124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <attr name=\"foo\" />\n" 18224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</declare-styleable>\n" 18324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "<attr name=\"foo\" format=\"string\"/>"; 1846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 1856f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1861ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/foo"); 1876f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(nullptr, attr); 1886f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_STRING), attr->typeMask); 1896f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseDoubleUseOfAttr) { 19224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<declare-styleable name=\"Theme\">" 19324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <attr name=\"foo\" />\n" 19424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</declare-styleable>\n" 19524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "<declare-styleable name=\"Window\">\n" 19624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <attr name=\"foo\" format=\"boolean\"/>\n" 19724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</declare-styleable>"; 1986f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 1996f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2001ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/foo"); 2016f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(nullptr, attr); 2026f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_BOOLEAN), attr->typeMask); 2036f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2046f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2056f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseEnumAttr) { 20624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<attr name=\"foo\">\n" 20724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <enum name=\"bar\" value=\"0\"/>\n" 20824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <enum name=\"bat\" value=\"1\"/>\n" 20924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <enum name=\"baz\" value=\"2\"/>\n" 21024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</attr>"; 2116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 2126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Attribute* enumAttr = test::getValue<Attribute>(&mTable, u"@attr/foo"); 2146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(enumAttr, nullptr); 2156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(enumAttr->typeMask, android::ResTable_map::TYPE_ENUM); 2166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_EQ(enumAttr->symbols.size(), 3u); 2176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(enumAttr->symbols[0].symbol.name); 2191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(enumAttr->symbols[0].symbol.name.value().entry, u"bar"); 2206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(enumAttr->symbols[0].value, 0u); 2216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(enumAttr->symbols[1].symbol.name); 2231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(enumAttr->symbols[1].symbol.name.value().entry, u"bat"); 2246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(enumAttr->symbols[1].value, 1u); 2256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2261ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(enumAttr->symbols[2].symbol.name); 2271ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(enumAttr->symbols[2].symbol.name.value().entry, u"baz"); 2286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(enumAttr->symbols[2].value, 2u); 2296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseFlagAttr) { 23224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<attr name=\"foo\">\n" 23324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <flag name=\"bar\" value=\"0\"/>\n" 23424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <flag name=\"bat\" value=\"1\"/>\n" 23524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <flag name=\"baz\" value=\"2\"/>\n" 23624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</attr>"; 2376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 2386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2391ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Attribute* flagAttr = test::getValue<Attribute>(&mTable, u"@attr/foo"); 24024b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski ASSERT_NE(nullptr, flagAttr); 2416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(flagAttr->typeMask, android::ResTable_map::TYPE_FLAGS); 2426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_EQ(flagAttr->symbols.size(), 3u); 2436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(flagAttr->symbols[0].symbol.name); 2451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(flagAttr->symbols[0].symbol.name.value().entry, u"bar"); 2466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(flagAttr->symbols[0].value, 0u); 2476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(flagAttr->symbols[1].symbol.name); 2491ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(flagAttr->symbols[1].symbol.name.value().entry, u"bat"); 2506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(flagAttr->symbols[1].value, 1u); 2516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2521ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(flagAttr->symbols[2].symbol.name); 2531ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(flagAttr->symbols[2].symbol.name.value().entry, u"baz"); 2546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(flagAttr->symbols[2].value, 2u); 2556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2561ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::unique_ptr<BinaryPrimitive> flagValue = ResourceUtils::tryParseFlagSymbol(flagAttr, 2571ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski u"baz|bat"); 25824b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski ASSERT_NE(nullptr, flagValue); 2596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(flagValue->value.data, 1u | 2u); 2606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, FailToParseEnumAttrWithNonUniqueKeys) { 26324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<attr name=\"foo\">\n" 26424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <enum name=\"bar\" value=\"0\"/>\n" 26524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <enum name=\"bat\" value=\"1\"/>\n" 26624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <enum name=\"bat\" value=\"2\"/>\n" 26724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</attr>"; 2686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_FALSE(testParse(input)); 2696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseStyle) { 27224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<style name=\"foo\" parent=\"@style/fu\">\n" 27324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item name=\"bar\">#ffffffff</item>\n" 27424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item name=\"bat\">@string/hey</item>\n" 27524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item name=\"baz\"><b>hey</b></item>\n" 27624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</style>"; 2776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 2786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2791ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Style* style = test::getValue<Style>(&mTable, u"@style/foo"); 28024b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski ASSERT_NE(nullptr, style); 2811ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->parent); 2821ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->parent.value().name); 2831ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@style/fu"), style->parent.value().name.value()); 2841ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ASSERT_EQ(3u, style->entries.size()); 2851ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 2861ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->entries[0].key.name); 2871ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@attr/bar"), style->entries[0].key.name.value()); 2881ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 2891ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->entries[1].key.name); 2901ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@attr/bat"), style->entries[1].key.name.value()); 2911ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 2921ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->entries[2].key.name); 2931ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@attr/baz"), style->entries[2].key.name.value()); 2946f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2956f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 296769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithShorthandParent) { 29724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<style name=\"foo\" parent=\"com.app:Theme\"/>"; 298769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ASSERT_TRUE(testParse(input)); 299769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 3001ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Style* style = test::getValue<Style>(&mTable, u"@style/foo"); 30124b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski ASSERT_NE(nullptr, style); 3021ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->parent); 3031ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->parent.value().name); 3041ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@com.app:style/Theme"), style->parent.value().name.value()); 305769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 306769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 30724aad163bc88cb10d2275385e9afc3de7f342d65Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithPackageAliasedParent) { 30824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<style xmlns:app=\"http://schemas.android.com/apk/res/android\"\n" 30924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " name=\"foo\" parent=\"app:Theme\"/>"; 31024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski ASSERT_TRUE(testParse(input)); 31124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 3121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Style* style = test::getValue<Style>(&mTable, u"@style/foo"); 31324b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski ASSERT_NE(nullptr, style); 3141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->parent); 3151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->parent.value().name); 3161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@android:style/Theme"), style->parent.value().name.value()); 31724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski} 31824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 31924aad163bc88cb10d2275385e9afc3de7f342d65Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithPackageAliasedItems) { 32024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = 32124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "<style xmlns:app=\"http://schemas.android.com/apk/res/android\" name=\"foo\">\n" 32224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item name=\"app:bar\">0</item>\n" 32324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</style>"; 32424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski ASSERT_TRUE(testParse(input)); 32524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 3261ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Style* style = test::getValue<Style>(&mTable, u"@style/foo"); 32724b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski ASSERT_NE(nullptr, style); 32824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski ASSERT_EQ(1u, style->entries.size()); 3291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@android:attr/bar"), style->entries[0].key.name.value()); 33024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski} 33124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 332bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithInferredParent) { 333bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski std::string input = "<style name=\"foo.bar\"/>"; 334bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski ASSERT_TRUE(testParse(input)); 335bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 3361ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Style* style = test::getValue<Style>(&mTable, u"@style/foo.bar"); 33724b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski ASSERT_NE(nullptr, style); 3381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->parent); 3391ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->parent.value().name); 3401ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(style->parent.value().name.value(), test::parseNameOrDie(u"@style/foo")); 341bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski EXPECT_TRUE(style->parentInferred); 342bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski} 343bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 344bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithInferredParentOverridenByEmptyParentAttribute) { 345bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski std::string input = "<style name=\"foo.bar\" parent=\"\"/>"; 346bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski ASSERT_TRUE(testParse(input)); 347bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 3481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Style* style = test::getValue<Style>(&mTable, u"@style/foo.bar"); 34924b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski ASSERT_NE(nullptr, style); 3501ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_EXPECT_FALSE(style->parent); 351bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski EXPECT_FALSE(style->parentInferred); 352bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski} 353bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 35424b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam LesinskiTEST_F(ResourceParserTest, ParseStyleWithPrivateParentReference) { 35524b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski std::string input = R"EOF(<style name="foo" parent="*android:style/bar" />)EOF"; 35624b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski ASSERT_TRUE(testParse(input)); 35724b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski 35824b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski Style* style = test::getValue<Style>(&mTable, u"@style/foo"); 35924b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski ASSERT_NE(nullptr, style); 36024b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski AAPT_ASSERT_TRUE(style->parent); 36124b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski EXPECT_TRUE(style->parent.value().privateReference); 36224b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski} 36324b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski 3646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseAutoGeneratedIdReference) { 36524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<string name=\"foo\">@+id/bar</string>"; 3666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 3676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3681ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Id* id = test::getValue<Id>(&mTable, u"@id/bar"); 3696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(id, nullptr); 3706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseAttributesDeclareStyleable) { 37324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<declare-styleable name=\"foo\">\n" 37424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <attr name=\"bar\" />\n" 37524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <attr name=\"bat\" format=\"string|reference\"/>\n" 3769ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski " <attr name=\"baz\">\n" 3779ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski " <enum name=\"foo\" value=\"1\"/>\n" 3789ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski " </attr>\n" 37924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</declare-styleable>"; 3806f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 3816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3829f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski Maybe<ResourceTable::SearchResult> result = 3839f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski mTable.findResource(test::parseNameOrDie(u"@styleable/foo")); 3849f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski AAPT_ASSERT_TRUE(result); 3859f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski EXPECT_EQ(SymbolState::kPublic, result.value().entry->symbolStatus.state); 3869f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski 3871ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/bar"); 3886f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(attr, nullptr); 3896f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_TRUE(attr->isWeak()); 3906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3911ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski attr = test::getValue<Attribute>(&mTable, u"@attr/bat"); 3926f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(attr, nullptr); 3936f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_TRUE(attr->isWeak()); 3946f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3959ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski attr = test::getValue<Attribute>(&mTable, u"@attr/baz"); 3969ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski ASSERT_NE(attr, nullptr); 3979ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski EXPECT_TRUE(attr->isWeak()); 3989ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski EXPECT_EQ(1u, attr->symbols.size()); 3999ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 4009ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski EXPECT_NE(nullptr, test::getValue<Id>(&mTable, u"@id/foo")); 4019ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 4021ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Styleable* styleable = test::getValue<Styleable>(&mTable, u"@styleable/foo"); 4036f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(styleable, nullptr); 4049ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski ASSERT_EQ(3u, styleable->entries.size()); 4056f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4061ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@attr/bar"), styleable->entries[0].name.value()); 4071ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@attr/bat"), styleable->entries[1].name.value()); 4086f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 4096f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 410467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam LesinskiTEST_F(ResourceParserTest, ParsePrivateAttributesDeclareStyleable) { 411467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski std::string input = "<declare-styleable name=\"foo\" xmlns:privAndroid=\"http://schemas.android.com/apk/prv/res/android\">\n" 412467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski " <attr name=\"*android:bar\" />\n" 413467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski " <attr name=\"privAndroid:bat\" />\n" 414467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski "</declare-styleable>"; 415467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski ASSERT_TRUE(testParse(input)); 416467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski Styleable* styleable = test::getValue<Styleable>(&mTable, u"@styleable/foo"); 417467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski ASSERT_NE(nullptr, styleable); 418467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski ASSERT_EQ(2u, styleable->entries.size()); 419467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 420467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski EXPECT_TRUE(styleable->entries[0].privateReference); 421467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski AAPT_ASSERT_TRUE(styleable->entries[0].name); 422467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski EXPECT_EQ(std::u16string(u"android"), styleable->entries[0].name.value().package); 423467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 424467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski EXPECT_TRUE(styleable->entries[1].privateReference); 425467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski AAPT_ASSERT_TRUE(styleable->entries[1].name); 426467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski EXPECT_EQ(std::u16string(u"android"), styleable->entries[1].name.value().package); 427467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 428467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 4296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseArray) { 43024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<array name=\"foo\">\n" 43124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item>@string/ref</item>\n" 43224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item>hey</item>\n" 43324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item>23</item>\n" 43424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</array>"; 4356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 4366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Array* array = test::getValue<Array>(&mTable, u"@array/foo"); 4386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(array, nullptr); 4396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_EQ(3u, array->items.size()); 4406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4411ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_NE(nullptr, valueCast<Reference>(array->items[0].get())); 4421ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_NE(nullptr, valueCast<String>(array->items[1].get())); 4431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_NE(nullptr, valueCast<BinaryPrimitive>(array->items[2].get())); 4446f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 4456f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4469ba47d813075fcb05c5e1532c137c93b394631cbAdam LesinskiTEST_F(ResourceParserTest, ParseStringArray) { 4479ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski std::string input = "<string-array name=\"foo\">\n" 4489ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski " <item>\"Werk\"</item>\n" 4499ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski "</string-array>\n"; 4509ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski ASSERT_TRUE(testParse(input)); 4519ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski EXPECT_NE(nullptr, test::getValue<Array>(&mTable, u"@array/foo")); 4529ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski} 4539ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 4546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParsePlural) { 45524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<plurals name=\"foo\">\n" 45624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item quantity=\"other\">apples</item>\n" 45724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item quantity=\"one\">apple</item>\n" 45824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</plurals>"; 4596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 4606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 4616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseCommentsWithResource) { 463e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski std::string input = "<!--This is a comment-->\n" 46424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "<string name=\"foo\">Hi</string>"; 4656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 4666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 467e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski String* value = test::getValue<String>(&mTable, u"@string/foo"); 468e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski ASSERT_NE(nullptr, value); 469e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski EXPECT_EQ(value->getComment(), u"This is a comment"); 470e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski} 471e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 472e78fd617ec60139a973a01925fa7adad31febb39Adam LesinskiTEST_F(ResourceParserTest, DoNotCombineMultipleComments) { 473e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski std::string input = "<!--One-->\n" 474e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski "<!--Two-->\n" 475e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski "<string name=\"foo\">Hi</string>"; 476e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 477e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski ASSERT_TRUE(testParse(input)); 478e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 479e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski String* value = test::getValue<String>(&mTable, u"@string/foo"); 480e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski ASSERT_NE(nullptr, value); 481e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski EXPECT_EQ(value->getComment(), u"Two"); 482e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski} 483e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 484e78fd617ec60139a973a01925fa7adad31febb39Adam LesinskiTEST_F(ResourceParserTest, IgnoreCommentBeforeEndTag) { 485e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski std::string input = "<!--One-->\n" 486e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski "<string name=\"foo\">\n" 487e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski " Hi\n" 488e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski "<!--Two-->\n" 489e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski "</string>"; 490e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 491e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski ASSERT_TRUE(testParse(input)); 4921ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 493e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski String* value = test::getValue<String>(&mTable, u"@string/foo"); 494e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski ASSERT_NE(nullptr, value); 495e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski EXPECT_EQ(value->getComment(), u"One"); 4966f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 4976f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 498ca5638fd85098c3d0a699492751043545f75553aAdam LesinskiTEST_F(ResourceParserTest, ParseNestedComments) { 499ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski // We only care about declare-styleable and enum/flag attributes because comments 500ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski // from those end up in R.java 501ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski std::string input = R"EOF( 502ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <declare-styleable name="foo"> 503ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <!-- The name of the bar --> 504ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <attr name="barName" format="string|reference" /> 505ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski </declare-styleable> 506ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 507ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <attr name="foo"> 508ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <!-- The very first --> 509ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <enum name="one" value="1" /> 510ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski </attr>)EOF"; 511ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski ASSERT_TRUE(testParse(input)); 512ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 513ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski Styleable* styleable = test::getValue<Styleable>(&mTable, u"@styleable/foo"); 514ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski ASSERT_NE(nullptr, styleable); 515ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski ASSERT_EQ(1u, styleable->entries.size()); 516ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 517ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski EXPECT_EQ(StringPiece16(u"The name of the bar"), styleable->entries.front().getComment()); 518ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 519ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/foo"); 520ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski ASSERT_NE(nullptr, attr); 521ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski ASSERT_EQ(1u, attr->symbols.size()); 522ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 523ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski EXPECT_EQ(StringPiece16(u"The very first"), attr->symbols.front().symbol.getComment()); 524ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski} 525ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 5266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/* 5276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Declaring an ID as public should not require a separate definition 5286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * (as an ID has no value). 5296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 5306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParsePublicIdAsDefinition) { 53124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<public type=\"id\" name=\"foo\"/>"; 5326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 5336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 5341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Id* id = test::getValue<Id>(&mTable, u"@id/foo"); 5356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(nullptr, id); 5366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 5376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 538e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam LesinskiTEST_F(ResourceParserTest, KeepAllProducts) { 5397751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski std::string input = R"EOF( 5407751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski <string name="foo" product="phone">hi</string> 5417751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski <string name="foo" product="no-sdcard">ho</string> 5427751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski <string name="bar" product="">wee</string> 5437751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski <string name="baz">woo</string> 5447751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski <string name="bit" product="phablet">hoot</string> 5457751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski <string name="bot" product="default">yes</string> 5467751afc796842bbb24bfbb19bd0fee4a7b7c8a4eAdam Lesinski )EOF"; 547e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ASSERT_TRUE(testParse(input)); 5489ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 549e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski EXPECT_NE(nullptr, test::getValueForConfigAndProduct<String>(&mTable, u"@string/foo", 550e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ConfigDescription::defaultConfig(), 551e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski "phone")); 552e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski EXPECT_NE(nullptr, test::getValueForConfigAndProduct<String>(&mTable, u"@string/foo", 553e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ConfigDescription::defaultConfig(), 554e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski "no-sdcard")); 555e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski EXPECT_NE(nullptr, test::getValueForConfigAndProduct<String>(&mTable, u"@string/bar", 556e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ConfigDescription::defaultConfig(), 557e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski "")); 558e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski EXPECT_NE(nullptr, test::getValueForConfigAndProduct<String>(&mTable, u"@string/baz", 559e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ConfigDescription::defaultConfig(), 560e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski "")); 561e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski EXPECT_NE(nullptr, test::getValueForConfigAndProduct<String>(&mTable, u"@string/bit", 562e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ConfigDescription::defaultConfig(), 563e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski "phablet")); 564e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski EXPECT_NE(nullptr, test::getValueForConfigAndProduct<String>(&mTable, u"@string/bot", 565e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ConfigDescription::defaultConfig(), 566e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski "default")); 5679ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski} 5689ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 56927afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam LesinskiTEST_F(ResourceParserTest, AutoIncrementIdsInPublicGroup) { 57027afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski std::string input = R"EOF( 57127afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski <public-group type="attr" first-id="0x01010040"> 57227afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski <public name="foo" /> 57327afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski <public name="bar" /> 57427afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski </public-group>)EOF"; 57527afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski ASSERT_TRUE(testParse(input)); 57627afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski 57727afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski Maybe<ResourceTable::SearchResult> result = mTable.findResource( 57827afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski test::parseNameOrDie(u"@attr/foo")); 57927afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski AAPT_ASSERT_TRUE(result); 58027afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski 58127afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski AAPT_ASSERT_TRUE(result.value().package->id); 58227afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski AAPT_ASSERT_TRUE(result.value().type->id); 58327afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski AAPT_ASSERT_TRUE(result.value().entry->id); 58427afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski ResourceId actualId(result.value().package->id.value(), 58527afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski result.value().type->id.value(), 58627afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski result.value().entry->id.value()); 58727afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski EXPECT_EQ(ResourceId(0x01010040), actualId); 58827afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski 58927afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski result = mTable.findResource(test::parseNameOrDie(u"@attr/bar")); 59027afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski AAPT_ASSERT_TRUE(result); 59127afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski 59227afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski AAPT_ASSERT_TRUE(result.value().package->id); 59327afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski AAPT_ASSERT_TRUE(result.value().type->id); 59427afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski AAPT_ASSERT_TRUE(result.value().entry->id); 59527afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski actualId = ResourceId(result.value().package->id.value(), 59627afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski result.value().type->id.value(), 59727afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski result.value().entry->id.value()); 59827afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski EXPECT_EQ(ResourceId(0x01010041), actualId); 59927afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski} 60027afb9e8894b512b21fcca6ce142f40f1ee16cbbAdam Lesinski 601fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam LesinskiTEST_F(ResourceParserTest, ExternalTypesShouldOnlyBeReferences) { 602fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam Lesinski std::string input = R"EOF(<item type="layout" name="foo">@layout/bar</item>)EOF"; 603fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam Lesinski ASSERT_TRUE(testParse(input)); 604fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam Lesinski 605fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam Lesinski input = R"EOF(<item type="layout" name="bar">"this is a string"</item>)EOF"; 606fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam Lesinski ASSERT_FALSE(testParse(input)); 607fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam Lesinski} 608fa10505ceaf9d4c41b76bb1b32f257926e96e441Adam Lesinski 609a6fe345be955368a13aea76aefb4db821aad11dfAdam LesinskiTEST_F(ResourceParserTest, AddResourcesElementShouldAddEntryWithUndefinedSymbol) { 610a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski std::string input = R"EOF(<add-resource name="bar" type="string" />)EOF"; 611a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski ASSERT_TRUE(testParse(input)); 612a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski 613a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski Maybe<ResourceTable::SearchResult> result = mTable.findResource( 614a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski test::parseNameOrDie(u"@string/bar")); 615a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski AAPT_ASSERT_TRUE(result); 616a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski const ResourceEntry* entry = result.value().entry; 617a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski ASSERT_NE(nullptr, entry); 618a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski EXPECT_EQ(SymbolState::kUndefined, entry->symbolStatus.state); 619a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski} 620a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski 6217ff3ee19f4b831a526baf4b928d1ac172d070d82Adam LesinskiTEST_F(ResourceParserTest, ParseItemElementWithFormat) { 6227ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski std::string input = R"EOF(<item name="foo" type="integer" format="float">0.3</item>)EOF"; 6237ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski ASSERT_TRUE(testParse(input)); 6247ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski 6257ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski BinaryPrimitive* val = test::getValue<BinaryPrimitive>(&mTable, u"@integer/foo"); 6267ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski ASSERT_NE(nullptr, val); 6277ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski 6287ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski EXPECT_EQ(uint32_t(android::Res_value::TYPE_FLOAT), val->value.dataType); 6297ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski} 6307ff3ee19f4b831a526baf4b928d1ac172d070d82Adam Lesinski 6316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} // namespace aapt 632