1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/value_iterators.h"
6
7 #include <type_traits>
8
9 #include "base/memory/ptr_util.h"
10 #include "base/values.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace base {
15
16 namespace detail {
17
18 namespace {
19
20 // Implementation of std::equal variant that is missing in C++11.
21 template <class BinaryPredicate, class InputIterator1, class InputIterator2>
are_equal(InputIterator1 first1,InputIterator1 last1,InputIterator2 first2,InputIterator2 last2,BinaryPredicate pred)22 bool are_equal(InputIterator1 first1,
23 InputIterator1 last1,
24 InputIterator2 first2,
25 InputIterator2 last2,
26 BinaryPredicate pred) {
27 for (; first1 != last1 && first2 != last2; ++first1, ++first2) {
28 if (!pred(*first1, *first2))
29 return false;
30 }
31 return first1 == last1 && first2 == last2;
32 }
33
34 } // namespace
35
TEST(ValueIteratorsTest,IsAssignable)36 TEST(ValueIteratorsTest, IsAssignable) {
37 static_assert(
38 !std::is_assignable<dict_iterator::reference::first_type, std::string>(),
39 "Can assign strings to dict_iterator");
40
41 static_assert(
42 std::is_assignable<dict_iterator::reference::second_type, Value>(),
43 "Can't assign Values to dict_iterator");
44
45 static_assert(!std::is_assignable<const_dict_iterator::reference::first_type,
46 std::string>(),
47 "Can assign strings to const_dict_iterator");
48
49 static_assert(
50 !std::is_assignable<const_dict_iterator::reference::second_type, Value>(),
51 "Can assign Values to const_dict_iterator");
52 }
53
TEST(ValueIteratorsTest,DictIteratorOperatorStar)54 TEST(ValueIteratorsTest, DictIteratorOperatorStar) {
55 DictStorage storage;
56 storage.emplace("0", std::make_unique<Value>(0));
57
58 using iterator = dict_iterator;
59 iterator iter(storage.begin());
60 EXPECT_EQ("0", (*iter).first);
61 EXPECT_EQ(Value(0), (*iter).second);
62
63 (*iter).second = Value(1);
64 EXPECT_EQ(Value(1), *storage["0"]);
65 }
66
TEST(ValueIteratorsTest,DictIteratorOperatorArrow)67 TEST(ValueIteratorsTest, DictIteratorOperatorArrow) {
68 DictStorage storage;
69 storage.emplace("0", std::make_unique<Value>(0));
70
71 using iterator = dict_iterator;
72 iterator iter(storage.begin());
73 EXPECT_EQ("0", iter->first);
74 EXPECT_EQ(Value(0), iter->second);
75
76 iter->second = Value(1);
77 EXPECT_EQ(Value(1), *storage["0"]);
78 }
79
TEST(ValueIteratorsTest,DictIteratorPreIncrement)80 TEST(ValueIteratorsTest, DictIteratorPreIncrement) {
81 DictStorage storage;
82 storage.emplace("0", std::make_unique<Value>(0));
83 storage.emplace("1", std::make_unique<Value>(1));
84
85 using iterator = dict_iterator;
86 iterator iter(storage.begin());
87 EXPECT_EQ("0", iter->first);
88 EXPECT_EQ(Value(0), iter->second);
89
90 iterator& iter_ref = ++iter;
91 EXPECT_EQ(&iter, &iter_ref);
92
93 EXPECT_EQ("1", iter_ref->first);
94 EXPECT_EQ(Value(1), iter_ref->second);
95 }
96
TEST(ValueIteratorsTest,DictIteratorPostIncrement)97 TEST(ValueIteratorsTest, DictIteratorPostIncrement) {
98 DictStorage storage;
99 storage.emplace("0", std::make_unique<Value>(0));
100 storage.emplace("1", std::make_unique<Value>(1));
101
102 using iterator = dict_iterator;
103 iterator iter(storage.begin());
104 iterator iter_old = iter++;
105
106 EXPECT_EQ("0", iter_old->first);
107 EXPECT_EQ(Value(0), iter_old->second);
108
109 EXPECT_EQ("1", iter->first);
110 EXPECT_EQ(Value(1), iter->second);
111 }
112
TEST(ValueIteratorsTest,DictIteratorPreDecrement)113 TEST(ValueIteratorsTest, DictIteratorPreDecrement) {
114 DictStorage storage;
115 storage.emplace("0", std::make_unique<Value>(0));
116 storage.emplace("1", std::make_unique<Value>(1));
117
118 using iterator = dict_iterator;
119 iterator iter(++storage.begin());
120 EXPECT_EQ("1", iter->first);
121 EXPECT_EQ(Value(1), iter->second);
122
123 iterator& iter_ref = --iter;
124 EXPECT_EQ(&iter, &iter_ref);
125
126 EXPECT_EQ("0", iter_ref->first);
127 EXPECT_EQ(Value(0), iter_ref->second);
128 }
129
TEST(ValueIteratorsTest,DictIteratorPostDecrement)130 TEST(ValueIteratorsTest, DictIteratorPostDecrement) {
131 DictStorage storage;
132 storage.emplace("0", std::make_unique<Value>(0));
133 storage.emplace("1", std::make_unique<Value>(1));
134
135 using iterator = dict_iterator;
136 iterator iter(++storage.begin());
137 iterator iter_old = iter--;
138
139 EXPECT_EQ("1", iter_old->first);
140 EXPECT_EQ(Value(1), iter_old->second);
141
142 EXPECT_EQ("0", iter->first);
143 EXPECT_EQ(Value(0), iter->second);
144 }
145
TEST(ValueIteratorsTest,DictIteratorOperatorEQ)146 TEST(ValueIteratorsTest, DictIteratorOperatorEQ) {
147 DictStorage storage;
148 using iterator = dict_iterator;
149 EXPECT_EQ(iterator(storage.begin()), iterator(storage.begin()));
150 EXPECT_EQ(iterator(storage.end()), iterator(storage.end()));
151 }
152
TEST(ValueIteratorsTest,DictIteratorOperatorNE)153 TEST(ValueIteratorsTest, DictIteratorOperatorNE) {
154 DictStorage storage;
155 storage.emplace("0", std::make_unique<Value>(0));
156
157 using iterator = dict_iterator;
158 EXPECT_NE(iterator(storage.begin()), iterator(storage.end()));
159 }
160
TEST(ValueIteratorsTest,ConstDictIteratorOperatorStar)161 TEST(ValueIteratorsTest, ConstDictIteratorOperatorStar) {
162 DictStorage storage;
163 storage.emplace("0", std::make_unique<Value>(0));
164
165 using iterator = const_dict_iterator;
166 iterator iter(storage.begin());
167 EXPECT_EQ("0", (*iter).first);
168 EXPECT_EQ(Value(0), (*iter).second);
169 }
170
TEST(ValueIteratorsTest,ConstDictIteratorOperatorArrow)171 TEST(ValueIteratorsTest, ConstDictIteratorOperatorArrow) {
172 DictStorage storage;
173 storage.emplace("0", std::make_unique<Value>(0));
174
175 using iterator = const_dict_iterator;
176 iterator iter(storage.begin());
177 EXPECT_EQ("0", iter->first);
178 EXPECT_EQ(Value(0), iter->second);
179 }
180
TEST(ValueIteratorsTest,ConstDictIteratorPreIncrement)181 TEST(ValueIteratorsTest, ConstDictIteratorPreIncrement) {
182 DictStorage storage;
183 storage.emplace("0", std::make_unique<Value>(0));
184 storage.emplace("1", std::make_unique<Value>(1));
185
186 using iterator = const_dict_iterator;
187 iterator iter(storage.begin());
188 EXPECT_EQ("0", iter->first);
189 EXPECT_EQ(Value(0), iter->second);
190
191 iterator& iter_ref = ++iter;
192 EXPECT_EQ(&iter, &iter_ref);
193
194 EXPECT_EQ("1", iter_ref->first);
195 EXPECT_EQ(Value(1), iter_ref->second);
196 }
197
TEST(ValueIteratorsTest,ConstDictIteratorPostIncrement)198 TEST(ValueIteratorsTest, ConstDictIteratorPostIncrement) {
199 DictStorage storage;
200 storage.emplace("0", std::make_unique<Value>(0));
201 storage.emplace("1", std::make_unique<Value>(1));
202
203 using iterator = const_dict_iterator;
204 iterator iter(storage.begin());
205 iterator iter_old = iter++;
206
207 EXPECT_EQ("0", iter_old->first);
208 EXPECT_EQ(Value(0), iter_old->second);
209
210 EXPECT_EQ("1", iter->first);
211 EXPECT_EQ(Value(1), iter->second);
212 }
213
TEST(ValueIteratorsTest,ConstDictIteratorPreDecrement)214 TEST(ValueIteratorsTest, ConstDictIteratorPreDecrement) {
215 DictStorage storage;
216 storage.emplace("0", std::make_unique<Value>(0));
217 storage.emplace("1", std::make_unique<Value>(1));
218
219 using iterator = const_dict_iterator;
220 iterator iter(++storage.begin());
221 EXPECT_EQ("1", iter->first);
222 EXPECT_EQ(Value(1), iter->second);
223
224 iterator& iter_ref = --iter;
225 EXPECT_EQ(&iter, &iter_ref);
226
227 EXPECT_EQ("0", iter_ref->first);
228 EXPECT_EQ(Value(0), iter_ref->second);
229 }
230
TEST(ValueIteratorsTest,ConstDictIteratorPostDecrement)231 TEST(ValueIteratorsTest, ConstDictIteratorPostDecrement) {
232 DictStorage storage;
233 storage.emplace("0", std::make_unique<Value>(0));
234 storage.emplace("1", std::make_unique<Value>(1));
235
236 using iterator = const_dict_iterator;
237 iterator iter(++storage.begin());
238 iterator iter_old = iter--;
239
240 EXPECT_EQ("1", iter_old->first);
241 EXPECT_EQ(Value(1), iter_old->second);
242
243 EXPECT_EQ("0", iter->first);
244 EXPECT_EQ(Value(0), iter->second);
245 }
246
TEST(ValueIteratorsTest,ConstDictIteratorOperatorEQ)247 TEST(ValueIteratorsTest, ConstDictIteratorOperatorEQ) {
248 DictStorage storage;
249 using iterator = const_dict_iterator;
250 EXPECT_EQ(iterator(storage.begin()), iterator(storage.begin()));
251 EXPECT_EQ(iterator(storage.end()), iterator(storage.end()));
252 }
253
TEST(ValueIteratorsTest,ConstDictIteratorOperatorNE)254 TEST(ValueIteratorsTest, ConstDictIteratorOperatorNE) {
255 DictStorage storage;
256 storage.emplace("0", std::make_unique<Value>(0));
257
258 using iterator = const_dict_iterator;
259 EXPECT_NE(iterator(storage.begin()), iterator(storage.end()));
260 }
261
TEST(ValueIteratorsTest,DictIteratorProxy)262 TEST(ValueIteratorsTest, DictIteratorProxy) {
263 DictStorage storage;
264 storage.emplace("null", std::make_unique<Value>(Value::Type::NONE));
265 storage.emplace("bool", std::make_unique<Value>(Value::Type::BOOLEAN));
266 storage.emplace("int", std::make_unique<Value>(Value::Type::INTEGER));
267 storage.emplace("double", std::make_unique<Value>(Value::Type::DOUBLE));
268 storage.emplace("string", std::make_unique<Value>(Value::Type::STRING));
269 storage.emplace("blob", std::make_unique<Value>(Value::Type::BINARY));
270 storage.emplace("dict", std::make_unique<Value>(Value::Type::DICTIONARY));
271 storage.emplace("list", std::make_unique<Value>(Value::Type::LIST));
272
273 using iterator = const_dict_iterator;
274 using iterator_proxy = dict_iterator_proxy;
275 iterator_proxy proxy(&storage);
276
277 auto equal_to = [](const DictStorage::value_type& lhs,
278 const iterator::reference& rhs) {
279 return std::tie(lhs.first, *lhs.second) == std::tie(rhs.first, rhs.second);
280 };
281
282 EXPECT_TRUE(are_equal(storage.begin(), storage.end(), proxy.begin(),
283 proxy.end(), equal_to));
284
285 EXPECT_TRUE(are_equal(storage.rbegin(), storage.rend(), proxy.rbegin(),
286 proxy.rend(), equal_to));
287
288 EXPECT_TRUE(are_equal(storage.cbegin(), storage.cend(), proxy.cbegin(),
289 proxy.cend(), equal_to));
290
291 EXPECT_TRUE(are_equal(storage.crbegin(), storage.crend(), proxy.crbegin(),
292 proxy.crend(), equal_to));
293 }
294
TEST(ValueIteratorsTest,ConstDictIteratorProxy)295 TEST(ValueIteratorsTest, ConstDictIteratorProxy) {
296 DictStorage storage;
297 storage.emplace("null", std::make_unique<Value>(Value::Type::NONE));
298 storage.emplace("bool", std::make_unique<Value>(Value::Type::BOOLEAN));
299 storage.emplace("int", std::make_unique<Value>(Value::Type::INTEGER));
300 storage.emplace("double", std::make_unique<Value>(Value::Type::DOUBLE));
301 storage.emplace("string", std::make_unique<Value>(Value::Type::STRING));
302 storage.emplace("blob", std::make_unique<Value>(Value::Type::BINARY));
303 storage.emplace("dict", std::make_unique<Value>(Value::Type::DICTIONARY));
304 storage.emplace("list", std::make_unique<Value>(Value::Type::LIST));
305
306 using iterator = const_dict_iterator;
307 using iterator_proxy = const_dict_iterator_proxy;
308 iterator_proxy proxy(&storage);
309
310 auto equal_to = [](const DictStorage::value_type& lhs,
311 const iterator::reference& rhs) {
312 return std::tie(lhs.first, *lhs.second) == std::tie(rhs.first, rhs.second);
313 };
314
315 EXPECT_TRUE(are_equal(storage.begin(), storage.end(), proxy.begin(),
316 proxy.end(), equal_to));
317
318 EXPECT_TRUE(are_equal(storage.rbegin(), storage.rend(), proxy.rbegin(),
319 proxy.rend(), equal_to));
320
321 EXPECT_TRUE(are_equal(storage.cbegin(), storage.cend(), proxy.cbegin(),
322 proxy.cend(), equal_to));
323
324 EXPECT_TRUE(are_equal(storage.crbegin(), storage.crend(), proxy.crbegin(),
325 proxy.crend(), equal_to));
326 }
327
328 } // namespace detail
329
330 } // namespace base
331