Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(133)

Side by Side Diff: base/containers/flat_sorted_containers_unittest.cc

Issue 2333253002: flat containers prototype (Closed)
Patch Set: Fixing performance bug in insert(It, It) Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2016 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 <algorithm>
6 #include <iterator>
7 #include <string>
8
9 #include "base/containers/flat_map.h"
10 #include "base/containers/flat_set.h"
11 #include "build/build_config.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace {
15
16 std::string Serialize(const std::string& that) {
17 return that;
18 }
19
20 std::string Serialize(int that) {
21 return std::to_string(that);
22 }
23
24 template <typename First, typename Second>
25 std::string Serialize(const std::pair<First, Second>& that) {
26 return std::string("{") + Serialize(that.first) + ", " +
27 Serialize(that.second) + std::string("}");
28 }
29
30 template <typename Range>
31 std::string Serialize(const Range& range) {
32 std::string res = "[";
33 auto it = std::begin(range);
34 res += Serialize(*it);
35 for (++it; it != std::end(range); ++it) {
36 res += ", " + Serialize(*it);
37 }
38 return res + ']';
39 }
40
41 template <typename Lhs, typename Rhs>
42 std::string ExpectedActualMsg(const Lhs& expected, const Rhs& rhs) {
43 return "\nExpected: " + Serialize(expected) + "\nDesired: " + Serialize(rhs);
44 }
45
46 struct AnyPairEquals {
47 template <typename Lhs, typename Rhs>
48 bool operator()(const Lhs& lhs, const Rhs& rhs) {
49 return lhs == rhs;
50 }
51 template <typename L1, typename L2, typename R1, typename R2>
52 bool operator()(const std::pair<L1, L2>& lhs, const std::pair<R1, R2>& rhs) {
53 return lhs.first == rhs.first && lhs.second == rhs.second;
54 }
55 };
56
57 template <typename FlatMap, typename TestRange>
58 bool check_map(const FlatMap& fl_map, const TestRange& test) {
59 auto test_beg = std::begin(test);
60 auto test_end = std::end(test);
61 if (static_cast<typename FlatMap::size_type>(
62 std::distance(test_beg, test_end)) != fl_map.size())
63 return false;
64 return std::equal(fl_map.begin(), fl_map.end(), test_beg, AnyPairEquals());
65 }
66
67 } // namespace
68
69 // this makes the compiler to instantiate everything
70 template class base::flat_map<std::unique_ptr<int>, std::unique_ptr<int>>;
71 template class base::flat_set<std::unique_ptr<int>>;
72
73 using RegularFlatMap = base::flat_map<std::string, int>;
74 using RegularFlatSet = base::flat_set<std::string>;
75
76 std::vector<RegularFlatMap::value_type> RegularKeyValuePairs() {
77 RegularFlatMap::value_type key_value_pairs[] = {
78 {"b", 3},
79 {"b", 5},
80 {"a", 3},
81 {"fr", 3},
82 {"fa", 3},
83 {"d", 12},
84 {"a", 7},
85 {"long", 1233},
86 {"q", 0},
87 };
88 return std::vector<RegularFlatMap::value_type>(std::begin(key_value_pairs),
89 std::end(key_value_pairs));
90 }
91
92 std::vector<RegularFlatSet::value_type> RegularKeys() {
93 auto key_value_pairs = RegularKeyValuePairs();
94 std::vector<RegularFlatSet::value_type> keys;
95 keys.reserve(key_value_pairs.size());
96 for (const auto& kv_pair : key_value_pairs)
97 keys.push_back(kv_pair.first);
98 return keys;
99 }
100
101 template <typename FlatCont, typename StdCont, typename KeyValuePairs>
102 void insert_test(const KeyValuePairs& key_value_pairs) {
103 {
104 const char prefix[] = "<it, bool> insert (value) ";
105 FlatCont fl_cont;
106 StdCont test_cont;
107 for (const auto& test_case : key_value_pairs) {
108 std::pair<typename FlatCont::iterator, bool> fl_insert =
109 fl_cont.insert(test_case);
110 std::pair<typename StdCont::iterator, bool> test_insert =
111 test_cont.insert(test_case);
112
113 EXPECT_TRUE(check_map(fl_cont, test_cont))
114 << prefix << ExpectedActualMsg(test_cont, fl_cont);
115 EXPECT_EQ(std::distance(fl_cont.begin(), fl_insert.first),
116 std::distance(test_cont.begin(), test_insert.first))
117 << prefix;
118 EXPECT_EQ(fl_insert.second, test_insert.second) << prefix;
119 }
120 }
121 {
122 const char prefix[] = "it insert (hint, value) ";
123 FlatCont fl_cont;
124 StdCont test_cont;
125 auto fl_hint = fl_cont.begin();
126 auto test_hint = test_cont.begin();
127 for (const auto& test_case : key_value_pairs) {
128 fl_hint = fl_cont.insert(fl_hint, test_case);
129 test_hint = test_cont.insert(test_hint, test_case);
130
131 EXPECT_TRUE(check_map(fl_cont, test_cont))
132 << prefix << ExpectedActualMsg(test_cont, fl_cont);
133 EXPECT_EQ(std::distance(fl_cont.begin(), fl_hint),
134 std::distance(test_cont.begin(), test_hint))
135 << prefix;
136 }
137 }
138 {
139 const char prefix[] = "void insert (first, last) ";
140 FlatCont fl_cont;
141 StdCont test_cont;
142 fl_cont.insert(std::begin(key_value_pairs), std::end(key_value_pairs));
143 test_cont.insert(std::begin(key_value_pairs), std::end(key_value_pairs));
144 EXPECT_TRUE(check_map(fl_cont, test_cont))
145 << prefix << ExpectedActualMsg(test_cont, fl_cont);
146 }
147
148 #ifndef OS_LINUX // on linux an older version of standard library is used.
149 {
150 const char prefix[] = "<it, bool> emplace(args...) ";
151 FlatCont fl_cont;
152 StdCont test_cont;
153 for (const auto& test_case : key_value_pairs) {
154 std::pair<typename FlatCont::iterator, bool> fl_emplace =
155 fl_cont.emplace(test_case);
156 std::pair<typename StdCont::iterator, bool> test_emplace =
157 test_cont.emplace(test_case);
158
159 EXPECT_TRUE(check_map(fl_cont, test_cont))
160 << prefix << ExpectedActualMsg(test_cont, fl_cont);
161 EXPECT_EQ(std::distance(fl_cont.begin(), fl_emplace.first),
162 std::distance(test_cont.begin(), test_emplace.first))
163 << prefix;
164 EXPECT_EQ(fl_emplace.second, test_emplace.second) << prefix;
165 }
166 }
167
168 {
169 const char prefix[] = "it emplace_hint (hint, value) ";
170 FlatCont fl_cont;
171 StdCont test_cont;
172 auto fl_hint = fl_cont.begin();
173 auto test_hint = test_cont.begin();
174 for (const auto& test_case : key_value_pairs) {
175 fl_hint = fl_cont.emplace_hint(fl_hint, test_case);
176 test_hint = test_cont.emplace_hint(test_hint, test_case);
177
178 EXPECT_TRUE(check_map(fl_cont, test_cont))
179 << prefix << ExpectedActualMsg(test_cont, fl_cont);
180 EXPECT_EQ(std::distance(fl_cont.begin(), fl_hint),
181 std::distance(test_cont.begin(), test_hint))
182 << prefix;
183 }
184 }
185 #endif // OS_LINUX
186 }
187
188 TEST(FlatMapTest, Insertions) {
189 using FlatMap = RegularFlatMap;
190 using FlatSet = RegularFlatSet;
191 using StdMap = RegularFlatMap::std_map;
192 using StdSet = RegularFlatSet::std_set;
193
194 auto key_value_pairs = RegularKeyValuePairs();
195 auto keys = RegularKeys();
196
197 {
198 const char prefix[] = "operator[] ";
199 FlatMap fl_map;
200 StdMap test_map;
201 for (const auto& test_case : key_value_pairs) {
202 fl_map[test_case.first] = test_case.second;
203 test_map[test_case.first] = test_case.second;
204 EXPECT_TRUE(check_map(fl_map, test_map))
205 << prefix << ExpectedActualMsg(test_map, fl_map);
206 }
207 }
208
209 insert_test<FlatMap, StdMap>(key_value_pairs);
210 insert_test<FlatSet, StdSet>(keys);
211 }
212
213 template <typename FlatCont, typename StdCont, typename KeyValuePairs>
214 void regular_type_test(const KeyValuePairs& key_value_pairs) {
215 {
216 const char prefix[] = "default ";
217 FlatCont fl_cont;
218 StdCont test_cont;
219 EXPECT_TRUE(check_map(fl_cont, test_cont))
220 << prefix << ExpectedActualMsg(test_cont, fl_cont);
221 }
222 {
223 const char prefix[] = "from underlying type ";
224 FlatCont fl_cont((typename FlatCont::underlying_type(key_value_pairs)));
225 StdCont test_cont(key_value_pairs.begin(), key_value_pairs.end());
226 EXPECT_TRUE(check_map(fl_cont, test_cont))
227 << prefix << ExpectedActualMsg(test_cont, fl_cont);
228 }
229 {
230 const char prefix[] = "from iterators ";
231 FlatCont fl_cont(key_value_pairs.begin(), key_value_pairs.end());
232 StdCont test_cont(key_value_pairs.begin(), key_value_pairs.end());
233 EXPECT_TRUE(check_map(fl_cont, test_cont))
234 << prefix << ExpectedActualMsg(test_cont, fl_cont);
235 }
236 {
237 const char prefix[] = "copy ";
238 FlatCont fl_cont(key_value_pairs.begin(), key_value_pairs.end());
239 StdCont test_cont(key_value_pairs.begin(), key_value_pairs.end());
240
241 FlatCont fl_cont1 = fl_cont;
242 StdCont test_cont1 = test_cont;
243 EXPECT_TRUE(check_map(fl_cont, test_cont))
244 << prefix << ExpectedActualMsg(test_cont, fl_cont);
245 }
246 {
247 const char prefix[] = "copy assign";
248 FlatCont fl_cont(key_value_pairs.begin(), key_value_pairs.end());
249 StdCont test_cont(key_value_pairs.begin(), key_value_pairs.end());
250
251 FlatCont fl_cont1;
252 fl_cont1 = fl_cont;
253 StdCont test_cont1;
254 test_cont1 = test_cont;
255 EXPECT_TRUE(check_map(fl_cont, test_cont))
256 << prefix << ExpectedActualMsg(test_cont, fl_cont);
257 }
258 {
259 const char prefix[] = "move ";
260 FlatCont fl_cont(key_value_pairs.begin(), key_value_pairs.end());
261 StdCont test_cont(key_value_pairs.begin(), key_value_pairs.end());
262
263 FlatCont fl_cont1 = std::move(fl_cont);
264 StdCont test_cont1 = std::move(test_cont);
265 EXPECT_TRUE(check_map(fl_cont, test_cont))
266 << prefix << ExpectedActualMsg(test_cont, fl_cont);
267 }
268 {
269 const char prefix[] = "move assign";
270 FlatCont fl_cont(key_value_pairs.begin(), key_value_pairs.end());
271 StdCont test_cont(key_value_pairs.begin(), key_value_pairs.end());
272
273 FlatCont fl_cont1;
274 fl_cont1 = std::move(fl_cont);
275 StdCont test_cont1;
276 test_cont1 = std::move(test_cont);
277 EXPECT_TRUE(check_map(fl_cont, test_cont))
278 << prefix << ExpectedActualMsg(test_cont, fl_cont);
279 }
280 {
281 const char prefix[] = "comparators ";
282 FlatCont lhs(key_value_pairs.begin(), key_value_pairs.end());
283 FlatCont rhs(key_value_pairs.begin(), key_value_pairs.end());
284 EXPECT_EQ(lhs, rhs);
285 lhs.erase(lhs.begin() + 5, lhs.end());
286 EXPECT_NE(lhs, rhs) << prefix << ExpectedActualMsg(lhs, rhs);
287 EXPECT_TRUE(lhs < rhs) << prefix << ExpectedActualMsg(lhs, rhs);
288 EXPECT_LE(lhs, rhs) << prefix << ExpectedActualMsg(lhs, rhs);
289
290 EXPECT_GT(rhs, lhs) << prefix << ExpectedActualMsg(lhs, rhs);
291 EXPECT_GE(rhs, lhs) << prefix << ExpectedActualMsg(lhs, rhs);
292 }
293 }
294
295 TEST(FlatMapTest, RegularTypeAndConstructors) {
296 using FlatMap = RegularFlatMap;
297 using StdMap = RegularFlatMap::std_map;
298 using FlatSet = RegularFlatSet;
299 using StdSet = RegularFlatSet::std_set;
300
301 auto key_value_pairs = RegularKeyValuePairs();
302 auto keys = RegularKeys();
303
304 regular_type_test<FlatMap, StdMap>(key_value_pairs);
305 regular_type_test<FlatSet, StdSet>(keys);
306
307 {
308 const char prefix[] = "comparators ";
309 FlatMap lhs(key_value_pairs.begin(), key_value_pairs.end());
310 FlatMap rhs(key_value_pairs.begin(), key_value_pairs.end());
311 EXPECT_EQ(lhs, rhs);
312 lhs.erase(lhs.begin() + 5, lhs.end());
313 EXPECT_NE(lhs, rhs) << prefix << ExpectedActualMsg(lhs, rhs);
314 EXPECT_TRUE(lhs < rhs) << prefix << ExpectedActualMsg(lhs, rhs);
315 EXPECT_LE(lhs, rhs) << prefix << ExpectedActualMsg(lhs, rhs);
316
317 EXPECT_GT(rhs, lhs) << prefix << ExpectedActualMsg(lhs, rhs);
318 EXPECT_GE(rhs, lhs) << prefix << ExpectedActualMsg(lhs, rhs);
319 }
320 {
321 const char prefix[] = "swap ";
322 FlatMap lhs(key_value_pairs.begin(), key_value_pairs.end());
323 FlatMap rhs(key_value_pairs.begin(), key_value_pairs.end());
324 lhs.erase(lhs.begin() + 5, lhs.end());
325
326 FlatMap::underlying_type original_lhs(lhs.begin(), lhs.end());
327 FlatMap::underlying_type original_rhs(rhs.begin(), rhs.end());
328
329 swap(lhs, rhs);
330 EXPECT_TRUE(check_map(lhs, original_rhs))
331 << prefix << ExpectedActualMsg(original_rhs, lhs);
332 EXPECT_TRUE(check_map(rhs, original_lhs))
333 << prefix << ExpectedActualMsg(original_lhs, rhs);
334
335 lhs.swap(rhs);
336 EXPECT_TRUE(check_map(lhs, original_lhs))
337 << prefix << ExpectedActualMsg(original_lhs, lhs);
338 EXPECT_TRUE(check_map(rhs, original_rhs))
339 << prefix << ExpectedActualMsg(original_rhs, rhs);
340 }
341 }
342
343 TEST(FlatMapTest, Getters) {
344 using FlatMap = RegularFlatMap;
345 using StdMap = RegularFlatMap::std_map;
346
347 auto key_value_pairs = RegularKeyValuePairs();
348 std::vector<FlatMap::key_type> keys;
349 keys.reserve(key_value_pairs.size());
350 for (const auto& kv_pair : key_value_pairs)
351 keys.push_back(kv_pair.first);
352
353 {
354 const char prefix[] = "at(key) ";
355 FlatMap fl_map(key_value_pairs.begin(), key_value_pairs.end());
356 StdMap test_map(key_value_pairs.begin(), key_value_pairs.end());
357 const FlatMap& fl_const = fl_map;
358 const StdMap& test_const = test_map;
359 for (const auto& key : keys) {
360 EXPECT_EQ(fl_map.at(key), test_map.at(key)) << prefix << key;
361 EXPECT_EQ(fl_const.at(key), test_const.at(key)) << prefix << key;
362 }
363 }
364
365 {
366 const char prefix[] = "count(key) ";
367 FlatMap fl_map(key_value_pairs.begin(), key_value_pairs.end());
368 StdMap test_map(key_value_pairs.begin(), key_value_pairs.end());
369 for (const auto& key : keys) {
370 EXPECT_EQ(fl_map.count(key), test_map.count(key)) << prefix << key;
371 }
372 }
373
374 // empty, size, max_size
375 {
376 FlatMap fl_map;
377 EXPECT_TRUE(fl_map.empty());
378 EXPECT_EQ(fl_map.size(), FlatMap::size_type(0));
379 EXPECT_EQ(fl_map.max_size(), FlatMap::underlying_type().max_size());
380 }
381
382 {
383 const char prefix[] = "it find (key) ";
384 FlatMap fl_map(key_value_pairs.begin(), key_value_pairs.end());
385 StdMap test_map(key_value_pairs.begin(), key_value_pairs.end());
386 const FlatMap& fl_const = fl_map;
387 const StdMap& test_const = test_map;
388
389 for (const auto& key : keys) {
390 auto fl_found = fl_map.find(key);
391 auto test_found = test_map.find(key);
392 auto fl_const_found = fl_const.find(key);
393 auto test_const_found = test_const.find(key);
394
395 EXPECT_EQ(std::distance(fl_map.begin(), fl_found),
396 std::distance(test_map.begin(), test_found))
397 << prefix;
398 EXPECT_EQ(std::distance(fl_found, fl_map.end()),
399 std::distance(test_found, test_map.end()))
400 << prefix;
401 EXPECT_EQ(std::distance(fl_const.begin(), fl_const_found),
402 std::distance(test_const.begin(), test_const_found))
403 << prefix;
404 EXPECT_EQ(std::distance(fl_const_found, fl_const.end()),
405 std::distance(test_const_found, test_const.end()))
406 << prefix;
407 }
408 }
409
410 {
411 const char prefix[] = "<it, it> equal_range (key) ";
412 FlatMap fl_map(key_value_pairs.begin(), key_value_pairs.end());
413 StdMap test_map(key_value_pairs.begin(), key_value_pairs.end());
414 const FlatMap& fl_const = fl_map;
415 const StdMap& test_const = test_map;
416
417 for (const auto& key : keys) {
418 auto fl_found = fl_map.equal_range(key);
419 auto test_found = test_map.equal_range(key);
420 auto fl_const_found = fl_const.equal_range(key);
421 auto test_const_found = test_const.equal_range(key);
422
423 EXPECT_EQ(std::distance(fl_map.begin(), fl_found.first),
424 std::distance(test_map.begin(), test_found.first))
425 << prefix;
426 EXPECT_EQ(std::distance(fl_found.first, fl_found.second),
427 std::distance(test_found.first, test_found.second))
428 << prefix;
429 EXPECT_EQ(std::distance(fl_found.second, fl_map.end()),
430 std::distance(test_found.second, test_map.end()))
431 << prefix;
432
433 EXPECT_EQ(std::distance(fl_const.begin(), fl_const_found.first),
434 std::distance(test_const.begin(), test_const_found.first))
435 << prefix;
436 EXPECT_EQ(std::distance(fl_const_found.first, fl_const_found.second),
437 std::distance(test_const_found.first, test_const_found.second))
438 << prefix;
439 EXPECT_EQ(std::distance(fl_const_found.second, fl_const.end()),
440 std::distance(test_const_found.second, test_const.end()))
441 << prefix;
442 }
443 }
444
445 {
446 const char prefix[] = "it lower_bound (key) ";
447 FlatMap fl_map(key_value_pairs.begin(), key_value_pairs.end());
448 StdMap test_map(key_value_pairs.begin(), key_value_pairs.end());
449 const FlatMap& fl_const = fl_map;
450 const StdMap& test_const = test_map;
451
452 for (const auto& key : keys) {
453 auto fl_found = fl_map.lower_bound(key);
454 auto test_found = test_map.lower_bound(key);
455 auto fl_const_found = fl_const.lower_bound(key);
456 auto test_const_found = test_const.lower_bound(key);
457
458 EXPECT_EQ(std::distance(fl_map.begin(), fl_found),
459 std::distance(test_map.begin(), test_found))
460 << prefix;
461 EXPECT_EQ(std::distance(fl_found, fl_map.end()),
462 std::distance(test_found, test_map.end()))
463 << prefix;
464 EXPECT_EQ(std::distance(fl_const.begin(), fl_const_found),
465 std::distance(test_const.begin(), test_const_found))
466 << prefix;
467 EXPECT_EQ(std::distance(fl_const_found, fl_const.end()),
468 std::distance(test_const_found, test_const.end()))
469 << prefix;
470 }
471 }
472 {
473 const char prefix[] = "it upper_bound (key) ";
474 FlatMap fl_map(key_value_pairs.begin(), key_value_pairs.end());
475 StdMap test_map(key_value_pairs.begin(), key_value_pairs.end());
476 const FlatMap& fl_const = fl_map;
477 const StdMap& test_const = test_map;
478
479 for (const auto& key : keys) {
480 auto fl_found = fl_map.upper_bound(key);
481 auto test_found = test_map.upper_bound(key);
482 auto fl_const_found = fl_const.upper_bound(key);
483 auto test_const_found = test_const.upper_bound(key);
484
485 EXPECT_EQ(std::distance(fl_map.begin(), fl_found),
486 std::distance(test_map.begin(), test_found))
487 << prefix;
488 EXPECT_EQ(std::distance(fl_found, fl_map.end()),
489 std::distance(test_found, test_map.end()))
490 << prefix;
491 EXPECT_EQ(std::distance(fl_const.begin(), fl_const_found),
492 std::distance(test_const.begin(), test_const_found))
493 << prefix;
494 EXPECT_EQ(std::distance(fl_const_found, fl_const.end()),
495 std::distance(test_const_found, test_const.end()))
496 << prefix;
497 }
498 }
499 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698