1 // Copyright (c) 2012 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/callback.h"
10 #include "base/bind.h"
11 #include "base/callback_helpers.h"
12 #include "base/callback_internal.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/test/test_timeouts.h"
15 #include "base/threading/thread.h"
16 #include "testing/gtest/include/gtest/gtest.h"
20 void NopInvokeFunc() {}
22 // White-box testpoints to inject into a callback object for checking
23 // comparators and emptiness APIs. Use a BindState that is specialized based on
24 // a type we declared in the anonymous namespace above to remove any chance of
25 // colliding with another instantiation and breaking the one-definition-rule.
26 struct FakeBindState : internal::BindStateBase {
27 FakeBindState() : BindStateBase(&NopInvokeFunc, &Destroy, &IsCancelled) {}
30 ~FakeBindState() = default;
31 static void Destroy(const internal::BindStateBase* self) {
32 delete static_cast<const FakeBindState*>(self);
34 static bool IsCancelled(const internal::BindStateBase*,
35 internal::BindStateBase::CancellationQueryMode mode) {
37 case internal::BindStateBase::IS_CANCELLED:
39 case internal::BindStateBase::MAYBE_VALID:
48 class CallbackTest : public ::testing::Test {
51 : callback_a_(new FakeBindState()), callback_b_(new FakeBindState()) {}
53 ~CallbackTest() override = default;
56 RepeatingCallback<void()> callback_a_;
57 const RepeatingCallback<void()> callback_b_; // Ensure APIs work with const.
58 RepeatingCallback<void()> null_callback_;
61 // Ensure we can create unbound callbacks. We need this to be able to store
62 // them in class members that can be initialized later.
63 TEST_F(CallbackTest, DefaultConstruction) {
64 RepeatingCallback<void()> c0;
65 RepeatingCallback<void(int)> c1;
66 RepeatingCallback<void(int, int)> c2;
67 RepeatingCallback<void(int, int, int)> c3;
68 RepeatingCallback<void(int, int, int, int)> c4;
69 RepeatingCallback<void(int, int, int, int, int)> c5;
70 RepeatingCallback<void(int, int, int, int, int, int)> c6;
72 EXPECT_TRUE(c0.is_null());
73 EXPECT_TRUE(c1.is_null());
74 EXPECT_TRUE(c2.is_null());
75 EXPECT_TRUE(c3.is_null());
76 EXPECT_TRUE(c4.is_null());
77 EXPECT_TRUE(c5.is_null());
78 EXPECT_TRUE(c6.is_null());
81 TEST_F(CallbackTest, IsNull) {
82 EXPECT_TRUE(null_callback_.is_null());
83 EXPECT_FALSE(callback_a_.is_null());
84 EXPECT_FALSE(callback_b_.is_null());
87 TEST_F(CallbackTest, Equals) {
88 EXPECT_TRUE(callback_a_.Equals(callback_a_));
89 EXPECT_FALSE(callback_a_.Equals(callback_b_));
90 EXPECT_FALSE(callback_b_.Equals(callback_a_));
92 // We should compare based on instance, not type.
93 RepeatingCallback<void()> callback_c(new FakeBindState());
94 RepeatingCallback<void()> callback_a2 = callback_a_;
95 EXPECT_TRUE(callback_a_.Equals(callback_a2));
96 EXPECT_FALSE(callback_a_.Equals(callback_c));
98 // Empty, however, is always equal to empty.
99 RepeatingCallback<void()> empty2;
100 EXPECT_TRUE(null_callback_.Equals(empty2));
103 TEST_F(CallbackTest, Reset) {
104 // Resetting should bring us back to empty.
105 ASSERT_FALSE(callback_a_.is_null());
106 ASSERT_FALSE(callback_a_.Equals(null_callback_));
110 EXPECT_TRUE(callback_a_.is_null());
111 EXPECT_TRUE(callback_a_.Equals(null_callback_));
114 TEST_F(CallbackTest, Move) {
115 // Moving should reset the callback.
116 ASSERT_FALSE(callback_a_.is_null());
117 ASSERT_FALSE(callback_a_.Equals(null_callback_));
119 auto tmp = std::move(callback_a_);
121 EXPECT_TRUE(callback_a_.is_null());
122 EXPECT_TRUE(callback_a_.Equals(null_callback_));
125 struct TestForReentrancy {
127 : cb_already_run(false),
128 cb(BindRepeating(&TestForReentrancy::AssertCBIsNull,
129 Unretained(this))) {}
130 void AssertCBIsNull() {
131 ASSERT_TRUE(cb.is_null());
132 cb_already_run = true;
138 TEST_F(CallbackTest, ResetAndReturn) {
139 TestForReentrancy tfr;
140 ASSERT_FALSE(tfr.cb.is_null());
141 ASSERT_FALSE(tfr.cb_already_run);
142 ResetAndReturn(&tfr.cb).Run();
143 ASSERT_TRUE(tfr.cb.is_null());
144 ASSERT_TRUE(tfr.cb_already_run);
147 TEST_F(CallbackTest, NullAfterMoveRun) {
148 RepeatingClosure cb = BindRepeating([] {});
153 const RepeatingClosure cb2 = BindRepeating([] {});
155 std::move(cb2).Run();
158 OnceClosure cb3 = BindOnce([] {});
160 std::move(cb3).Run();
164 TEST_F(CallbackTest, MaybeValidReturnsTrue) {
165 RepeatingCallback<void()> cb = BindRepeating([]() {});
166 // By default, MaybeValid() just returns true all the time.
167 EXPECT_TRUE(cb.MaybeValid());
169 EXPECT_TRUE(cb.MaybeValid());
172 // WeakPtr detection in BindRepeating() requires a method, not just any
174 class ClassWithAMethod {
179 TEST_F(CallbackTest, MaybeValidInvalidateWeakPtrsOnSameSequence) {
180 ClassWithAMethod obj;
181 WeakPtrFactory<ClassWithAMethod> factory(&obj);
182 WeakPtr<ClassWithAMethod> ptr = factory.GetWeakPtr();
184 RepeatingCallback<void()> cb =
185 BindRepeating(&ClassWithAMethod::TheMethod, ptr);
186 EXPECT_TRUE(cb.MaybeValid());
188 factory.InvalidateWeakPtrs();
189 // MaybeValid() should be false because InvalidateWeakPtrs() was called on
191 EXPECT_FALSE(cb.MaybeValid());
194 TEST_F(CallbackTest, MaybeValidInvalidateWeakPtrsOnOtherSequence) {
195 ClassWithAMethod obj;
196 WeakPtrFactory<ClassWithAMethod> factory(&obj);
197 WeakPtr<ClassWithAMethod> ptr = factory.GetWeakPtr();
199 RepeatingCallback<void()> cb =
200 BindRepeating(&ClassWithAMethod::TheMethod, ptr);
201 EXPECT_TRUE(cb.MaybeValid());
203 Thread other_thread("other_thread");
204 other_thread.StartAndWaitForTesting();
205 other_thread.task_runner()->PostTask(
208 [](RepeatingCallback<void()> cb) {
209 // Check that MaybeValid() _eventually_ returns false.
210 const TimeDelta timeout = TestTimeouts::tiny_timeout();
211 const TimeTicks begin = TimeTicks::Now();
212 while (cb.MaybeValid() && (TimeTicks::Now() - begin) < timeout)
213 PlatformThread::YieldCurrentThread();
214 EXPECT_FALSE(cb.MaybeValid());
217 factory.InvalidateWeakPtrs();
218 // |other_thread|'s destructor will join, ensuring we wait for the task to be
222 class CallbackOwner : public base::RefCounted<CallbackOwner> {
224 explicit CallbackOwner(bool* deleted) {
225 // WrapRefCounted() here is needed to avoid the check failure in the
226 // BindRepeating implementation, that refuses to create the first reference
227 // to ref-counted objects.
228 callback_ = BindRepeating(&CallbackOwner::Unused, WrapRefCounted(this));
233 // We are deleted here if no-one else had a ref to us.
237 friend class base::RefCounted<CallbackOwner>;
238 virtual ~CallbackOwner() {
242 FAIL() << "Should never be called";
245 RepeatingClosure callback_;
249 TEST_F(CallbackTest, CallbackHasLastRefOnContainingObject) {
250 bool deleted = false;
251 CallbackOwner* owner = new CallbackOwner(&deleted);
253 ASSERT_TRUE(deleted);