blob: 0595ed3f714b6aa5face6ea1e16c7dee46d9e7af [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"
[email protected]206a2ae82011-12-22 21:12:5813#include "base/memory/ref_counted.h"
14#include "base/memory/scoped_ptr.h"
15#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) {
766 // BUG: The scoped_refptr should cause the only AddRef()/Release() pair. But
767 // due to a bug in base::Bind(), there's an extra call when invoking the
768 // callback.
769 // https://code.google.com/p/chromium/issues/detail?id=251937
770 EXPECT_CALL(has_ref_, AddRef()).Times(2);
771 EXPECT_CALL(has_ref_, Release()).Times(2);
772
773 const scoped_refptr<StrictMock<HasRef> > refptr(&has_ref_);
774
tzik3bc7779b2015-12-19 09:18:46775 Callback<int()> scoped_refptr_const_ref_cb =
[email protected]edd2f1b2013-06-22 20:32:50776 Bind(&FunctionWithScopedRefptrFirstParam, base::ConstRef(refptr), 1);
777 EXPECT_EQ(1, scoped_refptr_const_ref_cb.Run());
778}
779
[email protected]08aa4552011-10-15 00:34:42780// Test Owned() support.
781TEST_F(BindTest, Owned) {
782 int deletes = 0;
783 DeleteCounter* counter = new DeleteCounter(&deletes);
784
785 // If we don't capture, delete happens on Callback destruction/reset.
786 // return the same value.
tzik3bc7779b2015-12-19 09:18:46787 Callback<DeleteCounter*()> no_capture_cb =
[email protected]08aa4552011-10-15 00:34:42788 Bind(&PolymorphicIdentity<DeleteCounter*>, Owned(counter));
[email protected]206a2ae82011-12-22 21:12:58789 ASSERT_EQ(counter, no_capture_cb.Run());
790 ASSERT_EQ(counter, no_capture_cb.Run());
[email protected]08aa4552011-10-15 00:34:42791 EXPECT_EQ(0, deletes);
792 no_capture_cb.Reset(); // This should trigger a delete.
793 EXPECT_EQ(1, deletes);
794
795 deletes = 0;
796 counter = new DeleteCounter(&deletes);
797 base::Closure own_object_cb =
798 Bind(&DeleteCounter::VoidMethod0, Owned(counter));
799 own_object_cb.Run();
800 EXPECT_EQ(0, deletes);
801 own_object_cb.Reset();
802 EXPECT_EQ(1, deletes);
803}
804
dchengf10b7732016-01-21 19:37:55805// Tests for Passed() wrapper support:
[email protected]206a2ae82011-12-22 21:12:58806// - Passed() can be constructed from a pointer to scoper.
807// - Passed() can be constructed from a scoper rvalue.
808// - Using Passed() gives Callback Ownership.
809// - Ownership is transferred from Callback to callee on the first Run().
810// - Callback supports unbound arguments.
dchengf10b7732016-01-21 19:37:55811template <typename T>
812class BindMoveOnlyTypeTest : public ::testing::Test {
813};
814
815struct CustomDeleter {
816 void operator()(DeleteCounter* c) { delete c; }
817};
818
819using MoveOnlyTypesToTest =
820 ::testing::Types<scoped_ptr<DeleteCounter>,
821 std::unique_ptr<DeleteCounter>,
822 std::unique_ptr<DeleteCounter, CustomDeleter>>;
823TYPED_TEST_CASE(BindMoveOnlyTypeTest, MoveOnlyTypesToTest);
824
825TYPED_TEST(BindMoveOnlyTypeTest, PassedToBoundCallback) {
[email protected]206a2ae82011-12-22 21:12:58826 int deletes = 0;
827
dchengf10b7732016-01-21 19:37:55828 TypeParam ptr(new DeleteCounter(&deletes));
829 Callback<TypeParam()> callback = Bind(&PassThru<TypeParam>, Passed(&ptr));
[email protected]206a2ae82011-12-22 21:12:58830 EXPECT_FALSE(ptr.get());
831 EXPECT_EQ(0, deletes);
832
833 // If we never invoke the Callback, it retains ownership and deletes.
[email protected]206a2ae82011-12-22 21:12:58834 callback.Reset();
[email protected]206a2ae82011-12-22 21:12:58835 EXPECT_EQ(1, deletes);
[email protected]206a2ae82011-12-22 21:12:58836}
837
dchengf10b7732016-01-21 19:37:55838TYPED_TEST(BindMoveOnlyTypeTest, PassedWithRvalue) {
dcheng69f2a042015-12-14 20:31:52839 int deletes = 0;
dchengf10b7732016-01-21 19:37:55840 Callback<TypeParam()> callback = Bind(
841 &PassThru<TypeParam>, Passed(TypeParam(new DeleteCounter(&deletes))));
dcheng69f2a042015-12-14 20:31:52842 EXPECT_EQ(0, deletes);
843
844 // If we never invoke the Callback, it retains ownership and deletes.
dchengf10b7732016-01-21 19:37:55845 callback.Reset();
dcheng69f2a042015-12-14 20:31:52846 EXPECT_EQ(1, deletes);
dchengf10b7732016-01-21 19:37:55847}
dcheng69f2a042015-12-14 20:31:52848
dchengf10b7732016-01-21 19:37:55849// Check that ownership can be transferred back out.
850TYPED_TEST(BindMoveOnlyTypeTest, ReturnMoveOnlyType) {
851 int deletes = 0;
dcheng69f2a042015-12-14 20:31:52852 DeleteCounter* counter = new DeleteCounter(&deletes);
dchengf10b7732016-01-21 19:37:55853 Callback<TypeParam()> callback =
854 Bind(&PassThru<TypeParam>, Passed(TypeParam(counter)));
855 TypeParam result = callback.Run();
dcheng69f2a042015-12-14 20:31:52856 ASSERT_EQ(counter, result.get());
857 EXPECT_EQ(0, deletes);
858
859 // Resetting does not delete since ownership was transferred.
860 callback.Reset();
861 EXPECT_EQ(0, deletes);
862
863 // Ensure that we actually did get ownership.
864 result.reset();
865 EXPECT_EQ(1, deletes);
dchengf10b7732016-01-21 19:37:55866}
dcheng69f2a042015-12-14 20:31:52867
dchengf10b7732016-01-21 19:37:55868TYPED_TEST(BindMoveOnlyTypeTest, UnboundForwarding) {
869 int deletes = 0;
870 TypeParam ptr(new DeleteCounter(&deletes));
dcheng69f2a042015-12-14 20:31:52871 // Test unbound argument forwarding.
dchengf10b7732016-01-21 19:37:55872 Callback<TypeParam(TypeParam)> cb_unbound = Bind(&PassThru<TypeParam>);
dcheng69f2a042015-12-14 20:31:52873 cb_unbound.Run(std::move(ptr));
dchengf10b7732016-01-21 19:37:55874 EXPECT_EQ(1, deletes);
dcheng69f2a042015-12-14 20:31:52875}
876
dcheng53b4cea2016-02-02 04:09:33877void VerifyVector(const std::vector<scoped_ptr<int>>& v) {
878 ASSERT_EQ(1u, v.size());
879 EXPECT_EQ(12345, *v[0]);
880}
881
882std::vector<scoped_ptr<int>> AcceptAndReturnMoveOnlyVector(
883 std::vector<scoped_ptr<int>> v) {
884 VerifyVector(v);
885 return v;
886}
887
888// Test that a vector containing move-only types can be used with Callback.
889TEST_F(BindTest, BindMoveOnlyVector) {
890 using MoveOnlyVector = std::vector<scoped_ptr<int>>;
891
892 MoveOnlyVector v;
893 v.push_back(make_scoped_ptr(new int(12345)));
894
895 // Early binding should work:
896 base::Callback<MoveOnlyVector()> bound_cb =
897 base::Bind(&AcceptAndReturnMoveOnlyVector, Passed(&v));
898 MoveOnlyVector intermediate_result = bound_cb.Run();
899 VerifyVector(intermediate_result);
900
901 // As should passing it as an argument to Run():
902 base::Callback<MoveOnlyVector(MoveOnlyVector)> unbound_cb =
903 base::Bind(&AcceptAndReturnMoveOnlyVector);
904 MoveOnlyVector final_result = unbound_cb.Run(std::move(intermediate_result));
905 VerifyVector(final_result);
906}
907
tzik52dcd672016-02-15 11:54:30908// Argument copy-constructor usage for non-reference copy-only parameters.
[email protected]b38d3572011-02-15 01:27:38909// - Bound arguments are only copied once.
910// - Forwarded arguments are only copied once.
[email protected]206a2ae82011-12-22 21:12:58911// - Forwarded arguments with coercions are only copied twice (once for the
912// coercion, and one for the final dispatch).
[email protected]b38d3572011-02-15 01:27:38913TEST_F(BindTest, ArgumentCopies) {
914 int copies = 0;
915 int assigns = 0;
916
917 CopyCounter counter(&copies, &assigns);
tzik52dcd672016-02-15 11:54:30918 Bind(&VoidPolymorphic<CopyCounter>::Run, counter);
919 EXPECT_EQ(1, copies);
[email protected]b38d3572011-02-15 01:27:38920 EXPECT_EQ(0, assigns);
921
922 copies = 0;
923 assigns = 0;
tzik52dcd672016-02-15 11:54:30924 Bind(&VoidPolymorphic<CopyCounter>::Run, CopyCounter(&copies, &assigns));
925 EXPECT_EQ(1, copies);
[email protected]b38d3572011-02-15 01:27:38926 EXPECT_EQ(0, assigns);
927
928 copies = 0;
929 assigns = 0;
tzik52dcd672016-02-15 11:54:30930 Bind(&VoidPolymorphic<CopyCounter>::Run).Run(counter);
931 EXPECT_EQ(1, copies);
[email protected]b38d3572011-02-15 01:27:38932 EXPECT_EQ(0, assigns);
tzik52dcd672016-02-15 11:54:30933
934 copies = 0;
935 assigns = 0;
936 Bind(&VoidPolymorphic<CopyCounter>::Run).Run(CopyCounter(&copies, &assigns));
937 EXPECT_EQ(1, copies);
938 EXPECT_EQ(0, assigns);
939
940 copies = 0;
941 assigns = 0;
942 DerivedCopyMoveCounter derived(&copies, &assigns, nullptr, nullptr);
943 Bind(&VoidPolymorphic<CopyCounter>::Run).Run(CopyCounter(derived));
944 EXPECT_EQ(2, copies);
945 EXPECT_EQ(0, assigns);
946
947 copies = 0;
948 assigns = 0;
949 Bind(&VoidPolymorphic<CopyCounter>::Run)
950 .Run(CopyCounter(
951 DerivedCopyMoveCounter(&copies, &assigns, nullptr, nullptr)));
952 EXPECT_EQ(2, copies);
953 EXPECT_EQ(0, assigns);
954}
955
956// Argument move-constructor usage for move-only parameters.
957// - Bound arguments passed by move are not copied.
958TEST_F(BindTest, ArgumentMoves) {
959 int move_constructs = 0;
960 int move_assigns = 0;
961
962 Bind(&VoidPolymorphic<const MoveCounter&>::Run,
963 MoveCounter(&move_constructs, &move_assigns));
964 EXPECT_EQ(1, move_constructs);
965 EXPECT_EQ(0, move_assigns);
966
967 // TODO(tzik): Support binding move-only type into a non-reference parameter
968 // of a variant of Callback.
969
970 // TODO(tzik): Support move-only type forwarding on Callback::Run.
971}
972
973// Argument constructor usage for non-reference movable-copyable
974// parameters.
975// - Bound arguments passed by move are not copied.
976// - Forwarded arguments are only copied once.
977// - Forwarded arguments with coercions are only copied once and moved once.
978TEST_F(BindTest, ArgumentCopiesAndMoves) {
979 int copies = 0;
980 int assigns = 0;
981 int move_constructs = 0;
982 int move_assigns = 0;
983
984 CopyMoveCounter counter(&copies, &assigns, &move_constructs, &move_assigns);
985 Bind(&VoidPolymorphic<CopyMoveCounter>::Run, counter);
986 EXPECT_EQ(1, copies);
987 EXPECT_EQ(0, assigns);
988 EXPECT_EQ(0, move_constructs);
989 EXPECT_EQ(0, move_assigns);
990
991 copies = 0;
992 assigns = 0;
993 move_constructs = 0;
994 move_assigns = 0;
995 Bind(&VoidPolymorphic<CopyMoveCounter>::Run,
996 CopyMoveCounter(&copies, &assigns, &move_constructs, &move_assigns));
997 EXPECT_EQ(0, copies);
998 EXPECT_EQ(0, assigns);
999 EXPECT_EQ(1, move_constructs);
1000 EXPECT_EQ(0, move_assigns);
1001
1002 copies = 0;
1003 assigns = 0;
1004 move_constructs = 0;
1005 move_assigns = 0;
1006 Bind(&VoidPolymorphic<CopyMoveCounter>::Run).Run(counter);
1007 EXPECT_EQ(1, copies);
1008 EXPECT_EQ(0, assigns);
1009 EXPECT_EQ(0, move_constructs);
1010 EXPECT_EQ(0, move_assigns);
1011
1012 // TODO(tzik): This case should be done in no copy and one move.
1013 copies = 0;
1014 assigns = 0;
1015 move_constructs = 0;
1016 move_assigns = 0;
1017 Bind(&VoidPolymorphic<CopyMoveCounter>::Run)
1018 .Run(CopyMoveCounter(&copies, &assigns, &move_constructs, &move_assigns));
1019 EXPECT_EQ(1, copies);
1020 EXPECT_EQ(0, assigns);
1021 EXPECT_EQ(0, move_constructs);
1022 EXPECT_EQ(0, move_assigns);
1023
1024 // TODO(tzik): This case should be done in one copy and one move.
1025 DerivedCopyMoveCounter derived_counter(&copies, &assigns, &move_constructs,
1026 &move_assigns);
1027 copies = 0;
1028 assigns = 0;
1029 move_constructs = 0;
1030 move_assigns = 0;
1031 Bind(&VoidPolymorphic<CopyMoveCounter>::Run)
1032 .Run(CopyMoveCounter(derived_counter));
1033 EXPECT_EQ(2, copies);
1034 EXPECT_EQ(0, assigns);
1035 EXPECT_EQ(0, move_constructs);
1036 EXPECT_EQ(0, move_assigns);
1037
1038 // TODO(tzik): This case should be done in no copy and two move.
1039 copies = 0;
1040 assigns = 0;
1041 move_constructs = 0;
1042 move_assigns = 0;
1043 Bind(&VoidPolymorphic<CopyMoveCounter>::Run)
1044 .Run(CopyMoveCounter(DerivedCopyMoveCounter(
1045 &copies, &assigns, &move_constructs, &move_assigns)));
1046 EXPECT_EQ(1, copies);
1047 EXPECT_EQ(0, assigns);
1048 EXPECT_EQ(1, move_constructs);
1049 EXPECT_EQ(0, move_assigns);
[email protected]b38d3572011-02-15 01:27:381050}
1051
1052// Callback construction and assignment tests.
1053// - Construction from an InvokerStorageHolder should not cause ref/deref.
1054// - Assignment from other callback should only cause one ref
1055//
1056// TODO(ajwong): Is there actually a way to test this?
1057
[email protected]054ac7542011-02-27 01:25:591058#if defined(OS_WIN)
1059int __fastcall FastCallFunc(int n) {
1060 return n;
1061}
1062
1063int __stdcall StdCallFunc(int n) {
1064 return n;
1065}
1066
1067// Windows specific calling convention support.
1068// - Can bind a __fastcall function.
1069// - Can bind a __stdcall function.
1070TEST_F(BindTest, WindowsCallingConventions) {
tzik3bc7779b2015-12-19 09:18:461071 Callback<int()> fastcall_cb = Bind(&FastCallFunc, 1);
[email protected]054ac7542011-02-27 01:25:591072 EXPECT_EQ(1, fastcall_cb.Run());
1073
tzik3bc7779b2015-12-19 09:18:461074 Callback<int()> stdcall_cb = Bind(&StdCallFunc, 2);
[email protected]054ac7542011-02-27 01:25:591075 EXPECT_EQ(2, stdcall_cb.Run());
1076}
1077#endif
1078
[email protected]8cf362c2012-11-20 08:28:141079#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && GTEST_HAS_DEATH_TEST
1080
1081// Test null callbacks cause a DCHECK.
1082TEST(BindDeathTest, NullCallback) {
1083 base::Callback<void(int)> null_cb;
1084 ASSERT_TRUE(null_cb.is_null());
1085 EXPECT_DEATH(base::Bind(null_cb, 42), "");
1086}
1087
1088#endif // (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) &&
1089 // GTEST_HAS_DEATH_TEST
1090
[email protected]b38d3572011-02-15 01:27:381091} // namespace
1092} // namespace base