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