1b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Use of this source code is governed by a BSD-style license that can be 3b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// found in the LICENSE file. 4b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 5b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/callback.h" 694ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez 794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include <memory> 894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez 994ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include "base/bind.h" 10b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/callback_helpers.h" 11b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/callback_internal.h" 12b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/memory/ref_counted.h" 13b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "testing/gtest/include/gtest/gtest.h" 14b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 15b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace base { 16b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 170c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavezvoid NopInvokeFunc(internal::BindStateBase*) {} 18b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 19b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// White-box testpoints to inject into a Callback<> object for checking 20b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// comparators and emptiness APIs. Use a BindState that is specialized 21b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// based on a type we declared in the anonymous namespace above to remove any 22b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// chance of colliding with another instantiation and breaking the 23b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// one-definition-rule. 240c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavezstruct FakeBindState1 : internal::BindStateBase { 250c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez FakeBindState1() : BindStateBase(&Destroy) {} 26b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat private: 270c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez ~FakeBindState1() {} 280c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez static void Destroy(internal::BindStateBase* self) { 290c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez delete static_cast<FakeBindState1*>(self); 30b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 31b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}; 32b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 330c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavezstruct FakeBindState2 : internal::BindStateBase { 340c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez FakeBindState2() : BindStateBase(&Destroy) {} 35b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat private: 360c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez ~FakeBindState2() {} 370c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez static void Destroy(internal::BindStateBase* self) { 380c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez delete static_cast<FakeBindState2*>(self); 39b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 40b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}; 41b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 42b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace { 43b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 44b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass CallbackTest : public ::testing::Test { 45b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public: 46b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat CallbackTest() 470c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez : callback_a_(new FakeBindState1(), &NopInvokeFunc), 480c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez callback_b_(new FakeBindState2(), &NopInvokeFunc) { 49b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 50b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 51b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ~CallbackTest() override {} 52b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 53b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat protected: 540d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko Callback<void()> callback_a_; 550d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko const Callback<void()> callback_b_; // Ensure APIs work with const. 560d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko Callback<void()> null_callback_; 57b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}; 58b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 59b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Ensure we can create unbound callbacks. We need this to be able to store 60b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// them in class members that can be initialized later. 61b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST_F(CallbackTest, DefaultConstruction) { 620d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko Callback<void()> c0; 63b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Callback<void(int)> c1; 64b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Callback<void(int,int)> c2; 65b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Callback<void(int,int,int)> c3; 66b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Callback<void(int,int,int,int)> c4; 67b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Callback<void(int,int,int,int,int)> c5; 68b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Callback<void(int,int,int,int,int,int)> c6; 69b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 70b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_TRUE(c0.is_null()); 71b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_TRUE(c1.is_null()); 72b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_TRUE(c2.is_null()); 73b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_TRUE(c3.is_null()); 74b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_TRUE(c4.is_null()); 75b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_TRUE(c5.is_null()); 76b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_TRUE(c6.is_null()); 77b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 78b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 79b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST_F(CallbackTest, IsNull) { 80b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_TRUE(null_callback_.is_null()); 81b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_FALSE(callback_a_.is_null()); 82b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_FALSE(callback_b_.is_null()); 83b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 84b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 85b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST_F(CallbackTest, Equals) { 86b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_TRUE(callback_a_.Equals(callback_a_)); 87b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_FALSE(callback_a_.Equals(callback_b_)); 88b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_FALSE(callback_b_.Equals(callback_a_)); 89b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 90b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // We should compare based on instance, not type. 910c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez Callback<void()> callback_c(new FakeBindState1(), &NopInvokeFunc); 920d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko Callback<void()> callback_a2 = callback_a_; 93b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_TRUE(callback_a_.Equals(callback_a2)); 94b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_FALSE(callback_a_.Equals(callback_c)); 95b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 96b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Empty, however, is always equal to empty. 970d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko Callback<void()> empty2; 98b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_TRUE(null_callback_.Equals(empty2)); 99b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 100b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 101b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST_F(CallbackTest, Reset) { 102b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Resetting should bring us back to empty. 103b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ASSERT_FALSE(callback_a_.is_null()); 104b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ASSERT_FALSE(callback_a_.Equals(null_callback_)); 105b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 106b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat callback_a_.Reset(); 107b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 108b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_TRUE(callback_a_.is_null()); 109b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_TRUE(callback_a_.Equals(null_callback_)); 110b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 111b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 112b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstruct TestForReentrancy { 113b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat TestForReentrancy() 114b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat : cb_already_run(false), 115b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat cb(Bind(&TestForReentrancy::AssertCBIsNull, Unretained(this))) { 116b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 117b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat void AssertCBIsNull() { 118b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ASSERT_TRUE(cb.is_null()); 119b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat cb_already_run = true; 120b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 121b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat bool cb_already_run; 122b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Closure cb; 123b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}; 124b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 125b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST_F(CallbackTest, ResetAndReturn) { 126b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat TestForReentrancy tfr; 127b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ASSERT_FALSE(tfr.cb.is_null()); 128b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ASSERT_FALSE(tfr.cb_already_run); 129b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ResetAndReturn(&tfr.cb).Run(); 130b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ASSERT_TRUE(tfr.cb.is_null()); 131b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ASSERT_TRUE(tfr.cb_already_run); 132b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 133b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 134b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass CallbackOwner : public base::RefCounted<CallbackOwner> { 135b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public: 136b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat explicit CallbackOwner(bool* deleted) { 137b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat callback_ = Bind(&CallbackOwner::Unused, this); 138b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat deleted_ = deleted; 139b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 140b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat void Reset() { 141b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat callback_.Reset(); 142b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // We are deleted here if no-one else had a ref to us. 143b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 144b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 145b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat private: 146b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat friend class base::RefCounted<CallbackOwner>; 147b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat virtual ~CallbackOwner() { 148b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat *deleted_ = true; 149b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 150b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat void Unused() { 151b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat FAIL() << "Should never be called"; 152b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 153b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 154b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Closure callback_; 155b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat bool* deleted_; 156b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}; 157b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 158b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST_F(CallbackTest, CallbackHasLastRefOnContainingObject) { 159b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat bool deleted = false; 160b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat CallbackOwner* owner = new CallbackOwner(&deleted); 161b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat owner->Reset(); 162b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ASSERT_TRUE(deleted); 163b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 164b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 165b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace 166b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace base 167