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. 4 5 #include "base/callback.h" 6 7 #include <gtest/gtest.h> 8 9 #include "base/bind.h" 10 #include "base/callback_internal.h" 11 #include "base/memory/ref_counted.h" 12 #include "base/memory/scoped_ptr.h" 13 14 namespace base { 15 16 namespace { 17 18 struct FakeInvoker { 19 // MSVC 2013 doesn't support Type Alias of function types. 20 // Revisit this after we update it to newer version. 21 typedef void RunType(internal::BindStateBase*); 22 static void Run(internal::BindStateBase*) { 23 } 24 }; 25 26 } // namespace 27 28 namespace internal { 29 30 // White-box testpoints to inject into a Callback<> object for checking 31 // comparators and emptiness APIs. Use a BindState that is specialized 32 // based on a type we declared in the anonymous namespace above to remove any 33 // chance of colliding with another instantiation and breaking the 34 // one-definition-rule. 35 template <> 36 struct BindState<void(), void(), FakeInvoker> 37 : public BindStateBase { 38 public: 39 BindState() : BindStateBase(&Destroy) {} 40 using InvokerType = FakeInvoker; 41 private: 42 ~BindState() {} 43 static void Destroy(BindStateBase* self) { 44 delete static_cast<BindState*>(self); 45 } 46 }; 47 48 template <> 49 struct BindState<void(), void(), FakeInvoker, FakeInvoker> 50 : public BindStateBase { 51 public: 52 BindState() : BindStateBase(&Destroy) {} 53 using InvokerType = FakeInvoker; 54 private: 55 ~BindState() {} 56 static void Destroy(BindStateBase* self) { 57 delete static_cast<BindState*>(self); 58 } 59 }; 60 } // namespace internal 61 62 namespace { 63 64 using FakeBindState1 = internal::BindState<void(), void(), FakeInvoker>; 65 using FakeBindState2 = 66 internal::BindState<void(), void(), FakeInvoker, FakeInvoker>; 67 68 class CallbackTest : public ::testing::Test { 69 public: 70 CallbackTest() 71 : callback_a_(new FakeBindState1()), 72 callback_b_(new FakeBindState2()) { 73 } 74 75 ~CallbackTest() override {} 76 77 protected: 78 Callback<void()> callback_a_; 79 const Callback<void()> callback_b_; // Ensure APIs work with const. 80 Callback<void()> null_callback_; 81 }; 82 83 // Ensure we can create unbound callbacks. We need this to be able to store 84 // them in class members that can be initialized later. 85 TEST_F(CallbackTest, DefaultConstruction) { 86 Callback<void()> c0; 87 Callback<void(int)> c1; 88 Callback<void(int,int)> c2; 89 Callback<void(int,int,int)> c3; 90 Callback<void(int,int,int,int)> c4; 91 Callback<void(int,int,int,int,int)> c5; 92 Callback<void(int,int,int,int,int,int)> c6; 93 94 EXPECT_TRUE(c0.is_null()); 95 EXPECT_TRUE(c1.is_null()); 96 EXPECT_TRUE(c2.is_null()); 97 EXPECT_TRUE(c3.is_null()); 98 EXPECT_TRUE(c4.is_null()); 99 EXPECT_TRUE(c5.is_null()); 100 EXPECT_TRUE(c6.is_null()); 101 } 102 103 TEST_F(CallbackTest, IsNull) { 104 EXPECT_TRUE(null_callback_.is_null()); 105 EXPECT_FALSE(callback_a_.is_null()); 106 EXPECT_FALSE(callback_b_.is_null()); 107 } 108 109 TEST_F(CallbackTest, Equals) { 110 EXPECT_TRUE(callback_a_.Equals(callback_a_)); 111 EXPECT_FALSE(callback_a_.Equals(callback_b_)); 112 EXPECT_FALSE(callback_b_.Equals(callback_a_)); 113 114 // We should compare based on instance, not type. 115 Callback<void()> callback_c(new FakeBindState1()); 116 Callback<void()> callback_a2 = callback_a_; 117 EXPECT_TRUE(callback_a_.Equals(callback_a2)); 118 EXPECT_FALSE(callback_a_.Equals(callback_c)); 119 120 // Empty, however, is always equal to empty. 121 Callback<void()> empty2; 122 EXPECT_TRUE(null_callback_.Equals(empty2)); 123 } 124 125 TEST_F(CallbackTest, Reset) { 126 // Resetting should bring us back to empty. 127 ASSERT_FALSE(callback_a_.is_null()); 128 ASSERT_FALSE(callback_a_.Equals(null_callback_)); 129 130 callback_a_.Reset(); 131 132 EXPECT_TRUE(callback_a_.is_null()); 133 EXPECT_TRUE(callback_a_.Equals(null_callback_)); 134 } 135 136 struct TestForReentrancy { 137 TestForReentrancy() 138 : cb_already_run(false), 139 cb(Bind(&TestForReentrancy::AssertCBIsNull, Unretained(this))) { 140 } 141 void AssertCBIsNull() { 142 ASSERT_TRUE(cb.is_null()); 143 cb_already_run = true; 144 } 145 bool cb_already_run; 146 Closure cb; 147 }; 148 149 class CallbackOwner : public base::RefCounted<CallbackOwner> { 150 public: 151 explicit CallbackOwner(bool* deleted) { 152 callback_ = Bind(&CallbackOwner::Unused, this); 153 deleted_ = deleted; 154 } 155 void Reset() { 156 callback_.Reset(); 157 // We are deleted here if no-one else had a ref to us. 158 } 159 160 private: 161 friend class base::RefCounted<CallbackOwner>; 162 virtual ~CallbackOwner() { 163 *deleted_ = true; 164 } 165 void Unused() { 166 FAIL() << "Should never be called"; 167 } 168 169 Closure callback_; 170 bool* deleted_; 171 }; 172 173 TEST_F(CallbackTest, CallbackHasLastRefOnContainingObject) { 174 bool deleted = false; 175 CallbackOwner* owner = new CallbackOwner(&deleted); 176 owner->Reset(); 177 ASSERT_TRUE(deleted); 178 } 179 180 } // namespace 181 } // namespace base 182