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 typedef void(RunType)(internal::BindStateBase*); 19 static void Run(internal::BindStateBase*) { 20 } 21 }; 22 23 } // namespace 24 25 namespace internal { 26 template <typename Runnable, typename RunType, typename BoundArgsType> 27 struct BindState; 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), void(void), void(FakeInvoker)> 36 : public BindStateBase { 37 public: 38 typedef FakeInvoker InvokerType; 39 }; 40 41 template <> 42 struct BindState<void(void), void(void), 43 void(FakeInvoker, FakeInvoker)> 44 : public BindStateBase { 45 public: 46 typedef FakeInvoker InvokerType; 47 }; 48 } // namespace internal 49 50 namespace { 51 52 typedef internal::BindState<void(void), void(void), void(FakeInvoker)> 53 FakeBindState1; 54 typedef internal::BindState<void(void), void(void), 55 void(FakeInvoker, FakeInvoker)> 56 FakeBindState2; 57 58 class CallbackTest : public ::testing::Test { 59 public: 60 CallbackTest() 61 : callback_a_(new FakeBindState1()), 62 callback_b_(new FakeBindState2()) { 63 } 64 65 virtual ~CallbackTest() { 66 } 67 68 protected: 69 Callback<void(void)> callback_a_; 70 const Callback<void(void)> callback_b_; // Ensure APIs work with const. 71 Callback<void(void)> null_callback_; 72 }; 73 74 // Ensure we can create unbound callbacks. We need this to be able to store 75 // them in class members that can be initialized later. 76 TEST_F(CallbackTest, DefaultConstruction) { 77 Callback<void(void)> c0; 78 Callback<void(int)> c1; 79 Callback<void(int,int)> c2; 80 Callback<void(int,int,int)> c3; 81 Callback<void(int,int,int,int)> c4; 82 Callback<void(int,int,int,int,int)> c5; 83 Callback<void(int,int,int,int,int,int)> c6; 84 85 EXPECT_TRUE(c0.is_null()); 86 EXPECT_TRUE(c1.is_null()); 87 EXPECT_TRUE(c2.is_null()); 88 EXPECT_TRUE(c3.is_null()); 89 EXPECT_TRUE(c4.is_null()); 90 EXPECT_TRUE(c5.is_null()); 91 EXPECT_TRUE(c6.is_null()); 92 } 93 94 TEST_F(CallbackTest, IsNull) { 95 EXPECT_TRUE(null_callback_.is_null()); 96 EXPECT_FALSE(callback_a_.is_null()); 97 EXPECT_FALSE(callback_b_.is_null()); 98 } 99 100 TEST_F(CallbackTest, Equals) { 101 EXPECT_TRUE(callback_a_.Equals(callback_a_)); 102 EXPECT_FALSE(callback_a_.Equals(callback_b_)); 103 EXPECT_FALSE(callback_b_.Equals(callback_a_)); 104 105 // We should compare based on instance, not type. 106 Callback<void(void)> callback_c(new FakeBindState1()); 107 Callback<void(void)> callback_a2 = callback_a_; 108 EXPECT_TRUE(callback_a_.Equals(callback_a2)); 109 EXPECT_FALSE(callback_a_.Equals(callback_c)); 110 111 // Empty, however, is always equal to empty. 112 Callback<void(void)> empty2; 113 EXPECT_TRUE(null_callback_.Equals(empty2)); 114 } 115 116 TEST_F(CallbackTest, Reset) { 117 // Resetting should bring us back to empty. 118 ASSERT_FALSE(callback_a_.is_null()); 119 ASSERT_FALSE(callback_a_.Equals(null_callback_)); 120 121 callback_a_.Reset(); 122 123 EXPECT_TRUE(callback_a_.is_null()); 124 EXPECT_TRUE(callback_a_.Equals(null_callback_)); 125 } 126 127 struct TestForReentrancy { 128 TestForReentrancy() 129 : cb_already_run(false), 130 cb(Bind(&TestForReentrancy::AssertCBIsNull, Unretained(this))) { 131 } 132 void AssertCBIsNull() { 133 ASSERT_TRUE(cb.is_null()); 134 cb_already_run = true; 135 } 136 bool cb_already_run; 137 Closure cb; 138 }; 139 140 TEST_F(CallbackTest, ResetAndReturn) { 141 TestForReentrancy tfr; 142 ASSERT_FALSE(tfr.cb.is_null()); 143 ASSERT_FALSE(tfr.cb_already_run); 144 ResetAndReturn(&tfr.cb).Run(); 145 ASSERT_TRUE(tfr.cb.is_null()); 146 ASSERT_TRUE(tfr.cb_already_run); 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