Index: base/cancelable_callback_unittest.cc |
diff --git a/base/cancelable_callback_unittest.cc b/base/cancelable_callback_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e3713df436b6cf69182b5cba5d45300ace02b622 |
--- /dev/null |
+++ b/base/cancelable_callback_unittest.cc |
@@ -0,0 +1,159 @@ |
+// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "base/cancelable_callback.h" |
csilv
2011/11/23 19:37:30
add includes for base/bind.h, base/bind_helpers.h
James Hawkins
2011/11/23 22:12:52
Done.
|
+#include "base/message_loop.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace base { |
+namespace { |
+ |
+class Counter { |
awong
2011/11/23 19:58:23
Why use a class instead of a bare function like:
James Hawkins
2011/11/23 22:12:52
This is an evolved version of a class I copied fro
|
+ public: |
+ Counter() : count_(0) { } |
+ void IncrementCount() { count_++; } |
+ void IncrementCountBy(int n) { count_ += n; } |
+ int count() const { return count_; } |
+ |
+ private: |
+ int count_; |
+}; |
+ |
+TEST(CancelableCallbackTest, Cancel) { |
awong
2011/11/23 19:58:23
For things related to bind/callback, I've been try
James Hawkins
2011/11/23 22:12:52
Done.
|
+ Counter counter; |
+ CancelableCallback cancelable(base::Bind(&Counter::IncrementCount, |
+ base::Unretained(&counter))); |
+ |
+ base::Closure callback = cancelable.callback(); |
+ callback.Run(); |
+ EXPECT_EQ(1, counter.count()); |
+ |
+ callback.Run(); |
+ EXPECT_EQ(2, counter.count()); |
+ |
+ cancelable.Cancel(); |
+ callback.Run(); |
+ EXPECT_EQ(2, counter.count()); |
+} |
+ |
+TEST(CancelableCallbackTest, MultipleCancel) { |
+ Counter counter; |
+ CancelableCallback cancelable(base::Bind(&Counter::IncrementCount, |
+ base::Unretained(&counter))); |
+ |
+ base::Closure callback1 = cancelable.callback(); |
+ cancelable.Cancel(); |
+ |
+ base::Closure callback2 = cancelable.callback(); |
+ base::Closure callback3 = cancelable.callback(); |
+ cancelable.Cancel(); |
groby-ooo-7-16
2011/11/23 19:18:57
I suspect it would be interesting for people to kn
James Hawkins
2011/11/23 19:37:10
How so?
groby-ooo-7-16
2011/11/23 19:43:14
Will callback2/3 be running without it? (It won't,
James Hawkins
2011/11/23 22:12:52
I've rearranged this, per-offline.
|
+ |
+ callback1.Run(); |
+ EXPECT_EQ(0, counter.count()); |
+ |
+ callback2.Run(); |
+ EXPECT_EQ(0, counter.count()); |
+ |
+ cancelable.Cancel(); |
+ callback3.Run(); |
+ EXPECT_EQ(0, counter.count()); |
+} |
+ |
+TEST(CancelableCallbackTest, NArity) { |
awong
2011/11/23 19:58:23
What's NArity mean in this context?
If you're tes
James Hawkins
2011/11/23 22:12:52
Done.
|
+ Counter counter; |
+ CancelableCallback cancelable( |
+ base::Bind(&Counter::IncrementCountBy, base::Unretained(&counter), 5)); |
+ |
+ base::Closure callback = cancelable.callback(); |
+ callback.Run(); |
+ EXPECT_EQ(5, counter.count()); |
+ |
+ callback.Run(); |
+ EXPECT_EQ(10, counter.count()); |
+ |
+ cancelable.Cancel(); |
+ callback.Run(); |
+ EXPECT_EQ(10, counter.count()); |
+} |
+ |
+TEST(CancelableCallbackTest, CallbackCanceledOnDestruction) { |
+ Counter counter; |
+ base::Closure callback; |
+ |
+ { |
+ CancelableCallback cancelable(base::Bind(&Counter::IncrementCount, |
+ base::Unretained(&counter))); |
+ |
+ callback = cancelable.callback(); |
+ callback.Run(); |
+ EXPECT_EQ(1, counter.count()); |
+ } |
+ |
+ callback.Run(); |
+ EXPECT_EQ(1, counter.count()); |
+} |
+ |
+TEST(CancelableCallbackTest, Reset) { |
+ Counter counter; |
+ CancelableCallback cancelable(base::Bind(&Counter::IncrementCount, |
+ base::Unretained(&counter))); |
+ |
+ base::Closure callback = cancelable.callback(); |
+ callback.Run(); |
+ EXPECT_EQ(1, counter.count()); |
+ |
+ callback.Run(); |
+ EXPECT_EQ(2, counter.count()); |
+ |
+ cancelable.Reset(base::Bind(&Counter::IncrementCountBy, |
+ base::Unretained(&counter), 3)); |
awong
2011/11/23 19:58:23
Also EXPECT_TRUE(cancelable.is_null())?
James Hawkins
2011/11/23 22:12:52
|cancelable| is not null at this point. I've added
|
+ |
+ // The stale copy of the cancelable callback is no longer active. |
+ callback.Run(); |
+ EXPECT_EQ(2, counter.count()); |
+ |
+ base::Closure callback2 = cancelable.callback(); |
+ callback2.Run(); |
+ EXPECT_EQ(5, counter.count()); |
+} |
+ |
+TEST(CancelableCallbackTest, IsNull) { |
+ CancelableCallback cancelable; |
+ EXPECT_TRUE(cancelable.is_null()); |
+ |
+ Counter counter; |
+ cancelable.Reset(base::Bind(&Counter::IncrementCount, |
+ base::Unretained(&counter))); |
+ EXPECT_FALSE(cancelable.is_null()); |
+ |
+ cancelable.Cancel(); |
+ EXPECT_TRUE(cancelable.is_null()); |
+} |
+ |
+TEST(CancelableCallbackTest, PostTask) { |
+ MessageLoop loop(MessageLoop::TYPE_DEFAULT); |
+ |
+ Counter counter; |
+ CancelableCallback cancelable(base::Bind(&Counter::IncrementCount, |
+ base::Unretained(&counter))); |
+ |
+ MessageLoop::current()->PostTask(FROM_HERE, cancelable.callback()); |
+ MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure()); |
+ MessageLoop::current()->Run(); |
+ |
+ EXPECT_EQ(1, counter.count()); |
+ |
+ MessageLoop::current()->PostTask(FROM_HERE, cancelable.callback()); |
+ MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure()); |
+ |
+ // Cancel before running the message loop. |
+ cancelable.Cancel(); |
+ MessageLoop::current()->Run(); |
+ |
+ // Callback never ran due to cancellation; count is the same. |
+ EXPECT_EQ(1, counter.count()); |
+} |
+ |
+} // namespace |
+} // namespace base |