ResourceTable_test.cpp revision 6f6ceb7e1456698b1f33e04536bfb3227f9fcfcb
1/* 2 * Copyright (C) 2015 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 "ResourceValues.h" 19#include "Util.h" 20 21#include <algorithm> 22#include <gtest/gtest.h> 23#include <ostream> 24#include <string> 25 26namespace aapt { 27 28struct TestValue : public Value { 29 std::u16string value; 30 31 TestValue(StringPiece16 str) : value(str.toString()) { 32 } 33 34 TestValue* clone() const override { 35 return new TestValue(value); 36 } 37 38 void print(std::ostream& out) const override { 39 out << "(test) " << value; 40 } 41 42 virtual void accept(ValueVisitor&, ValueVisitorArgs&&) override {} 43 virtual void accept(ConstValueVisitor&, ValueVisitorArgs&&) const override {} 44}; 45 46struct TestWeakValue : public Value { 47 bool isWeak() const override { 48 return true; 49 } 50 51 TestWeakValue* clone() const override { 52 return new TestWeakValue(); 53 } 54 55 void print(std::ostream& out) const override { 56 out << "(test) [weak]"; 57 } 58 59 virtual void accept(ValueVisitor&, ValueVisitorArgs&&) override {} 60 virtual void accept(ConstValueVisitor&, ValueVisitorArgs&&) const override {} 61}; 62 63TEST(ResourceTableTest, FailToAddResourceWithBadName) { 64 ResourceTable table; 65 table.setPackage(u"android"); 66 67 EXPECT_FALSE(table.addResource( 68 ResourceNameRef{ u"android", ResourceType::kId, u"hey,there" }, 69 {}, SourceLine{ "test.xml", 21 }, 70 util::make_unique<TestValue>(u"rawValue"))); 71 72 EXPECT_FALSE(table.addResource( 73 ResourceNameRef{ u"android", ResourceType::kId, u"hey:there" }, 74 {}, SourceLine{ "test.xml", 21 }, 75 util::make_unique<TestValue>(u"rawValue"))); 76} 77 78TEST(ResourceTableTest, AddOneResource) { 79 const std::u16string kAndroidPackage = u"android"; 80 81 ResourceTable table; 82 table.setPackage(kAndroidPackage); 83 84 const ResourceName name = { kAndroidPackage, ResourceType::kAttr, u"id" }; 85 86 EXPECT_TRUE(table.addResource(name, {}, SourceLine{ "test/path/file.xml", 23 }, 87 util::make_unique<TestValue>(u"rawValue"))); 88 89 const ResourceTableType* type; 90 const ResourceEntry* entry; 91 std::tie(type, entry) = table.findResource(name); 92 ASSERT_NE(nullptr, type); 93 ASSERT_NE(nullptr, entry); 94 EXPECT_EQ(name.entry, entry->name); 95 96 ASSERT_NE(std::end(entry->values), 97 std::find_if(std::begin(entry->values), std::end(entry->values), 98 [](const ResourceConfigValue& val) -> bool { 99 return val.config == ConfigDescription{}; 100 })); 101} 102 103TEST(ResourceTableTest, AddMultipleResources) { 104 const std::u16string kAndroidPackage = u"android"; 105 ResourceTable table; 106 table.setPackage(kAndroidPackage); 107 108 ConfigDescription config; 109 ConfigDescription languageConfig; 110 memcpy(languageConfig.language, "pl", sizeof(languageConfig.language)); 111 112 EXPECT_TRUE(table.addResource( 113 ResourceName{ kAndroidPackage, ResourceType::kAttr, u"layout_width" }, 114 config, SourceLine{ "test/path/file.xml", 10 }, 115 util::make_unique<TestValue>(u"rawValue"))); 116 117 EXPECT_TRUE(table.addResource( 118 ResourceName{ kAndroidPackage, ResourceType::kAttr, u"id" }, 119 config, SourceLine{ "test/path/file.xml", 12 }, 120 util::make_unique<TestValue>(u"rawValue"))); 121 122 EXPECT_TRUE(table.addResource( 123 ResourceName{ kAndroidPackage, ResourceType::kString, u"ok" }, 124 config, SourceLine{ "test/path/file.xml", 14 }, 125 util::make_unique<TestValue>(u"Ok"))); 126 127 EXPECT_TRUE(table.addResource( 128 ResourceName{ kAndroidPackage, ResourceType::kString, u"ok" }, 129 languageConfig, SourceLine{ "test/path/file.xml", 20 }, 130 util::make_unique<TestValue>(u"Tak"))); 131 132 const auto endTypeIter = std::end(table); 133 auto typeIter = std::begin(table); 134 135 ASSERT_NE(endTypeIter, typeIter); 136 EXPECT_EQ(ResourceType::kAttr, (*typeIter)->type); 137 138 { 139 const std::unique_ptr<ResourceTableType>& type = *typeIter; 140 const auto endEntryIter = std::end(type->entries); 141 auto entryIter = std::begin(type->entries); 142 ASSERT_NE(endEntryIter, entryIter); 143 EXPECT_EQ(std::u16string(u"id"), (*entryIter)->name); 144 145 ++entryIter; 146 ASSERT_NE(endEntryIter, entryIter); 147 EXPECT_EQ(std::u16string(u"layout_width"), (*entryIter)->name); 148 149 ++entryIter; 150 ASSERT_EQ(endEntryIter, entryIter); 151 } 152 153 ++typeIter; 154 ASSERT_NE(endTypeIter, typeIter); 155 EXPECT_EQ(ResourceType::kString, (*typeIter)->type); 156 157 { 158 const std::unique_ptr<ResourceTableType>& type = *typeIter; 159 const auto endEntryIter = std::end(type->entries); 160 auto entryIter = std::begin(type->entries); 161 ASSERT_NE(endEntryIter, entryIter); 162 EXPECT_EQ(std::u16string(u"ok"), (*entryIter)->name); 163 164 { 165 const std::unique_ptr<ResourceEntry>& entry = *entryIter; 166 const auto endConfigIter = std::end(entry->values); 167 auto configIter = std::begin(entry->values); 168 169 ASSERT_NE(endConfigIter, configIter); 170 EXPECT_EQ(config, configIter->config); 171 const TestValue* value = 172 dynamic_cast<const TestValue*>(configIter->value.get()); 173 ASSERT_NE(nullptr, value); 174 EXPECT_EQ(std::u16string(u"Ok"), value->value); 175 176 ++configIter; 177 ASSERT_NE(endConfigIter, configIter); 178 EXPECT_EQ(languageConfig, configIter->config); 179 EXPECT_NE(nullptr, configIter->value); 180 181 value = dynamic_cast<const TestValue*>(configIter->value.get()); 182 ASSERT_NE(nullptr, value); 183 EXPECT_EQ(std::u16string(u"Tak"), value->value); 184 185 ++configIter; 186 EXPECT_EQ(endConfigIter, configIter); 187 } 188 189 ++entryIter; 190 ASSERT_EQ(endEntryIter, entryIter); 191 } 192 193 ++typeIter; 194 EXPECT_EQ(endTypeIter, typeIter); 195} 196 197TEST(ResourceTableTest, OverrideWeakResourceValue) { 198 const std::u16string kAndroid = u"android"; 199 200 ResourceTable table; 201 table.setPackage(kAndroid); 202 table.setPackageId(0x01); 203 204 ASSERT_TRUE(table.addResource( 205 ResourceName{ kAndroid, ResourceType::kAttr, u"foo" }, 206 {}, {}, util::make_unique<TestWeakValue>())); 207 208 const ResourceTableType* type; 209 const ResourceEntry* entry; 210 std::tie(type, entry) = table.findResource( 211 ResourceNameRef{ kAndroid, ResourceType::kAttr, u"foo" }); 212 ASSERT_NE(nullptr, type); 213 ASSERT_NE(nullptr, entry); 214 ASSERT_EQ(entry->values.size(), 1u); 215 EXPECT_TRUE(entry->values.front().value->isWeak()); 216 217 ASSERT_TRUE(table.addResource(ResourceName{ kAndroid, ResourceType::kAttr, u"foo" }, {}, {}, 218 util::make_unique<TestValue>(u"bar"))); 219 220 std::tie(type, entry) = table.findResource( 221 ResourceNameRef{ kAndroid, ResourceType::kAttr, u"foo" }); 222 ASSERT_NE(nullptr, type); 223 ASSERT_NE(nullptr, entry); 224 ASSERT_EQ(entry->values.size(), 1u); 225 EXPECT_FALSE(entry->values.front().value->isWeak()); 226} 227 228} // namespace aapt 229