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