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