1b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Use of this source code is governed by a BSD-style license that can be
3b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// found in the LICENSE file.
4b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
5b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/callback.h"
694ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez
794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include <memory>
894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez
994ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include "base/bind.h"
10b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/callback_helpers.h"
11b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/callback_internal.h"
12b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/memory/ref_counted.h"
13b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "testing/gtest/include/gtest/gtest.h"
14b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
15b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace base {
16b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
170c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavezvoid NopInvokeFunc(internal::BindStateBase*) {}
18b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
19b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// White-box testpoints to inject into a Callback<> object for checking
20b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// comparators and emptiness APIs.  Use a BindState that is specialized
21b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// based on a type we declared in the anonymous namespace above to remove any
22b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// chance of colliding with another instantiation and breaking the
23b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// one-definition-rule.
240c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavezstruct FakeBindState1 : internal::BindStateBase {
250c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez  FakeBindState1() : BindStateBase(&Destroy) {}
26b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat private:
270c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez  ~FakeBindState1() {}
280c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez  static void Destroy(internal::BindStateBase* self) {
290c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez    delete static_cast<FakeBindState1*>(self);
30b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
31b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat};
32b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
330c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavezstruct FakeBindState2 : internal::BindStateBase {
340c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez  FakeBindState2() : BindStateBase(&Destroy) {}
35b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat private:
360c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez  ~FakeBindState2() {}
370c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez  static void Destroy(internal::BindStateBase* self) {
380c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez    delete static_cast<FakeBindState2*>(self);
39b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
40b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat};
41b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
42b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace {
43b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
44b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass CallbackTest : public ::testing::Test {
45b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public:
46b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  CallbackTest()
470c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez      : callback_a_(new FakeBindState1(), &NopInvokeFunc),
480c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez        callback_b_(new FakeBindState2(), &NopInvokeFunc) {
49b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
50b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
51b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ~CallbackTest() override {}
52b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
53b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat protected:
540d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  Callback<void()> callback_a_;
550d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  const Callback<void()> callback_b_;  // Ensure APIs work with const.
560d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  Callback<void()> null_callback_;
57b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat};
58b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
59b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Ensure we can create unbound callbacks. We need this to be able to store
60b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// them in class members that can be initialized later.
61b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST_F(CallbackTest, DefaultConstruction) {
620d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  Callback<void()> c0;
63b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Callback<void(int)> c1;
64b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Callback<void(int,int)> c2;
65b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Callback<void(int,int,int)> c3;
66b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Callback<void(int,int,int,int)> c4;
67b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Callback<void(int,int,int,int,int)> c5;
68b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Callback<void(int,int,int,int,int,int)> c6;
69b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
70b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_TRUE(c0.is_null());
71b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_TRUE(c1.is_null());
72b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_TRUE(c2.is_null());
73b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_TRUE(c3.is_null());
74b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_TRUE(c4.is_null());
75b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_TRUE(c5.is_null());
76b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_TRUE(c6.is_null());
77b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
78b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
79b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST_F(CallbackTest, IsNull) {
80b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_TRUE(null_callback_.is_null());
81b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_FALSE(callback_a_.is_null());
82b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_FALSE(callback_b_.is_null());
83b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
84b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
85b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST_F(CallbackTest, Equals) {
86b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_TRUE(callback_a_.Equals(callback_a_));
87b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_FALSE(callback_a_.Equals(callback_b_));
88b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_FALSE(callback_b_.Equals(callback_a_));
89b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
90b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // We should compare based on instance, not type.
910c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez  Callback<void()> callback_c(new FakeBindState1(), &NopInvokeFunc);
920d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  Callback<void()> callback_a2 = callback_a_;
93b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_TRUE(callback_a_.Equals(callback_a2));
94b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_FALSE(callback_a_.Equals(callback_c));
95b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
96b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Empty, however, is always equal to empty.
970d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  Callback<void()> empty2;
98b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_TRUE(null_callback_.Equals(empty2));
99b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
100b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
101b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST_F(CallbackTest, Reset) {
102b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Resetting should bring us back to empty.
103b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ASSERT_FALSE(callback_a_.is_null());
104b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ASSERT_FALSE(callback_a_.Equals(null_callback_));
105b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
106b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  callback_a_.Reset();
107b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
108b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_TRUE(callback_a_.is_null());
109b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_TRUE(callback_a_.Equals(null_callback_));
110b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
111b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
112b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstruct TestForReentrancy {
113b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  TestForReentrancy()
114b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      : cb_already_run(false),
115b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        cb(Bind(&TestForReentrancy::AssertCBIsNull, Unretained(this))) {
116b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
117b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  void AssertCBIsNull() {
118b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    ASSERT_TRUE(cb.is_null());
119b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    cb_already_run = true;
120b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
121b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  bool cb_already_run;
122b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Closure cb;
123b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat};
124b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
125b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST_F(CallbackTest, ResetAndReturn) {
126b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  TestForReentrancy tfr;
127b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ASSERT_FALSE(tfr.cb.is_null());
128b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ASSERT_FALSE(tfr.cb_already_run);
129b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ResetAndReturn(&tfr.cb).Run();
130b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ASSERT_TRUE(tfr.cb.is_null());
131b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ASSERT_TRUE(tfr.cb_already_run);
132b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
133b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
134b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass CallbackOwner : public base::RefCounted<CallbackOwner> {
135b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public:
136b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  explicit CallbackOwner(bool* deleted) {
137b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    callback_ = Bind(&CallbackOwner::Unused, this);
138b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    deleted_ = deleted;
139b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
140b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  void Reset() {
141b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    callback_.Reset();
142b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // We are deleted here if no-one else had a ref to us.
143b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
144b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
145b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat private:
146b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  friend class base::RefCounted<CallbackOwner>;
147b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  virtual ~CallbackOwner() {
148b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    *deleted_ = true;
149b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
150b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  void Unused() {
151b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    FAIL() << "Should never be called";
152b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
153b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
154b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  Closure callback_;
155b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  bool* deleted_;
156b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat};
157b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
158b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST_F(CallbackTest, CallbackHasLastRefOnContainingObject) {
159b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  bool deleted = false;
160b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  CallbackOwner* owner = new CallbackOwner(&deleted);
161b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  owner->Reset();
162b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ASSERT_TRUE(deleted);
163b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
164b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
165b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}  // namespace
166b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}  // namespace base
167