| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 #if defined(BASE_CALLBACK_H_) | 7 #if defined(BASE_CALLBACK_H_) |
| 8 // We explicitly do not want to include callback.h so people are not tempted | 8 // We explicitly do not want to include callback.h so people are not tempted |
| 9 // to use bind.h in a headerfile for getting the Callback types. | 9 // to use bind.h in a headerfile for getting the Callback types. |
| 10 #error "base/bind.h should avoid pulling in callback.h by default." | 10 #error "base/bind.h should avoid pulling in callback.h by default." |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 | 244 |
| 245 Callback<int(int,int,int,int,int)> c5 = Bind(&Sum, 32); | 245 Callback<int(int,int,int,int,int)> c5 = Bind(&Sum, 32); |
| 246 EXPECT_EQ(87, c5.Run(13, 12, 11, 10, 9)); | 246 EXPECT_EQ(87, c5.Run(13, 12, 11, 10, 9)); |
| 247 | 247 |
| 248 Callback<int(int,int,int,int,int,int)> c6 = Bind(&Sum); | 248 Callback<int(int,int,int,int,int,int)> c6 = Bind(&Sum); |
| 249 EXPECT_EQ(69, c6.Run(13, 12, 11, 10, 9, 14)); | 249 EXPECT_EQ(69, c6.Run(13, 12, 11, 10, 9, 14)); |
| 250 } | 250 } |
| 251 | 251 |
| 252 // Function type support. | 252 // Function type support. |
| 253 // - Normal function. | 253 // - Normal function. |
| 254 // - Normal function bound with non-refcounted first argument. |
| 254 // - Method bound to non-const object. | 255 // - Method bound to non-const object. |
| 255 // - Const method bound to non-const object. | 256 // - Const method bound to non-const object. |
| 256 // - Const method bound to const object. | 257 // - Const method bound to const object. |
| 257 // - Derived classes can be used with pointers to non-virtual base functions. | 258 // - Derived classes can be used with pointers to non-virtual base functions. |
| 258 // - Derived classes can be used with pointers to virtual base functions (and | 259 // - Derived classes can be used with pointers to virtual base functions (and |
| 259 // preserve virtual dispatch). | 260 // preserve virtual dispatch). |
| 260 TEST_F(BindTest, FunctionTypeSupport) { | 261 TEST_F(BindTest, FunctionTypeSupport) { |
| 261 EXPECT_CALL(static_func_mock_, VoidMethod0()); | 262 EXPECT_CALL(static_func_mock_, VoidMethod0()); |
| 262 EXPECT_CALL(has_ref_, AddRef()).Times(3); | 263 EXPECT_CALL(has_ref_, AddRef()).Times(3); |
| 263 EXPECT_CALL(has_ref_, Release()).Times(3); | 264 EXPECT_CALL(has_ref_, Release()).Times(3); |
| 264 EXPECT_CALL(has_ref_, VoidMethod0()); | 265 EXPECT_CALL(has_ref_, VoidMethod0()); |
| 265 EXPECT_CALL(has_ref_, VoidConstMethod0()).Times(2); | 266 EXPECT_CALL(has_ref_, VoidConstMethod0()).Times(2); |
| 266 | 267 |
| 267 Closure normal_cb = Bind(&VoidFunc0); | 268 Closure normal_cb = Bind(&VoidFunc0); |
| 269 Callback<NoRef*(void)> normal_non_refcounted_cb = |
| 270 Bind(&PolymorphicIdentity<NoRef*>, &no_ref_); |
| 271 normal_cb.Run(); |
| 272 EXPECT_EQ(&no_ref_, normal_non_refcounted_cb.Run()); |
| 273 |
| 268 Closure method_cb = Bind(&HasRef::VoidMethod0, &has_ref_); | 274 Closure method_cb = Bind(&HasRef::VoidMethod0, &has_ref_); |
| 269 Closure const_method_nonconst_obj_cb = Bind(&HasRef::VoidConstMethod0, | 275 Closure const_method_nonconst_obj_cb = Bind(&HasRef::VoidConstMethod0, |
| 270 &has_ref_); | 276 &has_ref_); |
| 271 Closure const_method_const_obj_cb = Bind(&HasRef::VoidConstMethod0, | 277 Closure const_method_const_obj_cb = Bind(&HasRef::VoidConstMethod0, |
| 272 const_has_ref_ptr_); | 278 const_has_ref_ptr_); |
| 273 normal_cb.Run(); | |
| 274 method_cb.Run(); | 279 method_cb.Run(); |
| 275 const_method_nonconst_obj_cb.Run(); | 280 const_method_nonconst_obj_cb.Run(); |
| 276 const_method_const_obj_cb.Run(); | 281 const_method_const_obj_cb.Run(); |
| 277 | 282 |
| 278 Child child; | 283 Child child; |
| 279 child.value = 0; | 284 child.value = 0; |
| 280 Closure virtual_set_cb = Bind(&Parent::VirtualSet, &child); | 285 Closure virtual_set_cb = Bind(&Parent::VirtualSet, &child); |
| 281 virtual_set_cb.Run(); | 286 virtual_set_cb.Run(); |
| 282 EXPECT_EQ(kChildValue, child.value); | 287 EXPECT_EQ(kChildValue, child.value); |
| 283 | 288 |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 EXPECT_GE(2, copies); | 578 EXPECT_GE(2, copies); |
| 574 EXPECT_EQ(0, assigns); | 579 EXPECT_EQ(0, assigns); |
| 575 } | 580 } |
| 576 | 581 |
| 577 // Callback construction and assignment tests. | 582 // Callback construction and assignment tests. |
| 578 // - Construction from an InvokerStorageHolder should not cause ref/deref. | 583 // - Construction from an InvokerStorageHolder should not cause ref/deref. |
| 579 // - Assignment from other callback should only cause one ref | 584 // - Assignment from other callback should only cause one ref |
| 580 // | 585 // |
| 581 // TODO(ajwong): Is there actually a way to test this? | 586 // TODO(ajwong): Is there actually a way to test this? |
| 582 | 587 |
| 583 // No-compile tests. These should not compile. If they do, we are allowing | |
| 584 // error-prone, or incorrect behavior in the callback system. Uncomment the | |
| 585 // tests to check. | |
| 586 TEST_F(BindTest, NoCompile) { | |
| 587 // - Method bound to const-object. | |
| 588 // | |
| 589 // Only const methods should be allowed to work with const objects. | |
| 590 // | |
| 591 // Callback<void(void)> method_to_const_cb = | |
| 592 // Bind(&HasRef::VoidMethod0, const_has_ref_ptr_); | |
| 593 // method_to_const_cb.Run(); | |
| 594 | |
| 595 // - Method bound to non-refcounted object. | |
| 596 // - Const Method bound to non-refcounted object. | |
| 597 // | |
| 598 // We require refcounts unless you have Unretained(). | |
| 599 // | |
| 600 // Callback<void(void)> no_ref_cb = | |
| 601 // Bind(&NoRef::VoidMethod0, &no_ref_); | |
| 602 // no_ref_cb.Run(); | |
| 603 // Callback<void(void)> no_ref_const_cb = | |
| 604 // Bind(&NoRef::VoidConstMethod0, &no_ref_); | |
| 605 // no_ref_const_cb.Run(); | |
| 606 | |
| 607 // - Unretained() used with a refcounted object. | |
| 608 // | |
| 609 // If the object supports refcounts, unretaining it in the callback is a | |
| 610 // memory management contract break. | |
| 611 // Callback<void(void)> unretained_cb = | |
| 612 // Bind(&HasRef::VoidConstMethod0, Unretained(&has_ref_)); | |
| 613 // unretained_cb.Run(); | |
| 614 | |
| 615 // - Const argument used with non-const pointer parameter of same type. | |
| 616 // - Const argument used with non-const pointer parameter of super type. | |
| 617 // | |
| 618 // This is just a const-correctness check. | |
| 619 // | |
| 620 // const Parent* const_parent_ptr; | |
| 621 // const Child* const_child_ptr; | |
| 622 // Callback<Parent*(void)> pointer_same_cb = | |
| 623 // Bind(&PolymorphicIdentity<Parent*>, const_parent_ptr); | |
| 624 // pointer_same_cb.Run(); | |
| 625 // Callback<Parent*(void)> pointer_super_cb = | |
| 626 // Bind(&PolymorphicIdentity<Parent*>, const_child_ptr); | |
| 627 // pointer_super_cb.Run(); | |
| 628 | |
| 629 // - Construction of Callback<A> from Callback<B> if A is supertype of B. | |
| 630 // Specific example: Callback<void(void)> a; Callback<int(void)> b; a = b; | |
| 631 // | |
| 632 // While this is technically safe, most people aren't used to it when coding | |
| 633 // C++ so if this is happening, it is almost certainly an error. | |
| 634 // | |
| 635 // Callback<int(void)> cb_a0 = Bind(&Identity, 1); | |
| 636 // Callback<void(void)> cb_b0 = cb_a0; | |
| 637 | |
| 638 // - Assignment of Callback<A> from Callback<B> if A is supertype of B. | |
| 639 // See explanation above. | |
| 640 // | |
| 641 // Callback<int(void)> cb_a1 = Bind(&Identity, 1); | |
| 642 // Callback<void(void)> cb_b1; | |
| 643 // cb_a1 = cb_b1; | |
| 644 | |
| 645 // - Functions with reference parameters, unsupported. | |
| 646 // | |
| 647 // First, non-const reference parameters are disallowed by the Google | |
| 648 // style guide. Seconds, since we are doing argument forwarding it becomes | |
| 649 // very tricky to avoid copies, maintain const correctness, and not | |
| 650 // accidentally have the function be modifying a temporary, or a copy. | |
| 651 // | |
| 652 // NoRefParent p; | |
| 653 // Callback<int(Parent&)> ref_arg_cb = Bind(&UnwrapNoRefParentRef); | |
| 654 // ref_arg_cb.Run(p); | |
| 655 // Callback<int(void)> ref_cb = Bind(&UnwrapNoRefParentRef, p); | |
| 656 // ref_cb.Run(); | |
| 657 | |
| 658 // - A method should not be bindable with an array of objects. | |
| 659 // | |
| 660 // This is likely not wanted behavior. We specifically check for it though | |
| 661 // because it is possible, depending on how you implement prebinding, to | |
| 662 // implicitly convert an array type to a pointer type. | |
| 663 // | |
| 664 // HasRef p[10]; | |
| 665 // Callback<void(void)> method_bound_to_array_cb = | |
| 666 // Bind(&HasRef::VoidConstMethod0, p); | |
| 667 // method_bound_to_array_cb.Run(); | |
| 668 | |
| 669 // - Refcounted types should not be bound as a raw pointer. | |
| 670 // HasRef for_raw_ptr; | |
| 671 // Callback<void(void)> ref_count_as_raw_ptr = | |
| 672 // Bind(&VoidPolymorphic1<HasRef*>, &for_raw_ptr); | |
| 673 | |
| 674 // - WeakPtrs cannot be bound to methods with return types. | |
| 675 // HasRef for_raw_ptr; | |
| 676 // WeakPtrFactory<NoRef> weak_factory(&no_ref_); | |
| 677 // Callback<int(void)> weak_ptr_with_non_void_return_type = | |
| 678 // Bind(&NoRef::IntMethod0, weak_factory.GetWeakPtr()); | |
| 679 | |
| 680 // - Bind result cannot be assigned to Callbacks with a mismatching type. | |
| 681 // Closure callback_mismatches_bind_type = Bind(&VoidPolymorphic1<int>); | |
| 682 } | |
| 683 | |
| 684 #if defined(OS_WIN) | 588 #if defined(OS_WIN) |
| 685 int __fastcall FastCallFunc(int n) { | 589 int __fastcall FastCallFunc(int n) { |
| 686 return n; | 590 return n; |
| 687 } | 591 } |
| 688 | 592 |
| 689 int __stdcall StdCallFunc(int n) { | 593 int __stdcall StdCallFunc(int n) { |
| 690 return n; | 594 return n; |
| 691 } | 595 } |
| 692 | 596 |
| 693 // Windows specific calling convention support. | 597 // Windows specific calling convention support. |
| 694 // - Can bind a __fastcall function. | 598 // - Can bind a __fastcall function. |
| 695 // - Can bind a __stdcall function. | 599 // - Can bind a __stdcall function. |
| 696 TEST_F(BindTest, WindowsCallingConventions) { | 600 TEST_F(BindTest, WindowsCallingConventions) { |
| 697 Callback<int(void)> fastcall_cb = Bind(&FastCallFunc, 1); | 601 Callback<int(void)> fastcall_cb = Bind(&FastCallFunc, 1); |
| 698 EXPECT_EQ(1, fastcall_cb.Run()); | 602 EXPECT_EQ(1, fastcall_cb.Run()); |
| 699 | 603 |
| 700 Callback<int(void)> stdcall_cb = Bind(&StdCallFunc, 2); | 604 Callback<int(void)> stdcall_cb = Bind(&StdCallFunc, 2); |
| 701 EXPECT_EQ(2, stdcall_cb.Run()); | 605 EXPECT_EQ(2, stdcall_cb.Run()); |
| 702 } | 606 } |
| 703 #endif | 607 #endif |
| 704 | 608 |
| 705 } // namespace | 609 } // namespace |
| 706 } // namespace base | 610 } // namespace base |
| OLD | NEW |