blob: ed8618289b7bc233b8bf4c651db07ef54eec294a [file] [log] [blame]
jdoerrie44efa9d2017-07-14 14:47:201// 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
14namespace base {
15
16namespace detail {
17
18namespace {
19
20// Implementation of std::equal variant that is missing in C++11.
21template <class BinaryPredicate, class InputIterator1, class InputIterator2>
22bool 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
36TEST(ValueIteratorsTest, SameDictStorage) {
37 static_assert(std::is_same<Value::DictStorage, DictStorage>::value,
38 "DictStorage differs between Value and Value Iterators.");
39}
40
41TEST(ValueIteratorsTest, IsAssignable) {
42 static_assert(
43 !std::is_assignable<dict_iterator::reference::first_type, std::string>(),
44 "Can assign strings to dict_iterator");
45
46 static_assert(
47 std::is_assignable<dict_iterator::reference::second_type, Value>(),
48 "Can't assign Values to dict_iterator");
49
50 static_assert(!std::is_assignable<const_dict_iterator::reference::first_type,
51 std::string>(),
52 "Can assign strings to const_dict_iterator");
53
54 static_assert(
55 !std::is_assignable<const_dict_iterator::reference::second_type, Value>(),
56 "Can assign Values to const_dict_iterator");
57}
58
59TEST(ValueIteratorsTest, DictIteratorOperatorStar) {
60 DictStorage storage;
Jeremy Roman9532f252017-08-16 23:27:2461 storage.emplace("0", std::make_unique<Value>(0));
jdoerrie44efa9d2017-07-14 14:47:2062
63 using iterator = dict_iterator;
64 iterator iter(storage.begin());
65 EXPECT_EQ("0", (*iter).first);
66 EXPECT_EQ(Value(0), (*iter).second);
67
68 (*iter).second = Value(1);
69 EXPECT_EQ(Value(1), *storage["0"]);
70}
71
72TEST(ValueIteratorsTest, DictIteratorOperatorArrow) {
73 DictStorage storage;
Jeremy Roman9532f252017-08-16 23:27:2474 storage.emplace("0", std::make_unique<Value>(0));
jdoerrie44efa9d2017-07-14 14:47:2075
76 using iterator = dict_iterator;
77 iterator iter(storage.begin());
78 EXPECT_EQ("0", iter->first);
79 EXPECT_EQ(Value(0), iter->second);
80
81 iter->second = Value(1);
82 EXPECT_EQ(Value(1), *storage["0"]);
83}
84
85TEST(ValueIteratorsTest, DictIteratorPreIncrement) {
86 DictStorage storage;
Jeremy Roman9532f252017-08-16 23:27:2487 storage.emplace("0", std::make_unique<Value>(0));
88 storage.emplace("1", std::make_unique<Value>(1));
jdoerrie44efa9d2017-07-14 14:47:2089
90 using iterator = dict_iterator;
91 iterator iter(storage.begin());
92 EXPECT_EQ("0", iter->first);
93 EXPECT_EQ(Value(0), iter->second);
94
95 iterator& iter_ref = ++iter;
96 EXPECT_EQ(&iter, &iter_ref);
97
98 EXPECT_EQ("1", iter_ref->first);
99 EXPECT_EQ(Value(1), iter_ref->second);
100}
101
102TEST(ValueIteratorsTest, DictIteratorPostIncrement) {
103 DictStorage storage;
Jeremy Roman9532f252017-08-16 23:27:24104 storage.emplace("0", std::make_unique<Value>(0));
105 storage.emplace("1", std::make_unique<Value>(1));
jdoerrie44efa9d2017-07-14 14:47:20106
107 using iterator = dict_iterator;
108 iterator iter(storage.begin());
109 iterator iter_old = iter++;
110
111 EXPECT_EQ("0", iter_old->first);
112 EXPECT_EQ(Value(0), iter_old->second);
113
114 EXPECT_EQ("1", iter->first);
115 EXPECT_EQ(Value(1), iter->second);
116}
117
118TEST(ValueIteratorsTest, DictIteratorPreDecrement) {
119 DictStorage storage;
Jeremy Roman9532f252017-08-16 23:27:24120 storage.emplace("0", std::make_unique<Value>(0));
121 storage.emplace("1", std::make_unique<Value>(1));
jdoerrie44efa9d2017-07-14 14:47:20122
123 using iterator = dict_iterator;
124 iterator iter(++storage.begin());
125 EXPECT_EQ("1", iter->first);
126 EXPECT_EQ(Value(1), iter->second);
127
128 iterator& iter_ref = --iter;
129 EXPECT_EQ(&iter, &iter_ref);
130
131 EXPECT_EQ("0", iter_ref->first);
132 EXPECT_EQ(Value(0), iter_ref->second);
133}
134
135TEST(ValueIteratorsTest, DictIteratorPostDecrement) {
136 DictStorage storage;
Jeremy Roman9532f252017-08-16 23:27:24137 storage.emplace("0", std::make_unique<Value>(0));
138 storage.emplace("1", std::make_unique<Value>(1));
jdoerrie44efa9d2017-07-14 14:47:20139
140 using iterator = dict_iterator;
141 iterator iter(++storage.begin());
142 iterator iter_old = iter--;
143
144 EXPECT_EQ("1", iter_old->first);
145 EXPECT_EQ(Value(1), iter_old->second);
146
147 EXPECT_EQ("0", iter->first);
148 EXPECT_EQ(Value(0), iter->second);
149}
150
151TEST(ValueIteratorsTest, DictIteratorOperatorEQ) {
152 DictStorage storage;
153 using iterator = dict_iterator;
154 EXPECT_EQ(iterator(storage.begin()), iterator(storage.begin()));
155 EXPECT_EQ(iterator(storage.end()), iterator(storage.end()));
156}
157
158TEST(ValueIteratorsTest, DictIteratorOperatorNE) {
159 DictStorage storage;
Jeremy Roman9532f252017-08-16 23:27:24160 storage.emplace("0", std::make_unique<Value>(0));
jdoerrie44efa9d2017-07-14 14:47:20161
162 using iterator = dict_iterator;
163 EXPECT_NE(iterator(storage.begin()), iterator(storage.end()));
164}
165
166TEST(ValueIteratorsTest, ConstDictIteratorOperatorStar) {
167 DictStorage storage;
Jeremy Roman9532f252017-08-16 23:27:24168 storage.emplace("0", std::make_unique<Value>(0));
jdoerrie44efa9d2017-07-14 14:47:20169
170 using iterator = const_dict_iterator;
171 iterator iter(storage.begin());
172 EXPECT_EQ("0", (*iter).first);
173 EXPECT_EQ(Value(0), (*iter).second);
174}
175
176TEST(ValueIteratorsTest, ConstDictIteratorOperatorArrow) {
177 DictStorage storage;
Jeremy Roman9532f252017-08-16 23:27:24178 storage.emplace("0", std::make_unique<Value>(0));
jdoerrie44efa9d2017-07-14 14:47:20179
180 using iterator = const_dict_iterator;
181 iterator iter(storage.begin());
182 EXPECT_EQ("0", iter->first);
183 EXPECT_EQ(Value(0), iter->second);
184}
185
186TEST(ValueIteratorsTest, ConstDictIteratorPreIncrement) {
187 DictStorage storage;
Jeremy Roman9532f252017-08-16 23:27:24188 storage.emplace("0", std::make_unique<Value>(0));
189 storage.emplace("1", std::make_unique<Value>(1));
jdoerrie44efa9d2017-07-14 14:47:20190
191 using iterator = const_dict_iterator;
192 iterator iter(storage.begin());
193 EXPECT_EQ("0", iter->first);
194 EXPECT_EQ(Value(0), iter->second);
195
196 iterator& iter_ref = ++iter;
197 EXPECT_EQ(&iter, &iter_ref);
198
199 EXPECT_EQ("1", iter_ref->first);
200 EXPECT_EQ(Value(1), iter_ref->second);
201}
202
203TEST(ValueIteratorsTest, ConstDictIteratorPostIncrement) {
204 DictStorage storage;
Jeremy Roman9532f252017-08-16 23:27:24205 storage.emplace("0", std::make_unique<Value>(0));
206 storage.emplace("1", std::make_unique<Value>(1));
jdoerrie44efa9d2017-07-14 14:47:20207
208 using iterator = const_dict_iterator;
209 iterator iter(storage.begin());
210 iterator iter_old = iter++;
211
212 EXPECT_EQ("0", iter_old->first);
213 EXPECT_EQ(Value(0), iter_old->second);
214
215 EXPECT_EQ("1", iter->first);
216 EXPECT_EQ(Value(1), iter->second);
217}
218
219TEST(ValueIteratorsTest, ConstDictIteratorPreDecrement) {
220 DictStorage storage;
Jeremy Roman9532f252017-08-16 23:27:24221 storage.emplace("0", std::make_unique<Value>(0));
222 storage.emplace("1", std::make_unique<Value>(1));
jdoerrie44efa9d2017-07-14 14:47:20223
224 using iterator = const_dict_iterator;
225 iterator iter(++storage.begin());
226 EXPECT_EQ("1", iter->first);
227 EXPECT_EQ(Value(1), iter->second);
228
229 iterator& iter_ref = --iter;
230 EXPECT_EQ(&iter, &iter_ref);
231
232 EXPECT_EQ("0", iter_ref->first);
233 EXPECT_EQ(Value(0), iter_ref->second);
234}
235
236TEST(ValueIteratorsTest, ConstDictIteratorPostDecrement) {
237 DictStorage storage;
Jeremy Roman9532f252017-08-16 23:27:24238 storage.emplace("0", std::make_unique<Value>(0));
239 storage.emplace("1", std::make_unique<Value>(1));
jdoerrie44efa9d2017-07-14 14:47:20240
241 using iterator = const_dict_iterator;
242 iterator iter(++storage.begin());
243 iterator iter_old = iter--;
244
245 EXPECT_EQ("1", iter_old->first);
246 EXPECT_EQ(Value(1), iter_old->second);
247
248 EXPECT_EQ("0", iter->first);
249 EXPECT_EQ(Value(0), iter->second);
250}
251
252TEST(ValueIteratorsTest, ConstDictIteratorOperatorEQ) {
253 DictStorage storage;
254 using iterator = const_dict_iterator;
255 EXPECT_EQ(iterator(storage.begin()), iterator(storage.begin()));
256 EXPECT_EQ(iterator(storage.end()), iterator(storage.end()));
257}
258
259TEST(ValueIteratorsTest, ConstDictIteratorOperatorNE) {
260 DictStorage storage;
Jeremy Roman9532f252017-08-16 23:27:24261 storage.emplace("0", std::make_unique<Value>(0));
jdoerrie44efa9d2017-07-14 14:47:20262
263 using iterator = const_dict_iterator;
264 EXPECT_NE(iterator(storage.begin()), iterator(storage.end()));
265}
266
267TEST(ValueIteratorsTest, DictIteratorProxy) {
268 DictStorage storage;
Jeremy Roman9532f252017-08-16 23:27:24269 storage.emplace("null", std::make_unique<Value>(Value::Type::NONE));
270 storage.emplace("bool", std::make_unique<Value>(Value::Type::BOOLEAN));
271 storage.emplace("int", std::make_unique<Value>(Value::Type::INTEGER));
272 storage.emplace("double", std::make_unique<Value>(Value::Type::DOUBLE));
273 storage.emplace("string", std::make_unique<Value>(Value::Type::STRING));
274 storage.emplace("blob", std::make_unique<Value>(Value::Type::BINARY));
275 storage.emplace("dict", std::make_unique<Value>(Value::Type::DICTIONARY));
276 storage.emplace("list", std::make_unique<Value>(Value::Type::LIST));
jdoerrie44efa9d2017-07-14 14:47:20277
jdoerriecc9f5732017-08-23 14:12:30278 using iterator = const_dict_iterator;
jdoerrie44efa9d2017-07-14 14:47:20279 using iterator_proxy = dict_iterator_proxy;
280 iterator_proxy proxy(&storage);
281
282 auto equal_to = [](const DictStorage::value_type& lhs,
jdoerriecc9f5732017-08-23 14:12:30283 const iterator::reference& rhs) {
jdoerrie44efa9d2017-07-14 14:47:20284 return std::tie(lhs.first, *lhs.second) == std::tie(rhs.first, rhs.second);
285 };
286
287 EXPECT_TRUE(are_equal(storage.begin(), storage.end(), proxy.begin(),
288 proxy.end(), equal_to));
289
290 EXPECT_TRUE(are_equal(storage.rbegin(), storage.rend(), proxy.rbegin(),
291 proxy.rend(), equal_to));
292
293 EXPECT_TRUE(are_equal(storage.cbegin(), storage.cend(), proxy.cbegin(),
294 proxy.cend(), equal_to));
295
296 EXPECT_TRUE(are_equal(storage.crbegin(), storage.crend(), proxy.crbegin(),
297 proxy.crend(), equal_to));
298}
299
300TEST(ValueIteratorsTest, ConstDictIteratorProxy) {
301 DictStorage storage;
Jeremy Roman9532f252017-08-16 23:27:24302 storage.emplace("null", std::make_unique<Value>(Value::Type::NONE));
303 storage.emplace("bool", std::make_unique<Value>(Value::Type::BOOLEAN));
304 storage.emplace("int", std::make_unique<Value>(Value::Type::INTEGER));
305 storage.emplace("double", std::make_unique<Value>(Value::Type::DOUBLE));
306 storage.emplace("string", std::make_unique<Value>(Value::Type::STRING));
307 storage.emplace("blob", std::make_unique<Value>(Value::Type::BINARY));
308 storage.emplace("dict", std::make_unique<Value>(Value::Type::DICTIONARY));
309 storage.emplace("list", std::make_unique<Value>(Value::Type::LIST));
jdoerrie44efa9d2017-07-14 14:47:20310
jdoerriecc9f5732017-08-23 14:12:30311 using iterator = const_dict_iterator;
jdoerrie44efa9d2017-07-14 14:47:20312 using iterator_proxy = const_dict_iterator_proxy;
313 iterator_proxy proxy(&storage);
314
315 auto equal_to = [](const DictStorage::value_type& lhs,
jdoerriecc9f5732017-08-23 14:12:30316 const iterator::reference& rhs) {
jdoerrie44efa9d2017-07-14 14:47:20317 return std::tie(lhs.first, *lhs.second) == std::tie(rhs.first, rhs.second);
318 };
319
320 EXPECT_TRUE(are_equal(storage.begin(), storage.end(), proxy.begin(),
321 proxy.end(), equal_to));
322
323 EXPECT_TRUE(are_equal(storage.rbegin(), storage.rend(), proxy.rbegin(),
324 proxy.rend(), equal_to));
325
326 EXPECT_TRUE(are_equal(storage.cbegin(), storage.cend(), proxy.cbegin(),
327 proxy.cend(), equal_to));
328
329 EXPECT_TRUE(are_equal(storage.crbegin(), storage.crend(), proxy.crbegin(),
330 proxy.crend(), equal_to));
331}
332
333} // namespace detail
334
335} // namespace base