blob: 0ea7d8a015d2066f8922a122d025c367331bbe35 [file] [log] [blame]
danzhc3be2d42019-04-25 07:47:41 -07001// Copyright (c) 2019 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// Tests SimpleLinkedHashMap.
6
7#include "net/third_party/quiche/src/common/simple_linked_hash_map.h"
8
9#include <memory>
10#include <utility>
11
12#include "net/third_party/quiche/src/common/platform/api/quiche_ptr_util.h"
13#include "net/third_party/quiche/src/common/platform/api/quiche_test.h"
14
15using testing::Pair;
16using testing::Pointee;
17using testing::UnorderedElementsAre;
18
19namespace quiche {
20namespace test {
21
22// Tests that move constructor works.
23TEST(LinkedHashMapTest, Move) {
24 // Use unique_ptr as an example of a non-copyable type.
25 SimpleLinkedHashMap<int, std::unique_ptr<int>> m;
26 m[2] = QuicheMakeUnique<int>(12);
27 m[3] = QuicheMakeUnique<int>(13);
28 SimpleLinkedHashMap<int, std::unique_ptr<int>> n = std::move(m);
29 EXPECT_THAT(n,
30 UnorderedElementsAre(Pair(2, Pointee(12)), Pair(3, Pointee(13))));
31}
32
33TEST(LinkedHashMapTest, CanEmplaceMoveOnly) {
34 SimpleLinkedHashMap<int, std::unique_ptr<int>> m;
35 struct Data {
36 int k, v;
37 };
38 const Data data[] = {{1, 123}, {3, 345}, {2, 234}, {4, 456}};
39 for (const auto& kv : data) {
40 m.emplace(std::piecewise_construct, std::make_tuple(kv.k),
41 std::make_tuple(new int{kv.v}));
42 }
43 EXPECT_TRUE(m.contains(2));
44 auto found = m.find(2);
45 ASSERT_TRUE(found != m.end());
46 EXPECT_EQ(234, *found->second);
47}
48
49struct NoCopy {
50 explicit NoCopy(int x) : x(x) {}
51 NoCopy(const NoCopy&) = delete;
52 NoCopy& operator=(const NoCopy&) = delete;
53 NoCopy(NoCopy&&) = delete;
54 NoCopy& operator=(NoCopy&&) = delete;
55 int x;
56};
57
58TEST(LinkedHashMapTest, CanEmplaceNoMoveNoCopy) {
59 SimpleLinkedHashMap<int, NoCopy> m;
60 struct Data {
61 int k, v;
62 };
63 const Data data[] = {{1, 123}, {3, 345}, {2, 234}, {4, 456}};
64 for (const auto& kv : data) {
65 m.emplace(std::piecewise_construct, std::make_tuple(kv.k),
66 std::make_tuple(kv.v));
67 }
68 EXPECT_TRUE(m.contains(2));
69 auto found = m.find(2);
70 ASSERT_TRUE(found != m.end());
71 EXPECT_EQ(234, found->second.x);
72}
73
74TEST(LinkedHashMapTest, ConstKeys) {
75 SimpleLinkedHashMap<int, int> m;
76 m.insert(std::make_pair(1, 2));
77 // Test that keys are const in iteration.
78 std::pair<int, int>& p = *m.begin();
79 EXPECT_EQ(1, p.first);
80}
81
82// Tests that iteration from begin() to end() works
83TEST(LinkedHashMapTest, Iteration) {
84 SimpleLinkedHashMap<int, int> m;
85 EXPECT_TRUE(m.begin() == m.end());
86
87 m.insert(std::make_pair(2, 12));
88 m.insert(std::make_pair(1, 11));
89 m.insert(std::make_pair(3, 13));
90
91 SimpleLinkedHashMap<int, int>::iterator i = m.begin();
92 ASSERT_TRUE(m.begin() == i);
93 ASSERT_TRUE(m.end() != i);
94 EXPECT_EQ(2, i->first);
95 EXPECT_EQ(12, i->second);
96
97 ++i;
98 ASSERT_TRUE(m.end() != i);
99 EXPECT_EQ(1, i->first);
100 EXPECT_EQ(11, i->second);
101
102 ++i;
103 ASSERT_TRUE(m.end() != i);
104 EXPECT_EQ(3, i->first);
105 EXPECT_EQ(13, i->second);
106
107 ++i; // Should be the end of the line.
108 ASSERT_TRUE(m.end() == i);
109}
110
111// Tests that reverse iteration from rbegin() to rend() works
112TEST(LinkedHashMapTest, ReverseIteration) {
113 SimpleLinkedHashMap<int, int> m;
114 EXPECT_TRUE(m.rbegin() == m.rend());
115
116 m.insert(std::make_pair(2, 12));
117 m.insert(std::make_pair(1, 11));
118 m.insert(std::make_pair(3, 13));
119
120 SimpleLinkedHashMap<int, int>::reverse_iterator i = m.rbegin();
121 ASSERT_TRUE(m.rbegin() == i);
122 ASSERT_TRUE(m.rend() != i);
123 EXPECT_EQ(3, i->first);
124 EXPECT_EQ(13, i->second);
125
126 ++i;
127 ASSERT_TRUE(m.rend() != i);
128 EXPECT_EQ(1, i->first);
129 EXPECT_EQ(11, i->second);
130
131 ++i;
132 ASSERT_TRUE(m.rend() != i);
133 EXPECT_EQ(2, i->first);
134 EXPECT_EQ(12, i->second);
135
136 ++i; // Should be the end of the line.
137 ASSERT_TRUE(m.rend() == i);
138}
139
140// Tests that clear() works
141TEST(LinkedHashMapTest, Clear) {
142 SimpleLinkedHashMap<int, int> m;
143 m.insert(std::make_pair(2, 12));
144 m.insert(std::make_pair(1, 11));
145 m.insert(std::make_pair(3, 13));
146
147 ASSERT_EQ(3u, m.size());
148
149 m.clear();
150
151 EXPECT_EQ(0u, m.size());
152
153 m.clear(); // Make sure we can call it on an empty map.
154
155 EXPECT_EQ(0u, m.size());
156}
157
158// Tests that size() works.
159TEST(LinkedHashMapTest, Size) {
160 SimpleLinkedHashMap<int, int> m;
161 EXPECT_EQ(0u, m.size());
162 m.insert(std::make_pair(2, 12));
163 EXPECT_EQ(1u, m.size());
164 m.insert(std::make_pair(1, 11));
165 EXPECT_EQ(2u, m.size());
166 m.insert(std::make_pair(3, 13));
167 EXPECT_EQ(3u, m.size());
168 m.clear();
169 EXPECT_EQ(0u, m.size());
170}
171
172// Tests empty()
173TEST(LinkedHashMapTest, Empty) {
174 SimpleLinkedHashMap<int, int> m;
175 ASSERT_TRUE(m.empty());
176 m.insert(std::make_pair(2, 12));
177 ASSERT_FALSE(m.empty());
178 m.clear();
179 ASSERT_TRUE(m.empty());
180}
181
182TEST(LinkedHashMapTest, Erase) {
183 SimpleLinkedHashMap<int, int> m;
184 ASSERT_EQ(0u, m.size());
danzh892f1f42019-04-26 08:57:56 -0700185 EXPECT_EQ(0u, m.erase(2)); // Nothing to erase yet
danzhc3be2d42019-04-25 07:47:41 -0700186
187 m.insert(std::make_pair(2, 12));
188 ASSERT_EQ(1u, m.size());
danzh892f1f42019-04-26 08:57:56 -0700189 EXPECT_EQ(1u, m.erase(2));
danzhc3be2d42019-04-25 07:47:41 -0700190 EXPECT_EQ(0u, m.size());
191
danzh892f1f42019-04-26 08:57:56 -0700192 EXPECT_EQ(0u, m.erase(2)); // Make sure nothing bad happens if we repeat.
danzhc3be2d42019-04-25 07:47:41 -0700193 EXPECT_EQ(0u, m.size());
194}
195
196TEST(LinkedHashMapTest, Erase2) {
197 SimpleLinkedHashMap<int, int> m;
198 ASSERT_EQ(0u, m.size());
danzh892f1f42019-04-26 08:57:56 -0700199 EXPECT_EQ(0u, m.erase(2)); // Nothing to erase yet
danzhc3be2d42019-04-25 07:47:41 -0700200
201 m.insert(std::make_pair(2, 12));
202 m.insert(std::make_pair(1, 11));
203 m.insert(std::make_pair(3, 13));
204 m.insert(std::make_pair(4, 14));
205 ASSERT_EQ(4u, m.size());
206
207 // Erase middle two
danzh892f1f42019-04-26 08:57:56 -0700208 EXPECT_EQ(1u, m.erase(1));
209 EXPECT_EQ(1u, m.erase(3));
danzhc3be2d42019-04-25 07:47:41 -0700210
211 EXPECT_EQ(2u, m.size());
212
213 // Make sure we can still iterate over everything that's left.
214 SimpleLinkedHashMap<int, int>::iterator it = m.begin();
215 ASSERT_TRUE(it != m.end());
216 EXPECT_EQ(12, it->second);
217 ++it;
218 ASSERT_TRUE(it != m.end());
219 EXPECT_EQ(14, it->second);
220 ++it;
221 ASSERT_TRUE(it == m.end());
222
danzh892f1f42019-04-26 08:57:56 -0700223 EXPECT_EQ(0u, m.erase(1)); // Make sure nothing bad happens if we repeat.
danzhc3be2d42019-04-25 07:47:41 -0700224 ASSERT_EQ(2u, m.size());
225
danzh892f1f42019-04-26 08:57:56 -0700226 EXPECT_EQ(1u, m.erase(2));
227 EXPECT_EQ(1u, m.erase(4));
danzhc3be2d42019-04-25 07:47:41 -0700228 ASSERT_EQ(0u, m.size());
229
danzh892f1f42019-04-26 08:57:56 -0700230 EXPECT_EQ(0u, m.erase(1)); // Make sure nothing bad happens if we repeat.
danzhc3be2d42019-04-25 07:47:41 -0700231 ASSERT_EQ(0u, m.size());
232}
233
234// Test that erase(iter,iter) and erase(iter) compile and work.
235TEST(LinkedHashMapTest, Erase3) {
236 SimpleLinkedHashMap<int, int> m;
237
238 m.insert(std::make_pair(1, 11));
239 m.insert(std::make_pair(2, 12));
240 m.insert(std::make_pair(3, 13));
241 m.insert(std::make_pair(4, 14));
242
243 // Erase middle two
244 SimpleLinkedHashMap<int, int>::iterator it2 = m.find(2);
245 SimpleLinkedHashMap<int, int>::iterator it4 = m.find(4);
246 EXPECT_EQ(m.erase(it2, it4), m.find(4));
danzh178723f2019-04-29 09:43:18 -0700247 EXPECT_EQ(2u, m.size());
danzhc3be2d42019-04-25 07:47:41 -0700248
249 // Make sure we can still iterate over everything that's left.
250 SimpleLinkedHashMap<int, int>::iterator it = m.begin();
251 ASSERT_TRUE(it != m.end());
252 EXPECT_EQ(11, it->second);
253 ++it;
254 ASSERT_TRUE(it != m.end());
255 EXPECT_EQ(14, it->second);
256 ++it;
257 ASSERT_TRUE(it == m.end());
258
259 // Erase first one using an iterator.
260 EXPECT_EQ(m.erase(m.begin()), m.find(4));
261
262 // Only the last element should be left.
263 it = m.begin();
264 ASSERT_TRUE(it != m.end());
265 EXPECT_EQ(14, it->second);
266 ++it;
267 ASSERT_TRUE(it == m.end());
268}
269
270TEST(LinkedHashMapTest, Insertion) {
271 SimpleLinkedHashMap<int, int> m;
272 ASSERT_EQ(0u, m.size());
273 std::pair<SimpleLinkedHashMap<int, int>::iterator, bool> result;
274
275 result = m.insert(std::make_pair(2, 12));
276 ASSERT_EQ(1u, m.size());
277 EXPECT_TRUE(result.second);
278 EXPECT_EQ(2, result.first->first);
279 EXPECT_EQ(12, result.first->second);
280
281 result = m.insert(std::make_pair(1, 11));
282 ASSERT_EQ(2u, m.size());
283 EXPECT_TRUE(result.second);
284 EXPECT_EQ(1, result.first->first);
285 EXPECT_EQ(11, result.first->second);
286
287 result = m.insert(std::make_pair(3, 13));
288 SimpleLinkedHashMap<int, int>::iterator result_iterator = result.first;
289 ASSERT_EQ(3u, m.size());
290 EXPECT_TRUE(result.second);
291 EXPECT_EQ(3, result.first->first);
292 EXPECT_EQ(13, result.first->second);
293
294 result = m.insert(std::make_pair(3, 13));
295 EXPECT_EQ(3u, m.size());
296 EXPECT_FALSE(result.second) << "No insertion should have occurred.";
297 EXPECT_TRUE(result_iterator == result.first)
298 << "Duplicate insertion should have given us the original iterator.";
299}
300
301static std::pair<int, int> Pair(int i, int j) {
302 return {i, j};
303}
304
305// Test front accessors.
306TEST(LinkedHashMapTest, Front) {
307 SimpleLinkedHashMap<int, int> m;
308
309 m.insert(std::make_pair(2, 12));
310 m.insert(std::make_pair(1, 11));
311 m.insert(std::make_pair(3, 13));
312
313 EXPECT_EQ(3u, m.size());
314 EXPECT_EQ(Pair(2, 12), m.front());
315 m.pop_front();
316 EXPECT_EQ(2u, m.size());
317 EXPECT_EQ(Pair(1, 11), m.front());
318 m.pop_front();
319 EXPECT_EQ(1u, m.size());
320 EXPECT_EQ(Pair(3, 13), m.front());
321 m.pop_front();
322 EXPECT_TRUE(m.empty());
323}
324
325TEST(LinkedHashMapTest, Find) {
326 SimpleLinkedHashMap<int, int> m;
327
328 EXPECT_TRUE(m.end() == m.find(1))
329 << "We shouldn't find anything in an empty map.";
330
331 m.insert(std::make_pair(2, 12));
332 EXPECT_TRUE(m.end() == m.find(1))
333 << "We shouldn't find an element that doesn't exist in the map.";
334
335 std::pair<SimpleLinkedHashMap<int, int>::iterator, bool> result =
336 m.insert(std::make_pair(1, 11));
337 ASSERT_TRUE(result.second);
338 ASSERT_TRUE(m.end() != result.first);
339 EXPECT_TRUE(result.first == m.find(1))
340 << "We should have found an element we know exists in the map.";
341 EXPECT_EQ(11, result.first->second);
342
343 // Check that a follow-up insertion doesn't affect our original
344 m.insert(std::make_pair(3, 13));
345 SimpleLinkedHashMap<int, int>::iterator it = m.find(1);
346 ASSERT_TRUE(m.end() != it);
347 EXPECT_EQ(11, it->second);
348
349 m.clear();
350 EXPECT_TRUE(m.end() == m.find(1))
351 << "We shouldn't find anything in a map that we've cleared.";
352}
353
354TEST(LinkedHashMapTest, Contains) {
355 SimpleLinkedHashMap<int, int> m;
356
357 EXPECT_FALSE(m.contains(1)) << "An empty map shouldn't contain anything.";
358
359 m.insert(std::make_pair(2, 12));
360 EXPECT_FALSE(m.contains(1))
361 << "The map shouldn't contain an element that doesn't exist.";
362
363 m.insert(std::make_pair(1, 11));
364 EXPECT_TRUE(m.contains(1))
365 << "The map should contain an element that we know exists.";
366
367 m.clear();
368 EXPECT_FALSE(m.contains(1))
369 << "A map that we've cleared shouldn't contain anything.";
370}
371
372TEST(LinkedHashMapTest, Swap) {
373 SimpleLinkedHashMap<int, int> m1;
374 SimpleLinkedHashMap<int, int> m2;
375 m1.insert(std::make_pair(1, 1));
376 m1.insert(std::make_pair(2, 2));
377 m2.insert(std::make_pair(3, 3));
378 ASSERT_EQ(2u, m1.size());
379 ASSERT_EQ(1u, m2.size());
380 m1.swap(m2);
381 ASSERT_EQ(1u, m1.size());
382 ASSERT_EQ(2u, m2.size());
383}
384
385TEST(LinkedHashMapTest, CustomHashAndEquality) {
386 struct CustomIntHash {
387 size_t operator()(int x) const { return x; }
388 };
389 SimpleLinkedHashMap<int, int, CustomIntHash> m;
390 m.insert(std::make_pair(1, 1));
391 EXPECT_TRUE(m.contains(1));
392 EXPECT_EQ(1, m[1]);
393}
394
395} // namespace test
396} // namespace quiche