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