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, ""); |
| 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 |