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