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 |