blob: f3a121159e882562457ecdf68e59a70e419ae667 [file] [log] [blame]
Vitaly Bukacbed2062015-08-17 12:54:05 -07001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/bind.h"
6
Alex Vakulenko674f0eb2016-01-20 08:10:48 -08007#include <memory>
8#include <utility>
9
Vitaly Buka8750b272015-08-18 18:39:08 -070010#include <gmock/gmock.h>
11#include <gtest/gtest.h>
12
Vitaly Bukacbed2062015-08-17 12:54:05 -070013#include "base/callback.h"
Alex Vakulenko674f0eb2016-01-20 08:10:48 -080014#include "base/macros.h"
Vitaly Bukacbed2062015-08-17 12:54:05 -070015#include "base/memory/ref_counted.h"
16#include "base/memory/scoped_ptr.h"
17#include "base/memory/weak_ptr.h"
Alex Vakulenko674f0eb2016-01-20 08:10:48 -080018#include "build/build_config.h"
Vitaly Bukacbed2062015-08-17 12:54:05 -070019
20using ::testing::Mock;
21using ::testing::Return;
22using ::testing::StrictMock;
23
24namespace base {
25namespace {
26
27class IncompleteType;
28
29class NoRef {
30 public:
31 NoRef() {}
32
Alex Vakulenko674f0eb2016-01-20 08:10:48 -080033 MOCK_METHOD0(VoidMethod0, void());
34 MOCK_CONST_METHOD0(VoidConstMethod0, void());
Vitaly Bukacbed2062015-08-17 12:54:05 -070035
Alex Vakulenko674f0eb2016-01-20 08:10:48 -080036 MOCK_METHOD0(IntMethod0, int());
37 MOCK_CONST_METHOD0(IntConstMethod0, int());
Vitaly Bukacbed2062015-08-17 12:54:05 -070038
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
Alex Vakulenko674f0eb2016-01-20 08:10:48 -080048 MOCK_CONST_METHOD0(AddRef, void());
49 MOCK_CONST_METHOD0(Release, bool());
Vitaly Bukacbed2062015-08-17 12:54:05 -070050
51 private:
52 // Particularly important in this test to ensure no copies are made.
53 DISALLOW_COPY_AND_ASSIGN(HasRef);
54};
55
56class HasRefPrivateDtor : public HasRef {
57 private:
58 ~HasRefPrivateDtor() {}
59};
60
61static const int kParentValue = 1;
62static const int kChildValue = 2;
63
64class Parent {
65 public:
Alex Vakulenko674f0eb2016-01-20 08:10:48 -080066 virtual ~Parent() = default;
67 void AddRef() const {}
68 void Release() const {}
Vitaly Bukacbed2062015-08-17 12:54:05 -070069 virtual void VirtualSet() { value = kParentValue; }
70 void NonVirtualSet() { value = kParentValue; }
71 int value;
72};
73
74class Child : public Parent {
75 public:
Alex Vakulenko674f0eb2016-01-20 08:10:48 -080076 ~Child() override = default;
Vitaly Bukacbed2062015-08-17 12:54:05 -070077 void VirtualSet() override { value = kChildValue; }
78 void NonVirtualSet() { value = kChildValue; }
79};
80
81class NoRefParent {
82 public:
Alex Vakulenko674f0eb2016-01-20 08:10:48 -080083 virtual ~NoRefParent() = default;
Vitaly Bukacbed2062015-08-17 12:54:05 -070084 virtual void VirtualSet() { value = kParentValue; }
85 void NonVirtualSet() { value = kParentValue; }
86 int value;
87};
88
89class NoRefChild : public NoRefParent {
Alex Vakulenko674f0eb2016-01-20 08:10:48 -080090 public:
91 ~NoRefChild() override = default;
Vitaly Bukacbed2062015-08-17 12:54:05 -070092 void VirtualSet() override { value = kChildValue; }
93 void NonVirtualSet() { value = kChildValue; }
94};
95
96// Used for probing the number of copies that occur if a type must be coerced
97// during argument forwarding in the Run() methods.
98struct DerivedCopyCounter {
99 DerivedCopyCounter(int* copies, int* assigns)
100 : copies_(copies), assigns_(assigns) {
101 }
102 int* copies_;
103 int* assigns_;
104};
105
106// Used for probing the number of copies in an argument.
107class CopyCounter {
108 public:
109 CopyCounter(int* copies, int* assigns)
110 : copies_(copies), assigns_(assigns) {
111 }
112
113 CopyCounter(const CopyCounter& other)
114 : copies_(other.copies_),
115 assigns_(other.assigns_) {
116 (*copies_)++;
117 }
118
119 // Probing for copies from coercion.
120 explicit CopyCounter(const DerivedCopyCounter& other)
121 : copies_(other.copies_),
122 assigns_(other.assigns_) {
123 (*copies_)++;
124 }
125
126 const CopyCounter& operator=(const CopyCounter& rhs) {
127 copies_ = rhs.copies_;
128 assigns_ = rhs.assigns_;
129
130 if (assigns_) {
131 (*assigns_)++;
132 }
133
134 return *this;
135 }
136
137 int copies() const {
138 return *copies_;
139 }
140
141 private:
142 int* copies_;
143 int* assigns_;
144};
145
146class DeleteCounter {
147 public:
148 explicit DeleteCounter(int* deletes)
149 : deletes_(deletes) {
150 }
151
152 ~DeleteCounter() {
153 (*deletes_)++;
154 }
155
156 void VoidMethod0() {}
157
158 private:
159 int* deletes_;
160};
161
162template <typename T>
163T PassThru(T scoper) {
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800164 return scoper;
Vitaly Bukacbed2062015-08-17 12:54:05 -0700165}
166
167// Some test functions that we can Bind to.
168template <typename T>
169T PolymorphicIdentity(T t) {
170 return t;
171}
172
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800173template <typename... Ts>
174struct VoidPolymorphic {
175 static void Run(Ts... t) {}
176};
Vitaly Bukacbed2062015-08-17 12:54:05 -0700177
178int Identity(int n) {
179 return n;
180}
181
182int ArrayGet(const int array[], int n) {
183 return array[n];
184}
185
186int Sum(int a, int b, int c, int d, int e, int f) {
187 return a + b + c + d + e + f;
188}
189
190const char* CStringIdentity(const char* s) {
191 return s;
192}
193
194int GetCopies(const CopyCounter& counter) {
195 return counter.copies();
196}
197
198int UnwrapNoRefParent(NoRefParent p) {
199 return p.value;
200}
201
202int UnwrapNoRefParentPtr(NoRefParent* p) {
203 return p->value;
204}
205
206int UnwrapNoRefParentConstRef(const NoRefParent& p) {
207 return p.value;
208}
209
210void RefArgSet(int &n) {
211 n = 2;
212}
213
214void PtrArgSet(int *n) {
215 *n = 2;
216}
217
218int FunctionWithWeakFirstParam(WeakPtr<NoRef> o, int n) {
219 return n;
220}
221
222int FunctionWithScopedRefptrFirstParam(const scoped_refptr<HasRef>& o, int n) {
223 return n;
224}
225
226void TakesACallback(const Closure& callback) {
227 callback.Run();
228}
229
230class BindTest : public ::testing::Test {
231 public:
232 BindTest() {
233 const_has_ref_ptr_ = &has_ref_;
234 const_no_ref_ptr_ = &no_ref_;
235 static_func_mock_ptr = &static_func_mock_;
236 }
237
238 virtual ~BindTest() {
239 }
240
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800241 static void VoidFunc0() {
Vitaly Bukacbed2062015-08-17 12:54:05 -0700242 static_func_mock_ptr->VoidMethod0();
243 }
244
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800245 static int IntFunc0() { return static_func_mock_ptr->IntMethod0(); }
Vitaly Bukacbed2062015-08-17 12:54:05 -0700246
247 protected:
248 StrictMock<NoRef> no_ref_;
249 StrictMock<HasRef> has_ref_;
250 const HasRef* const_has_ref_ptr_;
251 const NoRef* const_no_ref_ptr_;
252 StrictMock<NoRef> static_func_mock_;
253
254 // Used by the static functions to perform expectations.
255 static StrictMock<NoRef>* static_func_mock_ptr;
256
257 private:
258 DISALLOW_COPY_AND_ASSIGN(BindTest);
259};
260
261StrictMock<NoRef>* BindTest::static_func_mock_ptr;
262
263// Sanity check that we can instantiate a callback for each arity.
264TEST_F(BindTest, ArityTest) {
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800265 Callback<int()> c0 = Bind(&Sum, 32, 16, 8, 4, 2, 1);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700266 EXPECT_EQ(63, c0.Run());
267
268 Callback<int(int)> c1 = Bind(&Sum, 32, 16, 8, 4, 2);
269 EXPECT_EQ(75, c1.Run(13));
270
271 Callback<int(int,int)> c2 = Bind(&Sum, 32, 16, 8, 4);
272 EXPECT_EQ(85, c2.Run(13, 12));
273
274 Callback<int(int,int,int)> c3 = Bind(&Sum, 32, 16, 8);
275 EXPECT_EQ(92, c3.Run(13, 12, 11));
276
277 Callback<int(int,int,int,int)> c4 = Bind(&Sum, 32, 16);
278 EXPECT_EQ(94, c4.Run(13, 12, 11, 10));
279
280 Callback<int(int,int,int,int,int)> c5 = Bind(&Sum, 32);
281 EXPECT_EQ(87, c5.Run(13, 12, 11, 10, 9));
282
283 Callback<int(int,int,int,int,int,int)> c6 = Bind(&Sum);
284 EXPECT_EQ(69, c6.Run(13, 12, 11, 10, 9, 14));
285}
286
287// Test the Currying ability of the Callback system.
288TEST_F(BindTest, CurryingTest) {
289 Callback<int(int,int,int,int,int,int)> c6 = Bind(&Sum);
290 EXPECT_EQ(69, c6.Run(13, 12, 11, 10, 9, 14));
291
292 Callback<int(int,int,int,int,int)> c5 = Bind(c6, 32);
293 EXPECT_EQ(87, c5.Run(13, 12, 11, 10, 9));
294
295 Callback<int(int,int,int,int)> c4 = Bind(c5, 16);
296 EXPECT_EQ(94, c4.Run(13, 12, 11, 10));
297
298 Callback<int(int,int,int)> c3 = Bind(c4, 8);
299 EXPECT_EQ(92, c3.Run(13, 12, 11));
300
301 Callback<int(int,int)> c2 = Bind(c3, 4);
302 EXPECT_EQ(85, c2.Run(13, 12));
303
304 Callback<int(int)> c1 = Bind(c2, 2);
305 EXPECT_EQ(75, c1.Run(13));
306
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800307 Callback<int()> c0 = Bind(c1, 1);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700308 EXPECT_EQ(63, c0.Run());
309}
310
311// Test that currying the rvalue result of another Bind() works correctly.
312// - rvalue should be usable as argument to Bind().
313// - multiple runs of resulting Callback remain valid.
314TEST_F(BindTest, CurryingRvalueResultOfBind) {
315 int n = 0;
316 Closure cb = base::Bind(&TakesACallback, base::Bind(&PtrArgSet, &n));
317
318 // If we implement Bind() such that the return value has auto_ptr-like
319 // semantics, the second call here will fail because ownership of
320 // the internal BindState<> would have been transfered to a *temporary*
321 // constructon of a Callback object on the first call.
322 cb.Run();
323 EXPECT_EQ(2, n);
324
325 n = 0;
326 cb.Run();
327 EXPECT_EQ(2, n);
328}
329
330// Function type support.
331// - Normal function.
332// - Normal function bound with non-refcounted first argument.
333// - Method bound to non-const object.
334// - Method bound to scoped_refptr.
335// - Const method bound to non-const object.
336// - Const method bound to const object.
337// - Derived classes can be used with pointers to non-virtual base functions.
338// - Derived classes can be used with pointers to virtual base functions (and
339// preserve virtual dispatch).
340TEST_F(BindTest, FunctionTypeSupport) {
341 EXPECT_CALL(static_func_mock_, VoidMethod0());
342 EXPECT_CALL(has_ref_, AddRef()).Times(5);
343 EXPECT_CALL(has_ref_, Release()).Times(5);
344 EXPECT_CALL(has_ref_, VoidMethod0()).Times(2);
345 EXPECT_CALL(has_ref_, VoidConstMethod0()).Times(2);
346
347 Closure normal_cb = Bind(&VoidFunc0);
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800348 Callback<NoRef*()> normal_non_refcounted_cb =
Vitaly Bukacbed2062015-08-17 12:54:05 -0700349 Bind(&PolymorphicIdentity<NoRef*>, &no_ref_);
350 normal_cb.Run();
351 EXPECT_EQ(&no_ref_, normal_non_refcounted_cb.Run());
352
353 Closure method_cb = Bind(&HasRef::VoidMethod0, &has_ref_);
354 Closure method_refptr_cb = Bind(&HasRef::VoidMethod0,
355 make_scoped_refptr(&has_ref_));
356 Closure const_method_nonconst_obj_cb = Bind(&HasRef::VoidConstMethod0,
357 &has_ref_);
358 Closure const_method_const_obj_cb = Bind(&HasRef::VoidConstMethod0,
359 const_has_ref_ptr_);
360 method_cb.Run();
361 method_refptr_cb.Run();
362 const_method_nonconst_obj_cb.Run();
363 const_method_const_obj_cb.Run();
364
365 Child child;
366 child.value = 0;
367 Closure virtual_set_cb = Bind(&Parent::VirtualSet, &child);
368 virtual_set_cb.Run();
369 EXPECT_EQ(kChildValue, child.value);
370
371 child.value = 0;
372 Closure non_virtual_set_cb = Bind(&Parent::NonVirtualSet, &child);
373 non_virtual_set_cb.Run();
374 EXPECT_EQ(kParentValue, child.value);
375}
376
377// Return value support.
378// - Function with return value.
379// - Method with return value.
380// - Const method with return value.
381TEST_F(BindTest, ReturnValues) {
382 EXPECT_CALL(static_func_mock_, IntMethod0()).WillOnce(Return(1337));
383 EXPECT_CALL(has_ref_, AddRef()).Times(3);
384 EXPECT_CALL(has_ref_, Release()).Times(3);
385 EXPECT_CALL(has_ref_, IntMethod0()).WillOnce(Return(31337));
386 EXPECT_CALL(has_ref_, IntConstMethod0())
387 .WillOnce(Return(41337))
388 .WillOnce(Return(51337));
389
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800390 Callback<int()> normal_cb = Bind(&IntFunc0);
391 Callback<int()> method_cb = Bind(&HasRef::IntMethod0, &has_ref_);
392 Callback<int()> const_method_nonconst_obj_cb =
Vitaly Bukacbed2062015-08-17 12:54:05 -0700393 Bind(&HasRef::IntConstMethod0, &has_ref_);
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800394 Callback<int()> const_method_const_obj_cb =
Vitaly Bukacbed2062015-08-17 12:54:05 -0700395 Bind(&HasRef::IntConstMethod0, const_has_ref_ptr_);
396 EXPECT_EQ(1337, normal_cb.Run());
397 EXPECT_EQ(31337, method_cb.Run());
398 EXPECT_EQ(41337, const_method_nonconst_obj_cb.Run());
399 EXPECT_EQ(51337, const_method_const_obj_cb.Run());
400}
401
402// IgnoreResult adapter test.
403// - Function with return value.
404// - Method with return value.
405// - Const Method with return.
406// - Method with return value bound to WeakPtr<>.
407// - Const Method with return bound to WeakPtr<>.
408TEST_F(BindTest, IgnoreResult) {
409 EXPECT_CALL(static_func_mock_, IntMethod0()).WillOnce(Return(1337));
410 EXPECT_CALL(has_ref_, AddRef()).Times(2);
411 EXPECT_CALL(has_ref_, Release()).Times(2);
412 EXPECT_CALL(has_ref_, IntMethod0()).WillOnce(Return(10));
413 EXPECT_CALL(has_ref_, IntConstMethod0()).WillOnce(Return(11));
414 EXPECT_CALL(no_ref_, IntMethod0()).WillOnce(Return(12));
415 EXPECT_CALL(no_ref_, IntConstMethod0()).WillOnce(Return(13));
416
417 Closure normal_func_cb = Bind(IgnoreResult(&IntFunc0));
418 normal_func_cb.Run();
419
420 Closure non_void_method_cb =
421 Bind(IgnoreResult(&HasRef::IntMethod0), &has_ref_);
422 non_void_method_cb.Run();
423
424 Closure non_void_const_method_cb =
425 Bind(IgnoreResult(&HasRef::IntConstMethod0), &has_ref_);
426 non_void_const_method_cb.Run();
427
428 WeakPtrFactory<NoRef> weak_factory(&no_ref_);
429 WeakPtrFactory<const NoRef> const_weak_factory(const_no_ref_ptr_);
430
431 Closure non_void_weak_method_cb =
432 Bind(IgnoreResult(&NoRef::IntMethod0), weak_factory.GetWeakPtr());
433 non_void_weak_method_cb.Run();
434
435 Closure non_void_weak_const_method_cb =
436 Bind(IgnoreResult(&NoRef::IntConstMethod0), weak_factory.GetWeakPtr());
437 non_void_weak_const_method_cb.Run();
438
439 weak_factory.InvalidateWeakPtrs();
440 non_void_weak_const_method_cb.Run();
441 non_void_weak_method_cb.Run();
442}
443
444// Argument binding tests.
445// - Argument binding to primitive.
446// - Argument binding to primitive pointer.
447// - Argument binding to a literal integer.
448// - Argument binding to a literal string.
449// - Argument binding with template function.
450// - Argument binding to an object.
451// - Argument binding to pointer to incomplete type.
452// - Argument gets type converted.
453// - Pointer argument gets converted.
454// - Const Reference forces conversion.
455TEST_F(BindTest, ArgumentBinding) {
456 int n = 2;
457
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800458 Callback<int()> bind_primitive_cb = Bind(&Identity, n);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700459 EXPECT_EQ(n, bind_primitive_cb.Run());
460
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800461 Callback<int*()> bind_primitive_pointer_cb =
Vitaly Bukacbed2062015-08-17 12:54:05 -0700462 Bind(&PolymorphicIdentity<int*>, &n);
463 EXPECT_EQ(&n, bind_primitive_pointer_cb.Run());
464
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800465 Callback<int()> bind_int_literal_cb = Bind(&Identity, 3);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700466 EXPECT_EQ(3, bind_int_literal_cb.Run());
467
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800468 Callback<const char*()> bind_string_literal_cb =
Vitaly Bukacbed2062015-08-17 12:54:05 -0700469 Bind(&CStringIdentity, "hi");
470 EXPECT_STREQ("hi", bind_string_literal_cb.Run());
471
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800472 Callback<int()> bind_template_function_cb =
Vitaly Bukacbed2062015-08-17 12:54:05 -0700473 Bind(&PolymorphicIdentity<int>, 4);
474 EXPECT_EQ(4, bind_template_function_cb.Run());
475
476 NoRefParent p;
477 p.value = 5;
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800478 Callback<int()> bind_object_cb = Bind(&UnwrapNoRefParent, p);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700479 EXPECT_EQ(5, bind_object_cb.Run());
480
481 IncompleteType* incomplete_ptr = reinterpret_cast<IncompleteType*>(123);
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800482 Callback<IncompleteType*()> bind_incomplete_ptr_cb =
Vitaly Bukacbed2062015-08-17 12:54:05 -0700483 Bind(&PolymorphicIdentity<IncompleteType*>, incomplete_ptr);
484 EXPECT_EQ(incomplete_ptr, bind_incomplete_ptr_cb.Run());
485
486 NoRefChild c;
487 c.value = 6;
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800488 Callback<int()> bind_promotes_cb = Bind(&UnwrapNoRefParent, c);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700489 EXPECT_EQ(6, bind_promotes_cb.Run());
490
491 c.value = 7;
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800492 Callback<int()> bind_pointer_promotes_cb =
Vitaly Bukacbed2062015-08-17 12:54:05 -0700493 Bind(&UnwrapNoRefParentPtr, &c);
494 EXPECT_EQ(7, bind_pointer_promotes_cb.Run());
495
496 c.value = 8;
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800497 Callback<int()> bind_const_reference_promotes_cb =
Vitaly Bukacbed2062015-08-17 12:54:05 -0700498 Bind(&UnwrapNoRefParentConstRef, c);
499 EXPECT_EQ(8, bind_const_reference_promotes_cb.Run());
500}
501
502// Unbound argument type support tests.
503// - Unbound value.
504// - Unbound pointer.
505// - Unbound reference.
506// - Unbound const reference.
507// - Unbound unsized array.
508// - Unbound sized array.
509// - Unbound array-of-arrays.
510TEST_F(BindTest, UnboundArgumentTypeSupport) {
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800511 Callback<void(int)> unbound_value_cb = Bind(&VoidPolymorphic<int>::Run);
512 Callback<void(int*)> unbound_pointer_cb = Bind(&VoidPolymorphic<int*>::Run);
513 Callback<void(int&)> unbound_ref_cb = Bind(&VoidPolymorphic<int&>::Run);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700514 Callback<void(const int&)> unbound_const_ref_cb =
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800515 Bind(&VoidPolymorphic<const int&>::Run);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700516 Callback<void(int[])> unbound_unsized_array_cb =
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800517 Bind(&VoidPolymorphic<int[]>::Run);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700518 Callback<void(int[2])> unbound_sized_array_cb =
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800519 Bind(&VoidPolymorphic<int[2]>::Run);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700520 Callback<void(int[][2])> unbound_array_of_arrays_cb =
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800521 Bind(&VoidPolymorphic<int[][2]>::Run);
522
523 Callback<void(int&)> unbound_ref_with_bound_arg =
524 Bind(&VoidPolymorphic<int, int&>::Run, 1);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700525}
526
527// Function with unbound reference parameter.
528// - Original parameter is modified by callback.
529TEST_F(BindTest, UnboundReferenceSupport) {
530 int n = 0;
531 Callback<void(int&)> unbound_ref_cb = Bind(&RefArgSet);
532 unbound_ref_cb.Run(n);
533 EXPECT_EQ(2, n);
534}
535
536// Functions that take reference parameters.
537// - Forced reference parameter type still stores a copy.
538// - Forced const reference parameter type still stores a copy.
539TEST_F(BindTest, ReferenceArgumentBinding) {
540 int n = 1;
541 int& ref_n = n;
542 const int& const_ref_n = n;
543
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800544 Callback<int()> ref_copies_cb = Bind(&Identity, ref_n);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700545 EXPECT_EQ(n, ref_copies_cb.Run());
546 n++;
547 EXPECT_EQ(n - 1, ref_copies_cb.Run());
548
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800549 Callback<int()> const_ref_copies_cb = Bind(&Identity, const_ref_n);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700550 EXPECT_EQ(n, const_ref_copies_cb.Run());
551 n++;
552 EXPECT_EQ(n - 1, const_ref_copies_cb.Run());
553}
554
555// Check that we can pass in arrays and have them be stored as a pointer.
556// - Array of values stores a pointer.
557// - Array of const values stores a pointer.
558TEST_F(BindTest, ArrayArgumentBinding) {
559 int array[4] = {1, 1, 1, 1};
560 const int (*const_array_ptr)[4] = &array;
561
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800562 Callback<int()> array_cb = Bind(&ArrayGet, array, 1);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700563 EXPECT_EQ(1, array_cb.Run());
564
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800565 Callback<int()> const_array_cb = Bind(&ArrayGet, *const_array_ptr, 1);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700566 EXPECT_EQ(1, const_array_cb.Run());
567
568 array[1] = 3;
569 EXPECT_EQ(3, array_cb.Run());
570 EXPECT_EQ(3, const_array_cb.Run());
571}
572
573// Verify SupportsAddRefAndRelease correctly introspects the class type for
574// AddRef() and Release().
575// - Class with AddRef() and Release()
576// - Class without AddRef() and Release()
577// - Derived Class with AddRef() and Release()
578// - Derived Class without AddRef() and Release()
579// - Derived Class with AddRef() and Release() and a private destructor.
580TEST_F(BindTest, SupportsAddRefAndRelease) {
581 EXPECT_TRUE(internal::SupportsAddRefAndRelease<HasRef>::value);
582 EXPECT_FALSE(internal::SupportsAddRefAndRelease<NoRef>::value);
583
584 // StrictMock<T> is a derived class of T. So, we use StrictMock<HasRef> and
585 // StrictMock<NoRef> to test that SupportsAddRefAndRelease works over
586 // inheritance.
587 EXPECT_TRUE(internal::SupportsAddRefAndRelease<StrictMock<HasRef> >::value);
588 EXPECT_FALSE(internal::SupportsAddRefAndRelease<StrictMock<NoRef> >::value);
589
590 // This matters because the implementation creates a dummy class that
591 // inherits from the template type.
592 EXPECT_TRUE(internal::SupportsAddRefAndRelease<HasRefPrivateDtor>::value);
593}
594
595// Unretained() wrapper support.
596// - Method bound to Unretained() non-const object.
597// - Const method bound to Unretained() non-const object.
598// - Const method bound to Unretained() const object.
599TEST_F(BindTest, Unretained) {
600 EXPECT_CALL(no_ref_, VoidMethod0());
601 EXPECT_CALL(no_ref_, VoidConstMethod0()).Times(2);
602
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800603 Callback<void()> method_cb =
Vitaly Bukacbed2062015-08-17 12:54:05 -0700604 Bind(&NoRef::VoidMethod0, Unretained(&no_ref_));
605 method_cb.Run();
606
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800607 Callback<void()> const_method_cb =
Vitaly Bukacbed2062015-08-17 12:54:05 -0700608 Bind(&NoRef::VoidConstMethod0, Unretained(&no_ref_));
609 const_method_cb.Run();
610
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800611 Callback<void()> const_method_const_ptr_cb =
Vitaly Bukacbed2062015-08-17 12:54:05 -0700612 Bind(&NoRef::VoidConstMethod0, Unretained(const_no_ref_ptr_));
613 const_method_const_ptr_cb.Run();
614}
615
616// WeakPtr() support.
617// - Method bound to WeakPtr<> to non-const object.
618// - Const method bound to WeakPtr<> to non-const object.
619// - Const method bound to WeakPtr<> to const object.
620// - Normal Function with WeakPtr<> as P1 can have return type and is
621// not canceled.
622TEST_F(BindTest, WeakPtr) {
623 EXPECT_CALL(no_ref_, VoidMethod0());
624 EXPECT_CALL(no_ref_, VoidConstMethod0()).Times(2);
625
626 WeakPtrFactory<NoRef> weak_factory(&no_ref_);
627 WeakPtrFactory<const NoRef> const_weak_factory(const_no_ref_ptr_);
628
629 Closure method_cb =
630 Bind(&NoRef::VoidMethod0, weak_factory.GetWeakPtr());
631 method_cb.Run();
632
633 Closure const_method_cb =
634 Bind(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr());
635 const_method_cb.Run();
636
637 Closure const_method_const_ptr_cb =
638 Bind(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr());
639 const_method_const_ptr_cb.Run();
640
641 Callback<int(int)> normal_func_cb =
642 Bind(&FunctionWithWeakFirstParam, weak_factory.GetWeakPtr());
643 EXPECT_EQ(1, normal_func_cb.Run(1));
644
645 weak_factory.InvalidateWeakPtrs();
646 const_weak_factory.InvalidateWeakPtrs();
647
648 method_cb.Run();
649 const_method_cb.Run();
650 const_method_const_ptr_cb.Run();
651
652 // Still runs even after the pointers are invalidated.
653 EXPECT_EQ(2, normal_func_cb.Run(2));
654}
655
656// ConstRef() wrapper support.
657// - Binding w/o ConstRef takes a copy.
658// - Binding a ConstRef takes a reference.
659// - Binding ConstRef to a function ConstRef does not copy on invoke.
660TEST_F(BindTest, ConstRef) {
661 int n = 1;
662
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800663 Callback<int()> copy_cb = Bind(&Identity, n);
664 Callback<int()> const_ref_cb = Bind(&Identity, ConstRef(n));
Vitaly Bukacbed2062015-08-17 12:54:05 -0700665 EXPECT_EQ(n, copy_cb.Run());
666 EXPECT_EQ(n, const_ref_cb.Run());
667 n++;
668 EXPECT_EQ(n - 1, copy_cb.Run());
669 EXPECT_EQ(n, const_ref_cb.Run());
670
671 int copies = 0;
672 int assigns = 0;
673 CopyCounter counter(&copies, &assigns);
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800674 Callback<int()> all_const_ref_cb =
Vitaly Bukacbed2062015-08-17 12:54:05 -0700675 Bind(&GetCopies, ConstRef(counter));
676 EXPECT_EQ(0, all_const_ref_cb.Run());
677 EXPECT_EQ(0, copies);
678 EXPECT_EQ(0, assigns);
679}
680
681TEST_F(BindTest, ScopedRefptr) {
682 // BUG: The scoped_refptr should cause the only AddRef()/Release() pair. But
683 // due to a bug in base::Bind(), there's an extra call when invoking the
684 // callback.
685 // https://code.google.com/p/chromium/issues/detail?id=251937
686 EXPECT_CALL(has_ref_, AddRef()).Times(2);
687 EXPECT_CALL(has_ref_, Release()).Times(2);
688
689 const scoped_refptr<StrictMock<HasRef> > refptr(&has_ref_);
690
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800691 Callback<int()> scoped_refptr_const_ref_cb =
Vitaly Bukacbed2062015-08-17 12:54:05 -0700692 Bind(&FunctionWithScopedRefptrFirstParam, base::ConstRef(refptr), 1);
693 EXPECT_EQ(1, scoped_refptr_const_ref_cb.Run());
694}
695
696// Test Owned() support.
697TEST_F(BindTest, Owned) {
698 int deletes = 0;
699 DeleteCounter* counter = new DeleteCounter(&deletes);
700
701 // If we don't capture, delete happens on Callback destruction/reset.
702 // return the same value.
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800703 Callback<DeleteCounter*()> no_capture_cb =
Vitaly Bukacbed2062015-08-17 12:54:05 -0700704 Bind(&PolymorphicIdentity<DeleteCounter*>, Owned(counter));
705 ASSERT_EQ(counter, no_capture_cb.Run());
706 ASSERT_EQ(counter, no_capture_cb.Run());
707 EXPECT_EQ(0, deletes);
708 no_capture_cb.Reset(); // This should trigger a delete.
709 EXPECT_EQ(1, deletes);
710
711 deletes = 0;
712 counter = new DeleteCounter(&deletes);
713 base::Closure own_object_cb =
714 Bind(&DeleteCounter::VoidMethod0, Owned(counter));
715 own_object_cb.Run();
716 EXPECT_EQ(0, deletes);
717 own_object_cb.Reset();
718 EXPECT_EQ(1, deletes);
719}
720
721// Passed() wrapper support.
722// - Passed() can be constructed from a pointer to scoper.
723// - Passed() can be constructed from a scoper rvalue.
724// - Using Passed() gives Callback Ownership.
725// - Ownership is transferred from Callback to callee on the first Run().
726// - Callback supports unbound arguments.
727TEST_F(BindTest, ScopedPtr) {
728 int deletes = 0;
729
730 // Tests the Passed() function's support for pointers.
731 scoped_ptr<DeleteCounter> ptr(new DeleteCounter(&deletes));
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800732 Callback<scoped_ptr<DeleteCounter>()> unused_callback =
Vitaly Bukacbed2062015-08-17 12:54:05 -0700733 Bind(&PassThru<scoped_ptr<DeleteCounter> >, Passed(&ptr));
734 EXPECT_FALSE(ptr.get());
735 EXPECT_EQ(0, deletes);
736
737 // If we never invoke the Callback, it retains ownership and deletes.
738 unused_callback.Reset();
739 EXPECT_EQ(1, deletes);
740
741 // Tests the Passed() function's support for rvalues.
742 deletes = 0;
743 DeleteCounter* counter = new DeleteCounter(&deletes);
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800744 Callback<scoped_ptr<DeleteCounter>()> callback =
Vitaly Bukacbed2062015-08-17 12:54:05 -0700745 Bind(&PassThru<scoped_ptr<DeleteCounter> >,
746 Passed(scoped_ptr<DeleteCounter>(counter)));
747 EXPECT_FALSE(ptr.get());
748 EXPECT_EQ(0, deletes);
749
750 // Check that ownership can be transferred back out.
751 scoped_ptr<DeleteCounter> result = callback.Run();
752 ASSERT_EQ(counter, result.get());
753 EXPECT_EQ(0, deletes);
754
755 // Resetting does not delete since ownership was transferred.
756 callback.Reset();
757 EXPECT_EQ(0, deletes);
758
759 // Ensure that we actually did get ownership.
760 result.reset();
761 EXPECT_EQ(1, deletes);
762
763 // Test unbound argument forwarding.
764 Callback<scoped_ptr<DeleteCounter>(scoped_ptr<DeleteCounter>)> cb_unbound =
765 Bind(&PassThru<scoped_ptr<DeleteCounter> >);
766 ptr.reset(new DeleteCounter(&deletes));
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800767 cb_unbound.Run(std::move(ptr));
768}
769
770TEST_F(BindTest, UniquePtr) {
771 int deletes = 0;
772
773 // Tests the Passed() function's support for pointers.
774 std::unique_ptr<DeleteCounter> ptr(new DeleteCounter(&deletes));
775 Callback<std::unique_ptr<DeleteCounter>()> unused_callback =
776 Bind(&PassThru<std::unique_ptr<DeleteCounter>>, Passed(&ptr));
777 EXPECT_FALSE(ptr.get());
778 EXPECT_EQ(0, deletes);
779
780 // If we never invoke the Callback, it retains ownership and deletes.
781 unused_callback.Reset();
782 EXPECT_EQ(1, deletes);
783
784 // Tests the Passed() function's support for rvalues.
785 deletes = 0;
786 DeleteCounter* counter = new DeleteCounter(&deletes);
787 Callback<std::unique_ptr<DeleteCounter>()> callback =
788 Bind(&PassThru<std::unique_ptr<DeleteCounter>>,
789 Passed(std::unique_ptr<DeleteCounter>(counter)));
790 EXPECT_FALSE(ptr.get());
791 EXPECT_EQ(0, deletes);
792
793 // Check that ownership can be transferred back out.
794 std::unique_ptr<DeleteCounter> result = callback.Run();
795 ASSERT_EQ(counter, result.get());
796 EXPECT_EQ(0, deletes);
797
798 // Resetting does not delete since ownership was transferred.
799 callback.Reset();
800 EXPECT_EQ(0, deletes);
801
802 // Ensure that we actually did get ownership.
803 result.reset();
804 EXPECT_EQ(1, deletes);
805
806 // Test unbound argument forwarding.
807 Callback<std::unique_ptr<DeleteCounter>(std::unique_ptr<DeleteCounter>)>
808 cb_unbound = Bind(&PassThru<std::unique_ptr<DeleteCounter>>);
809 ptr.reset(new DeleteCounter(&deletes));
810 cb_unbound.Run(std::move(ptr));
Vitaly Bukacbed2062015-08-17 12:54:05 -0700811}
812
813// Argument Copy-constructor usage for non-reference parameters.
814// - Bound arguments are only copied once.
815// - Forwarded arguments are only copied once.
816// - Forwarded arguments with coercions are only copied twice (once for the
817// coercion, and one for the final dispatch).
818TEST_F(BindTest, ArgumentCopies) {
819 int copies = 0;
820 int assigns = 0;
821
822 CopyCounter counter(&copies, &assigns);
823
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800824 Callback<void()> copy_cb =
825 Bind(&VoidPolymorphic<CopyCounter>::Run, counter);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700826 EXPECT_GE(1, copies);
827 EXPECT_EQ(0, assigns);
828
829 copies = 0;
830 assigns = 0;
831 Callback<void(CopyCounter)> forward_cb =
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800832 Bind(&VoidPolymorphic<CopyCounter>::Run);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700833 forward_cb.Run(counter);
834 EXPECT_GE(1, copies);
835 EXPECT_EQ(0, assigns);
836
837 copies = 0;
838 assigns = 0;
839 DerivedCopyCounter derived(&copies, &assigns);
840 Callback<void(CopyCounter)> coerce_cb =
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800841 Bind(&VoidPolymorphic<CopyCounter>::Run);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700842 coerce_cb.Run(CopyCounter(derived));
843 EXPECT_GE(2, copies);
844 EXPECT_EQ(0, assigns);
845}
846
847// Callback construction and assignment tests.
848// - Construction from an InvokerStorageHolder should not cause ref/deref.
849// - Assignment from other callback should only cause one ref
850//
851// TODO(ajwong): Is there actually a way to test this?
852
853#if defined(OS_WIN)
854int __fastcall FastCallFunc(int n) {
855 return n;
856}
857
858int __stdcall StdCallFunc(int n) {
859 return n;
860}
861
862// Windows specific calling convention support.
863// - Can bind a __fastcall function.
864// - Can bind a __stdcall function.
865TEST_F(BindTest, WindowsCallingConventions) {
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800866 Callback<int()> fastcall_cb = Bind(&FastCallFunc, 1);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700867 EXPECT_EQ(1, fastcall_cb.Run());
868
Alex Vakulenko674f0eb2016-01-20 08:10:48 -0800869 Callback<int()> stdcall_cb = Bind(&StdCallFunc, 2);
Vitaly Bukacbed2062015-08-17 12:54:05 -0700870 EXPECT_EQ(2, stdcall_cb.Run());
871}
872#endif
873
874#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && GTEST_HAS_DEATH_TEST
875
876// Test null callbacks cause a DCHECK.
877TEST(BindDeathTest, NullCallback) {
878 base::Callback<void(int)> null_cb;
879 ASSERT_TRUE(null_cb.is_null());
880 EXPECT_DEATH(base::Bind(null_cb, 42), "");
881}
882
883#endif // (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) &&
884 // GTEST_HAS_DEATH_TEST
885
886} // namespace
887} // namespace base