Index: base/bind_unittest.cc |
diff --git a/base/bind_unittest.cc b/base/bind_unittest.cc |
index 0fdd24115012c53f8fa765f136fa7df457c6675e..4055ac76ee31d492ba8a4965ae772ba05d173d29 100644 |
--- a/base/bind_unittest.cc |
+++ b/base/bind_unittest.cc |
@@ -5,6 +5,9 @@ |
#include "base/bind.h" |
#include "base/callback.h" |
+#include "base/memory/pass_scoped_ptr.h" |
+#include "base/memory/ref_counted.h" |
+#include "base/memory/weak_ptr.h" |
#include "testing/gmock/include/gmock/gmock.h" |
#include "testing/gtest/include/gtest/gtest.h" |
@@ -149,6 +152,18 @@ class DeleteCounter { |
int* deletes_; |
}; |
+DeleteCounter* MaybeCapture(PassScopedPtr<DeleteCounter> ptr, |
+ bool expect_valid, |
+ bool should_capture) { |
+ EXPECT_EQ(expect_valid, ptr.is_valid()); |
+ if (should_capture) { |
+ scoped_ptr<DeleteCounter> scoped; |
+ ptr.ToScopedPtr(&scoped); |
+ return scoped.release(); |
+ } |
+ return NULL; |
+} |
+ |
// Some test functions that we can Bind to. |
template <typename T> |
T PolymorphicIdentity(T t) { |
@@ -631,6 +646,54 @@ TEST_F(BindTest, Owned) { |
EXPECT_EQ(1, deletes); |
} |
+// PassScopedPtr() wrapper support. |
+// - Binding PassScopedPtr gives Callback Ownership. |
+// - Callback only transfers ownership of PassScopedPtr on explicit Pass() |
+// or ToScopedPtr() call. |
+TEST_F(BindTest, PassScopedPtr) { |
+ int deletes = 0; |
+ |
+ // If we never invoke the Callback, it returns ownership and deletes. |
+ Callback<DeleteCounter*(bool, bool)> unused_callback = |
+ Bind(&MaybeCapture, |
+ PassScopedPtr<DeleteCounter>(new DeleteCounter(&deletes)).Pass()); |
+ EXPECT_EQ(0, deletes); |
levin
2011/11/02 00:51:30
Shouldn't these EXPECT calls be ASSERT?
If someth
awong
2011/11/11 00:21:58
Good catch. Fixed.
|
+ unused_callback.Reset(); |
+ EXPECT_EQ(1, deletes); |
+ |
+ // TODO(ajwong): Also test that Pass() captures the value, and that |
+ // after the value is captured, is_valid() is false. |
+ |
+ // Check that ownership is only transfered if ToScopedPtr() is called. |
+ deletes = 0; |
+ DeleteCounter* counter = new DeleteCounter(&deletes); |
+ EXPECT_EQ(0, deletes); |
+ Callback<DeleteCounter*(bool, bool)> callback = |
+ Bind(&MaybeCapture, |
+ PassScopedPtr<DeleteCounter>(counter).Pass()); |
+ EXPECT_EQ(0, deletes); |
+ |
+ // Multiple calls do not capture. |
+ // |
+ // TODO(ajwong): Actually assert is_valid() inside the test. |
+ EXPECT_TRUE(callback.Run(true, false) == NULL); |
+ EXPECT_TRUE(callback.Run(true, false) == NULL); |
+ EXPECT_EQ(0, deletes); |
+ |
+ // Transfer ownership out. |
+ scoped_ptr<DeleteCounter> result(callback.Run(true, true)); |
+ EXPECT_EQ(counter, result.get()); |
+ EXPECT_EQ(0, deletes); |
+ |
+ // Next invocation will find the PassScopedPtr is invalid. |
+ EXPECT_TRUE(callback.Run(false, false) == NULL); |
+ EXPECT_EQ(0, deletes); |
+ |
+ // Resetting does not delete since ownership was transfered. |
+ callback.Reset(); |
+ EXPECT_EQ(0, deletes); |
levin
2011/11/02 00:51:30
Why not "delete counter" here to avoid leaks in te
awong
2011/11/11 00:21:58
Don't need to. result owns it. There's no way to
|
+} |
+ |
// Argument Copy-constructor usage for non-reference parameters. |
// - Bound arguments are only copied once. |
// - Forwarded arguments are only copied once. |