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 |