Upstream version 5.34.104.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
282 TEST(WeakPtrTest, HasWeakPtrs) {
283   int data;
284   WeakPtrFactory<int> factory(&data);
285   {
286     WeakPtr<int> ptr = factory.GetWeakPtr();
287     EXPECT_TRUE(factory.HasWeakPtrs());
288   }
289   EXPECT_FALSE(factory.HasWeakPtrs());
290 }
291
292 TEST(WeakPtrTest, ObjectAndWeakPtrOnDifferentThreads) {
293   // Test that it is OK to create an object that supports WeakPtr on one thread,
294   // but use it on another.  This tests that we do not trip runtime checks that
295   // ensure that a WeakPtr is not used by multiple threads.
296   scoped_ptr<Target> target(OffThreadObjectCreator<Target>::NewObject());
297   WeakPtr<Target> weak_ptr = target->AsWeakPtr();
298   EXPECT_EQ(target.get(), weak_ptr.get());
299 }
300
301 TEST(WeakPtrTest, WeakPtrInitiateAndUseOnDifferentThreads) {
302   // Test that it is OK to create an object that has a WeakPtr member on one
303   // thread, but use it on another.  This tests that we do not trip runtime
304   // checks that ensure that a WeakPtr is not used by multiple threads.
305   scoped_ptr<Arrow> arrow(OffThreadObjectCreator<Arrow>::NewObject());
306   Target target;
307   arrow->target = target.AsWeakPtr();
308   EXPECT_EQ(&target, arrow->target.get());
309 }
310
311 TEST(WeakPtrTest, MoveOwnershipImplicitly) {
312   // Move object ownership to another thread by releasing all weak pointers
313   // on the original thread first, and then establish WeakPtr on a different
314   // thread.
315   BackgroundThread background;
316   background.Start();
317
318   Target* target = new Target();
319   {
320     WeakPtr<Target> weak_ptr = target->AsWeakPtr();
321     // Main thread deletes the WeakPtr, then the thread ownership of the
322     // object can be implicitly moved.
323   }
324   Arrow* arrow;
325
326   // Background thread creates WeakPtr(and implicitly owns the object).
327   background.CreateArrowFromTarget(&arrow, target);
328   EXPECT_EQ(background.DeRef(arrow), target);
329
330   {
331     // Main thread creates another WeakPtr, but this does not trigger implicitly
332     // thread ownership move.
333     Arrow arrow;
334     arrow.target = target->AsWeakPtr();
335
336     // The new WeakPtr is owned by background thread.
337     EXPECT_EQ(target, background.DeRef(&arrow));
338   }
339
340   // Target can only be deleted on background thread.
341   background.DeleteTarget(target);
342   background.DeleteArrow(arrow);
343 }
344
345 TEST(WeakPtrTest, MoveOwnershipOfUnreferencedObject) {
346   BackgroundThread background;
347   background.Start();
348
349   Arrow* arrow;
350   {
351     Target target;
352     // Background thread creates WeakPtr.
353     background.CreateArrowFromTarget(&arrow, &target);
354
355     // Bind to background thread.
356     EXPECT_EQ(&target, background.DeRef(arrow));
357
358     // Release the only WeakPtr.
359     arrow->target.reset();
360
361     // Now we should be able to create a new reference from this thread.
362     arrow->target = target.AsWeakPtr();
363
364     // Re-bind to main thread.
365     EXPECT_EQ(&target, arrow->target.get());
366
367     // And the main thread can now delete the target.
368   }
369
370   delete arrow;
371 }
372
373 TEST(WeakPtrTest, MoveOwnershipAfterInvalidate) {
374   BackgroundThread background;
375   background.Start();
376
377   Arrow arrow;
378   scoped_ptr<TargetWithFactory> target(new TargetWithFactory);
379
380   // Bind to main thread.
381   arrow.target = target->factory.GetWeakPtr();
382   EXPECT_EQ(target.get(), arrow.target.get());
383
384   target->factory.InvalidateWeakPtrs();
385   EXPECT_EQ(NULL, arrow.target.get());
386
387   arrow.target = target->factory.GetWeakPtr();
388   // Re-bind to background thread.
389   EXPECT_EQ(target.get(), background.DeRef(&arrow));
390
391   // And the background thread can now delete the target.
392   background.DeleteTarget(target.release());
393 }
394
395 TEST(WeakPtrTest, MainThreadRefOutlivesBackgroundThreadRef) {
396   // Originating thread has a WeakPtr that outlives others.
397   // - Main thread creates a WeakPtr
398   // - Background thread creates a WeakPtr copy from the one in main thread
399   // - Destruct the WeakPtr on background thread
400   // - Destruct the WeakPtr on main thread
401   BackgroundThread background;
402   background.Start();
403
404   Target target;
405   Arrow arrow;
406   arrow.target = target.AsWeakPtr();
407
408   Arrow* arrow_copy;
409   background.CreateArrowFromArrow(&arrow_copy, &arrow);
410   EXPECT_EQ(arrow_copy->target.get(), &target);
411   background.DeleteArrow(arrow_copy);
412 }
413
414 TEST(WeakPtrTest, BackgroundThreadRefOutlivesMainThreadRef) {
415   // Originating thread drops all references before another thread.
416   // - Main thread creates a WeakPtr and passes copy to background thread
417   // - Destruct the pointer on main thread
418   // - Destruct the pointer on background thread
419   BackgroundThread background;
420   background.Start();
421
422   Target target;
423   Arrow* arrow_copy;
424   {
425     Arrow arrow;
426     arrow.target = target.AsWeakPtr();
427     background.CreateArrowFromArrow(&arrow_copy, &arrow);
428   }
429   EXPECT_EQ(arrow_copy->target.get(), &target);
430   background.DeleteArrow(arrow_copy);
431 }
432
433 TEST(WeakPtrTest, OwnerThreadDeletesObject) {
434   // Originating thread invalidates WeakPtrs while its held by other thread.
435   // - Main thread creates WeakPtr and passes Copy to background thread
436   // - Object gets destroyed on main thread
437   //   (invalidates WeakPtr on background thread)
438   // - WeakPtr gets destroyed on Thread B
439   BackgroundThread background;
440   background.Start();
441   Arrow* arrow_copy;
442   {
443     Target target;
444     Arrow arrow;
445     arrow.target = target.AsWeakPtr();
446     background.CreateArrowFromArrow(&arrow_copy, &arrow);
447   }
448   EXPECT_EQ(NULL, arrow_copy->target.get());
449   background.DeleteArrow(arrow_copy);
450 }
451
452 TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtr) {
453   // Main thread creates a Target object.
454   Target target;
455   // Main thread creates an arrow referencing the Target.
456   Arrow *arrow = new Arrow();
457   arrow->target = target.AsWeakPtr();
458
459   // Background can copy and assign arrow (as well as the WeakPtr inside).
460   BackgroundThread background;
461   background.Start();
462   background.CopyAndAssignArrow(arrow);
463   background.DeleteArrow(arrow);
464 }
465
466 TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtrBase) {
467   // Main thread creates a Target object.
468   Target target;
469   // Main thread creates an arrow referencing the Target.
470   Arrow *arrow = new Arrow();
471   arrow->target = target.AsWeakPtr();
472
473   // Background can copy and assign arrow's WeakPtr to a base class WeakPtr.
474   BackgroundThread background;
475   background.Start();
476   background.CopyAndAssignArrowBase(arrow);
477   background.DeleteArrow(arrow);
478 }
479
480 TEST(WeakPtrTest, NonOwnerThreadCanDeleteWeakPtr) {
481   // Main thread creates a Target object.
482   Target target;
483   // Main thread creates an arrow referencing the Target.
484   Arrow* arrow = new Arrow();
485   arrow->target = target.AsWeakPtr();
486
487   // Background can delete arrow (as well as the WeakPtr inside).
488   BackgroundThread background;
489   background.Start();
490   background.DeleteArrow(arrow);
491 }
492
493 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && GTEST_HAS_DEATH_TEST
494
495 TEST(WeakPtrDeathTest, WeakPtrCopyDoesNotChangeThreadBinding) {
496   // The default style "fast" does not support multi-threaded tests
497   // (introduces deadlock on Linux).
498   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
499
500   BackgroundThread background;
501   background.Start();
502
503   // Main thread creates a Target object.
504   Target target;
505   // Main thread creates an arrow referencing the Target.
506   Arrow arrow;
507   arrow.target = target.AsWeakPtr();
508
509   // Background copies the WeakPtr.
510   Arrow* arrow_copy;
511   background.CreateArrowFromArrow(&arrow_copy, &arrow);
512
513   // The copy is still bound to main thread so I can deref.
514   EXPECT_EQ(arrow.target.get(), arrow_copy->target.get());
515
516   // Although background thread created the copy, it can not deref the copied
517   // WeakPtr.
518   ASSERT_DEATH(background.DeRef(arrow_copy), "");
519
520   background.DeleteArrow(arrow_copy);
521 }
522
523 TEST(WeakPtrDeathTest, NonOwnerThreadDereferencesWeakPtrAfterReference) {
524   // The default style "fast" does not support multi-threaded tests
525   // (introduces deadlock on Linux).
526   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
527
528   // Main thread creates a Target object.
529   Target target;
530
531   // Main thread creates an arrow referencing the Target (so target's
532   // thread ownership can not be implicitly moved).
533   Arrow arrow;
534   arrow.target = target.AsWeakPtr();
535   arrow.target.get();
536
537   // Background thread tries to deref target, which violates thread ownership.
538   BackgroundThread background;
539   background.Start();
540   ASSERT_DEATH(background.DeRef(&arrow), "");
541 }
542
543 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesWeakPtrAfterReference) {
544   // The default style "fast" does not support multi-threaded tests
545   // (introduces deadlock on Linux).
546   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
547
548   scoped_ptr<Target> target(new Target());
549
550   // Main thread creates an arrow referencing the Target.
551   Arrow arrow;
552   arrow.target = target->AsWeakPtr();
553
554   // Background thread tries to deref target, binding it to the thread.
555   BackgroundThread background;
556   background.Start();
557   background.DeRef(&arrow);
558
559   // Main thread deletes Target, violating thread binding.
560   ASSERT_DEATH(target.reset(), "");
561
562   // |target.reset()| died so |target| still holds the object, so we
563   // must pass it to the background thread to teardown.
564   background.DeleteTarget(target.release());
565 }
566
567 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesObjectAfterReference) {
568   // The default style "fast" does not support multi-threaded tests
569   // (introduces deadlock on Linux).
570   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
571
572   scoped_ptr<Target> target(new Target());
573
574   // Main thread creates an arrow referencing the Target, and references it, so
575   // that it becomes bound to the thread.
576   Arrow arrow;
577   arrow.target = target->AsWeakPtr();
578   arrow.target.get();
579
580   // Background thread tries to delete target, volating thread binding.
581   BackgroundThread background;
582   background.Start();
583   ASSERT_DEATH(background.DeleteTarget(target.release()), "");
584 }
585
586 TEST(WeakPtrDeathTest, NonOwnerThreadReferencesObjectAfterDeletion) {
587   // The default style "fast" does not support multi-threaded tests
588   // (introduces deadlock on Linux).
589   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
590
591   scoped_ptr<Target> target(new Target());
592
593   // Main thread creates an arrow referencing the Target.
594   Arrow arrow;
595   arrow.target = target->AsWeakPtr();
596
597   // Background thread tries to delete target, binding the object to the thread.
598   BackgroundThread background;
599   background.Start();
600   background.DeleteTarget(target.release());
601
602   // Main thread attempts to dereference the target, violating thread binding.
603   ASSERT_DEATH(arrow.target.get(), "");
604 }
605
606 #endif
607
608 }  // namespace base