| /* |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "ResourceTable.h" |
| #include "ResourceValues.h" |
| #include "Util.h" |
| |
| #include <algorithm> |
| #include <gtest/gtest.h> |
| #include <ostream> |
| #include <string> |
| |
| namespace aapt { |
| |
| struct TestValue : public Value { |
| std::u16string value; |
| |
| TestValue(StringPiece16 str) : value(str.toString()) { |
| } |
| |
| TestValue* clone(StringPool* /*newPool*/) const override { |
| return new TestValue(value); |
| } |
| |
| void print(std::ostream& out) const override { |
| out << "(test) " << value; |
| } |
| |
| virtual void accept(ValueVisitor&, ValueVisitorArgs&&) override {} |
| virtual void accept(ConstValueVisitor&, ValueVisitorArgs&&) const override {} |
| }; |
| |
| struct TestWeakValue : public Value { |
| bool isWeak() const override { |
| return true; |
| } |
| |
| TestWeakValue* clone(StringPool* /*newPool*/) const override { |
| return new TestWeakValue(); |
| } |
| |
| void print(std::ostream& out) const override { |
| out << "(test) [weak]"; |
| } |
| |
| virtual void accept(ValueVisitor&, ValueVisitorArgs&&) override {} |
| virtual void accept(ConstValueVisitor&, ValueVisitorArgs&&) const override {} |
| }; |
| |
| TEST(ResourceTableTest, FailToAddResourceWithBadName) { |
| ResourceTable table; |
| table.setPackage(u"android"); |
| |
| EXPECT_FALSE(table.addResource( |
| ResourceNameRef{ u"android", ResourceType::kId, u"hey,there" }, |
| {}, SourceLine{ "test.xml", 21 }, |
| util::make_unique<TestValue>(u"rawValue"))); |
| |
| EXPECT_FALSE(table.addResource( |
| ResourceNameRef{ u"android", ResourceType::kId, u"hey:there" }, |
| {}, SourceLine{ "test.xml", 21 }, |
| util::make_unique<TestValue>(u"rawValue"))); |
| } |
| |
| TEST(ResourceTableTest, AddOneResource) { |
| const std::u16string kAndroidPackage = u"android"; |
| |
| ResourceTable table; |
| table.setPackage(kAndroidPackage); |
| |
| const ResourceName name = { kAndroidPackage, ResourceType::kAttr, u"id" }; |
| |
| EXPECT_TRUE(table.addResource(name, {}, SourceLine{ "test/path/file.xml", 23 }, |
| util::make_unique<TestValue>(u"rawValue"))); |
| |
| const ResourceTableType* type; |
| const ResourceEntry* entry; |
| std::tie(type, entry) = table.findResource(name); |
| ASSERT_NE(nullptr, type); |
| ASSERT_NE(nullptr, entry); |
| EXPECT_EQ(name.entry, entry->name); |
| |
| ASSERT_NE(std::end(entry->values), |
| std::find_if(std::begin(entry->values), std::end(entry->values), |
| [](const ResourceConfigValue& val) -> bool { |
| return val.config == ConfigDescription{}; |
| })); |
| } |
| |
| TEST(ResourceTableTest, AddMultipleResources) { |
| const std::u16string kAndroidPackage = u"android"; |
| ResourceTable table; |
| table.setPackage(kAndroidPackage); |
| |
| ConfigDescription config; |
| ConfigDescription languageConfig; |
| memcpy(languageConfig.language, "pl", sizeof(languageConfig.language)); |
| |
| EXPECT_TRUE(table.addResource( |
| ResourceName{ kAndroidPackage, ResourceType::kAttr, u"layout_width" }, |
| config, SourceLine{ "test/path/file.xml", 10 }, |
| util::make_unique<TestValue>(u"rawValue"))); |
| |
| EXPECT_TRUE(table.addResource( |
| ResourceName{ kAndroidPackage, ResourceType::kAttr, u"id" }, |
| config, SourceLine{ "test/path/file.xml", 12 }, |
| util::make_unique<TestValue>(u"rawValue"))); |
| |
| EXPECT_TRUE(table.addResource( |
| ResourceName{ kAndroidPackage, ResourceType::kString, u"ok" }, |
| config, SourceLine{ "test/path/file.xml", 14 }, |
| util::make_unique<TestValue>(u"Ok"))); |
| |
| EXPECT_TRUE(table.addResource( |
| ResourceName{ kAndroidPackage, ResourceType::kString, u"ok" }, |
| languageConfig, SourceLine{ "test/path/file.xml", 20 }, |
| util::make_unique<TestValue>(u"Tak"))); |
| |
| const auto endTypeIter = std::end(table); |
| auto typeIter = std::begin(table); |
| |
| ASSERT_NE(endTypeIter, typeIter); |
| EXPECT_EQ(ResourceType::kAttr, (*typeIter)->type); |
| |
| { |
| const std::unique_ptr<ResourceTableType>& type = *typeIter; |
| const auto endEntryIter = std::end(type->entries); |
| auto entryIter = std::begin(type->entries); |
| ASSERT_NE(endEntryIter, entryIter); |
| EXPECT_EQ(std::u16string(u"id"), (*entryIter)->name); |
| |
| ++entryIter; |
| ASSERT_NE(endEntryIter, entryIter); |
| EXPECT_EQ(std::u16string(u"layout_width"), (*entryIter)->name); |
| |
| ++entryIter; |
| ASSERT_EQ(endEntryIter, entryIter); |
| } |
| |
| ++typeIter; |
| ASSERT_NE(endTypeIter, typeIter); |
| EXPECT_EQ(ResourceType::kString, (*typeIter)->type); |
| |
| { |
| const std::unique_ptr<ResourceTableType>& type = *typeIter; |
| const auto endEntryIter = std::end(type->entries); |
| auto entryIter = std::begin(type->entries); |
| ASSERT_NE(endEntryIter, entryIter); |
| EXPECT_EQ(std::u16string(u"ok"), (*entryIter)->name); |
| |
| { |
| const std::unique_ptr<ResourceEntry>& entry = *entryIter; |
| const auto endConfigIter = std::end(entry->values); |
| auto configIter = std::begin(entry->values); |
| |
| ASSERT_NE(endConfigIter, configIter); |
| EXPECT_EQ(config, configIter->config); |
| const TestValue* value = |
| dynamic_cast<const TestValue*>(configIter->value.get()); |
| ASSERT_NE(nullptr, value); |
| EXPECT_EQ(std::u16string(u"Ok"), value->value); |
| |
| ++configIter; |
| ASSERT_NE(endConfigIter, configIter); |
| EXPECT_EQ(languageConfig, configIter->config); |
| EXPECT_NE(nullptr, configIter->value); |
| |
| value = dynamic_cast<const TestValue*>(configIter->value.get()); |
| ASSERT_NE(nullptr, value); |
| EXPECT_EQ(std::u16string(u"Tak"), value->value); |
| |
| ++configIter; |
| EXPECT_EQ(endConfigIter, configIter); |
| } |
| |
| ++entryIter; |
| ASSERT_EQ(endEntryIter, entryIter); |
| } |
| |
| ++typeIter; |
| EXPECT_EQ(endTypeIter, typeIter); |
| } |
| |
| TEST(ResourceTableTest, OverrideWeakResourceValue) { |
| const std::u16string kAndroid = u"android"; |
| |
| ResourceTable table; |
| table.setPackage(kAndroid); |
| table.setPackageId(0x01); |
| |
| ASSERT_TRUE(table.addResource( |
| ResourceName{ kAndroid, ResourceType::kAttr, u"foo" }, |
| {}, {}, util::make_unique<TestWeakValue>())); |
| |
| const ResourceTableType* type; |
| const ResourceEntry* entry; |
| std::tie(type, entry) = table.findResource( |
| ResourceNameRef{ kAndroid, ResourceType::kAttr, u"foo" }); |
| ASSERT_NE(nullptr, type); |
| ASSERT_NE(nullptr, entry); |
| ASSERT_EQ(entry->values.size(), 1u); |
| EXPECT_TRUE(entry->values.front().value->isWeak()); |
| |
| ASSERT_TRUE(table.addResource(ResourceName{ kAndroid, ResourceType::kAttr, u"foo" }, {}, {}, |
| util::make_unique<TestValue>(u"bar"))); |
| |
| std::tie(type, entry) = table.findResource( |
| ResourceNameRef{ kAndroid, ResourceType::kAttr, u"foo" }); |
| ASSERT_NE(nullptr, type); |
| ASSERT_NE(nullptr, entry); |
| ASSERT_EQ(entry->values.size(), 1u); |
| EXPECT_FALSE(entry->values.front().value->isWeak()); |
| } |
| |
| } // namespace aapt |