1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/cancelable_callback.h"
8 #include "base/bind_helpers.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/run_loop.h"
12 #include "testing/gtest/include/gtest/gtest.h"
17 class TestRefCounted
: public RefCountedThreadSafe
<TestRefCounted
> {
19 friend class RefCountedThreadSafe
<TestRefCounted
>;
23 void Increment(int* count
) { (*count
)++; }
24 void IncrementBy(int* count
, int n
) { (*count
) += n
; }
25 void RefCountedParam(const scoped_refptr
<TestRefCounted
>& ref_counted
) {}
28 // - Callback can be run multiple times.
29 // - After Cancel(), Run() completes but has no effect.
30 TEST(CancelableCallbackTest
, Cancel
) {
32 CancelableClosure
cancelable(
33 base::Bind(&Increment
, base::Unretained(&count
)));
35 base::Closure callback
= cancelable
.callback();
47 // Cancel() called multiple times.
48 // - Cancel() cancels all copies of the wrapped callback.
49 // - Calling Cancel() more than once has no effect.
50 // - After Cancel(), callback() returns a null callback.
51 TEST(CancelableCallbackTest
, MultipleCancel
) {
53 CancelableClosure
cancelable(
54 base::Bind(&Increment
, base::Unretained(&count
)));
56 base::Closure callback1
= cancelable
.callback();
57 base::Closure callback2
= cancelable
.callback();
66 // Calling Cancel() again has no effect.
69 // callback() of a cancelled callback is null.
70 base::Closure callback3
= cancelable
.callback();
71 EXPECT_TRUE(callback3
.is_null());
74 // CancelableCallback destroyed before callback is run.
75 // - Destruction of CancelableCallback cancels outstanding callbacks.
76 TEST(CancelableCallbackTest
, CallbackCanceledOnDestruction
) {
78 base::Closure callback
;
81 CancelableClosure
cancelable(
82 base::Bind(&Increment
, base::Unretained(&count
)));
84 callback
= cancelable
.callback();
93 // Cancel() called on bound closure with a RefCounted parameter.
94 // - Cancel drops wrapped callback (and, implicitly, its bound arguments).
95 TEST(CancelableCallbackTest
, CancelDropsCallback
) {
96 scoped_refptr
<TestRefCounted
> ref_counted
= new TestRefCounted
;
97 EXPECT_TRUE(ref_counted
->HasOneRef());
99 CancelableClosure
cancelable(base::Bind(RefCountedParam
, ref_counted
));
100 EXPECT_FALSE(cancelable
.IsCancelled());
101 EXPECT_TRUE(ref_counted
.get());
102 EXPECT_FALSE(ref_counted
->HasOneRef());
104 // There is only one reference to |ref_counted| after the Cancel().
106 EXPECT_TRUE(cancelable
.IsCancelled());
107 EXPECT_TRUE(ref_counted
.get());
108 EXPECT_TRUE(ref_counted
->HasOneRef());
112 // - Reset() replaces the existing wrapped callback with a new callback.
113 // - Reset() deactivates outstanding callbacks.
114 TEST(CancelableCallbackTest
, Reset
) {
116 CancelableClosure
cancelable(
117 base::Bind(&Increment
, base::Unretained(&count
)));
119 base::Closure callback
= cancelable
.callback();
127 base::Bind(&IncrementBy
, base::Unretained(&count
), 3));
128 EXPECT_FALSE(cancelable
.IsCancelled());
130 // The stale copy of the cancelable callback is non-null.
131 ASSERT_FALSE(callback
.is_null());
133 // The stale copy of the cancelable callback is no longer active.
137 base::Closure callback2
= cancelable
.callback();
138 ASSERT_FALSE(callback2
.is_null());
145 // - Cancel() transforms the CancelableCallback into a cancelled state.
146 TEST(CancelableCallbackTest
, IsNull
) {
147 CancelableClosure cancelable
;
148 EXPECT_TRUE(cancelable
.IsCancelled());
151 cancelable
.Reset(base::Bind(&Increment
,
152 base::Unretained(&count
)));
153 EXPECT_FALSE(cancelable
.IsCancelled());
156 EXPECT_TRUE(cancelable
.IsCancelled());
159 // CancelableCallback posted to a MessageLoop with PostTask.
160 // - Callbacks posted to a MessageLoop can be cancelled.
161 TEST(CancelableCallbackTest
, PostTask
) {
162 MessageLoop
loop(MessageLoop::TYPE_DEFAULT
);
165 CancelableClosure
cancelable(base::Bind(&Increment
,
166 base::Unretained(&count
)));
168 MessageLoop::current()->PostTask(FROM_HERE
, cancelable
.callback());
169 RunLoop().RunUntilIdle();
173 MessageLoop::current()->PostTask(FROM_HERE
, cancelable
.callback());
175 // Cancel before running the message loop.
177 RunLoop().RunUntilIdle();
179 // Callback never ran due to cancellation; count is the same.