blob: 654a2775a2f23efc2f266d8db8286e20fed15b0a [file] [log] [blame]
[email protected]b38d3572011-02-15 01:27:381// Copyright (c) 2011 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
[email protected]b38d3572011-02-15 01:27:387#include "base/callback.h"
8#include "testing/gmock/include/gmock/gmock.h"
9#include "testing/gtest/include/gtest/gtest.h"
10
11using ::testing::Mock;
12using ::testing::Return;
13using ::testing::StrictMock;
14
15namespace base {
16namespace {
17
[email protected]8217d4542011-10-01 06:31:4118class IncompleteType;
19
[email protected]b38d3572011-02-15 01:27:3820class NoRef {
21 public:
22 NoRef() {}
23
24 MOCK_METHOD0(VoidMethod0, void(void));
25 MOCK_CONST_METHOD0(VoidConstMethod0, void(void));
26
27 MOCK_METHOD0(IntMethod0, int(void));
28 MOCK_CONST_METHOD0(IntConstMethod0, int(void));
29
30 private:
31 // Particularly important in this test to ensure no copies are made.
32 DISALLOW_COPY_AND_ASSIGN(NoRef);
33};
34
35class HasRef : public NoRef {
36 public:
37 HasRef() {}
38
39 MOCK_CONST_METHOD0(AddRef, void(void));
40 MOCK_CONST_METHOD0(Release, bool(void));
41
42 private:
43 // Particularly important in this test to ensure no copies are made.
44 DISALLOW_COPY_AND_ASSIGN(HasRef);
45};
46
[email protected]690bda882011-04-13 22:40:4647class HasRefPrivateDtor : public HasRef {
48 private:
49 ~HasRefPrivateDtor() {}
50};
51
[email protected]b38d3572011-02-15 01:27:3852static const int kParentValue = 1;
53static const int kChildValue = 2;
54
55class Parent {
56 public:
57 void AddRef(void) const {}
58 void Release(void) const {}
59 virtual void VirtualSet() { value = kParentValue; }
60 void NonVirtualSet() { value = kParentValue; }
61 int value;
62};
63
64class Child : public Parent {
65 public:
66 virtual void VirtualSet() { value = kChildValue; }
67 void NonVirtualSet() { value = kChildValue; }
68};
69
70class NoRefParent {
71 public:
72 virtual void VirtualSet() { value = kParentValue; }
73 void NonVirtualSet() { value = kParentValue; }
74 int value;
75};
76
77class NoRefChild : public NoRefParent {
78 virtual void VirtualSet() { value = kChildValue; }
79 void NonVirtualSet() { value = kChildValue; }
80};
81
82// Used for probing the number of copies that occur if a type must be coerced
83// during argument forwarding in the Run() methods.
84struct DerivedCopyCounter {
85 DerivedCopyCounter(int* copies, int* assigns)
86 : copies_(copies), assigns_(assigns) {
87 }
88 int* copies_;
89 int* assigns_;
90};
91
92// Used for probing the number of copies in an argument.
93class CopyCounter {
94 public:
95 CopyCounter(int* copies, int* assigns)
96 : copies_(copies), assigns_(assigns) {
97 }
98
99 CopyCounter(const CopyCounter& other)
100 : copies_(other.copies_),
101 assigns_(other.assigns_) {
102 (*copies_)++;
103 }
104
105 // Probing for copies from coerscion.
106 CopyCounter(const DerivedCopyCounter& other)
107 : copies_(other.copies_),
108 assigns_(other.assigns_) {
109 (*copies_)++;
110 }
111
112 const CopyCounter& operator=(const CopyCounter& rhs) {
113 copies_ = rhs.copies_;
114 assigns_ = rhs.assigns_;
115
116 if (assigns_) {
117 (*assigns_)++;
118 }
119
120 return *this;
121 }
122
123 int copies() const {
124 return *copies_;
125 }
126
127 int assigns() const {
128 return *assigns_;
129 }
130
131 private:
132 int* copies_;
133 int* assigns_;
134};
135
[email protected]08aa4552011-10-15 00:34:42136class DeleteCounter {
137 public:
138 explicit DeleteCounter(int* deletes)
139 : deletes_(deletes) {
140 }
141
142 ~DeleteCounter() {
143 (*deletes_)++;
144 }
145
146 void VoidMethod0() {}
147
148 private:
149 int* deletes_;
150};
151
[email protected]b38d3572011-02-15 01:27:38152// Some test functions that we can Bind to.
153template <typename T>
154T PolymorphicIdentity(T t) {
155 return t;
156}
157
158template <typename T>
159void VoidPolymorphic1(T t) {
160}
161
162int Identity(int n) {
163 return n;
164}
165
166int ArrayGet(const int array[], int n) {
167 return array[n];
168}
169
170int Sum(int a, int b, int c, int d, int e, int f) {
171 return a + b + c + d + e + f;
172}
173
[email protected]cea20fe42011-09-30 09:09:34174void OutputSum(int* output, int a, int b, int c, int d, int e) {
175 *output = a + b + c + d + e;
176}
177
[email protected]b38d3572011-02-15 01:27:38178const char* CStringIdentity(const char* s) {
179 return s;
180}
181
182int GetCopies(const CopyCounter& counter) {
183 return counter.copies();
184}
185
186int UnwrapNoRefParent(NoRefParent p) {
187 return p.value;
188}
189
190int UnwrapNoRefParentPtr(NoRefParent* p) {
191 return p->value;
192}
193
194int UnwrapNoRefParentConstRef(const NoRefParent& p) {
195 return p.value;
196}
197
[email protected]c18b1052011-03-24 02:02:17198void RefArgSet(int &n) {
199 n = 2;
200}
201
[email protected]93540582011-05-16 22:35:14202int FunctionWithWeakFirstParam(WeakPtr<NoRef> o, int n) {
203 return n;
204}
205
[email protected]b38d3572011-02-15 01:27:38206class BindTest : public ::testing::Test {
207 public:
208 BindTest() {
209 const_has_ref_ptr_ = &has_ref_;
210 const_no_ref_ptr_ = &no_ref_;
211 static_func_mock_ptr = &static_func_mock_;
212 }
213
214 virtual ~BindTest() {
215 }
216
217 static void VoidFunc0(void) {
218 static_func_mock_ptr->VoidMethod0();
219 }
220
221 static int IntFunc0(void) { return static_func_mock_ptr->IntMethod0(); }
222
223 protected:
224 StrictMock<NoRef> no_ref_;
225 StrictMock<HasRef> has_ref_;
226 const HasRef* const_has_ref_ptr_;
227 const NoRef* const_no_ref_ptr_;
228 StrictMock<NoRef> static_func_mock_;
229
230 // Used by the static functions to perform expectations.
231 static StrictMock<NoRef>* static_func_mock_ptr;
232
233 private:
234 DISALLOW_COPY_AND_ASSIGN(BindTest);
235};
236
237StrictMock<NoRef>* BindTest::static_func_mock_ptr;
238
[email protected]b38d3572011-02-15 01:27:38239// Sanity check that we can instantiate a callback for each arity.
240TEST_F(BindTest, ArityTest) {
241 Callback<int(void)> c0 = Bind(&Sum, 32, 16, 8, 4, 2, 1);
242 EXPECT_EQ(63, c0.Run());
243
244 Callback<int(int)> c1 = Bind(&Sum, 32, 16, 8, 4, 2);
245 EXPECT_EQ(75, c1.Run(13));
246
247 Callback<int(int,int)> c2 = Bind(&Sum, 32, 16, 8, 4);
248 EXPECT_EQ(85, c2.Run(13, 12));
249
250 Callback<int(int,int,int)> c3 = Bind(&Sum, 32, 16, 8);
251 EXPECT_EQ(92, c3.Run(13, 12, 11));
252
253 Callback<int(int,int,int,int)> c4 = Bind(&Sum, 32, 16);
254 EXPECT_EQ(94, c4.Run(13, 12, 11, 10));
255
256 Callback<int(int,int,int,int,int)> c5 = Bind(&Sum, 32);
257 EXPECT_EQ(87, c5.Run(13, 12, 11, 10, 9));
258
259 Callback<int(int,int,int,int,int,int)> c6 = Bind(&Sum);
260 EXPECT_EQ(69, c6.Run(13, 12, 11, 10, 9, 14));
261}
262
[email protected]7296f2762011-11-21 19:23:44263// Test the Currying ability of the Callback system.
264TEST_F(BindTest, CurryingTest) {
265 Callback<int(int,int,int,int,int,int)> c6 = Bind(&Sum);
266 EXPECT_EQ(69, c6.Run(13, 12, 11, 10, 9, 14));
[email protected]cea20fe42011-09-30 09:09:34267
[email protected]7296f2762011-11-21 19:23:44268 Callback<int(int,int,int,int,int)> c5 = Bind(c6, 32);
269 EXPECT_EQ(87, c5.Run(13, 12, 11, 10, 9));
[email protected]cea20fe42011-09-30 09:09:34270
[email protected]7296f2762011-11-21 19:23:44271 Callback<int(int,int,int,int)> c4 = Bind(c5, 16);
272 EXPECT_EQ(94, c4.Run(13, 12, 11, 10));
[email protected]cea20fe42011-09-30 09:09:34273
[email protected]7296f2762011-11-21 19:23:44274 Callback<int(int,int,int)> c3 = Bind(c4, 8);
275 EXPECT_EQ(92, c3.Run(13, 12, 11));
[email protected]cea20fe42011-09-30 09:09:34276
[email protected]7296f2762011-11-21 19:23:44277 Callback<int(int,int)> c2 = Bind(c3, 4);
278 EXPECT_EQ(85, c2.Run(13, 12));
[email protected]cea20fe42011-09-30 09:09:34279
[email protected]7296f2762011-11-21 19:23:44280 Callback<int(int)> c1 = Bind(c2, 2);
281 EXPECT_EQ(75, c1.Run(13));
282
283 Callback<int(void)> c0 = Bind(c1, 1);
284 EXPECT_EQ(63, c0.Run());
[email protected]cea20fe42011-09-30 09:09:34285}
286
[email protected]b38d3572011-02-15 01:27:38287// Function type support.
288// - Normal function.
[email protected]81814bce2011-09-10 03:03:00289// - Normal function bound with non-refcounted first argument.
[email protected]b38d3572011-02-15 01:27:38290// - Method bound to non-const object.
[email protected]7a15d1172011-10-07 00:25:29291// - Method bound to scoped_refptr.
[email protected]b38d3572011-02-15 01:27:38292// - Const method bound to non-const object.
293// - Const method bound to const object.
294// - Derived classes can be used with pointers to non-virtual base functions.
295// - Derived classes can be used with pointers to virtual base functions (and
296// preserve virtual dispatch).
297TEST_F(BindTest, FunctionTypeSupport) {
298 EXPECT_CALL(static_func_mock_, VoidMethod0());
[email protected]7a15d1172011-10-07 00:25:29299 EXPECT_CALL(has_ref_, AddRef()).Times(5);
300 EXPECT_CALL(has_ref_, Release()).Times(5);
301 EXPECT_CALL(has_ref_, VoidMethod0()).Times(2);
[email protected]b38d3572011-02-15 01:27:38302 EXPECT_CALL(has_ref_, VoidConstMethod0()).Times(2);
303
304 Closure normal_cb = Bind(&VoidFunc0);
[email protected]81814bce2011-09-10 03:03:00305 Callback<NoRef*(void)> normal_non_refcounted_cb =
306 Bind(&PolymorphicIdentity<NoRef*>, &no_ref_);
307 normal_cb.Run();
308 EXPECT_EQ(&no_ref_, normal_non_refcounted_cb.Run());
309
[email protected]b38d3572011-02-15 01:27:38310 Closure method_cb = Bind(&HasRef::VoidMethod0, &has_ref_);
[email protected]7a15d1172011-10-07 00:25:29311 Closure method_refptr_cb = Bind(&HasRef::VoidMethod0,
312 make_scoped_refptr(&has_ref_));
[email protected]b38d3572011-02-15 01:27:38313 Closure const_method_nonconst_obj_cb = Bind(&HasRef::VoidConstMethod0,
314 &has_ref_);
315 Closure const_method_const_obj_cb = Bind(&HasRef::VoidConstMethod0,
316 const_has_ref_ptr_);
[email protected]b38d3572011-02-15 01:27:38317 method_cb.Run();
[email protected]7a15d1172011-10-07 00:25:29318 method_refptr_cb.Run();
[email protected]b38d3572011-02-15 01:27:38319 const_method_nonconst_obj_cb.Run();
320 const_method_const_obj_cb.Run();
321
322 Child child;
323 child.value = 0;
324 Closure virtual_set_cb = Bind(&Parent::VirtualSet, &child);
325 virtual_set_cb.Run();
326 EXPECT_EQ(kChildValue, child.value);
327
328 child.value = 0;
329 Closure non_virtual_set_cb = Bind(&Parent::NonVirtualSet, &child);
330 non_virtual_set_cb.Run();
331 EXPECT_EQ(kParentValue, child.value);
332}
333
334// Return value support.
335// - Function with return value.
336// - Method with return value.
337// - Const method with return value.
338TEST_F(BindTest, ReturnValues) {
339 EXPECT_CALL(static_func_mock_, IntMethod0()).WillOnce(Return(1337));
340 EXPECT_CALL(has_ref_, AddRef()).Times(3);
341 EXPECT_CALL(has_ref_, Release()).Times(3);
342 EXPECT_CALL(has_ref_, IntMethod0()).WillOnce(Return(31337));
343 EXPECT_CALL(has_ref_, IntConstMethod0())
344 .WillOnce(Return(41337))
345 .WillOnce(Return(51337));
346
347 Callback<int(void)> normal_cb = Bind(&IntFunc0);
348 Callback<int(void)> method_cb = Bind(&HasRef::IntMethod0, &has_ref_);
349 Callback<int(void)> const_method_nonconst_obj_cb =
350 Bind(&HasRef::IntConstMethod0, &has_ref_);
351 Callback<int(void)> const_method_const_obj_cb =
352 Bind(&HasRef::IntConstMethod0, const_has_ref_ptr_);
353 EXPECT_EQ(1337, normal_cb.Run());
354 EXPECT_EQ(31337, method_cb.Run());
355 EXPECT_EQ(41337, const_method_nonconst_obj_cb.Run());
356 EXPECT_EQ(51337, const_method_const_obj_cb.Run());
357}
358
[email protected]7296f2762011-11-21 19:23:44359// IgnoreResult adapter test.
360// - Function with return value.
361// - Method with return value.
362// - Const Method with return.
363// - Method with return value bound to WeakPtr<>.
364// - Const Method with return bound to WeakPtr<>.
365TEST_F(BindTest, IgnoreResult) {
[email protected]e8bfc31d2011-09-28 00:26:37366 EXPECT_CALL(static_func_mock_, IntMethod0()).WillOnce(Return(1337));
[email protected]7296f2762011-11-21 19:23:44367 EXPECT_CALL(has_ref_, AddRef()).Times(2);
368 EXPECT_CALL(has_ref_, Release()).Times(2);
369 EXPECT_CALL(has_ref_, IntMethod0()).WillOnce(Return(10));
370 EXPECT_CALL(has_ref_, IntConstMethod0()).WillOnce(Return(11));
371 EXPECT_CALL(no_ref_, IntMethod0()).WillOnce(Return(12));
372 EXPECT_CALL(no_ref_, IntConstMethod0()).WillOnce(Return(13));
373
374 Closure normal_func_cb = Bind(IgnoreResult(&IntFunc0));
375 normal_func_cb.Run();
376
377 Closure non_void_method_cb =
378 Bind(IgnoreResult(&HasRef::IntMethod0), &has_ref_);
379 non_void_method_cb.Run();
380
381 Closure non_void_const_method_cb =
382 Bind(IgnoreResult(&HasRef::IntConstMethod0), &has_ref_);
383 non_void_const_method_cb.Run();
384
385 WeakPtrFactory<NoRef> weak_factory(&no_ref_);
386 WeakPtrFactory<const NoRef> const_weak_factory(const_no_ref_ptr_);
387
388 Closure non_void_weak_method_cb =
389 Bind(IgnoreResult(&NoRef::IntMethod0), weak_factory.GetWeakPtr());
390 non_void_weak_method_cb.Run();
391
392 Closure non_void_weak_const_method_cb =
393 Bind(IgnoreResult(&NoRef::IntConstMethod0), weak_factory.GetWeakPtr());
394 non_void_weak_const_method_cb.Run();
395
396 weak_factory.InvalidateWeakPtrs();
397 non_void_weak_const_method_cb.Run();
398 non_void_weak_method_cb.Run();
[email protected]e8bfc31d2011-09-28 00:26:37399}
400
[email protected]b38d3572011-02-15 01:27:38401// Argument binding tests.
402// - Argument binding to primitive.
403// - Argument binding to primitive pointer.
404// - Argument binding to a literal integer.
405// - Argument binding to a literal string.
406// - Argument binding with template function.
407// - Argument binding to an object.
[email protected]8217d4542011-10-01 06:31:41408// - Argument binding to pointer to incomplete type.
[email protected]b38d3572011-02-15 01:27:38409// - Argument gets type converted.
410// - Pointer argument gets converted.
411// - Const Reference forces conversion.
412TEST_F(BindTest, ArgumentBinding) {
413 int n = 2;
414
415 Callback<int(void)> bind_primitive_cb = Bind(&Identity, n);
416 EXPECT_EQ(n, bind_primitive_cb.Run());
417
418 Callback<int*(void)> bind_primitive_pointer_cb =
419 Bind(&PolymorphicIdentity<int*>, &n);
420 EXPECT_EQ(&n, bind_primitive_pointer_cb.Run());
421
422 Callback<int(void)> bind_int_literal_cb = Bind(&Identity, 3);
423 EXPECT_EQ(3, bind_int_literal_cb.Run());
424
425 Callback<const char*(void)> bind_string_literal_cb =
426 Bind(&CStringIdentity, "hi");
427 EXPECT_STREQ("hi", bind_string_literal_cb.Run());
428
429 Callback<int(void)> bind_template_function_cb =
430 Bind(&PolymorphicIdentity<int>, 4);
431 EXPECT_EQ(4, bind_template_function_cb.Run());
432
433 NoRefParent p;
434 p.value = 5;
435 Callback<int(void)> bind_object_cb = Bind(&UnwrapNoRefParent, p);
436 EXPECT_EQ(5, bind_object_cb.Run());
437
[email protected]8217d4542011-10-01 06:31:41438 IncompleteType* incomplete_ptr = reinterpret_cast<IncompleteType*>(123);
439 Callback<IncompleteType*(void)> bind_incomplete_ptr_cb =
440 Bind(&PolymorphicIdentity<IncompleteType*>, incomplete_ptr);
441 EXPECT_EQ(incomplete_ptr, bind_incomplete_ptr_cb.Run());
442
[email protected]b38d3572011-02-15 01:27:38443 NoRefChild c;
444 c.value = 6;
445 Callback<int(void)> bind_promotes_cb = Bind(&UnwrapNoRefParent, c);
446 EXPECT_EQ(6, bind_promotes_cb.Run());
447
448 c.value = 7;
449 Callback<int(void)> bind_pointer_promotes_cb =
450 Bind(&UnwrapNoRefParentPtr, &c);
451 EXPECT_EQ(7, bind_pointer_promotes_cb.Run());
452
453 c.value = 8;
454 Callback<int(void)> bind_const_reference_promotes_cb =
455 Bind(&UnwrapNoRefParentConstRef, c);
456 EXPECT_EQ(8, bind_const_reference_promotes_cb.Run());
457}
458
[email protected]c18b1052011-03-24 02:02:17459// Unbound argument type support tests.
460// - Unbound value.
461// - Unbound pointer.
462// - Unbound reference.
463// - Unbound const reference.
464// - Unbound unsized array.
465// - Unbound sized array.
466// - Unbound array-of-arrays.
467TEST_F(BindTest, UnboundArgumentTypeSupport) {
468 Callback<void(int)> unbound_value_cb = Bind(&VoidPolymorphic1<int>);
469 Callback<void(int*)> unbound_pointer_cb = Bind(&VoidPolymorphic1<int*>);
470 Callback<void(int&)> unbound_ref_cb = Bind(&VoidPolymorphic1<int&>);
471 Callback<void(const int&)> unbound_const_ref_cb =
472 Bind(&VoidPolymorphic1<const int&>);
473 Callback<void(int[])> unbound_unsized_array_cb =
474 Bind(&VoidPolymorphic1<int[]>);
475 Callback<void(int[2])> unbound_sized_array_cb =
476 Bind(&VoidPolymorphic1<int[2]>);
477 Callback<void(int[][2])> unbound_array_of_arrays_cb =
478 Bind(&VoidPolymorphic1<int[][2]>);
479}
480
481// Function with unbound reference parameter.
[email protected]7296f2762011-11-21 19:23:44482// - Original parameter is modified by callback.
[email protected]c18b1052011-03-24 02:02:17483TEST_F(BindTest, UnboundReferenceSupport) {
484 int n = 0;
485 Callback<void(int&)> unbound_ref_cb = Bind(&RefArgSet);
486 unbound_ref_cb.Run(n);
487 EXPECT_EQ(2, n);
488}
489
[email protected]b38d3572011-02-15 01:27:38490// Functions that take reference parameters.
491// - Forced reference parameter type still stores a copy.
492// - Forced const reference parameter type still stores a copy.
493TEST_F(BindTest, ReferenceArgumentBinding) {
494 int n = 1;
495 int& ref_n = n;
496 const int& const_ref_n = n;
497
498 Callback<int(void)> ref_copies_cb = Bind(&Identity, ref_n);
499 EXPECT_EQ(n, ref_copies_cb.Run());
500 n++;
501 EXPECT_EQ(n - 1, ref_copies_cb.Run());
502
503 Callback<int(void)> const_ref_copies_cb = Bind(&Identity, const_ref_n);
504 EXPECT_EQ(n, const_ref_copies_cb.Run());
505 n++;
506 EXPECT_EQ(n - 1, const_ref_copies_cb.Run());
507}
508
509// Check that we can pass in arrays and have them be stored as a pointer.
510// - Array of values stores a pointer.
511// - Array of const values stores a pointer.
512TEST_F(BindTest, ArrayArgumentBinding) {
513 int array[4] = {1, 1, 1, 1};
514 const int (*const_array_ptr)[4] = &array;
515
516 Callback<int(void)> array_cb = Bind(&ArrayGet, array, 1);
517 EXPECT_EQ(1, array_cb.Run());
518
519 Callback<int(void)> const_array_cb = Bind(&ArrayGet, *const_array_ptr, 1);
520 EXPECT_EQ(1, const_array_cb.Run());
521
522 array[1] = 3;
523 EXPECT_EQ(3, array_cb.Run());
524 EXPECT_EQ(3, const_array_cb.Run());
525}
526
527// Verify SupportsAddRefAndRelease correctly introspects the class type for
528// AddRef() and Release().
[email protected]690bda882011-04-13 22:40:46529// - Class with AddRef() and Release()
530// - Class without AddRef() and Release()
531// - Derived Class with AddRef() and Release()
532// - Derived Class without AddRef() and Release()
533// - Derived Class with AddRef() and Release() and a private destructor.
[email protected]b38d3572011-02-15 01:27:38534TEST_F(BindTest, SupportsAddRefAndRelease) {
535 EXPECT_TRUE(internal::SupportsAddRefAndRelease<HasRef>::value);
536 EXPECT_FALSE(internal::SupportsAddRefAndRelease<NoRef>::value);
537
538 // StrictMock<T> is a derived class of T. So, we use StrictMock<HasRef> and
539 // StrictMock<NoRef> to test that SupportsAddRefAndRelease works over
540 // inheritance.
541 EXPECT_TRUE(internal::SupportsAddRefAndRelease<StrictMock<HasRef> >::value);
542 EXPECT_FALSE(internal::SupportsAddRefAndRelease<StrictMock<NoRef> >::value);
[email protected]690bda882011-04-13 22:40:46543
544 // This matters because the implementation creates a dummy class that
545 // inherits from the template type.
546 EXPECT_TRUE(internal::SupportsAddRefAndRelease<HasRefPrivateDtor>::value);
[email protected]b38d3572011-02-15 01:27:38547}
548
549// Unretained() wrapper support.
[email protected]93540582011-05-16 22:35:14550// - Method bound to Unretained() non-const object.
[email protected]b38d3572011-02-15 01:27:38551// - Const method bound to Unretained() non-const object.
552// - Const method bound to Unretained() const object.
553TEST_F(BindTest, Unretained) {
554 EXPECT_CALL(no_ref_, VoidMethod0());
555 EXPECT_CALL(no_ref_, VoidConstMethod0()).Times(2);
556
557 Callback<void(void)> method_cb =
558 Bind(&NoRef::VoidMethod0, Unretained(&no_ref_));
559 method_cb.Run();
560
561 Callback<void(void)> const_method_cb =
562 Bind(&NoRef::VoidConstMethod0, Unretained(&no_ref_));
563 const_method_cb.Run();
564
565 Callback<void(void)> const_method_const_ptr_cb =
566 Bind(&NoRef::VoidConstMethod0, Unretained(const_no_ref_ptr_));
567 const_method_const_ptr_cb.Run();
568}
569
[email protected]93540582011-05-16 22:35:14570// WeakPtr() support.
571// - Method bound to WeakPtr<> to non-const object.
572// - Const method bound to WeakPtr<> to non-const object.
573// - Const method bound to WeakPtr<> to const object.
574// - Normal Function with WeakPtr<> as P1 can have return type and is
575// not canceled.
576TEST_F(BindTest, WeakPtr) {
577 EXPECT_CALL(no_ref_, VoidMethod0());
578 EXPECT_CALL(no_ref_, VoidConstMethod0()).Times(2);
579
580 WeakPtrFactory<NoRef> weak_factory(&no_ref_);
581 WeakPtrFactory<const NoRef> const_weak_factory(const_no_ref_ptr_);
582
[email protected]7296f2762011-11-21 19:23:44583 Closure method_cb =
[email protected]93540582011-05-16 22:35:14584 Bind(&NoRef::VoidMethod0, weak_factory.GetWeakPtr());
585 method_cb.Run();
586
[email protected]7296f2762011-11-21 19:23:44587 Closure const_method_cb =
[email protected]93540582011-05-16 22:35:14588 Bind(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr());
589 const_method_cb.Run();
590
[email protected]7296f2762011-11-21 19:23:44591 Closure const_method_const_ptr_cb =
[email protected]93540582011-05-16 22:35:14592 Bind(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr());
593 const_method_const_ptr_cb.Run();
594
595 Callback<int(int)> normal_func_cb =
596 Bind(&FunctionWithWeakFirstParam, weak_factory.GetWeakPtr());
597 EXPECT_EQ(1, normal_func_cb.Run(1));
598
599 weak_factory.InvalidateWeakPtrs();
600 const_weak_factory.InvalidateWeakPtrs();
601
602 method_cb.Run();
603 const_method_cb.Run();
604 const_method_const_ptr_cb.Run();
605
606 // Still runs even after the pointers are invalidated.
607 EXPECT_EQ(2, normal_func_cb.Run(2));
608}
609
[email protected]b38d3572011-02-15 01:27:38610// ConstRef() wrapper support.
611// - Binding w/o ConstRef takes a copy.
612// - Binding a ConstRef takes a reference.
613// - Binding ConstRef to a function ConstRef does not copy on invoke.
614TEST_F(BindTest, ConstRef) {
615 int n = 1;
616
617 Callback<int(void)> copy_cb = Bind(&Identity, n);
618 Callback<int(void)> const_ref_cb = Bind(&Identity, ConstRef(n));
619 EXPECT_EQ(n, copy_cb.Run());
620 EXPECT_EQ(n, const_ref_cb.Run());
621 n++;
622 EXPECT_EQ(n - 1, copy_cb.Run());
623 EXPECT_EQ(n, const_ref_cb.Run());
624
625 int copies = 0;
626 int assigns = 0;
627 CopyCounter counter(&copies, &assigns);
628 Callback<int(void)> all_const_ref_cb =
629 Bind(&GetCopies, ConstRef(counter));
630 EXPECT_EQ(0, all_const_ref_cb.Run());
631 EXPECT_EQ(0, copies);
632 EXPECT_EQ(0, assigns);
633}
634
[email protected]08aa4552011-10-15 00:34:42635// Test Owned() support.
636TEST_F(BindTest, Owned) {
637 int deletes = 0;
638 DeleteCounter* counter = new DeleteCounter(&deletes);
639
640 // If we don't capture, delete happens on Callback destruction/reset.
641 // return the same value.
642 Callback<DeleteCounter*(void)> no_capture_cb =
643 Bind(&PolymorphicIdentity<DeleteCounter*>, Owned(counter));
644 EXPECT_EQ(counter, no_capture_cb.Run());
645 EXPECT_EQ(counter, no_capture_cb.Run());
646 EXPECT_EQ(0, deletes);
647 no_capture_cb.Reset(); // This should trigger a delete.
648 EXPECT_EQ(1, deletes);
649
650 deletes = 0;
651 counter = new DeleteCounter(&deletes);
652 base::Closure own_object_cb =
653 Bind(&DeleteCounter::VoidMethod0, Owned(counter));
654 own_object_cb.Run();
655 EXPECT_EQ(0, deletes);
656 own_object_cb.Reset();
657 EXPECT_EQ(1, deletes);
658}
659
[email protected]b38d3572011-02-15 01:27:38660// Argument Copy-constructor usage for non-reference parameters.
661// - Bound arguments are only copied once.
662// - Forwarded arguments are only copied once.
663// - Forwarded arguments with coerscions are only copied twice (once for the
664// coerscion, and one for the final dispatch).
665TEST_F(BindTest, ArgumentCopies) {
666 int copies = 0;
667 int assigns = 0;
668
669 CopyCounter counter(&copies, &assigns);
670
671 Callback<void(void)> copy_cb =
672 Bind(&VoidPolymorphic1<CopyCounter>, counter);
673 EXPECT_GE(1, copies);
674 EXPECT_EQ(0, assigns);
675
676 copies = 0;
677 assigns = 0;
678 Callback<void(CopyCounter)> forward_cb =
679 Bind(&VoidPolymorphic1<CopyCounter>);
680 forward_cb.Run(counter);
681 EXPECT_GE(1, copies);
682 EXPECT_EQ(0, assigns);
683
684 copies = 0;
685 assigns = 0;
686 DerivedCopyCounter dervied(&copies, &assigns);
687 Callback<void(CopyCounter)> coerce_cb =
688 Bind(&VoidPolymorphic1<CopyCounter>);
689 coerce_cb.Run(dervied);
690 EXPECT_GE(2, copies);
691 EXPECT_EQ(0, assigns);
692}
693
694// Callback construction and assignment tests.
695// - Construction from an InvokerStorageHolder should not cause ref/deref.
696// - Assignment from other callback should only cause one ref
697//
698// TODO(ajwong): Is there actually a way to test this?
699
[email protected]054ac7542011-02-27 01:25:59700#if defined(OS_WIN)
701int __fastcall FastCallFunc(int n) {
702 return n;
703}
704
705int __stdcall StdCallFunc(int n) {
706 return n;
707}
708
709// Windows specific calling convention support.
710// - Can bind a __fastcall function.
711// - Can bind a __stdcall function.
712TEST_F(BindTest, WindowsCallingConventions) {
713 Callback<int(void)> fastcall_cb = Bind(&FastCallFunc, 1);
714 EXPECT_EQ(1, fastcall_cb.Run());
715
716 Callback<int(void)> stdcall_cb = Bind(&StdCallFunc, 2);
717 EXPECT_EQ(2, stdcall_cb.Run());
718}
719#endif
720
[email protected]b38d3572011-02-15 01:27:38721} // namespace
722} // namespace base