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
794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include <memory>
8b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <string>
9b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
10b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/bind.h"
1194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include "base/debug/leak_annotations.h"
12b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/location.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
2194ffa55491333f3dcc701befd0d2652922916d99Luis Hector ChavezWeakPtr<int> PassThru(WeakPtr<int> ptr) {
2294ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez  return ptr;
2394ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez}
2494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez
25b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erattemplate <class T>
26b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass OffThreadObjectCreator {
27b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public:
28b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  static T* NewObject() {
29b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    T* result;
30b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    {
31b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      Thread creator_thread("creator_thread");
32b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      creator_thread.Start();
33b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      creator_thread.task_runner()->PostTask(
34b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat          FROM_HERE, base::Bind(OffThreadObjectCreator::CreateObject, &result));
35b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    }
36b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    DCHECK(result);  // We synchronized on thread destruction above.
37b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    return result;
38b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
39b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat private:
40b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  static void CreateObject(T** result) {
41b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    *result = new T;
42b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
43b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat};
44b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
45b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstruct Base {
46b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  std::string member;
47b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat};
48b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstruct Derived : public Base {};
49b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
50b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstruct TargetBase {};
51b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstruct Target : public TargetBase, public SupportsWeakPtr<Target> {
52b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  virtual ~Target() {}
53b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat};
54b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstruct DerivedTarget : public Target {};
55b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstruct Arrow {
56b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  WeakPtr<Target> target;
57b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat};
58b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstruct TargetWithFactory : public Target {
59b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  TargetWithFactory() : factory(this) {}
60b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  WeakPtrFactory<Target> factory;
61b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat};
62b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
63b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Helper class to create and destroy weak pointer copies
64b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// and delete objects on a background thread.
65b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass BackgroundThread : public Thread {
66b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public:
67b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  BackgroundThread() : Thread("owner_thread") {}
68b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
69b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ~BackgroundThread() override { Stop(); }
70b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
71b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  void CreateArrowFromTarget(Arrow** arrow, Target* target) {
720c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez    WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
730c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez                             WaitableEvent::InitialState::NOT_SIGNALED);
74b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    task_runner()->PostTask(
75b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        FROM_HERE, base::Bind(&BackgroundThread::DoCreateArrowFromTarget, arrow,
76b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                              target, &completion));
77b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    completion.Wait();
78b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
79b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
80b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  void CreateArrowFromArrow(Arrow** arrow, const Arrow* other) {
810c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez    WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
820c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez                             WaitableEvent::InitialState::NOT_SIGNALED);
83b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    task_runner()->PostTask(
84b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        FROM_HERE, base::Bind(&BackgroundThread::DoCreateArrowFromArrow, arrow,
85b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                              other, &completion));
86b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    completion.Wait();
87b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
88b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
89b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  void DeleteTarget(Target* object) {
900c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez    WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
910c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez                             WaitableEvent::InitialState::NOT_SIGNALED);
92b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    task_runner()->PostTask(
93b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        FROM_HERE,
94b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        base::Bind(&BackgroundThread::DoDeleteTarget, object, &completion));
95b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    completion.Wait();
96b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
97b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
98b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  void CopyAndAssignArrow(Arrow* object) {
990c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez    WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
1000c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez                             WaitableEvent::InitialState::NOT_SIGNALED);
101b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    task_runner()->PostTask(
102b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        FROM_HERE, base::Bind(&BackgroundThread::DoCopyAndAssignArrow, object,
103b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                              &completion));
104b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    completion.Wait();
105b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
106b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
107b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  void CopyAndAssignArrowBase(Arrow* object) {
1080c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez    WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
1090c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez                             WaitableEvent::InitialState::NOT_SIGNALED);
110b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    task_runner()->PostTask(
111b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        FROM_HERE, base::Bind(&BackgroundThread::DoCopyAndAssignArrowBase,
112b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                              object, &completion));
113b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    completion.Wait();
114b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
115b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
116b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  void DeleteArrow(Arrow* object) {
1170c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez    WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
1180c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez                             WaitableEvent::InitialState::NOT_SIGNALED);
119b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    task_runner()->PostTask(
120b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        FROM_HERE,
121b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        base::Bind(&BackgroundThread::DoDeleteArrow, object, &completion));
122b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    completion.Wait();
123b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
124b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
125b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Target* DeRef(const Arrow* arrow) {
1260c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez    WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
1270c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez                             WaitableEvent::InitialState::NOT_SIGNALED);
12894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez    Target* result = nullptr;
129b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    task_runner()->PostTask(FROM_HERE, base::Bind(&BackgroundThread::DoDeRef,
130b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                                  arrow, &result, &completion));
131b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    completion.Wait();
132b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    return result;
133b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
134b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
135b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat protected:
136b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  static void DoCreateArrowFromArrow(Arrow** arrow,
137b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                     const Arrow* other,
138b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                     WaitableEvent* completion) {
139b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    *arrow = new Arrow;
140b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    **arrow = *other;
141b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    completion->Signal();
142b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
143b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
144b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  static void DoCreateArrowFromTarget(Arrow** arrow,
145b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                      Target* target,
146b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                      WaitableEvent* completion) {
147b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    *arrow = new Arrow;
148b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    (*arrow)->target = target->AsWeakPtr();
149b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    completion->Signal();
150b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
151b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
152b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  static void DoDeRef(const Arrow* arrow,
153b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                      Target** result,
154b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                      WaitableEvent* completion) {
155b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    *result = arrow->target.get();
156b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    completion->Signal();
157b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
158b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
159b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  static void DoDeleteTarget(Target* object, WaitableEvent* completion) {
160b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    delete object;
161b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    completion->Signal();
162b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
163b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
164b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  static void DoCopyAndAssignArrow(Arrow* object, WaitableEvent* completion) {
165b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Copy constructor.
166b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    Arrow a = *object;
167b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Assignment operator.
168b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    *object = a;
169b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    completion->Signal();
170b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
171b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
172b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  static void DoCopyAndAssignArrowBase(
173b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      Arrow* object,
174b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      WaitableEvent* completion) {
175b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Copy constructor.
176b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    WeakPtr<TargetBase> b = object->target;
177b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Assignment operator.
178b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    WeakPtr<TargetBase> c;
179b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    c = object->target;
180b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    completion->Signal();
181b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
182b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
183b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  static void DoDeleteArrow(Arrow* object, WaitableEvent* completion) {
184b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    delete object;
185b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    completion->Signal();
186b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
187b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat};
188b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
189b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}  // namespace
190b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
191b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrFactoryTest, Basic) {
192b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int data;
193b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  WeakPtrFactory<int> factory(&data);
194b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  WeakPtr<int> ptr = factory.GetWeakPtr();
195b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_EQ(&data, ptr.get());
196b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
197b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
198b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrFactoryTest, Comparison) {
199b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int data;
200b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  WeakPtrFactory<int> factory(&data);
201b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  WeakPtr<int> ptr = factory.GetWeakPtr();
202b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  WeakPtr<int> ptr2 = ptr;
203b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_EQ(ptr.get(), ptr2.get());
204b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
205b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
2060c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector ChavezTEST(WeakPtrFactoryTest, Move) {
2070c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez  int data;
2080c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez  WeakPtrFactory<int> factory(&data);
2090c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez  WeakPtr<int> ptr = factory.GetWeakPtr();
2100c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez  WeakPtr<int> ptr2 = factory.GetWeakPtr();
2110c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez  WeakPtr<int> ptr3 = std::move(ptr2);
2120c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez  EXPECT_NE(ptr.get(), ptr2.get());
2130c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez  EXPECT_EQ(ptr.get(), ptr3.get());
2140c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez}
2150c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez
216b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrFactoryTest, OutOfScope) {
217b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  WeakPtr<int> ptr;
21894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez  EXPECT_EQ(nullptr, ptr.get());
219b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
220b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    int data;
221b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    WeakPtrFactory<int> factory(&data);
222b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    ptr = factory.GetWeakPtr();
223b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
22494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez  EXPECT_EQ(nullptr, ptr.get());
225b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
226b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
227b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrFactoryTest, Multiple) {
228b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  WeakPtr<int> a, b;
229b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
230b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    int data;
231b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    WeakPtrFactory<int> factory(&data);
232b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    a = factory.GetWeakPtr();
233b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    b = factory.GetWeakPtr();
234b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(&data, a.get());
235b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(&data, b.get());
236b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
23794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez  EXPECT_EQ(nullptr, a.get());
23894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez  EXPECT_EQ(nullptr, b.get());
239b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
240b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
241b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrFactoryTest, MultipleStaged) {
242b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  WeakPtr<int> a;
243b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
244b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    int data;
245b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    WeakPtrFactory<int> factory(&data);
246b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    a = factory.GetWeakPtr();
247b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    {
248b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      WeakPtr<int> b = factory.GetWeakPtr();
249b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    }
25094ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez    EXPECT_NE(nullptr, a.get());
251b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
25294ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez  EXPECT_EQ(nullptr, a.get());
253b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
254b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
255b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrFactoryTest, Dereference) {
256b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Base data;
257b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  data.member = "123456";
258b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  WeakPtrFactory<Base> factory(&data);
259b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  WeakPtr<Base> ptr = factory.GetWeakPtr();
260b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_EQ(&data, ptr.get());
261b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_EQ(data.member, (*ptr).member);
262b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_EQ(data.member, ptr->member);
263b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
264b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
265b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrFactoryTest, UpCast) {
266b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Derived data;
267b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  WeakPtrFactory<Derived> factory(&data);
268b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  WeakPtr<Base> ptr = factory.GetWeakPtr();
269b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ptr = factory.GetWeakPtr();
270b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_EQ(ptr.get(), &data);
271b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
272b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
27394ffa55491333f3dcc701befd0d2652922916d99Luis Hector ChavezTEST(WeakPtrTest, ConstructFromNullptr) {
27494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez  WeakPtr<int> ptr = PassThru(nullptr);
27594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez  EXPECT_EQ(nullptr, ptr.get());
27694ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez}
27794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez
278b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, SupportsWeakPtr) {
279b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Target target;
280b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  WeakPtr<Target> ptr = target.AsWeakPtr();
281b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_EQ(&target, ptr.get());
282b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
283b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
284b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, DerivedTarget) {
285b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DerivedTarget target;
286b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  WeakPtr<DerivedTarget> ptr = AsWeakPtr(&target);
287b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_EQ(&target, ptr.get());
288b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
289b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
29045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(WeakPtrFactoryTest, BooleanTesting) {
29145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  int data;
29245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  WeakPtrFactory<int> factory(&data);
29345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
29445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  WeakPtr<int> ptr_to_an_instance = factory.GetWeakPtr();
29545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(ptr_to_an_instance);
29645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_FALSE(!ptr_to_an_instance);
29745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
29845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  if (ptr_to_an_instance) {
29945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  } else {
30045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    ADD_FAILURE() << "Pointer to an instance should result in true.";
30145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  }
30245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
30345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  if (!ptr_to_an_instance) {  // check for operator!().
30445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    ADD_FAILURE() << "Pointer to an instance should result in !x being false.";
30545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  }
30645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
30745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  WeakPtr<int> null_ptr;
30845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_FALSE(null_ptr);
30945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  EXPECT_TRUE(!null_ptr);
31045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
31145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  if (null_ptr) {
31245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    ADD_FAILURE() << "Null pointer should result in false.";
31345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  }
31445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
31545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  if (!null_ptr) {  // check for operator!().
31645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  } else {
31745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko    ADD_FAILURE() << "Null pointer should result in !x being true.";
31845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko  }
31945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko}
32045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko
3210c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector ChavezTEST(WeakPtrFactoryTest, ComparisonToNull) {
3220c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez  int data;
3230c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez  WeakPtrFactory<int> factory(&data);
3240c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez
3250c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez  WeakPtr<int> ptr_to_an_instance = factory.GetWeakPtr();
3260c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez  EXPECT_NE(nullptr, ptr_to_an_instance);
3270c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez  EXPECT_NE(ptr_to_an_instance, nullptr);
3280c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez
3290c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez  WeakPtr<int> null_ptr;
3300c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez  EXPECT_EQ(null_ptr, nullptr);
3310c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez  EXPECT_EQ(nullptr, null_ptr);
3320c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez}
3330c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez
334b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, InvalidateWeakPtrs) {
335b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int data;
336b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  WeakPtrFactory<int> factory(&data);
337b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  WeakPtr<int> ptr = factory.GetWeakPtr();
338b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_EQ(&data, ptr.get());
339b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_TRUE(factory.HasWeakPtrs());
340b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  factory.InvalidateWeakPtrs();
34194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez  EXPECT_EQ(nullptr, ptr.get());
342b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_FALSE(factory.HasWeakPtrs());
343b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
344b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Test that the factory can create new weak pointers after a
345b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // InvalidateWeakPtrs call, and they remain valid until the next
346b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // InvalidateWeakPtrs call.
347b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  WeakPtr<int> ptr2 = factory.GetWeakPtr();
348b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_EQ(&data, ptr2.get());
349b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_TRUE(factory.HasWeakPtrs());
350b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  factory.InvalidateWeakPtrs();
35194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez  EXPECT_EQ(nullptr, ptr2.get());
352b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_FALSE(factory.HasWeakPtrs());
353b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
354b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
355b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, HasWeakPtrs) {
356b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int data;
357b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  WeakPtrFactory<int> factory(&data);
358b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
359b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    WeakPtr<int> ptr = factory.GetWeakPtr();
360b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_TRUE(factory.HasWeakPtrs());
361b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
362b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_FALSE(factory.HasWeakPtrs());
363b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
364b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
365b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, ObjectAndWeakPtrOnDifferentThreads) {
366b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Test that it is OK to create an object that supports WeakPtr on one thread,
367b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // but use it on another.  This tests that we do not trip runtime checks that
368b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // ensure that a WeakPtr is not used by multiple threads.
36994ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez  std::unique_ptr<Target> target(OffThreadObjectCreator<Target>::NewObject());
370b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  WeakPtr<Target> weak_ptr = target->AsWeakPtr();
371b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_EQ(target.get(), weak_ptr.get());
372b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
373b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
374b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, WeakPtrInitiateAndUseOnDifferentThreads) {
375b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Test that it is OK to create an object that has a WeakPtr member on one
376b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // thread, but use it on another.  This tests that we do not trip runtime
377b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // checks that ensure that a WeakPtr is not used by multiple threads.
37894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez  std::unique_ptr<Arrow> arrow(OffThreadObjectCreator<Arrow>::NewObject());
379b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Target target;
380b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  arrow->target = target.AsWeakPtr();
381b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_EQ(&target, arrow->target.get());
382b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
383b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
384b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, MoveOwnershipImplicitly) {
385b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Move object ownership to another thread by releasing all weak pointers
386b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // on the original thread first, and then establish WeakPtr on a different
387b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // thread.
388b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  BackgroundThread background;
389b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.Start();
390b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
391b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Target* target = new Target();
392b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
393b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    WeakPtr<Target> weak_ptr = target->AsWeakPtr();
394b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Main thread deletes the WeakPtr, then the thread ownership of the
395b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // object can be implicitly moved.
396b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
397b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Arrow* arrow;
398b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
399b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Background thread creates WeakPtr(and implicitly owns the object).
400b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.CreateArrowFromTarget(&arrow, target);
401b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_EQ(background.DeRef(arrow), target);
402b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
403b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
404b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Main thread creates another WeakPtr, but this does not trigger implicitly
405b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // thread ownership move.
406b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    Arrow arrow;
407b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    arrow.target = target->AsWeakPtr();
408b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
409b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // The new WeakPtr is owned by background thread.
410b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(target, background.DeRef(&arrow));
411b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
412b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
413b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Target can only be deleted on background thread.
414b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.DeleteTarget(target);
415b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.DeleteArrow(arrow);
416b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
417b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
418b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, MoveOwnershipOfUnreferencedObject) {
419b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  BackgroundThread background;
420b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.Start();
421b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
422b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Arrow* arrow;
423b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
424b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    Target target;
425b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Background thread creates WeakPtr.
426b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    background.CreateArrowFromTarget(&arrow, &target);
427b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
428b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Bind to background thread.
429b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(&target, background.DeRef(arrow));
430b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
431b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Release the only WeakPtr.
432b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    arrow->target.reset();
433b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
434b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Now we should be able to create a new reference from this thread.
435b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    arrow->target = target.AsWeakPtr();
436b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
437b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Re-bind to main thread.
438b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(&target, arrow->target.get());
439b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
440b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // And the main thread can now delete the target.
441b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
442b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
443b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  delete arrow;
444b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
445b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
446b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, MoveOwnershipAfterInvalidate) {
447b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  BackgroundThread background;
448b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.Start();
449b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
450b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Arrow arrow;
45194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez  std::unique_ptr<TargetWithFactory> target(new TargetWithFactory);
452b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
453b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Bind to main thread.
454b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  arrow.target = target->factory.GetWeakPtr();
455b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_EQ(target.get(), arrow.target.get());
456b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
457b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  target->factory.InvalidateWeakPtrs();
45894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez  EXPECT_EQ(nullptr, arrow.target.get());
459b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
460b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  arrow.target = target->factory.GetWeakPtr();
461b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Re-bind to background thread.
462b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_EQ(target.get(), background.DeRef(&arrow));
463b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
464b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // And the background thread can now delete the target.
465b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.DeleteTarget(target.release());
466b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
467b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
468b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, MainThreadRefOutlivesBackgroundThreadRef) {
469b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Originating thread has a WeakPtr that outlives others.
470b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // - Main thread creates a WeakPtr
471b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // - Background thread creates a WeakPtr copy from the one in main thread
472b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // - Destruct the WeakPtr on background thread
473b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // - Destruct the WeakPtr on main thread
474b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  BackgroundThread background;
475b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.Start();
476b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
477b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Target target;
478b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Arrow arrow;
479b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  arrow.target = target.AsWeakPtr();
480b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
481b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Arrow* arrow_copy;
482b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.CreateArrowFromArrow(&arrow_copy, &arrow);
483b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_EQ(arrow_copy->target.get(), &target);
484b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.DeleteArrow(arrow_copy);
485b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
486b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
487b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, BackgroundThreadRefOutlivesMainThreadRef) {
488b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Originating thread drops all references before another thread.
489b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // - Main thread creates a WeakPtr and passes copy to background thread
490b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // - Destruct the pointer on main thread
491b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // - Destruct the pointer on background thread
492b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  BackgroundThread background;
493b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.Start();
494b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
495b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Target target;
496b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Arrow* arrow_copy;
497b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
498b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    Arrow arrow;
499b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    arrow.target = target.AsWeakPtr();
500b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    background.CreateArrowFromArrow(&arrow_copy, &arrow);
501b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
502b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_EQ(arrow_copy->target.get(), &target);
503b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.DeleteArrow(arrow_copy);
504b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
505b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
506b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, OwnerThreadDeletesObject) {
507b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Originating thread invalidates WeakPtrs while its held by other thread.
508b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // - Main thread creates WeakPtr and passes Copy to background thread
509b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // - Object gets destroyed on main thread
510b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  //   (invalidates WeakPtr on background thread)
511b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // - WeakPtr gets destroyed on Thread B
512b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  BackgroundThread background;
513b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.Start();
514b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Arrow* arrow_copy;
515b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
516b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    Target target;
517b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    Arrow arrow;
518b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    arrow.target = target.AsWeakPtr();
519b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    background.CreateArrowFromArrow(&arrow_copy, &arrow);
520b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
52194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez  EXPECT_EQ(nullptr, arrow_copy->target.get());
522b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.DeleteArrow(arrow_copy);
523b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
524b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
525b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtr) {
526b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Main thread creates a Target object.
527b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Target target;
528b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Main thread creates an arrow referencing the Target.
529b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Arrow *arrow = new Arrow();
530b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  arrow->target = target.AsWeakPtr();
531b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
532b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Background can copy and assign arrow (as well as the WeakPtr inside).
533b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  BackgroundThread background;
534b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.Start();
535b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.CopyAndAssignArrow(arrow);
536b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.DeleteArrow(arrow);
537b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
538b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
539b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtrBase) {
540b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Main thread creates a Target object.
541b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Target target;
542b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Main thread creates an arrow referencing the Target.
543b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Arrow *arrow = new Arrow();
544b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  arrow->target = target.AsWeakPtr();
545b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
546b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Background can copy and assign arrow's WeakPtr to a base class WeakPtr.
547b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  BackgroundThread background;
548b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.Start();
549b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.CopyAndAssignArrowBase(arrow);
550b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.DeleteArrow(arrow);
551b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
552b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
553b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, NonOwnerThreadCanDeleteWeakPtr) {
554b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Main thread creates a Target object.
555b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Target target;
556b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Main thread creates an arrow referencing the Target.
557b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Arrow* arrow = new Arrow();
558b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  arrow->target = target.AsWeakPtr();
559b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
560b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Background can delete arrow (as well as the WeakPtr inside).
561b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  BackgroundThread background;
562b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.Start();
563b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.DeleteArrow(arrow);
564b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
565b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
566b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && GTEST_HAS_DEATH_TEST
567b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
568b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrDeathTest, WeakPtrCopyDoesNotChangeThreadBinding) {
569b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // The default style "fast" does not support multi-threaded tests
570b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // (introduces deadlock on Linux).
571b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
572b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
573b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  BackgroundThread background;
574b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.Start();
575b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
576b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Main thread creates a Target object.
577b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Target target;
578b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Main thread creates an arrow referencing the Target.
579b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Arrow arrow;
580b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  arrow.target = target.AsWeakPtr();
581b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
582b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Background copies the WeakPtr.
583b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Arrow* arrow_copy;
584b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.CreateArrowFromArrow(&arrow_copy, &arrow);
585b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
586b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // The copy is still bound to main thread so I can deref.
587b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_EQ(arrow.target.get(), arrow_copy->target.get());
588b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
589b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Although background thread created the copy, it can not deref the copied
590b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // WeakPtr.
591b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ASSERT_DEATH(background.DeRef(arrow_copy), "");
592b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
593b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.DeleteArrow(arrow_copy);
594b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
595b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
596b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrDeathTest, NonOwnerThreadDereferencesWeakPtrAfterReference) {
597b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // The default style "fast" does not support multi-threaded tests
598b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // (introduces deadlock on Linux).
599b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
600b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
601b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Main thread creates a Target object.
602b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Target target;
603b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
604b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Main thread creates an arrow referencing the Target (so target's
605b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // thread ownership can not be implicitly moved).
606b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Arrow arrow;
607b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  arrow.target = target.AsWeakPtr();
608b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  arrow.target.get();
609b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
610b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Background thread tries to deref target, which violates thread ownership.
611b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  BackgroundThread background;
612b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.Start();
613b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ASSERT_DEATH(background.DeRef(&arrow), "");
614b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
615b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
616b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrDeathTest, NonOwnerThreadDeletesWeakPtrAfterReference) {
617b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // The default style "fast" does not support multi-threaded tests
618b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // (introduces deadlock on Linux).
619b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
620b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
62194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez  std::unique_ptr<Target> target(new Target());
622b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
623b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Main thread creates an arrow referencing the Target.
624b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Arrow arrow;
625b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  arrow.target = target->AsWeakPtr();
626b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
627b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Background thread tries to deref target, binding it to the thread.
628b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  BackgroundThread background;
629b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.Start();
630b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.DeRef(&arrow);
631b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
632b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Main thread deletes Target, violating thread binding.
633b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ASSERT_DEATH(target.reset(), "");
634b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
635b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // |target.reset()| died so |target| still holds the object, so we
636b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // must pass it to the background thread to teardown.
637b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.DeleteTarget(target.release());
638b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
639b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
640b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrDeathTest, NonOwnerThreadDeletesObjectAfterReference) {
641b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // The default style "fast" does not support multi-threaded tests
642b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // (introduces deadlock on Linux).
643b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
644b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
64594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez  std::unique_ptr<Target> target(new Target());
646b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
647b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Main thread creates an arrow referencing the Target, and references it, so
648b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // that it becomes bound to the thread.
649b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Arrow arrow;
650b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  arrow.target = target->AsWeakPtr();
651b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  arrow.target.get();
652b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
653b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Background thread tries to delete target, volating thread binding.
654b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  BackgroundThread background;
655b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.Start();
656b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ASSERT_DEATH(background.DeleteTarget(target.release()), "");
657b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
658b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
659b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrDeathTest, NonOwnerThreadReferencesObjectAfterDeletion) {
660b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // The default style "fast" does not support multi-threaded tests
661b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // (introduces deadlock on Linux).
662b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
663b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
66494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez  std::unique_ptr<Target> target(new Target());
665b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
666b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Main thread creates an arrow referencing the Target.
667b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Arrow arrow;
668b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  arrow.target = target->AsWeakPtr();
669b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
670b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Background thread tries to delete target, binding the object to the thread.
671b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  BackgroundThread background;
672b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.Start();
673b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  background.DeleteTarget(target.release());
674b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
675b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Main thread attempts to dereference the target, violating thread binding.
676b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ASSERT_DEATH(arrow.target.get(), "");
677b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
678b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
679b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif
680b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
681b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}  // namespace base
682