- add sources.
[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   virtual ~ConDecLogger() { --*ptr_; }
29
30   virtual void SetPtr(int* ptr) OVERRIDE { ptr_ = ptr; ++*ptr_; }
31
32   virtual int SomeMeth(int x) const OVERRIDE { return x; }
33
34  private:
35   int* ptr_;
36
37   DISALLOW_COPY_AND_ASSIGN(ConDecLogger);
38 };
39
40 struct CountingDeleter {
41   explicit CountingDeleter(int* count) : count_(count) {}
42   inline void operator()(double* ptr) const {
43     (*count_)++;
44   }
45   int* count_;
46 };
47
48 // Used to test assignment of convertible deleters.
49 struct CountingDeleterChild : public CountingDeleter {
50   explicit CountingDeleterChild(int* count) : CountingDeleter(count) {}
51 };
52
53 class OverloadedNewAndDelete {
54  public:
55   void* operator new(size_t size) {
56     g_new_count++;
57     return malloc(size);
58   }
59
60   void operator delete(void* ptr) {
61     g_delete_count++;
62     free(ptr);
63   }
64
65   static void ResetCounters() {
66     g_new_count = 0;
67     g_delete_count = 0;
68   }
69
70   static int new_count() { return g_new_count; }
71   static int delete_count() { return g_delete_count; }
72
73  private:
74   static int g_new_count;
75   static int g_delete_count;
76 };
77
78 int OverloadedNewAndDelete::g_new_count = 0;
79 int OverloadedNewAndDelete::g_delete_count = 0;
80
81 scoped_ptr<ConDecLogger> PassThru(scoped_ptr<ConDecLogger> logger) {
82   return logger.Pass();
83 }
84
85 void GrabAndDrop(scoped_ptr<ConDecLogger> logger) {
86 }
87
88 // Do not delete this function!  It's existence is to test that you can
89 // return a temporarily constructed version of the scoper.
90 scoped_ptr<ConDecLogger> TestReturnOfType(int* constructed) {
91   return scoped_ptr<ConDecLogger>(new ConDecLogger(constructed));
92 }
93
94 scoped_ptr<ConDecLoggerParent> UpcastUsingPassAs(
95     scoped_ptr<ConDecLogger> object) {
96   return object.PassAs<ConDecLoggerParent>();
97 }
98
99 }  // namespace
100
101 TEST(ScopedPtrTest, ScopedPtr) {
102   int constructed = 0;
103
104   // Ensure size of scoped_ptr<> doesn't increase unexpectedly.
105   COMPILE_ASSERT(sizeof(int*) >= sizeof(scoped_ptr<int>),
106                  scoped_ptr_larger_than_raw_ptr);
107
108   {
109     scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
110     EXPECT_EQ(1, constructed);
111     EXPECT_TRUE(scoper.get());
112
113     EXPECT_EQ(10, scoper->SomeMeth(10));
114     EXPECT_EQ(10, scoper.get()->SomeMeth(10));
115     EXPECT_EQ(10, (*scoper).SomeMeth(10));
116   }
117   EXPECT_EQ(0, constructed);
118
119   // Test reset() and release()
120   {
121     scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
122     EXPECT_EQ(1, constructed);
123     EXPECT_TRUE(scoper.get());
124
125     scoper.reset(new ConDecLogger(&constructed));
126     EXPECT_EQ(1, constructed);
127     EXPECT_TRUE(scoper.get());
128
129     scoper.reset();
130     EXPECT_EQ(0, constructed);
131     EXPECT_FALSE(scoper.get());
132
133     scoper.reset(new ConDecLogger(&constructed));
134     EXPECT_EQ(1, constructed);
135     EXPECT_TRUE(scoper.get());
136
137     ConDecLogger* take = scoper.release();
138     EXPECT_EQ(1, constructed);
139     EXPECT_FALSE(scoper.get());
140     delete take;
141     EXPECT_EQ(0, constructed);
142
143     scoper.reset(new ConDecLogger(&constructed));
144     EXPECT_EQ(1, constructed);
145     EXPECT_TRUE(scoper.get());
146   }
147   EXPECT_EQ(0, constructed);
148
149   // Test swap(), == and !=
150   {
151     scoped_ptr<ConDecLogger> scoper1;
152     scoped_ptr<ConDecLogger> scoper2;
153     EXPECT_TRUE(scoper1 == scoper2.get());
154     EXPECT_FALSE(scoper1 != scoper2.get());
155
156     ConDecLogger* logger = new ConDecLogger(&constructed);
157     scoper1.reset(logger);
158     EXPECT_EQ(logger, scoper1.get());
159     EXPECT_FALSE(scoper2.get());
160     EXPECT_FALSE(scoper1 == scoper2.get());
161     EXPECT_TRUE(scoper1 != scoper2.get());
162
163     scoper2.swap(scoper1);
164     EXPECT_EQ(logger, scoper2.get());
165     EXPECT_FALSE(scoper1.get());
166     EXPECT_FALSE(scoper1 == scoper2.get());
167     EXPECT_TRUE(scoper1 != scoper2.get());
168   }
169   EXPECT_EQ(0, constructed);
170 }
171
172 TEST(ScopedPtrTest, ScopedPtrDepthSubtyping) {
173   int constructed = 0;
174
175   // Test construction from a scoped_ptr to a derived class.
176   {
177     scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
178     EXPECT_EQ(1, constructed);
179     EXPECT_TRUE(scoper.get());
180
181     scoped_ptr<ConDecLoggerParent> scoper_parent(scoper.Pass());
182     EXPECT_EQ(1, constructed);
183     EXPECT_TRUE(scoper_parent.get());
184     EXPECT_FALSE(scoper.get());
185
186     EXPECT_EQ(10, scoper_parent->SomeMeth(10));
187     EXPECT_EQ(10, scoper_parent.get()->SomeMeth(10));
188     EXPECT_EQ(10, (*scoper_parent).SomeMeth(10));
189   }
190   EXPECT_EQ(0, constructed);
191
192   // Test assignment from a scoped_ptr to a derived class.
193   {
194     scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
195     EXPECT_EQ(1, constructed);
196     EXPECT_TRUE(scoper.get());
197
198     scoped_ptr<ConDecLoggerParent> scoper_parent;
199     scoper_parent = scoper.Pass();
200     EXPECT_EQ(1, constructed);
201     EXPECT_TRUE(scoper_parent.get());
202     EXPECT_FALSE(scoper.get());
203   }
204   EXPECT_EQ(0, constructed);
205
206   // Test construction of a scoped_ptr with an additional const annotation.
207   {
208     scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
209     EXPECT_EQ(1, constructed);
210     EXPECT_TRUE(scoper.get());
211
212     scoped_ptr<const ConDecLogger> scoper_const(scoper.Pass());
213     EXPECT_EQ(1, constructed);
214     EXPECT_TRUE(scoper_const.get());
215     EXPECT_FALSE(scoper.get());
216
217     EXPECT_EQ(10, scoper_const->SomeMeth(10));
218     EXPECT_EQ(10, scoper_const.get()->SomeMeth(10));
219     EXPECT_EQ(10, (*scoper_const).SomeMeth(10));
220   }
221   EXPECT_EQ(0, constructed);
222
223   // Test assignment to a scoped_ptr with an additional const annotation.
224   {
225     scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
226     EXPECT_EQ(1, constructed);
227     EXPECT_TRUE(scoper.get());
228
229     scoped_ptr<const ConDecLogger> scoper_const;
230     scoper_const = scoper.Pass();
231     EXPECT_EQ(1, constructed);
232     EXPECT_TRUE(scoper_const.get());
233     EXPECT_FALSE(scoper.get());
234   }
235   EXPECT_EQ(0, constructed);
236
237   // Test assignment to a scoped_ptr deleter of parent type.
238   {
239     // Custom deleters never touch these value.
240     double dummy_value, dummy_value2;
241     int deletes = 0;
242     int alternate_deletes = 0;
243     scoped_ptr<double, CountingDeleter> scoper(&dummy_value,
244                                                CountingDeleter(&deletes));
245     scoped_ptr<double, CountingDeleterChild> scoper_child(
246         &dummy_value2, CountingDeleterChild(&alternate_deletes));
247
248     EXPECT_TRUE(scoper);
249     EXPECT_TRUE(scoper_child);
250     EXPECT_EQ(0, deletes);
251     EXPECT_EQ(0, alternate_deletes);
252
253     // Test this compiles and correctly overwrites the deleter state.
254     scoper = scoper_child.Pass();
255     EXPECT_TRUE(scoper);
256     EXPECT_FALSE(scoper_child);
257     EXPECT_EQ(1, deletes);
258     EXPECT_EQ(0, alternate_deletes);
259
260     scoper.reset();
261     EXPECT_FALSE(scoper);
262     EXPECT_FALSE(scoper_child);
263     EXPECT_EQ(1, deletes);
264     EXPECT_EQ(1, alternate_deletes);
265
266     scoper_child.reset(&dummy_value);
267     EXPECT_TRUE(scoper_child);
268     EXPECT_EQ(1, deletes);
269     EXPECT_EQ(1, alternate_deletes);
270     scoped_ptr<double, CountingDeleter> scoper_construct(scoper_child.Pass());
271     EXPECT_TRUE(scoper_construct);
272     EXPECT_FALSE(scoper_child);
273     EXPECT_EQ(1, deletes);
274     EXPECT_EQ(1, alternate_deletes);
275
276     scoper_construct.reset();
277     EXPECT_EQ(1, deletes);
278     EXPECT_EQ(2, alternate_deletes);
279   }
280 }
281
282 TEST(ScopedPtrTest, ScopedPtrWithArray) {
283   static const int kNumLoggers = 12;
284
285   int constructed = 0;
286
287   {
288     scoped_ptr<ConDecLogger[]> scoper(new ConDecLogger[kNumLoggers]);
289     EXPECT_TRUE(scoper);
290     EXPECT_EQ(&scoper[0], scoper.get());
291     for (int i = 0; i < kNumLoggers; ++i) {
292       scoper[i].SetPtr(&constructed);
293     }
294     EXPECT_EQ(12, constructed);
295
296     EXPECT_EQ(10, scoper.get()->SomeMeth(10));
297     EXPECT_EQ(10, scoper[2].SomeMeth(10));
298   }
299   EXPECT_EQ(0, constructed);
300
301   // Test reset() and release()
302   {
303     scoped_ptr<ConDecLogger[]> scoper;
304     EXPECT_FALSE(scoper.get());
305     EXPECT_FALSE(scoper.release());
306     EXPECT_FALSE(scoper.get());
307     scoper.reset();
308     EXPECT_FALSE(scoper.get());
309
310     scoper.reset(new ConDecLogger[kNumLoggers]);
311     for (int i = 0; i < kNumLoggers; ++i) {
312       scoper[i].SetPtr(&constructed);
313     }
314     EXPECT_EQ(12, constructed);
315     scoper.reset();
316     EXPECT_EQ(0, constructed);
317
318     scoper.reset(new ConDecLogger[kNumLoggers]);
319     for (int i = 0; i < kNumLoggers; ++i) {
320       scoper[i].SetPtr(&constructed);
321     }
322     EXPECT_EQ(12, constructed);
323     ConDecLogger* ptr = scoper.release();
324     EXPECT_EQ(12, constructed);
325     delete[] ptr;
326     EXPECT_EQ(0, constructed);
327   }
328   EXPECT_EQ(0, constructed);
329
330   // Test swap(), ==, !=, and type-safe Boolean.
331   {
332     scoped_ptr<ConDecLogger[]> scoper1;
333     scoped_ptr<ConDecLogger[]> scoper2;
334     EXPECT_TRUE(scoper1 == scoper2.get());
335     EXPECT_FALSE(scoper1 != scoper2.get());
336
337     ConDecLogger* loggers = new ConDecLogger[kNumLoggers];
338     for (int i = 0; i < kNumLoggers; ++i) {
339       loggers[i].SetPtr(&constructed);
340     }
341     scoper1.reset(loggers);
342     EXPECT_TRUE(scoper1);
343     EXPECT_EQ(loggers, scoper1.get());
344     EXPECT_FALSE(scoper2);
345     EXPECT_FALSE(scoper2.get());
346     EXPECT_FALSE(scoper1 == scoper2.get());
347     EXPECT_TRUE(scoper1 != scoper2.get());
348
349     scoper2.swap(scoper1);
350     EXPECT_EQ(loggers, scoper2.get());
351     EXPECT_FALSE(scoper1.get());
352     EXPECT_FALSE(scoper1 == scoper2.get());
353     EXPECT_TRUE(scoper1 != scoper2.get());
354   }
355   EXPECT_EQ(0, constructed);
356
357   {
358     ConDecLogger* loggers = new ConDecLogger[kNumLoggers];
359     scoped_ptr<ConDecLogger[]> scoper(loggers);
360     EXPECT_TRUE(scoper);
361     for (int i = 0; i < kNumLoggers; ++i) {
362       scoper[i].SetPtr(&constructed);
363     }
364     EXPECT_EQ(kNumLoggers, constructed);
365
366     // Test Pass() with constructor;
367     scoped_ptr<ConDecLogger[]> scoper2(scoper.Pass());
368     EXPECT_EQ(kNumLoggers, constructed);
369
370     // Test Pass() with assignment;
371     scoped_ptr<ConDecLogger[]> scoper3;
372     scoper3 = scoper2.Pass();
373     EXPECT_EQ(kNumLoggers, constructed);
374     EXPECT_FALSE(scoper);
375     EXPECT_FALSE(scoper2);
376     EXPECT_TRUE(scoper3);
377   }
378   EXPECT_EQ(0, constructed);
379 }
380
381 TEST(ScopedPtrTest, PassBehavior) {
382   int constructed = 0;
383   {
384     ConDecLogger* logger = new ConDecLogger(&constructed);
385     scoped_ptr<ConDecLogger> scoper(logger);
386     EXPECT_EQ(1, constructed);
387
388     // Test Pass() with constructor;
389     scoped_ptr<ConDecLogger> scoper2(scoper.Pass());
390     EXPECT_EQ(1, constructed);
391
392     // Test Pass() with assignment;
393     scoped_ptr<ConDecLogger> scoper3;
394     scoper3 = scoper2.Pass();
395     EXPECT_EQ(1, constructed);
396     EXPECT_FALSE(scoper.get());
397     EXPECT_FALSE(scoper2.get());
398     EXPECT_TRUE(scoper3.get());
399   }
400
401   // Test uncaught Pass() does not leak.
402   {
403     ConDecLogger* logger = new ConDecLogger(&constructed);
404     scoped_ptr<ConDecLogger> scoper(logger);
405     EXPECT_EQ(1, constructed);
406
407     // Should auto-destruct logger by end of scope.
408     scoper.Pass();
409     EXPECT_FALSE(scoper.get());
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, PassAs) {
461   int constructed = 0;
462   {
463     scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
464     EXPECT_EQ(1, constructed);
465     EXPECT_TRUE(scoper.get());
466
467     scoped_ptr<ConDecLoggerParent> scoper_parent;
468     scoper_parent = UpcastUsingPassAs(scoper.Pass());
469     EXPECT_EQ(1, constructed);
470     EXPECT_TRUE(scoper_parent.get());
471     EXPECT_FALSE(scoper.get());
472   }
473   EXPECT_EQ(0, constructed);
474 }
475
476 TEST(ScopedPtrTest, CustomDeleter) {
477   double dummy_value;  // Custom deleter never touches this value.
478   int deletes = 0;
479   int alternate_deletes = 0;
480
481   // Normal delete support.
482   {
483     deletes = 0;
484     scoped_ptr<double, CountingDeleter> scoper(&dummy_value,
485                                                CountingDeleter(&deletes));
486     EXPECT_EQ(0, deletes);
487     EXPECT_TRUE(scoper.get());
488   }
489   EXPECT_EQ(1, deletes);
490
491   // Test reset() and release().
492   deletes = 0;
493   {
494     scoped_ptr<double, CountingDeleter> scoper(NULL,
495                                                CountingDeleter(&deletes));
496     EXPECT_FALSE(scoper.get());
497     EXPECT_FALSE(scoper.release());
498     EXPECT_FALSE(scoper.get());
499     scoper.reset();
500     EXPECT_FALSE(scoper.get());
501     EXPECT_EQ(0, deletes);
502
503     scoper.reset(&dummy_value);
504     scoper.reset();
505     EXPECT_EQ(1, deletes);
506
507     scoper.reset(&dummy_value);
508     EXPECT_EQ(&dummy_value, scoper.release());
509   }
510   EXPECT_EQ(1, deletes);
511
512   // Test get_deleter().
513   deletes = 0;
514   alternate_deletes = 0;
515   {
516     scoped_ptr<double, CountingDeleter> scoper(&dummy_value,
517                                                CountingDeleter(&deletes));
518     // Call deleter manually.
519     EXPECT_EQ(0, deletes);
520     scoper.get_deleter()(&dummy_value);
521     EXPECT_EQ(1, deletes);
522
523     // Deleter is still there after reset.
524     scoper.reset();
525     EXPECT_EQ(2, deletes);
526     scoper.get_deleter()(&dummy_value);
527     EXPECT_EQ(3, deletes);
528
529     // Deleter can be assigned into (matches C++11 unique_ptr<> spec).
530     scoper.get_deleter() = CountingDeleter(&alternate_deletes);
531     scoper.reset(&dummy_value);
532     EXPECT_EQ(0, alternate_deletes);
533
534   }
535   EXPECT_EQ(3, deletes);
536   EXPECT_EQ(1, alternate_deletes);
537
538   // Test operator= deleter support.
539   deletes = 0;
540   alternate_deletes = 0;
541   {
542     double dummy_value2;
543     scoped_ptr<double, CountingDeleter> scoper(&dummy_value,
544                                                CountingDeleter(&deletes));
545     scoped_ptr<double, CountingDeleter> scoper2(
546         &dummy_value2,
547         CountingDeleter(&alternate_deletes));
548     EXPECT_EQ(0, deletes);
549     EXPECT_EQ(0, alternate_deletes);
550
551     // Pass the second deleter through a constructor and an operator=. Then
552     // reinitialize the empty scopers to ensure that each one is deleting
553     // properly.
554     scoped_ptr<double, CountingDeleter> scoper3(scoper2.Pass());
555     scoper = scoper3.Pass();
556     EXPECT_EQ(1, deletes);
557
558     scoper2.reset(&dummy_value2);
559     scoper3.reset(&dummy_value2);
560     EXPECT_EQ(0, alternate_deletes);
561
562   }
563   EXPECT_EQ(1, deletes);
564   EXPECT_EQ(3, alternate_deletes);
565
566   // Test swap(), ==, !=, and type-safe Boolean.
567   {
568     scoped_ptr<double, CountingDeleter> scoper1(NULL,
569                                                 CountingDeleter(&deletes));
570     scoped_ptr<double, CountingDeleter> scoper2(NULL,
571                                                 CountingDeleter(&deletes));
572     EXPECT_TRUE(scoper1 == scoper2.get());
573     EXPECT_FALSE(scoper1 != scoper2.get());
574
575     scoper1.reset(&dummy_value);
576     EXPECT_TRUE(scoper1);
577     EXPECT_EQ(&dummy_value, scoper1.get());
578     EXPECT_FALSE(scoper2);
579     EXPECT_FALSE(scoper2.get());
580     EXPECT_FALSE(scoper1 == scoper2.get());
581     EXPECT_TRUE(scoper1 != scoper2.get());
582
583     scoper2.swap(scoper1);
584     EXPECT_EQ(&dummy_value, scoper2.get());
585     EXPECT_FALSE(scoper1.get());
586     EXPECT_FALSE(scoper1 == scoper2.get());
587     EXPECT_TRUE(scoper1 != scoper2.get());
588   }
589 }
590
591 // Sanity check test for overloaded new and delete operators. Does not do full
592 // coverage of reset/release/Pass() operations as that is redundant with the
593 // above.
594 TEST(ScopedPtrTest, OverloadedNewAndDelete) {
595   {
596     OverloadedNewAndDelete::ResetCounters();
597     scoped_ptr<OverloadedNewAndDelete> scoper(new OverloadedNewAndDelete());
598     EXPECT_TRUE(scoper.get());
599
600     scoped_ptr<OverloadedNewAndDelete> scoper2(scoper.Pass());
601   }
602   EXPECT_EQ(1, OverloadedNewAndDelete::delete_count());
603   EXPECT_EQ(1, OverloadedNewAndDelete::new_count());
604 }
605
606 // TODO scoped_ptr_malloc