| // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "base/callback.h" | 
 |  | 
 | #include <gtest/gtest.h> | 
 |  | 
 | #include "base/bind.h" | 
 | #include "base/callback_internal.h" | 
 | #include "base/memory/ref_counted.h" | 
 | #include "base/memory/scoped_ptr.h" | 
 |  | 
 | namespace base { | 
 |  | 
 | namespace { | 
 |  | 
 | struct FakeInvoker { | 
 |   // MSVC 2013 doesn't support Type Alias of function types. | 
 |   // Revisit this after we update it to newer version. | 
 |   typedef void RunType(internal::BindStateBase*); | 
 |   static void Run(internal::BindStateBase*) { | 
 |   } | 
 | }; | 
 |  | 
 | }  // namespace | 
 |  | 
 | namespace internal { | 
 |  | 
 | // White-box testpoints to inject into a Callback<> object for checking | 
 | // comparators and emptiness APIs.  Use a BindState that is specialized | 
 | // based on a type we declared in the anonymous namespace above to remove any | 
 | // chance of colliding with another instantiation and breaking the | 
 | // one-definition-rule. | 
 | template <> | 
 | struct BindState<void(), void(), FakeInvoker> | 
 |     : public BindStateBase { | 
 |  public: | 
 |   BindState() : BindStateBase(&Destroy) {} | 
 |   using InvokerType = FakeInvoker; | 
 |  private: | 
 |   ~BindState() {} | 
 |   static void Destroy(BindStateBase* self) { | 
 |     delete static_cast<BindState*>(self); | 
 |   } | 
 | }; | 
 |  | 
 | template <> | 
 | struct BindState<void(), void(), FakeInvoker, FakeInvoker> | 
 |     : public BindStateBase { | 
 |  public: | 
 |   BindState() : BindStateBase(&Destroy) {} | 
 |   using InvokerType = FakeInvoker; | 
 |  private: | 
 |   ~BindState() {} | 
 |   static void Destroy(BindStateBase* self) { | 
 |     delete static_cast<BindState*>(self); | 
 |   } | 
 | }; | 
 | }  // namespace internal | 
 |  | 
 | namespace { | 
 |  | 
 | using FakeBindState1 = internal::BindState<void(), void(), FakeInvoker>; | 
 | using FakeBindState2 = | 
 |     internal::BindState<void(), void(), FakeInvoker, FakeInvoker>; | 
 |  | 
 | class CallbackTest : public ::testing::Test { | 
 |  public: | 
 |   CallbackTest() | 
 |       : callback_a_(new FakeBindState1()), | 
 |         callback_b_(new FakeBindState2()) { | 
 |   } | 
 |  | 
 |   ~CallbackTest() override {} | 
 |  | 
 |  protected: | 
 |   Callback<void()> callback_a_; | 
 |   const Callback<void()> callback_b_;  // Ensure APIs work with const. | 
 |   Callback<void()> null_callback_; | 
 | }; | 
 |  | 
 | // Ensure we can create unbound callbacks. We need this to be able to store | 
 | // them in class members that can be initialized later. | 
 | TEST_F(CallbackTest, DefaultConstruction) { | 
 |   Callback<void()> c0; | 
 |   Callback<void(int)> c1; | 
 |   Callback<void(int,int)> c2; | 
 |   Callback<void(int,int,int)> c3; | 
 |   Callback<void(int,int,int,int)> c4; | 
 |   Callback<void(int,int,int,int,int)> c5; | 
 |   Callback<void(int,int,int,int,int,int)> c6; | 
 |  | 
 |   EXPECT_TRUE(c0.is_null()); | 
 |   EXPECT_TRUE(c1.is_null()); | 
 |   EXPECT_TRUE(c2.is_null()); | 
 |   EXPECT_TRUE(c3.is_null()); | 
 |   EXPECT_TRUE(c4.is_null()); | 
 |   EXPECT_TRUE(c5.is_null()); | 
 |   EXPECT_TRUE(c6.is_null()); | 
 | } | 
 |  | 
 | TEST_F(CallbackTest, IsNull) { | 
 |   EXPECT_TRUE(null_callback_.is_null()); | 
 |   EXPECT_FALSE(callback_a_.is_null()); | 
 |   EXPECT_FALSE(callback_b_.is_null()); | 
 | } | 
 |  | 
 | TEST_F(CallbackTest, Equals) { | 
 |   EXPECT_TRUE(callback_a_.Equals(callback_a_)); | 
 |   EXPECT_FALSE(callback_a_.Equals(callback_b_)); | 
 |   EXPECT_FALSE(callback_b_.Equals(callback_a_)); | 
 |  | 
 |   // We should compare based on instance, not type. | 
 |   Callback<void()> callback_c(new FakeBindState1()); | 
 |   Callback<void()> callback_a2 = callback_a_; | 
 |   EXPECT_TRUE(callback_a_.Equals(callback_a2)); | 
 |   EXPECT_FALSE(callback_a_.Equals(callback_c)); | 
 |  | 
 |   // Empty, however, is always equal to empty. | 
 |   Callback<void()> empty2; | 
 |   EXPECT_TRUE(null_callback_.Equals(empty2)); | 
 | } | 
 |  | 
 | TEST_F(CallbackTest, Reset) { | 
 |   // Resetting should bring us back to empty. | 
 |   ASSERT_FALSE(callback_a_.is_null()); | 
 |   ASSERT_FALSE(callback_a_.Equals(null_callback_)); | 
 |  | 
 |   callback_a_.Reset(); | 
 |  | 
 |   EXPECT_TRUE(callback_a_.is_null()); | 
 |   EXPECT_TRUE(callback_a_.Equals(null_callback_)); | 
 | } | 
 |  | 
 | struct TestForReentrancy { | 
 |   TestForReentrancy() | 
 |       : cb_already_run(false), | 
 |         cb(Bind(&TestForReentrancy::AssertCBIsNull, Unretained(this))) { | 
 |   } | 
 |   void AssertCBIsNull() { | 
 |     ASSERT_TRUE(cb.is_null()); | 
 |     cb_already_run = true; | 
 |   } | 
 |   bool cb_already_run; | 
 |   Closure cb; | 
 | }; | 
 |  | 
 | class CallbackOwner : public base::RefCounted<CallbackOwner> { | 
 |  public: | 
 |   explicit CallbackOwner(bool* deleted) { | 
 |     callback_ = Bind(&CallbackOwner::Unused, this); | 
 |     deleted_ = deleted; | 
 |   } | 
 |   void Reset() { | 
 |     callback_.Reset(); | 
 |     // We are deleted here if no-one else had a ref to us. | 
 |   } | 
 |  | 
 |  private: | 
 |   friend class base::RefCounted<CallbackOwner>; | 
 |   virtual ~CallbackOwner() { | 
 |     *deleted_ = true; | 
 |   } | 
 |   void Unused() { | 
 |     FAIL() << "Should never be called"; | 
 |   } | 
 |  | 
 |   Closure callback_; | 
 |   bool* deleted_; | 
 | }; | 
 |  | 
 | TEST_F(CallbackTest, CallbackHasLastRefOnContainingObject) { | 
 |   bool deleted = false; | 
 |   CallbackOwner* owner = new CallbackOwner(&deleted); | 
 |   owner->Reset(); | 
 |   ASSERT_TRUE(deleted); | 
 | } | 
 |  | 
 | }  // namespace | 
 | }  // namespace base |