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