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 14namespace base { 15 16namespace { 17 18struct 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 28namespace 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. 35template <> 36struct 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 48template <> 49struct 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 62namespace { 63 64using FakeBindState1 = internal::BindState<void(), void(), FakeInvoker>; 65using FakeBindState2 = 66 internal::BindState<void(), void(), FakeInvoker, FakeInvoker>; 67 68class 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. 85TEST_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 103TEST_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 109TEST_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 125TEST_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 136struct 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 149class 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 173TEST_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