TableProtoSerializer_test.cpp revision 58a20a6482a56a262fd83a617482641e3a981db1
1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "ResourceTable.h" 18#include "proto/ProtoSerialize.h" 19#include "test/Test.h" 20 21namespace aapt { 22 23TEST(TableProtoSerializer, SerializeSinglePackage) { 24 std::unique_ptr<IAaptContext> context = test::ContextBuilder().build(); 25 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder() 26 .setPackageId("com.app.a", 0x7f) 27 .addFileReference("com.app.a:layout/main", ResourceId(0x7f020000), 28 "res/layout/main.xml") 29 .addReference("com.app.a:layout/other", ResourceId(0x7f020001), 30 "com.app.a:layout/main") 31 .addString("com.app.a:string/text", {}, "hi") 32 .addValue("com.app.a:id/foo", {}, util::make_unique<Id>()) 33 .build(); 34 35 Symbol publicSymbol; 36 publicSymbol.state = SymbolState::kPublic; 37 ASSERT_TRUE(table->setSymbolState(test::parseNameOrDie("com.app.a:layout/main"), 38 ResourceId(0x7f020000), 39 publicSymbol, context->getDiagnostics())); 40 41 Id* id = test::getValue<Id>(table.get(), "com.app.a:id/foo"); 42 ASSERT_NE(nullptr, id); 43 44 // Make a plural. 45 std::unique_ptr<Plural> plural = util::make_unique<Plural>(); 46 plural->values[Plural::One] = util::make_unique<String>(table->stringPool.makeRef("one")); 47 ASSERT_TRUE(table->addResource(test::parseNameOrDie("com.app.a:plurals/hey"), 48 ConfigDescription{}, {}, std::move(plural), 49 context->getDiagnostics())); 50 51 // Make a resource with different products. 52 ASSERT_TRUE(table->addResource(test::parseNameOrDie("com.app.a:integer/one"), 53 test::parseConfigOrDie("land"), {}, 54 test::buildPrimitive(android::Res_value::TYPE_INT_DEC, 123u), 55 context->getDiagnostics())); 56 ASSERT_TRUE(table->addResource(test::parseNameOrDie("com.app.a:integer/one"), 57 test::parseConfigOrDie("land"), "tablet", 58 test::buildPrimitive(android::Res_value::TYPE_INT_DEC, 321u), 59 context->getDiagnostics())); 60 61 // Make a reference with both resource name and resource ID. 62 // The reference should point to a resource outside of this table to test that both 63 // name and id get serialized. 64 Reference expectedRef; 65 expectedRef.name = test::parseNameOrDie("android:layout/main"); 66 expectedRef.id = ResourceId(0x01020000); 67 ASSERT_TRUE(table->addResource(test::parseNameOrDie("com.app.a:layout/abc"), 68 ConfigDescription::defaultConfig(), {}, 69 util::make_unique<Reference>(expectedRef), 70 context->getDiagnostics())); 71 72 std::unique_ptr<pb::ResourceTable> pbTable = serializeTableToPb(table.get()); 73 ASSERT_NE(nullptr, pbTable); 74 75 std::unique_ptr<ResourceTable> newTable = deserializeTableFromPb(*pbTable, 76 Source{ "test" }, 77 context->getDiagnostics()); 78 ASSERT_NE(nullptr, newTable); 79 80 Id* newId = test::getValue<Id>(newTable.get(), "com.app.a:id/foo"); 81 ASSERT_NE(nullptr, newId); 82 EXPECT_EQ(id->isWeak(), newId->isWeak()); 83 84 Maybe<ResourceTable::SearchResult> result = newTable->findResource( 85 test::parseNameOrDie("com.app.a:layout/main")); 86 AAPT_ASSERT_TRUE(result); 87 EXPECT_EQ(SymbolState::kPublic, result.value().type->symbolStatus.state); 88 EXPECT_EQ(SymbolState::kPublic, result.value().entry->symbolStatus.state); 89 90 // Find the product-dependent values 91 BinaryPrimitive* prim = test::getValueForConfigAndProduct<BinaryPrimitive>( 92 newTable.get(), "com.app.a:integer/one", test::parseConfigOrDie("land"), ""); 93 ASSERT_NE(nullptr, prim); 94 EXPECT_EQ(123u, prim->value.data); 95 96 prim = test::getValueForConfigAndProduct<BinaryPrimitive>( 97 newTable.get(), "com.app.a:integer/one", test::parseConfigOrDie("land"), "tablet"); 98 ASSERT_NE(nullptr, prim); 99 EXPECT_EQ(321u, prim->value.data); 100 101 Reference* actualRef = test::getValue<Reference>(newTable.get(), "com.app.a:layout/abc"); 102 ASSERT_NE(nullptr, actualRef); 103 AAPT_ASSERT_TRUE(actualRef->name); 104 AAPT_ASSERT_TRUE(actualRef->id); 105 EXPECT_EQ(expectedRef.name.value(), actualRef->name.value()); 106 EXPECT_EQ(expectedRef.id.value(), actualRef->id.value()); 107} 108 109TEST(TableProtoSerializer, SerializeFileHeader) { 110 std::unique_ptr<IAaptContext> context = test::ContextBuilder().build(); 111 112 ResourceFile f; 113 f.config = test::parseConfigOrDie("hdpi-v9"); 114 f.name = test::parseNameOrDie("com.app.a:layout/main"); 115 f.source.path = "res/layout-hdpi-v9/main.xml"; 116 f.exportedSymbols.push_back(SourcedResourceName{ test::parseNameOrDie("id/unchecked"), 23u }); 117 118 const std::string expectedData = "1234"; 119 120 std::unique_ptr<pb::CompiledFile> pbFile = serializeCompiledFileToPb(f); 121 122 std::string outputStr; 123 { 124 google::protobuf::io::StringOutputStream outStream(&outputStr); 125 CompiledFileOutputStream outFileStream(&outStream, pbFile.get()); 126 127 ASSERT_TRUE(outFileStream.Write(expectedData.data(), expectedData.size())); 128 ASSERT_TRUE(outFileStream.Finish()); 129 } 130 131 CompiledFileInputStream inFileStream(outputStr.data(), outputStr.size()); 132 const pb::CompiledFile* newPbFile = inFileStream.CompiledFile(); 133 ASSERT_NE(nullptr, newPbFile); 134 135 std::unique_ptr<ResourceFile> file = deserializeCompiledFileFromPb(*newPbFile, Source("test"), 136 context->getDiagnostics()); 137 ASSERT_NE(nullptr, file); 138 139 std::string actualData((const char*)inFileStream.data(), inFileStream.size()); 140 EXPECT_EQ(expectedData, actualData); 141 EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(inFileStream.data()) & 0x03); 142 143 ASSERT_EQ(1u, file->exportedSymbols.size()); 144 EXPECT_EQ(test::parseNameOrDie("id/unchecked"), file->exportedSymbols[0].name); 145} 146 147TEST(TableProtoSerializer, DeserializeCorruptHeaderSafely) { 148 ResourceFile f; 149 std::unique_ptr<pb::CompiledFile> pbFile = serializeCompiledFileToPb(f); 150 151 const std::string expectedData = "1234"; 152 153 std::string outputStr; 154 { 155 google::protobuf::io::StringOutputStream outStream(&outputStr); 156 CompiledFileOutputStream outFileStream(&outStream, pbFile.get()); 157 158 ASSERT_TRUE(outFileStream.Write(expectedData.data(), expectedData.size())); 159 ASSERT_TRUE(outFileStream.Finish()); 160 } 161 162 outputStr[0] = 0xff; 163 164 CompiledFileInputStream inFileStream(outputStr.data(), outputStr.size()); 165 EXPECT_EQ(nullptr, inFileStream.CompiledFile()); 166 EXPECT_EQ(nullptr, inFileStream.data()); 167 EXPECT_EQ(0u, inFileStream.size()); 168} 169 170} // namespace aapt 171