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,SameDictStorage)36 TEST(ValueIteratorsTest, SameDictStorage) {
37   static_assert(std::is_same<Value::DictStorage, DictStorage>::value,
38                 "DictStorage differs between Value and Value Iterators.");
39 }
40 
TEST(ValueIteratorsTest,IsAssignable)41 TEST(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 
TEST(ValueIteratorsTest,DictIteratorOperatorStar)59 TEST(ValueIteratorsTest, DictIteratorOperatorStar) {
60   DictStorage storage;
61   storage.emplace("0", std::make_unique<Value>(0));
62 
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 
TEST(ValueIteratorsTest,DictIteratorOperatorArrow)72 TEST(ValueIteratorsTest, DictIteratorOperatorArrow) {
73   DictStorage storage;
74   storage.emplace("0", std::make_unique<Value>(0));
75 
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 
TEST(ValueIteratorsTest,DictIteratorPreIncrement)85 TEST(ValueIteratorsTest, DictIteratorPreIncrement) {
86   DictStorage storage;
87   storage.emplace("0", std::make_unique<Value>(0));
88   storage.emplace("1", std::make_unique<Value>(1));
89 
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 
TEST(ValueIteratorsTest,DictIteratorPostIncrement)102 TEST(ValueIteratorsTest, DictIteratorPostIncrement) {
103   DictStorage storage;
104   storage.emplace("0", std::make_unique<Value>(0));
105   storage.emplace("1", std::make_unique<Value>(1));
106 
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 
TEST(ValueIteratorsTest,DictIteratorPreDecrement)118 TEST(ValueIteratorsTest, DictIteratorPreDecrement) {
119   DictStorage storage;
120   storage.emplace("0", std::make_unique<Value>(0));
121   storage.emplace("1", std::make_unique<Value>(1));
122 
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 
TEST(ValueIteratorsTest,DictIteratorPostDecrement)135 TEST(ValueIteratorsTest, DictIteratorPostDecrement) {
136   DictStorage storage;
137   storage.emplace("0", std::make_unique<Value>(0));
138   storage.emplace("1", std::make_unique<Value>(1));
139 
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 
TEST(ValueIteratorsTest,DictIteratorOperatorEQ)151 TEST(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 
TEST(ValueIteratorsTest,DictIteratorOperatorNE)158 TEST(ValueIteratorsTest, DictIteratorOperatorNE) {
159   DictStorage storage;
160   storage.emplace("0", std::make_unique<Value>(0));
161 
162   using iterator = dict_iterator;
163   EXPECT_NE(iterator(storage.begin()), iterator(storage.end()));
164 }
165 
TEST(ValueIteratorsTest,ConstDictIteratorOperatorStar)166 TEST(ValueIteratorsTest, ConstDictIteratorOperatorStar) {
167   DictStorage storage;
168   storage.emplace("0", std::make_unique<Value>(0));
169 
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 
TEST(ValueIteratorsTest,ConstDictIteratorOperatorArrow)176 TEST(ValueIteratorsTest, ConstDictIteratorOperatorArrow) {
177   DictStorage storage;
178   storage.emplace("0", std::make_unique<Value>(0));
179 
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 
TEST(ValueIteratorsTest,ConstDictIteratorPreIncrement)186 TEST(ValueIteratorsTest, ConstDictIteratorPreIncrement) {
187   DictStorage storage;
188   storage.emplace("0", std::make_unique<Value>(0));
189   storage.emplace("1", std::make_unique<Value>(1));
190 
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 
TEST(ValueIteratorsTest,ConstDictIteratorPostIncrement)203 TEST(ValueIteratorsTest, ConstDictIteratorPostIncrement) {
204   DictStorage storage;
205   storage.emplace("0", std::make_unique<Value>(0));
206   storage.emplace("1", std::make_unique<Value>(1));
207 
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 
TEST(ValueIteratorsTest,ConstDictIteratorPreDecrement)219 TEST(ValueIteratorsTest, ConstDictIteratorPreDecrement) {
220   DictStorage storage;
221   storage.emplace("0", std::make_unique<Value>(0));
222   storage.emplace("1", std::make_unique<Value>(1));
223 
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 
TEST(ValueIteratorsTest,ConstDictIteratorPostDecrement)236 TEST(ValueIteratorsTest, ConstDictIteratorPostDecrement) {
237   DictStorage storage;
238   storage.emplace("0", std::make_unique<Value>(0));
239   storage.emplace("1", std::make_unique<Value>(1));
240 
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 
TEST(ValueIteratorsTest,ConstDictIteratorOperatorEQ)252 TEST(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 
TEST(ValueIteratorsTest,ConstDictIteratorOperatorNE)259 TEST(ValueIteratorsTest, ConstDictIteratorOperatorNE) {
260   DictStorage storage;
261   storage.emplace("0", std::make_unique<Value>(0));
262 
263   using iterator = const_dict_iterator;
264   EXPECT_NE(iterator(storage.begin()), iterator(storage.end()));
265 }
266 
TEST(ValueIteratorsTest,DictIteratorProxy)267 TEST(ValueIteratorsTest, DictIteratorProxy) {
268   DictStorage storage;
269   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));
277 
278   using iterator = const_dict_iterator;
279   using iterator_proxy = dict_iterator_proxy;
280   iterator_proxy proxy(&storage);
281 
282   auto equal_to = [](const DictStorage::value_type& lhs,
283                      const iterator::reference& rhs) {
284     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 
TEST(ValueIteratorsTest,ConstDictIteratorProxy)300 TEST(ValueIteratorsTest, ConstDictIteratorProxy) {
301   DictStorage storage;
302   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));
310 
311   using iterator = const_dict_iterator;
312   using iterator_proxy = const_dict_iterator_proxy;
313   iterator_proxy proxy(&storage);
314 
315   auto equal_to = [](const DictStorage::value_type& lhs,
316                      const iterator::reference& rhs) {
317     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
336