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 <memory>
      8 
      9 #include "base/bind.h"
     10 #include "base/callback_helpers.h"
     11 #include "base/callback_internal.h"
     12 #include "base/memory/ref_counted.h"
     13 #include "testing/gtest/include/gtest/gtest.h"
     14 
     15 namespace base {
     16 
     17 void NopInvokeFunc() {}
     18 
     19 // White-box testpoints to inject into a Callback<> object for checking
     20 // comparators and emptiness APIs.  Use a BindState that is specialized
     21 // based on a type we declared in the anonymous namespace above to remove any
     22 // chance of colliding with another instantiation and breaking the
     23 // one-definition-rule.
     24 struct FakeBindState : internal::BindStateBase {
     25   FakeBindState() : BindStateBase(&NopInvokeFunc, &Destroy, &IsCancelled) {}
     26 
     27  private:
     28   ~FakeBindState() {}
     29   static void Destroy(const internal::BindStateBase* self) {
     30     delete static_cast<const FakeBindState*>(self);
     31   }
     32   static bool IsCancelled(const internal::BindStateBase*) {
     33     return false;
     34   }
     35 };
     36 
     37 namespace {
     38 
     39 class CallbackTest : public ::testing::Test {
     40  public:
     41   CallbackTest()
     42       : callback_a_(new FakeBindState()), callback_b_(new FakeBindState()) {}
     43 
     44   ~CallbackTest() override {}
     45 
     46  protected:
     47   Callback<void()> callback_a_;
     48   const Callback<void()> callback_b_;  // Ensure APIs work with const.
     49   Callback<void()> null_callback_;
     50 };
     51 
     52 // Ensure we can create unbound callbacks. We need this to be able to store
     53 // them in class members that can be initialized later.
     54 TEST_F(CallbackTest, DefaultConstruction) {
     55   Callback<void()> c0;
     56   Callback<void(int)> c1;
     57   Callback<void(int,int)> c2;
     58   Callback<void(int,int,int)> c3;
     59   Callback<void(int,int,int,int)> c4;
     60   Callback<void(int,int,int,int,int)> c5;
     61   Callback<void(int,int,int,int,int,int)> c6;
     62 
     63   EXPECT_TRUE(c0.is_null());
     64   EXPECT_TRUE(c1.is_null());
     65   EXPECT_TRUE(c2.is_null());
     66   EXPECT_TRUE(c3.is_null());
     67   EXPECT_TRUE(c4.is_null());
     68   EXPECT_TRUE(c5.is_null());
     69   EXPECT_TRUE(c6.is_null());
     70 }
     71 
     72 TEST_F(CallbackTest, IsNull) {
     73   EXPECT_TRUE(null_callback_.is_null());
     74   EXPECT_FALSE(callback_a_.is_null());
     75   EXPECT_FALSE(callback_b_.is_null());
     76 }
     77 
     78 TEST_F(CallbackTest, Equals) {
     79   EXPECT_TRUE(callback_a_.Equals(callback_a_));
     80   EXPECT_FALSE(callback_a_.Equals(callback_b_));
     81   EXPECT_FALSE(callback_b_.Equals(callback_a_));
     82 
     83   // We should compare based on instance, not type.
     84   Callback<void()> callback_c(new FakeBindState());
     85   Callback<void()> callback_a2 = callback_a_;
     86   EXPECT_TRUE(callback_a_.Equals(callback_a2));
     87   EXPECT_FALSE(callback_a_.Equals(callback_c));
     88 
     89   // Empty, however, is always equal to empty.
     90   Callback<void()> empty2;
     91   EXPECT_TRUE(null_callback_.Equals(empty2));
     92 }
     93 
     94 TEST_F(CallbackTest, Reset) {
     95   // Resetting should bring us back to empty.
     96   ASSERT_FALSE(callback_a_.is_null());
     97   ASSERT_FALSE(callback_a_.Equals(null_callback_));
     98 
     99   callback_a_.Reset();
    100 
    101   EXPECT_TRUE(callback_a_.is_null());
    102   EXPECT_TRUE(callback_a_.Equals(null_callback_));
    103 }
    104 
    105 TEST_F(CallbackTest, Move) {
    106   // Moving should reset the callback.
    107   ASSERT_FALSE(callback_a_.is_null());
    108   ASSERT_FALSE(callback_a_.Equals(null_callback_));
    109 
    110   auto tmp = std::move(callback_a_);
    111 
    112   EXPECT_TRUE(callback_a_.is_null());
    113   EXPECT_TRUE(callback_a_.Equals(null_callback_));
    114 }
    115 
    116 struct TestForReentrancy {
    117   TestForReentrancy()
    118       : cb_already_run(false),
    119         cb(Bind(&TestForReentrancy::AssertCBIsNull, Unretained(this))) {
    120   }
    121   void AssertCBIsNull() {
    122     ASSERT_TRUE(cb.is_null());
    123     cb_already_run = true;
    124   }
    125   bool cb_already_run;
    126   Closure cb;
    127 };
    128 
    129 TEST_F(CallbackTest, ResetAndReturn) {
    130   TestForReentrancy tfr;
    131   ASSERT_FALSE(tfr.cb.is_null());
    132   ASSERT_FALSE(tfr.cb_already_run);
    133   ResetAndReturn(&tfr.cb).Run();
    134   ASSERT_TRUE(tfr.cb.is_null());
    135   ASSERT_TRUE(tfr.cb_already_run);
    136 }
    137 
    138 TEST_F(CallbackTest, NullAfterMoveRun) {
    139   Closure cb = Bind([] {});
    140   ASSERT_TRUE(cb);
    141   std::move(cb).Run();
    142   ASSERT_FALSE(cb);
    143 
    144   const Closure cb2 = Bind([] {});
    145   ASSERT_TRUE(cb2);
    146   std::move(cb2).Run();
    147   ASSERT_TRUE(cb2);
    148 
    149   OnceClosure cb3 = BindOnce([] {});
    150   ASSERT_TRUE(cb3);
    151   std::move(cb3).Run();
    152   ASSERT_FALSE(cb3);
    153 }
    154 
    155 class CallbackOwner : public base::RefCounted<CallbackOwner> {
    156  public:
    157   explicit CallbackOwner(bool* deleted) {
    158     callback_ = Bind(&CallbackOwner::Unused, this);
    159     deleted_ = deleted;
    160   }
    161   void Reset() {
    162     callback_.Reset();
    163     // We are deleted here if no-one else had a ref to us.
    164   }
    165 
    166  private:
    167   friend class base::RefCounted<CallbackOwner>;
    168   virtual ~CallbackOwner() {
    169     *deleted_ = true;
    170   }
    171   void Unused() {
    172     FAIL() << "Should never be called";
    173   }
    174 
    175   Closure callback_;
    176   bool* deleted_;
    177 };
    178 
    179 TEST_F(CallbackTest, CallbackHasLastRefOnContainingObject) {
    180   bool deleted = false;
    181   CallbackOwner* owner = new CallbackOwner(&deleted);
    182   owner->Reset();
    183   ASSERT_TRUE(deleted);
    184 }
    185 
    186 }  // namespace
    187 }  // namespace base
    188