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.h"
11 #include "testing/gtest/include/gtest/gtest.h"
16 class TestRefCounted
: public RefCountedThreadSafe
<TestRefCounted
> {
18 friend class RefCountedThreadSafe
<TestRefCounted
>;
22 void Increment(int* count
) { (*count
)++; }
23 void IncrementBy(int* count
, int n
) { (*count
) += n
; }
24 void RefCountedParam(const scoped_refptr
<TestRefCounted
>& ref_counted
) {}
27 // - Callback can be run multiple times.
28 // - After Cancel(), Run() completes but has no effect.
29 TEST(CancelableCallbackTest
, Cancel
) {
31 CancelableClosure
cancelable(
32 base::Bind(&Increment
, base::Unretained(&count
)));
34 base::Closure callback
= cancelable
.callback();
46 // Cancel() called multiple times.
47 // - Cancel() cancels all copies of the wrapped callback.
48 // - Calling Cancel() more than once has no effect.
49 // - After Cancel(), callback() returns a null callback.
50 TEST(CancelableCallbackTest
, MultipleCancel
) {
52 CancelableClosure
cancelable(
53 base::Bind(&Increment
, base::Unretained(&count
)));
55 base::Closure callback1
= cancelable
.callback();
56 base::Closure callback2
= cancelable
.callback();
65 // Calling Cancel() again has no effect.
68 // callback() of a cancelled callback is null.
69 base::Closure callback3
= cancelable
.callback();
70 EXPECT_TRUE(callback3
.is_null());
73 // CancelableCallback destroyed before callback is run.
74 // - Destruction of CancelableCallback cancels outstanding callbacks.
75 TEST(CancelableCallbackTest
, CallbackCanceledOnDestruction
) {
77 base::Closure callback
;
80 CancelableClosure
cancelable(
81 base::Bind(&Increment
, base::Unretained(&count
)));
83 callback
= cancelable
.callback();
92 // Cancel() called on bound closure with a RefCounted parameter.
93 // - Cancel drops wrapped callback (and, implicitly, its bound arguments).
94 TEST(CancelableCallbackTest
, CancelDropsCallback
) {
95 scoped_refptr
<TestRefCounted
> ref_counted
= new TestRefCounted
;
96 EXPECT_TRUE(ref_counted
->HasOneRef());
98 CancelableClosure
cancelable(base::Bind(RefCountedParam
, ref_counted
));
99 EXPECT_FALSE(cancelable
.IsCancelled());
100 EXPECT_TRUE(ref_counted
.get());
101 EXPECT_FALSE(ref_counted
->HasOneRef());
103 // There is only one reference to |ref_counted| after the Cancel().
105 EXPECT_TRUE(cancelable
.IsCancelled());
106 EXPECT_TRUE(ref_counted
.get());
107 EXPECT_TRUE(ref_counted
->HasOneRef());
111 // - Reset() replaces the existing wrapped callback with a new callback.
112 // - Reset() deactivates outstanding callbacks.
113 TEST(CancelableCallbackTest
, Reset
) {
115 CancelableClosure
cancelable(
116 base::Bind(&Increment
, base::Unretained(&count
)));
118 base::Closure callback
= cancelable
.callback();
126 base::Bind(&IncrementBy
, base::Unretained(&count
), 3));
127 EXPECT_FALSE(cancelable
.IsCancelled());
129 // The stale copy of the cancelable callback is non-null.
130 ASSERT_FALSE(callback
.is_null());
132 // The stale copy of the cancelable callback is no longer active.
136 base::Closure callback2
= cancelable
.callback();
137 ASSERT_FALSE(callback2
.is_null());
144 // - Cancel() transforms the CancelableCallback into a cancelled state.
145 TEST(CancelableCallbackTest
, IsNull
) {
146 CancelableClosure cancelable
;
147 EXPECT_TRUE(cancelable
.IsCancelled());
150 cancelable
.Reset(base::Bind(&Increment
,
151 base::Unretained(&count
)));
152 EXPECT_FALSE(cancelable
.IsCancelled());
155 EXPECT_TRUE(cancelable
.IsCancelled());
158 // CancelableCallback posted to a MessageLoop with PostTask.
159 // - Callbacks posted to a MessageLoop can be cancelled.
160 TEST(CancelableCallbackTest
, PostTask
) {
161 MessageLoop
loop(MessageLoop::TYPE_DEFAULT
);
164 CancelableClosure
cancelable(base::Bind(&Increment
,
165 base::Unretained(&count
)));
167 MessageLoop::current()->PostTask(FROM_HERE
, cancelable
.callback());
168 MessageLoop::current()->PostTask(FROM_HERE
, MessageLoop::QuitClosure());
169 MessageLoop::current()->Run();
173 MessageLoop::current()->PostTask(FROM_HERE
, cancelable
.callback());
174 MessageLoop::current()->PostTask(FROM_HERE
, MessageLoop::QuitClosure());
176 // Cancel before running the message loop.
178 MessageLoop::current()->Run();
180 // Callback never ran due to cancellation; count is the same.