blob: 615ad330a92957acbe53e9797010c607667366fb [file] [log] [blame]
[email protected]44106182012-04-06 03:53:021// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]b38d3572011-02-15 01:27:382// 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
dcheng69f2a042015-12-14 20:31:527#include <memory>
8#include <utility>
dcheng53b4cea2016-02-02 04:09:339#include <vector>
dcheng69f2a042015-12-14 20:31:5210
[email protected]b38d3572011-02-15 01:27:3811#include "base/callback.h"
avi9b6f42932015-12-26 22:15:1412#include "base/macros.h"
dcheng093de9b2016-04-04 21:25:5113#include "base/memory/ptr_util.h"
[email protected]206a2ae82011-12-22 21:12:5814#include "base/memory/ref_counted.h"
[email protected]206a2ae82011-12-22 21:12:5815#include "base/memory/weak_ptr.h"
avi9b6f42932015-12-26 22:15:1416#include "build/build_config.h"
[email protected]b38d3572011-02-15 01:27:3817#include "testing/gmock/include/gmock/gmock.h"
18#include "testing/gtest/include/gtest/gtest.h"
19
20using ::testing::Mock;
21using ::testing::Return;
22using ::testing::StrictMock;
23
24namespace base {
25namespace {
26
[email protected]8217d4542011-10-01 06:31:4127class IncompleteType;
28
[email protected]b38d3572011-02-15 01:27:3829class NoRef {
30 public:
31 NoRef() {}
32
tzik3bc7779b2015-12-19 09:18:4633 MOCK_METHOD0(VoidMethod0, void());
34 MOCK_CONST_METHOD0(VoidConstMethod0, void());
[email protected]b38d3572011-02-15 01:27:3835
tzik3bc7779b2015-12-19 09:18:4636 MOCK_METHOD0(IntMethod0, int());
37 MOCK_CONST_METHOD0(IntConstMethod0, int());
[email protected]b38d3572011-02-15 01:27:3838
39 private:
40 // Particularly important in this test to ensure no copies are made.
41 DISALLOW_COPY_AND_ASSIGN(NoRef);
42};
43
44class HasRef : public NoRef {
45 public:
46 HasRef() {}
47
tzik3bc7779b2015-12-19 09:18:4648 MOCK_CONST_METHOD0(AddRef, void());
49 MOCK_CONST_METHOD0(Release, bool());
[email protected]b38d3572011-02-15 01:27:3850
51 private:
52 // Particularly important in this test to ensure no copies are made.
53 DISALLOW_COPY_AND_ASSIGN(HasRef);
54};
55
[email protected]690bda882011-04-13 22:40:4656class HasRefPrivateDtor : public HasRef {
57 private:
58 ~HasRefPrivateDtor() {}
59};
60
[email protected]b38d3572011-02-15 01:27:3861static const int kParentValue = 1;
62static const int kChildValue = 2;
63
64class Parent {
65 public:
tzik3bc7779b2015-12-19 09:18:4666 void AddRef() const {}
67 void Release() const {}
[email protected]b38d3572011-02-15 01:27:3868 virtual void VirtualSet() { value = kParentValue; }
69 void NonVirtualSet() { value = kParentValue; }
70 int value;
71};
72
73class Child : public Parent {
74 public:
dcheng56488182014-10-21 10:54:5175 void VirtualSet() override { value = kChildValue; }
[email protected]b38d3572011-02-15 01:27:3876 void NonVirtualSet() { value = kChildValue; }
77};
78
79class NoRefParent {
80 public:
81 virtual void VirtualSet() { value = kParentValue; }
82 void NonVirtualSet() { value = kParentValue; }
83 int value;
84};
85
86class NoRefChild : public NoRefParent {
dcheng56488182014-10-21 10:54:5187 void VirtualSet() override { value = kChildValue; }
[email protected]b38d3572011-02-15 01:27:3888 void NonVirtualSet() { value = kChildValue; }
89};
90
tzik52dcd672016-02-15 11:54:3091// Used for probing the number of copies and moves that occur if a type must be
92// coerced during argument forwarding in the Run() methods.
93struct DerivedCopyMoveCounter {
94 DerivedCopyMoveCounter(int* copies,
95 int* assigns,
96 int* move_constructs,
97 int* move_assigns)
98 : copies_(copies),
99 assigns_(assigns),
100 move_constructs_(move_constructs),
101 move_assigns_(move_assigns) {}
[email protected]b38d3572011-02-15 01:27:38102 int* copies_;
103 int* assigns_;
tzik52dcd672016-02-15 11:54:30104 int* move_constructs_;
105 int* move_assigns_;
[email protected]b38d3572011-02-15 01:27:38106};
107
tzik52dcd672016-02-15 11:54:30108// Used for probing the number of copies and moves in an argument.
109class CopyMoveCounter {
[email protected]b38d3572011-02-15 01:27:38110 public:
tzik52dcd672016-02-15 11:54:30111 CopyMoveCounter(int* copies,
112 int* assigns,
113 int* move_constructs,
114 int* move_assigns)
115 : copies_(copies),
116 assigns_(assigns),
117 move_constructs_(move_constructs),
118 move_assigns_(move_assigns) {}
119
120 CopyMoveCounter(const CopyMoveCounter& other)
121 : copies_(other.copies_),
122 assigns_(other.assigns_),
123 move_constructs_(other.move_constructs_),
124 move_assigns_(other.move_assigns_) {
125 (*copies_)++;
[email protected]b38d3572011-02-15 01:27:38126 }
127
tzik52dcd672016-02-15 11:54:30128 CopyMoveCounter(CopyMoveCounter&& other)
[email protected]b38d3572011-02-15 01:27:38129 : copies_(other.copies_),
tzik52dcd672016-02-15 11:54:30130 assigns_(other.assigns_),
131 move_constructs_(other.move_constructs_),
132 move_assigns_(other.move_assigns_) {
133 (*move_constructs_)++;
[email protected]b38d3572011-02-15 01:27:38134 }
135
[email protected]206a2ae82011-12-22 21:12:58136 // Probing for copies from coercion.
tzik52dcd672016-02-15 11:54:30137 explicit CopyMoveCounter(const DerivedCopyMoveCounter& other)
[email protected]b38d3572011-02-15 01:27:38138 : copies_(other.copies_),
tzik52dcd672016-02-15 11:54:30139 assigns_(other.assigns_),
140 move_constructs_(other.move_constructs_),
141 move_assigns_(other.move_assigns_) {
[email protected]b38d3572011-02-15 01:27:38142 (*copies_)++;
143 }
144
tzik52dcd672016-02-15 11:54:30145 // Probing for moves from coercion.
146 explicit CopyMoveCounter(DerivedCopyMoveCounter&& other)
147 : copies_(other.copies_),
148 assigns_(other.assigns_),
149 move_constructs_(other.move_constructs_),
150 move_assigns_(other.move_assigns_) {
151 (*move_constructs_)++;
152 }
153
154 const CopyMoveCounter& operator=(const CopyMoveCounter& rhs) {
[email protected]b38d3572011-02-15 01:27:38155 copies_ = rhs.copies_;
156 assigns_ = rhs.assigns_;
tzik52dcd672016-02-15 11:54:30157 move_constructs_ = rhs.move_constructs_;
158 move_assigns_ = rhs.move_assigns_;
[email protected]b38d3572011-02-15 01:27:38159
tzik52dcd672016-02-15 11:54:30160 (*assigns_)++;
161
162 return *this;
163 }
164
165 const CopyMoveCounter& operator=(CopyMoveCounter&& rhs) {
166 copies_ = rhs.copies_;
167 assigns_ = rhs.assigns_;
168 move_constructs_ = rhs.move_constructs_;
169 move_assigns_ = rhs.move_assigns_;
170
171 (*move_assigns_)++;
[email protected]b38d3572011-02-15 01:27:38172
173 return *this;
174 }
175
176 int copies() const {
177 return *copies_;
178 }
179
[email protected]b38d3572011-02-15 01:27:38180 private:
181 int* copies_;
182 int* assigns_;
tzik52dcd672016-02-15 11:54:30183 int* move_constructs_;
184 int* move_assigns_;
185};
186
187// Used for probing the number of copies in an argument. The instance is a
188// copyable and non-movable type.
189class CopyCounter {
190 public:
191 CopyCounter(int* copies, int* assigns)
192 : counter_(copies, assigns, nullptr, nullptr) {}
193 CopyCounter(const CopyCounter& other) : counter_(other.counter_) {}
194 CopyCounter& operator=(const CopyCounter& other) {
195 counter_ = other.counter_;
196 return *this;
197 }
198
199 explicit CopyCounter(const DerivedCopyMoveCounter& other) : counter_(other) {}
200
201 int copies() const { return counter_.copies(); }
202
203 private:
204 CopyMoveCounter counter_;
205};
206
207// Used for probing the number of moves in an argument. The instance is a
208// non-copyable and movable type.
209class MoveCounter {
210 public:
211 MoveCounter(int* move_constructs, int* move_assigns)
212 : counter_(nullptr, nullptr, move_constructs, move_assigns) {}
213 MoveCounter(MoveCounter&& other) : counter_(std::move(other.counter_)) {}
214 MoveCounter& operator=(MoveCounter&& other) {
215 counter_ = std::move(other.counter_);
216 return *this;
217 }
218
219 explicit MoveCounter(DerivedCopyMoveCounter&& other)
220 : counter_(std::move(other)) {}
221
222 private:
223 CopyMoveCounter counter_;
[email protected]b38d3572011-02-15 01:27:38224};
225
[email protected]08aa4552011-10-15 00:34:42226class DeleteCounter {
227 public:
228 explicit DeleteCounter(int* deletes)
229 : deletes_(deletes) {
230 }
231
232 ~DeleteCounter() {
233 (*deletes_)++;
234 }
235
236 void VoidMethod0() {}
237
238 private:
239 int* deletes_;
240};
241
[email protected]206a2ae82011-12-22 21:12:58242template <typename T>
243T PassThru(T scoper) {
dcheng69f2a042015-12-14 20:31:52244 return scoper;
[email protected]206a2ae82011-12-22 21:12:58245}
246
[email protected]b38d3572011-02-15 01:27:38247// Some test functions that we can Bind to.
248template <typename T>
249T PolymorphicIdentity(T t) {
250 return t;
251}
252
tzik7fe3a682015-12-18 02:23:26253template <typename... Ts>
254struct VoidPolymorphic {
255 static void Run(Ts... t) {}
256};
[email protected]b38d3572011-02-15 01:27:38257
258int Identity(int n) {
259 return n;
260}
261
262int ArrayGet(const int array[], int n) {
263 return array[n];
264}
265
266int Sum(int a, int b, int c, int d, int e, int f) {
267 return a + b + c + d + e + f;
268}
269
270const char* CStringIdentity(const char* s) {
271 return s;
272}
273
tzik52dcd672016-02-15 11:54:30274int GetCopies(const CopyMoveCounter& counter) {
[email protected]b38d3572011-02-15 01:27:38275 return counter.copies();
276}
277
278int UnwrapNoRefParent(NoRefParent p) {
279 return p.value;
280}
281
282int UnwrapNoRefParentPtr(NoRefParent* p) {
283 return p->value;
284}
285
286int UnwrapNoRefParentConstRef(const NoRefParent& p) {
287 return p.value;
288}
289
[email protected]c18b1052011-03-24 02:02:17290void RefArgSet(int &n) {
291 n = 2;
292}
293
[email protected]e24f8762011-12-20 00:10:04294void PtrArgSet(int *n) {
295 *n = 2;
296}
297
[email protected]93540582011-05-16 22:35:14298int FunctionWithWeakFirstParam(WeakPtr<NoRef> o, int n) {
299 return n;
300}
301
[email protected]edd2f1b2013-06-22 20:32:50302int FunctionWithScopedRefptrFirstParam(const scoped_refptr<HasRef>& o, int n) {
303 return n;
304}
305
[email protected]e24f8762011-12-20 00:10:04306void TakesACallback(const Closure& callback) {
307 callback.Run();
308}
309
[email protected]b38d3572011-02-15 01:27:38310class BindTest : public ::testing::Test {
311 public:
312 BindTest() {
313 const_has_ref_ptr_ = &has_ref_;
314 const_no_ref_ptr_ = &no_ref_;
315 static_func_mock_ptr = &static_func_mock_;
316 }
317
318 virtual ~BindTest() {
319 }
320
tzik3bc7779b2015-12-19 09:18:46321 static void VoidFunc0() {
[email protected]b38d3572011-02-15 01:27:38322 static_func_mock_ptr->VoidMethod0();
323 }
324
tzik3bc7779b2015-12-19 09:18:46325 static int IntFunc0() { return static_func_mock_ptr->IntMethod0(); }
[email protected]b38d3572011-02-15 01:27:38326
327 protected:
328 StrictMock<NoRef> no_ref_;
329 StrictMock<HasRef> has_ref_;
330 const HasRef* const_has_ref_ptr_;
331 const NoRef* const_no_ref_ptr_;
332 StrictMock<NoRef> static_func_mock_;
333
334 // Used by the static functions to perform expectations.
335 static StrictMock<NoRef>* static_func_mock_ptr;
336
337 private:
338 DISALLOW_COPY_AND_ASSIGN(BindTest);
339};
340
341StrictMock<NoRef>* BindTest::static_func_mock_ptr;
342
[email protected]b38d3572011-02-15 01:27:38343// Sanity check that we can instantiate a callback for each arity.
344TEST_F(BindTest, ArityTest) {
tzik3bc7779b2015-12-19 09:18:46345 Callback<int()> c0 = Bind(&Sum, 32, 16, 8, 4, 2, 1);
[email protected]b38d3572011-02-15 01:27:38346 EXPECT_EQ(63, c0.Run());
347
348 Callback<int(int)> c1 = Bind(&Sum, 32, 16, 8, 4, 2);
349 EXPECT_EQ(75, c1.Run(13));
350
351 Callback<int(int,int)> c2 = Bind(&Sum, 32, 16, 8, 4);
352 EXPECT_EQ(85, c2.Run(13, 12));
353
354 Callback<int(int,int,int)> c3 = Bind(&Sum, 32, 16, 8);
355 EXPECT_EQ(92, c3.Run(13, 12, 11));
356
357 Callback<int(int,int,int,int)> c4 = Bind(&Sum, 32, 16);
358 EXPECT_EQ(94, c4.Run(13, 12, 11, 10));
359
360 Callback<int(int,int,int,int,int)> c5 = Bind(&Sum, 32);
361 EXPECT_EQ(87, c5.Run(13, 12, 11, 10, 9));
362
363 Callback<int(int,int,int,int,int,int)> c6 = Bind(&Sum);
364 EXPECT_EQ(69, c6.Run(13, 12, 11, 10, 9, 14));
365}
366
[email protected]7296f2762011-11-21 19:23:44367// Test the Currying ability of the Callback system.
368TEST_F(BindTest, CurryingTest) {
369 Callback<int(int,int,int,int,int,int)> c6 = Bind(&Sum);
370 EXPECT_EQ(69, c6.Run(13, 12, 11, 10, 9, 14));
[email protected]cea20fe42011-09-30 09:09:34371
[email protected]7296f2762011-11-21 19:23:44372 Callback<int(int,int,int,int,int)> c5 = Bind(c6, 32);
373 EXPECT_EQ(87, c5.Run(13, 12, 11, 10, 9));
[email protected]cea20fe42011-09-30 09:09:34374
[email protected]7296f2762011-11-21 19:23:44375 Callback<int(int,int,int,int)> c4 = Bind(c5, 16);
376 EXPECT_EQ(94, c4.Run(13, 12, 11, 10));
[email protected]cea20fe42011-09-30 09:09:34377
[email protected]7296f2762011-11-21 19:23:44378 Callback<int(int,int,int)> c3 = Bind(c4, 8);
379 EXPECT_EQ(92, c3.Run(13, 12, 11));
[email protected]cea20fe42011-09-30 09:09:34380
[email protected]7296f2762011-11-21 19:23:44381 Callback<int(int,int)> c2 = Bind(c3, 4);
382 EXPECT_EQ(85, c2.Run(13, 12));
[email protected]cea20fe42011-09-30 09:09:34383
[email protected]7296f2762011-11-21 19:23:44384 Callback<int(int)> c1 = Bind(c2, 2);
385 EXPECT_EQ(75, c1.Run(13));
386
tzik3bc7779b2015-12-19 09:18:46387 Callback<int()> c0 = Bind(c1, 1);
[email protected]7296f2762011-11-21 19:23:44388 EXPECT_EQ(63, c0.Run());
[email protected]cea20fe42011-09-30 09:09:34389}
390
[email protected]e24f8762011-12-20 00:10:04391// Test that currying the rvalue result of another Bind() works correctly.
392// - rvalue should be usable as argument to Bind().
393// - multiple runs of resulting Callback remain valid.
394TEST_F(BindTest, CurryingRvalueResultOfBind) {
395 int n = 0;
396 Closure cb = base::Bind(&TakesACallback, base::Bind(&PtrArgSet, &n));
397
398 // If we implement Bind() such that the return value has auto_ptr-like
399 // semantics, the second call here will fail because ownership of
400 // the internal BindState<> would have been transfered to a *temporary*
401 // constructon of a Callback object on the first call.
402 cb.Run();
403 EXPECT_EQ(2, n);
404
405 n = 0;
406 cb.Run();
407 EXPECT_EQ(2, n);
408}
409
[email protected]b38d3572011-02-15 01:27:38410// Function type support.
411// - Normal function.
[email protected]81814bce2011-09-10 03:03:00412// - Normal function bound with non-refcounted first argument.
[email protected]b38d3572011-02-15 01:27:38413// - Method bound to non-const object.
[email protected]7a15d1172011-10-07 00:25:29414// - Method bound to scoped_refptr.
[email protected]b38d3572011-02-15 01:27:38415// - Const method bound to non-const object.
416// - Const method bound to const object.
417// - Derived classes can be used with pointers to non-virtual base functions.
418// - Derived classes can be used with pointers to virtual base functions (and
419// preserve virtual dispatch).
420TEST_F(BindTest, FunctionTypeSupport) {
421 EXPECT_CALL(static_func_mock_, VoidMethod0());
tzik9ca302192016-02-11 10:24:45422 EXPECT_CALL(has_ref_, AddRef()).Times(4);
423 EXPECT_CALL(has_ref_, Release()).Times(4);
[email protected]7a15d1172011-10-07 00:25:29424 EXPECT_CALL(has_ref_, VoidMethod0()).Times(2);
[email protected]b38d3572011-02-15 01:27:38425 EXPECT_CALL(has_ref_, VoidConstMethod0()).Times(2);
426
427 Closure normal_cb = Bind(&VoidFunc0);
tzik3bc7779b2015-12-19 09:18:46428 Callback<NoRef*()> normal_non_refcounted_cb =
[email protected]81814bce2011-09-10 03:03:00429 Bind(&PolymorphicIdentity<NoRef*>, &no_ref_);
430 normal_cb.Run();
431 EXPECT_EQ(&no_ref_, normal_non_refcounted_cb.Run());
432
[email protected]b38d3572011-02-15 01:27:38433 Closure method_cb = Bind(&HasRef::VoidMethod0, &has_ref_);
[email protected]7a15d1172011-10-07 00:25:29434 Closure method_refptr_cb = Bind(&HasRef::VoidMethod0,
435 make_scoped_refptr(&has_ref_));
[email protected]b38d3572011-02-15 01:27:38436 Closure const_method_nonconst_obj_cb = Bind(&HasRef::VoidConstMethod0,
437 &has_ref_);
438 Closure const_method_const_obj_cb = Bind(&HasRef::VoidConstMethod0,
439 const_has_ref_ptr_);
[email protected]b38d3572011-02-15 01:27:38440 method_cb.Run();
[email protected]7a15d1172011-10-07 00:25:29441 method_refptr_cb.Run();
[email protected]b38d3572011-02-15 01:27:38442 const_method_nonconst_obj_cb.Run();
443 const_method_const_obj_cb.Run();
444
445 Child child;
446 child.value = 0;
447 Closure virtual_set_cb = Bind(&Parent::VirtualSet, &child);
448 virtual_set_cb.Run();
449 EXPECT_EQ(kChildValue, child.value);
450
451 child.value = 0;
452 Closure non_virtual_set_cb = Bind(&Parent::NonVirtualSet, &child);
453 non_virtual_set_cb.Run();
454 EXPECT_EQ(kParentValue, child.value);
455}
456
457// Return value support.
458// - Function with return value.
459// - Method with return value.
460// - Const method with return value.
461TEST_F(BindTest, ReturnValues) {
462 EXPECT_CALL(static_func_mock_, IntMethod0()).WillOnce(Return(1337));
463 EXPECT_CALL(has_ref_, AddRef()).Times(3);
464 EXPECT_CALL(has_ref_, Release()).Times(3);
465 EXPECT_CALL(has_ref_, IntMethod0()).WillOnce(Return(31337));
466 EXPECT_CALL(has_ref_, IntConstMethod0())
467 .WillOnce(Return(41337))
468 .WillOnce(Return(51337));
469
tzik3bc7779b2015-12-19 09:18:46470 Callback<int()> normal_cb = Bind(&IntFunc0);
471 Callback<int()> method_cb = Bind(&HasRef::IntMethod0, &has_ref_);
472 Callback<int()> const_method_nonconst_obj_cb =
[email protected]b38d3572011-02-15 01:27:38473 Bind(&HasRef::IntConstMethod0, &has_ref_);
tzik3bc7779b2015-12-19 09:18:46474 Callback<int()> const_method_const_obj_cb =
[email protected]b38d3572011-02-15 01:27:38475 Bind(&HasRef::IntConstMethod0, const_has_ref_ptr_);
476 EXPECT_EQ(1337, normal_cb.Run());
477 EXPECT_EQ(31337, method_cb.Run());
478 EXPECT_EQ(41337, const_method_nonconst_obj_cb.Run());
479 EXPECT_EQ(51337, const_method_const_obj_cb.Run());
480}
481
[email protected]7296f2762011-11-21 19:23:44482// IgnoreResult adapter test.
483// - Function with return value.
484// - Method with return value.
485// - Const Method with return.
486// - Method with return value bound to WeakPtr<>.
487// - Const Method with return bound to WeakPtr<>.
488TEST_F(BindTest, IgnoreResult) {
[email protected]e8bfc31d2011-09-28 00:26:37489 EXPECT_CALL(static_func_mock_, IntMethod0()).WillOnce(Return(1337));
[email protected]7296f2762011-11-21 19:23:44490 EXPECT_CALL(has_ref_, AddRef()).Times(2);
491 EXPECT_CALL(has_ref_, Release()).Times(2);
492 EXPECT_CALL(has_ref_, IntMethod0()).WillOnce(Return(10));
493 EXPECT_CALL(has_ref_, IntConstMethod0()).WillOnce(Return(11));
494 EXPECT_CALL(no_ref_, IntMethod0()).WillOnce(Return(12));
495 EXPECT_CALL(no_ref_, IntConstMethod0()).WillOnce(Return(13));
496
497 Closure normal_func_cb = Bind(IgnoreResult(&IntFunc0));
498 normal_func_cb.Run();
499
500 Closure non_void_method_cb =
501 Bind(IgnoreResult(&HasRef::IntMethod0), &has_ref_);
502 non_void_method_cb.Run();
503
504 Closure non_void_const_method_cb =
505 Bind(IgnoreResult(&HasRef::IntConstMethod0), &has_ref_);
506 non_void_const_method_cb.Run();
507
508 WeakPtrFactory<NoRef> weak_factory(&no_ref_);
509 WeakPtrFactory<const NoRef> const_weak_factory(const_no_ref_ptr_);
510
511 Closure non_void_weak_method_cb =
512 Bind(IgnoreResult(&NoRef::IntMethod0), weak_factory.GetWeakPtr());
513 non_void_weak_method_cb.Run();
514
515 Closure non_void_weak_const_method_cb =
516 Bind(IgnoreResult(&NoRef::IntConstMethod0), weak_factory.GetWeakPtr());
517 non_void_weak_const_method_cb.Run();
518
519 weak_factory.InvalidateWeakPtrs();
520 non_void_weak_const_method_cb.Run();
521 non_void_weak_method_cb.Run();
[email protected]e8bfc31d2011-09-28 00:26:37522}
523
[email protected]b38d3572011-02-15 01:27:38524// Argument binding tests.
525// - Argument binding to primitive.
526// - Argument binding to primitive pointer.
527// - Argument binding to a literal integer.
528// - Argument binding to a literal string.
529// - Argument binding with template function.
530// - Argument binding to an object.
[email protected]8217d4542011-10-01 06:31:41531// - Argument binding to pointer to incomplete type.
[email protected]b38d3572011-02-15 01:27:38532// - Argument gets type converted.
533// - Pointer argument gets converted.
534// - Const Reference forces conversion.
535TEST_F(BindTest, ArgumentBinding) {
536 int n = 2;
537
tzik3bc7779b2015-12-19 09:18:46538 Callback<int()> bind_primitive_cb = Bind(&Identity, n);
[email protected]b38d3572011-02-15 01:27:38539 EXPECT_EQ(n, bind_primitive_cb.Run());
540
tzik3bc7779b2015-12-19 09:18:46541 Callback<int*()> bind_primitive_pointer_cb =
[email protected]b38d3572011-02-15 01:27:38542 Bind(&PolymorphicIdentity<int*>, &n);
543 EXPECT_EQ(&n, bind_primitive_pointer_cb.Run());
544
tzik3bc7779b2015-12-19 09:18:46545 Callback<int()> bind_int_literal_cb = Bind(&Identity, 3);
[email protected]b38d3572011-02-15 01:27:38546 EXPECT_EQ(3, bind_int_literal_cb.Run());
547
tzik3bc7779b2015-12-19 09:18:46548 Callback<const char*()> bind_string_literal_cb =
[email protected]b38d3572011-02-15 01:27:38549 Bind(&CStringIdentity, "hi");
550 EXPECT_STREQ("hi", bind_string_literal_cb.Run());
551
tzik3bc7779b2015-12-19 09:18:46552 Callback<int()> bind_template_function_cb =
[email protected]b38d3572011-02-15 01:27:38553 Bind(&PolymorphicIdentity<int>, 4);
554 EXPECT_EQ(4, bind_template_function_cb.Run());
555
556 NoRefParent p;
557 p.value = 5;
tzik3bc7779b2015-12-19 09:18:46558 Callback<int()> bind_object_cb = Bind(&UnwrapNoRefParent, p);
[email protected]b38d3572011-02-15 01:27:38559 EXPECT_EQ(5, bind_object_cb.Run());
560
[email protected]8217d4542011-10-01 06:31:41561 IncompleteType* incomplete_ptr = reinterpret_cast<IncompleteType*>(123);
tzik3bc7779b2015-12-19 09:18:46562 Callback<IncompleteType*()> bind_incomplete_ptr_cb =
[email protected]8217d4542011-10-01 06:31:41563 Bind(&PolymorphicIdentity<IncompleteType*>, incomplete_ptr);
564 EXPECT_EQ(incomplete_ptr, bind_incomplete_ptr_cb.Run());
565
[email protected]b38d3572011-02-15 01:27:38566 NoRefChild c;
567 c.value = 6;
tzik3bc7779b2015-12-19 09:18:46568 Callback<int()> bind_promotes_cb = Bind(&UnwrapNoRefParent, c);
[email protected]b38d3572011-02-15 01:27:38569 EXPECT_EQ(6, bind_promotes_cb.Run());
570
571 c.value = 7;
tzik3bc7779b2015-12-19 09:18:46572 Callback<int()> bind_pointer_promotes_cb =
[email protected]b38d3572011-02-15 01:27:38573 Bind(&UnwrapNoRefParentPtr, &c);
574 EXPECT_EQ(7, bind_pointer_promotes_cb.Run());
575
576 c.value = 8;
tzik3bc7779b2015-12-19 09:18:46577 Callback<int()> bind_const_reference_promotes_cb =
[email protected]b38d3572011-02-15 01:27:38578 Bind(&UnwrapNoRefParentConstRef, c);
579 EXPECT_EQ(8, bind_const_reference_promotes_cb.Run());
580}
581
[email protected]c18b1052011-03-24 02:02:17582// Unbound argument type support tests.
583// - Unbound value.
584// - Unbound pointer.
585// - Unbound reference.
586// - Unbound const reference.
587// - Unbound unsized array.
588// - Unbound sized array.
589// - Unbound array-of-arrays.
590TEST_F(BindTest, UnboundArgumentTypeSupport) {
tzik7fe3a682015-12-18 02:23:26591 Callback<void(int)> unbound_value_cb = Bind(&VoidPolymorphic<int>::Run);
592 Callback<void(int*)> unbound_pointer_cb = Bind(&VoidPolymorphic<int*>::Run);
593 Callback<void(int&)> unbound_ref_cb = Bind(&VoidPolymorphic<int&>::Run);
[email protected]c18b1052011-03-24 02:02:17594 Callback<void(const int&)> unbound_const_ref_cb =
tzik7fe3a682015-12-18 02:23:26595 Bind(&VoidPolymorphic<const int&>::Run);
[email protected]c18b1052011-03-24 02:02:17596 Callback<void(int[])> unbound_unsized_array_cb =
tzik7fe3a682015-12-18 02:23:26597 Bind(&VoidPolymorphic<int[]>::Run);
[email protected]c18b1052011-03-24 02:02:17598 Callback<void(int[2])> unbound_sized_array_cb =
tzik7fe3a682015-12-18 02:23:26599 Bind(&VoidPolymorphic<int[2]>::Run);
[email protected]c18b1052011-03-24 02:02:17600 Callback<void(int[][2])> unbound_array_of_arrays_cb =
tzik7fe3a682015-12-18 02:23:26601 Bind(&VoidPolymorphic<int[][2]>::Run);
602
603 Callback<void(int&)> unbound_ref_with_bound_arg =
604 Bind(&VoidPolymorphic<int, int&>::Run, 1);
[email protected]c18b1052011-03-24 02:02:17605}
606
607// Function with unbound reference parameter.
[email protected]7296f2762011-11-21 19:23:44608// - Original parameter is modified by callback.
[email protected]c18b1052011-03-24 02:02:17609TEST_F(BindTest, UnboundReferenceSupport) {
610 int n = 0;
611 Callback<void(int&)> unbound_ref_cb = Bind(&RefArgSet);
612 unbound_ref_cb.Run(n);
613 EXPECT_EQ(2, n);
614}
615
[email protected]b38d3572011-02-15 01:27:38616// Functions that take reference parameters.
617// - Forced reference parameter type still stores a copy.
618// - Forced const reference parameter type still stores a copy.
619TEST_F(BindTest, ReferenceArgumentBinding) {
620 int n = 1;
621 int& ref_n = n;
622 const int& const_ref_n = n;
623
tzik3bc7779b2015-12-19 09:18:46624 Callback<int()> ref_copies_cb = Bind(&Identity, ref_n);
[email protected]b38d3572011-02-15 01:27:38625 EXPECT_EQ(n, ref_copies_cb.Run());
626 n++;
627 EXPECT_EQ(n - 1, ref_copies_cb.Run());
628
tzik3bc7779b2015-12-19 09:18:46629 Callback<int()> const_ref_copies_cb = Bind(&Identity, const_ref_n);
[email protected]b38d3572011-02-15 01:27:38630 EXPECT_EQ(n, const_ref_copies_cb.Run());
631 n++;
632 EXPECT_EQ(n - 1, const_ref_copies_cb.Run());
633}
634
635// Check that we can pass in arrays and have them be stored as a pointer.
636// - Array of values stores a pointer.
637// - Array of const values stores a pointer.
638TEST_F(BindTest, ArrayArgumentBinding) {
639 int array[4] = {1, 1, 1, 1};
640 const int (*const_array_ptr)[4] = &array;
641
tzik3bc7779b2015-12-19 09:18:46642 Callback<int()> array_cb = Bind(&ArrayGet, array, 1);
[email protected]b38d3572011-02-15 01:27:38643 EXPECT_EQ(1, array_cb.Run());
644
tzik3bc7779b2015-12-19 09:18:46645 Callback<int()> const_array_cb = Bind(&ArrayGet, *const_array_ptr, 1);
[email protected]b38d3572011-02-15 01:27:38646 EXPECT_EQ(1, const_array_cb.Run());
647
648 array[1] = 3;
649 EXPECT_EQ(3, array_cb.Run());
650 EXPECT_EQ(3, const_array_cb.Run());
651}
652
653// Verify SupportsAddRefAndRelease correctly introspects the class type for
654// AddRef() and Release().
[email protected]690bda882011-04-13 22:40:46655// - Class with AddRef() and Release()
656// - Class without AddRef() and Release()
657// - Derived Class with AddRef() and Release()
658// - Derived Class without AddRef() and Release()
659// - Derived Class with AddRef() and Release() and a private destructor.
[email protected]b38d3572011-02-15 01:27:38660TEST_F(BindTest, SupportsAddRefAndRelease) {
661 EXPECT_TRUE(internal::SupportsAddRefAndRelease<HasRef>::value);
662 EXPECT_FALSE(internal::SupportsAddRefAndRelease<NoRef>::value);
663
664 // StrictMock<T> is a derived class of T. So, we use StrictMock<HasRef> and
665 // StrictMock<NoRef> to test that SupportsAddRefAndRelease works over
666 // inheritance.
667 EXPECT_TRUE(internal::SupportsAddRefAndRelease<StrictMock<HasRef> >::value);
668 EXPECT_FALSE(internal::SupportsAddRefAndRelease<StrictMock<NoRef> >::value);
[email protected]690bda882011-04-13 22:40:46669
670 // This matters because the implementation creates a dummy class that
671 // inherits from the template type.
672 EXPECT_TRUE(internal::SupportsAddRefAndRelease<HasRefPrivateDtor>::value);
[email protected]b38d3572011-02-15 01:27:38673}
674
675// Unretained() wrapper support.
[email protected]93540582011-05-16 22:35:14676// - Method bound to Unretained() non-const object.
[email protected]b38d3572011-02-15 01:27:38677// - Const method bound to Unretained() non-const object.
678// - Const method bound to Unretained() const object.
679TEST_F(BindTest, Unretained) {
680 EXPECT_CALL(no_ref_, VoidMethod0());
681 EXPECT_CALL(no_ref_, VoidConstMethod0()).Times(2);
682
tzik3bc7779b2015-12-19 09:18:46683 Callback<void()> method_cb =
[email protected]b38d3572011-02-15 01:27:38684 Bind(&NoRef::VoidMethod0, Unretained(&no_ref_));
685 method_cb.Run();
686
tzik3bc7779b2015-12-19 09:18:46687 Callback<void()> const_method_cb =
[email protected]b38d3572011-02-15 01:27:38688 Bind(&NoRef::VoidConstMethod0, Unretained(&no_ref_));
689 const_method_cb.Run();
690
tzik3bc7779b2015-12-19 09:18:46691 Callback<void()> const_method_const_ptr_cb =
[email protected]b38d3572011-02-15 01:27:38692 Bind(&NoRef::VoidConstMethod0, Unretained(const_no_ref_ptr_));
693 const_method_const_ptr_cb.Run();
694}
695
[email protected]93540582011-05-16 22:35:14696// WeakPtr() support.
697// - Method bound to WeakPtr<> to non-const object.
698// - Const method bound to WeakPtr<> to non-const object.
699// - Const method bound to WeakPtr<> to const object.
700// - Normal Function with WeakPtr<> as P1 can have return type and is
701// not canceled.
702TEST_F(BindTest, WeakPtr) {
703 EXPECT_CALL(no_ref_, VoidMethod0());
704 EXPECT_CALL(no_ref_, VoidConstMethod0()).Times(2);
705
706 WeakPtrFactory<NoRef> weak_factory(&no_ref_);
707 WeakPtrFactory<const NoRef> const_weak_factory(const_no_ref_ptr_);
708
[email protected]7296f2762011-11-21 19:23:44709 Closure method_cb =
[email protected]93540582011-05-16 22:35:14710 Bind(&NoRef::VoidMethod0, weak_factory.GetWeakPtr());
711 method_cb.Run();
712
[email protected]7296f2762011-11-21 19:23:44713 Closure const_method_cb =
[email protected]93540582011-05-16 22:35:14714 Bind(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr());
715 const_method_cb.Run();
716
[email protected]7296f2762011-11-21 19:23:44717 Closure const_method_const_ptr_cb =
[email protected]93540582011-05-16 22:35:14718 Bind(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr());
719 const_method_const_ptr_cb.Run();
720
721 Callback<int(int)> normal_func_cb =
722 Bind(&FunctionWithWeakFirstParam, weak_factory.GetWeakPtr());
723 EXPECT_EQ(1, normal_func_cb.Run(1));
724
725 weak_factory.InvalidateWeakPtrs();
726 const_weak_factory.InvalidateWeakPtrs();
727
728 method_cb.Run();
729 const_method_cb.Run();
730 const_method_const_ptr_cb.Run();
731
732 // Still runs even after the pointers are invalidated.
733 EXPECT_EQ(2, normal_func_cb.Run(2));
734}
735
[email protected]b38d3572011-02-15 01:27:38736// ConstRef() wrapper support.
737// - Binding w/o ConstRef takes a copy.
738// - Binding a ConstRef takes a reference.
739// - Binding ConstRef to a function ConstRef does not copy on invoke.
740TEST_F(BindTest, ConstRef) {
741 int n = 1;
742
tzik3bc7779b2015-12-19 09:18:46743 Callback<int()> copy_cb = Bind(&Identity, n);
744 Callback<int()> const_ref_cb = Bind(&Identity, ConstRef(n));
[email protected]b38d3572011-02-15 01:27:38745 EXPECT_EQ(n, copy_cb.Run());
746 EXPECT_EQ(n, const_ref_cb.Run());
747 n++;
748 EXPECT_EQ(n - 1, copy_cb.Run());
749 EXPECT_EQ(n, const_ref_cb.Run());
750
751 int copies = 0;
752 int assigns = 0;
tzik52dcd672016-02-15 11:54:30753 int move_constructs = 0;
754 int move_assigns = 0;
755 CopyMoveCounter counter(&copies, &assigns, &move_constructs, &move_assigns);
tzik3bc7779b2015-12-19 09:18:46756 Callback<int()> all_const_ref_cb =
[email protected]b38d3572011-02-15 01:27:38757 Bind(&GetCopies, ConstRef(counter));
758 EXPECT_EQ(0, all_const_ref_cb.Run());
759 EXPECT_EQ(0, copies);
760 EXPECT_EQ(0, assigns);
tzik52dcd672016-02-15 11:54:30761 EXPECT_EQ(0, move_constructs);
762 EXPECT_EQ(0, move_assigns);
[email protected]b38d3572011-02-15 01:27:38763}
764
[email protected]edd2f1b2013-06-22 20:32:50765TEST_F(BindTest, ScopedRefptr) {
tzik1fcff5c2016-05-12 04:09:05766 EXPECT_CALL(has_ref_, AddRef()).Times(1);
767 EXPECT_CALL(has_ref_, Release()).Times(1);
[email protected]edd2f1b2013-06-22 20:32:50768
tzik1fcff5c2016-05-12 04:09:05769 const scoped_refptr<HasRef> refptr(&has_ref_);
tzik3bc7779b2015-12-19 09:18:46770 Callback<int()> scoped_refptr_const_ref_cb =
[email protected]edd2f1b2013-06-22 20:32:50771 Bind(&FunctionWithScopedRefptrFirstParam, base::ConstRef(refptr), 1);
772 EXPECT_EQ(1, scoped_refptr_const_ref_cb.Run());
773}
774
[email protected]08aa4552011-10-15 00:34:42775// Test Owned() support.
776TEST_F(BindTest, Owned) {
777 int deletes = 0;
778 DeleteCounter* counter = new DeleteCounter(&deletes);
779
780 // If we don't capture, delete happens on Callback destruction/reset.
781 // return the same value.
tzik3bc7779b2015-12-19 09:18:46782 Callback<DeleteCounter*()> no_capture_cb =
[email protected]08aa4552011-10-15 00:34:42783 Bind(&PolymorphicIdentity<DeleteCounter*>, Owned(counter));
[email protected]206a2ae82011-12-22 21:12:58784 ASSERT_EQ(counter, no_capture_cb.Run());
785 ASSERT_EQ(counter, no_capture_cb.Run());
[email protected]08aa4552011-10-15 00:34:42786 EXPECT_EQ(0, deletes);
787 no_capture_cb.Reset(); // This should trigger a delete.
788 EXPECT_EQ(1, deletes);
789
790 deletes = 0;
791 counter = new DeleteCounter(&deletes);
792 base::Closure own_object_cb =
793 Bind(&DeleteCounter::VoidMethod0, Owned(counter));
794 own_object_cb.Run();
795 EXPECT_EQ(0, deletes);
796 own_object_cb.Reset();
797 EXPECT_EQ(1, deletes);
798}
799
tzik4435e8042016-05-11 23:05:05800TEST_F(BindTest, UniquePtrReceiver) {
801 std::unique_ptr<StrictMock<NoRef>> no_ref(new StrictMock<NoRef>);
802 EXPECT_CALL(*no_ref, VoidMethod0()).Times(1);
803 Bind(&NoRef::VoidMethod0, std::move(no_ref)).Run();
804}
805
dchengf10b7732016-01-21 19:37:55806// Tests for Passed() wrapper support:
[email protected]206a2ae82011-12-22 21:12:58807// - Passed() can be constructed from a pointer to scoper.
808// - Passed() can be constructed from a scoper rvalue.
809// - Using Passed() gives Callback Ownership.
810// - Ownership is transferred from Callback to callee on the first Run().
811// - Callback supports unbound arguments.
dchengf10b7732016-01-21 19:37:55812template <typename T>
813class BindMoveOnlyTypeTest : public ::testing::Test {
814};
815
816struct CustomDeleter {
817 void operator()(DeleteCounter* c) { delete c; }
818};
819
820using MoveOnlyTypesToTest =
dcheng093de9b2016-04-04 21:25:51821 ::testing::Types<std::unique_ptr<DeleteCounter>,
dchengf10b7732016-01-21 19:37:55822 std::unique_ptr<DeleteCounter>,
823 std::unique_ptr<DeleteCounter, CustomDeleter>>;
824TYPED_TEST_CASE(BindMoveOnlyTypeTest, MoveOnlyTypesToTest);
825
826TYPED_TEST(BindMoveOnlyTypeTest, PassedToBoundCallback) {
[email protected]206a2ae82011-12-22 21:12:58827 int deletes = 0;
828
dchengf10b7732016-01-21 19:37:55829 TypeParam ptr(new DeleteCounter(&deletes));
830 Callback<TypeParam()> callback = Bind(&PassThru<TypeParam>, Passed(&ptr));
[email protected]206a2ae82011-12-22 21:12:58831 EXPECT_FALSE(ptr.get());
832 EXPECT_EQ(0, deletes);
833
834 // If we never invoke the Callback, it retains ownership and deletes.
[email protected]206a2ae82011-12-22 21:12:58835 callback.Reset();
[email protected]206a2ae82011-12-22 21:12:58836 EXPECT_EQ(1, deletes);
[email protected]206a2ae82011-12-22 21:12:58837}
838
dchengf10b7732016-01-21 19:37:55839TYPED_TEST(BindMoveOnlyTypeTest, PassedWithRvalue) {
dcheng69f2a042015-12-14 20:31:52840 int deletes = 0;
dchengf10b7732016-01-21 19:37:55841 Callback<TypeParam()> callback = Bind(
842 &PassThru<TypeParam>, Passed(TypeParam(new DeleteCounter(&deletes))));
dcheng69f2a042015-12-14 20:31:52843 EXPECT_EQ(0, deletes);
844
845 // If we never invoke the Callback, it retains ownership and deletes.
dchengf10b7732016-01-21 19:37:55846 callback.Reset();
dcheng69f2a042015-12-14 20:31:52847 EXPECT_EQ(1, deletes);
dchengf10b7732016-01-21 19:37:55848}
dcheng69f2a042015-12-14 20:31:52849
dchengf10b7732016-01-21 19:37:55850// Check that ownership can be transferred back out.
851TYPED_TEST(BindMoveOnlyTypeTest, ReturnMoveOnlyType) {
852 int deletes = 0;
dcheng69f2a042015-12-14 20:31:52853 DeleteCounter* counter = new DeleteCounter(&deletes);
dchengf10b7732016-01-21 19:37:55854 Callback<TypeParam()> callback =
855 Bind(&PassThru<TypeParam>, Passed(TypeParam(counter)));
856 TypeParam result = callback.Run();
dcheng69f2a042015-12-14 20:31:52857 ASSERT_EQ(counter, result.get());
858 EXPECT_EQ(0, deletes);
859
860 // Resetting does not delete since ownership was transferred.
861 callback.Reset();
862 EXPECT_EQ(0, deletes);
863
864 // Ensure that we actually did get ownership.
865 result.reset();
866 EXPECT_EQ(1, deletes);
dchengf10b7732016-01-21 19:37:55867}
dcheng69f2a042015-12-14 20:31:52868
dchengf10b7732016-01-21 19:37:55869TYPED_TEST(BindMoveOnlyTypeTest, UnboundForwarding) {
870 int deletes = 0;
871 TypeParam ptr(new DeleteCounter(&deletes));
dcheng69f2a042015-12-14 20:31:52872 // Test unbound argument forwarding.
dchengf10b7732016-01-21 19:37:55873 Callback<TypeParam(TypeParam)> cb_unbound = Bind(&PassThru<TypeParam>);
dcheng69f2a042015-12-14 20:31:52874 cb_unbound.Run(std::move(ptr));
dchengf10b7732016-01-21 19:37:55875 EXPECT_EQ(1, deletes);
dcheng69f2a042015-12-14 20:31:52876}
877
dcheng093de9b2016-04-04 21:25:51878void VerifyVector(const std::vector<std::unique_ptr<int>>& v) {
dcheng53b4cea2016-02-02 04:09:33879 ASSERT_EQ(1u, v.size());
880 EXPECT_EQ(12345, *v[0]);
881}
882
dcheng093de9b2016-04-04 21:25:51883std::vector<std::unique_ptr<int>> AcceptAndReturnMoveOnlyVector(
884 std::vector<std::unique_ptr<int>> v) {
dcheng53b4cea2016-02-02 04:09:33885 VerifyVector(v);
886 return v;
887}
888
889// Test that a vector containing move-only types can be used with Callback.
890TEST_F(BindTest, BindMoveOnlyVector) {
dcheng093de9b2016-04-04 21:25:51891 using MoveOnlyVector = std::vector<std::unique_ptr<int>>;
dcheng53b4cea2016-02-02 04:09:33892
893 MoveOnlyVector v;
dcheng093de9b2016-04-04 21:25:51894 v.push_back(WrapUnique(new int(12345)));
dcheng53b4cea2016-02-02 04:09:33895
896 // Early binding should work:
897 base::Callback<MoveOnlyVector()> bound_cb =
898 base::Bind(&AcceptAndReturnMoveOnlyVector, Passed(&v));
899 MoveOnlyVector intermediate_result = bound_cb.Run();
900 VerifyVector(intermediate_result);
901
902 // As should passing it as an argument to Run():
903 base::Callback<MoveOnlyVector(MoveOnlyVector)> unbound_cb =
904 base::Bind(&AcceptAndReturnMoveOnlyVector);
905 MoveOnlyVector final_result = unbound_cb.Run(std::move(intermediate_result));
906 VerifyVector(final_result);
907}
908
tzik52dcd672016-02-15 11:54:30909// Argument copy-constructor usage for non-reference copy-only parameters.
[email protected]b38d3572011-02-15 01:27:38910// - Bound arguments are only copied once.
911// - Forwarded arguments are only copied once.
[email protected]206a2ae82011-12-22 21:12:58912// - Forwarded arguments with coercions are only copied twice (once for the
913// coercion, and one for the final dispatch).
[email protected]b38d3572011-02-15 01:27:38914TEST_F(BindTest, ArgumentCopies) {
915 int copies = 0;
916 int assigns = 0;
917
918 CopyCounter counter(&copies, &assigns);
tzik52dcd672016-02-15 11:54:30919 Bind(&VoidPolymorphic<CopyCounter>::Run, counter);
920 EXPECT_EQ(1, copies);
[email protected]b38d3572011-02-15 01:27:38921 EXPECT_EQ(0, assigns);
922
923 copies = 0;
924 assigns = 0;
tzik52dcd672016-02-15 11:54:30925 Bind(&VoidPolymorphic<CopyCounter>::Run, CopyCounter(&copies, &assigns));
926 EXPECT_EQ(1, copies);
[email protected]b38d3572011-02-15 01:27:38927 EXPECT_EQ(0, assigns);
928
929 copies = 0;
930 assigns = 0;
tzik52dcd672016-02-15 11:54:30931 Bind(&VoidPolymorphic<CopyCounter>::Run).Run(counter);
tzika43eff02016-03-09 05:46:05932 EXPECT_EQ(2, copies);
[email protected]b38d3572011-02-15 01:27:38933 EXPECT_EQ(0, assigns);
tzik52dcd672016-02-15 11:54:30934
935 copies = 0;
936 assigns = 0;
937 Bind(&VoidPolymorphic<CopyCounter>::Run).Run(CopyCounter(&copies, &assigns));
938 EXPECT_EQ(1, copies);
939 EXPECT_EQ(0, assigns);
940
941 copies = 0;
942 assigns = 0;
943 DerivedCopyMoveCounter derived(&copies, &assigns, nullptr, nullptr);
944 Bind(&VoidPolymorphic<CopyCounter>::Run).Run(CopyCounter(derived));
945 EXPECT_EQ(2, copies);
946 EXPECT_EQ(0, assigns);
947
948 copies = 0;
949 assigns = 0;
950 Bind(&VoidPolymorphic<CopyCounter>::Run)
951 .Run(CopyCounter(
952 DerivedCopyMoveCounter(&copies, &assigns, nullptr, nullptr)));
953 EXPECT_EQ(2, copies);
954 EXPECT_EQ(0, assigns);
955}
956
957// Argument move-constructor usage for move-only parameters.
958// - Bound arguments passed by move are not copied.
959TEST_F(BindTest, ArgumentMoves) {
960 int move_constructs = 0;
961 int move_assigns = 0;
962
963 Bind(&VoidPolymorphic<const MoveCounter&>::Run,
964 MoveCounter(&move_constructs, &move_assigns));
965 EXPECT_EQ(1, move_constructs);
966 EXPECT_EQ(0, move_assigns);
967
968 // TODO(tzik): Support binding move-only type into a non-reference parameter
969 // of a variant of Callback.
970
tzika43eff02016-03-09 05:46:05971 move_constructs = 0;
972 move_assigns = 0;
973 Bind(&VoidPolymorphic<MoveCounter>::Run)
974 .Run(MoveCounter(&move_constructs, &move_assigns));
975 EXPECT_EQ(1, move_constructs);
976 EXPECT_EQ(0, move_assigns);
977
978 move_constructs = 0;
979 move_assigns = 0;
980 Bind(&VoidPolymorphic<MoveCounter>::Run)
981 .Run(MoveCounter(DerivedCopyMoveCounter(
982 nullptr, nullptr, &move_constructs, &move_assigns)));
983 EXPECT_EQ(2, move_constructs);
984 EXPECT_EQ(0, move_assigns);
tzik52dcd672016-02-15 11:54:30985}
986
987// Argument constructor usage for non-reference movable-copyable
988// parameters.
989// - Bound arguments passed by move are not copied.
990// - Forwarded arguments are only copied once.
991// - Forwarded arguments with coercions are only copied once and moved once.
992TEST_F(BindTest, ArgumentCopiesAndMoves) {
993 int copies = 0;
994 int assigns = 0;
995 int move_constructs = 0;
996 int move_assigns = 0;
997
998 CopyMoveCounter counter(&copies, &assigns, &move_constructs, &move_assigns);
999 Bind(&VoidPolymorphic<CopyMoveCounter>::Run, counter);
1000 EXPECT_EQ(1, copies);
1001 EXPECT_EQ(0, assigns);
1002 EXPECT_EQ(0, move_constructs);
1003 EXPECT_EQ(0, move_assigns);
1004
1005 copies = 0;
1006 assigns = 0;
1007 move_constructs = 0;
1008 move_assigns = 0;
1009 Bind(&VoidPolymorphic<CopyMoveCounter>::Run,
1010 CopyMoveCounter(&copies, &assigns, &move_constructs, &move_assigns));
1011 EXPECT_EQ(0, copies);
1012 EXPECT_EQ(0, assigns);
1013 EXPECT_EQ(1, move_constructs);
1014 EXPECT_EQ(0, move_assigns);
1015
1016 copies = 0;
1017 assigns = 0;
1018 move_constructs = 0;
1019 move_assigns = 0;
1020 Bind(&VoidPolymorphic<CopyMoveCounter>::Run).Run(counter);
1021 EXPECT_EQ(1, copies);
1022 EXPECT_EQ(0, assigns);
tzika43eff02016-03-09 05:46:051023 EXPECT_EQ(1, move_constructs);
tzik52dcd672016-02-15 11:54:301024 EXPECT_EQ(0, move_assigns);
1025
tzik52dcd672016-02-15 11:54:301026 copies = 0;
1027 assigns = 0;
1028 move_constructs = 0;
1029 move_assigns = 0;
1030 Bind(&VoidPolymorphic<CopyMoveCounter>::Run)
1031 .Run(CopyMoveCounter(&copies, &assigns, &move_constructs, &move_assigns));
tzika43eff02016-03-09 05:46:051032 EXPECT_EQ(0, copies);
tzik52dcd672016-02-15 11:54:301033 EXPECT_EQ(0, assigns);
tzika43eff02016-03-09 05:46:051034 EXPECT_EQ(1, move_constructs);
tzik52dcd672016-02-15 11:54:301035 EXPECT_EQ(0, move_assigns);
1036
tzik52dcd672016-02-15 11:54:301037 DerivedCopyMoveCounter derived_counter(&copies, &assigns, &move_constructs,
1038 &move_assigns);
1039 copies = 0;
1040 assigns = 0;
1041 move_constructs = 0;
1042 move_assigns = 0;
1043 Bind(&VoidPolymorphic<CopyMoveCounter>::Run)
1044 .Run(CopyMoveCounter(derived_counter));
tzika43eff02016-03-09 05:46:051045 EXPECT_EQ(1, copies);
tzik52dcd672016-02-15 11:54:301046 EXPECT_EQ(0, assigns);
tzika43eff02016-03-09 05:46:051047 EXPECT_EQ(1, move_constructs);
tzik52dcd672016-02-15 11:54:301048 EXPECT_EQ(0, move_assigns);
1049
tzik52dcd672016-02-15 11:54:301050 copies = 0;
1051 assigns = 0;
1052 move_constructs = 0;
1053 move_assigns = 0;
1054 Bind(&VoidPolymorphic<CopyMoveCounter>::Run)
1055 .Run(CopyMoveCounter(DerivedCopyMoveCounter(
1056 &copies, &assigns, &move_constructs, &move_assigns)));
tzika43eff02016-03-09 05:46:051057 EXPECT_EQ(0, copies);
tzik52dcd672016-02-15 11:54:301058 EXPECT_EQ(0, assigns);
tzika43eff02016-03-09 05:46:051059 EXPECT_EQ(2, move_constructs);
tzik52dcd672016-02-15 11:54:301060 EXPECT_EQ(0, move_assigns);
[email protected]b38d3572011-02-15 01:27:381061}
1062
1063// Callback construction and assignment tests.
1064// - Construction from an InvokerStorageHolder should not cause ref/deref.
1065// - Assignment from other callback should only cause one ref
1066//
1067// TODO(ajwong): Is there actually a way to test this?
1068
[email protected]054ac7542011-02-27 01:25:591069#if defined(OS_WIN)
1070int __fastcall FastCallFunc(int n) {
1071 return n;
1072}
1073
1074int __stdcall StdCallFunc(int n) {
1075 return n;
1076}
1077
1078// Windows specific calling convention support.
1079// - Can bind a __fastcall function.
1080// - Can bind a __stdcall function.
1081TEST_F(BindTest, WindowsCallingConventions) {
tzik3bc7779b2015-12-19 09:18:461082 Callback<int()> fastcall_cb = Bind(&FastCallFunc, 1);
[email protected]054ac7542011-02-27 01:25:591083 EXPECT_EQ(1, fastcall_cb.Run());
1084
tzik3bc7779b2015-12-19 09:18:461085 Callback<int()> stdcall_cb = Bind(&StdCallFunc, 2);
[email protected]054ac7542011-02-27 01:25:591086 EXPECT_EQ(2, stdcall_cb.Run());
1087}
1088#endif
1089
[email protected]8cf362c2012-11-20 08:28:141090#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && GTEST_HAS_DEATH_TEST
1091
1092// Test null callbacks cause a DCHECK.
1093TEST(BindDeathTest, NullCallback) {
1094 base::Callback<void(int)> null_cb;
1095 ASSERT_TRUE(null_cb.is_null());
1096 EXPECT_DEATH(base::Bind(null_cb, 42), "");
1097}
1098
1099#endif // (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) &&
1100 // GTEST_HAS_DEATH_TEST
1101
[email protected]b38d3572011-02-15 01:27:381102} // namespace
1103} // namespace base