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
17namespace base {
18namespace {
19
20template <class T>
21class 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
41struct Base {
42  std::string member;
43};
44struct Derived : public Base {};
45
46struct TargetBase {};
47struct Target : public TargetBase, public SupportsWeakPtr<Target> {
48  virtual ~Target() {}
49};
50struct DerivedTarget : public Target {};
51struct Arrow {
52  WeakPtr<Target> target;
53};
54struct 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.
61class 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
187TEST(WeakPtrFactoryTest, Basic) {
188  int data;
189  WeakPtrFactory<int> factory(&data);
190  WeakPtr<int> ptr = factory.GetWeakPtr();
191  EXPECT_EQ(&data, ptr.get());
192}
193
194TEST(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
202TEST(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
213TEST(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
227TEST(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
241TEST(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
251TEST(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
259TEST(WeakPtrTest, SupportsWeakPtr) {
260  Target target;
261  WeakPtr<Target> ptr = target.AsWeakPtr();
262  EXPECT_EQ(&target, ptr.get());
263}
264
265TEST(WeakPtrTest, DerivedTarget) {
266  DerivedTarget target;
267  WeakPtr<DerivedTarget> ptr = AsWeakPtr(&target);
268  EXPECT_EQ(&target, ptr.get());
269}
270
271TEST(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
282TEST(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
292TEST(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
301TEST(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
311TEST(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
345TEST(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
373TEST(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
395TEST(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
414TEST(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
433TEST(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
452TEST(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
466TEST(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
480TEST(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
495TEST(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
523TEST(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
543TEST(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
567TEST(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
586TEST(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
609