blob: 06d8699730de0f3ebd5567a53096b836014b760d [file] [log] [blame]
/*
* 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