blob: dbe7960e28c43a58d5f349831e0575d5457f09b9 [file] [log] [blame]
[email protected]7f18b7c42012-02-24 09:13:091// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]3125d6462009-09-01 20:50:172// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]4c44b8442012-06-15 16:36:125#include "base/memory/weak_ptr.h"
6
7#include <string>
8
[email protected]8f5a7e492012-01-01 02:14:479#include "base/bind.h"
[email protected]3b63f8f42011-03-28 01:54:1510#include "base/memory/scoped_ptr.h"
[email protected]d9b14782010-04-15 08:08:0711#include "base/message_loop.h"
[email protected]1edefc42011-08-26 17:32:2912#include "base/synchronization/waitable_event.h"
[email protected]34b99632011-01-01 01:01:0613#include "base/threading/thread.h"
[email protected]4c44b8442012-06-15 16:36:1214#include "testing/gtest/include/gtest/gtest.h"
[email protected]3125d6462009-09-01 20:50:1715
16namespace base {
17namespace {
18
19template <class T>
20class OffThreadObjectCreator {
21 public:
22 static T* NewObject() {
23 T* result;
24 {
25 Thread creator_thread("creator_thread");
26 creator_thread.Start();
[email protected]0586b0e2010-02-12 21:38:3727 creator_thread.message_loop()->PostTask(
28 FROM_HERE,
[email protected]8f5a7e492012-01-01 02:14:4729 base::Bind(OffThreadObjectCreator::CreateObject, &result));
[email protected]3125d6462009-09-01 20:50:1730 }
31 DCHECK(result); // We synchronized on thread destruction above.
32 return result;
33 }
34 private:
35 static void CreateObject(T** result) {
36 *result = new T;
37 }
38};
39
[email protected]5d6688f2012-07-11 21:39:0340struct Base {
41 std::string member;
42};
[email protected]c33acdb2013-03-02 02:31:4543struct Derived : public Base {};
[email protected]3125d6462009-09-01 20:50:1744
[email protected]c33acdb2013-03-02 02:31:4545struct TargetBase {};
46struct Target : public TargetBase, public SupportsWeakPtr<Target> {};
47struct DerivedTarget : public Target {};
[email protected]5d6688f2012-07-11 21:39:0348struct Arrow {
49 WeakPtr<Target> target;
50};
[email protected]3125d6462009-09-01 20:50:1751
[email protected]1edefc42011-08-26 17:32:2952// Helper class to create and destroy weak pointer copies
53// and delete objects on a background thread.
54class BackgroundThread : public Thread {
55 public:
[email protected]44106182012-04-06 03:53:0256 BackgroundThread() : Thread("owner_thread") {}
[email protected]1edefc42011-08-26 17:32:2957
[email protected]44106182012-04-06 03:53:0258 virtual ~BackgroundThread() {
[email protected]d583c3a2011-11-02 15:31:5659 Stop();
60 }
61
[email protected]5d6688f2012-07-11 21:39:0362 void CreateArrowFromTarget(Arrow** arrow, Target* target) {
[email protected]1edefc42011-08-26 17:32:2963 WaitableEvent completion(true, false);
64 message_loop()->PostTask(
65 FROM_HERE,
[email protected]5d6688f2012-07-11 21:39:0366 base::Bind(&BackgroundThread::DoCreateArrowFromTarget,
67 arrow, target, &completion));
[email protected]1edefc42011-08-26 17:32:2968 completion.Wait();
69 }
70
[email protected]5d6688f2012-07-11 21:39:0371 void CreateArrowFromArrow(Arrow** arrow, const Arrow* other) {
[email protected]1edefc42011-08-26 17:32:2972 WaitableEvent completion(true, false);
73 message_loop()->PostTask(
74 FROM_HERE,
[email protected]5d6688f2012-07-11 21:39:0375 base::Bind(&BackgroundThread::DoCreateArrowFromArrow,
76 arrow, other, &completion));
[email protected]1edefc42011-08-26 17:32:2977 completion.Wait();
78 }
79
[email protected]5d6688f2012-07-11 21:39:0380 void DeleteTarget(Target* object) {
[email protected]1edefc42011-08-26 17:32:2981 WaitableEvent completion(true, false);
82 message_loop()->PostTask(
83 FROM_HERE,
[email protected]5d6688f2012-07-11 21:39:0384 base::Bind(&BackgroundThread::DoDeleteTarget, object, &completion));
[email protected]1edefc42011-08-26 17:32:2985 completion.Wait();
86 }
87
[email protected]c33acdb2013-03-02 02:31:4588 void CopyAndAssignArrow(Arrow* object) {
89 WaitableEvent completion(true, false);
90 message_loop()->PostTask(
91 FROM_HERE,
92 base::Bind(&BackgroundThread::DoCopyAndAssignArrow,
93 object, &completion));
94 completion.Wait();
95 }
96
97 void CopyAndAssignArrowBase(Arrow* object) {
98 WaitableEvent completion(true, false);
99 message_loop()->PostTask(
100 FROM_HERE,
101 base::Bind(&BackgroundThread::DoCopyAndAssignArrowBase,
102 object, &completion));
103 completion.Wait();
104 }
105
[email protected]5d6688f2012-07-11 21:39:03106 void DeleteArrow(Arrow* object) {
[email protected]1edefc42011-08-26 17:32:29107 WaitableEvent completion(true, false);
108 message_loop()->PostTask(
109 FROM_HERE,
[email protected]5d6688f2012-07-11 21:39:03110 base::Bind(&BackgroundThread::DoDeleteArrow, object, &completion));
[email protected]1edefc42011-08-26 17:32:29111 completion.Wait();
112 }
113
[email protected]5d6688f2012-07-11 21:39:03114 Target* DeRef(const Arrow* arrow) {
[email protected]1edefc42011-08-26 17:32:29115 WaitableEvent completion(true, false);
[email protected]5d6688f2012-07-11 21:39:03116 Target* result = NULL;
[email protected]1edefc42011-08-26 17:32:29117 message_loop()->PostTask(
118 FROM_HERE,
[email protected]5d6688f2012-07-11 21:39:03119 base::Bind(&BackgroundThread::DoDeRef, arrow, &result, &completion));
[email protected]1edefc42011-08-26 17:32:29120 completion.Wait();
121 return result;
122 }
123
124 protected:
[email protected]5d6688f2012-07-11 21:39:03125 static void DoCreateArrowFromArrow(Arrow** arrow,
126 const Arrow* other,
127 WaitableEvent* completion) {
128 *arrow = new Arrow;
129 **arrow = *other;
[email protected]1edefc42011-08-26 17:32:29130 completion->Signal();
131 }
132
[email protected]5d6688f2012-07-11 21:39:03133 static void DoCreateArrowFromTarget(Arrow** arrow,
134 Target* target,
135 WaitableEvent* completion) {
136 *arrow = new Arrow;
137 (*arrow)->target = target->AsWeakPtr();
[email protected]1edefc42011-08-26 17:32:29138 completion->Signal();
139 }
140
[email protected]5d6688f2012-07-11 21:39:03141 static void DoDeRef(const Arrow* arrow,
142 Target** result,
[email protected]1edefc42011-08-26 17:32:29143 WaitableEvent* completion) {
[email protected]5d6688f2012-07-11 21:39:03144 *result = arrow->target.get();
[email protected]1edefc42011-08-26 17:32:29145 completion->Signal();
146 }
147
[email protected]5d6688f2012-07-11 21:39:03148 static void DoDeleteTarget(Target* object, WaitableEvent* completion) {
[email protected]1edefc42011-08-26 17:32:29149 delete object;
150 completion->Signal();
151 }
152
[email protected]c33acdb2013-03-02 02:31:45153 static void DoCopyAndAssignArrow(Arrow* object, WaitableEvent* completion) {
154 // Copy constructor.
155 Arrow a = *object;
156 // Assignment operator.
157 *object = a;
158 completion->Signal();
159 }
160
161 static void DoCopyAndAssignArrowBase(
162 Arrow* object,
163 WaitableEvent* completion) {
164 // Copy constructor.
165 WeakPtr<TargetBase> b = object->target;
166 // Assignment operator.
167 WeakPtr<TargetBase> c;
168 c = object->target;
169 completion->Signal();
170 }
171
[email protected]5d6688f2012-07-11 21:39:03172 static void DoDeleteArrow(Arrow* object, WaitableEvent* completion) {
[email protected]1edefc42011-08-26 17:32:29173 delete object;
174 completion->Signal();
175 }
176};
177
[email protected]3125d6462009-09-01 20:50:17178} // namespace
179
[email protected]5d6688f2012-07-11 21:39:03180TEST(WeakPtrFactoryTest, Basic) {
[email protected]3125d6462009-09-01 20:50:17181 int data;
182 WeakPtrFactory<int> factory(&data);
183 WeakPtr<int> ptr = factory.GetWeakPtr();
184 EXPECT_EQ(&data, ptr.get());
185}
186
[email protected]5d6688f2012-07-11 21:39:03187TEST(WeakPtrFactoryTest, Comparison) {
[email protected]3125d6462009-09-01 20:50:17188 int data;
189 WeakPtrFactory<int> factory(&data);
190 WeakPtr<int> ptr = factory.GetWeakPtr();
191 WeakPtr<int> ptr2 = ptr;
[email protected]5d6688f2012-07-11 21:39:03192 EXPECT_EQ(ptr, ptr2);
[email protected]3125d6462009-09-01 20:50:17193}
194
[email protected]5d6688f2012-07-11 21:39:03195TEST(WeakPtrFactoryTest, OutOfScope) {
[email protected]3125d6462009-09-01 20:50:17196 WeakPtr<int> ptr;
[email protected]5d6688f2012-07-11 21:39:03197 EXPECT_EQ(NULL, ptr.get());
[email protected]3125d6462009-09-01 20:50:17198 {
199 int data;
200 WeakPtrFactory<int> factory(&data);
201 ptr = factory.GetWeakPtr();
202 }
[email protected]5d6688f2012-07-11 21:39:03203 EXPECT_EQ(NULL, ptr.get());
[email protected]3125d6462009-09-01 20:50:17204}
205
[email protected]5d6688f2012-07-11 21:39:03206TEST(WeakPtrFactoryTest, Multiple) {
[email protected]3125d6462009-09-01 20:50:17207 WeakPtr<int> a, b;
208 {
209 int data;
210 WeakPtrFactory<int> factory(&data);
211 a = factory.GetWeakPtr();
212 b = factory.GetWeakPtr();
213 EXPECT_EQ(&data, a.get());
214 EXPECT_EQ(&data, b.get());
215 }
[email protected]5d6688f2012-07-11 21:39:03216 EXPECT_EQ(NULL, a.get());
217 EXPECT_EQ(NULL, b.get());
[email protected]3125d6462009-09-01 20:50:17218}
219
[email protected]5d6688f2012-07-11 21:39:03220TEST(WeakPtrFactoryTest, MultipleStaged) {
[email protected]09733b452011-05-24 23:49:07221 WeakPtr<int> a;
222 {
223 int data;
224 WeakPtrFactory<int> factory(&data);
225 a = factory.GetWeakPtr();
226 {
227 WeakPtr<int> b = factory.GetWeakPtr();
228 }
[email protected]5d6688f2012-07-11 21:39:03229 EXPECT_TRUE(NULL != a.get());
[email protected]09733b452011-05-24 23:49:07230 }
[email protected]5d6688f2012-07-11 21:39:03231 EXPECT_EQ(NULL, a.get());
[email protected]09733b452011-05-24 23:49:07232}
233
[email protected]5d6688f2012-07-11 21:39:03234TEST(WeakPtrFactoryTest, Dereference) {
235 Base data;
236 data.member = "123456";
237 WeakPtrFactory<Base> factory(&data);
238 WeakPtr<Base> ptr = factory.GetWeakPtr();
239 EXPECT_EQ(&data, ptr.get());
240 EXPECT_EQ(data.member, (*ptr).member);
241 EXPECT_EQ(data.member, ptr->member);
242}
243
244TEST(WeakPtrFactoryTest, UpCast) {
[email protected]3125d6462009-09-01 20:50:17245 Derived data;
246 WeakPtrFactory<Derived> factory(&data);
247 WeakPtr<Base> ptr = factory.GetWeakPtr();
248 ptr = factory.GetWeakPtr();
249 EXPECT_EQ(ptr.get(), &data);
250}
251
252TEST(WeakPtrTest, SupportsWeakPtr) {
[email protected]5d6688f2012-07-11 21:39:03253 Target target;
254 WeakPtr<Target> ptr = target.AsWeakPtr();
255 EXPECT_EQ(&target, ptr.get());
[email protected]3125d6462009-09-01 20:50:17256}
257
[email protected]5d6688f2012-07-11 21:39:03258TEST(WeakPtrTest, DerivedTarget) {
259 DerivedTarget target;
260 WeakPtr<DerivedTarget> ptr = AsWeakPtr(&target);
261 EXPECT_EQ(&target, ptr.get());
[email protected]4c44b8442012-06-15 16:36:12262}
263
[email protected]3125d6462009-09-01 20:50:17264TEST(WeakPtrTest, InvalidateWeakPtrs) {
265 int data;
266 WeakPtrFactory<int> factory(&data);
267 WeakPtr<int> ptr = factory.GetWeakPtr();
268 EXPECT_EQ(&data, ptr.get());
[email protected]59326aac2009-09-25 23:34:34269 EXPECT_TRUE(factory.HasWeakPtrs());
[email protected]3125d6462009-09-01 20:50:17270 factory.InvalidateWeakPtrs();
[email protected]5d6688f2012-07-11 21:39:03271 EXPECT_EQ(NULL, ptr.get());
[email protected]59326aac2009-09-25 23:34:34272 EXPECT_FALSE(factory.HasWeakPtrs());
273}
274
275TEST(WeakPtrTest, HasWeakPtrs) {
276 int data;
277 WeakPtrFactory<int> factory(&data);
278 {
279 WeakPtr<int> ptr = factory.GetWeakPtr();
280 EXPECT_TRUE(factory.HasWeakPtrs());
281 }
282 EXPECT_FALSE(factory.HasWeakPtrs());
[email protected]3125d6462009-09-01 20:50:17283}
284
[email protected]5d6688f2012-07-11 21:39:03285TEST(WeakPtrTest, ObjectAndWeakPtrOnDifferentThreads) {
286 // Test that it is OK to create an object that supports WeakPtr on one thread,
287 // but use it on another. This tests that we do not trip runtime checks that
288 // ensure that a WeakPtr is not used by multiple threads.
289 scoped_ptr<Target> target(OffThreadObjectCreator<Target>::NewObject());
290 WeakPtr<Target> weak_ptr = target->AsWeakPtr();
291 EXPECT_EQ(target.get(), weak_ptr.get());
[email protected]3125d6462009-09-01 20:50:17292}
293
[email protected]5d6688f2012-07-11 21:39:03294TEST(WeakPtrTest, WeakPtrInitiateAndUseOnDifferentThreads) {
295 // Test that it is OK to create an object that has a WeakPtr member on one
[email protected]856581a2012-07-04 01:02:14296 // thread, but use it on another. This tests that we do not trip runtime
[email protected]5d6688f2012-07-11 21:39:03297 // checks that ensure that a WeakPtr is not used by multiple threads.
298 scoped_ptr<Arrow> arrow(OffThreadObjectCreator<Arrow>::NewObject());
299 Target target;
300 arrow->target = target.AsWeakPtr();
301 EXPECT_EQ(&target, arrow->target.get());
[email protected]856581a2012-07-04 01:02:14302}
303
[email protected]5d6688f2012-07-11 21:39:03304TEST(WeakPtrTest, MoveOwnershipImplicitly) {
305 // Move object ownership to another thread by releasing all weak pointers
306 // on the original thread first, and then establish WeakPtr on a different
307 // thread.
308 BackgroundThread background;
309 background.Start();
310
311 Target* target = new Target();
[email protected]1edefc42011-08-26 17:32:29312 {
[email protected]5d6688f2012-07-11 21:39:03313 WeakPtr<Target> weak_ptr = target->AsWeakPtr();
314 // Main thread deletes the WeakPtr, then the thread ownership of the
315 // object can be implicitly moved.
[email protected]1edefc42011-08-26 17:32:29316 }
[email protected]5d6688f2012-07-11 21:39:03317 Arrow* arrow;
318
319 // Background thread creates WeakPtr(and implicitly owns the object).
320 background.CreateArrowFromTarget(&arrow, target);
321 EXPECT_EQ(background.DeRef(arrow), target);
322
323 {
324 // Main thread creates another WeakPtr, but this does not trigger implicitly
325 // thread ownership move.
326 Arrow arrow;
327 arrow.target = target->AsWeakPtr();
328
329 // The new WeakPtr is owned by background thread.
330 EXPECT_EQ(target, background.DeRef(&arrow));
331 }
332
333 // Target can only be deleted on background thread.
334 background.DeleteTarget(target);
335 background.DeleteArrow(arrow);
[email protected]1edefc42011-08-26 17:32:29336}
337
[email protected]5d6688f2012-07-11 21:39:03338TEST(WeakPtrTest, MoveOwnershipExplicitlyObjectNotReferenced) {
339 // Case 1: The target is not bound to any thread yet. So calling
340 // DetachFromThread() is a no-op.
341 Target target;
342 target.DetachFromThread();
343
344 // Case 2: The target is bound to main thread but no WeakPtr is pointing to
345 // it. In this case, it will be re-bound to any thread trying to get a
346 // WeakPtr pointing to it. So detach function call is again no-op.
347 {
348 WeakPtr<Target> weak_ptr = target.AsWeakPtr();
349 }
350 target.DetachFromThread();
[email protected]1edefc42011-08-26 17:32:29351}
352
[email protected]5d6688f2012-07-11 21:39:03353TEST(WeakPtrTest, MoveOwnershipExplicitly) {
354 BackgroundThread background;
355 background.Start();
356
357 Arrow* arrow;
358 {
359 Target target;
360 // Background thread creates WeakPtr(and implicitly owns the object).
361 background.CreateArrowFromTarget(&arrow, &target);
362 EXPECT_EQ(&target, background.DeRef(arrow));
363
364 // Detach from background thread.
365 target.DetachFromThread();
366
367 // Re-bind to main thread.
368 EXPECT_EQ(&target, arrow->target.get());
369
370 // Main thread can now delete the target.
371 }
372
373 // WeakPtr can be deleted on non-owner thread.
374 background.DeleteArrow(arrow);
375}
376
377TEST(WeakPtrTest, MainThreadRefOutlivesBackgroundThreadRef) {
[email protected]1edefc42011-08-26 17:32:29378 // Originating thread has a WeakPtr that outlives others.
[email protected]5d6688f2012-07-11 21:39:03379 // - Main thread creates a WeakPtr
380 // - Background thread creates a WeakPtr copy from the one in main thread
381 // - Destruct the WeakPtr on background thread
382 // - Destruct the WeakPtr on main thread
383 BackgroundThread background;
384 background.Start();
385
386 Target target;
387 Arrow arrow;
388 arrow.target = target.AsWeakPtr();
389
390 Arrow* arrow_copy;
391 background.CreateArrowFromArrow(&arrow_copy, &arrow);
392 EXPECT_EQ(arrow_copy->target, &target);
393 background.DeleteArrow(arrow_copy);
[email protected]1edefc42011-08-26 17:32:29394}
395
[email protected]5d6688f2012-07-11 21:39:03396TEST(WeakPtrTest, BackgroundThreadRefOutlivesMainThreadRef) {
[email protected]1edefc42011-08-26 17:32:29397 // Originating thread drops all references before another thread.
[email protected]5d6688f2012-07-11 21:39:03398 // - Main thread creates a WeakPtr and passes copy to background thread
399 // - Destruct the pointer on main thread
400 // - Destruct the pointer on background thread
401 BackgroundThread background;
402 background.Start();
403
404 Target target;
405 Arrow* arrow_copy;
[email protected]1edefc42011-08-26 17:32:29406 {
[email protected]5d6688f2012-07-11 21:39:03407 Arrow arrow;
408 arrow.target = target.AsWeakPtr();
409 background.CreateArrowFromArrow(&arrow_copy, &arrow);
[email protected]1edefc42011-08-26 17:32:29410 }
[email protected]5d6688f2012-07-11 21:39:03411 EXPECT_EQ(arrow_copy->target, &target);
412 background.DeleteArrow(arrow_copy);
[email protected]1edefc42011-08-26 17:32:29413}
414
415TEST(WeakPtrTest, OwnerThreadDeletesObject) {
416 // Originating thread invalidates WeakPtrs while its held by other thread.
[email protected]5d6688f2012-07-11 21:39:03417 // - Main thread creates WeakPtr and passes Copy to background thread
418 // - Object gets destroyed on main thread
419 // (invalidates WeakPtr on background thread)
[email protected]1edefc42011-08-26 17:32:29420 // - WeakPtr gets destroyed on Thread B
[email protected]5d6688f2012-07-11 21:39:03421 BackgroundThread background;
422 background.Start();
423 Arrow* arrow_copy;
[email protected]1edefc42011-08-26 17:32:29424 {
[email protected]5d6688f2012-07-11 21:39:03425 Target target;
426 Arrow arrow;
427 arrow.target = target.AsWeakPtr();
428 background.CreateArrowFromArrow(&arrow_copy, &arrow);
[email protected]1edefc42011-08-26 17:32:29429 }
[email protected]5d6688f2012-07-11 21:39:03430 EXPECT_EQ(NULL, arrow_copy->target.get());
431 background.DeleteArrow(arrow_copy);
[email protected]1edefc42011-08-26 17:32:29432}
433
[email protected]c33acdb2013-03-02 02:31:45434TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtr) {
435 // Main thread creates a Target object.
436 Target target;
437 // Main thread creates an arrow referencing the Target.
438 Arrow* arrow = new Arrow();
439 arrow->target = target.AsWeakPtr();
440
441 // Background can copy and assign arrow (as well as the WeakPtr inside).
442 BackgroundThread background;
443 background.Start();
444 background.CopyAndAssignArrow(arrow);
445}
446
447TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtrBase) {
448 // Main thread creates a Target object.
449 Target target;
450 // Main thread creates an arrow referencing the Target.
451 Arrow* arrow = new Arrow();
452 arrow->target = target.AsWeakPtr();
453
454 // Background can copy and assign arrow's WeakPtr to a base class WeakPtr.
455 BackgroundThread background;
456 background.Start();
457 background.CopyAndAssignArrowBase(arrow);
458}
459
[email protected]5d6688f2012-07-11 21:39:03460TEST(WeakPtrTest, NonOwnerThreadCanDeleteWeakPtr) {
461 // Main thread creates a Target object.
462 Target target;
463 // Main thread creates an arrow referencing the Target.
464 Arrow* arrow = new Arrow();
465 arrow->target = target.AsWeakPtr();
466
467 // Background can delete arrow (as well as the WeakPtr inside).
468 BackgroundThread background;
469 background.Start();
470 background.DeleteArrow(arrow);
[email protected]7f18b7c42012-02-24 09:13:09471}
472
[email protected]5d6688f2012-07-11 21:39:03473#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && GTEST_HAS_DEATH_TEST
474
475TEST(WeakPtrDeathTest, WeakPtrCopyDoesNotChangeThreadBinding) {
476 // The default style "fast" does not support multi-threaded tests
477 // (introduces deadlock on Linux).
478 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
479
480 BackgroundThread background;
481 background.Start();
482
483 // Main thread creates a Target object.
484 Target target;
485 // Main thread creates an arrow referencing the Target.
486 Arrow arrow;
487 arrow.target = target.AsWeakPtr();
488
489 // Background copies the WeakPtr.
490 Arrow* arrow_copy;
491 background.CreateArrowFromArrow(&arrow_copy, &arrow);
492
493 // The copy is still bound to main thread so I can deref.
494 EXPECT_EQ(arrow.target.get(), arrow_copy->target.get());
495
496 // Although background thread created the copy, it can not deref the copied
497 // WeakPtr.
498 ASSERT_DEATH(background.DeRef(arrow_copy), "");
499
500 background.DeleteArrow(arrow_copy);
501}
502
503TEST(WeakPtrDeathTest, NonOwnerThreadDereferencesWeakPtr) {
504 // The default style "fast" does not support multi-threaded tests
505 // (introduces deadlock on Linux).
506 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
507
508 // Main thread creates a Target object.
509 Target target;
510
511 // Main thread creates an arrow referencing the Target (so target's
512 // thread ownership can not be implicitly moved).
513 Arrow arrow;
514 arrow.target = target.AsWeakPtr();
515
516 // Background thread tries to deref target, which violates thread ownership.
517 BackgroundThread background;
518 background.Start();
519 ASSERT_DEATH(background.DeRef(&arrow), "");
520}
521
522TEST(WeakPtrDeathTest, NonOwnerThreadDeletesObject) {
523 // The default style "fast" does not support multi-threaded tests
524 // (introduces deadlock on Linux).
525 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
526
527 scoped_ptr<Target> target(new Target());
528 // Main thread creates an arrow referencing the Target (so target's thread
529 // ownership can not be implicitly moved).
530 Arrow arrow;
531 arrow.target = target->AsWeakPtr();
532
533 // Background thread tries to delete target, which violates thread ownership.
534 BackgroundThread background;
535 background.Start();
536 ASSERT_DEATH(background.DeleteTarget(target.release()), "");
537}
538
539#endif
540
[email protected]3125d6462009-09-01 20:50:17541} // namespace base