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_internal.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/notreached.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_EQ(callback_a_, callback_a_);
89 EXPECT_NE(callback_a_, callback_b_);
90 EXPECT_NE(callback_b_, 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_EQ(callback_a_, callback_a2);
96 EXPECT_NE(callback_a_, callback_c);
98 // Empty, however, is always equal to empty.
99 RepeatingCallback<void()> empty2;
100 EXPECT_EQ(null_callback_, empty2);
103 TEST_F(CallbackTest, Reset) {
104 // Resetting should bring us back to empty.
105 ASSERT_FALSE(callback_a_.is_null());
106 EXPECT_NE(callback_a_, null_callback_);
110 EXPECT_TRUE(callback_a_.is_null());
111 EXPECT_EQ(callback_a_, null_callback_);
114 TEST_F(CallbackTest, Move) {
115 // Moving should reset the callback.
116 ASSERT_FALSE(callback_a_.is_null());
117 EXPECT_NE(callback_a_, null_callback_);
119 auto tmp = std::move(callback_a_);
121 EXPECT_TRUE(callback_a_.is_null());
122 EXPECT_EQ(callback_a_, null_callback_);
125 TEST_F(CallbackTest, NullAfterMoveRun) {
126 RepeatingCallback<void(void*)> cb = BindRepeating([](void* param) {
127 EXPECT_TRUE(static_cast<RepeatingCallback<void(void*)>*>(param)->is_null());
130 std::move(cb).Run(&cb);
133 const RepeatingClosure cb2 = BindRepeating([] {});
135 std::move(cb2).Run();
138 OnceCallback<void(void*)> cb3 = BindOnce([](void* param) {
139 EXPECT_TRUE(static_cast<OnceCallback<void(void*)>*>(param)->is_null());
142 std::move(cb3).Run(&cb3);
146 TEST_F(CallbackTest, MaybeValidReturnsTrue) {
147 RepeatingCallback<void()> cb = BindRepeating([]() {});
148 // By default, MaybeValid() just returns true all the time.
149 EXPECT_TRUE(cb.MaybeValid());
151 EXPECT_TRUE(cb.MaybeValid());
154 // WeakPtr detection in BindRepeating() requires a method, not just any
156 class ClassWithAMethod {
161 TEST_F(CallbackTest, MaybeValidInvalidateWeakPtrsOnSameSequence) {
162 ClassWithAMethod obj;
163 WeakPtrFactory<ClassWithAMethod> factory(&obj);
164 WeakPtr<ClassWithAMethod> ptr = factory.GetWeakPtr();
166 RepeatingCallback<void()> cb =
167 BindRepeating(&ClassWithAMethod::TheMethod, ptr);
168 EXPECT_TRUE(cb.MaybeValid());
169 EXPECT_FALSE(cb.IsCancelled());
171 factory.InvalidateWeakPtrs();
172 // MaybeValid() should be false and IsCancelled() should become true because
173 // InvalidateWeakPtrs() was called on the same thread.
174 EXPECT_FALSE(cb.MaybeValid());
175 EXPECT_TRUE(cb.IsCancelled());
176 // is_null() is not affected by the invalidated WeakPtr.
177 EXPECT_FALSE(cb.is_null());
180 TEST_F(CallbackTest, MaybeValidInvalidateWeakPtrsOnOtherSequence) {
181 ClassWithAMethod obj;
182 WeakPtrFactory<ClassWithAMethod> factory(&obj);
183 WeakPtr<ClassWithAMethod> ptr = factory.GetWeakPtr();
185 RepeatingCallback<void()> cb =
186 BindRepeating(&ClassWithAMethod::TheMethod, ptr);
187 EXPECT_TRUE(cb.MaybeValid());
189 Thread other_thread("other_thread");
190 other_thread.StartAndWaitForTesting();
191 other_thread.task_runner()->PostTask(
194 [](RepeatingCallback<void()> cb) {
195 // Check that MaybeValid() _eventually_ returns false.
196 const TimeDelta timeout = TestTimeouts::tiny_timeout();
197 const TimeTicks begin = TimeTicks::Now();
198 while (cb.MaybeValid() && (TimeTicks::Now() - begin) < timeout)
199 PlatformThread::YieldCurrentThread();
200 EXPECT_FALSE(cb.MaybeValid());
203 factory.InvalidateWeakPtrs();
204 // |other_thread|'s destructor will join, ensuring we wait for the task to be
208 class CallbackOwner : public base::RefCounted<CallbackOwner> {
210 explicit CallbackOwner(bool* deleted) {
211 // WrapRefCounted() here is needed to avoid the check failure in the
212 // BindRepeating implementation, that refuses to create the first reference
213 // to ref-counted objects.
214 callback_ = BindRepeating(&CallbackOwner::Unused, WrapRefCounted(this));
219 // We are deleted here if no-one else had a ref to us.
223 friend class base::RefCounted<CallbackOwner>;
224 virtual ~CallbackOwner() {
228 FAIL() << "Should never be called";
231 RepeatingClosure callback_;
235 TEST_F(CallbackTest, CallbackHasLastRefOnContainingObject) {
236 bool deleted = false;
237 CallbackOwner* owner = new CallbackOwner(&deleted);
239 ASSERT_TRUE(deleted);