Chromium Code Reviews| 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/bind.h" | 5 #include "base/bind.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <utility> | 8 #include <utility> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "base/callback.h" | 11 #include "base/callback.h" |
| 12 #include "base/macros.h" | 12 #include "base/macros.h" |
| 13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 14 #include "base/memory/ref_counted.h" | 14 #include "base/memory/ref_counted.h" |
| 15 #include "base/memory/weak_ptr.h" | 15 #include "base/memory/weak_ptr.h" |
| 16 #include "base/test/gtest_util.h" | 16 #include "base/test/gtest_util.h" |
| 17 #include "build/build_config.h" | 17 #include "build/build_config.h" |
| 18 #include "testing/gmock/include/gmock/gmock.h" | 18 #include "testing/gmock/include/gmock/gmock.h" |
| 19 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
| 20 | 20 |
| 21 using ::testing::Mock; | 21 using ::testing::Mock; |
| 22 using ::testing::ByMove; | |
| 22 using ::testing::Return; | 23 using ::testing::Return; |
| 23 using ::testing::StrictMock; | 24 using ::testing::StrictMock; |
| 24 | 25 |
| 26 using base::internal::BindOneShot; | |
| 27 using base::internal::BindRepeating; | |
| 28 using base::internal::OneShotCallback; | |
| 29 using base::internal::RepeatingCallback; | |
| 30 using base::internal::OneShotClosure; | |
| 31 using base::internal::RepeatingClosure; | |
| 32 | |
| 25 namespace base { | 33 namespace base { |
| 26 namespace { | 34 namespace { |
| 27 | 35 |
| 28 class IncompleteType; | 36 class IncompleteType; |
| 29 | 37 |
| 30 class NoRef { | 38 class NoRef { |
| 31 public: | 39 public: |
| 32 NoRef() {} | 40 NoRef() {} |
| 33 | 41 |
| 34 MOCK_METHOD0(VoidMethod0, void()); | 42 MOCK_METHOD0(VoidMethod0, void()); |
| 35 MOCK_CONST_METHOD0(VoidConstMethod0, void()); | 43 MOCK_CONST_METHOD0(VoidConstMethod0, void()); |
| 36 | 44 |
| 37 MOCK_METHOD0(IntMethod0, int()); | 45 MOCK_METHOD0(IntMethod0, int()); |
| 38 MOCK_CONST_METHOD0(IntConstMethod0, int()); | 46 MOCK_CONST_METHOD0(IntConstMethod0, int()); |
| 39 | 47 |
| 48 MOCK_METHOD0(UniquePtrMethod0, std::unique_ptr<int>()); | |
| 49 | |
| 40 private: | 50 private: |
| 41 // Particularly important in this test to ensure no copies are made. | 51 // Particularly important in this test to ensure no copies are made. |
| 42 DISALLOW_COPY_AND_ASSIGN(NoRef); | 52 DISALLOW_COPY_AND_ASSIGN(NoRef); |
| 43 }; | 53 }; |
| 44 | 54 |
| 45 class HasRef : public NoRef { | 55 class HasRef : public NoRef { |
| 46 public: | 56 public: |
| 47 HasRef() {} | 57 HasRef() {} |
| 48 | 58 |
| 49 MOCK_CONST_METHOD0(AddRef, void()); | 59 MOCK_CONST_METHOD0(AddRef, void()); |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 333 StrictMock<NoRef> static_func_mock_; | 343 StrictMock<NoRef> static_func_mock_; |
| 334 | 344 |
| 335 // Used by the static functions to perform expectations. | 345 // Used by the static functions to perform expectations. |
| 336 static StrictMock<NoRef>* static_func_mock_ptr; | 346 static StrictMock<NoRef>* static_func_mock_ptr; |
| 337 | 347 |
| 338 private: | 348 private: |
| 339 DISALLOW_COPY_AND_ASSIGN(BindTest); | 349 DISALLOW_COPY_AND_ASSIGN(BindTest); |
| 340 }; | 350 }; |
| 341 | 351 |
| 342 StrictMock<NoRef>* BindTest::static_func_mock_ptr; | 352 StrictMock<NoRef>* BindTest::static_func_mock_ptr; |
| 353 StrictMock<NoRef>* g_func_mock_ptr; | |
| 354 | |
| 355 void VoidFunc0() { | |
| 356 g_func_mock_ptr->VoidMethod0(); | |
| 357 } | |
| 358 | |
| 359 int IntFunc0() { | |
| 360 return g_func_mock_ptr->IntMethod0(); | |
| 361 } | |
| 343 | 362 |
| 344 // Sanity check that we can instantiate a callback for each arity. | 363 // Sanity check that we can instantiate a callback for each arity. |
| 345 TEST_F(BindTest, ArityTest) { | 364 TEST_F(BindTest, ArityTest) { |
| 346 Callback<int()> c0 = Bind(&Sum, 32, 16, 8, 4, 2, 1); | 365 Callback<int()> c0 = Bind(&Sum, 32, 16, 8, 4, 2, 1); |
| 347 EXPECT_EQ(63, c0.Run()); | 366 EXPECT_EQ(63, c0.Run()); |
| 348 | 367 |
| 349 Callback<int(int)> c1 = Bind(&Sum, 32, 16, 8, 4, 2); | 368 Callback<int(int)> c1 = Bind(&Sum, 32, 16, 8, 4, 2); |
| 350 EXPECT_EQ(75, c1.Run(13)); | 369 EXPECT_EQ(75, c1.Run(13)); |
| 351 | 370 |
| 352 Callback<int(int,int)> c2 = Bind(&Sum, 32, 16, 8, 4); | 371 Callback<int(int,int)> c2 = Bind(&Sum, 32, 16, 8, 4); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 387 | 406 |
| 388 Callback<int()> c0 = Bind(c1, 1); | 407 Callback<int()> c0 = Bind(c1, 1); |
| 389 EXPECT_EQ(63, c0.Run()); | 408 EXPECT_EQ(63, c0.Run()); |
| 390 } | 409 } |
| 391 | 410 |
| 392 // Test that currying the rvalue result of another Bind() works correctly. | 411 // Test that currying the rvalue result of another Bind() works correctly. |
| 393 // - rvalue should be usable as argument to Bind(). | 412 // - rvalue should be usable as argument to Bind(). |
| 394 // - multiple runs of resulting Callback remain valid. | 413 // - multiple runs of resulting Callback remain valid. |
| 395 TEST_F(BindTest, CurryingRvalueResultOfBind) { | 414 TEST_F(BindTest, CurryingRvalueResultOfBind) { |
| 396 int n = 0; | 415 int n = 0; |
| 397 Closure cb = base::Bind(&TakesACallback, base::Bind(&PtrArgSet, &n)); | 416 RepeatingClosure cb = BindRepeating(&TakesACallback, |
|
dcheng
2016/08/23 05:25:38
I guess this change now depends on the OneShotCall
tzik
2016/08/23 07:01:09
There was only one caller of Unwrap before the One
| |
| 417 BindRepeating(&PtrArgSet, &n)); | |
| 398 | 418 |
| 399 // If we implement Bind() such that the return value has auto_ptr-like | 419 // If we implement Bind() such that the return value has auto_ptr-like |
| 400 // semantics, the second call here will fail because ownership of | 420 // semantics, the second call here will fail because ownership of |
| 401 // the internal BindState<> would have been transfered to a *temporary* | 421 // the internal BindState<> would have been transfered to a *temporary* |
| 402 // constructon of a Callback object on the first call. | 422 // constructon of a Callback object on the first call. |
| 403 cb.Run(); | 423 cb.Run(); |
| 404 EXPECT_EQ(2, n); | 424 EXPECT_EQ(2, n); |
| 405 | 425 |
| 406 n = 0; | 426 n = 0; |
| 407 cb.Run(); | 427 cb.Run(); |
| 408 EXPECT_EQ(2, n); | 428 EXPECT_EQ(2, n); |
| 409 } | 429 } |
| 410 | 430 |
| 411 // Function type support. | 431 TEST_F(BindTest, RepeatingCallbackBasicTest) { |
| 412 // - Normal function. | 432 RepeatingCallback<int(int)> c0 = BindRepeating(&Sum, 1, 2, 4, 8, 16); |
| 413 // - Normal function bound with non-refcounted first argument. | |
| 414 // - Method bound to non-const object. | |
| 415 // - Method bound to scoped_refptr. | |
| 416 // - Const method bound to non-const object. | |
| 417 // - Const method bound to const object. | |
| 418 // - Derived classes can be used with pointers to non-virtual base functions. | |
| 419 // - Derived classes can be used with pointers to virtual base functions (and | |
| 420 // preserve virtual dispatch). | |
| 421 TEST_F(BindTest, FunctionTypeSupport) { | |
| 422 EXPECT_CALL(static_func_mock_, VoidMethod0()); | |
| 423 EXPECT_CALL(has_ref_, AddRef()).Times(4); | |
| 424 EXPECT_CALL(has_ref_, Release()).Times(4); | |
| 425 EXPECT_CALL(has_ref_, VoidMethod0()).Times(2); | |
| 426 EXPECT_CALL(has_ref_, VoidConstMethod0()).Times(2); | |
| 427 | 433 |
| 428 Closure normal_cb = Bind(&VoidFunc0); | 434 // RepeatingCallback can run via a lvalue-reference. |
| 429 Callback<NoRef*()> normal_non_refcounted_cb = | 435 EXPECT_EQ(63, c0.Run(32)); |
| 430 Bind(&PolymorphicIdentity<NoRef*>, &no_ref_); | |
| 431 normal_cb.Run(); | |
| 432 EXPECT_EQ(&no_ref_, normal_non_refcounted_cb.Run()); | |
| 433 | 436 |
| 434 Closure method_cb = Bind(&HasRef::VoidMethod0, &has_ref_); | 437 // It is valid to call a RepeatingCallback more than once. |
| 435 Closure method_refptr_cb = Bind(&HasRef::VoidMethod0, | 438 EXPECT_EQ(54, c0.Run(23)); |
| 436 make_scoped_refptr(&has_ref_)); | |
| 437 Closure const_method_nonconst_obj_cb = Bind(&HasRef::VoidConstMethod0, | |
| 438 &has_ref_); | |
| 439 Closure const_method_const_obj_cb = Bind(&HasRef::VoidConstMethod0, | |
| 440 const_has_ref_ptr_); | |
| 441 method_cb.Run(); | |
| 442 method_refptr_cb.Run(); | |
| 443 const_method_nonconst_obj_cb.Run(); | |
| 444 const_method_const_obj_cb.Run(); | |
| 445 | 439 |
| 446 Child child; | 440 // BindRepeating can handle a RepeatingCallback as the target functor. |
| 447 child.value = 0; | 441 RepeatingCallback<int()> c1 = BindRepeating(c0, 11); |
| 448 Closure virtual_set_cb = Bind(&Parent::VirtualSet, &child); | |
| 449 virtual_set_cb.Run(); | |
| 450 EXPECT_EQ(kChildValue, child.value); | |
| 451 | 442 |
| 452 child.value = 0; | 443 // RepeatingCallback can run via a rvalue-referenc. |
| 453 Closure non_virtual_set_cb = Bind(&Parent::NonVirtualSet, &child); | 444 EXPECT_EQ(42, std::move(c1).Run()); |
| 454 non_virtual_set_cb.Run(); | 445 |
| 455 EXPECT_EQ(kParentValue, child.value); | 446 // BindRepeating can handle a rvalue-reference of RepeatingCallback. |
| 447 EXPECT_EQ(32, BindRepeating(std::move(c0), 1).Run()); | |
| 456 } | 448 } |
| 457 | 449 |
| 458 // Return value support. | 450 TEST_F(BindTest, OneShotCallbackBasicTest) { |
| 459 // - Function with return value. | 451 OneShotCallback<int(int)> c0 = BindOneShot(&Sum, 1, 2, 4, 8, 16); |
| 460 // - Method with return value. | |
| 461 // - Const method with return value. | |
| 462 TEST_F(BindTest, ReturnValues) { | |
| 463 EXPECT_CALL(static_func_mock_, IntMethod0()).WillOnce(Return(1337)); | |
| 464 EXPECT_CALL(has_ref_, AddRef()).Times(3); | |
| 465 EXPECT_CALL(has_ref_, Release()).Times(3); | |
| 466 EXPECT_CALL(has_ref_, IntMethod0()).WillOnce(Return(31337)); | |
| 467 EXPECT_CALL(has_ref_, IntConstMethod0()) | |
| 468 .WillOnce(Return(41337)) | |
| 469 .WillOnce(Return(51337)); | |
| 470 | 452 |
| 471 Callback<int()> normal_cb = Bind(&IntFunc0); | 453 // OneShotCallback can run via a rvalue-reference. |
| 472 Callback<int()> method_cb = Bind(&HasRef::IntMethod0, &has_ref_); | 454 EXPECT_EQ(63, std::move(c0).Run(32)); |
| 473 Callback<int()> const_method_nonconst_obj_cb = | 455 |
| 474 Bind(&HasRef::IntConstMethod0, &has_ref_); | 456 // After running via the rvalue-reference, the value of the OneShotCallback |
| 475 Callback<int()> const_method_const_obj_cb = | 457 // is undefined. The implementation simply clears the instance after the |
| 476 Bind(&HasRef::IntConstMethod0, const_has_ref_ptr_); | 458 // invocation. |
| 477 EXPECT_EQ(1337, normal_cb.Run()); | 459 EXPECT_TRUE(c0.is_null()); |
| 478 EXPECT_EQ(31337, method_cb.Run()); | 460 |
| 479 EXPECT_EQ(41337, const_method_nonconst_obj_cb.Run()); | 461 c0 = BindOneShot(&Sum, 2, 3, 5, 7, 11); |
| 480 EXPECT_EQ(51337, const_method_const_obj_cb.Run()); | 462 |
| 463 // BindOneShot can handle a rvalue-reference of OneShotCallback as the target | |
| 464 // functor. | |
| 465 OneShotCallback<int()> c1 = BindOneShot(std::move(c0), 13); | |
| 466 EXPECT_EQ(41, std::move(c1).Run()); | |
| 467 | |
| 468 RepeatingCallback<int(int)> c2 = BindRepeating(&Sum, 2, 3, 5, 7, 11); | |
| 469 EXPECT_EQ(41, BindOneShot(c2, 13).Run()); | |
| 481 } | 470 } |
| 482 | 471 |
| 483 // IgnoreResult adapter test. | 472 // IgnoreResult adapter test. |
| 484 // - Function with return value. | 473 // - Function with return value. |
| 485 // - Method with return value. | 474 // - Method with return value. |
| 486 // - Const Method with return. | 475 // - Const Method with return. |
| 487 // - Method with return value bound to WeakPtr<>. | 476 // - Method with return value bound to WeakPtr<>. |
| 488 // - Const Method with return bound to WeakPtr<>. | 477 // - Const Method with return bound to WeakPtr<>. |
| 489 TEST_F(BindTest, IgnoreResult) { | 478 TEST_F(BindTest, IgnoreResultForRepeating) { |
| 490 EXPECT_CALL(static_func_mock_, IntMethod0()).WillOnce(Return(1337)); | 479 EXPECT_CALL(static_func_mock_, IntMethod0()).WillOnce(Return(1337)); |
| 491 EXPECT_CALL(has_ref_, AddRef()).Times(2); | 480 EXPECT_CALL(has_ref_, AddRef()).Times(2); |
| 492 EXPECT_CALL(has_ref_, Release()).Times(2); | 481 EXPECT_CALL(has_ref_, Release()).Times(2); |
| 493 EXPECT_CALL(has_ref_, IntMethod0()).WillOnce(Return(10)); | 482 EXPECT_CALL(has_ref_, IntMethod0()).WillOnce(Return(10)); |
| 494 EXPECT_CALL(has_ref_, IntConstMethod0()).WillOnce(Return(11)); | 483 EXPECT_CALL(has_ref_, IntConstMethod0()).WillOnce(Return(11)); |
| 495 EXPECT_CALL(no_ref_, IntMethod0()).WillOnce(Return(12)); | 484 EXPECT_CALL(no_ref_, IntMethod0()).WillOnce(Return(12)); |
| 496 EXPECT_CALL(no_ref_, IntConstMethod0()).WillOnce(Return(13)); | 485 EXPECT_CALL(no_ref_, IntConstMethod0()).WillOnce(Return(13)); |
| 497 | 486 |
| 498 Closure normal_func_cb = Bind(IgnoreResult(&IntFunc0)); | 487 RepeatingClosure normal_func_cb = BindRepeating(IgnoreResult(&IntFunc0)); |
| 499 normal_func_cb.Run(); | 488 normal_func_cb.Run(); |
| 500 | 489 |
| 501 Closure non_void_method_cb = | 490 RepeatingClosure non_void_method_cb = |
| 502 Bind(IgnoreResult(&HasRef::IntMethod0), &has_ref_); | 491 BindRepeating(IgnoreResult(&HasRef::IntMethod0), &has_ref_); |
| 503 non_void_method_cb.Run(); | 492 non_void_method_cb.Run(); |
| 504 | 493 |
| 505 Closure non_void_const_method_cb = | 494 RepeatingClosure non_void_const_method_cb = |
| 506 Bind(IgnoreResult(&HasRef::IntConstMethod0), &has_ref_); | 495 BindRepeating(IgnoreResult(&HasRef::IntConstMethod0), &has_ref_); |
| 507 non_void_const_method_cb.Run(); | 496 non_void_const_method_cb.Run(); |
| 508 | 497 |
| 509 WeakPtrFactory<NoRef> weak_factory(&no_ref_); | 498 WeakPtrFactory<NoRef> weak_factory(&no_ref_); |
| 510 WeakPtrFactory<const NoRef> const_weak_factory(const_no_ref_ptr_); | 499 WeakPtrFactory<const NoRef> const_weak_factory(const_no_ref_ptr_); |
| 511 | 500 |
| 512 Closure non_void_weak_method_cb = | 501 RepeatingClosure non_void_weak_method_cb = |
| 513 Bind(IgnoreResult(&NoRef::IntMethod0), weak_factory.GetWeakPtr()); | 502 BindRepeating(IgnoreResult(&NoRef::IntMethod0), |
| 503 weak_factory.GetWeakPtr()); | |
| 514 non_void_weak_method_cb.Run(); | 504 non_void_weak_method_cb.Run(); |
| 515 | 505 |
| 516 Closure non_void_weak_const_method_cb = | 506 RepeatingClosure non_void_weak_const_method_cb = |
| 517 Bind(IgnoreResult(&NoRef::IntConstMethod0), weak_factory.GetWeakPtr()); | 507 BindRepeating(IgnoreResult(&NoRef::IntConstMethod0), |
| 508 weak_factory.GetWeakPtr()); | |
| 518 non_void_weak_const_method_cb.Run(); | 509 non_void_weak_const_method_cb.Run(); |
| 519 | 510 |
| 520 weak_factory.InvalidateWeakPtrs(); | 511 weak_factory.InvalidateWeakPtrs(); |
| 521 non_void_weak_const_method_cb.Run(); | 512 non_void_weak_const_method_cb.Run(); |
| 522 non_void_weak_method_cb.Run(); | 513 non_void_weak_method_cb.Run(); |
| 523 } | 514 } |
| 524 | 515 |
| 525 // Argument binding tests. | 516 TEST_F(BindTest, IgnoreResultForOneShot) { |
| 526 // - Argument binding to primitive. | 517 EXPECT_CALL(static_func_mock_, IntMethod0()).WillOnce(Return(1337)); |
| 527 // - Argument binding to primitive pointer. | 518 EXPECT_CALL(has_ref_, AddRef()).Times(2); |
| 528 // - Argument binding to a literal integer. | 519 EXPECT_CALL(has_ref_, Release()).Times(2); |
| 529 // - Argument binding to a literal string. | 520 EXPECT_CALL(has_ref_, IntMethod0()).WillOnce(Return(10)); |
| 530 // - Argument binding with template function. | 521 EXPECT_CALL(has_ref_, IntConstMethod0()).WillOnce(Return(11)); |
| 531 // - Argument binding to an object. | |
| 532 // - Argument binding to pointer to incomplete type. | |
| 533 // - Argument gets type converted. | |
| 534 // - Pointer argument gets converted. | |
| 535 // - Const Reference forces conversion. | |
| 536 TEST_F(BindTest, ArgumentBinding) { | |
| 537 int n = 2; | |
| 538 | 522 |
| 539 Callback<int()> bind_primitive_cb = Bind(&Identity, n); | 523 OneShotClosure normal_func_cb = BindOneShot(IgnoreResult(&IntFunc0)); |
| 540 EXPECT_EQ(n, bind_primitive_cb.Run()); | 524 std::move(normal_func_cb).Run(); |
| 541 | 525 |
| 542 Callback<int*()> bind_primitive_pointer_cb = | 526 OneShotClosure non_void_method_cb = |
| 543 Bind(&PolymorphicIdentity<int*>, &n); | 527 BindOneShot(IgnoreResult(&HasRef::IntMethod0), &has_ref_); |
| 544 EXPECT_EQ(&n, bind_primitive_pointer_cb.Run()); | 528 std::move(non_void_method_cb).Run(); |
| 545 | 529 |
| 546 Callback<int()> bind_int_literal_cb = Bind(&Identity, 3); | 530 OneShotClosure non_void_const_method_cb = |
| 547 EXPECT_EQ(3, bind_int_literal_cb.Run()); | 531 BindOneShot(IgnoreResult(&HasRef::IntConstMethod0), &has_ref_); |
| 532 std::move(non_void_const_method_cb).Run(); | |
| 548 | 533 |
| 549 Callback<const char*()> bind_string_literal_cb = | 534 WeakPtrFactory<NoRef> weak_factory(&no_ref_); |
| 550 Bind(&CStringIdentity, "hi"); | 535 WeakPtrFactory<const NoRef> const_weak_factory(const_no_ref_ptr_); |
| 551 EXPECT_STREQ("hi", bind_string_literal_cb.Run()); | |
| 552 | 536 |
| 553 Callback<int()> bind_template_function_cb = | 537 OneShotClosure non_void_weak_method_cb = |
| 554 Bind(&PolymorphicIdentity<int>, 4); | 538 BindOneShot(IgnoreResult(&NoRef::IntMethod0), |
| 555 EXPECT_EQ(4, bind_template_function_cb.Run()); | 539 weak_factory.GetWeakPtr()); |
| 540 OneShotClosure non_void_weak_const_method_cb = | |
| 541 BindOneShot(IgnoreResult(&NoRef::IntConstMethod0), | |
| 542 weak_factory.GetWeakPtr()); | |
| 556 | 543 |
| 557 NoRefParent p; | 544 weak_factory.InvalidateWeakPtrs(); |
| 558 p.value = 5; | 545 std::move(non_void_weak_const_method_cb).Run(); |
| 559 Callback<int()> bind_object_cb = Bind(&UnwrapNoRefParent, p); | 546 std::move(non_void_weak_method_cb).Run(); |
| 560 EXPECT_EQ(5, bind_object_cb.Run()); | |
| 561 | |
| 562 IncompleteType* incomplete_ptr = reinterpret_cast<IncompleteType*>(123); | |
| 563 Callback<IncompleteType*()> bind_incomplete_ptr_cb = | |
| 564 Bind(&PolymorphicIdentity<IncompleteType*>, incomplete_ptr); | |
| 565 EXPECT_EQ(incomplete_ptr, bind_incomplete_ptr_cb.Run()); | |
| 566 | |
| 567 NoRefChild c; | |
| 568 c.value = 6; | |
| 569 Callback<int()> bind_promotes_cb = Bind(&UnwrapNoRefParent, c); | |
| 570 EXPECT_EQ(6, bind_promotes_cb.Run()); | |
| 571 | |
| 572 c.value = 7; | |
| 573 Callback<int()> bind_pointer_promotes_cb = | |
| 574 Bind(&UnwrapNoRefParentPtr, &c); | |
| 575 EXPECT_EQ(7, bind_pointer_promotes_cb.Run()); | |
| 576 | |
| 577 c.value = 8; | |
| 578 Callback<int()> bind_const_reference_promotes_cb = | |
| 579 Bind(&UnwrapNoRefParentConstRef, c); | |
| 580 EXPECT_EQ(8, bind_const_reference_promotes_cb.Run()); | |
| 581 } | |
| 582 | |
| 583 // Unbound argument type support tests. | |
| 584 // - Unbound value. | |
| 585 // - Unbound pointer. | |
| 586 // - Unbound reference. | |
| 587 // - Unbound const reference. | |
| 588 // - Unbound unsized array. | |
| 589 // - Unbound sized array. | |
| 590 // - Unbound array-of-arrays. | |
| 591 TEST_F(BindTest, UnboundArgumentTypeSupport) { | |
| 592 Callback<void(int)> unbound_value_cb = Bind(&VoidPolymorphic<int>::Run); | |
| 593 Callback<void(int*)> unbound_pointer_cb = Bind(&VoidPolymorphic<int*>::Run); | |
| 594 Callback<void(int&)> unbound_ref_cb = Bind(&VoidPolymorphic<int&>::Run); | |
| 595 Callback<void(const int&)> unbound_const_ref_cb = | |
| 596 Bind(&VoidPolymorphic<const int&>::Run); | |
| 597 Callback<void(int[])> unbound_unsized_array_cb = | |
| 598 Bind(&VoidPolymorphic<int[]>::Run); | |
| 599 Callback<void(int[2])> unbound_sized_array_cb = | |
| 600 Bind(&VoidPolymorphic<int[2]>::Run); | |
| 601 Callback<void(int[][2])> unbound_array_of_arrays_cb = | |
| 602 Bind(&VoidPolymorphic<int[][2]>::Run); | |
| 603 | |
| 604 Callback<void(int&)> unbound_ref_with_bound_arg = | |
| 605 Bind(&VoidPolymorphic<int, int&>::Run, 1); | |
| 606 } | |
| 607 | |
| 608 // Function with unbound reference parameter. | |
| 609 // - Original parameter is modified by callback. | |
| 610 TEST_F(BindTest, UnboundReferenceSupport) { | |
| 611 int n = 0; | |
| 612 Callback<void(int&)> unbound_ref_cb = Bind(&RefArgSet); | |
| 613 unbound_ref_cb.Run(n); | |
| 614 EXPECT_EQ(2, n); | |
| 615 } | 547 } |
| 616 | 548 |
| 617 // Functions that take reference parameters. | 549 // Functions that take reference parameters. |
| 618 // - Forced reference parameter type still stores a copy. | 550 // - Forced reference parameter type still stores a copy. |
| 619 // - Forced const reference parameter type still stores a copy. | 551 // - Forced const reference parameter type still stores a copy. |
| 620 TEST_F(BindTest, ReferenceArgumentBinding) { | 552 TEST_F(BindTest, ReferenceArgumentBindingForRepeating) { |
| 621 int n = 1; | 553 int n = 1; |
| 622 int& ref_n = n; | 554 int& ref_n = n; |
| 623 const int& const_ref_n = n; | 555 const int& const_ref_n = n; |
| 624 | 556 |
| 625 Callback<int()> ref_copies_cb = Bind(&Identity, ref_n); | 557 RepeatingCallback<int()> ref_copies_cb = BindRepeating(&Identity, ref_n); |
| 626 EXPECT_EQ(n, ref_copies_cb.Run()); | 558 EXPECT_EQ(n, ref_copies_cb.Run()); |
| 627 n++; | 559 n++; |
| 628 EXPECT_EQ(n - 1, ref_copies_cb.Run()); | 560 EXPECT_EQ(n - 1, ref_copies_cb.Run()); |
| 629 | 561 |
| 630 Callback<int()> const_ref_copies_cb = Bind(&Identity, const_ref_n); | 562 RepeatingCallback<int()> const_ref_copies_cb = |
| 563 BindRepeating(&Identity, const_ref_n); | |
| 631 EXPECT_EQ(n, const_ref_copies_cb.Run()); | 564 EXPECT_EQ(n, const_ref_copies_cb.Run()); |
| 632 n++; | 565 n++; |
| 633 EXPECT_EQ(n - 1, const_ref_copies_cb.Run()); | 566 EXPECT_EQ(n - 1, const_ref_copies_cb.Run()); |
| 634 } | 567 } |
| 635 | 568 |
| 569 TEST_F(BindTest, ReferenceArgumentBindingForOneShot) { | |
| 570 int n = 1; | |
| 571 int& ref_n = n; | |
| 572 const int& const_ref_n = n; | |
| 573 | |
| 574 OneShotCallback<int()> ref_copies_cb = BindOneShot(&Identity, ref_n); | |
| 575 n++; | |
| 576 EXPECT_EQ(n - 1, std::move(ref_copies_cb).Run()); | |
| 577 | |
| 578 OneShotCallback<int()> const_ref_copies_cb = | |
| 579 BindOneShot(&Identity, const_ref_n); | |
| 580 n++; | |
| 581 EXPECT_EQ(n - 1, std::move(const_ref_copies_cb).Run()); | |
| 582 } | |
| 583 | |
| 636 // Check that we can pass in arrays and have them be stored as a pointer. | 584 // Check that we can pass in arrays and have them be stored as a pointer. |
| 637 // - Array of values stores a pointer. | 585 // - Array of values stores a pointer. |
| 638 // - Array of const values stores a pointer. | 586 // - Array of const values stores a pointer. |
| 639 TEST_F(BindTest, ArrayArgumentBinding) { | 587 TEST_F(BindTest, ArrayArgumentBindingForRepeating) { |
| 640 int array[4] = {1, 1, 1, 1}; | 588 int array[4] = {1, 1, 1, 1}; |
| 641 const int (*const_array_ptr)[4] = &array; | 589 const int (*const_array_ptr)[4] = &array; |
| 642 | 590 |
| 643 Callback<int()> array_cb = Bind(&ArrayGet, array, 1); | 591 RepeatingCallback<int()> array_cb = BindRepeating(&ArrayGet, array, 1); |
| 644 EXPECT_EQ(1, array_cb.Run()); | 592 EXPECT_EQ(1, array_cb.Run()); |
| 645 | 593 |
| 646 Callback<int()> const_array_cb = Bind(&ArrayGet, *const_array_ptr, 1); | 594 RepeatingCallback<int()> const_array_cb = |
| 595 BindRepeating(&ArrayGet, *const_array_ptr, 1); | |
| 647 EXPECT_EQ(1, const_array_cb.Run()); | 596 EXPECT_EQ(1, const_array_cb.Run()); |
| 648 | 597 |
| 649 array[1] = 3; | 598 array[1] = 3; |
| 650 EXPECT_EQ(3, array_cb.Run()); | 599 EXPECT_EQ(3, array_cb.Run()); |
| 651 EXPECT_EQ(3, const_array_cb.Run()); | 600 EXPECT_EQ(3, const_array_cb.Run()); |
| 652 } | 601 } |
| 653 | 602 |
| 654 // Unretained() wrapper support. | 603 TEST_F(BindTest, ArrayArgumentBindingForOneShot) { |
| 655 // - Method bound to Unretained() non-const object. | 604 int array[4] = {1, 1, 1, 1}; |
| 656 // - Const method bound to Unretained() non-const object. | 605 const int (*const_array_ptr)[4] = &array; |
| 657 // - Const method bound to Unretained() const object. | |
| 658 TEST_F(BindTest, Unretained) { | |
| 659 EXPECT_CALL(no_ref_, VoidMethod0()); | |
| 660 EXPECT_CALL(no_ref_, VoidConstMethod0()).Times(2); | |
| 661 | 606 |
| 662 Callback<void()> method_cb = | 607 OneShotCallback<int()> array_cb = BindOneShot(&ArrayGet, array, 1); |
| 663 Bind(&NoRef::VoidMethod0, Unretained(&no_ref_)); | 608 OneShotCallback<int()> const_array_cb = |
| 664 method_cb.Run(); | 609 BindOneShot(&ArrayGet, *const_array_ptr, 1); |
| 665 | 610 |
| 666 Callback<void()> const_method_cb = | 611 array[1] = 3; |
| 667 Bind(&NoRef::VoidConstMethod0, Unretained(&no_ref_)); | 612 EXPECT_EQ(3, std::move(array_cb).Run()); |
| 668 const_method_cb.Run(); | 613 EXPECT_EQ(3, std::move(const_array_cb).Run()); |
| 669 | |
| 670 Callback<void()> const_method_const_ptr_cb = | |
| 671 Bind(&NoRef::VoidConstMethod0, Unretained(const_no_ref_ptr_)); | |
| 672 const_method_const_ptr_cb.Run(); | |
| 673 } | 614 } |
| 674 | 615 |
| 675 // WeakPtr() support. | 616 // WeakPtr() support. |
| 676 // - Method bound to WeakPtr<> to non-const object. | 617 // - Method bound to WeakPtr<> to non-const object. |
| 677 // - Const method bound to WeakPtr<> to non-const object. | 618 // - Const method bound to WeakPtr<> to non-const object. |
| 678 // - Const method bound to WeakPtr<> to const object. | 619 // - Const method bound to WeakPtr<> to const object. |
| 679 // - Normal Function with WeakPtr<> as P1 can have return type and is | 620 // - Normal Function with WeakPtr<> as P1 can have return type and is |
| 680 // not canceled. | 621 // not canceled. |
| 681 TEST_F(BindTest, WeakPtr) { | 622 TEST_F(BindTest, WeakPtrForRepeating) { |
| 682 EXPECT_CALL(no_ref_, VoidMethod0()); | 623 EXPECT_CALL(no_ref_, VoidMethod0()); |
| 683 EXPECT_CALL(no_ref_, VoidConstMethod0()).Times(2); | 624 EXPECT_CALL(no_ref_, VoidConstMethod0()).Times(2); |
| 684 | 625 |
| 685 WeakPtrFactory<NoRef> weak_factory(&no_ref_); | 626 WeakPtrFactory<NoRef> weak_factory(&no_ref_); |
| 686 WeakPtrFactory<const NoRef> const_weak_factory(const_no_ref_ptr_); | 627 WeakPtrFactory<const NoRef> const_weak_factory(const_no_ref_ptr_); |
| 687 | 628 |
| 688 Closure method_cb = | 629 RepeatingClosure method_cb = |
| 689 Bind(&NoRef::VoidMethod0, weak_factory.GetWeakPtr()); | 630 BindRepeating(&NoRef::VoidMethod0, weak_factory.GetWeakPtr()); |
| 690 method_cb.Run(); | 631 method_cb.Run(); |
| 691 | 632 |
| 692 Closure const_method_cb = | 633 RepeatingClosure const_method_cb = |
| 693 Bind(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr()); | 634 BindRepeating(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr()); |
| 694 const_method_cb.Run(); | 635 const_method_cb.Run(); |
| 695 | 636 |
| 696 Closure const_method_const_ptr_cb = | 637 RepeatingClosure const_method_const_ptr_cb = |
| 697 Bind(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr()); | 638 BindRepeating(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr()); |
| 698 const_method_const_ptr_cb.Run(); | 639 const_method_const_ptr_cb.Run(); |
| 699 | 640 |
| 700 Callback<int(int)> normal_func_cb = | 641 RepeatingCallback<int(int)> normal_func_cb = |
| 701 Bind(&FunctionWithWeakFirstParam, weak_factory.GetWeakPtr()); | 642 BindRepeating(&FunctionWithWeakFirstParam, weak_factory.GetWeakPtr()); |
| 702 EXPECT_EQ(1, normal_func_cb.Run(1)); | 643 EXPECT_EQ(1, normal_func_cb.Run(1)); |
| 703 | 644 |
| 704 weak_factory.InvalidateWeakPtrs(); | 645 weak_factory.InvalidateWeakPtrs(); |
| 705 const_weak_factory.InvalidateWeakPtrs(); | 646 const_weak_factory.InvalidateWeakPtrs(); |
| 706 | 647 |
| 707 method_cb.Run(); | 648 method_cb.Run(); |
| 708 const_method_cb.Run(); | 649 const_method_cb.Run(); |
| 709 const_method_const_ptr_cb.Run(); | 650 const_method_const_ptr_cb.Run(); |
| 710 | 651 |
| 711 // Still runs even after the pointers are invalidated. | 652 // Still runs even after the pointers are invalidated. |
| 712 EXPECT_EQ(2, normal_func_cb.Run(2)); | 653 EXPECT_EQ(2, normal_func_cb.Run(2)); |
| 713 } | 654 } |
| 714 | 655 |
| 656 TEST_F(BindTest, WeakPtrForOneShot) { | |
| 657 WeakPtrFactory<NoRef> weak_factory(&no_ref_); | |
| 658 WeakPtrFactory<const NoRef> const_weak_factory(const_no_ref_ptr_); | |
| 659 | |
| 660 OneShotClosure method_cb = | |
| 661 BindOneShot(&NoRef::VoidMethod0, weak_factory.GetWeakPtr()); | |
| 662 OneShotClosure const_method_cb = | |
| 663 BindOneShot(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr()); | |
| 664 OneShotClosure const_method_const_ptr_cb = | |
| 665 BindOneShot(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr()); | |
| 666 Callback<int(int)> normal_func_cb = | |
| 667 Bind(&FunctionWithWeakFirstParam, weak_factory.GetWeakPtr()); | |
| 668 | |
| 669 weak_factory.InvalidateWeakPtrs(); | |
| 670 const_weak_factory.InvalidateWeakPtrs(); | |
| 671 | |
| 672 std::move(method_cb).Run(); | |
| 673 std::move(const_method_cb).Run(); | |
| 674 std::move(const_method_const_ptr_cb).Run(); | |
| 675 | |
| 676 // Still runs even after the pointers are invalidated. | |
| 677 EXPECT_EQ(2, std::move(normal_func_cb).Run(2)); | |
| 678 } | |
| 679 | |
| 715 // ConstRef() wrapper support. | 680 // ConstRef() wrapper support. |
| 716 // - Binding w/o ConstRef takes a copy. | 681 // - Binding w/o ConstRef takes a copy. |
| 717 // - Binding a ConstRef takes a reference. | 682 // - Binding a ConstRef takes a reference. |
| 718 // - Binding ConstRef to a function ConstRef does not copy on invoke. | 683 // - Binding ConstRef to a function ConstRef does not copy on invoke. |
| 719 TEST_F(BindTest, ConstRef) { | 684 TEST_F(BindTest, ConstRefForRepeating) { |
| 720 int n = 1; | 685 int n = 1; |
| 721 | 686 |
| 722 Callback<int()> copy_cb = Bind(&Identity, n); | 687 RepeatingCallback<int()> copy_cb = BindRepeating(&Identity, n); |
| 723 Callback<int()> const_ref_cb = Bind(&Identity, ConstRef(n)); | 688 RepeatingCallback<int()> const_ref_cb = BindRepeating(&Identity, ConstRef(n)); |
| 724 EXPECT_EQ(n, copy_cb.Run()); | 689 EXPECT_EQ(n, copy_cb.Run()); |
| 725 EXPECT_EQ(n, const_ref_cb.Run()); | 690 EXPECT_EQ(n, const_ref_cb.Run()); |
| 726 n++; | 691 n++; |
| 727 EXPECT_EQ(n - 1, copy_cb.Run()); | 692 EXPECT_EQ(n - 1, copy_cb.Run()); |
| 728 EXPECT_EQ(n, const_ref_cb.Run()); | 693 EXPECT_EQ(n, const_ref_cb.Run()); |
| 729 | 694 |
| 730 int copies = 0; | 695 int copies = 0; |
| 731 int assigns = 0; | 696 int assigns = 0; |
| 732 int move_constructs = 0; | 697 int move_constructs = 0; |
| 733 int move_assigns = 0; | 698 int move_assigns = 0; |
| 734 CopyMoveCounter counter(&copies, &assigns, &move_constructs, &move_assigns); | 699 CopyMoveCounter counter(&copies, &assigns, &move_constructs, &move_assigns); |
| 735 Callback<int()> all_const_ref_cb = | 700 RepeatingCallback<int()> all_const_ref_cb = |
| 736 Bind(&GetCopies, ConstRef(counter)); | 701 BindRepeating(&GetCopies, ConstRef(counter)); |
| 737 EXPECT_EQ(0, all_const_ref_cb.Run()); | 702 EXPECT_EQ(0, all_const_ref_cb.Run()); |
| 738 EXPECT_EQ(0, copies); | 703 EXPECT_EQ(0, copies); |
| 739 EXPECT_EQ(0, assigns); | 704 EXPECT_EQ(0, assigns); |
| 740 EXPECT_EQ(0, move_constructs); | 705 EXPECT_EQ(0, move_constructs); |
| 741 EXPECT_EQ(0, move_assigns); | 706 EXPECT_EQ(0, move_assigns); |
| 742 } | 707 } |
| 743 | 708 |
| 744 TEST_F(BindTest, ScopedRefptr) { | 709 TEST_F(BindTest, ConstRefForOneShot) { |
| 745 EXPECT_CALL(has_ref_, AddRef()).Times(1); | 710 int n = 1; |
| 746 EXPECT_CALL(has_ref_, Release()).Times(1); | |
| 747 | 711 |
| 748 const scoped_refptr<HasRef> refptr(&has_ref_); | 712 OneShotCallback<int()> copy_cb = BindOneShot(&Identity, n); |
| 749 Callback<int()> scoped_refptr_const_ref_cb = | 713 OneShotCallback<int()> const_ref_cb = BindOneShot(&Identity, ConstRef(n)); |
| 750 Bind(&FunctionWithScopedRefptrFirstParam, base::ConstRef(refptr), 1); | 714 n++; |
| 751 EXPECT_EQ(1, scoped_refptr_const_ref_cb.Run()); | 715 EXPECT_EQ(n - 1, std::move(copy_cb).Run()); |
| 716 EXPECT_EQ(n, std::move(const_ref_cb).Run()); | |
| 717 | |
| 718 int copies = 0; | |
| 719 int assigns = 0; | |
| 720 int move_constructs = 0; | |
| 721 int move_assigns = 0; | |
| 722 CopyMoveCounter counter(&copies, &assigns, &move_constructs, &move_assigns); | |
| 723 OneShotCallback<int()> all_const_ref_cb = | |
| 724 BindOneShot(&GetCopies, ConstRef(counter)); | |
| 725 EXPECT_EQ(0, std::move(all_const_ref_cb).Run()); | |
| 726 EXPECT_EQ(0, copies); | |
| 727 EXPECT_EQ(0, assigns); | |
| 728 EXPECT_EQ(0, move_constructs); | |
| 729 EXPECT_EQ(0, move_assigns); | |
| 752 } | 730 } |
| 753 | 731 |
| 754 // Test Owned() support. | 732 // Test Owned() support. |
| 755 TEST_F(BindTest, Owned) { | 733 TEST_F(BindTest, OwnedForRepeating) { |
| 756 int deletes = 0; | 734 int deletes = 0; |
| 757 DeleteCounter* counter = new DeleteCounter(&deletes); | 735 DeleteCounter* counter = new DeleteCounter(&deletes); |
| 758 | 736 |
| 759 // If we don't capture, delete happens on Callback destruction/reset. | 737 // If we don't capture, delete happens on Callback destruction/reset. |
| 760 // return the same value. | 738 // return the same value. |
| 761 Callback<DeleteCounter*()> no_capture_cb = | 739 RepeatingCallback<DeleteCounter*()> no_capture_cb = |
| 762 Bind(&PolymorphicIdentity<DeleteCounter*>, Owned(counter)); | 740 BindRepeating(&PolymorphicIdentity<DeleteCounter*>, Owned(counter)); |
| 763 ASSERT_EQ(counter, no_capture_cb.Run()); | 741 ASSERT_EQ(counter, no_capture_cb.Run()); |
| 764 ASSERT_EQ(counter, no_capture_cb.Run()); | 742 ASSERT_EQ(counter, no_capture_cb.Run()); |
| 765 EXPECT_EQ(0, deletes); | 743 EXPECT_EQ(0, deletes); |
| 766 no_capture_cb.Reset(); // This should trigger a delete. | 744 no_capture_cb.Reset(); // This should trigger a delete. |
| 767 EXPECT_EQ(1, deletes); | 745 EXPECT_EQ(1, deletes); |
| 768 | 746 |
| 769 deletes = 0; | 747 deletes = 0; |
| 770 counter = new DeleteCounter(&deletes); | 748 counter = new DeleteCounter(&deletes); |
| 771 base::Closure own_object_cb = | 749 RepeatingClosure own_object_cb = |
| 772 Bind(&DeleteCounter::VoidMethod0, Owned(counter)); | 750 BindRepeating(&DeleteCounter::VoidMethod0, Owned(counter)); |
| 773 own_object_cb.Run(); | 751 own_object_cb.Run(); |
| 774 EXPECT_EQ(0, deletes); | 752 EXPECT_EQ(0, deletes); |
| 775 own_object_cb.Reset(); | 753 own_object_cb.Reset(); |
| 776 EXPECT_EQ(1, deletes); | 754 EXPECT_EQ(1, deletes); |
| 777 } | 755 } |
| 778 | 756 |
| 779 TEST_F(BindTest, UniquePtrReceiver) { | 757 TEST_F(BindTest, OwnedForOneShot) { |
| 758 int deletes = 0; | |
| 759 DeleteCounter* counter = new DeleteCounter(&deletes); | |
| 760 | |
| 761 // If we don't capture, delete happens on Callback destruction/reset. | |
| 762 // return the same value. | |
| 763 OneShotCallback<DeleteCounter*()> no_capture_cb = | |
| 764 BindOneShot(&PolymorphicIdentity<DeleteCounter*>, Owned(counter)); | |
| 765 EXPECT_EQ(0, deletes); | |
| 766 no_capture_cb.Reset(); // This should trigger a delete. | |
| 767 EXPECT_EQ(1, deletes); | |
| 768 | |
| 769 deletes = 0; | |
| 770 counter = new DeleteCounter(&deletes); | |
| 771 OneShotClosure own_object_cb = | |
| 772 BindOneShot(&DeleteCounter::VoidMethod0, Owned(counter)); | |
| 773 EXPECT_EQ(0, deletes); | |
| 774 own_object_cb.Reset(); | |
| 775 EXPECT_EQ(1, deletes); | |
| 776 } | |
| 777 | |
| 778 template <typename T> | |
| 779 class BindVariantsTest : public ::testing::Test { | |
| 780 }; | |
| 781 | |
| 782 struct RepeatingTestConfig { | |
| 783 template <typename Signature> | |
| 784 using CallbackType = RepeatingCallback<Signature>; | |
| 785 using ClosureType = RepeatingClosure; | |
| 786 | |
| 787 template <typename F, typename... Args> | |
| 788 static CallbackType<MakeUnboundRunType<F, Args...>> | |
| 789 Bind(F&& f, Args&&... args) { | |
| 790 return BindRepeating(std::forward<F>(f), std::forward<Args>(args)...); | |
| 791 } | |
| 792 }; | |
| 793 | |
| 794 struct OneShotTestConfig { | |
| 795 template <typename Signature> | |
| 796 using CallbackType = OneShotCallback<Signature>; | |
| 797 using ClosureType = OneShotClosure; | |
| 798 | |
| 799 template <typename F, typename... Args> | |
| 800 static CallbackType<MakeUnboundRunType<F, Args...>> | |
| 801 Bind(F&& f, Args&&... args) { | |
| 802 return BindOneShot(std::forward<F>(f), std::forward<Args>(args)...); | |
| 803 } | |
| 804 }; | |
| 805 | |
| 806 using BindVariantsTestConfig = ::testing::Types< | |
| 807 RepeatingTestConfig, OneShotTestConfig>; | |
| 808 TYPED_TEST_CASE(BindVariantsTest, BindVariantsTestConfig); | |
| 809 | |
| 810 template <typename TypeParam, typename Signature> | |
| 811 using CallbackType = typename TypeParam::template CallbackType<Signature>; | |
| 812 | |
| 813 // Function type support. | |
| 814 // - Normal function. | |
| 815 // - Normal function bound with non-refcounted first argument. | |
| 816 // - Method bound to non-const object. | |
| 817 // - Method bound to scoped_refptr. | |
| 818 // - Const method bound to non-const object. | |
| 819 // - Const method bound to const object. | |
| 820 // - Derived classes can be used with pointers to non-virtual base functions. | |
| 821 // - Derived classes can be used with pointers to virtual base functions (and | |
| 822 // preserve virtual dispatch). | |
| 823 TYPED_TEST(BindVariantsTest, FunctionTypeSupport) { | |
| 824 using ClosureType = typename TypeParam::ClosureType; | |
| 825 | |
| 826 StrictMock<HasRef> has_ref; | |
| 827 StrictMock<NoRef> no_ref; | |
| 828 StrictMock<NoRef> static_func_mock; | |
| 829 const HasRef* const_has_ref_ptr = &has_ref; | |
| 830 g_func_mock_ptr = &static_func_mock; | |
| 831 | |
| 832 EXPECT_CALL(static_func_mock, VoidMethod0()); | |
| 833 EXPECT_CALL(has_ref, AddRef()).Times(4); | |
| 834 EXPECT_CALL(has_ref, Release()).Times(4); | |
| 835 EXPECT_CALL(has_ref, VoidMethod0()).Times(2); | |
| 836 EXPECT_CALL(has_ref, VoidConstMethod0()).Times(2); | |
| 837 | |
| 838 ClosureType normal_cb = TypeParam::Bind(&VoidFunc0); | |
| 839 CallbackType<TypeParam, NoRef*()> normal_non_refcounted_cb = | |
| 840 TypeParam::Bind(&PolymorphicIdentity<NoRef*>, &no_ref); | |
| 841 std::move(normal_cb).Run(); | |
| 842 EXPECT_EQ(&no_ref, std::move(normal_non_refcounted_cb).Run()); | |
| 843 | |
| 844 ClosureType method_cb = TypeParam::Bind(&HasRef::VoidMethod0, &has_ref); | |
| 845 ClosureType method_refptr_cb = TypeParam::Bind(&HasRef::VoidMethod0, | |
| 846 make_scoped_refptr(&has_ref)); | |
| 847 ClosureType const_method_nonconst_obj_cb = | |
| 848 TypeParam::Bind(&HasRef::VoidConstMethod0, &has_ref); | |
| 849 ClosureType const_method_const_obj_cb = | |
| 850 TypeParam::Bind(&HasRef::VoidConstMethod0, const_has_ref_ptr); | |
| 851 std::move(method_cb).Run(); | |
| 852 std::move(method_refptr_cb).Run(); | |
| 853 std::move(const_method_nonconst_obj_cb).Run(); | |
| 854 std::move(const_method_const_obj_cb).Run(); | |
| 855 | |
| 856 Child child; | |
| 857 child.value = 0; | |
| 858 ClosureType virtual_set_cb = TypeParam::Bind(&Parent::VirtualSet, &child); | |
| 859 std::move(virtual_set_cb).Run(); | |
| 860 EXPECT_EQ(kChildValue, child.value); | |
| 861 | |
| 862 child.value = 0; | |
| 863 ClosureType non_virtual_set_cb = | |
| 864 TypeParam::Bind(&Parent::NonVirtualSet, &child); | |
| 865 std::move(non_virtual_set_cb).Run(); | |
| 866 EXPECT_EQ(kParentValue, child.value); | |
| 867 } | |
| 868 | |
| 869 // Return value support. | |
| 870 // - Function with return value. | |
| 871 // - Method with return value. | |
| 872 // - Const method with return value. | |
| 873 // - Move-only return value. | |
| 874 TYPED_TEST(BindVariantsTest, ReturnValues) { | |
| 875 StrictMock<NoRef> static_func_mock; | |
| 876 StrictMock<HasRef> has_ref; | |
| 877 g_func_mock_ptr = &static_func_mock; | |
| 878 const HasRef* const_has_ref_ptr = &has_ref; | |
| 879 | |
| 880 EXPECT_CALL(static_func_mock, IntMethod0()).WillOnce(Return(1337)); | |
| 881 EXPECT_CALL(has_ref, AddRef()).Times(4); | |
| 882 EXPECT_CALL(has_ref, Release()).Times(4); | |
| 883 EXPECT_CALL(has_ref, IntMethod0()).WillOnce(Return(31337)); | |
| 884 EXPECT_CALL(has_ref, IntConstMethod0()) | |
| 885 .WillOnce(Return(41337)) | |
| 886 .WillOnce(Return(51337)); | |
| 887 EXPECT_CALL(has_ref, UniquePtrMethod0()) | |
| 888 .WillOnce(Return(ByMove(MakeUnique<int>(42)))); | |
| 889 | |
| 890 CallbackType<TypeParam, int()> normal_cb = TypeParam::Bind(&IntFunc0); | |
| 891 CallbackType<TypeParam, int()> method_cb = | |
| 892 TypeParam::Bind(&HasRef::IntMethod0, &has_ref); | |
| 893 CallbackType<TypeParam, int()> const_method_nonconst_obj_cb = | |
| 894 TypeParam::Bind(&HasRef::IntConstMethod0, &has_ref); | |
| 895 CallbackType<TypeParam, int()> const_method_const_obj_cb = | |
| 896 TypeParam::Bind(&HasRef::IntConstMethod0, const_has_ref_ptr); | |
| 897 CallbackType<TypeParam, std::unique_ptr<int>()> move_only_rv_cb = | |
| 898 TypeParam::Bind(&HasRef::UniquePtrMethod0, &has_ref); | |
| 899 EXPECT_EQ(1337, std::move(normal_cb).Run()); | |
| 900 EXPECT_EQ(31337, std::move(method_cb).Run()); | |
| 901 EXPECT_EQ(41337, std::move(const_method_nonconst_obj_cb).Run()); | |
| 902 EXPECT_EQ(51337, std::move(const_method_const_obj_cb).Run()); | |
| 903 EXPECT_EQ(42, *std::move(move_only_rv_cb).Run()); | |
| 904 } | |
| 905 | |
| 906 // Argument binding tests. | |
| 907 // - Argument binding to primitive. | |
| 908 // - Argument binding to primitive pointer. | |
| 909 // - Argument binding to a literal integer. | |
| 910 // - Argument binding to a literal string. | |
| 911 // - Argument binding with template function. | |
| 912 // - Argument binding to an object. | |
| 913 // - Argument binding to pointer to incomplete type. | |
| 914 // - Argument gets type converted. | |
| 915 // - Pointer argument gets converted. | |
| 916 // - Const Reference forces conversion. | |
| 917 TYPED_TEST(BindVariantsTest, ArgumentBinding) { | |
| 918 int n = 2; | |
| 919 | |
| 920 EXPECT_EQ(n, TypeParam::Bind(&Identity, n).Run()); | |
| 921 EXPECT_EQ(&n, TypeParam::Bind(&PolymorphicIdentity<int*>, &n).Run()); | |
| 922 EXPECT_EQ(3, TypeParam::Bind(&Identity, 3).Run()); | |
| 923 EXPECT_STREQ("hi", TypeParam::Bind(&CStringIdentity, "hi").Run()); | |
| 924 EXPECT_EQ(4, TypeParam::Bind(&PolymorphicIdentity<int>, 4).Run()); | |
| 925 | |
| 926 NoRefParent p; | |
| 927 p.value = 5; | |
| 928 EXPECT_EQ(5, TypeParam::Bind(&UnwrapNoRefParent, p).Run()); | |
| 929 | |
| 930 IncompleteType* incomplete_ptr = reinterpret_cast<IncompleteType*>(123); | |
| 931 EXPECT_EQ(incomplete_ptr, | |
| 932 TypeParam::Bind(&PolymorphicIdentity<IncompleteType*>, | |
| 933 incomplete_ptr).Run()); | |
| 934 | |
| 935 NoRefChild c; | |
| 936 c.value = 6; | |
| 937 EXPECT_EQ(6, TypeParam::Bind(&UnwrapNoRefParent, c).Run()); | |
| 938 | |
| 939 c.value = 7; | |
| 940 EXPECT_EQ(7, TypeParam::Bind(&UnwrapNoRefParentPtr, &c).Run()); | |
| 941 | |
| 942 c.value = 8; | |
| 943 EXPECT_EQ(8, TypeParam::Bind(&UnwrapNoRefParentConstRef, c).Run()); | |
| 944 } | |
| 945 | |
| 946 // Unbound argument type support tests. | |
| 947 // - Unbound value. | |
| 948 // - Unbound pointer. | |
| 949 // - Unbound reference. | |
| 950 // - Unbound const reference. | |
| 951 // - Unbound unsized array. | |
| 952 // - Unbound sized array. | |
| 953 // - Unbound array-of-arrays. | |
| 954 TYPED_TEST(BindVariantsTest, UnboundArgumentTypeSupport) { | |
| 955 CallbackType<TypeParam, void(int)> unbound_value_cb = | |
| 956 TypeParam::Bind(&VoidPolymorphic<int>::Run); | |
| 957 CallbackType<TypeParam, void(int*)> unbound_pointer_cb = | |
| 958 TypeParam::Bind(&VoidPolymorphic<int*>::Run); | |
| 959 CallbackType<TypeParam, void(int&)> unbound_ref_cb = | |
| 960 TypeParam::Bind(&VoidPolymorphic<int&>::Run); | |
| 961 CallbackType<TypeParam, void(const int&)> unbound_const_ref_cb = | |
| 962 TypeParam::Bind(&VoidPolymorphic<const int&>::Run); | |
| 963 CallbackType<TypeParam, void(int[])> unbound_unsized_array_cb = | |
| 964 TypeParam::Bind(&VoidPolymorphic<int[]>::Run); | |
| 965 CallbackType<TypeParam, void(int[2])> unbound_sized_array_cb = | |
| 966 TypeParam::Bind(&VoidPolymorphic<int[2]>::Run); | |
| 967 CallbackType<TypeParam, void(int[][2])> unbound_array_of_arrays_cb = | |
| 968 TypeParam::Bind(&VoidPolymorphic<int[][2]>::Run); | |
| 969 CallbackType<TypeParam, void(int&)> unbound_ref_with_bound_arg = | |
| 970 TypeParam::Bind(&VoidPolymorphic<int, int&>::Run, 1); | |
| 971 } | |
| 972 | |
| 973 // Function with unbound reference parameter. | |
| 974 // - Original parameter is modified by callback. | |
| 975 TYPED_TEST(BindVariantsTest, UnboundReferenceSupport) { | |
| 976 int n = 0; | |
| 977 CallbackType<TypeParam, void(int&)> unbound_ref_cb = | |
| 978 TypeParam::Bind(&RefArgSet); | |
| 979 std::move(unbound_ref_cb).Run(n); | |
| 980 EXPECT_EQ(2, n); | |
| 981 } | |
| 982 | |
| 983 // Unretained() wrapper support. | |
| 984 // - Method bound to Unretained() non-const object. | |
| 985 // - Const method bound to Unretained() non-const object. | |
| 986 // - Const method bound to Unretained() const object. | |
| 987 TYPED_TEST(BindVariantsTest, Unretained) { | |
| 988 StrictMock<NoRef> no_ref; | |
| 989 const NoRef* const_no_ref_ptr = &no_ref; | |
| 990 | |
| 991 EXPECT_CALL(no_ref, VoidMethod0()); | |
| 992 EXPECT_CALL(no_ref, VoidConstMethod0()).Times(2); | |
| 993 | |
| 994 TypeParam::Bind(&NoRef::VoidMethod0, Unretained(&no_ref)).Run(); | |
| 995 TypeParam::Bind(&NoRef::VoidConstMethod0, Unretained(&no_ref)).Run(); | |
| 996 TypeParam::Bind(&NoRef::VoidConstMethod0, Unretained(const_no_ref_ptr)).Run(); | |
| 997 } | |
| 998 | |
| 999 TYPED_TEST(BindVariantsTest, ScopedRefptr) { | |
| 1000 StrictMock<HasRef> has_ref; | |
| 1001 EXPECT_CALL(has_ref, AddRef()).Times(1); | |
| 1002 EXPECT_CALL(has_ref, Release()).Times(1); | |
| 1003 | |
| 1004 const scoped_refptr<HasRef> refptr(&has_ref); | |
| 1005 CallbackType<TypeParam, int()> scoped_refptr_const_ref_cb = | |
| 1006 TypeParam::Bind(&FunctionWithScopedRefptrFirstParam, | |
| 1007 base::ConstRef(refptr), 1); | |
| 1008 EXPECT_EQ(1, std::move(scoped_refptr_const_ref_cb).Run()); | |
| 1009 } | |
| 1010 | |
| 1011 TYPED_TEST(BindVariantsTest, UniquePtrReceiver) { | |
| 780 std::unique_ptr<StrictMock<NoRef>> no_ref(new StrictMock<NoRef>); | 1012 std::unique_ptr<StrictMock<NoRef>> no_ref(new StrictMock<NoRef>); |
| 781 EXPECT_CALL(*no_ref, VoidMethod0()).Times(1); | 1013 EXPECT_CALL(*no_ref, VoidMethod0()).Times(1); |
| 782 Bind(&NoRef::VoidMethod0, std::move(no_ref)).Run(); | 1014 TypeParam::Bind(&NoRef::VoidMethod0, std::move(no_ref)).Run(); |
| 783 } | 1015 } |
| 784 | 1016 |
| 785 // Tests for Passed() wrapper support: | 1017 // Tests for Passed() wrapper support: |
| 786 // - Passed() can be constructed from a pointer to scoper. | 1018 // - Passed() can be constructed from a pointer to scoper. |
| 787 // - Passed() can be constructed from a scoper rvalue. | 1019 // - Passed() can be constructed from a scoper rvalue. |
| 788 // - Using Passed() gives Callback Ownership. | 1020 // - Using Passed() gives Callback Ownership. |
| 789 // - Ownership is transferred from Callback to callee on the first Run(). | 1021 // - Ownership is transferred from Callback to callee on the first Run(). |
| 790 // - Callback supports unbound arguments. | 1022 // - Callback supports unbound arguments. |
| 791 template <typename T> | 1023 template <typename T> |
| 792 class BindMoveOnlyTypeTest : public ::testing::Test { | 1024 class BindMoveOnlyTypeTest : public ::testing::Test { |
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1172 | 1404 |
| 1173 // Test null callbacks cause a DCHECK. | 1405 // Test null callbacks cause a DCHECK. |
| 1174 TEST(BindDeathTest, NullCallback) { | 1406 TEST(BindDeathTest, NullCallback) { |
| 1175 base::Callback<void(int)> null_cb; | 1407 base::Callback<void(int)> null_cb; |
| 1176 ASSERT_TRUE(null_cb.is_null()); | 1408 ASSERT_TRUE(null_cb.is_null()); |
| 1177 EXPECT_DCHECK_DEATH(base::Bind(null_cb, 42)); | 1409 EXPECT_DCHECK_DEATH(base::Bind(null_cb, 42)); |
| 1178 } | 1410 } |
| 1179 | 1411 |
| 1180 } // namespace | 1412 } // namespace |
| 1181 } // namespace base | 1413 } // namespace base |
| OLD | NEW |