Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2923)

Unified Diff: base/bind_unittest.cc

Issue 1498973002: WIP: base::Bind for rvalue references. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/bind_internal_win.h ('k') | base/callback.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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.
« no previous file with comments | « base/bind_internal_win.h ('k') | base/callback.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698