Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
retain_ptr_unittest.cpp
Go to the documentation of this file.
1// Copyright 2016 The PDFium Authors
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 "core/fxcrt/retain_ptr.h"
6
7#include <functional>
8#include <set>
9#include <utility>
10#include <vector>
11
12#include "testing/gtest/include/gtest/gtest.h"
13#include "testing/pseudo_retainable.h"
14#include "third_party/base/containers/contains.h"
15
16namespace {
17
18template <typename T, typename C = std::less<T>>
19class NoLinearSearchSet : public std::set<T, C> {
20 public:
21 typename std::set<T, C>::iterator begin() noexcept = delete;
22 typename std::set<T, C>::const_iterator cbegin() const noexcept = delete;
23};
24
25} // namespace
26
27namespace fxcrt {
28namespace {
29
30template <typename T, typename C = std::less<T>>
31class NoLinearSearchSet : public std::set<T, C> {
32 public:
33 typename std::set<T, C>::iterator begin() noexcept = delete;
34 typename std::set<T, C>::const_iterator cbegin() const noexcept = delete;
35};
36
37} // namespace
38
39TEST(RetainPtr, DefaultCtor) {
41 EXPECT_FALSE(ptr.Get());
42}
43
44TEST(RetainPtr, NullptrCtor) {
45 RetainPtr<PseudoRetainable> ptr(nullptr);
46 EXPECT_FALSE(ptr.Get());
47}
48
49TEST(RetainPtr, RawCtor) {
51 {
52 RetainPtr<PseudoRetainable> ptr(&obj);
53 EXPECT_EQ(&obj, ptr.Get());
54 EXPECT_EQ(1, obj.retain_count());
55 EXPECT_EQ(0, obj.release_count());
56 }
57 EXPECT_EQ(1, obj.retain_count());
58 EXPECT_EQ(1, obj.release_count());
59}
60
61TEST(RetainPtr, CopyCtor) {
63 {
64 RetainPtr<PseudoRetainable> ptr1(&obj);
65 {
66 RetainPtr<PseudoRetainable> ptr2(ptr1);
67 EXPECT_EQ(2, obj.retain_count());
68 EXPECT_EQ(0, obj.release_count());
69 }
70 EXPECT_EQ(2, obj.retain_count());
71 EXPECT_EQ(1, obj.release_count());
72 }
73 EXPECT_EQ(2, obj.retain_count());
74 EXPECT_EQ(2, obj.release_count());
75}
76
77TEST(RetainPtr, MoveCtor) {
79 {
80 RetainPtr<PseudoRetainable> ptr1(&obj);
81 {
82 RetainPtr<PseudoRetainable> ptr2(std::move(ptr1));
83 EXPECT_FALSE(ptr1.Get());
84 EXPECT_EQ(&obj, ptr2.Get());
85 EXPECT_EQ(1, obj.retain_count());
86 EXPECT_EQ(0, obj.release_count());
87 }
88 EXPECT_EQ(1, obj.retain_count());
89 EXPECT_EQ(1, obj.release_count());
90 }
91 EXPECT_EQ(1, obj.retain_count());
92 EXPECT_EQ(1, obj.release_count());
93}
94
97 {
98 RetainPtr<PseudoRetainable> ptr1(&obj);
99 {
100 RetainPtr<const PseudoRetainable> ptr2(ptr1);
101 EXPECT_EQ(2, obj.retain_count());
102 EXPECT_EQ(0, obj.release_count());
103 }
104 EXPECT_EQ(2, obj.retain_count());
105 EXPECT_EQ(1, obj.release_count());
106 }
107 EXPECT_EQ(2, obj.retain_count());
108 EXPECT_EQ(2, obj.release_count());
109}
110
113 {
114 RetainPtr<PseudoRetainable> ptr1(&obj);
115 {
116 RetainPtr<const PseudoRetainable> ptr2(std::move(ptr1));
117 EXPECT_FALSE(ptr1.Get());
118 EXPECT_EQ(&obj, ptr2.Get());
119 EXPECT_EQ(1, obj.retain_count());
120 EXPECT_EQ(0, obj.release_count());
121 }
122 EXPECT_EQ(1, obj.retain_count());
123 EXPECT_EQ(1, obj.release_count());
124 }
125 EXPECT_EQ(1, obj.retain_count());
126 EXPECT_EQ(1, obj.release_count());
127}
128
129TEST(RetainPtr, NullptrAssign) {
131 RetainPtr<PseudoRetainable> ptr(&obj);
132 ptr = nullptr;
133 EXPECT_FALSE(ptr);
134}
135
136TEST(RetainPtr, RawAssign) {
139 ptr = pdfium::WrapRetain(&obj);
140 EXPECT_EQ(&obj, ptr);
141}
142
143TEST(RetainPtr, CopyAssign) {
145 {
146 RetainPtr<PseudoRetainable> ptr(&obj);
147 {
149 ptr2 = ptr;
150 EXPECT_EQ(2, obj.retain_count());
151 EXPECT_EQ(0, obj.release_count());
152 }
153 {
154 // Test assignment from wrapped underlying type.
156 ptr2 = pdfium::WrapRetain(ptr.Get());
157 EXPECT_EQ(3, obj.retain_count());
158 EXPECT_EQ(1, obj.release_count());
159 }
160 EXPECT_EQ(3, obj.retain_count());
161 EXPECT_EQ(2, obj.release_count());
162 }
163 EXPECT_EQ(3, obj.retain_count());
164 EXPECT_EQ(3, obj.release_count());
165}
166
167TEST(RetainPtr, MoveAssign) {
169 {
170 RetainPtr<PseudoRetainable> ptr1(&obj);
171 {
173 EXPECT_EQ(&obj, ptr1.Get());
174 EXPECT_FALSE(ptr2.Get());
175 ptr2 = std::move(ptr1);
176 EXPECT_FALSE(ptr1.Get());
177 EXPECT_EQ(&obj, ptr2.Get());
178 EXPECT_EQ(1, obj.retain_count());
179 EXPECT_EQ(0, obj.release_count());
180 }
181 EXPECT_EQ(1, obj.retain_count());
182 EXPECT_EQ(1, obj.release_count());
183 }
184 EXPECT_EQ(1, obj.retain_count());
185 EXPECT_EQ(1, obj.release_count());
186}
187
190 {
191 RetainPtr<PseudoRetainable> ptr(&obj);
192 {
193 RetainPtr<const PseudoRetainable> ptr2;
194 ptr2 = ptr;
195 EXPECT_EQ(2, obj.retain_count());
196 EXPECT_EQ(0, obj.release_count());
197 }
198 {
199 // Test assignment from wrapped underlying type.
200 RetainPtr<const PseudoRetainable> ptr2;
201 ptr2 = pdfium::WrapRetain(ptr.Get());
202 EXPECT_EQ(3, obj.retain_count());
203 EXPECT_EQ(1, obj.release_count());
204 }
205 EXPECT_EQ(3, obj.retain_count());
206 EXPECT_EQ(2, obj.release_count());
207 }
208 EXPECT_EQ(3, obj.retain_count());
209 EXPECT_EQ(3, obj.release_count());
210}
211
214 {
215 RetainPtr<PseudoRetainable> ptr1(&obj);
216 {
217 RetainPtr<const PseudoRetainable> ptr2;
218 ptr2 = std::move(ptr1);
219 EXPECT_FALSE(ptr1);
220 EXPECT_EQ(&obj, ptr2.Get());
221 EXPECT_EQ(1, obj.retain_count());
222 EXPECT_EQ(0, obj.release_count());
223 }
224 EXPECT_EQ(1, obj.retain_count());
225 EXPECT_EQ(1, obj.release_count());
226 }
227 EXPECT_EQ(1, obj.retain_count());
228 EXPECT_EQ(1, obj.release_count());
229}
230
232 class A : public Retainable {};
233 class B : public A {};
234
235 // Test passes if it compiles without error.
236 RetainPtr<A> var = (0) ? pdfium::MakeRetain<A>() : pdfium::MakeRetain<B>();
237 EXPECT_TRUE(var);
238}
239
240TEST(RetainPtr, ResetNull) {
242 {
243 RetainPtr<PseudoRetainable> ptr(&obj);
244 ptr.Reset();
245 EXPECT_EQ(1, obj.retain_count());
246 EXPECT_EQ(1, obj.release_count());
247 }
248 EXPECT_EQ(1, obj.retain_count());
249 EXPECT_EQ(1, obj.release_count());
250}
251
252TEST(RetainPtr, Reset) {
253 PseudoRetainable obj1;
254 PseudoRetainable obj2;
255 {
256 RetainPtr<PseudoRetainable> ptr(&obj1);
257 ptr.Reset(&obj2);
258 EXPECT_EQ(1, obj1.retain_count());
259 EXPECT_EQ(1, obj1.release_count());
260 EXPECT_EQ(1, obj2.retain_count());
261 EXPECT_EQ(0, obj2.release_count());
262 }
263 EXPECT_EQ(1, obj1.retain_count());
264 EXPECT_EQ(1, obj1.release_count());
265 EXPECT_EQ(1, obj2.retain_count());
266 EXPECT_EQ(1, obj2.release_count());
267}
268
269TEST(RetainPtr, Swap) {
270 PseudoRetainable obj1;
271 PseudoRetainable obj2;
272 {
273 RetainPtr<PseudoRetainable> ptr1(&obj1);
274 {
275 RetainPtr<PseudoRetainable> ptr2(&obj2);
276 ptr1.Swap(ptr2);
277 EXPECT_EQ(1, obj1.retain_count());
278 EXPECT_EQ(0, obj1.release_count());
279 EXPECT_EQ(1, obj2.retain_count());
280 EXPECT_EQ(0, obj2.release_count());
281 }
282 EXPECT_EQ(1, obj1.retain_count());
283 EXPECT_EQ(1, obj1.release_count());
284 EXPECT_EQ(1, obj2.retain_count());
285 EXPECT_EQ(0, obj2.release_count());
286 }
287 EXPECT_EQ(1, obj1.retain_count());
288 EXPECT_EQ(1, obj1.release_count());
289 EXPECT_EQ(1, obj2.retain_count());
290 EXPECT_EQ(1, obj2.release_count());
291}
292
293TEST(RetainPtr, Leak) {
295 PseudoRetainable* leak;
296 {
297 RetainPtr<PseudoRetainable> ptr(&obj);
298 leak = ptr.Leak();
299 EXPECT_EQ(1, obj.retain_count());
300 EXPECT_EQ(0, obj.release_count());
301 }
302 EXPECT_EQ(1, obj.retain_count());
303 EXPECT_EQ(0, obj.release_count());
304 {
306 ptr.Unleak(leak);
307 EXPECT_EQ(1, obj.retain_count());
308 EXPECT_EQ(0, obj.release_count());
309 }
310 EXPECT_EQ(1, obj.retain_count());
311 EXPECT_EQ(1, obj.release_count());
312}
313
314TEST(RetainPtr, SwapNull) {
315 PseudoRetainable obj1;
316 {
317 RetainPtr<PseudoRetainable> ptr1(&obj1);
318 {
320 ptr1.Swap(ptr2);
321 EXPECT_FALSE(ptr1);
322 EXPECT_TRUE(ptr2);
323 EXPECT_EQ(1, obj1.retain_count());
324 EXPECT_EQ(0, obj1.release_count());
325 }
326 EXPECT_EQ(1, obj1.retain_count());
327 EXPECT_EQ(1, obj1.release_count());
328 }
329 EXPECT_EQ(1, obj1.retain_count());
330 EXPECT_EQ(1, obj1.release_count());
331}
332
333TEST(RetainPtr, Equals) {
334 PseudoRetainable obj1;
335 PseudoRetainable obj2;
336 RetainPtr<PseudoRetainable> null_ptr1;
337 RetainPtr<PseudoRetainable> obj1_ptr1(&obj1);
338 RetainPtr<PseudoRetainable> obj2_ptr1(&obj2);
339 {
340 RetainPtr<PseudoRetainable> null_ptr2;
341 EXPECT_TRUE(null_ptr1 == null_ptr2);
342 EXPECT_TRUE(null_ptr1 == nullptr);
343
344 RetainPtr<PseudoRetainable> obj1_ptr2(&obj1);
345 EXPECT_TRUE(obj1_ptr1 == obj1_ptr2);
346 EXPECT_TRUE(obj1_ptr2 == &obj1);
347
348 RetainPtr<PseudoRetainable> obj2_ptr2(&obj2);
349 EXPECT_TRUE(obj2_ptr1 == obj2_ptr2);
350 }
351 EXPECT_FALSE(null_ptr1 == obj1_ptr1);
352 EXPECT_FALSE(null_ptr1 == obj2_ptr1);
353 EXPECT_FALSE(obj1_ptr1 == obj2_ptr1);
354}
355
357 PseudoRetainable obj1;
358 PseudoRetainable obj2;
359 RetainPtr<PseudoRetainable> obj1_ptr(&obj1);
360 RetainPtr<PseudoRetainable> obj2_ptr(&obj2);
361 EXPECT_TRUE(&obj1 == obj1_ptr);
362 EXPECT_FALSE(&obj1 == obj2_ptr);
363 EXPECT_FALSE(&obj2 == obj1_ptr);
364 EXPECT_TRUE(&obj2 == obj2_ptr);
365}
366
367TEST(RetainPtr, NotEquals) {
368 PseudoRetainable obj1;
369 PseudoRetainable obj2;
370 RetainPtr<PseudoRetainable> null_ptr1;
371 RetainPtr<PseudoRetainable> obj1_ptr1(&obj1);
372 RetainPtr<PseudoRetainable> obj2_ptr1(&obj2);
373 {
374 RetainPtr<PseudoRetainable> null_ptr2;
375 RetainPtr<PseudoRetainable> obj1_ptr2(&obj1);
376 RetainPtr<PseudoRetainable> obj2_ptr2(&obj2);
377 EXPECT_FALSE(null_ptr1 != null_ptr2);
378 EXPECT_FALSE(obj1_ptr1 != obj1_ptr2);
379 EXPECT_FALSE(obj2_ptr1 != obj2_ptr2);
380 }
381 EXPECT_TRUE(null_ptr1 != obj1_ptr1);
382 EXPECT_TRUE(null_ptr1 != obj2_ptr1);
383 EXPECT_TRUE(obj1_ptr1 != obj2_ptr1);
384}
385
387 PseudoRetainable obj1;
388 PseudoRetainable obj2;
389 RetainPtr<PseudoRetainable> obj1_ptr(&obj1);
390 RetainPtr<PseudoRetainable> obj2_ptr(&obj2);
391 EXPECT_FALSE(&obj1 != obj1_ptr);
392 EXPECT_TRUE(&obj1 != obj2_ptr);
393 EXPECT_TRUE(&obj2 != obj1_ptr);
394 EXPECT_FALSE(&obj2 != obj2_ptr);
395}
396
397TEST(RetainPtr, LessThan) {
398 PseudoRetainable objs[2];
399 RetainPtr<PseudoRetainable> obj1_ptr(&objs[0]);
400 RetainPtr<PseudoRetainable> obj2_ptr(&objs[1]);
401 EXPECT_TRUE(obj1_ptr < obj2_ptr);
402 EXPECT_FALSE(obj2_ptr < obj1_ptr);
403}
404
405TEST(RetainPtr, Bool) {
406 PseudoRetainable obj1;
407 RetainPtr<PseudoRetainable> null_ptr;
408 RetainPtr<PseudoRetainable> obj1_ptr(&obj1);
409 bool null_bool = !!null_ptr;
410 bool obj1_bool = !!obj1_ptr;
411 EXPECT_FALSE(null_bool);
412 EXPECT_TRUE(obj1_bool);
413}
414
415TEST(RetainPtr, MakeRetained) {
416 auto ptr = pdfium::MakeRetain<Retainable>();
417 EXPECT_TRUE(ptr->HasOneRef());
418 {
419 RetainPtr<Retainable> other = ptr;
420 EXPECT_FALSE(ptr->HasOneRef());
421 }
422 EXPECT_TRUE(ptr->HasOneRef());
423}
424
425TEST(RetainPtr, VectorMove) {
426 // Proves move ctor is selected by std::vector over copy/delete, this
427 // may require the ctor to be marked "noexcept".
429 {
430 RetainPtr<PseudoRetainable> ptr(&obj);
431 std::vector<RetainPtr<PseudoRetainable>> vec1;
432 vec1.push_back(std::move(ptr));
433 EXPECT_EQ(1, obj.retain_count());
434 EXPECT_EQ(0, obj.release_count());
435
436 std::vector<RetainPtr<PseudoRetainable>> vec2 = std::move(vec1);
437 EXPECT_EQ(1, obj.retain_count());
438 EXPECT_EQ(0, obj.release_count());
439
440 vec2.resize(4096);
441 EXPECT_EQ(1, obj.retain_count());
442 EXPECT_EQ(0, obj.release_count());
443 }
444 EXPECT_EQ(1, obj.retain_count());
445 EXPECT_EQ(1, obj.release_count());
446}
447
448TEST(RetainPtr, SetContains) {
449 // Makes sure pdfium::Contains() works the same way with raw pointers and
450 // RetainPtrs for containers that use find().
451 PseudoRetainable obj1;
452 PseudoRetainable obj2;
453 RetainPtr<PseudoRetainable> ptr1(&obj1);
454 RetainPtr<PseudoRetainable> ptr2(&obj2);
455 RetainPtr<const PseudoRetainable> const_ptr1(&obj1);
456 RetainPtr<const PseudoRetainable> const_ptr2(&obj2);
457 NoLinearSearchSet<RetainPtr<const PseudoRetainable>, std::less<>> the_set;
458
459 // Intially, two smart pointers to each object.
460 EXPECT_EQ(2, obj1.retain_count());
461 EXPECT_EQ(0, obj1.release_count());
462 EXPECT_EQ(2, obj2.retain_count());
463 EXPECT_EQ(0, obj2.release_count());
464
465 // Passed by const-ref, increment on copy into set's data structure.
466 the_set.insert(const_ptr1);
467 EXPECT_EQ(3, obj1.retain_count());
468 EXPECT_EQ(0, obj1.release_count());
469 EXPECT_EQ(2, obj2.retain_count());
470 EXPECT_EQ(0, obj2.release_count());
471
472 // None of the following should cause any churn.
473 EXPECT_NE(the_set.end(), the_set.find(&obj1));
474 EXPECT_EQ(the_set.end(), the_set.find(&obj2));
475 EXPECT_TRUE(pdfium::Contains(the_set, &obj1));
476 EXPECT_FALSE(pdfium::Contains(the_set, &obj2));
477 EXPECT_EQ(3, obj1.retain_count());
478 EXPECT_EQ(0, obj1.release_count());
479 EXPECT_EQ(2, obj2.retain_count());
480 EXPECT_EQ(0, obj2.release_count());
481
482 EXPECT_NE(the_set.end(), the_set.find(const_ptr1));
483 EXPECT_EQ(the_set.end(), the_set.find(const_ptr2));
484 EXPECT_TRUE(pdfium::Contains(the_set, const_ptr1));
485 EXPECT_FALSE(pdfium::Contains(the_set, const_ptr2));
486 EXPECT_EQ(3, obj1.retain_count());
487 EXPECT_EQ(0, obj1.release_count());
488 EXPECT_EQ(2, obj2.retain_count());
489 EXPECT_EQ(0, obj2.release_count());
490
491 // These involve const-removing conversions which seem to churn.
492 EXPECT_NE(the_set.end(), the_set.find(ptr1));
493 EXPECT_EQ(the_set.end(), the_set.find(ptr2));
494 EXPECT_TRUE(pdfium::Contains(the_set, ptr1));
495 EXPECT_FALSE(pdfium::Contains(the_set, ptr2));
496 EXPECT_EQ(5, obj1.retain_count());
497 EXPECT_EQ(2, obj1.release_count());
498 EXPECT_EQ(4, obj2.retain_count());
499 EXPECT_EQ(2, obj2.release_count());
500}
501
502TEST(RetainPtr, VectorContains) {
503 // Makes sure pdfium::Contains() works the same way with raw pointers and
504 // RetainPtrs. for containers that use begin()/end().
505 PseudoRetainable obj1;
506 PseudoRetainable obj2;
507 std::vector<const PseudoRetainable*> vec;
508 vec.push_back(&obj1);
509 EXPECT_TRUE(pdfium::Contains(vec, &obj1));
510 EXPECT_FALSE(pdfium::Contains(vec, &obj2));
511
512 RetainPtr<PseudoRetainable> ptr1(&obj1);
513 RetainPtr<PseudoRetainable> ptr2(&obj2);
514 EXPECT_TRUE(pdfium::Contains(vec, ptr1));
515 EXPECT_FALSE(pdfium::Contains(vec, ptr2));
516
517 RetainPtr<const PseudoRetainable> const_ptr1(&obj1);
518 RetainPtr<const PseudoRetainable> const_ptr2(&obj2);
519 EXPECT_TRUE(pdfium::Contains(vec, const_ptr1));
520 EXPECT_FALSE(pdfium::Contains(vec, const_ptr2));
521}
522
523} // namespace fxcrt
int release_count() const
int retain_count() const
TEST(CFX_BytrString, EqualNoCase)