Chromium Code Reviews| 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. |