| Index: base/bind_unittest.cc
|
| diff --git a/base/bind_unittest.cc b/base/bind_unittest.cc
|
| index f885403c92dfa68b0ba0a4afe534e4c3d39ad918..50845be62041ff639a1fdfcb8d6798fc597721ce 100644
|
| --- a/base/bind_unittest.cc
|
| +++ b/base/bind_unittest.cc
|
| @@ -150,7 +150,7 @@ class DeleteCounter {
|
|
|
| template <typename T>
|
| T PassThru(T scoper) {
|
| - return scoper.Pass();
|
| + return scoper;
|
| }
|
|
|
| // Some test functions that we can Bind to.
|
| @@ -327,8 +327,8 @@ TEST_F(BindTest, CurryingRvalueResultOfBind) {
|
| // preserve virtual dispatch).
|
| TEST_F(BindTest, FunctionTypeSupport) {
|
| EXPECT_CALL(static_func_mock_, VoidMethod0());
|
| - EXPECT_CALL(has_ref_, AddRef()).Times(5);
|
| - EXPECT_CALL(has_ref_, Release()).Times(5);
|
| + EXPECT_CALL(has_ref_, AddRef()).Times(4);
|
| + EXPECT_CALL(has_ref_, Release()).Times(4);
|
| EXPECT_CALL(has_ref_, VoidMethod0()).Times(2);
|
| EXPECT_CALL(has_ref_, VoidConstMethod0()).Times(2);
|
|
|
| @@ -715,7 +715,7 @@ TEST_F(BindTest, ScopedPtr) {
|
| // Tests the Passed() function's support for pointers.
|
| scoped_ptr<DeleteCounter> ptr(new DeleteCounter(&deletes));
|
| Callback<scoped_ptr<DeleteCounter>(void)> unused_callback =
|
| - Bind(&PassThru<scoped_ptr<DeleteCounter> >, Passed(&ptr));
|
| + Bind(&PassThru<scoped_ptr<DeleteCounter>>, Passed(&ptr));
|
| EXPECT_FALSE(ptr.get());
|
| EXPECT_EQ(0, deletes);
|
|
|
| @@ -752,6 +752,105 @@ TEST_F(BindTest, ScopedPtr) {
|
| cb_unbound.Run(ptr.Pass());
|
| }
|
|
|
| +// RValue support.
|
| +// - Bind() can take move-only values by RValue-reference.
|
| +// - Using an RValue gives Callback Ownership.
|
| +// - Ownership is transferred from Callback to callee on the first Run().
|
| +// - Callback supports unbound arguments.
|
| +TEST_F(BindTest, ScopedPtrRValue) {
|
| + int deletes = 0;
|
| +
|
| + // Tests the Passed() function's support for pointers.
|
| + scoped_ptr<DeleteCounter> ptr(new DeleteCounter(&deletes));
|
| + Callback<scoped_ptr<DeleteCounter>(void)> unused_callback =
|
| + Bind(&PassThru<scoped_ptr<DeleteCounter>>, std::move(ptr));
|
| + EXPECT_FALSE(ptr.get());
|
| + EXPECT_EQ(0, deletes);
|
| +
|
| + // If we never invoke the Callback, it retains ownership and deletes.
|
| + unused_callback.Reset();
|
| + EXPECT_EQ(1, deletes);
|
| +
|
| + // Tests the Passed() function's support for rvalues.
|
| + deletes = 0;
|
| + DeleteCounter* counter = new DeleteCounter(&deletes);
|
| + Callback<scoped_ptr<DeleteCounter>(void)> callback =
|
| + Bind(&PassThru<scoped_ptr<DeleteCounter> >,
|
| + scoped_ptr<DeleteCounter>(counter));
|
| + EXPECT_FALSE(ptr.get());
|
| + EXPECT_EQ(0, deletes);
|
| +
|
| + // Check that ownership can be transferred back out.
|
| + scoped_ptr<DeleteCounter> result = callback.Run();
|
| + ASSERT_EQ(counter, result.get());
|
| + EXPECT_EQ(0, deletes);
|
| +
|
| + // Resetting does not delete since ownership was transferred.
|
| + callback.Reset();
|
| + EXPECT_EQ(0, deletes);
|
| +
|
| + // Ensure that we actually did get ownership.
|
| + result.reset();
|
| + EXPECT_EQ(1, deletes);
|
| +
|
| + // Test unbound argument forwarding.
|
| + Callback<scoped_ptr<DeleteCounter>(scoped_ptr<DeleteCounter>)> cb_unbound =
|
| + Bind(&PassThru<scoped_ptr<DeleteCounter> >);
|
| + ptr.reset(new DeleteCounter(&deletes));
|
| + cb_unbound.Run(std::move(ptr));
|
| +}
|
| +
|
| +// RValue support.
|
| +// - Bind() can take move-only values by RValue-reference.
|
| +// - Using an RValue gives Callback Ownership.
|
| +// - Ownership is transferred from Callback to callee on the first Run().
|
| +// - Callback supports unbound arguments.
|
| +TEST_F(BindTest, ContainerOfMoveOnlyValues) {
|
| + int deletes = 0;
|
| +
|
| + // Tests the Passed() function's support for pointers.
|
| + std::vector<scoped_ptr<DeleteCounter>> ptrs;
|
| + ptrs.emplace_back(new DeleteCounter(&deletes));
|
| + Callback<std::vector<scoped_ptr<DeleteCounter>>(void)> unused_callback =
|
| + Bind(&PassThru<std::vector<scoped_ptr<DeleteCounter>>>, std::move(ptrs));
|
| + EXPECT_EQ(0, deletes);
|
| +
|
| + // If we never invoke the Callback, it retains ownership and deletes.
|
| + unused_callback.Reset();
|
| + EXPECT_EQ(1, deletes);
|
| +
|
| + // Tests the Passed() function's support for rvalues.
|
| + deletes = 0;
|
| + ptrs.clear();
|
| + DeleteCounter* counter = new DeleteCounter(&deletes);
|
| + ptrs.emplace_back(counter);
|
| + Callback<std::vector<scoped_ptr<DeleteCounter>>(void)> callback =
|
| + Bind(&PassThru<std::vector<scoped_ptr<DeleteCounter>>>, std::move(ptrs));
|
| + EXPECT_EQ(0, deletes);
|
| +
|
| + // Check that ownership can be transferred back out.
|
| + std::vector<scoped_ptr<DeleteCounter>> result = callback.Run();
|
| + ASSERT_EQ(1u, result.size());
|
| + ASSERT_EQ(counter, result[0].get());
|
| + EXPECT_EQ(0, deletes);
|
| +
|
| + // Resetting does not delete since ownership was transferred.
|
| + callback.Reset();
|
| + EXPECT_EQ(0, deletes);
|
| +
|
| + // Ensure that we actually did get ownership.
|
| + result.clear();
|
| + EXPECT_EQ(1, deletes);
|
| +
|
| + // Test unbound argument forwarding.
|
| + Callback<std::vector<scoped_ptr<DeleteCounter>>(
|
| + std::vector<scoped_ptr<DeleteCounter>>)>
|
| + cb_unbound = Bind(&PassThru<std::vector<scoped_ptr<DeleteCounter>>>);
|
| + ptrs.clear();
|
| + ptrs.emplace_back(new DeleteCounter(&deletes));
|
| + cb_unbound.Run(std::move(ptrs));
|
| +}
|
| +
|
| // Argument Copy-constructor usage for non-reference parameters.
|
| // - Bound arguments are only copied once.
|
| // - Forwarded arguments are only copied once.
|
|
|