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