blob: 06d8699730de0f3ebd5567a53096b836014b760d [file] [log] [blame]
Adam Lesinski6f6ceb72014-11-14 14:48:12 -08001/*
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
Adam Lesinski769de982015-04-10 19:43:55 -070034 TestValue* clone(StringPool* /*newPool*/) const override {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080035 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
Adam Lesinski769de982015-04-10 19:43:55 -070051 TestWeakValue* clone(StringPool* /*newPool*/) const override {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080052 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