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. 4 5 #include "base/cancelable_callback.h" 6 7 #include <memory> 8 9 #include "base/bind.h" 10 #include "base/bind_helpers.h" 11 #include "base/location.h" 12 #include "base/memory/ptr_util.h" 13 #include "base/memory/ref_counted.h" 14 #include "base/run_loop.h" 15 #include "base/single_thread_task_runner.h" 16 #include "base/threading/thread_task_runner_handle.h" 17 #include "testing/gtest/include/gtest/gtest.h" 18 19 namespace base { 20 namespace { 21 22 class TestRefCounted : public RefCountedThreadSafe<TestRefCounted> { 23 private: 24 friend class RefCountedThreadSafe<TestRefCounted>; 25 ~TestRefCounted() {}; 26 }; 27 28 void Increment(int* count) { (*count)++; } 29 void IncrementBy(int* count, int n) { (*count) += n; } 30 void RefCountedParam(const scoped_refptr<TestRefCounted>& ref_counted) {} 31 32 void OnMoveOnlyReceived(int* value, std::unique_ptr<int> result) { 33 *value = *result; 34 } 35 36 // Cancel(). 37 // - Callback can be run multiple times. 38 // - After Cancel(), Run() completes but has no effect. 39 TEST(CancelableCallbackTest, Cancel) { 40 int count = 0; 41 CancelableClosure cancelable( 42 base::Bind(&Increment, base::Unretained(&count))); 43 44 base::Closure callback = cancelable.callback(); 45 callback.Run(); 46 EXPECT_EQ(1, count); 47 48 callback.Run(); 49 EXPECT_EQ(2, count); 50 51 cancelable.Cancel(); 52 callback.Run(); 53 EXPECT_EQ(2, count); 54 } 55 56 // Cancel() called multiple times. 57 // - Cancel() cancels all copies of the wrapped callback. 58 // - Calling Cancel() more than once has no effect. 59 // - After Cancel(), callback() returns a null callback. 60 TEST(CancelableCallbackTest, MultipleCancel) { 61 int count = 0; 62 CancelableClosure cancelable( 63 base::Bind(&Increment, base::Unretained(&count))); 64 65 base::Closure callback1 = cancelable.callback(); 66 base::Closure callback2 = cancelable.callback(); 67 cancelable.Cancel(); 68 69 callback1.Run(); 70 EXPECT_EQ(0, count); 71 72 callback2.Run(); 73 EXPECT_EQ(0, count); 74 75 // Calling Cancel() again has no effect. 76 cancelable.Cancel(); 77 78 // callback() of a cancelled callback is null. 79 base::Closure callback3 = cancelable.callback(); 80 EXPECT_TRUE(callback3.is_null()); 81 } 82 83 // CancelableCallback destroyed before callback is run. 84 // - Destruction of CancelableCallback cancels outstanding callbacks. 85 TEST(CancelableCallbackTest, CallbackCanceledOnDestruction) { 86 int count = 0; 87 base::Closure callback; 88 89 { 90 CancelableClosure cancelable( 91 base::Bind(&Increment, base::Unretained(&count))); 92 93 callback = cancelable.callback(); 94 callback.Run(); 95 EXPECT_EQ(1, count); 96 } 97 98 callback.Run(); 99 EXPECT_EQ(1, count); 100 } 101 102 // Cancel() called on bound closure with a RefCounted parameter. 103 // - Cancel drops wrapped callback (and, implicitly, its bound arguments). 104 TEST(CancelableCallbackTest, CancelDropsCallback) { 105 scoped_refptr<TestRefCounted> ref_counted = new TestRefCounted; 106 EXPECT_TRUE(ref_counted->HasOneRef()); 107 108 CancelableClosure cancelable(base::Bind(RefCountedParam, ref_counted)); 109 EXPECT_FALSE(cancelable.IsCancelled()); 110 EXPECT_TRUE(ref_counted.get()); 111 EXPECT_FALSE(ref_counted->HasOneRef()); 112 113 // There is only one reference to |ref_counted| after the Cancel(). 114 cancelable.Cancel(); 115 EXPECT_TRUE(cancelable.IsCancelled()); 116 EXPECT_TRUE(ref_counted.get()); 117 EXPECT_TRUE(ref_counted->HasOneRef()); 118 } 119 120 // Reset(). 121 // - Reset() replaces the existing wrapped callback with a new callback. 122 // - Reset() deactivates outstanding callbacks. 123 TEST(CancelableCallbackTest, Reset) { 124 int count = 0; 125 CancelableClosure cancelable( 126 base::Bind(&Increment, base::Unretained(&count))); 127 128 base::Closure callback = cancelable.callback(); 129 callback.Run(); 130 EXPECT_EQ(1, count); 131 132 callback.Run(); 133 EXPECT_EQ(2, count); 134 135 cancelable.Reset( 136 base::Bind(&IncrementBy, base::Unretained(&count), 3)); 137 EXPECT_FALSE(cancelable.IsCancelled()); 138 139 // The stale copy of the cancelable callback is non-null. 140 ASSERT_FALSE(callback.is_null()); 141 142 // The stale copy of the cancelable callback is no longer active. 143 callback.Run(); 144 EXPECT_EQ(2, count); 145 146 base::Closure callback2 = cancelable.callback(); 147 ASSERT_FALSE(callback2.is_null()); 148 149 callback2.Run(); 150 EXPECT_EQ(5, count); 151 } 152 153 // IsCanceled(). 154 // - Cancel() transforms the CancelableCallback into a cancelled state. 155 TEST(CancelableCallbackTest, IsNull) { 156 CancelableClosure cancelable; 157 EXPECT_TRUE(cancelable.IsCancelled()); 158 159 int count = 0; 160 cancelable.Reset(base::Bind(&Increment, 161 base::Unretained(&count))); 162 EXPECT_FALSE(cancelable.IsCancelled()); 163 164 cancelable.Cancel(); 165 EXPECT_TRUE(cancelable.IsCancelled()); 166 } 167 168 // CancelableCallback posted to a MessageLoop with PostTask. 169 // - Callbacks posted to a MessageLoop can be cancelled. 170 TEST(CancelableCallbackTest, PostTask) { 171 MessageLoop loop; 172 173 int count = 0; 174 CancelableClosure cancelable(base::Bind(&Increment, 175 base::Unretained(&count))); 176 177 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, cancelable.callback()); 178 RunLoop().RunUntilIdle(); 179 180 EXPECT_EQ(1, count); 181 182 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, cancelable.callback()); 183 184 // Cancel before running the message loop. 185 cancelable.Cancel(); 186 RunLoop().RunUntilIdle(); 187 188 // Callback never ran due to cancellation; count is the same. 189 EXPECT_EQ(1, count); 190 } 191 192 // CancelableCallback can be used with move-only types. 193 TEST(CancelableCallbackTest, MoveOnlyType) { 194 const int kExpectedResult = 42; 195 196 int result = 0; 197 CancelableCallback<void(std::unique_ptr<int>)> cb( 198 base::Bind(&OnMoveOnlyReceived, base::Unretained(&result))); 199 cb.callback().Run(base::WrapUnique(new int(kExpectedResult))); 200 201 EXPECT_EQ(kExpectedResult, result); 202 } 203 204 } // namespace 205 } // namespace base 206