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