OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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/memory/scoped_ptr.h" | |
6 | |
7 #include <stddef.h> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/callback.h" | |
11 #include "base/macros.h" | |
12 #include "build/build_config.h" | |
13 #include "testing/gtest/include/gtest/gtest.h" | |
14 | |
15 namespace { | |
16 | |
17 // Used to test depth subtyping. | |
18 class ConDecLoggerParent { | |
19 public: | |
20 virtual ~ConDecLoggerParent() {} | |
21 | |
22 virtual void SetPtr(int* ptr) = 0; | |
23 | |
24 virtual int SomeMeth(int x) const = 0; | |
25 }; | |
26 | |
27 class ConDecLogger : public ConDecLoggerParent { | |
28 public: | |
29 ConDecLogger() : ptr_(NULL) { } | |
30 explicit ConDecLogger(int* ptr) { SetPtr(ptr); } | |
31 ~ConDecLogger() override { --*ptr_; } | |
32 | |
33 void SetPtr(int* ptr) override { | |
34 ptr_ = ptr; | |
35 ++*ptr_; | |
36 } | |
37 | |
38 int SomeMeth(int x) const override { return x; } | |
39 | |
40 private: | |
41 int* ptr_; | |
42 | |
43 DISALLOW_COPY_AND_ASSIGN(ConDecLogger); | |
44 }; | |
45 | |
46 struct CountingDeleter { | |
47 explicit CountingDeleter(int* count) : count_(count) {} | |
48 inline void operator()(double* ptr) const { | |
49 (*count_)++; | |
50 } | |
51 int* count_; | |
52 }; | |
53 | |
54 // Used to test assignment of convertible deleters. | |
55 struct CountingDeleterChild : public CountingDeleter { | |
56 explicit CountingDeleterChild(int* count) : CountingDeleter(count) {} | |
57 }; | |
58 | |
59 class OverloadedNewAndDelete { | |
60 public: | |
61 void* operator new(size_t size) { | |
62 g_new_count++; | |
63 return malloc(size); | |
64 } | |
65 | |
66 void operator delete(void* ptr) { | |
67 g_delete_count++; | |
68 free(ptr); | |
69 } | |
70 | |
71 static void ResetCounters() { | |
72 g_new_count = 0; | |
73 g_delete_count = 0; | |
74 } | |
75 | |
76 static int new_count() { return g_new_count; } | |
77 static int delete_count() { return g_delete_count; } | |
78 | |
79 private: | |
80 static int g_new_count; | |
81 static int g_delete_count; | |
82 }; | |
83 | |
84 int OverloadedNewAndDelete::g_new_count = 0; | |
85 int OverloadedNewAndDelete::g_delete_count = 0; | |
86 | |
87 scoped_ptr<ConDecLogger> PassThru(scoped_ptr<ConDecLogger> logger) { | |
88 return logger; | |
89 } | |
90 | |
91 void GrabAndDrop(scoped_ptr<ConDecLogger> logger) { | |
92 } | |
93 | |
94 // Do not delete this function! It's existence is to test that you can | |
95 // return a temporarily constructed version of the scoper. | |
96 scoped_ptr<ConDecLogger> TestReturnOfType(int* constructed) { | |
97 return scoped_ptr<ConDecLogger>(new ConDecLogger(constructed)); | |
98 } | |
99 | |
100 } // namespace | |
101 | |
102 TEST(ScopedPtrTest, ScopedPtr) { | |
103 int constructed = 0; | |
104 | |
105 // Ensure size of scoped_ptr<> doesn't increase unexpectedly. | |
106 static_assert(sizeof(int*) >= sizeof(scoped_ptr<int>), | |
107 "scoped_ptr shouldn't be larger than the raw pointer"); | |
108 | |
109 { | |
110 scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed)); | |
111 EXPECT_EQ(1, constructed); | |
112 EXPECT_TRUE(scoper.get()); | |
113 | |
114 EXPECT_EQ(10, scoper->SomeMeth(10)); | |
115 EXPECT_EQ(10, scoper.get()->SomeMeth(10)); | |
116 EXPECT_EQ(10, (*scoper).SomeMeth(10)); | |
117 } | |
118 EXPECT_EQ(0, constructed); | |
119 | |
120 // Test reset() and release() | |
121 { | |
122 scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed)); | |
123 EXPECT_EQ(1, constructed); | |
124 EXPECT_TRUE(scoper.get()); | |
125 | |
126 scoper.reset(new ConDecLogger(&constructed)); | |
127 EXPECT_EQ(1, constructed); | |
128 EXPECT_TRUE(scoper.get()); | |
129 | |
130 scoper.reset(); | |
131 EXPECT_EQ(0, constructed); | |
132 EXPECT_FALSE(scoper.get()); | |
133 | |
134 scoper.reset(new ConDecLogger(&constructed)); | |
135 EXPECT_EQ(1, constructed); | |
136 EXPECT_TRUE(scoper.get()); | |
137 | |
138 ConDecLogger* take = scoper.release(); | |
139 EXPECT_EQ(1, constructed); | |
140 EXPECT_FALSE(scoper.get()); | |
141 delete take; | |
142 EXPECT_EQ(0, constructed); | |
143 | |
144 scoper.reset(new ConDecLogger(&constructed)); | |
145 EXPECT_EQ(1, constructed); | |
146 EXPECT_TRUE(scoper.get()); | |
147 } | |
148 EXPECT_EQ(0, constructed); | |
149 | |
150 // Test swap(). | |
151 { | |
152 scoped_ptr<ConDecLogger> scoper1; | |
153 scoped_ptr<ConDecLogger> scoper2; | |
154 EXPECT_TRUE(scoper1.get() == scoper2.get()); | |
155 EXPECT_FALSE(scoper1.get() != scoper2.get()); | |
156 | |
157 ConDecLogger* logger = new ConDecLogger(&constructed); | |
158 scoper1.reset(logger); | |
159 EXPECT_EQ(logger, scoper1.get()); | |
160 EXPECT_FALSE(scoper2.get()); | |
161 EXPECT_FALSE(scoper1.get() == scoper2.get()); | |
162 EXPECT_TRUE(scoper1.get() != scoper2.get()); | |
163 | |
164 scoper2.swap(scoper1); | |
165 EXPECT_EQ(logger, scoper2.get()); | |
166 EXPECT_FALSE(scoper1.get()); | |
167 EXPECT_FALSE(scoper1.get() == scoper2.get()); | |
168 EXPECT_TRUE(scoper1.get() != scoper2.get()); | |
169 } | |
170 EXPECT_EQ(0, constructed); | |
171 } | |
172 | |
173 TEST(ScopedPtrTest, ScopedPtrDepthSubtyping) { | |
174 int constructed = 0; | |
175 | |
176 // Test construction from a scoped_ptr to a derived class. | |
177 { | |
178 scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed)); | |
179 EXPECT_EQ(1, constructed); | |
180 EXPECT_TRUE(scoper.get()); | |
181 | |
182 scoped_ptr<ConDecLoggerParent> scoper_parent(std::move(scoper)); | |
183 EXPECT_EQ(1, constructed); | |
184 EXPECT_TRUE(scoper_parent.get()); | |
185 EXPECT_FALSE(scoper.get()); | |
186 | |
187 EXPECT_EQ(10, scoper_parent->SomeMeth(10)); | |
188 EXPECT_EQ(10, scoper_parent.get()->SomeMeth(10)); | |
189 EXPECT_EQ(10, (*scoper_parent).SomeMeth(10)); | |
190 } | |
191 EXPECT_EQ(0, constructed); | |
192 | |
193 // Test assignment from a scoped_ptr to a derived class. | |
194 { | |
195 scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed)); | |
196 EXPECT_EQ(1, constructed); | |
197 EXPECT_TRUE(scoper.get()); | |
198 | |
199 scoped_ptr<ConDecLoggerParent> scoper_parent; | |
200 scoper_parent = std::move(scoper); | |
201 EXPECT_EQ(1, constructed); | |
202 EXPECT_TRUE(scoper_parent.get()); | |
203 EXPECT_FALSE(scoper.get()); | |
204 } | |
205 EXPECT_EQ(0, constructed); | |
206 | |
207 // Test construction of a scoped_ptr with an additional const annotation. | |
208 { | |
209 scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed)); | |
210 EXPECT_EQ(1, constructed); | |
211 EXPECT_TRUE(scoper.get()); | |
212 | |
213 scoped_ptr<const ConDecLogger> scoper_const(std::move(scoper)); | |
214 EXPECT_EQ(1, constructed); | |
215 EXPECT_TRUE(scoper_const.get()); | |
216 EXPECT_FALSE(scoper.get()); | |
217 | |
218 EXPECT_EQ(10, scoper_const->SomeMeth(10)); | |
219 EXPECT_EQ(10, scoper_const.get()->SomeMeth(10)); | |
220 EXPECT_EQ(10, (*scoper_const).SomeMeth(10)); | |
221 } | |
222 EXPECT_EQ(0, constructed); | |
223 | |
224 // Test assignment to a scoped_ptr with an additional const annotation. | |
225 { | |
226 scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed)); | |
227 EXPECT_EQ(1, constructed); | |
228 EXPECT_TRUE(scoper.get()); | |
229 | |
230 scoped_ptr<const ConDecLogger> scoper_const; | |
231 scoper_const = std::move(scoper); | |
232 EXPECT_EQ(1, constructed); | |
233 EXPECT_TRUE(scoper_const.get()); | |
234 EXPECT_FALSE(scoper.get()); | |
235 } | |
236 EXPECT_EQ(0, constructed); | |
237 | |
238 // Test assignment to a scoped_ptr deleter of parent type. | |
239 { | |
240 // Custom deleters never touch these value. | |
241 double dummy_value, dummy_value2; | |
242 int deletes = 0; | |
243 int alternate_deletes = 0; | |
244 scoped_ptr<double, CountingDeleter> scoper(&dummy_value, | |
245 CountingDeleter(&deletes)); | |
246 scoped_ptr<double, CountingDeleterChild> scoper_child( | |
247 &dummy_value2, CountingDeleterChild(&alternate_deletes)); | |
248 | |
249 EXPECT_TRUE(scoper); | |
250 EXPECT_TRUE(scoper_child); | |
251 EXPECT_EQ(0, deletes); | |
252 EXPECT_EQ(0, alternate_deletes); | |
253 | |
254 // Test this compiles and correctly overwrites the deleter state. | |
255 scoper = std::move(scoper_child); | |
256 EXPECT_TRUE(scoper); | |
257 EXPECT_FALSE(scoper_child); | |
258 EXPECT_EQ(1, deletes); | |
259 EXPECT_EQ(0, alternate_deletes); | |
260 | |
261 scoper.reset(); | |
262 EXPECT_FALSE(scoper); | |
263 EXPECT_FALSE(scoper_child); | |
264 EXPECT_EQ(1, deletes); | |
265 EXPECT_EQ(1, alternate_deletes); | |
266 | |
267 scoper_child.reset(&dummy_value); | |
268 EXPECT_TRUE(scoper_child); | |
269 EXPECT_EQ(1, deletes); | |
270 EXPECT_EQ(1, alternate_deletes); | |
271 scoped_ptr<double, CountingDeleter> scoper_construct( | |
272 std::move(scoper_child)); | |
273 EXPECT_TRUE(scoper_construct); | |
274 EXPECT_FALSE(scoper_child); | |
275 EXPECT_EQ(1, deletes); | |
276 EXPECT_EQ(1, alternate_deletes); | |
277 | |
278 scoper_construct.reset(); | |
279 EXPECT_EQ(1, deletes); | |
280 EXPECT_EQ(2, alternate_deletes); | |
281 } | |
282 } | |
283 | |
284 TEST(ScopedPtrTest, ScopedPtrWithArray) { | |
285 static const int kNumLoggers = 12; | |
286 | |
287 int constructed = 0; | |
288 | |
289 { | |
290 scoped_ptr<ConDecLogger[]> scoper(new ConDecLogger[kNumLoggers]); | |
291 EXPECT_TRUE(scoper); | |
292 EXPECT_EQ(&scoper[0], scoper.get()); | |
293 for (int i = 0; i < kNumLoggers; ++i) { | |
294 scoper[i].SetPtr(&constructed); | |
295 } | |
296 EXPECT_EQ(12, constructed); | |
297 | |
298 EXPECT_EQ(10, scoper.get()->SomeMeth(10)); | |
299 EXPECT_EQ(10, scoper[2].SomeMeth(10)); | |
300 } | |
301 EXPECT_EQ(0, constructed); | |
302 | |
303 // Test reset() and release() | |
304 { | |
305 scoped_ptr<ConDecLogger[]> scoper; | |
306 EXPECT_FALSE(scoper.get()); | |
307 EXPECT_FALSE(scoper.release()); | |
308 EXPECT_FALSE(scoper.get()); | |
309 scoper.reset(); | |
310 EXPECT_FALSE(scoper.get()); | |
311 | |
312 scoper.reset(new ConDecLogger[kNumLoggers]); | |
313 for (int i = 0; i < kNumLoggers; ++i) { | |
314 scoper[i].SetPtr(&constructed); | |
315 } | |
316 EXPECT_EQ(12, constructed); | |
317 scoper.reset(); | |
318 EXPECT_EQ(0, constructed); | |
319 | |
320 scoper.reset(new ConDecLogger[kNumLoggers]); | |
321 for (int i = 0; i < kNumLoggers; ++i) { | |
322 scoper[i].SetPtr(&constructed); | |
323 } | |
324 EXPECT_EQ(12, constructed); | |
325 ConDecLogger* ptr = scoper.release(); | |
326 EXPECT_EQ(12, constructed); | |
327 delete[] ptr; | |
328 EXPECT_EQ(0, constructed); | |
329 } | |
330 EXPECT_EQ(0, constructed); | |
331 | |
332 // Test swap() and type-safe Boolean. | |
333 { | |
334 scoped_ptr<ConDecLogger[]> scoper1; | |
335 scoped_ptr<ConDecLogger[]> scoper2; | |
336 EXPECT_TRUE(scoper1.get() == scoper2.get()); | |
337 EXPECT_FALSE(scoper1.get() != scoper2.get()); | |
338 | |
339 ConDecLogger* loggers = new ConDecLogger[kNumLoggers]; | |
340 for (int i = 0; i < kNumLoggers; ++i) { | |
341 loggers[i].SetPtr(&constructed); | |
342 } | |
343 scoper1.reset(loggers); | |
344 EXPECT_TRUE(scoper1); | |
345 EXPECT_EQ(loggers, scoper1.get()); | |
346 EXPECT_FALSE(scoper2); | |
347 EXPECT_FALSE(scoper2.get()); | |
348 EXPECT_FALSE(scoper1.get() == scoper2.get()); | |
349 EXPECT_TRUE(scoper1.get() != scoper2.get()); | |
350 | |
351 scoper2.swap(scoper1); | |
352 EXPECT_EQ(loggers, scoper2.get()); | |
353 EXPECT_FALSE(scoper1.get()); | |
354 EXPECT_FALSE(scoper1.get() == scoper2.get()); | |
355 EXPECT_TRUE(scoper1.get() != scoper2.get()); | |
356 } | |
357 EXPECT_EQ(0, constructed); | |
358 | |
359 { | |
360 ConDecLogger* loggers = new ConDecLogger[kNumLoggers]; | |
361 scoped_ptr<ConDecLogger[]> scoper(loggers); | |
362 EXPECT_TRUE(scoper); | |
363 for (int i = 0; i < kNumLoggers; ++i) { | |
364 scoper[i].SetPtr(&constructed); | |
365 } | |
366 EXPECT_EQ(kNumLoggers, constructed); | |
367 | |
368 // Test moving with constructor; | |
369 scoped_ptr<ConDecLogger[]> scoper2(std::move(scoper)); | |
370 EXPECT_EQ(kNumLoggers, constructed); | |
371 | |
372 // Test moving with assignment; | |
373 scoped_ptr<ConDecLogger[]> scoper3; | |
374 scoper3 = std::move(scoper2); | |
375 EXPECT_EQ(kNumLoggers, constructed); | |
376 EXPECT_FALSE(scoper); | |
377 EXPECT_FALSE(scoper2); | |
378 EXPECT_TRUE(scoper3); | |
379 } | |
380 EXPECT_EQ(0, constructed); | |
381 } | |
382 | |
383 TEST(ScopedPtrTest, MoveBehavior) { | |
384 int constructed = 0; | |
385 { | |
386 ConDecLogger* logger = new ConDecLogger(&constructed); | |
387 scoped_ptr<ConDecLogger> scoper(logger); | |
388 EXPECT_EQ(1, constructed); | |
389 | |
390 // Test moving with constructor; | |
391 scoped_ptr<ConDecLogger> scoper2(std::move(scoper)); | |
392 EXPECT_EQ(1, constructed); | |
393 | |
394 // Test moving with assignment; | |
395 scoped_ptr<ConDecLogger> scoper3; | |
396 scoper3 = std::move(scoper2); | |
397 EXPECT_EQ(1, constructed); | |
398 EXPECT_FALSE(scoper.get()); | |
399 EXPECT_FALSE(scoper2.get()); | |
400 EXPECT_TRUE(scoper3.get()); | |
401 } | |
402 | |
403 // Test that passing to function which does nothing does not leak. | |
404 { | |
405 ConDecLogger* logger = new ConDecLogger(&constructed); | |
406 scoped_ptr<ConDecLogger> scoper(logger); | |
407 EXPECT_EQ(1, constructed); | |
408 | |
409 // Should auto-destruct logger by end of scope. | |
410 GrabAndDrop(std::move(scoper)); | |
411 EXPECT_FALSE(scoper.get()); | |
412 } | |
413 EXPECT_EQ(0, constructed); | |
414 } | |
415 | |
416 TEST(ScopedPtrTest, ReturnTypeBehavior) { | |
417 int constructed = 0; | |
418 | |
419 // Test that we can return a scoped_ptr. | |
420 { | |
421 ConDecLogger* logger = new ConDecLogger(&constructed); | |
422 scoped_ptr<ConDecLogger> scoper(logger); | |
423 EXPECT_EQ(1, constructed); | |
424 | |
425 PassThru(std::move(scoper)); | |
426 EXPECT_FALSE(scoper.get()); | |
427 } | |
428 EXPECT_EQ(0, constructed); | |
429 | |
430 // Test uncaught return type not leak. | |
431 { | |
432 ConDecLogger* logger = new ConDecLogger(&constructed); | |
433 scoped_ptr<ConDecLogger> scoper(logger); | |
434 EXPECT_EQ(1, constructed); | |
435 | |
436 // Should auto-destruct logger by end of scope. | |
437 PassThru(std::move(scoper)); | |
438 EXPECT_FALSE(scoper.get()); | |
439 } | |
440 EXPECT_EQ(0, constructed); | |
441 | |
442 // Call TestReturnOfType() so the compiler doesn't warn for an unused | |
443 // function. | |
444 { | |
445 TestReturnOfType(&constructed); | |
446 } | |
447 EXPECT_EQ(0, constructed); | |
448 } | |
449 | |
450 TEST(ScopedPtrTest, CustomDeleter) { | |
451 double dummy_value; // Custom deleter never touches this value. | |
452 int deletes = 0; | |
453 int alternate_deletes = 0; | |
454 | |
455 // Normal delete support. | |
456 { | |
457 deletes = 0; | |
458 scoped_ptr<double, CountingDeleter> scoper(&dummy_value, | |
459 CountingDeleter(&deletes)); | |
460 EXPECT_EQ(0, deletes); | |
461 EXPECT_TRUE(scoper.get()); | |
462 } | |
463 EXPECT_EQ(1, deletes); | |
464 | |
465 // Test reset() and release(). | |
466 deletes = 0; | |
467 { | |
468 scoped_ptr<double, CountingDeleter> scoper(NULL, | |
469 CountingDeleter(&deletes)); | |
470 EXPECT_FALSE(scoper.get()); | |
471 EXPECT_FALSE(scoper.release()); | |
472 EXPECT_FALSE(scoper.get()); | |
473 scoper.reset(); | |
474 EXPECT_FALSE(scoper.get()); | |
475 EXPECT_EQ(0, deletes); | |
476 | |
477 scoper.reset(&dummy_value); | |
478 scoper.reset(); | |
479 EXPECT_EQ(1, deletes); | |
480 | |
481 scoper.reset(&dummy_value); | |
482 EXPECT_EQ(&dummy_value, scoper.release()); | |
483 } | |
484 EXPECT_EQ(1, deletes); | |
485 | |
486 // Test get_deleter(). | |
487 deletes = 0; | |
488 alternate_deletes = 0; | |
489 { | |
490 scoped_ptr<double, CountingDeleter> scoper(&dummy_value, | |
491 CountingDeleter(&deletes)); | |
492 // Call deleter manually. | |
493 EXPECT_EQ(0, deletes); | |
494 scoper.get_deleter()(&dummy_value); | |
495 EXPECT_EQ(1, deletes); | |
496 | |
497 // Deleter is still there after reset. | |
498 scoper.reset(); | |
499 EXPECT_EQ(2, deletes); | |
500 scoper.get_deleter()(&dummy_value); | |
501 EXPECT_EQ(3, deletes); | |
502 | |
503 // Deleter can be assigned into (matches C++11 unique_ptr<> spec). | |
504 scoper.get_deleter() = CountingDeleter(&alternate_deletes); | |
505 scoper.reset(&dummy_value); | |
506 EXPECT_EQ(0, alternate_deletes); | |
507 | |
508 } | |
509 EXPECT_EQ(3, deletes); | |
510 EXPECT_EQ(1, alternate_deletes); | |
511 | |
512 // Test operator= deleter support. | |
513 deletes = 0; | |
514 alternate_deletes = 0; | |
515 { | |
516 double dummy_value2; | |
517 scoped_ptr<double, CountingDeleter> scoper(&dummy_value, | |
518 CountingDeleter(&deletes)); | |
519 scoped_ptr<double, CountingDeleter> scoper2( | |
520 &dummy_value2, | |
521 CountingDeleter(&alternate_deletes)); | |
522 EXPECT_EQ(0, deletes); | |
523 EXPECT_EQ(0, alternate_deletes); | |
524 | |
525 // Pass the second deleter through a constructor and an operator=. Then | |
526 // reinitialize the empty scopers to ensure that each one is deleting | |
527 // properly. | |
528 scoped_ptr<double, CountingDeleter> scoper3(std::move(scoper2)); | |
529 scoper = std::move(scoper3); | |
530 EXPECT_EQ(1, deletes); | |
531 | |
532 scoper2.reset(&dummy_value2); | |
533 scoper3.reset(&dummy_value2); | |
534 EXPECT_EQ(0, alternate_deletes); | |
535 | |
536 } | |
537 EXPECT_EQ(1, deletes); | |
538 EXPECT_EQ(3, alternate_deletes); | |
539 | |
540 // Test swap(), and type-safe Boolean. | |
541 { | |
542 scoped_ptr<double, CountingDeleter> scoper1(NULL, | |
543 CountingDeleter(&deletes)); | |
544 scoped_ptr<double, CountingDeleter> scoper2(NULL, | |
545 CountingDeleter(&deletes)); | |
546 EXPECT_TRUE(scoper1.get() == scoper2.get()); | |
547 EXPECT_FALSE(scoper1.get() != scoper2.get()); | |
548 | |
549 scoper1.reset(&dummy_value); | |
550 EXPECT_TRUE(scoper1); | |
551 EXPECT_EQ(&dummy_value, scoper1.get()); | |
552 EXPECT_FALSE(scoper2); | |
553 EXPECT_FALSE(scoper2.get()); | |
554 EXPECT_FALSE(scoper1.get() == scoper2.get()); | |
555 EXPECT_TRUE(scoper1.get() != scoper2.get()); | |
556 | |
557 scoper2.swap(scoper1); | |
558 EXPECT_EQ(&dummy_value, scoper2.get()); | |
559 EXPECT_FALSE(scoper1.get()); | |
560 EXPECT_FALSE(scoper1.get() == scoper2.get()); | |
561 EXPECT_TRUE(scoper1.get() != scoper2.get()); | |
562 } | |
563 } | |
564 | |
565 // Sanity check test for overloaded new and delete operators. Does not do full | |
566 // coverage of reset/release/move operations as that is redundant with the | |
567 // above. | |
568 TEST(ScopedPtrTest, OverloadedNewAndDelete) { | |
569 { | |
570 OverloadedNewAndDelete::ResetCounters(); | |
571 scoped_ptr<OverloadedNewAndDelete> scoper(new OverloadedNewAndDelete()); | |
572 EXPECT_TRUE(scoper.get()); | |
573 | |
574 scoped_ptr<OverloadedNewAndDelete> scoper2(std::move(scoper)); | |
575 } | |
576 EXPECT_EQ(1, OverloadedNewAndDelete::delete_count()); | |
577 EXPECT_EQ(1, OverloadedNewAndDelete::new_count()); | |
578 } | |
579 | |
580 scoped_ptr<int> NullIntReturn() { | |
581 return nullptr; | |
582 } | |
583 | |
584 TEST(ScopedPtrTest, Nullptr) { | |
585 scoped_ptr<int> scoper1(nullptr); | |
586 scoped_ptr<int> scoper2(new int); | |
587 scoper2 = nullptr; | |
588 scoped_ptr<int> scoper3(NullIntReturn()); | |
589 scoped_ptr<int> scoper4 = NullIntReturn(); | |
590 EXPECT_EQ(nullptr, scoper1.get()); | |
591 EXPECT_EQ(nullptr, scoper2.get()); | |
592 EXPECT_EQ(nullptr, scoper3.get()); | |
593 EXPECT_EQ(nullptr, scoper4.get()); | |
594 } | |
595 | |
596 scoped_ptr<int[]> NullIntArrayReturn() { | |
597 return nullptr; | |
598 } | |
599 | |
600 TEST(ScopedPtrTest, NullptrArray) { | |
601 scoped_ptr<int[]> scoper1(nullptr); | |
602 scoped_ptr<int[]> scoper2(new int[3]); | |
603 scoper2 = nullptr; | |
604 scoped_ptr<int[]> scoper3(NullIntArrayReturn()); | |
605 scoped_ptr<int[]> scoper4 = NullIntArrayReturn(); | |
606 EXPECT_EQ(nullptr, scoper1.get()); | |
607 EXPECT_EQ(nullptr, scoper2.get()); | |
608 EXPECT_EQ(nullptr, scoper3.get()); | |
609 EXPECT_EQ(nullptr, scoper4.get()); | |
610 } | |
611 | |
612 class Super {}; | |
613 class Sub : public Super {}; | |
614 | |
615 scoped_ptr<Sub> SubClassReturn() { | |
616 return make_scoped_ptr(new Sub); | |
617 } | |
618 | |
619 TEST(ScopedPtrTest, Conversion) { | |
620 scoped_ptr<Sub> sub1(new Sub); | |
621 scoped_ptr<Sub> sub2(new Sub); | |
622 | |
623 // Upcast with move works. | |
624 scoped_ptr<Super> super1 = std::move(sub1); | |
625 super1 = std::move(sub2); | |
626 | |
627 // Upcast with an rvalue works. | |
628 scoped_ptr<Super> super2 = SubClassReturn(); | |
629 super2 = SubClassReturn(); | |
630 } | |
631 | |
632 TEST(ScopedPtrTest, ReferenceCycle) { | |
633 struct StructB; | |
634 struct StructA { | |
635 scoped_ptr<StructB> b; | |
636 }; | |
637 | |
638 struct StructB { | |
639 scoped_ptr<StructA> a; | |
640 }; | |
641 | |
642 // Create a reference cycle. | |
643 StructA* a = new StructA; | |
644 a->b.reset(new StructB); | |
645 a->b->a.reset(a); | |
646 | |
647 // Break the cycle by calling reset(). This will cause |a| (and hence, |a->b|) | |
648 // to be deleted before the call to reset() returns. This tests that the | |
649 // implementation of scoped_ptr::reset() doesn't access |this| after it | |
650 // deletes the underlying pointer. This behaviour is consistent with the | |
651 // definition of unique_ptr::reset in C++11. | |
652 a->b.reset(); | |
653 } | |
654 | |
655 TEST(ScopedPtrTest, Operators) { | |
656 struct Parent {}; | |
657 struct Child : public Parent {}; | |
658 | |
659 scoped_ptr<Parent> p(new Parent); | |
660 scoped_ptr<Parent> p2(new Parent); | |
661 scoped_ptr<Child> c(new Child); | |
662 scoped_ptr<Parent> pnull; | |
663 | |
664 // Operator==. | |
665 EXPECT_TRUE(p == p); | |
666 EXPECT_FALSE(p == c); | |
667 EXPECT_FALSE(p == p2); | |
668 EXPECT_FALSE(p == pnull); | |
669 | |
670 EXPECT_FALSE(p == nullptr); | |
671 EXPECT_FALSE(nullptr == p); | |
672 EXPECT_TRUE(pnull == nullptr); | |
673 EXPECT_TRUE(nullptr == pnull); | |
674 | |
675 // Operator!=. | |
676 EXPECT_FALSE(p != p); | |
677 EXPECT_TRUE(p != c); | |
678 EXPECT_TRUE(p != p2); | |
679 EXPECT_TRUE(p != pnull); | |
680 | |
681 EXPECT_TRUE(p != nullptr); | |
682 EXPECT_TRUE(nullptr != p); | |
683 EXPECT_FALSE(pnull != nullptr); | |
684 EXPECT_FALSE(nullptr != pnull); | |
685 | |
686 // Compare two scoped_ptr<T>. | |
687 EXPECT_EQ(p.get() < p2.get(), p < p2); | |
688 EXPECT_EQ(p.get() <= p2.get(), p <= p2); | |
689 EXPECT_EQ(p.get() > p2.get(), p > p2); | |
690 EXPECT_EQ(p.get() >= p2.get(), p >= p2); | |
691 EXPECT_EQ(p2.get() < p.get(), p2 < p); | |
692 EXPECT_EQ(p2.get() <= p.get(), p2 <= p); | |
693 EXPECT_EQ(p2.get() > p.get(), p2 > p); | |
694 EXPECT_EQ(p2.get() >= p.get(), p2 >= p); | |
695 | |
696 // And convertible scoped_ptr<T> and scoped_ptr<U>. | |
697 EXPECT_EQ(p.get() < c.get(), p < c); | |
698 EXPECT_EQ(p.get() <= c.get(), p <= c); | |
699 EXPECT_EQ(p.get() > c.get(), p > c); | |
700 EXPECT_EQ(p.get() >= c.get(), p >= c); | |
701 EXPECT_EQ(c.get() < p.get(), c < p); | |
702 EXPECT_EQ(c.get() <= p.get(), c <= p); | |
703 EXPECT_EQ(c.get() > p.get(), c > p); | |
704 EXPECT_EQ(c.get() >= p.get(), c >= p); | |
705 | |
706 // Compare to nullptr. | |
707 EXPECT_TRUE(p > nullptr); | |
708 EXPECT_FALSE(nullptr > p); | |
709 EXPECT_FALSE(pnull > nullptr); | |
710 EXPECT_FALSE(nullptr > pnull); | |
711 | |
712 EXPECT_TRUE(p >= nullptr); | |
713 EXPECT_FALSE(nullptr >= p); | |
714 EXPECT_TRUE(pnull >= nullptr); | |
715 EXPECT_TRUE(nullptr >= pnull); | |
716 | |
717 EXPECT_FALSE(p < nullptr); | |
718 EXPECT_TRUE(nullptr < p); | |
719 EXPECT_FALSE(pnull < nullptr); | |
720 EXPECT_FALSE(nullptr < pnull); | |
721 | |
722 EXPECT_FALSE(p <= nullptr); | |
723 EXPECT_TRUE(nullptr <= p); | |
724 EXPECT_TRUE(pnull <= nullptr); | |
725 EXPECT_TRUE(nullptr <= pnull); | |
726 }; | |
727 | |
728 TEST(ScopedPtrTest, ArrayOperators) { | |
729 struct Parent {}; | |
730 struct Child : public Parent {}; | |
731 | |
732 scoped_ptr<Parent[]> p(new Parent[1]); | |
733 scoped_ptr<Parent[]> p2(new Parent[1]); | |
734 scoped_ptr<Child[]> c(new Child[1]); | |
735 scoped_ptr<Parent[]> pnull; | |
736 | |
737 // Operator==. | |
738 EXPECT_TRUE(p == p); | |
739 EXPECT_FALSE(p == c); | |
740 EXPECT_FALSE(p == p2); | |
741 EXPECT_FALSE(p == pnull); | |
742 | |
743 EXPECT_FALSE(p == nullptr); | |
744 EXPECT_FALSE(nullptr == p); | |
745 EXPECT_TRUE(pnull == nullptr); | |
746 EXPECT_TRUE(nullptr == pnull); | |
747 | |
748 // Operator!=. | |
749 EXPECT_FALSE(p != p); | |
750 EXPECT_TRUE(p != c); | |
751 EXPECT_TRUE(p != p2); | |
752 EXPECT_TRUE(p != pnull); | |
753 | |
754 EXPECT_TRUE(p != nullptr); | |
755 EXPECT_TRUE(nullptr != p); | |
756 EXPECT_FALSE(pnull != nullptr); | |
757 EXPECT_FALSE(nullptr != pnull); | |
758 | |
759 // Compare two scoped_ptr<T>. | |
760 EXPECT_EQ(p.get() < p2.get(), p < p2); | |
761 EXPECT_EQ(p.get() <= p2.get(), p <= p2); | |
762 EXPECT_EQ(p.get() > p2.get(), p > p2); | |
763 EXPECT_EQ(p.get() >= p2.get(), p >= p2); | |
764 EXPECT_EQ(p2.get() < p.get(), p2 < p); | |
765 EXPECT_EQ(p2.get() <= p.get(), p2 <= p); | |
766 EXPECT_EQ(p2.get() > p.get(), p2 > p); | |
767 EXPECT_EQ(p2.get() >= p.get(), p2 >= p); | |
768 | |
769 // And convertible scoped_ptr<T> and scoped_ptr<U>. | |
770 EXPECT_EQ(p.get() < c.get(), p < c); | |
771 EXPECT_EQ(p.get() <= c.get(), p <= c); | |
772 EXPECT_EQ(p.get() > c.get(), p > c); | |
773 EXPECT_EQ(p.get() >= c.get(), p >= c); | |
774 EXPECT_EQ(c.get() < p.get(), c < p); | |
775 EXPECT_EQ(c.get() <= p.get(), c <= p); | |
776 EXPECT_EQ(c.get() > p.get(), c > p); | |
777 EXPECT_EQ(c.get() >= p.get(), c >= p); | |
778 | |
779 // Compare to nullptr. | |
780 EXPECT_TRUE(p > nullptr); | |
781 EXPECT_FALSE(nullptr > p); | |
782 EXPECT_FALSE(pnull > nullptr); | |
783 EXPECT_FALSE(nullptr > pnull); | |
784 | |
785 EXPECT_TRUE(p >= nullptr); | |
786 EXPECT_FALSE(nullptr >= p); | |
787 EXPECT_TRUE(pnull >= nullptr); | |
788 EXPECT_TRUE(nullptr >= pnull); | |
789 | |
790 EXPECT_FALSE(p < nullptr); | |
791 EXPECT_TRUE(nullptr < p); | |
792 EXPECT_FALSE(pnull < nullptr); | |
793 EXPECT_FALSE(nullptr < pnull); | |
794 | |
795 EXPECT_FALSE(p <= nullptr); | |
796 EXPECT_TRUE(nullptr <= p); | |
797 EXPECT_TRUE(pnull <= nullptr); | |
798 EXPECT_TRUE(nullptr <= pnull); | |
799 } | |
800 | |
801 // Boolean tests can be performed. | |
802 TEST(ScopedPtrTest, BooleanTesting) { | |
803 scoped_ptr<int> ptr_to_an_instance(new int); | |
804 EXPECT_TRUE(ptr_to_an_instance); | |
805 EXPECT_FALSE(!ptr_to_an_instance); | |
806 | |
807 if (ptr_to_an_instance) { | |
808 } else { | |
809 ADD_FAILURE() << "Pointer to an instance should result in true."; | |
810 } | |
811 | |
812 if (!ptr_to_an_instance) { // check for operator!(). | |
813 ADD_FAILURE() << "Pointer to an instance should result in !x being false."; | |
814 } | |
815 | |
816 scoped_ptr<int> null_ptr; | |
817 EXPECT_FALSE(null_ptr); | |
818 EXPECT_TRUE(!null_ptr); | |
819 | |
820 if (null_ptr) { | |
821 ADD_FAILURE() << "Null pointer should result in false."; | |
822 } | |
823 | |
824 if (!null_ptr) { // check for operator!(). | |
825 } else { | |
826 ADD_FAILURE() << "Null pointer should result in !x being true."; | |
827 } | |
828 } | |
OLD | NEW |