Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / base / memory / scoped_ptr_unittest.cc
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 "base/basictypes.h"
8 #include "base/bind.h"
9 #include "base/callback.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11
12 namespace {
13
14 // Used to test depth subtyping.
15 class ConDecLoggerParent {
16  public:
17   virtual ~ConDecLoggerParent() {}
18
19   virtual void SetPtr(int* ptr) = 0;
20
21   virtual int SomeMeth(int x) const = 0;
22 };
23
24 class ConDecLogger : public ConDecLoggerParent {
25  public:
26   ConDecLogger() : ptr_(NULL) { }
27   explicit ConDecLogger(int* ptr) { SetPtr(ptr); }
28   ~ConDecLogger() override { --*ptr_; }
29
30   void SetPtr(int* ptr) override {
31     ptr_ = ptr;
32     ++*ptr_;
33   }
34
35   int SomeMeth(int x) const override { return x; }
36
37  private:
38   int* ptr_;
39
40   DISALLOW_COPY_AND_ASSIGN(ConDecLogger);
41 };
42
43 struct CountingDeleter {
44   explicit CountingDeleter(int* count) : count_(count) {}
45   inline void operator()(double* ptr) const {
46     (*count_)++;
47   }
48   int* count_;
49 };
50
51 // Used to test assignment of convertible deleters.
52 struct CountingDeleterChild : public CountingDeleter {
53   explicit CountingDeleterChild(int* count) : CountingDeleter(count) {}
54 };
55
56 class OverloadedNewAndDelete {
57  public:
58   void* operator new(size_t size) {
59     g_new_count++;
60     return malloc(size);
61   }
62
63   void operator delete(void* ptr) {
64     g_delete_count++;
65     free(ptr);
66   }
67
68   static void ResetCounters() {
69     g_new_count = 0;
70     g_delete_count = 0;
71   }
72
73   static int new_count() { return g_new_count; }
74   static int delete_count() { return g_delete_count; }
75
76  private:
77   static int g_new_count;
78   static int g_delete_count;
79 };
80
81 int OverloadedNewAndDelete::g_new_count = 0;
82 int OverloadedNewAndDelete::g_delete_count = 0;
83
84 scoped_ptr<ConDecLogger> PassThru(scoped_ptr<ConDecLogger> logger) {
85   return logger.Pass();
86 }
87
88 void GrabAndDrop(scoped_ptr<ConDecLogger> logger) {
89 }
90
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));
95 }
96
97 }  // namespace
98
99 TEST(ScopedPtrTest, ScopedPtr) {
100   int constructed = 0;
101
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);
105
106   {
107     scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
108     EXPECT_EQ(1, constructed);
109     EXPECT_TRUE(scoper.get());
110
111     EXPECT_EQ(10, scoper->SomeMeth(10));
112     EXPECT_EQ(10, scoper.get()->SomeMeth(10));
113     EXPECT_EQ(10, (*scoper).SomeMeth(10));
114   }
115   EXPECT_EQ(0, constructed);
116
117   // Test reset() and release()
118   {
119     scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
120     EXPECT_EQ(1, constructed);
121     EXPECT_TRUE(scoper.get());
122
123     scoper.reset(new ConDecLogger(&constructed));
124     EXPECT_EQ(1, constructed);
125     EXPECT_TRUE(scoper.get());
126
127     scoper.reset();
128     EXPECT_EQ(0, constructed);
129     EXPECT_FALSE(scoper.get());
130
131     scoper.reset(new ConDecLogger(&constructed));
132     EXPECT_EQ(1, constructed);
133     EXPECT_TRUE(scoper.get());
134
135     ConDecLogger* take = scoper.release();
136     EXPECT_EQ(1, constructed);
137     EXPECT_FALSE(scoper.get());
138     delete take;
139     EXPECT_EQ(0, constructed);
140
141     scoper.reset(new ConDecLogger(&constructed));
142     EXPECT_EQ(1, constructed);
143     EXPECT_TRUE(scoper.get());
144   }
145   EXPECT_EQ(0, constructed);
146
147   // Test swap(), == and !=
148   {
149     scoped_ptr<ConDecLogger> scoper1;
150     scoped_ptr<ConDecLogger> scoper2;
151     EXPECT_TRUE(scoper1 == scoper2.get());
152     EXPECT_FALSE(scoper1 != scoper2.get());
153
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());
160
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());
166   }
167   EXPECT_EQ(0, constructed);
168 }
169
170 TEST(ScopedPtrTest, ScopedPtrDepthSubtyping) {
171   int constructed = 0;
172
173   // Test construction from a scoped_ptr to a derived class.
174   {
175     scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
176     EXPECT_EQ(1, constructed);
177     EXPECT_TRUE(scoper.get());
178
179     scoped_ptr<ConDecLoggerParent> scoper_parent(scoper.Pass());
180     EXPECT_EQ(1, constructed);
181     EXPECT_TRUE(scoper_parent.get());
182     EXPECT_FALSE(scoper.get());
183
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));
187   }
188   EXPECT_EQ(0, constructed);
189
190   // Test assignment from a scoped_ptr to a derived class.
191   {
192     scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
193     EXPECT_EQ(1, constructed);
194     EXPECT_TRUE(scoper.get());
195
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());
201   }
202   EXPECT_EQ(0, constructed);
203
204   // Test construction of a scoped_ptr with an additional const annotation.
205   {
206     scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
207     EXPECT_EQ(1, constructed);
208     EXPECT_TRUE(scoper.get());
209
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());
214
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));
218   }
219   EXPECT_EQ(0, constructed);
220
221   // Test assignment to a scoped_ptr with an additional const annotation.
222   {
223     scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
224     EXPECT_EQ(1, constructed);
225     EXPECT_TRUE(scoper.get());
226
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());
232   }
233   EXPECT_EQ(0, constructed);
234
235   // Test assignment to a scoped_ptr deleter of parent type.
236   {
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));
245
246     EXPECT_TRUE(scoper);
247     EXPECT_TRUE(scoper_child);
248     EXPECT_EQ(0, deletes);
249     EXPECT_EQ(0, alternate_deletes);
250
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);
257
258     scoper.reset();
259     EXPECT_FALSE(scoper);
260     EXPECT_FALSE(scoper_child);
261     EXPECT_EQ(1, deletes);
262     EXPECT_EQ(1, alternate_deletes);
263
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);
273
274     scoper_construct.reset();
275     EXPECT_EQ(1, deletes);
276     EXPECT_EQ(2, alternate_deletes);
277   }
278 }
279
280 TEST(ScopedPtrTest, ScopedPtrWithArray) {
281   static const int kNumLoggers = 12;
282
283   int constructed = 0;
284
285   {
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);
291     }
292     EXPECT_EQ(12, constructed);
293
294     EXPECT_EQ(10, scoper.get()->SomeMeth(10));
295     EXPECT_EQ(10, scoper[2].SomeMeth(10));
296   }
297   EXPECT_EQ(0, constructed);
298
299   // Test reset() and release()
300   {
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());
307
308     scoper.reset(new ConDecLogger[kNumLoggers]);
309     for (int i = 0; i < kNumLoggers; ++i) {
310       scoper[i].SetPtr(&constructed);
311     }
312     EXPECT_EQ(12, constructed);
313     scoper.reset();
314     EXPECT_EQ(0, constructed);
315
316     scoper.reset(new ConDecLogger[kNumLoggers]);
317     for (int i = 0; i < kNumLoggers; ++i) {
318       scoper[i].SetPtr(&constructed);
319     }
320     EXPECT_EQ(12, constructed);
321     ConDecLogger* ptr = scoper.release();
322     EXPECT_EQ(12, constructed);
323     delete[] ptr;
324     EXPECT_EQ(0, constructed);
325   }
326   EXPECT_EQ(0, constructed);
327
328   // Test swap(), ==, !=, and type-safe Boolean.
329   {
330     scoped_ptr<ConDecLogger[]> scoper1;
331     scoped_ptr<ConDecLogger[]> scoper2;
332     EXPECT_TRUE(scoper1 == scoper2.get());
333     EXPECT_FALSE(scoper1 != scoper2.get());
334
335     ConDecLogger* loggers = new ConDecLogger[kNumLoggers];
336     for (int i = 0; i < kNumLoggers; ++i) {
337       loggers[i].SetPtr(&constructed);
338     }
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());
346
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());
352   }
353   EXPECT_EQ(0, constructed);
354
355   {
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);
361     }
362     EXPECT_EQ(kNumLoggers, constructed);
363
364     // Test Pass() with constructor;
365     scoped_ptr<ConDecLogger[]> scoper2(scoper.Pass());
366     EXPECT_EQ(kNumLoggers, constructed);
367
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);
375   }
376   EXPECT_EQ(0, constructed);
377 }
378
379 TEST(ScopedPtrTest, PassBehavior) {
380   int constructed = 0;
381   {
382     ConDecLogger* logger = new ConDecLogger(&constructed);
383     scoped_ptr<ConDecLogger> scoper(logger);
384     EXPECT_EQ(1, constructed);
385
386     // Test Pass() with constructor;
387     scoped_ptr<ConDecLogger> scoper2(scoper.Pass());
388     EXPECT_EQ(1, constructed);
389
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());
397   }
398
399   // Test uncaught Pass() does not have side effects.
400   {
401     ConDecLogger* logger = new ConDecLogger(&constructed);
402     scoped_ptr<ConDecLogger> scoper(logger);
403     EXPECT_EQ(1, constructed);
404
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);
410   }
411   EXPECT_EQ(0, constructed);
412
413   // Test that passing to function which does nothing does not leak.
414   {
415     ConDecLogger* logger = new ConDecLogger(&constructed);
416     scoped_ptr<ConDecLogger> scoper(logger);
417     EXPECT_EQ(1, constructed);
418
419     // Should auto-destruct logger by end of scope.
420     GrabAndDrop(scoper.Pass());
421     EXPECT_FALSE(scoper.get());
422   }
423   EXPECT_EQ(0, constructed);
424 }
425
426 TEST(ScopedPtrTest, ReturnTypeBehavior) {
427   int constructed = 0;
428
429   // Test that we can return a scoped_ptr.
430   {
431     ConDecLogger* logger = new ConDecLogger(&constructed);
432     scoped_ptr<ConDecLogger> scoper(logger);
433     EXPECT_EQ(1, constructed);
434
435     PassThru(scoper.Pass());
436     EXPECT_FALSE(scoper.get());
437   }
438   EXPECT_EQ(0, constructed);
439
440   // Test uncaught return type not leak.
441   {
442     ConDecLogger* logger = new ConDecLogger(&constructed);
443     scoped_ptr<ConDecLogger> scoper(logger);
444     EXPECT_EQ(1, constructed);
445
446     // Should auto-destruct logger by end of scope.
447     PassThru(scoper.Pass());
448     EXPECT_FALSE(scoper.get());
449   }
450   EXPECT_EQ(0, constructed);
451
452   // Call TestReturnOfType() so the compiler doesn't warn for an unused
453   // function.
454   {
455     TestReturnOfType(&constructed);
456   }
457   EXPECT_EQ(0, constructed);
458 }
459
460 TEST(ScopedPtrTest, CustomDeleter) {
461   double dummy_value;  // Custom deleter never touches this value.
462   int deletes = 0;
463   int alternate_deletes = 0;
464
465   // Normal delete support.
466   {
467     deletes = 0;
468     scoped_ptr<double, CountingDeleter> scoper(&dummy_value,
469                                                CountingDeleter(&deletes));
470     EXPECT_EQ(0, deletes);
471     EXPECT_TRUE(scoper.get());
472   }
473   EXPECT_EQ(1, deletes);
474
475   // Test reset() and release().
476   deletes = 0;
477   {
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);
486
487     scoper.reset(&dummy_value);
488     scoper.reset();
489     EXPECT_EQ(1, deletes);
490
491     scoper.reset(&dummy_value);
492     EXPECT_EQ(&dummy_value, scoper.release());
493   }
494   EXPECT_EQ(1, deletes);
495
496   // Test get_deleter().
497   deletes = 0;
498   alternate_deletes = 0;
499   {
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);
506
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);
512
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);
517
518   }
519   EXPECT_EQ(3, deletes);
520   EXPECT_EQ(1, alternate_deletes);
521
522   // Test operator= deleter support.
523   deletes = 0;
524   alternate_deletes = 0;
525   {
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);
534
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);
541
542     scoper2.reset(&dummy_value2);
543     scoper3.reset(&dummy_value2);
544     EXPECT_EQ(0, alternate_deletes);
545
546   }
547   EXPECT_EQ(1, deletes);
548   EXPECT_EQ(3, alternate_deletes);
549
550   // Test swap(), ==, !=, and type-safe Boolean.
551   {
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());
558
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());
566
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());
572   }
573 }
574
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) {
579   {
580     OverloadedNewAndDelete::ResetCounters();
581     scoped_ptr<OverloadedNewAndDelete> scoper(new OverloadedNewAndDelete());
582     EXPECT_TRUE(scoper.get());
583
584     scoped_ptr<OverloadedNewAndDelete> scoper2(scoper.Pass());
585   }
586   EXPECT_EQ(1, OverloadedNewAndDelete::delete_count());
587   EXPECT_EQ(1, OverloadedNewAndDelete::new_count());
588 }
589
590 scoped_ptr<int> NullIntReturn() {
591   return nullptr;
592 }
593
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());
604 }
605
606 scoped_ptr<int[]> NullIntArrayReturn() {
607   return nullptr;
608 }
609
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());
620 }
621
622 class Super {};
623 class Sub : public Super {};
624
625 scoped_ptr<Sub> SubClassReturn() {
626   return make_scoped_ptr(new Sub);
627 }
628
629 TEST(ScopedPtrTest, Conversion) {
630   scoped_ptr<Sub> sub1(new Sub);
631   scoped_ptr<Sub> sub2(new Sub);
632
633   // Upcast with Pass() works.
634   scoped_ptr<Super> super1 = sub1.Pass();
635   super1 = sub2.Pass();
636
637   // Upcast with an rvalue works.
638   scoped_ptr<Super> super2 = SubClassReturn();
639   super2 = SubClassReturn();
640 }
641
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()), "");
647 }
648
649 TEST(ScopedPtrTest, SelfResetAbortsWithDefaultArrayDeleter) {
650   scoped_ptr<int[]> y(new int[4]);
651   EXPECT_DEATH(y.reset(y.get()), "");
652 }
653
654 TEST(ScopedPtrTest, SelfResetAbortsWithDefaultFreeDeleter) {
655   scoped_ptr<int, base::FreeDeleter> z(static_cast<int*>(malloc(sizeof(int))));
656   EXPECT_DEATH(z.reset(z.get()), "");
657 }
658
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; }
663   };
664   scoped_ptr<int, CustomDeleter> x(new int);
665   EXPECT_DEATH(x.reset(x.get()), "");
666 }
667 #endif
668
669 TEST(ScopedPtrTest, SelfResetWithCustomDeleterOptOut) {
670   // A custom deleter should be able to opt out of self-reset abort behavior.
671   struct NoOpDeleter {
672     typedef void AllowSelfReset;
673     inline void operator()(int*) {}
674   };
675   scoped_ptr<int> owner(new int);
676   scoped_ptr<int, NoOpDeleter> x(owner.get());
677   x.reset(x.get());
678 }