Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / base / memory / weak_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/weak_ptr.h"
6
7 #include <string>
8
9 #include "base/bind.h"
10 #include "base/debug/leak_annotations.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/synchronization/waitable_event.h"
14 #include "base/threading/thread.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 namespace base {
18 namespace {
19
20 template <class T>
21 class OffThreadObjectCreator {
22  public:
23   static T* NewObject() {
24     T* result;
25     {
26       Thread creator_thread("creator_thread");
27       creator_thread.Start();
28       creator_thread.message_loop()->PostTask(
29           FROM_HERE,
30           base::Bind(OffThreadObjectCreator::CreateObject, &result));
31     }
32     DCHECK(result);  // We synchronized on thread destruction above.
33     return result;
34   }
35  private:
36   static void CreateObject(T** result) {
37     *result = new T;
38   }
39 };
40
41 struct Base {
42   std::string member;
43 };
44 struct Derived : public Base {};
45
46 struct TargetBase {};
47 struct Target : public TargetBase, public SupportsWeakPtr<Target> {
48   virtual ~Target() {}
49 };
50 struct DerivedTarget : public Target {};
51 struct Arrow {
52   WeakPtr<Target> target;
53 };
54 struct TargetWithFactory : public Target {
55   TargetWithFactory() : factory(this) {}
56   WeakPtrFactory<Target> factory;
57 };
58
59 // Helper class to create and destroy weak pointer copies
60 // and delete objects on a background thread.
61 class BackgroundThread : public Thread {
62  public:
63   BackgroundThread() : Thread("owner_thread") {}
64
65   virtual ~BackgroundThread() {
66     Stop();
67   }
68
69   void CreateArrowFromTarget(Arrow** arrow, Target* target) {
70     WaitableEvent completion(true, false);
71     message_loop()->PostTask(
72         FROM_HERE,
73         base::Bind(&BackgroundThread::DoCreateArrowFromTarget,
74                    arrow, target, &completion));
75     completion.Wait();
76   }
77
78   void CreateArrowFromArrow(Arrow** arrow, const Arrow* other) {
79     WaitableEvent completion(true, false);
80     message_loop()->PostTask(
81         FROM_HERE,
82         base::Bind(&BackgroundThread::DoCreateArrowFromArrow,
83                    arrow, other, &completion));
84     completion.Wait();
85   }
86
87   void DeleteTarget(Target* object) {
88     WaitableEvent completion(true, false);
89     message_loop()->PostTask(
90         FROM_HERE,
91         base::Bind(&BackgroundThread::DoDeleteTarget, object, &completion));
92     completion.Wait();
93   }
94
95   void CopyAndAssignArrow(Arrow* object) {
96     WaitableEvent completion(true, false);
97     message_loop()->PostTask(
98         FROM_HERE,
99         base::Bind(&BackgroundThread::DoCopyAndAssignArrow,
100                    object, &completion));
101     completion.Wait();
102   }
103
104   void CopyAndAssignArrowBase(Arrow* object) {
105     WaitableEvent completion(true, false);
106     message_loop()->PostTask(
107         FROM_HERE,
108         base::Bind(&BackgroundThread::DoCopyAndAssignArrowBase,
109                    object, &completion));
110     completion.Wait();
111   }
112
113   void DeleteArrow(Arrow* object) {
114     WaitableEvent completion(true, false);
115     message_loop()->PostTask(
116         FROM_HERE,
117         base::Bind(&BackgroundThread::DoDeleteArrow, object, &completion));
118     completion.Wait();
119   }
120
121   Target* DeRef(const Arrow* arrow) {
122     WaitableEvent completion(true, false);
123     Target* result = NULL;
124     message_loop()->PostTask(
125         FROM_HERE,
126         base::Bind(&BackgroundThread::DoDeRef, arrow, &result, &completion));
127     completion.Wait();
128     return result;
129   }
130
131  protected:
132   static void DoCreateArrowFromArrow(Arrow** arrow,
133                                      const Arrow* other,
134                                      WaitableEvent* completion) {
135     *arrow = new Arrow;
136     **arrow = *other;
137     completion->Signal();
138   }
139
140   static void DoCreateArrowFromTarget(Arrow** arrow,
141                                       Target* target,
142                                       WaitableEvent* completion) {
143     *arrow = new Arrow;
144     (*arrow)->target = target->AsWeakPtr();
145     completion->Signal();
146   }
147
148   static void DoDeRef(const Arrow* arrow,
149                       Target** result,
150                       WaitableEvent* completion) {
151     *result = arrow->target.get();
152     completion->Signal();
153   }
154
155   static void DoDeleteTarget(Target* object, WaitableEvent* completion) {
156     delete object;
157     completion->Signal();
158   }
159
160   static void DoCopyAndAssignArrow(Arrow* object, WaitableEvent* completion) {
161     // Copy constructor.
162     Arrow a = *object;
163     // Assignment operator.
164     *object = a;
165     completion->Signal();
166   }
167
168   static void DoCopyAndAssignArrowBase(
169       Arrow* object,
170       WaitableEvent* completion) {
171     // Copy constructor.
172     WeakPtr<TargetBase> b = object->target;
173     // Assignment operator.
174     WeakPtr<TargetBase> c;
175     c = object->target;
176     completion->Signal();
177   }
178
179   static void DoDeleteArrow(Arrow* object, WaitableEvent* completion) {
180     delete object;
181     completion->Signal();
182   }
183 };
184
185 }  // namespace
186
187 TEST(WeakPtrFactoryTest, Basic) {
188   int data;
189   WeakPtrFactory<int> factory(&data);
190   WeakPtr<int> ptr = factory.GetWeakPtr();
191   EXPECT_EQ(&data, ptr.get());
192 }
193
194 TEST(WeakPtrFactoryTest, Comparison) {
195   int data;
196   WeakPtrFactory<int> factory(&data);
197   WeakPtr<int> ptr = factory.GetWeakPtr();
198   WeakPtr<int> ptr2 = ptr;
199   EXPECT_EQ(ptr.get(), ptr2.get());
200 }
201
202 TEST(WeakPtrFactoryTest, OutOfScope) {
203   WeakPtr<int> ptr;
204   EXPECT_EQ(NULL, ptr.get());
205   {
206     int data;
207     WeakPtrFactory<int> factory(&data);
208     ptr = factory.GetWeakPtr();
209   }
210   EXPECT_EQ(NULL, ptr.get());
211 }
212
213 TEST(WeakPtrFactoryTest, Multiple) {
214   WeakPtr<int> a, b;
215   {
216     int data;
217     WeakPtrFactory<int> factory(&data);
218     a = factory.GetWeakPtr();
219     b = factory.GetWeakPtr();
220     EXPECT_EQ(&data, a.get());
221     EXPECT_EQ(&data, b.get());
222   }
223   EXPECT_EQ(NULL, a.get());
224   EXPECT_EQ(NULL, b.get());
225 }
226
227 TEST(WeakPtrFactoryTest, MultipleStaged) {
228   WeakPtr<int> a;
229   {
230     int data;
231     WeakPtrFactory<int> factory(&data);
232     a = factory.GetWeakPtr();
233     {
234       WeakPtr<int> b = factory.GetWeakPtr();
235     }
236     EXPECT_TRUE(NULL != a.get());
237   }
238   EXPECT_EQ(NULL, a.get());
239 }
240
241 TEST(WeakPtrFactoryTest, Dereference) {
242   Base data;
243   data.member = "123456";
244   WeakPtrFactory<Base> factory(&data);
245   WeakPtr<Base> ptr = factory.GetWeakPtr();
246   EXPECT_EQ(&data, ptr.get());
247   EXPECT_EQ(data.member, (*ptr).member);
248   EXPECT_EQ(data.member, ptr->member);
249 }
250
251 TEST(WeakPtrFactoryTest, UpCast) {
252   Derived data;
253   WeakPtrFactory<Derived> factory(&data);
254   WeakPtr<Base> ptr = factory.GetWeakPtr();
255   ptr = factory.GetWeakPtr();
256   EXPECT_EQ(ptr.get(), &data);
257 }
258
259 TEST(WeakPtrTest, SupportsWeakPtr) {
260   Target target;
261   WeakPtr<Target> ptr = target.AsWeakPtr();
262   EXPECT_EQ(&target, ptr.get());
263 }
264
265 TEST(WeakPtrTest, DerivedTarget) {
266   DerivedTarget target;
267   WeakPtr<DerivedTarget> ptr = AsWeakPtr(&target);
268   EXPECT_EQ(&target, ptr.get());
269 }
270
271 TEST(WeakPtrTest, InvalidateWeakPtrs) {
272   int data;
273   WeakPtrFactory<int> factory(&data);
274   WeakPtr<int> ptr = factory.GetWeakPtr();
275   EXPECT_EQ(&data, ptr.get());
276   EXPECT_TRUE(factory.HasWeakPtrs());
277   factory.InvalidateWeakPtrs();
278   EXPECT_EQ(NULL, ptr.get());
279   EXPECT_FALSE(factory.HasWeakPtrs());
280
281   // Test that the factory can create new weak pointers after a
282   // InvalidateWeakPtrs call, and they remain valid until the next
283   // InvalidateWeakPtrs call.
284   WeakPtr<int> ptr2 = factory.GetWeakPtr();
285   EXPECT_EQ(&data, ptr2.get());
286   EXPECT_TRUE(factory.HasWeakPtrs());
287   factory.InvalidateWeakPtrs();
288   EXPECT_EQ(NULL, ptr2.get());
289   EXPECT_FALSE(factory.HasWeakPtrs());
290 }
291
292 TEST(WeakPtrTest, HasWeakPtrs) {
293   int data;
294   WeakPtrFactory<int> factory(&data);
295   {
296     WeakPtr<int> ptr = factory.GetWeakPtr();
297     EXPECT_TRUE(factory.HasWeakPtrs());
298   }
299   EXPECT_FALSE(factory.HasWeakPtrs());
300 }
301
302 TEST(WeakPtrTest, ObjectAndWeakPtrOnDifferentThreads) {
303   // Test that it is OK to create an object that supports WeakPtr on one thread,
304   // but use it on another.  This tests that we do not trip runtime checks that
305   // ensure that a WeakPtr is not used by multiple threads.
306   scoped_ptr<Target> target(OffThreadObjectCreator<Target>::NewObject());
307   WeakPtr<Target> weak_ptr = target->AsWeakPtr();
308   EXPECT_EQ(target.get(), weak_ptr.get());
309 }
310
311 TEST(WeakPtrTest, WeakPtrInitiateAndUseOnDifferentThreads) {
312   // Test that it is OK to create an object that has a WeakPtr member on one
313   // thread, but use it on another.  This tests that we do not trip runtime
314   // checks that ensure that a WeakPtr is not used by multiple threads.
315   scoped_ptr<Arrow> arrow(OffThreadObjectCreator<Arrow>::NewObject());
316   Target target;
317   arrow->target = target.AsWeakPtr();
318   EXPECT_EQ(&target, arrow->target.get());
319 }
320
321 TEST(WeakPtrTest, MoveOwnershipImplicitly) {
322   // Move object ownership to another thread by releasing all weak pointers
323   // on the original thread first, and then establish WeakPtr on a different
324   // thread.
325   BackgroundThread background;
326   background.Start();
327
328   Target* target = new Target();
329   {
330     WeakPtr<Target> weak_ptr = target->AsWeakPtr();
331     // Main thread deletes the WeakPtr, then the thread ownership of the
332     // object can be implicitly moved.
333   }
334   Arrow* arrow;
335
336   // Background thread creates WeakPtr(and implicitly owns the object).
337   background.CreateArrowFromTarget(&arrow, target);
338   EXPECT_EQ(background.DeRef(arrow), target);
339
340   {
341     // Main thread creates another WeakPtr, but this does not trigger implicitly
342     // thread ownership move.
343     Arrow arrow;
344     arrow.target = target->AsWeakPtr();
345
346     // The new WeakPtr is owned by background thread.
347     EXPECT_EQ(target, background.DeRef(&arrow));
348   }
349
350   // Target can only be deleted on background thread.
351   background.DeleteTarget(target);
352   background.DeleteArrow(arrow);
353 }
354
355 TEST(WeakPtrTest, MoveOwnershipOfUnreferencedObject) {
356   BackgroundThread background;
357   background.Start();
358
359   Arrow* arrow;
360   {
361     Target target;
362     // Background thread creates WeakPtr.
363     background.CreateArrowFromTarget(&arrow, &target);
364
365     // Bind to background thread.
366     EXPECT_EQ(&target, background.DeRef(arrow));
367
368     // Release the only WeakPtr.
369     arrow->target.reset();
370
371     // Now we should be able to create a new reference from this thread.
372     arrow->target = target.AsWeakPtr();
373
374     // Re-bind to main thread.
375     EXPECT_EQ(&target, arrow->target.get());
376
377     // And the main thread can now delete the target.
378   }
379
380   delete arrow;
381 }
382
383 TEST(WeakPtrTest, MoveOwnershipAfterInvalidate) {
384   BackgroundThread background;
385   background.Start();
386
387   Arrow arrow;
388   scoped_ptr<TargetWithFactory> target(new TargetWithFactory);
389
390   // Bind to main thread.
391   arrow.target = target->factory.GetWeakPtr();
392   EXPECT_EQ(target.get(), arrow.target.get());
393
394   target->factory.InvalidateWeakPtrs();
395   EXPECT_EQ(NULL, arrow.target.get());
396
397   arrow.target = target->factory.GetWeakPtr();
398   // Re-bind to background thread.
399   EXPECT_EQ(target.get(), background.DeRef(&arrow));
400
401   // And the background thread can now delete the target.
402   background.DeleteTarget(target.release());
403 }
404
405 TEST(WeakPtrTest, MainThreadRefOutlivesBackgroundThreadRef) {
406   // Originating thread has a WeakPtr that outlives others.
407   // - Main thread creates a WeakPtr
408   // - Background thread creates a WeakPtr copy from the one in main thread
409   // - Destruct the WeakPtr on background thread
410   // - Destruct the WeakPtr on main thread
411   BackgroundThread background;
412   background.Start();
413
414   Target target;
415   Arrow arrow;
416   arrow.target = target.AsWeakPtr();
417
418   Arrow* arrow_copy;
419   background.CreateArrowFromArrow(&arrow_copy, &arrow);
420   EXPECT_EQ(arrow_copy->target.get(), &target);
421   background.DeleteArrow(arrow_copy);
422 }
423
424 TEST(WeakPtrTest, BackgroundThreadRefOutlivesMainThreadRef) {
425   // Originating thread drops all references before another thread.
426   // - Main thread creates a WeakPtr and passes copy to background thread
427   // - Destruct the pointer on main thread
428   // - Destruct the pointer on background thread
429   BackgroundThread background;
430   background.Start();
431
432   Target target;
433   Arrow* arrow_copy;
434   {
435     Arrow arrow;
436     arrow.target = target.AsWeakPtr();
437     background.CreateArrowFromArrow(&arrow_copy, &arrow);
438   }
439   EXPECT_EQ(arrow_copy->target.get(), &target);
440   background.DeleteArrow(arrow_copy);
441 }
442
443 TEST(WeakPtrTest, OwnerThreadDeletesObject) {
444   // Originating thread invalidates WeakPtrs while its held by other thread.
445   // - Main thread creates WeakPtr and passes Copy to background thread
446   // - Object gets destroyed on main thread
447   //   (invalidates WeakPtr on background thread)
448   // - WeakPtr gets destroyed on Thread B
449   BackgroundThread background;
450   background.Start();
451   Arrow* arrow_copy;
452   {
453     Target target;
454     Arrow arrow;
455     arrow.target = target.AsWeakPtr();
456     background.CreateArrowFromArrow(&arrow_copy, &arrow);
457   }
458   EXPECT_EQ(NULL, arrow_copy->target.get());
459   background.DeleteArrow(arrow_copy);
460 }
461
462 TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtr) {
463   // Main thread creates a Target object.
464   Target target;
465   // Main thread creates an arrow referencing the Target.
466   Arrow *arrow = new Arrow();
467   arrow->target = target.AsWeakPtr();
468
469   // Background can copy and assign arrow (as well as the WeakPtr inside).
470   BackgroundThread background;
471   background.Start();
472   background.CopyAndAssignArrow(arrow);
473   background.DeleteArrow(arrow);
474 }
475
476 TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtrBase) {
477   // Main thread creates a Target object.
478   Target target;
479   // Main thread creates an arrow referencing the Target.
480   Arrow *arrow = new Arrow();
481   arrow->target = target.AsWeakPtr();
482
483   // Background can copy and assign arrow's WeakPtr to a base class WeakPtr.
484   BackgroundThread background;
485   background.Start();
486   background.CopyAndAssignArrowBase(arrow);
487   background.DeleteArrow(arrow);
488 }
489
490 TEST(WeakPtrTest, NonOwnerThreadCanDeleteWeakPtr) {
491   // Main thread creates a Target object.
492   Target target;
493   // Main thread creates an arrow referencing the Target.
494   Arrow* arrow = new Arrow();
495   arrow->target = target.AsWeakPtr();
496
497   // Background can delete arrow (as well as the WeakPtr inside).
498   BackgroundThread background;
499   background.Start();
500   background.DeleteArrow(arrow);
501 }
502
503 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && GTEST_HAS_DEATH_TEST
504
505 TEST(WeakPtrDeathTest, WeakPtrCopyDoesNotChangeThreadBinding) {
506   // The default style "fast" does not support multi-threaded tests
507   // (introduces deadlock on Linux).
508   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
509
510   BackgroundThread background;
511   background.Start();
512
513   // Main thread creates a Target object.
514   Target target;
515   // Main thread creates an arrow referencing the Target.
516   Arrow arrow;
517   arrow.target = target.AsWeakPtr();
518
519   // Background copies the WeakPtr.
520   Arrow* arrow_copy;
521   background.CreateArrowFromArrow(&arrow_copy, &arrow);
522
523   // The copy is still bound to main thread so I can deref.
524   EXPECT_EQ(arrow.target.get(), arrow_copy->target.get());
525
526   // Although background thread created the copy, it can not deref the copied
527   // WeakPtr.
528   ASSERT_DEATH(background.DeRef(arrow_copy), "");
529
530   background.DeleteArrow(arrow_copy);
531 }
532
533 TEST(WeakPtrDeathTest, NonOwnerThreadDereferencesWeakPtrAfterReference) {
534   // The default style "fast" does not support multi-threaded tests
535   // (introduces deadlock on Linux).
536   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
537
538   // Main thread creates a Target object.
539   Target target;
540
541   // Main thread creates an arrow referencing the Target (so target's
542   // thread ownership can not be implicitly moved).
543   Arrow arrow;
544   arrow.target = target.AsWeakPtr();
545   arrow.target.get();
546
547   // Background thread tries to deref target, which violates thread ownership.
548   BackgroundThread background;
549   background.Start();
550   ASSERT_DEATH(background.DeRef(&arrow), "");
551 }
552
553 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesWeakPtrAfterReference) {
554   // The default style "fast" does not support multi-threaded tests
555   // (introduces deadlock on Linux).
556   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
557
558   scoped_ptr<Target> target(new Target());
559
560   // Main thread creates an arrow referencing the Target.
561   Arrow arrow;
562   arrow.target = target->AsWeakPtr();
563
564   // Background thread tries to deref target, binding it to the thread.
565   BackgroundThread background;
566   background.Start();
567   background.DeRef(&arrow);
568
569   // Main thread deletes Target, violating thread binding.
570   ASSERT_DEATH(target.reset(), "");
571
572   // |target.reset()| died so |target| still holds the object, so we
573   // must pass it to the background thread to teardown.
574   background.DeleteTarget(target.release());
575 }
576
577 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesObjectAfterReference) {
578   // The default style "fast" does not support multi-threaded tests
579   // (introduces deadlock on Linux).
580   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
581
582   scoped_ptr<Target> target(new Target());
583
584   // Main thread creates an arrow referencing the Target, and references it, so
585   // that it becomes bound to the thread.
586   Arrow arrow;
587   arrow.target = target->AsWeakPtr();
588   arrow.target.get();
589
590   // Background thread tries to delete target, volating thread binding.
591   BackgroundThread background;
592   background.Start();
593   ASSERT_DEATH(background.DeleteTarget(target.release()), "");
594 }
595
596 TEST(WeakPtrDeathTest, NonOwnerThreadReferencesObjectAfterDeletion) {
597   // The default style "fast" does not support multi-threaded tests
598   // (introduces deadlock on Linux).
599   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
600
601   scoped_ptr<Target> target(new Target());
602
603   // Main thread creates an arrow referencing the Target.
604   Arrow arrow;
605   arrow.target = target->AsWeakPtr();
606
607   // Background thread tries to delete target, binding the object to the thread.
608   BackgroundThread background;
609   background.Start();
610   background.DeleteTarget(target.release());
611
612   // Main thread attempts to dereference the target, violating thread binding.
613   ASSERT_DEATH(arrow.target.get(), "");
614 }
615
616 #endif
617
618 }  // namespace base