11ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski/* 21ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Copyright (C) 2015 The Android Open Source Project 31ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * 41ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 51ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * you may not use this file except in compliance with the License. 61ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * You may obtain a copy of the License at 71ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * 81ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 91ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * 101ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Unless required by applicable law or agreed to in writing, software 111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * See the License for the specific language governing permissions and 141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * limitations under the License. 151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski */ 161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 174670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski#include "format/binary/TableFlattener.h" 18ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 19c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski#include "android-base/stringprintf.h" 20c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 21cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski#include "ResourceUtils.h" 22c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski#include "SdkConstants.h" 234670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski#include "format/binary/BinaryResourceParser.h" 24fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski#include "test/Test.h" 251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "util/Util.h" 261ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 271ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskiusing namespace android; 281ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 2971be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinskiusing ::testing::Gt; 30a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinskiusing ::testing::IsNull; 31a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinskiusing ::testing::NotNull; 32a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski 331ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskinamespace aapt { 341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskiclass TableFlattenerTest : public ::testing::Test { 36cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public: 37cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski void SetUp() override { 384670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski context_ = 394670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski test::ContextBuilder().SetCompilationPackage("com.app.test").SetPackageId(0x7f).Build(); 40cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 41cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 42c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski ::testing::AssertionResult Flatten(IAaptContext* context, const TableFlattenerOptions& options, 43c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski ResourceTable* table, std::string* out_content) { 44cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski BigBuffer buffer(1024); 45c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski TableFlattener flattener(options, &buffer); 46c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski if (!flattener.Consume(context, table)) { 47cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return ::testing::AssertionFailure() << "failed to flatten ResourceTable"; 48cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 49c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski *out_content = buffer.to_string(); 50c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski return ::testing::AssertionSuccess(); 51c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski } 52c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 53c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski ::testing::AssertionResult Flatten(IAaptContext* context, const TableFlattenerOptions& options, 54c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski ResourceTable* table, ResTable* out_table) { 55c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski std::string content; 56c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski auto result = Flatten(context, options, table, &content); 57c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski if (!result) { 58c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski return result; 59c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski } 60cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 61ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski if (out_table->add(content.data(), content.size(), 1, true) != NO_ERROR) { 62cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return ::testing::AssertionFailure() << "flattened ResTable is corrupt"; 63cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 64cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return ::testing::AssertionSuccess(); 65cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 66cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 67ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski ::testing::AssertionResult Flatten(IAaptContext* context, const TableFlattenerOptions& options, 68c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski ResourceTable* table, ResourceTable* out_table) { 69c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski std::string content; 70c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski auto result = Flatten(context, options, table, &content); 71c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski if (!result) { 72c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski return result; 73cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 74cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 758780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski BinaryResourceParser parser(context->GetDiagnostics(), out_table, {}, content.data(), 768780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski content.size()); 77ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!parser.Parse()) { 78cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return ::testing::AssertionFailure() << "flattened ResTable is corrupt"; 79cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 80cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return ::testing::AssertionSuccess(); 81cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 82cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 834670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski ::testing::AssertionResult Exists(ResTable* table, const StringPiece& expected_name, 84ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const ResourceId& expected_id, 85ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const ConfigDescription& expected_config, 864670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski const uint8_t expected_data_type, const uint32_t expected_data, 87ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const uint32_t expected_spec_flags) { 88ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const ResourceName expected_res_name = test::ParseNameOrDie(expected_name); 89cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 90ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski table->setParameters(&expected_config); 91cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 92cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ResTable_config config; 93cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski Res_value val; 94ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski uint32_t spec_flags; 954670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski if (table->getResource(expected_id.id, &val, false, 0, &spec_flags, &config) < 0) { 96cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return ::testing::AssertionFailure() << "could not find resource with"; 97cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 98cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 99ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (expected_data_type != val.dataType) { 100cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return ::testing::AssertionFailure() 101ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski << "expected data type " << std::hex << (int)expected_data_type 1024670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski << " but got data type " << (int)val.dataType << std::dec << " instead"; 103cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 104cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 105ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (expected_data != val.data) { 106cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return ::testing::AssertionFailure() 1074670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski << "expected data " << std::hex << expected_data << " but got data " << val.data 1084670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski << std::dec << " instead"; 109cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 110cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 111ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (expected_spec_flags != spec_flags) { 112cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return ::testing::AssertionFailure() 1134670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski << "expected specFlags " << std::hex << expected_spec_flags << " but got specFlags " 1144670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski << spec_flags << std::dec << " instead"; 1151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 117ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResTable::resource_name actual_name; 118ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!table->getResourceName(expected_id.id, false, &actual_name)) { 119cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return ::testing::AssertionFailure() << "failed to find resource name"; 1201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 122ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Maybe<ResourceName> resName = ResourceUtils::ToResourceName(actual_name); 123cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!resName) { 124cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return ::testing::AssertionFailure() 125ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski << "expected name '" << expected_res_name << "' but got '" 1264670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski << StringPiece16(actual_name.package, actual_name.packageLen) << ":" 1274670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski << StringPiece16(actual_name.type, actual_name.typeLen) << "/" 1284670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski << StringPiece16(actual_name.name, actual_name.nameLen) << "'"; 1291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 131b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ResourceName actual_res_name(resName.value()); 132b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson 133b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson if (expected_res_name.entry != actual_res_name.entry || 134b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson expected_res_name.package != actual_res_name.package || 135b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson expected_res_name.type != actual_res_name.type) { 136b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson return ::testing::AssertionFailure() << "expected resource '" << expected_res_name.to_string() 137b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson << "' but got '" << actual_res_name.to_string() << "'"; 138b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson } 139b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson 140ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (expected_config != config) { 1414670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski return ::testing::AssertionFailure() << "expected config '" << expected_config 1424670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski << "' but got '" << ConfigDescription(config) << "'"; 1431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 144cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return ::testing::AssertionSuccess(); 145cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 147c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski protected: 148ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<IAaptContext> context_; 1491ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}; 1501ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1511ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiTEST_F(TableFlattenerTest, FlattenFullyLinkedTable) { 152cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::unique_ptr<ResourceTable> table = 153cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski test::ResourceTableBuilder() 154ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .SetPackageId("com.app.test", 0x7f) 155ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .AddSimple("com.app.test:id/one", ResourceId(0x7f020000)) 156ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .AddSimple("com.app.test:id/two", ResourceId(0x7f020001)) 157ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .AddValue("com.app.test:id/three", ResourceId(0x7f020002), 1584670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski test::BuildReference("com.app.test:id/one", ResourceId(0x7f020000))) 159ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .AddValue("com.app.test:integer/one", ResourceId(0x7f030000), 1604670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski util::make_unique<BinaryPrimitive>(uint8_t(Res_value::TYPE_INT_DEC), 1u)) 161ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .AddValue("com.app.test:integer/one", test::ParseConfigOrDie("v1"), 162cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ResourceId(0x7f030000), 1634670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski util::make_unique<BinaryPrimitive>(uint8_t(Res_value::TYPE_INT_DEC), 2u)) 164ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .AddString("com.app.test:string/test", ResourceId(0x7f040000), "foo") 1654670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski .AddString("com.app.test:layout/bar", ResourceId(0x7f050000), "res/layout/bar.xml") 166ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .Build(); 167cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 168ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResTable res_table; 169c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski ASSERT_TRUE(Flatten(context_.get(), {}, table.get(), &res_table)); 170cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1714670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski EXPECT_TRUE(Exists(&res_table, "com.app.test:id/one", ResourceId(0x7f020000), {}, 1724670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski Res_value::TYPE_INT_BOOLEAN, 0u, 0u)); 173cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1744670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski EXPECT_TRUE(Exists(&res_table, "com.app.test:id/two", ResourceId(0x7f020001), {}, 1754670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski Res_value::TYPE_INT_BOOLEAN, 0u, 0u)); 176cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1774670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski EXPECT_TRUE(Exists(&res_table, "com.app.test:id/three", ResourceId(0x7f020002), {}, 1784670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski Res_value::TYPE_REFERENCE, 0x7f020000u, 0u)); 179cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1804670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski EXPECT_TRUE(Exists(&res_table, "com.app.test:integer/one", ResourceId(0x7f030000), {}, 1814670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski Res_value::TYPE_INT_DEC, 1u, ResTable_config::CONFIG_VERSION)); 182cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 1834670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski EXPECT_TRUE(Exists(&res_table, "com.app.test:integer/one", ResourceId(0x7f030000), 1844670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski test::ParseConfigOrDie("v1"), Res_value::TYPE_INT_DEC, 2u, 185cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ResTable_config::CONFIG_VERSION)); 186cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 187ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::u16string foo_str = u"foo"; 1884670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski ssize_t idx = res_table.getTableStringBlock(0)->indexOfString(foo_str.data(), foo_str.size()); 189cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_GE(idx, 0); 1904670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski EXPECT_TRUE(Exists(&res_table, "com.app.test:string/test", ResourceId(0x7f040000), {}, 1914670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski Res_value::TYPE_STRING, (uint32_t)idx, 0u)); 192cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 193ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::u16string bar_path = u"res/layout/bar.xml"; 1944670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski idx = res_table.getTableStringBlock(0)->indexOfString(bar_path.data(), bar_path.size()); 195cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ASSERT_GE(idx, 0); 1964670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski EXPECT_TRUE(Exists(&res_table, "com.app.test:layout/bar", ResourceId(0x7f050000), {}, 1974670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski Res_value::TYPE_STRING, (uint32_t)idx, 0u)); 1981ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 1991ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 2001ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiTEST_F(TableFlattenerTest, FlattenEntriesWithGapsInIds) { 201cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::unique_ptr<ResourceTable> table = 202cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski test::ResourceTableBuilder() 203ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .SetPackageId("com.app.test", 0x7f) 204ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .AddSimple("com.app.test:id/one", ResourceId(0x7f020001)) 205ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .AddSimple("com.app.test:id/three", ResourceId(0x7f020003)) 206ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .Build(); 207cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 208ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResTable res_table; 209c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski ASSERT_TRUE(Flatten(context_.get(), {}, table.get(), &res_table)); 210cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 2114670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski EXPECT_TRUE(Exists(&res_table, "com.app.test:id/one", ResourceId(0x7f020001), {}, 2124670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski Res_value::TYPE_INT_BOOLEAN, 0u, 0u)); 2134670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski EXPECT_TRUE(Exists(&res_table, "com.app.test:id/three", ResourceId(0x7f020003), {}, 2144670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski Res_value::TYPE_INT_BOOLEAN, 0u, 0u)); 2151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 2161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 217a587065721053ad54e34f484868142407d59512dAdam LesinskiTEST_F(TableFlattenerTest, FlattenMinMaxAttributes) { 21873bff1e8519bb73f17a801f45977d41b69b5b0d0Adam Lesinski Attribute attr; 219ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr.type_mask = android::ResTable_map::TYPE_INTEGER; 220ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr.min_int = 10; 221ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr.max_int = 23; 222cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::unique_ptr<ResourceTable> table = 223cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski test::ResourceTableBuilder() 224ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .SetPackageId("android", 0x01) 2254670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski .AddValue("android:attr/foo", ResourceId(0x01010000), util::make_unique<Attribute>(attr)) 226ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski .Build(); 227cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 228cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski ResourceTable result; 229c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski ASSERT_TRUE(Flatten(context_.get(), {}, table.get(), &result)); 230cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 231a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski Attribute* actual_attr = test::GetValue<Attribute>(&result, "android:attr/foo"); 232a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(actual_attr, NotNull()); 233a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_EQ(attr.IsWeak(), actual_attr->IsWeak()); 234a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_EQ(attr.type_mask, actual_attr->type_mask); 235a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_EQ(attr.min_int, actual_attr->min_int); 236a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski EXPECT_EQ(attr.max_int, actual_attr->max_int); 237a587065721053ad54e34f484868142407d59512dAdam Lesinski} 238a587065721053ad54e34f484868142407d59512dAdam Lesinski 239c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinskistatic std::unique_ptr<ResourceTable> BuildTableWithSparseEntries( 240c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski IAaptContext* context, const ConfigDescription& sparse_config, float load) { 241c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski std::unique_ptr<ResourceTable> table = 242c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski test::ResourceTableBuilder() 243c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .SetPackageId(context->GetCompilationPackage(), context->GetPackageId()) 244c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .Build(); 245c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 246c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski // Add regular entries. 247c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski int stride = static_cast<int>(1.0f / load); 248c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski for (int i = 0; i < 100; i++) { 249c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski const ResourceName name = test::ParseNameOrDie( 250c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski base::StringPrintf("%s:string/foo_%d", context->GetCompilationPackage().data(), i)); 251c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski const ResourceId resid(context->GetPackageId(), 0x02, static_cast<uint16_t>(i)); 252c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski const auto value = 253c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski util::make_unique<BinaryPrimitive>(Res_value::TYPE_INT_DEC, static_cast<uint32_t>(i)); 25471be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski CHECK(table->AddResourceWithId(name, resid, ConfigDescription::DefaultConfig(), "", 25571be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski std::unique_ptr<Value>(value->Clone(nullptr)), 25671be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski context->GetDiagnostics())); 257c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 258c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski // Every few entries, write out a sparse_config value. This will give us the desired load. 259c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski if (i % stride == 0) { 26071be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski CHECK(table->AddResourceWithId(name, resid, sparse_config, "", 26171be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski std::unique_ptr<Value>(value->Clone(nullptr)), 26271be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski context->GetDiagnostics())); 263c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski } 264c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski } 265c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski return table; 266c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski} 267c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 268c8f71aa67ea599cb80205496cb67e9e7a121299cAdam LesinskiTEST_F(TableFlattenerTest, FlattenSparseEntryWithMinSdkO) { 269c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski std::unique_ptr<IAaptContext> context = test::ContextBuilder() 270c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .SetCompilationPackage("android") 271c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .SetPackageId(0x01) 272c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .SetMinSdkVersion(SDK_O) 273c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .Build(); 274c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 275c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski const ConfigDescription sparse_config = test::ParseConfigOrDie("en-rGB"); 276c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski auto table_in = BuildTableWithSparseEntries(context.get(), sparse_config, 0.25f); 277c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 278c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski TableFlattenerOptions options; 279c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski options.use_sparse_entries = true; 280c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 281c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski std::string no_sparse_contents; 282c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski ASSERT_TRUE(Flatten(context.get(), {}, table_in.get(), &no_sparse_contents)); 283c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 284c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski std::string sparse_contents; 285c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski ASSERT_TRUE(Flatten(context.get(), options, table_in.get(), &sparse_contents)); 286c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 287c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski EXPECT_GT(no_sparse_contents.size(), sparse_contents.size()); 288c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 289c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski // Attempt to parse the sparse contents. 290c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 291c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski ResourceTable sparse_table; 2928780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski BinaryResourceParser parser(context->GetDiagnostics(), &sparse_table, Source("test.arsc"), 293c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski sparse_contents.data(), sparse_contents.size()); 294c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski ASSERT_TRUE(parser.Parse()); 295c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 296c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski auto value = test::GetValueForConfig<BinaryPrimitive>(&sparse_table, "android:string/foo_0", 297c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski sparse_config); 298a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(value, NotNull()); 299c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski EXPECT_EQ(0u, value->value.data); 300c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 3014670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski ASSERT_THAT(test::GetValueForConfig<BinaryPrimitive>(&sparse_table, "android:string/foo_1", 3024670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski sparse_config), 3034670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski IsNull()); 304c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 3054670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski value = test::GetValueForConfig<BinaryPrimitive>(&sparse_table, "android:string/foo_4", 3064670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski sparse_config); 307a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(value, NotNull()); 308c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski EXPECT_EQ(4u, value->value.data); 309c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski} 310c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 311c8f71aa67ea599cb80205496cb67e9e7a121299cAdam LesinskiTEST_F(TableFlattenerTest, FlattenSparseEntryWithConfigSdkVersionO) { 312c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski std::unique_ptr<IAaptContext> context = test::ContextBuilder() 313c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .SetCompilationPackage("android") 314c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .SetPackageId(0x01) 315c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .SetMinSdkVersion(SDK_LOLLIPOP) 316c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .Build(); 317c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 318c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski const ConfigDescription sparse_config = test::ParseConfigOrDie("en-rGB-v26"); 319c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski auto table_in = BuildTableWithSparseEntries(context.get(), sparse_config, 0.25f); 320c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 321c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski TableFlattenerOptions options; 322c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski options.use_sparse_entries = true; 323c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 324c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski std::string no_sparse_contents; 325c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski ASSERT_TRUE(Flatten(context.get(), {}, table_in.get(), &no_sparse_contents)); 326c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 327c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski std::string sparse_contents; 328c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski ASSERT_TRUE(Flatten(context.get(), options, table_in.get(), &sparse_contents)); 329c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 330c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski EXPECT_GT(no_sparse_contents.size(), sparse_contents.size()); 331c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski} 332c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 333c8f71aa67ea599cb80205496cb67e9e7a121299cAdam LesinskiTEST_F(TableFlattenerTest, DoNotUseSparseEntryForDenseConfig) { 334c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski std::unique_ptr<IAaptContext> context = test::ContextBuilder() 335c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .SetCompilationPackage("android") 336c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .SetPackageId(0x01) 337c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .SetMinSdkVersion(SDK_O) 338c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski .Build(); 339c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 340c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski const ConfigDescription sparse_config = test::ParseConfigOrDie("en-rGB"); 341c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski auto table_in = BuildTableWithSparseEntries(context.get(), sparse_config, 0.80f); 342c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 343c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski TableFlattenerOptions options; 344c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski options.use_sparse_entries = true; 345c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 346c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski std::string no_sparse_contents; 347c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski ASSERT_TRUE(Flatten(context.get(), {}, table_in.get(), &no_sparse_contents)); 348c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 349c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski std::string sparse_contents; 350c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski ASSERT_TRUE(Flatten(context.get(), options, table_in.get(), &sparse_contents)); 351c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 352c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski EXPECT_EQ(no_sparse_contents.size(), sparse_contents.size()); 353c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski} 354c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski 355ceb9b2f80f853059233cdd29057f39a5960a74aeAdam LesinskiTEST_F(TableFlattenerTest, FlattenSharedLibrary) { 356ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski std::unique_ptr<IAaptContext> context = 357ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski test::ContextBuilder().SetCompilationPackage("lib").SetPackageId(0x00).Build(); 358ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski std::unique_ptr<ResourceTable> table = 359ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski test::ResourceTableBuilder() 360ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski .SetPackageId("lib", 0x00) 361ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski .AddValue("lib:id/foo", ResourceId(0x00010000), util::make_unique<Id>()) 362ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski .Build(); 363ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski ResourceTable result; 364ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski ASSERT_TRUE(Flatten(context.get(), {}, table.get(), &result)); 365ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski 366ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski Maybe<ResourceTable::SearchResult> search_result = 367ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski result.FindResource(test::ParseNameOrDie("lib:id/foo")); 368a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_TRUE(search_result); 369ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski EXPECT_EQ(0x00u, search_result.value().package->id.value()); 370ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski 371ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski auto iter = result.included_packages_.find(0x00); 372ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski ASSERT_NE(result.included_packages_.end(), iter); 373ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski EXPECT_EQ("lib", iter->second); 374ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski} 375ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski 376ceb9b2f80f853059233cdd29057f39a5960a74aeAdam LesinskiTEST_F(TableFlattenerTest, FlattenTableReferencingSharedLibraries) { 377ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski std::unique_ptr<IAaptContext> context = 378ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski test::ContextBuilder().SetCompilationPackage("app").SetPackageId(0x7f).Build(); 379ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski std::unique_ptr<ResourceTable> table = 380ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski test::ResourceTableBuilder() 381ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski .SetPackageId("app", 0x7f) 382ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski .AddValue("app:id/foo", ResourceId(0x7f010000), 383ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski test::BuildReference("lib_one:id/foo", ResourceId(0x02010000))) 384ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski .AddValue("app:id/bar", ResourceId(0x7f010001), 385ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski test::BuildReference("lib_two:id/bar", ResourceId(0x03010000))) 386ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski .Build(); 387ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski table->included_packages_[0x02] = "lib_one"; 388ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski table->included_packages_[0x03] = "lib_two"; 389ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski 390ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski ResTable result; 391ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski ASSERT_TRUE(Flatten(context.get(), {}, table.get(), &result)); 392ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski 393ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski const DynamicRefTable* dynamic_ref_table = result.getDynamicRefTableForCookie(1); 394a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(dynamic_ref_table, NotNull()); 395ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski 3964ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski const KeyedVector<String16, uint8_t>& entries = dynamic_ref_table->entries(); 397ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski 398ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski ssize_t idx = entries.indexOfKey(android::String16("lib_one")); 399ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski ASSERT_GE(idx, 0); 400ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski EXPECT_EQ(0x02u, entries.valueAt(idx)); 401ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski 402ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski idx = entries.indexOfKey(android::String16("lib_two")); 403ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski ASSERT_GE(idx, 0); 404ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski EXPECT_EQ(0x03u, entries.valueAt(idx)); 405ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski} 406ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski 4074ca56978a9aea3f021a54ed9265de10811984d94Adam LesinskiTEST_F(TableFlattenerTest, PackageWithNonStandardIdHasDynamicRefTable) { 4084ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski std::unique_ptr<IAaptContext> context = 4094ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski test::ContextBuilder().SetCompilationPackage("app").SetPackageId(0x80).Build(); 4104ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder() 4114ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski .SetPackageId("app", 0x80) 4124ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski .AddSimple("app:id/foo", ResourceId(0x80010000)) 4134ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski .Build(); 4144ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski 4154ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski ResTable result; 4164ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski ASSERT_TRUE(Flatten(context.get(), {}, table.get(), &result)); 4174ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski 4184ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski const DynamicRefTable* dynamic_ref_table = result.getDynamicRefTableForCookie(1); 419a45893a5c51cc26f1fd63ec1aa4c39f55911c85bAdam Lesinski ASSERT_THAT(dynamic_ref_table, NotNull()); 4204ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski 4214ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski const KeyedVector<String16, uint8_t>& entries = dynamic_ref_table->entries(); 4224ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski ssize_t idx = entries.indexOfKey(android::String16("app")); 4234ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski ASSERT_GE(idx, 0); 4244ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski EXPECT_EQ(0x80u, entries.valueAt(idx)); 4254ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski} 4264ca56978a9aea3f021a54ed9265de10811984d94Adam Lesinski 427b522f04bc2a581e2877bef4a44ac00b827f879edAdam LesinskiTEST_F(TableFlattenerTest, LongPackageNameIsTruncated) { 428b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski std::string kPackageName(256, 'F'); 429b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski 430b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski std::unique_ptr<IAaptContext> context = 431b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski test::ContextBuilder().SetCompilationPackage(kPackageName).SetPackageId(0x7f).Build(); 432b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski std::unique_ptr<ResourceTable> table = 433b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski test::ResourceTableBuilder() 434b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski .SetPackageId(kPackageName, 0x7f) 435b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski .AddSimple(kPackageName + ":id/foo", ResourceId(0x7f010000)) 436b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski .Build(); 437b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski 438b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski ResTable result; 439b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski ASSERT_TRUE(Flatten(context.get(), {}, table.get(), &result)); 440b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski 441b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski ASSERT_EQ(1u, result.getBasePackageCount()); 442b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski EXPECT_EQ(127u, result.getBasePackageName(0).size()); 443b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski} 444b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski 445b522f04bc2a581e2877bef4a44ac00b827f879edAdam LesinskiTEST_F(TableFlattenerTest, LongSharedLibraryPackageNameIsIllegal) { 446b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski std::string kPackageName(256, 'F'); 447b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski 448b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski std::unique_ptr<IAaptContext> context = test::ContextBuilder() 449b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski .SetCompilationPackage(kPackageName) 450b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski .SetPackageId(0x7f) 451b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski .SetPackageType(PackageType::kSharedLib) 452b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski .Build(); 453b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski std::unique_ptr<ResourceTable> table = 454b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski test::ResourceTableBuilder() 455b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski .SetPackageId(kPackageName, 0x7f) 456b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski .AddSimple(kPackageName + ":id/foo", ResourceId(0x7f010000)) 457b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski .Build(); 458b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski 459b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski ResTable result; 460b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski ASSERT_FALSE(Flatten(context.get(), {}, table.get(), &result)); 461b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski} 462b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski 463b0643302c78d00db3036707a0df0ae5ce923ae15Luke NicholsonTEST_F(TableFlattenerTest, ObfuscatingResourceNamesNoWhitelistSucceeds) { 464b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson std::unique_ptr<ResourceTable> table = 465b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson test::ResourceTableBuilder() 466b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson .SetPackageId("com.app.test", 0x7f) 467b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson .AddSimple("com.app.test:id/one", ResourceId(0x7f020000)) 468b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson .AddSimple("com.app.test:id/two", ResourceId(0x7f020001)) 469b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson .AddValue("com.app.test:id/three", ResourceId(0x7f020002), 470b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson test::BuildReference("com.app.test:id/one", ResourceId(0x7f020000))) 471b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson .AddValue("com.app.test:integer/one", ResourceId(0x7f030000), 472b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson util::make_unique<BinaryPrimitive>(uint8_t(Res_value::TYPE_INT_DEC), 1u)) 473b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson .AddValue("com.app.test:integer/one", test::ParseConfigOrDie("v1"), 474b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ResourceId(0x7f030000), 475b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson util::make_unique<BinaryPrimitive>(uint8_t(Res_value::TYPE_INT_DEC), 2u)) 476b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson .AddString("com.app.test:string/test", ResourceId(0x7f040000), "foo") 477b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson .AddString("com.app.test:layout/bar", ResourceId(0x7f050000), "res/layout/bar.xml") 478b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson .Build(); 479b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson 480b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson TableFlattenerOptions options; 481b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson options.collapse_key_stringpool = true; 482b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson 483b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ResTable res_table; 484b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson 485b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ASSERT_TRUE(Flatten(context_.get(), options, table.get(), &res_table)); 486b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson 487b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson EXPECT_TRUE(Exists(&res_table, "com.app.test:id/0_resource_name_obfuscated", 488b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ResourceId(0x7f020000), {}, Res_value::TYPE_INT_BOOLEAN, 0u, 0u)); 489b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson 490b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson EXPECT_TRUE(Exists(&res_table, "com.app.test:id/0_resource_name_obfuscated", 491b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ResourceId(0x7f020001), {}, Res_value::TYPE_INT_BOOLEAN, 0u, 0u)); 492b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson 493b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson EXPECT_TRUE(Exists(&res_table, "com.app.test:id/0_resource_name_obfuscated", 494b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ResourceId(0x7f020002), {}, Res_value::TYPE_REFERENCE, 0x7f020000u, 0u)); 495b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson 496b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson EXPECT_TRUE(Exists(&res_table, "com.app.test:integer/0_resource_name_obfuscated", 497b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ResourceId(0x7f030000), {}, Res_value::TYPE_INT_DEC, 1u, 498b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ResTable_config::CONFIG_VERSION)); 499b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson 500b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson EXPECT_TRUE(Exists(&res_table, "com.app.test:integer/0_resource_name_obfuscated", 501b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ResourceId(0x7f030000), test::ParseConfigOrDie("v1"), Res_value::TYPE_INT_DEC, 502b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson 2u, ResTable_config::CONFIG_VERSION)); 503b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson 504b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson std::u16string foo_str = u"foo"; 505b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ssize_t idx = res_table.getTableStringBlock(0)->indexOfString(foo_str.data(), foo_str.size()); 506b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ASSERT_GE(idx, 0); 507b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson EXPECT_TRUE(Exists(&res_table, "com.app.test:string/0_resource_name_obfuscated", 508b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ResourceId(0x7f040000), {}, Res_value::TYPE_STRING, (uint32_t)idx, 0u)); 509b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson 510b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson std::u16string bar_path = u"res/layout/bar.xml"; 511b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson idx = res_table.getTableStringBlock(0)->indexOfString(bar_path.data(), bar_path.size()); 512b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ASSERT_GE(idx, 0); 513b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson EXPECT_TRUE(Exists(&res_table, "com.app.test:layout/0_resource_name_obfuscated", 514b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ResourceId(0x7f050000), {}, Res_value::TYPE_STRING, (uint32_t)idx, 0u)); 515b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson} 516b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson 517b0643302c78d00db3036707a0df0ae5ce923ae15Luke NicholsonTEST_F(TableFlattenerTest, ObfuscatingResourceNamesWithWhitelistSucceeds) { 518b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson std::unique_ptr<ResourceTable> table = 519b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson test::ResourceTableBuilder() 520b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson .SetPackageId("com.app.test", 0x7f) 521b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson .AddSimple("com.app.test:id/one", ResourceId(0x7f020000)) 522b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson .AddSimple("com.app.test:id/two", ResourceId(0x7f020001)) 523b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson .AddValue("com.app.test:id/three", ResourceId(0x7f020002), 524b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson test::BuildReference("com.app.test:id/one", ResourceId(0x7f020000))) 525b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson .AddValue("com.app.test:integer/one", ResourceId(0x7f030000), 526b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson util::make_unique<BinaryPrimitive>(uint8_t(Res_value::TYPE_INT_DEC), 1u)) 527b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson .AddValue("com.app.test:integer/one", test::ParseConfigOrDie("v1"), 528b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ResourceId(0x7f030000), 529b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson util::make_unique<BinaryPrimitive>(uint8_t(Res_value::TYPE_INT_DEC), 2u)) 530b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson .AddString("com.app.test:string/test", ResourceId(0x7f040000), "foo") 531b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson .AddString("com.app.test:layout/bar", ResourceId(0x7f050000), "res/layout/bar.xml") 532b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson .Build(); 533b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson 534b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson TableFlattenerOptions options; 535b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson options.collapse_key_stringpool = true; 536b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson options.whitelisted_resources.insert("test"); 537b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson options.whitelisted_resources.insert("three"); 538b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ResTable res_table; 539b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson 540b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ASSERT_TRUE(Flatten(context_.get(), options, table.get(), &res_table)); 541b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson 542b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson EXPECT_TRUE(Exists(&res_table, "com.app.test:id/0_resource_name_obfuscated", 543b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ResourceId(0x7f020000), {}, Res_value::TYPE_INT_BOOLEAN, 0u, 0u)); 544b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson 545b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson EXPECT_TRUE(Exists(&res_table, "com.app.test:id/0_resource_name_obfuscated", 546b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ResourceId(0x7f020001), {}, Res_value::TYPE_INT_BOOLEAN, 0u, 0u)); 547b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson 548b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson EXPECT_TRUE(Exists(&res_table, "com.app.test:id/three", ResourceId(0x7f020002), {}, 549b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson Res_value::TYPE_REFERENCE, 0x7f020000u, 0u)); 550b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson 551b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson EXPECT_TRUE(Exists(&res_table, "com.app.test:integer/0_resource_name_obfuscated", 552b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ResourceId(0x7f030000), {}, Res_value::TYPE_INT_DEC, 1u, 553b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ResTable_config::CONFIG_VERSION)); 554b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson 555b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson EXPECT_TRUE(Exists(&res_table, "com.app.test:integer/0_resource_name_obfuscated", 556b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ResourceId(0x7f030000), test::ParseConfigOrDie("v1"), Res_value::TYPE_INT_DEC, 557b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson 2u, ResTable_config::CONFIG_VERSION)); 558b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson 559b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson std::u16string foo_str = u"foo"; 560b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ssize_t idx = res_table.getTableStringBlock(0)->indexOfString(foo_str.data(), foo_str.size()); 561b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ASSERT_GE(idx, 0); 562b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson EXPECT_TRUE(Exists(&res_table, "com.app.test:string/test", ResourceId(0x7f040000), {}, 563b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson Res_value::TYPE_STRING, (uint32_t)idx, 0u)); 564b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson 565b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson std::u16string bar_path = u"res/layout/bar.xml"; 566b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson idx = res_table.getTableStringBlock(0)->indexOfString(bar_path.data(), bar_path.size()); 567b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ASSERT_GE(idx, 0); 568b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson EXPECT_TRUE(Exists(&res_table, "com.app.test:layout/0_resource_name_obfuscated", 569b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson ResourceId(0x7f050000), {}, Res_value::TYPE_STRING, (uint32_t)idx, 0u)); 570b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson} 571b0643302c78d00db3036707a0df0ae5ce923ae15Luke Nicholson 57271be70507de9cb619b644e55eda1cc181e3f7e90Adam LesinskiTEST_F(TableFlattenerTest, FlattenOverlayable) { 57371be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski std::unique_ptr<ResourceTable> table = 57471be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski test::ResourceTableBuilder() 57571be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski .SetPackageId("com.app.test", 0x7f) 57671be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski .AddSimple("com.app.test:integer/overlayable", ResourceId(0x7f020000)) 57771be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski .Build(); 57871be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski 57971be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski ASSERT_TRUE(table->SetOverlayable(test::ParseNameOrDie("com.app.test:integer/overlayable"), 58071be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski Overlayable{}, test::GetDiagnostics())); 58171be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski 58271be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski ResTable res_table; 58371be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski ASSERT_TRUE(Flatten(context_.get(), {}, table.get(), &res_table)); 58471be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski 58571be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski const StringPiece16 overlayable_name(u"com.app.test:integer/overlayable"); 58671be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski uint32_t spec_flags = 0u; 58771be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski ASSERT_THAT(res_table.identifierForName(overlayable_name.data(), overlayable_name.size(), nullptr, 58871be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski 0u, nullptr, 0u, &spec_flags), 58971be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski Gt(0u)); 59071be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski EXPECT_TRUE(spec_flags & android::ResTable_typeSpec::SPEC_OVERLAYABLE); 59171be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski} 59271be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski 593cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski} // namespace aapt 594