blob: 6e01f7f3fdb0241dbed1286d8780dc335541d37b [file] [log] [blame]
rsleevi@chromium.orgde3a6cf2012-04-06 12:53:02 +09001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
ajwong@chromium.orge2cca632011-02-15 10:27:38 +09002// 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
dcheng3d580cf2015-12-15 05:31:52 +09007#include <memory>
8#include <utility>
dchengb61e1f92016-02-02 13:09:33 +09009#include <vector>
dcheng3d580cf2015-12-15 05:31:52 +090010
ajwong@chromium.orge2cca632011-02-15 10:27:38 +090011#include "base/callback.h"
avia6a6a682015-12-27 07:15:14 +090012#include "base/macros.h"
dchengcc8e4d82016-04-05 06:25:51 +090013#include "base/memory/ptr_util.h"
ajwong@chromium.orgf66a7db2011-12-23 06:12:58 +090014#include "base/memory/ref_counted.h"
ajwong@chromium.orgf66a7db2011-12-23 06:12:58 +090015#include "base/memory/weak_ptr.h"
gabbcf9c762016-08-02 01:39:56 +090016#include "base/test/gtest_util.h"
avia6a6a682015-12-27 07:15:14 +090017#include "build/build_config.h"
ajwong@chromium.orge2cca632011-02-15 10:27:38 +090018#include "testing/gmock/include/gmock/gmock.h"
19#include "testing/gtest/include/gtest/gtest.h"
20
dchengb78a84f2016-09-24 14:05:57 +090021using ::testing::_;
ajwong@chromium.orge2cca632011-02-15 10:27:38 +090022using ::testing::Mock;
tzikd14dea22016-10-12 13:55:02 +090023using ::testing::ByMove;
ajwong@chromium.orge2cca632011-02-15 10:27:38 +090024using ::testing::Return;
25using ::testing::StrictMock;
26
27namespace base {
28namespace {
29
ajwong@chromium.org27e56852011-10-01 15:31:41 +090030class IncompleteType;
31
ajwong@chromium.orge2cca632011-02-15 10:27:38 +090032class NoRef {
33 public:
34 NoRef() {}
35
tzik260fab52015-12-19 18:18:46 +090036 MOCK_METHOD0(VoidMethod0, void());
37 MOCK_CONST_METHOD0(VoidConstMethod0, void());
ajwong@chromium.orge2cca632011-02-15 10:27:38 +090038
tzik260fab52015-12-19 18:18:46 +090039 MOCK_METHOD0(IntMethod0, int());
40 MOCK_CONST_METHOD0(IntConstMethod0, int());
ajwong@chromium.orge2cca632011-02-15 10:27:38 +090041
dchengb78a84f2016-09-24 14:05:57 +090042 MOCK_METHOD1(VoidMethodWithIntArg, void(int));
tzikd14dea22016-10-12 13:55:02 +090043 MOCK_METHOD0(UniquePtrMethod0, std::unique_ptr<int>());
dchengb78a84f2016-09-24 14:05:57 +090044
ajwong@chromium.orge2cca632011-02-15 10:27:38 +090045 private:
46 // Particularly important in this test to ensure no copies are made.
47 DISALLOW_COPY_AND_ASSIGN(NoRef);
48};
49
50class HasRef : public NoRef {
51 public:
52 HasRef() {}
53
tzik260fab52015-12-19 18:18:46 +090054 MOCK_CONST_METHOD0(AddRef, void());
55 MOCK_CONST_METHOD0(Release, bool());
ajwong@chromium.orge2cca632011-02-15 10:27:38 +090056
57 private:
58 // Particularly important in this test to ensure no copies are made.
59 DISALLOW_COPY_AND_ASSIGN(HasRef);
60};
61
ajwong@chromium.org62997402011-04-14 07:40:46 +090062class HasRefPrivateDtor : public HasRef {
63 private:
64 ~HasRefPrivateDtor() {}
65};
66
ajwong@chromium.orge2cca632011-02-15 10:27:38 +090067static const int kParentValue = 1;
68static const int kChildValue = 2;
69
70class Parent {
71 public:
tzik260fab52015-12-19 18:18:46 +090072 void AddRef() const {}
73 void Release() const {}
ajwong@chromium.orge2cca632011-02-15 10:27:38 +090074 virtual void VirtualSet() { value = kParentValue; }
75 void NonVirtualSet() { value = kParentValue; }
76 int value;
77};
78
79class Child : public Parent {
80 public:
dcheng7dc8df52014-10-21 19:54:51 +090081 void VirtualSet() override { value = kChildValue; }
ajwong@chromium.orge2cca632011-02-15 10:27:38 +090082 void NonVirtualSet() { value = kChildValue; }
83};
84
85class NoRefParent {
86 public:
87 virtual void VirtualSet() { value = kParentValue; }
88 void NonVirtualSet() { value = kParentValue; }
89 int value;
90};
91
92class NoRefChild : public NoRefParent {
dcheng7dc8df52014-10-21 19:54:51 +090093 void VirtualSet() override { value = kChildValue; }
ajwong@chromium.orge2cca632011-02-15 10:27:38 +090094 void NonVirtualSet() { value = kChildValue; }
95};
96
tzik14cb77d2016-02-15 20:54:30 +090097// Used for probing the number of copies and moves that occur if a type must be
98// coerced during argument forwarding in the Run() methods.
99struct DerivedCopyMoveCounter {
100 DerivedCopyMoveCounter(int* copies,
101 int* assigns,
102 int* move_constructs,
103 int* move_assigns)
104 : copies_(copies),
105 assigns_(assigns),
106 move_constructs_(move_constructs),
107 move_assigns_(move_assigns) {}
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900108 int* copies_;
109 int* assigns_;
tzik14cb77d2016-02-15 20:54:30 +0900110 int* move_constructs_;
111 int* move_assigns_;
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900112};
113
tzik14cb77d2016-02-15 20:54:30 +0900114// Used for probing the number of copies and moves in an argument.
115class CopyMoveCounter {
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900116 public:
tzik14cb77d2016-02-15 20:54:30 +0900117 CopyMoveCounter(int* copies,
118 int* assigns,
119 int* move_constructs,
120 int* move_assigns)
121 : copies_(copies),
122 assigns_(assigns),
123 move_constructs_(move_constructs),
124 move_assigns_(move_assigns) {}
125
126 CopyMoveCounter(const CopyMoveCounter& other)
127 : copies_(other.copies_),
128 assigns_(other.assigns_),
129 move_constructs_(other.move_constructs_),
130 move_assigns_(other.move_assigns_) {
131 (*copies_)++;
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900132 }
133
tzik14cb77d2016-02-15 20:54:30 +0900134 CopyMoveCounter(CopyMoveCounter&& other)
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900135 : copies_(other.copies_),
tzik14cb77d2016-02-15 20:54:30 +0900136 assigns_(other.assigns_),
137 move_constructs_(other.move_constructs_),
138 move_assigns_(other.move_assigns_) {
139 (*move_constructs_)++;
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900140 }
141
ajwong@chromium.orgf66a7db2011-12-23 06:12:58 +0900142 // Probing for copies from coercion.
tzik14cb77d2016-02-15 20:54:30 +0900143 explicit CopyMoveCounter(const DerivedCopyMoveCounter& other)
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900144 : copies_(other.copies_),
tzik14cb77d2016-02-15 20:54:30 +0900145 assigns_(other.assigns_),
146 move_constructs_(other.move_constructs_),
147 move_assigns_(other.move_assigns_) {
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900148 (*copies_)++;
149 }
150
tzik14cb77d2016-02-15 20:54:30 +0900151 // Probing for moves from coercion.
152 explicit CopyMoveCounter(DerivedCopyMoveCounter&& other)
153 : copies_(other.copies_),
154 assigns_(other.assigns_),
155 move_constructs_(other.move_constructs_),
156 move_assigns_(other.move_assigns_) {
157 (*move_constructs_)++;
158 }
159
160 const CopyMoveCounter& operator=(const CopyMoveCounter& rhs) {
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900161 copies_ = rhs.copies_;
162 assigns_ = rhs.assigns_;
tzik14cb77d2016-02-15 20:54:30 +0900163 move_constructs_ = rhs.move_constructs_;
164 move_assigns_ = rhs.move_assigns_;
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900165
tzik14cb77d2016-02-15 20:54:30 +0900166 (*assigns_)++;
167
168 return *this;
169 }
170
171 const CopyMoveCounter& operator=(CopyMoveCounter&& rhs) {
172 copies_ = rhs.copies_;
173 assigns_ = rhs.assigns_;
174 move_constructs_ = rhs.move_constructs_;
175 move_assigns_ = rhs.move_assigns_;
176
177 (*move_assigns_)++;
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900178
179 return *this;
180 }
181
182 int copies() const {
183 return *copies_;
184 }
185
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900186 private:
187 int* copies_;
188 int* assigns_;
tzik14cb77d2016-02-15 20:54:30 +0900189 int* move_constructs_;
190 int* move_assigns_;
191};
192
193// Used for probing the number of copies in an argument. The instance is a
194// copyable and non-movable type.
195class CopyCounter {
196 public:
197 CopyCounter(int* copies, int* assigns)
198 : counter_(copies, assigns, nullptr, nullptr) {}
199 CopyCounter(const CopyCounter& other) : counter_(other.counter_) {}
200 CopyCounter& operator=(const CopyCounter& other) {
201 counter_ = other.counter_;
202 return *this;
203 }
204
205 explicit CopyCounter(const DerivedCopyMoveCounter& other) : counter_(other) {}
206
207 int copies() const { return counter_.copies(); }
208
209 private:
210 CopyMoveCounter counter_;
211};
212
213// Used for probing the number of moves in an argument. The instance is a
214// non-copyable and movable type.
215class MoveCounter {
216 public:
217 MoveCounter(int* move_constructs, int* move_assigns)
218 : counter_(nullptr, nullptr, move_constructs, move_assigns) {}
219 MoveCounter(MoveCounter&& other) : counter_(std::move(other.counter_)) {}
220 MoveCounter& operator=(MoveCounter&& other) {
221 counter_ = std::move(other.counter_);
222 return *this;
223 }
224
225 explicit MoveCounter(DerivedCopyMoveCounter&& other)
226 : counter_(std::move(other)) {}
227
228 private:
229 CopyMoveCounter counter_;
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900230};
231
ajwong@chromium.org41339142011-10-15 09:34:42 +0900232class DeleteCounter {
233 public:
234 explicit DeleteCounter(int* deletes)
235 : deletes_(deletes) {
236 }
237
238 ~DeleteCounter() {
239 (*deletes_)++;
240 }
241
242 void VoidMethod0() {}
243
244 private:
245 int* deletes_;
246};
247
ajwong@chromium.orgf66a7db2011-12-23 06:12:58 +0900248template <typename T>
249T PassThru(T scoper) {
dcheng3d580cf2015-12-15 05:31:52 +0900250 return scoper;
ajwong@chromium.orgf66a7db2011-12-23 06:12:58 +0900251}
252
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900253// Some test functions that we can Bind to.
254template <typename T>
255T PolymorphicIdentity(T t) {
256 return t;
257}
258
tzik5b8bf3f2015-12-18 11:23:26 +0900259template <typename... Ts>
260struct VoidPolymorphic {
261 static void Run(Ts... t) {}
262};
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900263
264int Identity(int n) {
265 return n;
266}
267
268int ArrayGet(const int array[], int n) {
269 return array[n];
270}
271
272int Sum(int a, int b, int c, int d, int e, int f) {
273 return a + b + c + d + e + f;
274}
275
276const char* CStringIdentity(const char* s) {
277 return s;
278}
279
tzik14cb77d2016-02-15 20:54:30 +0900280int GetCopies(const CopyMoveCounter& counter) {
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900281 return counter.copies();
282}
283
284int UnwrapNoRefParent(NoRefParent p) {
285 return p.value;
286}
287
288int UnwrapNoRefParentPtr(NoRefParent* p) {
289 return p->value;
290}
291
292int UnwrapNoRefParentConstRef(const NoRefParent& p) {
293 return p.value;
294}
295
ajwong@chromium.orga7e74822011-03-24 11:02:17 +0900296void RefArgSet(int &n) {
297 n = 2;
298}
299
ajwong@chromium.orgabd70002011-12-20 09:10:04 +0900300void PtrArgSet(int *n) {
301 *n = 2;
302}
303
ajwong@chromium.orgc711b822011-05-17 07:35:14 +0900304int FunctionWithWeakFirstParam(WeakPtr<NoRef> o, int n) {
305 return n;
306}
307
willchan@chromium.org6141a822013-06-23 05:32:50 +0900308int FunctionWithScopedRefptrFirstParam(const scoped_refptr<HasRef>& o, int n) {
309 return n;
310}
311
ajwong@chromium.orgabd70002011-12-20 09:10:04 +0900312void TakesACallback(const Closure& callback) {
313 callback.Run();
314}
315
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900316class BindTest : public ::testing::Test {
317 public:
318 BindTest() {
319 const_has_ref_ptr_ = &has_ref_;
320 const_no_ref_ptr_ = &no_ref_;
321 static_func_mock_ptr = &static_func_mock_;
322 }
323
324 virtual ~BindTest() {
325 }
326
tzik260fab52015-12-19 18:18:46 +0900327 static void VoidFunc0() {
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900328 static_func_mock_ptr->VoidMethod0();
329 }
330
tzik260fab52015-12-19 18:18:46 +0900331 static int IntFunc0() { return static_func_mock_ptr->IntMethod0(); }
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900332
333 protected:
334 StrictMock<NoRef> no_ref_;
335 StrictMock<HasRef> has_ref_;
336 const HasRef* const_has_ref_ptr_;
337 const NoRef* const_no_ref_ptr_;
338 StrictMock<NoRef> static_func_mock_;
339
340 // Used by the static functions to perform expectations.
341 static StrictMock<NoRef>* static_func_mock_ptr;
342
343 private:
344 DISALLOW_COPY_AND_ASSIGN(BindTest);
345};
346
347StrictMock<NoRef>* BindTest::static_func_mock_ptr;
tzikd14dea22016-10-12 13:55:02 +0900348StrictMock<NoRef>* g_func_mock_ptr;
349
350void VoidFunc0() {
351 g_func_mock_ptr->VoidMethod0();
352}
353
354int IntFunc0() {
355 return g_func_mock_ptr->IntMethod0();
356}
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900357
tzike7cf9012016-08-23 13:23:49 +0900358TEST_F(BindTest, BasicTest) {
359 Callback<int(int, int, int)> cb = Bind(&Sum, 32, 16, 8);
360 EXPECT_EQ(92, cb.Run(13, 12, 11));
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900361
tzike7cf9012016-08-23 13:23:49 +0900362 Callback<int(int, int, int, int, int, int)> c1 = Bind(&Sum);
363 EXPECT_EQ(69, c1.Run(14, 13, 12, 11, 10, 9));
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900364
tzike7cf9012016-08-23 13:23:49 +0900365 Callback<int(int, int, int)> c2 = Bind(c1, 32, 16, 8);
366 EXPECT_EQ(86, c2.Run(11, 10, 9));
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900367
tzike7cf9012016-08-23 13:23:49 +0900368 Callback<int()> c3 = Bind(c2, 4, 2, 1);
369 EXPECT_EQ(63, c3.Run());
ajwong@chromium.orgd483ffe2011-09-30 18:09:34 +0900370}
371
ajwong@chromium.orgabd70002011-12-20 09:10:04 +0900372// Test that currying the rvalue result of another Bind() works correctly.
373// - rvalue should be usable as argument to Bind().
374// - multiple runs of resulting Callback remain valid.
375TEST_F(BindTest, CurryingRvalueResultOfBind) {
376 int n = 0;
tzikd14dea22016-10-12 13:55:02 +0900377 RepeatingClosure cb = BindRepeating(&TakesACallback,
378 BindRepeating(&PtrArgSet, &n));
ajwong@chromium.orgabd70002011-12-20 09:10:04 +0900379
380 // If we implement Bind() such that the return value has auto_ptr-like
381 // semantics, the second call here will fail because ownership of
382 // the internal BindState<> would have been transfered to a *temporary*
383 // constructon of a Callback object on the first call.
384 cb.Run();
385 EXPECT_EQ(2, n);
386
387 n = 0;
388 cb.Run();
389 EXPECT_EQ(2, n);
390}
391
tzikd14dea22016-10-12 13:55:02 +0900392TEST_F(BindTest, RepeatingCallbackBasicTest) {
393 RepeatingCallback<int(int)> c0 = BindRepeating(&Sum, 1, 2, 4, 8, 16);
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900394
tzikd14dea22016-10-12 13:55:02 +0900395 // RepeatingCallback can run via a lvalue-reference.
396 EXPECT_EQ(63, c0.Run(32));
ajwong@chromium.org505386d2011-09-10 12:03:00 +0900397
tzikd14dea22016-10-12 13:55:02 +0900398 // It is valid to call a RepeatingCallback more than once.
399 EXPECT_EQ(54, c0.Run(23));
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900400
tzikd14dea22016-10-12 13:55:02 +0900401 // BindRepeating can handle a RepeatingCallback as the target functor.
402 RepeatingCallback<int()> c1 = BindRepeating(c0, 11);
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900403
tzikd14dea22016-10-12 13:55:02 +0900404 // RepeatingCallback can run via a rvalue-reference.
405 EXPECT_EQ(42, std::move(c1).Run());
406
407 // BindRepeating can handle a rvalue-reference of RepeatingCallback.
408 EXPECT_EQ(32, BindRepeating(std::move(c0), 1).Run());
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900409}
410
tzikd14dea22016-10-12 13:55:02 +0900411TEST_F(BindTest, OnceCallbackBasicTest) {
412 OnceCallback<int(int)> c0 = BindOnce(&Sum, 1, 2, 4, 8, 16);
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900413
tzikd14dea22016-10-12 13:55:02 +0900414 // OnceCallback can run via a rvalue-reference.
415 EXPECT_EQ(63, std::move(c0).Run(32));
416
417 // After running via the rvalue-reference, the value of the OnceCallback
418 // is undefined. The implementation simply clears the instance after the
419 // invocation.
420 EXPECT_TRUE(c0.is_null());
421
422 c0 = BindOnce(&Sum, 2, 3, 5, 7, 11);
423
424 // BindOnce can handle a rvalue-reference of OnceCallback as the target
425 // functor.
426 OnceCallback<int()> c1 = BindOnce(std::move(c0), 13);
427 EXPECT_EQ(41, std::move(c1).Run());
428
429 RepeatingCallback<int(int)> c2 = BindRepeating(&Sum, 2, 3, 5, 7, 11);
430 EXPECT_EQ(41, BindOnce(c2, 13).Run());
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900431}
432
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900433// IgnoreResult adapter test.
434// - Function with return value.
435// - Method with return value.
436// - Const Method with return.
437// - Method with return value bound to WeakPtr<>.
438// - Const Method with return bound to WeakPtr<>.
tzikd14dea22016-10-12 13:55:02 +0900439TEST_F(BindTest, IgnoreResultForRepeating) {
ajwong@chromium.org718dddf2011-09-28 09:26:37 +0900440 EXPECT_CALL(static_func_mock_, IntMethod0()).WillOnce(Return(1337));
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900441 EXPECT_CALL(has_ref_, AddRef()).Times(2);
442 EXPECT_CALL(has_ref_, Release()).Times(2);
443 EXPECT_CALL(has_ref_, IntMethod0()).WillOnce(Return(10));
444 EXPECT_CALL(has_ref_, IntConstMethod0()).WillOnce(Return(11));
445 EXPECT_CALL(no_ref_, IntMethod0()).WillOnce(Return(12));
446 EXPECT_CALL(no_ref_, IntConstMethod0()).WillOnce(Return(13));
447
tzikd14dea22016-10-12 13:55:02 +0900448 RepeatingClosure normal_func_cb = BindRepeating(IgnoreResult(&IntFunc0));
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900449 normal_func_cb.Run();
450
tzikd14dea22016-10-12 13:55:02 +0900451 RepeatingClosure non_void_method_cb =
452 BindRepeating(IgnoreResult(&HasRef::IntMethod0), &has_ref_);
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900453 non_void_method_cb.Run();
454
tzikd14dea22016-10-12 13:55:02 +0900455 RepeatingClosure non_void_const_method_cb =
456 BindRepeating(IgnoreResult(&HasRef::IntConstMethod0), &has_ref_);
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900457 non_void_const_method_cb.Run();
458
459 WeakPtrFactory<NoRef> weak_factory(&no_ref_);
460 WeakPtrFactory<const NoRef> const_weak_factory(const_no_ref_ptr_);
461
tzikd14dea22016-10-12 13:55:02 +0900462 RepeatingClosure non_void_weak_method_cb =
463 BindRepeating(IgnoreResult(&NoRef::IntMethod0),
464 weak_factory.GetWeakPtr());
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900465 non_void_weak_method_cb.Run();
466
tzikd14dea22016-10-12 13:55:02 +0900467 RepeatingClosure non_void_weak_const_method_cb =
468 BindRepeating(IgnoreResult(&NoRef::IntConstMethod0),
469 weak_factory.GetWeakPtr());
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900470 non_void_weak_const_method_cb.Run();
471
472 weak_factory.InvalidateWeakPtrs();
473 non_void_weak_const_method_cb.Run();
474 non_void_weak_method_cb.Run();
ajwong@chromium.org718dddf2011-09-28 09:26:37 +0900475}
476
tzikd14dea22016-10-12 13:55:02 +0900477TEST_F(BindTest, IgnoreResultForOnce) {
478 EXPECT_CALL(static_func_mock_, IntMethod0()).WillOnce(Return(1337));
479 EXPECT_CALL(has_ref_, AddRef()).Times(2);
480 EXPECT_CALL(has_ref_, Release()).Times(2);
481 EXPECT_CALL(has_ref_, IntMethod0()).WillOnce(Return(10));
482 EXPECT_CALL(has_ref_, IntConstMethod0()).WillOnce(Return(11));
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900483
tzikd14dea22016-10-12 13:55:02 +0900484 OnceClosure normal_func_cb = BindOnce(IgnoreResult(&IntFunc0));
485 std::move(normal_func_cb).Run();
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900486
tzikd14dea22016-10-12 13:55:02 +0900487 OnceClosure non_void_method_cb =
488 BindOnce(IgnoreResult(&HasRef::IntMethod0), &has_ref_);
489 std::move(non_void_method_cb).Run();
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900490
tzikd14dea22016-10-12 13:55:02 +0900491 OnceClosure non_void_const_method_cb =
492 BindOnce(IgnoreResult(&HasRef::IntConstMethod0), &has_ref_);
493 std::move(non_void_const_method_cb).Run();
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900494
tzikd14dea22016-10-12 13:55:02 +0900495 WeakPtrFactory<NoRef> weak_factory(&no_ref_);
496 WeakPtrFactory<const NoRef> const_weak_factory(const_no_ref_ptr_);
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900497
tzikd14dea22016-10-12 13:55:02 +0900498 OnceClosure non_void_weak_method_cb =
499 BindOnce(IgnoreResult(&NoRef::IntMethod0),
500 weak_factory.GetWeakPtr());
501 OnceClosure non_void_weak_const_method_cb =
502 BindOnce(IgnoreResult(&NoRef::IntConstMethod0),
503 weak_factory.GetWeakPtr());
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900504
tzikd14dea22016-10-12 13:55:02 +0900505 weak_factory.InvalidateWeakPtrs();
506 std::move(non_void_weak_const_method_cb).Run();
507 std::move(non_void_weak_method_cb).Run();
ajwong@chromium.orga7e74822011-03-24 11:02:17 +0900508}
509
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900510// Functions that take reference parameters.
511// - Forced reference parameter type still stores a copy.
512// - Forced const reference parameter type still stores a copy.
tzikd14dea22016-10-12 13:55:02 +0900513TEST_F(BindTest, ReferenceArgumentBindingForRepeating) {
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900514 int n = 1;
515 int& ref_n = n;
516 const int& const_ref_n = n;
517
tzikd14dea22016-10-12 13:55:02 +0900518 RepeatingCallback<int()> ref_copies_cb = BindRepeating(&Identity, ref_n);
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900519 EXPECT_EQ(n, ref_copies_cb.Run());
520 n++;
521 EXPECT_EQ(n - 1, ref_copies_cb.Run());
522
tzikd14dea22016-10-12 13:55:02 +0900523 RepeatingCallback<int()> const_ref_copies_cb =
524 BindRepeating(&Identity, const_ref_n);
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900525 EXPECT_EQ(n, const_ref_copies_cb.Run());
526 n++;
527 EXPECT_EQ(n - 1, const_ref_copies_cb.Run());
528}
529
tzikd14dea22016-10-12 13:55:02 +0900530TEST_F(BindTest, ReferenceArgumentBindingForOnce) {
531 int n = 1;
532 int& ref_n = n;
533 const int& const_ref_n = n;
534
535 OnceCallback<int()> ref_copies_cb = BindOnce(&Identity, ref_n);
536 n++;
537 EXPECT_EQ(n - 1, std::move(ref_copies_cb).Run());
538
539 OnceCallback<int()> const_ref_copies_cb =
540 BindOnce(&Identity, const_ref_n);
541 n++;
542 EXPECT_EQ(n - 1, std::move(const_ref_copies_cb).Run());
543}
544
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900545// Check that we can pass in arrays and have them be stored as a pointer.
546// - Array of values stores a pointer.
547// - Array of const values stores a pointer.
tzikd14dea22016-10-12 13:55:02 +0900548TEST_F(BindTest, ArrayArgumentBindingForRepeating) {
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900549 int array[4] = {1, 1, 1, 1};
550 const int (*const_array_ptr)[4] = &array;
551
tzikd14dea22016-10-12 13:55:02 +0900552 RepeatingCallback<int()> array_cb = BindRepeating(&ArrayGet, array, 1);
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900553 EXPECT_EQ(1, array_cb.Run());
554
tzikd14dea22016-10-12 13:55:02 +0900555 RepeatingCallback<int()> const_array_cb =
556 BindRepeating(&ArrayGet, *const_array_ptr, 1);
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900557 EXPECT_EQ(1, const_array_cb.Run());
558
559 array[1] = 3;
560 EXPECT_EQ(3, array_cb.Run());
561 EXPECT_EQ(3, const_array_cb.Run());
562}
563
tzikd14dea22016-10-12 13:55:02 +0900564TEST_F(BindTest, ArrayArgumentBindingForOnce) {
565 int array[4] = {1, 1, 1, 1};
566 const int (*const_array_ptr)[4] = &array;
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900567
tzikd14dea22016-10-12 13:55:02 +0900568 OnceCallback<int()> array_cb = BindOnce(&ArrayGet, array, 1);
569 OnceCallback<int()> const_array_cb =
570 BindOnce(&ArrayGet, *const_array_ptr, 1);
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900571
tzikd14dea22016-10-12 13:55:02 +0900572 array[1] = 3;
573 EXPECT_EQ(3, std::move(array_cb).Run());
574 EXPECT_EQ(3, std::move(const_array_cb).Run());
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900575}
576
ajwong@chromium.orgc711b822011-05-17 07:35:14 +0900577// WeakPtr() support.
578// - Method bound to WeakPtr<> to non-const object.
579// - Const method bound to WeakPtr<> to non-const object.
580// - Const method bound to WeakPtr<> to const object.
581// - Normal Function with WeakPtr<> as P1 can have return type and is
582// not canceled.
tzikd14dea22016-10-12 13:55:02 +0900583TEST_F(BindTest, WeakPtrForRepeating) {
ajwong@chromium.orgc711b822011-05-17 07:35:14 +0900584 EXPECT_CALL(no_ref_, VoidMethod0());
585 EXPECT_CALL(no_ref_, VoidConstMethod0()).Times(2);
586
587 WeakPtrFactory<NoRef> weak_factory(&no_ref_);
588 WeakPtrFactory<const NoRef> const_weak_factory(const_no_ref_ptr_);
589
tzikd14dea22016-10-12 13:55:02 +0900590 RepeatingClosure method_cb =
591 BindRepeating(&NoRef::VoidMethod0, weak_factory.GetWeakPtr());
ajwong@chromium.orgc711b822011-05-17 07:35:14 +0900592 method_cb.Run();
593
tzikd14dea22016-10-12 13:55:02 +0900594 RepeatingClosure const_method_cb =
595 BindRepeating(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr());
ajwong@chromium.orgc711b822011-05-17 07:35:14 +0900596 const_method_cb.Run();
597
tzikd14dea22016-10-12 13:55:02 +0900598 RepeatingClosure const_method_const_ptr_cb =
599 BindRepeating(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr());
ajwong@chromium.orgc711b822011-05-17 07:35:14 +0900600 const_method_const_ptr_cb.Run();
601
tzikd14dea22016-10-12 13:55:02 +0900602 RepeatingCallback<int(int)> normal_func_cb =
603 BindRepeating(&FunctionWithWeakFirstParam, weak_factory.GetWeakPtr());
ajwong@chromium.orgc711b822011-05-17 07:35:14 +0900604 EXPECT_EQ(1, normal_func_cb.Run(1));
605
606 weak_factory.InvalidateWeakPtrs();
607 const_weak_factory.InvalidateWeakPtrs();
608
609 method_cb.Run();
610 const_method_cb.Run();
611 const_method_const_ptr_cb.Run();
612
613 // Still runs even after the pointers are invalidated.
614 EXPECT_EQ(2, normal_func_cb.Run(2));
615}
616
tzikd14dea22016-10-12 13:55:02 +0900617TEST_F(BindTest, WeakPtrForOnce) {
618 WeakPtrFactory<NoRef> weak_factory(&no_ref_);
619 WeakPtrFactory<const NoRef> const_weak_factory(const_no_ref_ptr_);
620
621 OnceClosure method_cb =
622 BindOnce(&NoRef::VoidMethod0, weak_factory.GetWeakPtr());
623 OnceClosure const_method_cb =
624 BindOnce(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr());
625 OnceClosure const_method_const_ptr_cb =
626 BindOnce(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr());
627 Callback<int(int)> normal_func_cb =
628 Bind(&FunctionWithWeakFirstParam, weak_factory.GetWeakPtr());
629
630 weak_factory.InvalidateWeakPtrs();
631 const_weak_factory.InvalidateWeakPtrs();
632
633 std::move(method_cb).Run();
634 std::move(const_method_cb).Run();
635 std::move(const_method_const_ptr_cb).Run();
636
637 // Still runs even after the pointers are invalidated.
638 EXPECT_EQ(2, std::move(normal_func_cb).Run(2));
639}
640
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900641// ConstRef() wrapper support.
642// - Binding w/o ConstRef takes a copy.
643// - Binding a ConstRef takes a reference.
644// - Binding ConstRef to a function ConstRef does not copy on invoke.
tzikd14dea22016-10-12 13:55:02 +0900645TEST_F(BindTest, ConstRefForRepeating) {
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900646 int n = 1;
647
tzikd14dea22016-10-12 13:55:02 +0900648 RepeatingCallback<int()> copy_cb = BindRepeating(&Identity, n);
649 RepeatingCallback<int()> const_ref_cb = BindRepeating(&Identity, ConstRef(n));
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900650 EXPECT_EQ(n, copy_cb.Run());
651 EXPECT_EQ(n, const_ref_cb.Run());
652 n++;
653 EXPECT_EQ(n - 1, copy_cb.Run());
654 EXPECT_EQ(n, const_ref_cb.Run());
655
656 int copies = 0;
657 int assigns = 0;
tzik14cb77d2016-02-15 20:54:30 +0900658 int move_constructs = 0;
659 int move_assigns = 0;
660 CopyMoveCounter counter(&copies, &assigns, &move_constructs, &move_assigns);
tzikd14dea22016-10-12 13:55:02 +0900661 RepeatingCallback<int()> all_const_ref_cb =
662 BindRepeating(&GetCopies, ConstRef(counter));
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900663 EXPECT_EQ(0, all_const_ref_cb.Run());
664 EXPECT_EQ(0, copies);
665 EXPECT_EQ(0, assigns);
tzik14cb77d2016-02-15 20:54:30 +0900666 EXPECT_EQ(0, move_constructs);
667 EXPECT_EQ(0, move_assigns);
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900668}
669
tzikd14dea22016-10-12 13:55:02 +0900670TEST_F(BindTest, ConstRefForOnce) {
671 int n = 1;
willchan@chromium.org6141a822013-06-23 05:32:50 +0900672
tzikd14dea22016-10-12 13:55:02 +0900673 OnceCallback<int()> copy_cb = BindOnce(&Identity, n);
674 OnceCallback<int()> const_ref_cb = BindOnce(&Identity, ConstRef(n));
675 n++;
676 EXPECT_EQ(n - 1, std::move(copy_cb).Run());
677 EXPECT_EQ(n, std::move(const_ref_cb).Run());
678
679 int copies = 0;
680 int assigns = 0;
681 int move_constructs = 0;
682 int move_assigns = 0;
683 CopyMoveCounter counter(&copies, &assigns, &move_constructs, &move_assigns);
684 OnceCallback<int()> all_const_ref_cb =
685 BindOnce(&GetCopies, ConstRef(counter));
686 EXPECT_EQ(0, std::move(all_const_ref_cb).Run());
687 EXPECT_EQ(0, copies);
688 EXPECT_EQ(0, assigns);
689 EXPECT_EQ(0, move_constructs);
690 EXPECT_EQ(0, move_assigns);
willchan@chromium.org6141a822013-06-23 05:32:50 +0900691}
692
ajwong@chromium.org41339142011-10-15 09:34:42 +0900693// Test Owned() support.
tzikd14dea22016-10-12 13:55:02 +0900694TEST_F(BindTest, OwnedForRepeating) {
ajwong@chromium.org41339142011-10-15 09:34:42 +0900695 int deletes = 0;
696 DeleteCounter* counter = new DeleteCounter(&deletes);
697
698 // If we don't capture, delete happens on Callback destruction/reset.
699 // return the same value.
tzikd14dea22016-10-12 13:55:02 +0900700 RepeatingCallback<DeleteCounter*()> no_capture_cb =
701 BindRepeating(&PolymorphicIdentity<DeleteCounter*>, Owned(counter));
ajwong@chromium.orgf66a7db2011-12-23 06:12:58 +0900702 ASSERT_EQ(counter, no_capture_cb.Run());
703 ASSERT_EQ(counter, no_capture_cb.Run());
ajwong@chromium.org41339142011-10-15 09:34:42 +0900704 EXPECT_EQ(0, deletes);
705 no_capture_cb.Reset(); // This should trigger a delete.
706 EXPECT_EQ(1, deletes);
707
708 deletes = 0;
709 counter = new DeleteCounter(&deletes);
tzikd14dea22016-10-12 13:55:02 +0900710 RepeatingClosure own_object_cb =
711 BindRepeating(&DeleteCounter::VoidMethod0, Owned(counter));
ajwong@chromium.org41339142011-10-15 09:34:42 +0900712 own_object_cb.Run();
713 EXPECT_EQ(0, deletes);
714 own_object_cb.Reset();
715 EXPECT_EQ(1, deletes);
716}
717
tzikd14dea22016-10-12 13:55:02 +0900718TEST_F(BindTest, OwnedForOnce) {
719 int deletes = 0;
720 DeleteCounter* counter = new DeleteCounter(&deletes);
721
722 // If we don't capture, delete happens on Callback destruction/reset.
723 // return the same value.
724 OnceCallback<DeleteCounter*()> no_capture_cb =
725 BindOnce(&PolymorphicIdentity<DeleteCounter*>, Owned(counter));
726 EXPECT_EQ(0, deletes);
727 no_capture_cb.Reset(); // This should trigger a delete.
728 EXPECT_EQ(1, deletes);
729
730 deletes = 0;
731 counter = new DeleteCounter(&deletes);
732 OnceClosure own_object_cb =
733 BindOnce(&DeleteCounter::VoidMethod0, Owned(counter));
734 EXPECT_EQ(0, deletes);
735 own_object_cb.Reset();
736 EXPECT_EQ(1, deletes);
737}
738
739template <typename T>
740class BindVariantsTest : public ::testing::Test {
741};
742
743struct RepeatingTestConfig {
744 template <typename Signature>
745 using CallbackType = RepeatingCallback<Signature>;
746 using ClosureType = RepeatingClosure;
747
748 template <typename F, typename... Args>
749 static CallbackType<MakeUnboundRunType<F, Args...>>
750 Bind(F&& f, Args&&... args) {
751 return BindRepeating(std::forward<F>(f), std::forward<Args>(args)...);
752 }
753};
754
755struct OnceTestConfig {
756 template <typename Signature>
757 using CallbackType = OnceCallback<Signature>;
758 using ClosureType = OnceClosure;
759
760 template <typename F, typename... Args>
761 static CallbackType<MakeUnboundRunType<F, Args...>>
762 Bind(F&& f, Args&&... args) {
763 return BindOnce(std::forward<F>(f), std::forward<Args>(args)...);
764 }
765};
766
767using BindVariantsTestConfig = ::testing::Types<
768 RepeatingTestConfig, OnceTestConfig>;
769TYPED_TEST_CASE(BindVariantsTest, BindVariantsTestConfig);
770
771template <typename TypeParam, typename Signature>
772using CallbackType = typename TypeParam::template CallbackType<Signature>;
773
774// Function type support.
775// - Normal function.
776// - Normal function bound with non-refcounted first argument.
777// - Method bound to non-const object.
778// - Method bound to scoped_refptr.
779// - Const method bound to non-const object.
780// - Const method bound to const object.
781// - Derived classes can be used with pointers to non-virtual base functions.
782// - Derived classes can be used with pointers to virtual base functions (and
783// preserve virtual dispatch).
784TYPED_TEST(BindVariantsTest, FunctionTypeSupport) {
785 using ClosureType = typename TypeParam::ClosureType;
786
787 StrictMock<HasRef> has_ref;
788 StrictMock<NoRef> no_ref;
789 StrictMock<NoRef> static_func_mock;
790 const HasRef* const_has_ref_ptr = &has_ref;
791 g_func_mock_ptr = &static_func_mock;
792
793 EXPECT_CALL(static_func_mock, VoidMethod0());
794 EXPECT_CALL(has_ref, AddRef()).Times(4);
795 EXPECT_CALL(has_ref, Release()).Times(4);
796 EXPECT_CALL(has_ref, VoidMethod0()).Times(2);
797 EXPECT_CALL(has_ref, VoidConstMethod0()).Times(2);
798
799 ClosureType normal_cb = TypeParam::Bind(&VoidFunc0);
800 CallbackType<TypeParam, NoRef*()> normal_non_refcounted_cb =
801 TypeParam::Bind(&PolymorphicIdentity<NoRef*>, &no_ref);
802 std::move(normal_cb).Run();
803 EXPECT_EQ(&no_ref, std::move(normal_non_refcounted_cb).Run());
804
805 ClosureType method_cb = TypeParam::Bind(&HasRef::VoidMethod0, &has_ref);
806 ClosureType method_refptr_cb = TypeParam::Bind(&HasRef::VoidMethod0,
807 make_scoped_refptr(&has_ref));
808 ClosureType const_method_nonconst_obj_cb =
809 TypeParam::Bind(&HasRef::VoidConstMethod0, &has_ref);
810 ClosureType const_method_const_obj_cb =
811 TypeParam::Bind(&HasRef::VoidConstMethod0, const_has_ref_ptr);
812 std::move(method_cb).Run();
813 std::move(method_refptr_cb).Run();
814 std::move(const_method_nonconst_obj_cb).Run();
815 std::move(const_method_const_obj_cb).Run();
816
817 Child child;
818 child.value = 0;
819 ClosureType virtual_set_cb = TypeParam::Bind(&Parent::VirtualSet, &child);
820 std::move(virtual_set_cb).Run();
821 EXPECT_EQ(kChildValue, child.value);
822
823 child.value = 0;
824 ClosureType non_virtual_set_cb =
825 TypeParam::Bind(&Parent::NonVirtualSet, &child);
826 std::move(non_virtual_set_cb).Run();
827 EXPECT_EQ(kParentValue, child.value);
828}
829
830// Return value support.
831// - Function with return value.
832// - Method with return value.
833// - Const method with return value.
834// - Move-only return value.
835TYPED_TEST(BindVariantsTest, ReturnValues) {
836 StrictMock<NoRef> static_func_mock;
837 StrictMock<HasRef> has_ref;
838 g_func_mock_ptr = &static_func_mock;
839 const HasRef* const_has_ref_ptr = &has_ref;
840
841 EXPECT_CALL(static_func_mock, IntMethod0()).WillOnce(Return(1337));
842 EXPECT_CALL(has_ref, AddRef()).Times(4);
843 EXPECT_CALL(has_ref, Release()).Times(4);
844 EXPECT_CALL(has_ref, IntMethod0()).WillOnce(Return(31337));
845 EXPECT_CALL(has_ref, IntConstMethod0())
846 .WillOnce(Return(41337))
847 .WillOnce(Return(51337));
848 EXPECT_CALL(has_ref, UniquePtrMethod0())
849 .WillOnce(Return(ByMove(MakeUnique<int>(42))));
850
851 CallbackType<TypeParam, int()> normal_cb = TypeParam::Bind(&IntFunc0);
852 CallbackType<TypeParam, int()> method_cb =
853 TypeParam::Bind(&HasRef::IntMethod0, &has_ref);
854 CallbackType<TypeParam, int()> const_method_nonconst_obj_cb =
855 TypeParam::Bind(&HasRef::IntConstMethod0, &has_ref);
856 CallbackType<TypeParam, int()> const_method_const_obj_cb =
857 TypeParam::Bind(&HasRef::IntConstMethod0, const_has_ref_ptr);
858 CallbackType<TypeParam, std::unique_ptr<int>()> move_only_rv_cb =
859 TypeParam::Bind(&HasRef::UniquePtrMethod0, &has_ref);
860 EXPECT_EQ(1337, std::move(normal_cb).Run());
861 EXPECT_EQ(31337, std::move(method_cb).Run());
862 EXPECT_EQ(41337, std::move(const_method_nonconst_obj_cb).Run());
863 EXPECT_EQ(51337, std::move(const_method_const_obj_cb).Run());
864 EXPECT_EQ(42, *std::move(move_only_rv_cb).Run());
865}
866
867// Argument binding tests.
868// - Argument binding to primitive.
869// - Argument binding to primitive pointer.
870// - Argument binding to a literal integer.
871// - Argument binding to a literal string.
872// - Argument binding with template function.
873// - Argument binding to an object.
874// - Argument binding to pointer to incomplete type.
875// - Argument gets type converted.
876// - Pointer argument gets converted.
877// - Const Reference forces conversion.
878TYPED_TEST(BindVariantsTest, ArgumentBinding) {
879 int n = 2;
880
881 EXPECT_EQ(n, TypeParam::Bind(&Identity, n).Run());
882 EXPECT_EQ(&n, TypeParam::Bind(&PolymorphicIdentity<int*>, &n).Run());
883 EXPECT_EQ(3, TypeParam::Bind(&Identity, 3).Run());
884 EXPECT_STREQ("hi", TypeParam::Bind(&CStringIdentity, "hi").Run());
885 EXPECT_EQ(4, TypeParam::Bind(&PolymorphicIdentity<int>, 4).Run());
886
887 NoRefParent p;
888 p.value = 5;
889 EXPECT_EQ(5, TypeParam::Bind(&UnwrapNoRefParent, p).Run());
890
891 IncompleteType* incomplete_ptr = reinterpret_cast<IncompleteType*>(123);
892 EXPECT_EQ(incomplete_ptr,
893 TypeParam::Bind(&PolymorphicIdentity<IncompleteType*>,
894 incomplete_ptr).Run());
895
896 NoRefChild c;
897 c.value = 6;
898 EXPECT_EQ(6, TypeParam::Bind(&UnwrapNoRefParent, c).Run());
899
900 c.value = 7;
901 EXPECT_EQ(7, TypeParam::Bind(&UnwrapNoRefParentPtr, &c).Run());
902
903 c.value = 8;
904 EXPECT_EQ(8, TypeParam::Bind(&UnwrapNoRefParentConstRef, c).Run());
905}
906
907// Unbound argument type support tests.
908// - Unbound value.
909// - Unbound pointer.
910// - Unbound reference.
911// - Unbound const reference.
912// - Unbound unsized array.
913// - Unbound sized array.
914// - Unbound array-of-arrays.
915TYPED_TEST(BindVariantsTest, UnboundArgumentTypeSupport) {
916 CallbackType<TypeParam, void(int)> unbound_value_cb =
917 TypeParam::Bind(&VoidPolymorphic<int>::Run);
918 CallbackType<TypeParam, void(int*)> unbound_pointer_cb =
919 TypeParam::Bind(&VoidPolymorphic<int*>::Run);
920 CallbackType<TypeParam, void(int&)> unbound_ref_cb =
921 TypeParam::Bind(&VoidPolymorphic<int&>::Run);
922 CallbackType<TypeParam, void(const int&)> unbound_const_ref_cb =
923 TypeParam::Bind(&VoidPolymorphic<const int&>::Run);
924 CallbackType<TypeParam, void(int[])> unbound_unsized_array_cb =
925 TypeParam::Bind(&VoidPolymorphic<int[]>::Run);
926 CallbackType<TypeParam, void(int[2])> unbound_sized_array_cb =
927 TypeParam::Bind(&VoidPolymorphic<int[2]>::Run);
928 CallbackType<TypeParam, void(int[][2])> unbound_array_of_arrays_cb =
929 TypeParam::Bind(&VoidPolymorphic<int[][2]>::Run);
930 CallbackType<TypeParam, void(int&)> unbound_ref_with_bound_arg =
931 TypeParam::Bind(&VoidPolymorphic<int, int&>::Run, 1);
932}
933
934// Function with unbound reference parameter.
935// - Original parameter is modified by callback.
936TYPED_TEST(BindVariantsTest, UnboundReferenceSupport) {
937 int n = 0;
938 CallbackType<TypeParam, void(int&)> unbound_ref_cb =
939 TypeParam::Bind(&RefArgSet);
940 std::move(unbound_ref_cb).Run(n);
941 EXPECT_EQ(2, n);
942}
943
944// Unretained() wrapper support.
945// - Method bound to Unretained() non-const object.
946// - Const method bound to Unretained() non-const object.
947// - Const method bound to Unretained() const object.
948TYPED_TEST(BindVariantsTest, Unretained) {
949 StrictMock<NoRef> no_ref;
950 const NoRef* const_no_ref_ptr = &no_ref;
951
952 EXPECT_CALL(no_ref, VoidMethod0());
953 EXPECT_CALL(no_ref, VoidConstMethod0()).Times(2);
954
955 TypeParam::Bind(&NoRef::VoidMethod0, Unretained(&no_ref)).Run();
956 TypeParam::Bind(&NoRef::VoidConstMethod0, Unretained(&no_ref)).Run();
957 TypeParam::Bind(&NoRef::VoidConstMethod0, Unretained(const_no_ref_ptr)).Run();
958}
959
960TYPED_TEST(BindVariantsTest, ScopedRefptr) {
961 StrictMock<HasRef> has_ref;
962 EXPECT_CALL(has_ref, AddRef()).Times(1);
963 EXPECT_CALL(has_ref, Release()).Times(1);
964
965 const scoped_refptr<HasRef> refptr(&has_ref);
966 CallbackType<TypeParam, int()> scoped_refptr_const_ref_cb =
967 TypeParam::Bind(&FunctionWithScopedRefptrFirstParam,
968 base::ConstRef(refptr), 1);
969 EXPECT_EQ(1, std::move(scoped_refptr_const_ref_cb).Run());
970}
971
972TYPED_TEST(BindVariantsTest, UniquePtrReceiver) {
tzikfa7381d2016-05-12 08:05:05 +0900973 std::unique_ptr<StrictMock<NoRef>> no_ref(new StrictMock<NoRef>);
974 EXPECT_CALL(*no_ref, VoidMethod0()).Times(1);
tzikd14dea22016-10-12 13:55:02 +0900975 TypeParam::Bind(&NoRef::VoidMethod0, std::move(no_ref)).Run();
tzikfa7381d2016-05-12 08:05:05 +0900976}
977
dcheng11c9cca2016-01-22 04:37:55 +0900978// Tests for Passed() wrapper support:
ajwong@chromium.orgf66a7db2011-12-23 06:12:58 +0900979// - Passed() can be constructed from a pointer to scoper.
980// - Passed() can be constructed from a scoper rvalue.
981// - Using Passed() gives Callback Ownership.
982// - Ownership is transferred from Callback to callee on the first Run().
983// - Callback supports unbound arguments.
dcheng11c9cca2016-01-22 04:37:55 +0900984template <typename T>
985class BindMoveOnlyTypeTest : public ::testing::Test {
986};
987
988struct CustomDeleter {
989 void operator()(DeleteCounter* c) { delete c; }
990};
991
992using MoveOnlyTypesToTest =
dchengcc8e4d82016-04-05 06:25:51 +0900993 ::testing::Types<std::unique_ptr<DeleteCounter>,
dcheng11c9cca2016-01-22 04:37:55 +0900994 std::unique_ptr<DeleteCounter, CustomDeleter>>;
995TYPED_TEST_CASE(BindMoveOnlyTypeTest, MoveOnlyTypesToTest);
996
997TYPED_TEST(BindMoveOnlyTypeTest, PassedToBoundCallback) {
ajwong@chromium.orgf66a7db2011-12-23 06:12:58 +0900998 int deletes = 0;
999
dcheng11c9cca2016-01-22 04:37:55 +09001000 TypeParam ptr(new DeleteCounter(&deletes));
1001 Callback<TypeParam()> callback = Bind(&PassThru<TypeParam>, Passed(&ptr));
ajwong@chromium.orgf66a7db2011-12-23 06:12:58 +09001002 EXPECT_FALSE(ptr.get());
1003 EXPECT_EQ(0, deletes);
1004
1005 // If we never invoke the Callback, it retains ownership and deletes.
ajwong@chromium.orgf66a7db2011-12-23 06:12:58 +09001006 callback.Reset();
ajwong@chromium.orgf66a7db2011-12-23 06:12:58 +09001007 EXPECT_EQ(1, deletes);
ajwong@chromium.orgf66a7db2011-12-23 06:12:58 +09001008}
1009
dcheng11c9cca2016-01-22 04:37:55 +09001010TYPED_TEST(BindMoveOnlyTypeTest, PassedWithRvalue) {
dcheng3d580cf2015-12-15 05:31:52 +09001011 int deletes = 0;
dcheng11c9cca2016-01-22 04:37:55 +09001012 Callback<TypeParam()> callback = Bind(
1013 &PassThru<TypeParam>, Passed(TypeParam(new DeleteCounter(&deletes))));
dcheng3d580cf2015-12-15 05:31:52 +09001014 EXPECT_EQ(0, deletes);
1015
1016 // If we never invoke the Callback, it retains ownership and deletes.
dcheng11c9cca2016-01-22 04:37:55 +09001017 callback.Reset();
dcheng3d580cf2015-12-15 05:31:52 +09001018 EXPECT_EQ(1, deletes);
dcheng11c9cca2016-01-22 04:37:55 +09001019}
dcheng3d580cf2015-12-15 05:31:52 +09001020
dcheng11c9cca2016-01-22 04:37:55 +09001021// Check that ownership can be transferred back out.
1022TYPED_TEST(BindMoveOnlyTypeTest, ReturnMoveOnlyType) {
1023 int deletes = 0;
dcheng3d580cf2015-12-15 05:31:52 +09001024 DeleteCounter* counter = new DeleteCounter(&deletes);
dcheng11c9cca2016-01-22 04:37:55 +09001025 Callback<TypeParam()> callback =
1026 Bind(&PassThru<TypeParam>, Passed(TypeParam(counter)));
1027 TypeParam result = callback.Run();
dcheng3d580cf2015-12-15 05:31:52 +09001028 ASSERT_EQ(counter, result.get());
1029 EXPECT_EQ(0, deletes);
1030
1031 // Resetting does not delete since ownership was transferred.
1032 callback.Reset();
1033 EXPECT_EQ(0, deletes);
1034
1035 // Ensure that we actually did get ownership.
1036 result.reset();
1037 EXPECT_EQ(1, deletes);
dcheng11c9cca2016-01-22 04:37:55 +09001038}
dcheng3d580cf2015-12-15 05:31:52 +09001039
dcheng11c9cca2016-01-22 04:37:55 +09001040TYPED_TEST(BindMoveOnlyTypeTest, UnboundForwarding) {
1041 int deletes = 0;
1042 TypeParam ptr(new DeleteCounter(&deletes));
dcheng3d580cf2015-12-15 05:31:52 +09001043 // Test unbound argument forwarding.
dcheng11c9cca2016-01-22 04:37:55 +09001044 Callback<TypeParam(TypeParam)> cb_unbound = Bind(&PassThru<TypeParam>);
dcheng3d580cf2015-12-15 05:31:52 +09001045 cb_unbound.Run(std::move(ptr));
dcheng11c9cca2016-01-22 04:37:55 +09001046 EXPECT_EQ(1, deletes);
dcheng3d580cf2015-12-15 05:31:52 +09001047}
1048
dchengcc8e4d82016-04-05 06:25:51 +09001049void VerifyVector(const std::vector<std::unique_ptr<int>>& v) {
dchengb61e1f92016-02-02 13:09:33 +09001050 ASSERT_EQ(1u, v.size());
1051 EXPECT_EQ(12345, *v[0]);
1052}
1053
dchengcc8e4d82016-04-05 06:25:51 +09001054std::vector<std::unique_ptr<int>> AcceptAndReturnMoveOnlyVector(
1055 std::vector<std::unique_ptr<int>> v) {
dchengb61e1f92016-02-02 13:09:33 +09001056 VerifyVector(v);
1057 return v;
1058}
1059
1060// Test that a vector containing move-only types can be used with Callback.
1061TEST_F(BindTest, BindMoveOnlyVector) {
dchengcc8e4d82016-04-05 06:25:51 +09001062 using MoveOnlyVector = std::vector<std::unique_ptr<int>>;
dchengb61e1f92016-02-02 13:09:33 +09001063
1064 MoveOnlyVector v;
dchengcc8e4d82016-04-05 06:25:51 +09001065 v.push_back(WrapUnique(new int(12345)));
dchengb61e1f92016-02-02 13:09:33 +09001066
1067 // Early binding should work:
1068 base::Callback<MoveOnlyVector()> bound_cb =
1069 base::Bind(&AcceptAndReturnMoveOnlyVector, Passed(&v));
1070 MoveOnlyVector intermediate_result = bound_cb.Run();
1071 VerifyVector(intermediate_result);
1072
1073 // As should passing it as an argument to Run():
1074 base::Callback<MoveOnlyVector(MoveOnlyVector)> unbound_cb =
1075 base::Bind(&AcceptAndReturnMoveOnlyVector);
1076 MoveOnlyVector final_result = unbound_cb.Run(std::move(intermediate_result));
1077 VerifyVector(final_result);
1078}
1079
tzik14cb77d2016-02-15 20:54:30 +09001080// Argument copy-constructor usage for non-reference copy-only parameters.
ajwong@chromium.orge2cca632011-02-15 10:27:38 +09001081// - Bound arguments are only copied once.
1082// - Forwarded arguments are only copied once.
ajwong@chromium.orgf66a7db2011-12-23 06:12:58 +09001083// - Forwarded arguments with coercions are only copied twice (once for the
1084// coercion, and one for the final dispatch).
ajwong@chromium.orge2cca632011-02-15 10:27:38 +09001085TEST_F(BindTest, ArgumentCopies) {
1086 int copies = 0;
1087 int assigns = 0;
1088
1089 CopyCounter counter(&copies, &assigns);
tzik14cb77d2016-02-15 20:54:30 +09001090 Bind(&VoidPolymorphic<CopyCounter>::Run, counter);
1091 EXPECT_EQ(1, copies);
ajwong@chromium.orge2cca632011-02-15 10:27:38 +09001092 EXPECT_EQ(0, assigns);
1093
1094 copies = 0;
1095 assigns = 0;
tzik14cb77d2016-02-15 20:54:30 +09001096 Bind(&VoidPolymorphic<CopyCounter>::Run, CopyCounter(&copies, &assigns));
1097 EXPECT_EQ(1, copies);
ajwong@chromium.orge2cca632011-02-15 10:27:38 +09001098 EXPECT_EQ(0, assigns);
1099
1100 copies = 0;
1101 assigns = 0;
tzik14cb77d2016-02-15 20:54:30 +09001102 Bind(&VoidPolymorphic<CopyCounter>::Run).Run(counter);
tzik0d4bab22016-03-09 14:46:05 +09001103 EXPECT_EQ(2, copies);
ajwong@chromium.orge2cca632011-02-15 10:27:38 +09001104 EXPECT_EQ(0, assigns);
tzik14cb77d2016-02-15 20:54:30 +09001105
1106 copies = 0;
1107 assigns = 0;
1108 Bind(&VoidPolymorphic<CopyCounter>::Run).Run(CopyCounter(&copies, &assigns));
1109 EXPECT_EQ(1, copies);
1110 EXPECT_EQ(0, assigns);
1111
1112 copies = 0;
1113 assigns = 0;
1114 DerivedCopyMoveCounter derived(&copies, &assigns, nullptr, nullptr);
1115 Bind(&VoidPolymorphic<CopyCounter>::Run).Run(CopyCounter(derived));
1116 EXPECT_EQ(2, copies);
1117 EXPECT_EQ(0, assigns);
1118
1119 copies = 0;
1120 assigns = 0;
1121 Bind(&VoidPolymorphic<CopyCounter>::Run)
1122 .Run(CopyCounter(
1123 DerivedCopyMoveCounter(&copies, &assigns, nullptr, nullptr)));
1124 EXPECT_EQ(2, copies);
1125 EXPECT_EQ(0, assigns);
1126}
1127
1128// Argument move-constructor usage for move-only parameters.
1129// - Bound arguments passed by move are not copied.
1130TEST_F(BindTest, ArgumentMoves) {
1131 int move_constructs = 0;
1132 int move_assigns = 0;
1133
1134 Bind(&VoidPolymorphic<const MoveCounter&>::Run,
1135 MoveCounter(&move_constructs, &move_assigns));
1136 EXPECT_EQ(1, move_constructs);
1137 EXPECT_EQ(0, move_assigns);
1138
1139 // TODO(tzik): Support binding move-only type into a non-reference parameter
1140 // of a variant of Callback.
1141
tzik0d4bab22016-03-09 14:46:05 +09001142 move_constructs = 0;
1143 move_assigns = 0;
1144 Bind(&VoidPolymorphic<MoveCounter>::Run)
1145 .Run(MoveCounter(&move_constructs, &move_assigns));
1146 EXPECT_EQ(1, move_constructs);
1147 EXPECT_EQ(0, move_assigns);
1148
1149 move_constructs = 0;
1150 move_assigns = 0;
1151 Bind(&VoidPolymorphic<MoveCounter>::Run)
1152 .Run(MoveCounter(DerivedCopyMoveCounter(
1153 nullptr, nullptr, &move_constructs, &move_assigns)));
1154 EXPECT_EQ(2, move_constructs);
1155 EXPECT_EQ(0, move_assigns);
tzik14cb77d2016-02-15 20:54:30 +09001156}
1157
1158// Argument constructor usage for non-reference movable-copyable
1159// parameters.
1160// - Bound arguments passed by move are not copied.
1161// - Forwarded arguments are only copied once.
1162// - Forwarded arguments with coercions are only copied once and moved once.
1163TEST_F(BindTest, ArgumentCopiesAndMoves) {
1164 int copies = 0;
1165 int assigns = 0;
1166 int move_constructs = 0;
1167 int move_assigns = 0;
1168
1169 CopyMoveCounter counter(&copies, &assigns, &move_constructs, &move_assigns);
1170 Bind(&VoidPolymorphic<CopyMoveCounter>::Run, counter);
1171 EXPECT_EQ(1, copies);
1172 EXPECT_EQ(0, assigns);
1173 EXPECT_EQ(0, move_constructs);
1174 EXPECT_EQ(0, move_assigns);
1175
1176 copies = 0;
1177 assigns = 0;
1178 move_constructs = 0;
1179 move_assigns = 0;
1180 Bind(&VoidPolymorphic<CopyMoveCounter>::Run,
1181 CopyMoveCounter(&copies, &assigns, &move_constructs, &move_assigns));
1182 EXPECT_EQ(0, copies);
1183 EXPECT_EQ(0, assigns);
1184 EXPECT_EQ(1, move_constructs);
1185 EXPECT_EQ(0, move_assigns);
1186
1187 copies = 0;
1188 assigns = 0;
1189 move_constructs = 0;
1190 move_assigns = 0;
1191 Bind(&VoidPolymorphic<CopyMoveCounter>::Run).Run(counter);
1192 EXPECT_EQ(1, copies);
1193 EXPECT_EQ(0, assigns);
tzik0d4bab22016-03-09 14:46:05 +09001194 EXPECT_EQ(1, move_constructs);
tzik14cb77d2016-02-15 20:54:30 +09001195 EXPECT_EQ(0, move_assigns);
1196
tzik14cb77d2016-02-15 20:54:30 +09001197 copies = 0;
1198 assigns = 0;
1199 move_constructs = 0;
1200 move_assigns = 0;
1201 Bind(&VoidPolymorphic<CopyMoveCounter>::Run)
1202 .Run(CopyMoveCounter(&copies, &assigns, &move_constructs, &move_assigns));
tzik0d4bab22016-03-09 14:46:05 +09001203 EXPECT_EQ(0, copies);
tzik14cb77d2016-02-15 20:54:30 +09001204 EXPECT_EQ(0, assigns);
tzik0d4bab22016-03-09 14:46:05 +09001205 EXPECT_EQ(1, move_constructs);
tzik14cb77d2016-02-15 20:54:30 +09001206 EXPECT_EQ(0, move_assigns);
1207
tzik14cb77d2016-02-15 20:54:30 +09001208 DerivedCopyMoveCounter derived_counter(&copies, &assigns, &move_constructs,
1209 &move_assigns);
1210 copies = 0;
1211 assigns = 0;
1212 move_constructs = 0;
1213 move_assigns = 0;
1214 Bind(&VoidPolymorphic<CopyMoveCounter>::Run)
1215 .Run(CopyMoveCounter(derived_counter));
tzik0d4bab22016-03-09 14:46:05 +09001216 EXPECT_EQ(1, copies);
tzik14cb77d2016-02-15 20:54:30 +09001217 EXPECT_EQ(0, assigns);
tzik0d4bab22016-03-09 14:46:05 +09001218 EXPECT_EQ(1, move_constructs);
tzik14cb77d2016-02-15 20:54:30 +09001219 EXPECT_EQ(0, move_assigns);
1220
tzik14cb77d2016-02-15 20:54:30 +09001221 copies = 0;
1222 assigns = 0;
1223 move_constructs = 0;
1224 move_assigns = 0;
1225 Bind(&VoidPolymorphic<CopyMoveCounter>::Run)
1226 .Run(CopyMoveCounter(DerivedCopyMoveCounter(
1227 &copies, &assigns, &move_constructs, &move_assigns)));
tzik0d4bab22016-03-09 14:46:05 +09001228 EXPECT_EQ(0, copies);
tzik14cb77d2016-02-15 20:54:30 +09001229 EXPECT_EQ(0, assigns);
tzik0d4bab22016-03-09 14:46:05 +09001230 EXPECT_EQ(2, move_constructs);
tzik14cb77d2016-02-15 20:54:30 +09001231 EXPECT_EQ(0, move_assigns);
ajwong@chromium.orge2cca632011-02-15 10:27:38 +09001232}
1233
tzik31d3fae2016-07-08 18:42:38 +09001234TEST_F(BindTest, CapturelessLambda) {
1235 EXPECT_FALSE(internal::IsConvertibleToRunType<void>::value);
1236 EXPECT_FALSE(internal::IsConvertibleToRunType<int>::value);
1237 EXPECT_FALSE(internal::IsConvertibleToRunType<void(*)()>::value);
1238 EXPECT_FALSE(internal::IsConvertibleToRunType<void(NoRef::*)()>::value);
1239
1240 auto f = []() {};
1241 EXPECT_TRUE(internal::IsConvertibleToRunType<decltype(f)>::value);
1242
1243 int i = 0;
krasin44a8a932017-01-19 04:29:33 +09001244 auto g = [i]() { (void)i; };
tzik31d3fae2016-07-08 18:42:38 +09001245 EXPECT_FALSE(internal::IsConvertibleToRunType<decltype(g)>::value);
1246
1247 auto h = [](int, double) { return 'k'; };
1248 EXPECT_TRUE((std::is_same<
1249 char(int, double),
1250 internal::ExtractCallableRunType<decltype(h)>>::value));
1251
1252 EXPECT_EQ(42, Bind([] { return 42; }).Run());
1253 EXPECT_EQ(42, Bind([](int i) { return i * 7; }, 6).Run());
1254
1255 int x = 1;
1256 base::Callback<void(int)> cb =
1257 Bind([](int* x, int i) { *x *= i; }, Unretained(&x));
1258 cb.Run(6);
1259 EXPECT_EQ(6, x);
1260 cb.Run(7);
1261 EXPECT_EQ(42, x);
1262}
1263
tzik058872d2016-09-08 19:58:53 +09001264TEST_F(BindTest, Cancellation) {
dchengb78a84f2016-09-24 14:05:57 +09001265 EXPECT_CALL(no_ref_, VoidMethodWithIntArg(_)).Times(2);
tzik058872d2016-09-08 19:58:53 +09001266
1267 WeakPtrFactory<NoRef> weak_factory(&no_ref_);
tzik9c756522016-10-07 13:34:54 +09001268 RepeatingCallback<void(int)> cb =
1269 BindRepeating(&NoRef::VoidMethodWithIntArg, weak_factory.GetWeakPtr());
1270 RepeatingClosure cb2 = BindRepeating(cb, 8);
1271 OnceClosure cb3 = BindOnce(cb, 8);
1272
1273 OnceCallback<void(int)> cb4 =
1274 BindOnce(&NoRef::VoidMethodWithIntArg, weak_factory.GetWeakPtr());
1275 EXPECT_FALSE(cb4.IsCancelled());
1276
1277 OnceClosure cb5 = BindOnce(std::move(cb4), 8);
tzik058872d2016-09-08 19:58:53 +09001278
1279 EXPECT_FALSE(cb.IsCancelled());
1280 EXPECT_FALSE(cb2.IsCancelled());
tzik9c756522016-10-07 13:34:54 +09001281 EXPECT_FALSE(cb3.IsCancelled());
1282 EXPECT_FALSE(cb5.IsCancelled());
tzik058872d2016-09-08 19:58:53 +09001283
dchengb78a84f2016-09-24 14:05:57 +09001284 cb.Run(6);
tzik058872d2016-09-08 19:58:53 +09001285 cb2.Run();
1286
1287 weak_factory.InvalidateWeakPtrs();
1288
1289 EXPECT_TRUE(cb.IsCancelled());
1290 EXPECT_TRUE(cb2.IsCancelled());
tzik9c756522016-10-07 13:34:54 +09001291 EXPECT_TRUE(cb3.IsCancelled());
1292 EXPECT_TRUE(cb5.IsCancelled());
tzik058872d2016-09-08 19:58:53 +09001293
dchengb78a84f2016-09-24 14:05:57 +09001294 cb.Run(6);
tzik058872d2016-09-08 19:58:53 +09001295 cb2.Run();
tzik9c756522016-10-07 13:34:54 +09001296 std::move(cb3).Run();
1297 std::move(cb5).Run();
tzik058872d2016-09-08 19:58:53 +09001298}
1299
tzikc60a8122016-09-13 14:28:59 +09001300TEST_F(BindTest, OnceCallback) {
tzikc60a8122016-09-13 14:28:59 +09001301 // Check if Callback variants have declarations of conversions as expected.
1302 // Copy constructor and assignment of RepeatingCallback.
1303 static_assert(std::is_constructible<
1304 RepeatingClosure, const RepeatingClosure&>::value,
1305 "RepeatingClosure should be copyable.");
1306 static_assert(is_assignable<
1307 RepeatingClosure, const RepeatingClosure&>::value,
1308 "RepeatingClosure should be copy-assignable.");
1309
1310 // Move constructor and assignment of RepeatingCallback.
1311 static_assert(std::is_constructible<
1312 RepeatingClosure, RepeatingClosure&&>::value,
1313 "RepeatingClosure should be movable.");
1314 static_assert(is_assignable<
1315 RepeatingClosure, RepeatingClosure&&>::value,
1316 "RepeatingClosure should be move-assignable");
1317
1318 // Conversions from OnceCallback to RepeatingCallback.
1319 static_assert(!std::is_constructible<
1320 RepeatingClosure, const OnceClosure&>::value,
1321 "OnceClosure should not be convertible to RepeatingClosure.");
1322 static_assert(!is_assignable<
1323 RepeatingClosure, const OnceClosure&>::value,
1324 "OnceClosure should not be convertible to RepeatingClosure.");
1325
1326 // Destructive conversions from OnceCallback to RepeatingCallback.
1327 static_assert(!std::is_constructible<
1328 RepeatingClosure, OnceClosure&&>::value,
1329 "OnceClosure should not be convertible to RepeatingClosure.");
1330 static_assert(!is_assignable<
1331 RepeatingClosure, OnceClosure&&>::value,
1332 "OnceClosure should not be convertible to RepeatingClosure.");
1333
1334 // Copy constructor and assignment of OnceCallback.
1335 static_assert(!std::is_constructible<
1336 OnceClosure, const OnceClosure&>::value,
1337 "OnceClosure should not be copyable.");
1338 static_assert(!is_assignable<
1339 OnceClosure, const OnceClosure&>::value,
1340 "OnceClosure should not be copy-assignable");
1341
1342 // Move constructor and assignment of OnceCallback.
1343 static_assert(std::is_constructible<
1344 OnceClosure, OnceClosure&&>::value,
1345 "OnceClosure should be movable.");
1346 static_assert(is_assignable<
1347 OnceClosure, OnceClosure&&>::value,
1348 "OnceClosure should be move-assignable.");
1349
1350 // Conversions from RepeatingCallback to OnceCallback.
1351 static_assert(std::is_constructible<
1352 OnceClosure, const RepeatingClosure&>::value,
1353 "RepeatingClosure should be convertible to OnceClosure.");
1354 static_assert(is_assignable<
1355 OnceClosure, const RepeatingClosure&>::value,
1356 "RepeatingClosure should be convertible to OnceClosure.");
1357
1358 // Destructive conversions from RepeatingCallback to OnceCallback.
1359 static_assert(std::is_constructible<
1360 OnceClosure, RepeatingClosure&&>::value,
1361 "RepeatingClosure should be convertible to OnceClosure.");
1362 static_assert(is_assignable<
1363 OnceClosure, RepeatingClosure&&>::value,
1364 "RepeatingClosure should be covretible to OnceClosure.");
1365
1366 OnceClosure cb = BindOnce(&VoidPolymorphic<>::Run);
1367 std::move(cb).Run();
1368
1369 // RepeatingCallback should be convertible to OnceCallback.
1370 OnceClosure cb2 = BindRepeating(&VoidPolymorphic<>::Run);
1371 std::move(cb2).Run();
1372
1373 RepeatingClosure cb3 = BindRepeating(&VoidPolymorphic<>::Run);
1374 cb = cb3;
1375 std::move(cb).Run();
1376
1377 cb = std::move(cb2);
1378
1379 OnceCallback<void(int)> cb4 = BindOnce(
1380 &VoidPolymorphic<std::unique_ptr<int>, int>::Run, MakeUnique<int>(0));
1381 BindOnce(std::move(cb4), 1).Run();
1382}
1383
ajwong@chromium.orge2cca632011-02-15 10:27:38 +09001384// Callback construction and assignment tests.
1385// - Construction from an InvokerStorageHolder should not cause ref/deref.
1386// - Assignment from other callback should only cause one ref
1387//
1388// TODO(ajwong): Is there actually a way to test this?
1389
ajwong@chromium.orgcb175342011-02-27 10:25:59 +09001390#if defined(OS_WIN)
1391int __fastcall FastCallFunc(int n) {
1392 return n;
1393}
1394
1395int __stdcall StdCallFunc(int n) {
1396 return n;
1397}
1398
1399// Windows specific calling convention support.
1400// - Can bind a __fastcall function.
1401// - Can bind a __stdcall function.
1402TEST_F(BindTest, WindowsCallingConventions) {
tzik260fab52015-12-19 18:18:46 +09001403 Callback<int()> fastcall_cb = Bind(&FastCallFunc, 1);
ajwong@chromium.orgcb175342011-02-27 10:25:59 +09001404 EXPECT_EQ(1, fastcall_cb.Run());
1405
tzik260fab52015-12-19 18:18:46 +09001406 Callback<int()> stdcall_cb = Bind(&StdCallFunc, 2);
ajwong@chromium.orgcb175342011-02-27 10:25:59 +09001407 EXPECT_EQ(2, stdcall_cb.Run());
1408}
1409#endif
1410
hashimoto@chromium.orgbc14c572012-11-20 17:28:14 +09001411// Test null callbacks cause a DCHECK.
1412TEST(BindDeathTest, NullCallback) {
1413 base::Callback<void(int)> null_cb;
1414 ASSERT_TRUE(null_cb.is_null());
gab73fdcc32016-08-05 12:25:40 +09001415 EXPECT_DCHECK_DEATH(base::Bind(null_cb, 42));
hashimoto@chromium.orgbc14c572012-11-20 17:28:14 +09001416}
1417
ajwong@chromium.orge2cca632011-02-15 10:27:38 +09001418} // namespace
1419} // namespace base