ResourceParser_test.cpp revision 9f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4
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 "XmlPullParser.h" 221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "test/Context.h" 246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <gtest/gtest.h> 266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <sstream> 276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <string> 286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskinamespace aapt { 306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiconstexpr const char* kXmlPreamble = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; 326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 331ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiTEST(ResourceParserSingleTest, FailToParseWithNoRootResourcesElement) { 341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::unique_ptr<IAaptContext> context = test::ContextBuilder().build(); 351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::stringstream input(kXmlPreamble); 361ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski input << "<attr name=\"foo\"/>" << std::endl; 371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ResourceTable table; 381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ResourceParser parser(context->getDiagnostics(), &table, Source{ "test" }, {}); 391ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski XmlPullParser xmlParser(input); 401ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ASSERT_FALSE(parser.parse(&xmlParser)); 41769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 42769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistruct ResourceParserTest : public ::testing::Test { 441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ResourceTable mTable; 451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::unique_ptr<IAaptContext> mContext; 461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski void SetUp() override { 481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski mContext = test::ContextBuilder().build(); 496f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 519ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski ::testing::AssertionResult testParse(const StringPiece& str, 529ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski Maybe<std::u16string> product = {}) { 536f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski std::stringstream input(kXmlPreamble); 5424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski input << "<resources>\n" << str << "\n</resources>" << std::endl; 559f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski ResourceParserOptions parserOptions; 569f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski parserOptions.product = product; 579ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski ResourceParser parser(mContext->getDiagnostics(), &mTable, Source{ "test" }, {}, 589f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski parserOptions); 591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski XmlPullParser xmlParser(input); 601ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (parser.parse(&xmlParser)) { 616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return ::testing::AssertionSuccess(); 626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return ::testing::AssertionFailure(); 646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}; 666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseQuotedString) { 6824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<string name=\"foo\"> \" hey there \" </string>"; 696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 711ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski String* str = test::getValue<String>(&mTable, u"@string/foo"); 726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(nullptr, str); 736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(std::u16string(u" hey there "), *str->value); 746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 766f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseEscapedString) { 7724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<string name=\"foo\">\\?123</string>"; 786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 801ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski String* str = test::getValue<String>(&mTable, u"@string/foo"); 816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(nullptr, str); 826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(std::u16string(u"?123"), *str->value); 836f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 859f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam LesinskiTEST_F(ResourceParserTest, ParseFormattedString) { 869f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski std::string input = "<string name=\"foo\">%d %s</string>"; 879f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski ASSERT_FALSE(testParse(input)); 889f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski 899f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski input = "<string name=\"foo\">%1$d %2$s</string>"; 909f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski ASSERT_TRUE(testParse(input)); 919f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski} 929f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski 931ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiTEST_F(ResourceParserTest, IgnoreXliffTags) { 941ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::string input = "<string name=\"foo\" \n" 951ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski " xmlns:xliff=\"urn:oasis:names:tc:xliff:document:1.2\">\n" 961ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski " There are <xliff:g id=\"count\">%1$d</xliff:g> apples</string>"; 971ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ASSERT_TRUE(testParse(input)); 981ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 991ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski String* str = test::getValue<String>(&mTable, u"@string/foo"); 1001ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ASSERT_NE(nullptr, str); 1011ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(StringPiece16(u"There are %1$d apples"), StringPiece16(*str->value)); 1021ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 1031ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 104dfa5e0705ff82f15e228ba076bc192893bcbe118Adam LesinskiTEST_F(ResourceParserTest, ParseNull) { 105dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski std::string input = "<integer name=\"foo\">@null</integer>"; 106dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski ASSERT_TRUE(testParse(input)); 107dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski 108dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski // The Android runtime treats a value of android::Res_value::TYPE_NULL as 109dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski // a non-existing value, and this causes problems in styles when trying to resolve 110dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski // an attribute. Null values must be encoded as android::Res_value::TYPE_REFERENCE 111dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski // with a data value of 0. 1121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski BinaryPrimitive* integer = test::getValue<BinaryPrimitive>(&mTable, u"@integer/foo"); 113dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski ASSERT_NE(nullptr, integer); 114dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski EXPECT_EQ(uint16_t(android::Res_value::TYPE_REFERENCE), integer->value.dataType); 115dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski EXPECT_EQ(0u, integer->value.data); 116dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski} 117dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski 118dfa5e0705ff82f15e228ba076bc192893bcbe118Adam LesinskiTEST_F(ResourceParserTest, ParseEmpty) { 119dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski std::string input = "<integer name=\"foo\">@empty</integer>"; 120dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski ASSERT_TRUE(testParse(input)); 121dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski 1221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski BinaryPrimitive* integer = test::getValue<BinaryPrimitive>(&mTable, u"@integer/foo"); 123dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski ASSERT_NE(nullptr, integer); 124dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski EXPECT_EQ(uint16_t(android::Res_value::TYPE_NULL), integer->value.dataType); 125dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski EXPECT_EQ(uint32_t(android::Res_value::DATA_NULL_EMPTY), integer->value.data); 126dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski} 127dfa5e0705ff82f15e228ba076bc192893bcbe118Adam Lesinski 1286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseAttr) { 12924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<attr name=\"foo\" format=\"string\"/>\n" 13024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "<attr name=\"bar\"/>"; 1316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 1326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1331ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/foo"); 1341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ASSERT_NE(nullptr, attr); 1356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_STRING), attr->typeMask); 1366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski attr = test::getValue<Attribute>(&mTable, u"@attr/bar"); 1381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ASSERT_NE(nullptr, attr); 1396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_ANY), attr->typeMask); 1406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseUseAndDeclOfAttr) { 14324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<declare-styleable name=\"Styleable\">\n" 14424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <attr name=\"foo\" />\n" 14524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</declare-styleable>\n" 14624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "<attr name=\"foo\" format=\"string\"/>"; 1476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 1486f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1491ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/foo"); 1506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(nullptr, attr); 1516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_STRING), attr->typeMask); 1526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1536f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseDoubleUseOfAttr) { 15524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<declare-styleable name=\"Theme\">" 15624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <attr name=\"foo\" />\n" 15724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</declare-styleable>\n" 15824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "<declare-styleable name=\"Window\">\n" 15924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <attr name=\"foo\" format=\"boolean\"/>\n" 16024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</declare-styleable>"; 1616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 1626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1631ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/foo"); 1646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(nullptr, attr); 1656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_BOOLEAN), attr->typeMask); 1666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseEnumAttr) { 16924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<attr name=\"foo\">\n" 17024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <enum name=\"bar\" value=\"0\"/>\n" 17124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <enum name=\"bat\" value=\"1\"/>\n" 17224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <enum name=\"baz\" value=\"2\"/>\n" 17324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</attr>"; 1746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 1756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1761ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Attribute* enumAttr = test::getValue<Attribute>(&mTable, u"@attr/foo"); 1776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(enumAttr, nullptr); 1786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(enumAttr->typeMask, android::ResTable_map::TYPE_ENUM); 1796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_EQ(enumAttr->symbols.size(), 3u); 1806f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1811ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(enumAttr->symbols[0].symbol.name); 1821ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(enumAttr->symbols[0].symbol.name.value().entry, u"bar"); 1836f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(enumAttr->symbols[0].value, 0u); 1846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1851ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(enumAttr->symbols[1].symbol.name); 1861ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(enumAttr->symbols[1].symbol.name.value().entry, u"bat"); 1876f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(enumAttr->symbols[1].value, 1u); 1886f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1891ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(enumAttr->symbols[2].symbol.name); 1901ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(enumAttr->symbols[2].symbol.name.value().entry, u"baz"); 1916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(enumAttr->symbols[2].value, 2u); 1926f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1936f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1946f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseFlagAttr) { 19524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<attr name=\"foo\">\n" 19624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <flag name=\"bar\" value=\"0\"/>\n" 19724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <flag name=\"bat\" value=\"1\"/>\n" 19824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <flag name=\"baz\" value=\"2\"/>\n" 19924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</attr>"; 2006f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 2016f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2021ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Attribute* flagAttr = test::getValue<Attribute>(&mTable, u"@attr/foo"); 2036f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(flagAttr, nullptr); 2046f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(flagAttr->typeMask, android::ResTable_map::TYPE_FLAGS); 2056f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_EQ(flagAttr->symbols.size(), 3u); 2066f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2071ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(flagAttr->symbols[0].symbol.name); 2081ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(flagAttr->symbols[0].symbol.name.value().entry, u"bar"); 2096f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(flagAttr->symbols[0].value, 0u); 2106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(flagAttr->symbols[1].symbol.name); 2121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(flagAttr->symbols[1].symbol.name.value().entry, u"bat"); 2136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(flagAttr->symbols[1].value, 1u); 2146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(flagAttr->symbols[2].symbol.name); 2161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(flagAttr->symbols[2].symbol.name.value().entry, u"baz"); 2176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(flagAttr->symbols[2].value, 2u); 2186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::unique_ptr<BinaryPrimitive> flagValue = ResourceUtils::tryParseFlagSymbol(flagAttr, 2201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski u"baz|bat"); 2216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(flagValue, nullptr); 2226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_EQ(flagValue->value.data, 1u | 2u); 2236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, FailToParseEnumAttrWithNonUniqueKeys) { 22624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<attr name=\"foo\">\n" 22724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <enum name=\"bar\" value=\"0\"/>\n" 22824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <enum name=\"bat\" value=\"1\"/>\n" 22924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <enum name=\"bat\" value=\"2\"/>\n" 23024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</attr>"; 2316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_FALSE(testParse(input)); 2326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseStyle) { 23524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<style name=\"foo\" parent=\"@style/fu\">\n" 23624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item name=\"bar\">#ffffffff</item>\n" 23724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item name=\"bat\">@string/hey</item>\n" 23824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item name=\"baz\"><b>hey</b></item>\n" 23924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</style>"; 2406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 2416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 2421ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Style* style = test::getValue<Style>(&mTable, u"@style/foo"); 2436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(style, nullptr); 2441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->parent); 2451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->parent.value().name); 2461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@style/fu"), style->parent.value().name.value()); 2471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ASSERT_EQ(3u, style->entries.size()); 2481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 2491ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->entries[0].key.name); 2501ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@attr/bar"), style->entries[0].key.name.value()); 2511ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 2521ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->entries[1].key.name); 2531ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@attr/bat"), style->entries[1].key.name.value()); 2541ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 2551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->entries[2].key.name); 2561ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@attr/baz"), style->entries[2].key.name.value()); 2576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 2586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 259769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithShorthandParent) { 26024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<style name=\"foo\" parent=\"com.app:Theme\"/>"; 261769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ASSERT_TRUE(testParse(input)); 262769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 2631ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Style* style = test::getValue<Style>(&mTable, u"@style/foo"); 264769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski ASSERT_NE(style, nullptr); 2651ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->parent); 2661ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->parent.value().name); 2671ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@com.app:style/Theme"), style->parent.value().name.value()); 268769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 269769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 27024aad163bc88cb10d2275385e9afc3de7f342d65Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithPackageAliasedParent) { 27124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<style xmlns:app=\"http://schemas.android.com/apk/res/android\"\n" 27224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " name=\"foo\" parent=\"app:Theme\"/>"; 27324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski ASSERT_TRUE(testParse(input)); 27424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 2751ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Style* style = test::getValue<Style>(&mTable, u"@style/foo"); 27624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski ASSERT_NE(style, nullptr); 2771ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->parent); 2781ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->parent.value().name); 2791ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@android:style/Theme"), style->parent.value().name.value()); 28024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski} 28124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 28224aad163bc88cb10d2275385e9afc3de7f342d65Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithPackageAliasedItems) { 28324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = 28424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "<style xmlns:app=\"http://schemas.android.com/apk/res/android\" name=\"foo\">\n" 28524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item name=\"app:bar\">0</item>\n" 28624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</style>"; 28724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski ASSERT_TRUE(testParse(input)); 28824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 2891ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Style* style = test::getValue<Style>(&mTable, u"@style/foo"); 29024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski ASSERT_NE(style, nullptr); 29124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski ASSERT_EQ(1u, style->entries.size()); 2921ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@android:attr/bar"), style->entries[0].key.name.value()); 29324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski} 29424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski 295bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithInferredParent) { 296bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski std::string input = "<style name=\"foo.bar\"/>"; 297bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski ASSERT_TRUE(testParse(input)); 298bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 2991ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Style* style = test::getValue<Style>(&mTable, u"@style/foo.bar"); 300bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski ASSERT_NE(style, nullptr); 3011ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->parent); 3021ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_ASSERT_TRUE(style->parent.value().name); 3031ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(style->parent.value().name.value(), test::parseNameOrDie(u"@style/foo")); 304bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski EXPECT_TRUE(style->parentInferred); 305bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski} 306bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 307bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam LesinskiTEST_F(ResourceParserTest, ParseStyleWithInferredParentOverridenByEmptyParentAttribute) { 308bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski std::string input = "<style name=\"foo.bar\" parent=\"\"/>"; 309bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski ASSERT_TRUE(testParse(input)); 310bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 3111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Style* style = test::getValue<Style>(&mTable, u"@style/foo.bar"); 312bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski ASSERT_NE(style, nullptr); 3131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski AAPT_EXPECT_FALSE(style->parent); 314bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski EXPECT_FALSE(style->parentInferred); 315bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski} 316bdaa092a193d8ddccbd9ad8434be97878e6ded59Adam Lesinski 3176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseAutoGeneratedIdReference) { 31824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<string name=\"foo\">@+id/bar</string>"; 3196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 3206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Id* id = test::getValue<Id>(&mTable, u"@id/bar"); 3226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(id, nullptr); 3236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseAttributesDeclareStyleable) { 32624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<declare-styleable name=\"foo\">\n" 32724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <attr name=\"bar\" />\n" 32824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <attr name=\"bat\" format=\"string|reference\"/>\n" 3299ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski " <attr name=\"baz\">\n" 3309ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski " <enum name=\"foo\" value=\"1\"/>\n" 3319ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski " </attr>\n" 33224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</declare-styleable>"; 3336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 3346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3359f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski Maybe<ResourceTable::SearchResult> result = 3369f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski mTable.findResource(test::parseNameOrDie(u"@styleable/foo")); 3379f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski AAPT_ASSERT_TRUE(result); 3389f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski EXPECT_EQ(SymbolState::kPublic, result.value().entry->symbolStatus.state); 3399f22204c3a9ddac4f92573c9ab098e6cf3ed1cb4Adam Lesinski 3401ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/bar"); 3416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(attr, nullptr); 3426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_TRUE(attr->isWeak()); 3436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski attr = test::getValue<Attribute>(&mTable, u"@attr/bat"); 3456f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(attr, nullptr); 3466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EXPECT_TRUE(attr->isWeak()); 3476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3489ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski attr = test::getValue<Attribute>(&mTable, u"@attr/baz"); 3499ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski ASSERT_NE(attr, nullptr); 3509ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski EXPECT_TRUE(attr->isWeak()); 3519ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski EXPECT_EQ(1u, attr->symbols.size()); 3529ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 3539ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski EXPECT_NE(nullptr, test::getValue<Id>(&mTable, u"@id/foo")); 3549ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 3551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Styleable* styleable = test::getValue<Styleable>(&mTable, u"@styleable/foo"); 3566f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(styleable, nullptr); 3579ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski ASSERT_EQ(3u, styleable->entries.size()); 3586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@attr/bar"), styleable->entries[0].name.value()); 3601ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_EQ(test::parseNameOrDie(u"@attr/bat"), styleable->entries[1].name.value()); 3616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseArray) { 36424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<array name=\"foo\">\n" 36524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item>@string/ref</item>\n" 36624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item>hey</item>\n" 36724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item>23</item>\n" 36824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</array>"; 3696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 3706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3711ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Array* array = test::getValue<Array>(&mTable, u"@array/foo"); 3726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(array, nullptr); 3736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_EQ(3u, array->items.size()); 3746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3751ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_NE(nullptr, valueCast<Reference>(array->items[0].get())); 3761ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_NE(nullptr, valueCast<String>(array->items[1].get())); 3771ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski EXPECT_NE(nullptr, valueCast<BinaryPrimitive>(array->items[2].get())); 3786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3809ba47d813075fcb05c5e1532c137c93b394631cbAdam LesinskiTEST_F(ResourceParserTest, ParseStringArray) { 3819ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski std::string input = "<string-array name=\"foo\">\n" 3829ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski " <item>\"Werk\"</item>\n" 3839ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski "</string-array>\n"; 3849ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski ASSERT_TRUE(testParse(input)); 3859ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski EXPECT_NE(nullptr, test::getValue<Array>(&mTable, u"@array/foo")); 3869ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski} 3879ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 3886f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParsePlural) { 38924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<plurals name=\"foo\">\n" 39024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item quantity=\"other\">apples</item>\n" 39124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski " <item quantity=\"one\">apple</item>\n" 39224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "</plurals>"; 3936f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 3946f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3956f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 3966f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParseCommentsWithResource) { 397e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski std::string input = "<!--This is a comment-->\n" 39824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski "<string name=\"foo\">Hi</string>"; 3996f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 4006f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 401e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski String* value = test::getValue<String>(&mTable, u"@string/foo"); 402e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski ASSERT_NE(nullptr, value); 403e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski EXPECT_EQ(value->getComment(), u"This is a comment"); 404e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski} 405e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 406e78fd617ec60139a973a01925fa7adad31febb39Adam LesinskiTEST_F(ResourceParserTest, DoNotCombineMultipleComments) { 407e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski std::string input = "<!--One-->\n" 408e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski "<!--Two-->\n" 409e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski "<string name=\"foo\">Hi</string>"; 410e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 411e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski ASSERT_TRUE(testParse(input)); 412e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 413e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski String* value = test::getValue<String>(&mTable, u"@string/foo"); 414e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski ASSERT_NE(nullptr, value); 415e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski EXPECT_EQ(value->getComment(), u"Two"); 416e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski} 417e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 418e78fd617ec60139a973a01925fa7adad31febb39Adam LesinskiTEST_F(ResourceParserTest, IgnoreCommentBeforeEndTag) { 419e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski std::string input = "<!--One-->\n" 420e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski "<string name=\"foo\">\n" 421e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski " Hi\n" 422e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski "<!--Two-->\n" 423e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski "</string>"; 424e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski 425e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski ASSERT_TRUE(testParse(input)); 4261ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 427e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski String* value = test::getValue<String>(&mTable, u"@string/foo"); 428e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski ASSERT_NE(nullptr, value); 429e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski EXPECT_EQ(value->getComment(), u"One"); 4306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 4316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 432ca5638fd85098c3d0a699492751043545f75553aAdam LesinskiTEST_F(ResourceParserTest, ParseNestedComments) { 433ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski // We only care about declare-styleable and enum/flag attributes because comments 434ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski // from those end up in R.java 435ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski std::string input = R"EOF( 436ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <declare-styleable name="foo"> 437ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <!-- The name of the bar --> 438ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <attr name="barName" format="string|reference" /> 439ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski </declare-styleable> 440ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 441ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <attr name="foo"> 442ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <!-- The very first --> 443ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski <enum name="one" value="1" /> 444ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski </attr>)EOF"; 445ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski ASSERT_TRUE(testParse(input)); 446ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 447ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski Styleable* styleable = test::getValue<Styleable>(&mTable, u"@styleable/foo"); 448ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski ASSERT_NE(nullptr, styleable); 449ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski ASSERT_EQ(1u, styleable->entries.size()); 450ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 451ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski EXPECT_EQ(StringPiece16(u"The name of the bar"), styleable->entries.front().getComment()); 452ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 453ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/foo"); 454ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski ASSERT_NE(nullptr, attr); 455ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski ASSERT_EQ(1u, attr->symbols.size()); 456ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 457ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski EXPECT_EQ(StringPiece16(u"The very first"), attr->symbols.front().symbol.getComment()); 458ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski} 459ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 4606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/* 4616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Declaring an ID as public should not require a separate definition 4626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * (as an ID has no value). 4636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 4646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam LesinskiTEST_F(ResourceParserTest, ParsePublicIdAsDefinition) { 46524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski std::string input = "<public type=\"id\" name=\"foo\"/>"; 4666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_TRUE(testParse(input)); 4676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4681ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Id* id = test::getValue<Id>(&mTable, u"@id/foo"); 4696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ASSERT_NE(nullptr, id); 4706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 4716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 4729ba47d813075fcb05c5e1532c137c93b394631cbAdam LesinskiTEST_F(ResourceParserTest, FilterProductsThatDontMatch) { 4739ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski std::string input = "<string name=\"foo\" product=\"phone\">hi</string>\n" 4749ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski "<string name=\"foo\" product=\"no-sdcard\">ho</string>\n" 4759ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski "<string name=\"bar\" product=\"\">wee</string>\n" 4769ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski "<string name=\"baz\">woo</string>\n"; 4779ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski ASSERT_TRUE(testParse(input, std::u16string(u"no-sdcard"))); 4789ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 4799ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski String* fooStr = test::getValue<String>(&mTable, u"@string/foo"); 4809ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski ASSERT_NE(nullptr, fooStr); 4819ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski EXPECT_EQ(StringPiece16(u"ho"), *fooStr->value); 4829ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 4839ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski EXPECT_NE(nullptr, test::getValue<String>(&mTable, u"@string/bar")); 4849ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski EXPECT_NE(nullptr, test::getValue<String>(&mTable, u"@string/baz")); 4859ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski} 4869ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 4879ba47d813075fcb05c5e1532c137c93b394631cbAdam LesinskiTEST_F(ResourceParserTest, FailWhenProductFilterStripsOutAllVersionsOfResource) { 4889ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski std::string input = "<string name=\"foo\" product=\"tablet\">hello</string>\n"; 4899ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski ASSERT_FALSE(testParse(input, std::u16string(u"phone"))); 4909ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski} 4919ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 4926f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} // namespace aapt 493