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