Roll google-toolbax-for-mac a095262:17eee69 (svn 685:703).
[chromium-blink-merge.git] / base / memory / scoped_ptr_unittest.cc
blobca7cfbf0cf02923d5daad193efebd5772760ae03
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.
5 #include "base/memory/scoped_ptr.h"
7 #include "base/basictypes.h"
8 #include "base/bind.h"
9 #include "base/callback.h"
10 #include "testing/gtest/include/gtest/gtest.h"
12 namespace {
14 // Used to test depth subtyping.
15 class ConDecLoggerParent {
16 public:
17 virtual ~ConDecLoggerParent() {}
19 virtual void SetPtr(int* ptr) = 0;
21 virtual int SomeMeth(int x) const = 0;
24 class ConDecLogger : public ConDecLoggerParent {
25 public:
26 ConDecLogger() : ptr_(NULL) { }
27 explicit ConDecLogger(int* ptr) { SetPtr(ptr); }
28 ~ConDecLogger() override { --*ptr_; }
30 void SetPtr(int* ptr) override {
31 ptr_ = ptr;
32 ++*ptr_;
35 int SomeMeth(int x) const override { return x; }
37 private:
38 int* ptr_;
40 DISALLOW_COPY_AND_ASSIGN(ConDecLogger);
43 struct CountingDeleter {
44 explicit CountingDeleter(int* count) : count_(count) {}
45 inline void operator()(double* ptr) const {
46 (*count_)++;
48 int* count_;
51 // Used to test assignment of convertible deleters.
52 struct CountingDeleterChild : public CountingDeleter {
53 explicit CountingDeleterChild(int* count) : CountingDeleter(count) {}
56 class OverloadedNewAndDelete {
57 public:
58 void* operator new(size_t size) {
59 g_new_count++;
60 return malloc(size);
63 void operator delete(void* ptr) {
64 g_delete_count++;
65 free(ptr);
68 static void ResetCounters() {
69 g_new_count = 0;
70 g_delete_count = 0;
73 static int new_count() { return g_new_count; }
74 static int delete_count() { return g_delete_count; }
76 private:
77 static int g_new_count;
78 static int g_delete_count;
81 int OverloadedNewAndDelete::g_new_count = 0;
82 int OverloadedNewAndDelete::g_delete_count = 0;
84 scoped_ptr<ConDecLogger> PassThru(scoped_ptr<ConDecLogger> logger) {
85 return logger.Pass();
88 void GrabAndDrop(scoped_ptr<ConDecLogger> logger) {
91 // Do not delete this function! It's existence is to test that you can
92 // return a temporarily constructed version of the scoper.
93 scoped_ptr<ConDecLogger> TestReturnOfType(int* constructed) {
94 return scoped_ptr<ConDecLogger>(new ConDecLogger(constructed));
97 } // namespace
99 TEST(ScopedPtrTest, ScopedPtr) {
100 int constructed = 0;
102 // Ensure size of scoped_ptr<> doesn't increase unexpectedly.
103 COMPILE_ASSERT(sizeof(int*) >= sizeof(scoped_ptr<int>),
104 scoped_ptr_larger_than_raw_ptr);
107 scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
108 EXPECT_EQ(1, constructed);
109 EXPECT_TRUE(scoper.get());
111 EXPECT_EQ(10, scoper->SomeMeth(10));
112 EXPECT_EQ(10, scoper.get()->SomeMeth(10));
113 EXPECT_EQ(10, (*scoper).SomeMeth(10));
115 EXPECT_EQ(0, constructed);
117 // Test reset() and release()
119 scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
120 EXPECT_EQ(1, constructed);
121 EXPECT_TRUE(scoper.get());
123 scoper.reset(new ConDecLogger(&constructed));
124 EXPECT_EQ(1, constructed);
125 EXPECT_TRUE(scoper.get());
127 scoper.reset();
128 EXPECT_EQ(0, constructed);
129 EXPECT_FALSE(scoper.get());
131 scoper.reset(new ConDecLogger(&constructed));
132 EXPECT_EQ(1, constructed);
133 EXPECT_TRUE(scoper.get());
135 ConDecLogger* take = scoper.release();
136 EXPECT_EQ(1, constructed);
137 EXPECT_FALSE(scoper.get());
138 delete take;
139 EXPECT_EQ(0, constructed);
141 scoper.reset(new ConDecLogger(&constructed));
142 EXPECT_EQ(1, constructed);
143 EXPECT_TRUE(scoper.get());
145 EXPECT_EQ(0, constructed);
147 // Test swap(), == and !=
149 scoped_ptr<ConDecLogger> scoper1;
150 scoped_ptr<ConDecLogger> scoper2;
151 EXPECT_TRUE(scoper1 == scoper2.get());
152 EXPECT_FALSE(scoper1 != scoper2.get());
154 ConDecLogger* logger = new ConDecLogger(&constructed);
155 scoper1.reset(logger);
156 EXPECT_EQ(logger, scoper1.get());
157 EXPECT_FALSE(scoper2.get());
158 EXPECT_FALSE(scoper1 == scoper2.get());
159 EXPECT_TRUE(scoper1 != scoper2.get());
161 scoper2.swap(scoper1);
162 EXPECT_EQ(logger, scoper2.get());
163 EXPECT_FALSE(scoper1.get());
164 EXPECT_FALSE(scoper1 == scoper2.get());
165 EXPECT_TRUE(scoper1 != scoper2.get());
167 EXPECT_EQ(0, constructed);
170 TEST(ScopedPtrTest, ScopedPtrDepthSubtyping) {
171 int constructed = 0;
173 // Test construction from a scoped_ptr to a derived class.
175 scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
176 EXPECT_EQ(1, constructed);
177 EXPECT_TRUE(scoper.get());
179 scoped_ptr<ConDecLoggerParent> scoper_parent(scoper.Pass());
180 EXPECT_EQ(1, constructed);
181 EXPECT_TRUE(scoper_parent.get());
182 EXPECT_FALSE(scoper.get());
184 EXPECT_EQ(10, scoper_parent->SomeMeth(10));
185 EXPECT_EQ(10, scoper_parent.get()->SomeMeth(10));
186 EXPECT_EQ(10, (*scoper_parent).SomeMeth(10));
188 EXPECT_EQ(0, constructed);
190 // Test assignment from a scoped_ptr to a derived class.
192 scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
193 EXPECT_EQ(1, constructed);
194 EXPECT_TRUE(scoper.get());
196 scoped_ptr<ConDecLoggerParent> scoper_parent;
197 scoper_parent = scoper.Pass();
198 EXPECT_EQ(1, constructed);
199 EXPECT_TRUE(scoper_parent.get());
200 EXPECT_FALSE(scoper.get());
202 EXPECT_EQ(0, constructed);
204 // Test construction of a scoped_ptr with an additional const annotation.
206 scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
207 EXPECT_EQ(1, constructed);
208 EXPECT_TRUE(scoper.get());
210 scoped_ptr<const ConDecLogger> scoper_const(scoper.Pass());
211 EXPECT_EQ(1, constructed);
212 EXPECT_TRUE(scoper_const.get());
213 EXPECT_FALSE(scoper.get());
215 EXPECT_EQ(10, scoper_const->SomeMeth(10));
216 EXPECT_EQ(10, scoper_const.get()->SomeMeth(10));
217 EXPECT_EQ(10, (*scoper_const).SomeMeth(10));
219 EXPECT_EQ(0, constructed);
221 // Test assignment to a scoped_ptr with an additional const annotation.
223 scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
224 EXPECT_EQ(1, constructed);
225 EXPECT_TRUE(scoper.get());
227 scoped_ptr<const ConDecLogger> scoper_const;
228 scoper_const = scoper.Pass();
229 EXPECT_EQ(1, constructed);
230 EXPECT_TRUE(scoper_const.get());
231 EXPECT_FALSE(scoper.get());
233 EXPECT_EQ(0, constructed);
235 // Test assignment to a scoped_ptr deleter of parent type.
237 // Custom deleters never touch these value.
238 double dummy_value, dummy_value2;
239 int deletes = 0;
240 int alternate_deletes = 0;
241 scoped_ptr<double, CountingDeleter> scoper(&dummy_value,
242 CountingDeleter(&deletes));
243 scoped_ptr<double, CountingDeleterChild> scoper_child(
244 &dummy_value2, CountingDeleterChild(&alternate_deletes));
246 EXPECT_TRUE(scoper);
247 EXPECT_TRUE(scoper_child);
248 EXPECT_EQ(0, deletes);
249 EXPECT_EQ(0, alternate_deletes);
251 // Test this compiles and correctly overwrites the deleter state.
252 scoper = scoper_child.Pass();
253 EXPECT_TRUE(scoper);
254 EXPECT_FALSE(scoper_child);
255 EXPECT_EQ(1, deletes);
256 EXPECT_EQ(0, alternate_deletes);
258 scoper.reset();
259 EXPECT_FALSE(scoper);
260 EXPECT_FALSE(scoper_child);
261 EXPECT_EQ(1, deletes);
262 EXPECT_EQ(1, alternate_deletes);
264 scoper_child.reset(&dummy_value);
265 EXPECT_TRUE(scoper_child);
266 EXPECT_EQ(1, deletes);
267 EXPECT_EQ(1, alternate_deletes);
268 scoped_ptr<double, CountingDeleter> scoper_construct(scoper_child.Pass());
269 EXPECT_TRUE(scoper_construct);
270 EXPECT_FALSE(scoper_child);
271 EXPECT_EQ(1, deletes);
272 EXPECT_EQ(1, alternate_deletes);
274 scoper_construct.reset();
275 EXPECT_EQ(1, deletes);
276 EXPECT_EQ(2, alternate_deletes);
280 TEST(ScopedPtrTest, ScopedPtrWithArray) {
281 static const int kNumLoggers = 12;
283 int constructed = 0;
286 scoped_ptr<ConDecLogger[]> scoper(new ConDecLogger[kNumLoggers]);
287 EXPECT_TRUE(scoper);
288 EXPECT_EQ(&scoper[0], scoper.get());
289 for (int i = 0; i < kNumLoggers; ++i) {
290 scoper[i].SetPtr(&constructed);
292 EXPECT_EQ(12, constructed);
294 EXPECT_EQ(10, scoper.get()->SomeMeth(10));
295 EXPECT_EQ(10, scoper[2].SomeMeth(10));
297 EXPECT_EQ(0, constructed);
299 // Test reset() and release()
301 scoped_ptr<ConDecLogger[]> scoper;
302 EXPECT_FALSE(scoper.get());
303 EXPECT_FALSE(scoper.release());
304 EXPECT_FALSE(scoper.get());
305 scoper.reset();
306 EXPECT_FALSE(scoper.get());
308 scoper.reset(new ConDecLogger[kNumLoggers]);
309 for (int i = 0; i < kNumLoggers; ++i) {
310 scoper[i].SetPtr(&constructed);
312 EXPECT_EQ(12, constructed);
313 scoper.reset();
314 EXPECT_EQ(0, constructed);
316 scoper.reset(new ConDecLogger[kNumLoggers]);
317 for (int i = 0; i < kNumLoggers; ++i) {
318 scoper[i].SetPtr(&constructed);
320 EXPECT_EQ(12, constructed);
321 ConDecLogger* ptr = scoper.release();
322 EXPECT_EQ(12, constructed);
323 delete[] ptr;
324 EXPECT_EQ(0, constructed);
326 EXPECT_EQ(0, constructed);
328 // Test swap(), ==, !=, and type-safe Boolean.
330 scoped_ptr<ConDecLogger[]> scoper1;
331 scoped_ptr<ConDecLogger[]> scoper2;
332 EXPECT_TRUE(scoper1 == scoper2.get());
333 EXPECT_FALSE(scoper1 != scoper2.get());
335 ConDecLogger* loggers = new ConDecLogger[kNumLoggers];
336 for (int i = 0; i < kNumLoggers; ++i) {
337 loggers[i].SetPtr(&constructed);
339 scoper1.reset(loggers);
340 EXPECT_TRUE(scoper1);
341 EXPECT_EQ(loggers, scoper1.get());
342 EXPECT_FALSE(scoper2);
343 EXPECT_FALSE(scoper2.get());
344 EXPECT_FALSE(scoper1 == scoper2.get());
345 EXPECT_TRUE(scoper1 != scoper2.get());
347 scoper2.swap(scoper1);
348 EXPECT_EQ(loggers, scoper2.get());
349 EXPECT_FALSE(scoper1.get());
350 EXPECT_FALSE(scoper1 == scoper2.get());
351 EXPECT_TRUE(scoper1 != scoper2.get());
353 EXPECT_EQ(0, constructed);
356 ConDecLogger* loggers = new ConDecLogger[kNumLoggers];
357 scoped_ptr<ConDecLogger[]> scoper(loggers);
358 EXPECT_TRUE(scoper);
359 for (int i = 0; i < kNumLoggers; ++i) {
360 scoper[i].SetPtr(&constructed);
362 EXPECT_EQ(kNumLoggers, constructed);
364 // Test Pass() with constructor;
365 scoped_ptr<ConDecLogger[]> scoper2(scoper.Pass());
366 EXPECT_EQ(kNumLoggers, constructed);
368 // Test Pass() with assignment;
369 scoped_ptr<ConDecLogger[]> scoper3;
370 scoper3 = scoper2.Pass();
371 EXPECT_EQ(kNumLoggers, constructed);
372 EXPECT_FALSE(scoper);
373 EXPECT_FALSE(scoper2);
374 EXPECT_TRUE(scoper3);
376 EXPECT_EQ(0, constructed);
379 TEST(ScopedPtrTest, PassBehavior) {
380 int constructed = 0;
382 ConDecLogger* logger = new ConDecLogger(&constructed);
383 scoped_ptr<ConDecLogger> scoper(logger);
384 EXPECT_EQ(1, constructed);
386 // Test Pass() with constructor;
387 scoped_ptr<ConDecLogger> scoper2(scoper.Pass());
388 EXPECT_EQ(1, constructed);
390 // Test Pass() with assignment;
391 scoped_ptr<ConDecLogger> scoper3;
392 scoper3 = scoper2.Pass();
393 EXPECT_EQ(1, constructed);
394 EXPECT_FALSE(scoper.get());
395 EXPECT_FALSE(scoper2.get());
396 EXPECT_TRUE(scoper3.get());
399 // Test uncaught Pass() does not have side effects.
401 ConDecLogger* logger = new ConDecLogger(&constructed);
402 scoped_ptr<ConDecLogger> scoper(logger);
403 EXPECT_EQ(1, constructed);
405 // Should auto-destruct logger by end of scope.
406 scoped_ptr<ConDecLogger>&& rvalue = scoper.Pass();
407 // The Pass() function mimics std::move(), which does not have side-effects.
408 EXPECT_TRUE(scoper.get());
409 EXPECT_TRUE(rvalue);
411 EXPECT_EQ(0, constructed);
413 // Test that passing to function which does nothing does not leak.
415 ConDecLogger* logger = new ConDecLogger(&constructed);
416 scoped_ptr<ConDecLogger> scoper(logger);
417 EXPECT_EQ(1, constructed);
419 // Should auto-destruct logger by end of scope.
420 GrabAndDrop(scoper.Pass());
421 EXPECT_FALSE(scoper.get());
423 EXPECT_EQ(0, constructed);
426 TEST(ScopedPtrTest, ReturnTypeBehavior) {
427 int constructed = 0;
429 // Test that we can return a scoped_ptr.
431 ConDecLogger* logger = new ConDecLogger(&constructed);
432 scoped_ptr<ConDecLogger> scoper(logger);
433 EXPECT_EQ(1, constructed);
435 PassThru(scoper.Pass());
436 EXPECT_FALSE(scoper.get());
438 EXPECT_EQ(0, constructed);
440 // Test uncaught return type not leak.
442 ConDecLogger* logger = new ConDecLogger(&constructed);
443 scoped_ptr<ConDecLogger> scoper(logger);
444 EXPECT_EQ(1, constructed);
446 // Should auto-destruct logger by end of scope.
447 PassThru(scoper.Pass());
448 EXPECT_FALSE(scoper.get());
450 EXPECT_EQ(0, constructed);
452 // Call TestReturnOfType() so the compiler doesn't warn for an unused
453 // function.
455 TestReturnOfType(&constructed);
457 EXPECT_EQ(0, constructed);
460 TEST(ScopedPtrTest, CustomDeleter) {
461 double dummy_value; // Custom deleter never touches this value.
462 int deletes = 0;
463 int alternate_deletes = 0;
465 // Normal delete support.
467 deletes = 0;
468 scoped_ptr<double, CountingDeleter> scoper(&dummy_value,
469 CountingDeleter(&deletes));
470 EXPECT_EQ(0, deletes);
471 EXPECT_TRUE(scoper.get());
473 EXPECT_EQ(1, deletes);
475 // Test reset() and release().
476 deletes = 0;
478 scoped_ptr<double, CountingDeleter> scoper(NULL,
479 CountingDeleter(&deletes));
480 EXPECT_FALSE(scoper.get());
481 EXPECT_FALSE(scoper.release());
482 EXPECT_FALSE(scoper.get());
483 scoper.reset();
484 EXPECT_FALSE(scoper.get());
485 EXPECT_EQ(0, deletes);
487 scoper.reset(&dummy_value);
488 scoper.reset();
489 EXPECT_EQ(1, deletes);
491 scoper.reset(&dummy_value);
492 EXPECT_EQ(&dummy_value, scoper.release());
494 EXPECT_EQ(1, deletes);
496 // Test get_deleter().
497 deletes = 0;
498 alternate_deletes = 0;
500 scoped_ptr<double, CountingDeleter> scoper(&dummy_value,
501 CountingDeleter(&deletes));
502 // Call deleter manually.
503 EXPECT_EQ(0, deletes);
504 scoper.get_deleter()(&dummy_value);
505 EXPECT_EQ(1, deletes);
507 // Deleter is still there after reset.
508 scoper.reset();
509 EXPECT_EQ(2, deletes);
510 scoper.get_deleter()(&dummy_value);
511 EXPECT_EQ(3, deletes);
513 // Deleter can be assigned into (matches C++11 unique_ptr<> spec).
514 scoper.get_deleter() = CountingDeleter(&alternate_deletes);
515 scoper.reset(&dummy_value);
516 EXPECT_EQ(0, alternate_deletes);
519 EXPECT_EQ(3, deletes);
520 EXPECT_EQ(1, alternate_deletes);
522 // Test operator= deleter support.
523 deletes = 0;
524 alternate_deletes = 0;
526 double dummy_value2;
527 scoped_ptr<double, CountingDeleter> scoper(&dummy_value,
528 CountingDeleter(&deletes));
529 scoped_ptr<double, CountingDeleter> scoper2(
530 &dummy_value2,
531 CountingDeleter(&alternate_deletes));
532 EXPECT_EQ(0, deletes);
533 EXPECT_EQ(0, alternate_deletes);
535 // Pass the second deleter through a constructor and an operator=. Then
536 // reinitialize the empty scopers to ensure that each one is deleting
537 // properly.
538 scoped_ptr<double, CountingDeleter> scoper3(scoper2.Pass());
539 scoper = scoper3.Pass();
540 EXPECT_EQ(1, deletes);
542 scoper2.reset(&dummy_value2);
543 scoper3.reset(&dummy_value2);
544 EXPECT_EQ(0, alternate_deletes);
547 EXPECT_EQ(1, deletes);
548 EXPECT_EQ(3, alternate_deletes);
550 // Test swap(), ==, !=, and type-safe Boolean.
552 scoped_ptr<double, CountingDeleter> scoper1(NULL,
553 CountingDeleter(&deletes));
554 scoped_ptr<double, CountingDeleter> scoper2(NULL,
555 CountingDeleter(&deletes));
556 EXPECT_TRUE(scoper1 == scoper2.get());
557 EXPECT_FALSE(scoper1 != scoper2.get());
559 scoper1.reset(&dummy_value);
560 EXPECT_TRUE(scoper1);
561 EXPECT_EQ(&dummy_value, scoper1.get());
562 EXPECT_FALSE(scoper2);
563 EXPECT_FALSE(scoper2.get());
564 EXPECT_FALSE(scoper1 == scoper2.get());
565 EXPECT_TRUE(scoper1 != scoper2.get());
567 scoper2.swap(scoper1);
568 EXPECT_EQ(&dummy_value, scoper2.get());
569 EXPECT_FALSE(scoper1.get());
570 EXPECT_FALSE(scoper1 == scoper2.get());
571 EXPECT_TRUE(scoper1 != scoper2.get());
575 // Sanity check test for overloaded new and delete operators. Does not do full
576 // coverage of reset/release/Pass() operations as that is redundant with the
577 // above.
578 TEST(ScopedPtrTest, OverloadedNewAndDelete) {
580 OverloadedNewAndDelete::ResetCounters();
581 scoped_ptr<OverloadedNewAndDelete> scoper(new OverloadedNewAndDelete());
582 EXPECT_TRUE(scoper.get());
584 scoped_ptr<OverloadedNewAndDelete> scoper2(scoper.Pass());
586 EXPECT_EQ(1, OverloadedNewAndDelete::delete_count());
587 EXPECT_EQ(1, OverloadedNewAndDelete::new_count());
590 scoped_ptr<int> NullIntReturn() {
591 return nullptr;
594 TEST(ScopedPtrTest, Nullptr) {
595 scoped_ptr<int> scoper1(nullptr);
596 scoped_ptr<int> scoper2(new int);
597 scoper2 = nullptr;
598 scoped_ptr<int> scoper3(NullIntReturn());
599 scoped_ptr<int> scoper4 = NullIntReturn();
600 EXPECT_EQ(nullptr, scoper1.get());
601 EXPECT_EQ(nullptr, scoper2.get());
602 EXPECT_EQ(nullptr, scoper3.get());
603 EXPECT_EQ(nullptr, scoper4.get());
606 scoped_ptr<int[]> NullIntArrayReturn() {
607 return nullptr;
610 TEST(ScopedPtrTest, NullptrArray) {
611 scoped_ptr<int[]> scoper1(nullptr);
612 scoped_ptr<int[]> scoper2(new int[3]);
613 scoper2 = nullptr;
614 scoped_ptr<int[]> scoper3(NullIntArrayReturn());
615 scoped_ptr<int[]> scoper4 = NullIntArrayReturn();
616 EXPECT_EQ(nullptr, scoper1.get());
617 EXPECT_EQ(nullptr, scoper2.get());
618 EXPECT_EQ(nullptr, scoper3.get());
619 EXPECT_EQ(nullptr, scoper4.get());
622 class Super {};
623 class Sub : public Super {};
625 scoped_ptr<Sub> SubClassReturn() {
626 return make_scoped_ptr(new Sub);
629 TEST(ScopedPtrTest, Conversion) {
630 scoped_ptr<Sub> sub1(new Sub);
631 scoped_ptr<Sub> sub2(new Sub);
633 // Upcast with Pass() works.
634 scoped_ptr<Super> super1 = sub1.Pass();
635 super1 = sub2.Pass();
637 // Upcast with an rvalue works.
638 scoped_ptr<Super> super2 = SubClassReturn();
639 super2 = SubClassReturn();
642 // Android death tests don't work properly with assert(). Yay.
643 #if !defined(NDEBUG) && defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID)
644 TEST(ScopedPtrTest, SelfResetAbortsWithDefaultDeleter) {
645 scoped_ptr<int> x(new int);
646 EXPECT_DEATH(x.reset(x.get()), "");
649 TEST(ScopedPtrTest, SelfResetAbortsWithDefaultArrayDeleter) {
650 scoped_ptr<int[]> y(new int[4]);
651 EXPECT_DEATH(y.reset(y.get()), "");
654 TEST(ScopedPtrTest, SelfResetAbortsWithDefaultFreeDeleter) {
655 scoped_ptr<int, base::FreeDeleter> z(static_cast<int*>(malloc(sizeof(int))));
656 EXPECT_DEATH(z.reset(z.get()), "");
659 // A custom deleter that doesn't opt out should still crash.
660 TEST(ScopedPtrTest, SelfResetAbortsWithCustomDeleter) {
661 struct CustomDeleter {
662 inline void operator()(int* x) { delete x; }
664 scoped_ptr<int, CustomDeleter> x(new int);
665 EXPECT_DEATH(x.reset(x.get()), "");
667 #endif
669 TEST(ScopedPtrTest, SelfResetWithCustomDeleterOptOut) {
670 // A custom deleter should be able to opt out of self-reset abort behavior.
671 struct NoOpDeleter {
672 #if !defined(NDEBUG)
673 typedef void AllowSelfReset;
674 #endif
675 inline void operator()(int*) {}
677 scoped_ptr<int> owner(new int);
678 scoped_ptr<int, NoOpDeleter> x(owner.get());
679 x.reset(x.get());