OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/memory/weak_ptr.h" | 5 #include "base/memory/weak_ptr.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
332 | 332 |
333 // Target can only be deleted on background thread. | 333 // Target can only be deleted on background thread. |
334 background.DeleteTarget(target); | 334 background.DeleteTarget(target); |
335 background.DeleteArrow(arrow); | 335 background.DeleteArrow(arrow); |
336 } | 336 } |
337 | 337 |
338 TEST(WeakPtrTest, MoveOwnershipExplicitlyObjectNotReferenced) { | 338 TEST(WeakPtrTest, MoveOwnershipExplicitlyObjectNotReferenced) { |
339 // Case 1: The target is not bound to any thread yet. So calling | 339 // Case 1: The target is not bound to any thread yet. So calling |
340 // DetachFromThread() is a no-op. | 340 // DetachFromThread() is a no-op. |
341 Target target; | 341 Target target; |
342 target.DetachFromThread(); | 342 target.DetachFromThreadHack(); |
343 | 343 |
344 // Case 2: The target is bound to main thread but no WeakPtr is pointing to | 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 | 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. | 346 // WeakPtr pointing to it. So detach function call is again no-op. |
347 { | 347 { |
348 WeakPtr<Target> weak_ptr = target.AsWeakPtr(); | 348 WeakPtr<Target> weak_ptr = target.AsWeakPtr(); |
349 } | 349 } |
350 target.DetachFromThread(); | 350 target.DetachFromThreadHack(); |
351 } | 351 } |
352 | 352 |
353 TEST(WeakPtrTest, MoveOwnershipExplicitly) { | 353 TEST(WeakPtrTest, MoveOwnershipExplicitly) { |
354 BackgroundThread background; | 354 BackgroundThread background; |
355 background.Start(); | 355 background.Start(); |
356 | 356 |
357 Arrow* arrow; | 357 Arrow* arrow; |
358 { | 358 { |
359 Target target; | 359 Target target; |
360 // Background thread creates WeakPtr(and implicitly owns the object). | 360 // Background thread creates WeakPtr(and implicitly owns the object). |
361 background.CreateArrowFromTarget(&arrow, &target); | 361 background.CreateArrowFromTarget(&arrow, &target); |
362 EXPECT_EQ(&target, background.DeRef(arrow)); | 362 EXPECT_EQ(&target, background.DeRef(arrow)); |
363 | 363 |
364 // Detach from background thread. | 364 // Detach from background thread. |
365 target.DetachFromThread(); | 365 target.DetachFromThreadHack(); |
366 | 366 |
367 // Re-bind to main thread. | 367 // Re-bind to main thread. |
368 EXPECT_EQ(&target, arrow->target.get()); | 368 EXPECT_EQ(&target, arrow->target.get()); |
369 | 369 |
370 // Main thread can now delete the target. | 370 // Main thread can now delete the target. |
371 } | 371 } |
372 | 372 |
373 // WeakPtr can be deleted on non-owner thread. | 373 // WeakPtr can be deleted on non-owner thread. |
374 background.DeleteArrow(arrow); | 374 background.DeleteArrow(arrow); |
375 } | 375 } |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
493 // The copy is still bound to main thread so I can deref. | 493 // The copy is still bound to main thread so I can deref. |
494 EXPECT_EQ(arrow.target.get(), arrow_copy->target.get()); | 494 EXPECT_EQ(arrow.target.get(), arrow_copy->target.get()); |
495 | 495 |
496 // Although background thread created the copy, it can not deref the copied | 496 // Although background thread created the copy, it can not deref the copied |
497 // WeakPtr. | 497 // WeakPtr. |
498 ASSERT_DEATH(background.DeRef(arrow_copy), ""); | 498 ASSERT_DEATH(background.DeRef(arrow_copy), ""); |
499 | 499 |
500 background.DeleteArrow(arrow_copy); | 500 background.DeleteArrow(arrow_copy); |
501 } | 501 } |
502 | 502 |
503 TEST(WeakPtrDeathTest, NonOwnerThreadDereferencesWeakPtr) { | 503 TEST(WeakPtrDeathTest, NonOwnerThreadDereferencesWeakPtrAfterReference) { |
504 // The default style "fast" does not support multi-threaded tests | 504 // The default style "fast" does not support multi-threaded tests |
505 // (introduces deadlock on Linux). | 505 // (introduces deadlock on Linux). |
506 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; | 506 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; |
507 | 507 |
508 // Main thread creates a Target object. | 508 // Main thread creates a Target object. |
509 Target target; | 509 Target target; |
510 | 510 |
511 // Main thread creates an arrow referencing the Target (so target's | 511 // Main thread creates an arrow referencing the Target (so target's |
512 // thread ownership can not be implicitly moved). | 512 // thread ownership can not be implicitly moved). |
513 Arrow arrow; | 513 Arrow arrow; |
514 arrow.target = target.AsWeakPtr(); | 514 arrow.target = target.AsWeakPtr(); |
515 arrow.target.get(); | |
515 | 516 |
516 // Background thread tries to deref target, which violates thread ownership. | 517 // Background thread tries to deref target, which violates thread ownership. |
517 BackgroundThread background; | 518 BackgroundThread background; |
518 background.Start(); | 519 background.Start(); |
519 ASSERT_DEATH(background.DeRef(&arrow), ""); | 520 ASSERT_DEATH(background.DeRef(&arrow), ""); |
520 } | 521 } |
521 | 522 |
522 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesObject) { | 523 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesWeakPtrAfterReference) { |
523 // The default style "fast" does not support multi-threaded tests | 524 // The default style "fast" does not support multi-threaded tests |
524 // (introduces deadlock on Linux). | 525 // (introduces deadlock on Linux). |
525 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; | 526 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; |
526 | 527 |
527 scoped_ptr<Target> target(new Target()); | 528 scoped_ptr<Target> target(new Target()); |
528 // Main thread creates an arrow referencing the Target (so target's thread | 529 |
529 // ownership can not be implicitly moved). | 530 // Main thread creates an arrow referencing the Target. |
530 Arrow arrow; | 531 Arrow arrow; |
531 arrow.target = target->AsWeakPtr(); | 532 arrow.target = target->AsWeakPtr(); |
532 | 533 |
533 // Background thread tries to delete target, which violates thread ownership. | 534 // Background thread tries to deref target, binding it to the thread. |
535 BackgroundThread background; | |
536 background.Start(); | |
537 background.DeRef(&arrow); | |
538 | |
539 // Main thread deletes Target, violating thread binding. | |
540 Target* foo = target.release(); | |
541 ASSERT_DEATH(delete foo, ""); | |
awong
2013/05/17 19:02:32
Should this death test bother matching for the log
Wez
2013/05/18 07:02:35
Done.
| |
542 } | |
543 | |
544 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesObjectAfterReference) { | |
545 // The default style "fast" does not support multi-threaded tests | |
546 // (introduces deadlock on Linux). | |
547 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; | |
548 | |
549 scoped_ptr<Target> target(new Target()); | |
550 | |
551 // Main thread creates an arrow referencing the Target, and references it, so | |
552 // that it becomes bound to the thread. | |
553 Arrow arrow; | |
554 arrow.target = target->AsWeakPtr(); | |
555 arrow.target.get(); | |
556 | |
557 // Background thread tries to delete target, volating thread binding. | |
534 BackgroundThread background; | 558 BackgroundThread background; |
535 background.Start(); | 559 background.Start(); |
536 ASSERT_DEATH(background.DeleteTarget(target.release()), ""); | 560 ASSERT_DEATH(background.DeleteTarget(target.release()), ""); |
537 } | 561 } |
538 | 562 |
563 TEST(WeakPtrDeathTest, NonOwnerThreadReferencesObjectAfterDeletion) { | |
564 // The default style "fast" does not support multi-threaded tests | |
565 // (introduces deadlock on Linux). | |
566 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; | |
567 | |
568 scoped_ptr<Target> target(new Target()); | |
569 | |
570 // Main thread creates an arrow referencing the Target. | |
571 Arrow arrow; | |
572 arrow.target = target->AsWeakPtr(); | |
573 | |
574 // Background thread tries to delete target, binding the object to the thread. | |
575 BackgroundThread background; | |
576 background.Start(); | |
577 background.DeleteTarget(target.release()); | |
578 | |
579 // Main thread attempts to dereference the target, violating thread binding. | |
580 ASSERT_DEATH(arrow.target.get(), ""); | |
581 } | |
582 | |
539 #endif | 583 #endif |
540 | 584 |
541 } // namespace base | 585 } // namespace base |
OLD | NEW |