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