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  // 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
292TEST(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
302TEST(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
311TEST(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
321TEST(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
355TEST(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
383TEST(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
405TEST(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
424TEST(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
443TEST(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
462TEST(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
476TEST(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
490TEST(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
505TEST(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
533TEST(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
553TEST(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
577TEST(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
596TEST(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
619