OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2011 Apple Inc. All rights reserved. | |
3 * | |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions | |
6 * are met: | |
7 * 1. Redistributions of source code must retain the above copyright | |
8 * notice, this list of conditions and the following disclaimer. | |
9 * 2. Redistributions in binary form must reproduce the above copyright | |
10 * notice, this list of conditions and the following disclaimer in the | |
11 * documentation and/or other materials provided with the distribution. | |
12 * | |
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' | |
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS | |
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | |
23 * THE POSSIBILITY OF SUCH DAMAGE. | |
24 */ | |
25 | |
26 #include "wtf/Functional.h" | |
27 | |
28 #include "testing/gtest/include/gtest/gtest.h" | |
29 #include "wtf/RefCounted.h" | |
30 #include "wtf/WeakPtr.h" | |
31 #include <utility> | |
32 | |
33 namespace WTF { | |
34 | |
35 class UnwrappedClass { | |
36 public: | |
37 explicit UnwrappedClass(int value) : m_value(value) {} | |
38 | |
39 int value() const { return m_value; } | |
40 | |
41 private: | |
42 int m_value; | |
43 }; | |
44 | |
45 // This class must be wrapped in bind() and unwrapped in closure execution. | |
46 class ClassToBeWrapped { | |
47 WTF_MAKE_NONCOPYABLE(ClassToBeWrapped); | |
48 | |
49 public: | |
50 explicit ClassToBeWrapped(int value) : m_value(value) {} | |
51 | |
52 int value() const { return m_value; } | |
53 | |
54 private: | |
55 int m_value; | |
56 }; | |
57 | |
58 class WrappedClass { | |
59 public: | |
60 WrappedClass(const ClassToBeWrapped& to_be_wrapped) | |
61 : m_value(to_be_wrapped.value()) {} | |
62 | |
63 explicit WrappedClass(int value) : m_value(value) {} | |
64 | |
65 UnwrappedClass unwrap() const { return UnwrappedClass(m_value); } | |
66 | |
67 private: | |
68 int m_value; | |
69 }; | |
70 | |
71 template <> | |
72 struct ParamStorageTraits<ClassToBeWrapped> { | |
73 using StorageType = WrappedClass; | |
74 }; | |
75 | |
76 class HasWeakPtrSupport { | |
77 public: | |
78 HasWeakPtrSupport() : m_weakPtrFactory(this) {} | |
79 | |
80 WTF::WeakPtr<HasWeakPtrSupport> createWeakPtr() { | |
81 return m_weakPtrFactory.createWeakPtr(); | |
82 } | |
83 | |
84 void revokeAll() { m_weakPtrFactory.revokeAll(); } | |
85 | |
86 void increment(int* counter) { ++*counter; } | |
87 | |
88 private: | |
89 WTF::WeakPtrFactory<HasWeakPtrSupport> m_weakPtrFactory; | |
90 }; | |
91 | |
92 } // namespace WTF | |
93 | |
94 namespace base { | |
95 | |
96 template <> | |
97 struct BindUnwrapTraits<WTF::WrappedClass> { | |
98 static WTF::UnwrappedClass Unwrap(const WTF::WrappedClass& wrapped) { | |
99 return wrapped.unwrap(); | |
100 } | |
101 }; | |
102 | |
103 } // namespace base | |
104 | |
105 namespace WTF { | |
106 namespace { | |
107 | |
108 int returnFortyTwo() { | |
109 return 42; | |
110 } | |
111 | |
112 TEST(FunctionalTest, Basic) { | |
113 std::unique_ptr<Function<int()>> returnFortyTwoFunction = | |
114 bind(returnFortyTwo); | |
115 EXPECT_EQ(42, (*returnFortyTwoFunction)()); | |
116 } | |
117 | |
118 int multiplyByTwo(int n) { | |
119 return n * 2; | |
120 } | |
121 | |
122 double multiplyByOneAndAHalf(double d) { | |
123 return d * 1.5; | |
124 } | |
125 | |
126 TEST(FunctionalTest, UnaryBind) { | |
127 std::unique_ptr<Function<int()>> multiplyFourByTwoFunction = | |
128 bind(multiplyByTwo, 4); | |
129 EXPECT_EQ(8, (*multiplyFourByTwoFunction)()); | |
130 | |
131 std::unique_ptr<Function<double()>> multiplyByOneAndAHalfFunction = | |
132 bind(multiplyByOneAndAHalf, 3); | |
133 EXPECT_EQ(4.5, (*multiplyByOneAndAHalfFunction)()); | |
134 } | |
135 | |
136 TEST(FunctionalTest, UnaryPartBind) { | |
137 std::unique_ptr<Function<int(int)>> multiplyByTwoFunction = | |
138 bind(multiplyByTwo); | |
139 EXPECT_EQ(8, (*multiplyByTwoFunction)(4)); | |
140 | |
141 std::unique_ptr<Function<double(double)>> multiplyByOneAndAHalfFunction = | |
142 bind(multiplyByOneAndAHalf); | |
143 EXPECT_EQ(4.5, (*multiplyByOneAndAHalfFunction)(3)); | |
144 } | |
145 | |
146 int multiply(int x, int y) { | |
147 return x * y; | |
148 } | |
149 | |
150 int subtract(int x, int y) { | |
151 return x - y; | |
152 } | |
153 | |
154 TEST(FunctionalTest, BinaryBind) { | |
155 std::unique_ptr<Function<int()>> multiplyFourByTwoFunction = | |
156 bind(multiply, 4, 2); | |
157 EXPECT_EQ(8, (*multiplyFourByTwoFunction)()); | |
158 | |
159 std::unique_ptr<Function<int()>> subtractTwoFromFourFunction = | |
160 bind(subtract, 4, 2); | |
161 EXPECT_EQ(2, (*subtractTwoFromFourFunction)()); | |
162 } | |
163 | |
164 TEST(FunctionalTest, BinaryPartBind) { | |
165 std::unique_ptr<Function<int(int)>> multiplyFourFunction = bind(multiply, 4); | |
166 EXPECT_EQ(8, (*multiplyFourFunction)(2)); | |
167 std::unique_ptr<Function<int(int, int)>> multiplyFunction = bind(multiply); | |
168 EXPECT_EQ(8, (*multiplyFunction)(4, 2)); | |
169 | |
170 std::unique_ptr<Function<int(int)>> subtractFromFourFunction = | |
171 bind(subtract, 4); | |
172 EXPECT_EQ(2, (*subtractFromFourFunction)(2)); | |
173 std::unique_ptr<Function<int(int, int)>> subtractFunction = bind(subtract); | |
174 EXPECT_EQ(2, (*subtractFunction)(4, 2)); | |
175 } | |
176 | |
177 void sixArgFunc(int a, double b, char c, int* d, double* e, char* f) { | |
178 *d = a; | |
179 *e = b; | |
180 *f = c; | |
181 } | |
182 | |
183 void assertArgs(int actualInt, | |
184 double actualDouble, | |
185 char actualChar, | |
186 int expectedInt, | |
187 double expectedDouble, | |
188 char expectedChar) { | |
189 EXPECT_EQ(expectedInt, actualInt); | |
190 EXPECT_EQ(expectedDouble, actualDouble); | |
191 EXPECT_EQ(expectedChar, actualChar); | |
192 } | |
193 | |
194 TEST(FunctionalTest, MultiPartBind) { | |
195 int a = 0; | |
196 double b = 0.5; | |
197 char c = 'a'; | |
198 | |
199 std::unique_ptr<Function<void(int, double, char, int*, double*, char*)>> | |
200 unbound = bind(sixArgFunc); | |
201 (*unbound)(1, 1.5, 'b', &a, &b, &c); | |
202 assertArgs(a, b, c, 1, 1.5, 'b'); | |
203 | |
204 std::unique_ptr<Function<void(double, char, int*, double*, char*)>> oneBound = | |
205 bind(sixArgFunc, 2); | |
206 (*oneBound)(2.5, 'c', &a, &b, &c); | |
207 assertArgs(a, b, c, 2, 2.5, 'c'); | |
208 | |
209 std::unique_ptr<Function<void(char, int*, double*, char*)>> twoBound = | |
210 bind(sixArgFunc, 3, 3.5); | |
211 (*twoBound)('d', &a, &b, &c); | |
212 assertArgs(a, b, c, 3, 3.5, 'd'); | |
213 | |
214 std::unique_ptr<Function<void(int*, double*, char*)>> threeBound = | |
215 bind(sixArgFunc, 4, 4.5, 'e'); | |
216 (*threeBound)(&a, &b, &c); | |
217 assertArgs(a, b, c, 4, 4.5, 'e'); | |
218 | |
219 std::unique_ptr<Function<void(double*, char*)>> fourBound = | |
220 bind(sixArgFunc, 5, 5.5, 'f', WTF::unretained(&a)); | |
221 (*fourBound)(&b, &c); | |
222 assertArgs(a, b, c, 5, 5.5, 'f'); | |
223 | |
224 std::unique_ptr<Function<void(char*)>> fiveBound = | |
225 bind(sixArgFunc, 6, 6.5, 'g', WTF::unretained(&a), WTF::unretained(&b)); | |
226 (*fiveBound)(&c); | |
227 assertArgs(a, b, c, 6, 6.5, 'g'); | |
228 | |
229 std::unique_ptr<Function<void()>> sixBound = | |
230 bind(sixArgFunc, 7, 7.5, 'h', WTF::unretained(&a), WTF::unretained(&b), | |
231 WTF::unretained(&c)); | |
232 (*sixBound)(); | |
233 assertArgs(a, b, c, 7, 7.5, 'h'); | |
234 } | |
235 | |
236 class A { | |
237 public: | |
238 explicit A(int i) : m_i(i) {} | |
239 | |
240 int f() { return m_i; } | |
241 int addF(int j) { return m_i + j; } | |
242 virtual int overridden() { return 42; } | |
243 | |
244 private: | |
245 int m_i; | |
246 }; | |
247 | |
248 class B : public A { | |
249 public: | |
250 explicit B(int i) : A(i) {} | |
251 | |
252 int f() { return A::f() + 1; } | |
253 int addF(int j) { return A::addF(j) + 1; } | |
254 int overridden() override { return 43; } | |
255 }; | |
256 | |
257 TEST(FunctionalTest, MemberFunctionBind) { | |
258 A a(10); | |
259 std::unique_ptr<Function<int()>> function1 = bind(&A::f, WTF::unretained(&a)); | |
260 EXPECT_EQ(10, (*function1)()); | |
261 | |
262 std::unique_ptr<Function<int()>> function2 = | |
263 bind(&A::addF, WTF::unretained(&a), 15); | |
264 EXPECT_EQ(25, (*function2)()); | |
265 | |
266 std::unique_ptr<Function<int()>> function3 = | |
267 bind(&A::overridden, WTF::unretained(&a)); | |
268 EXPECT_EQ(42, (*function3)()); | |
269 } | |
270 | |
271 TEST(FunctionalTest, MemberFunctionBindWithSubclassPointer) { | |
272 B b(10); | |
273 std::unique_ptr<Function<int()>> function1 = bind(&A::f, WTF::unretained(&b)); | |
274 EXPECT_EQ(10, (*function1)()); | |
275 | |
276 std::unique_ptr<Function<int()>> function2 = | |
277 bind(&A::addF, WTF::unretained(&b), 15); | |
278 EXPECT_EQ(25, (*function2)()); | |
279 | |
280 std::unique_ptr<Function<int()>> function3 = | |
281 bind(&A::overridden, WTF::unretained(&b)); | |
282 EXPECT_EQ(43, (*function3)()); | |
283 | |
284 std::unique_ptr<Function<int()>> function4 = bind(&B::f, WTF::unretained(&b)); | |
285 EXPECT_EQ(11, (*function4)()); | |
286 | |
287 std::unique_ptr<Function<int()>> function5 = | |
288 bind(&B::addF, WTF::unretained(&b), 15); | |
289 EXPECT_EQ(26, (*function5)()); | |
290 } | |
291 | |
292 TEST(FunctionalTest, MemberFunctionBindWithSubclassPointerWithCast) { | |
293 B b(10); | |
294 std::unique_ptr<Function<int()>> function1 = | |
295 bind(&A::f, WTF::unretained(static_cast<A*>(&b))); | |
296 EXPECT_EQ(10, (*function1)()); | |
297 | |
298 std::unique_ptr<Function<int()>> function2 = | |
299 bind(&A::addF, WTF::unretained(static_cast<A*>(&b)), 15); | |
300 EXPECT_EQ(25, (*function2)()); | |
301 | |
302 std::unique_ptr<Function<int()>> function3 = | |
303 bind(&A::overridden, WTF::unretained(static_cast<A*>(&b))); | |
304 EXPECT_EQ(43, (*function3)()); | |
305 } | |
306 | |
307 TEST(FunctionalTest, MemberFunctionPartBind) { | |
308 A a(10); | |
309 std::unique_ptr<Function<int(class A*)>> function1 = bind(&A::f); | |
310 EXPECT_EQ(10, (*function1)(&a)); | |
311 | |
312 std::unique_ptr<Function<int(class A*, int)>> unboundFunction2 = | |
313 bind(&A::addF); | |
314 EXPECT_EQ(25, (*unboundFunction2)(&a, 15)); | |
315 std::unique_ptr<Function<int(int)>> objectBoundFunction2 = | |
316 bind(&A::addF, WTF::unretained(&a)); | |
317 EXPECT_EQ(25, (*objectBoundFunction2)(15)); | |
318 } | |
319 | |
320 TEST(FunctionalTest, MemberFunctionBindByUniquePtr) { | |
321 std::unique_ptr<Function<int()>> function1 = | |
322 WTF::bind(&A::f, WTF::makeUnique<A>(10)); | |
323 EXPECT_EQ(10, (*function1)()); | |
324 } | |
325 | |
326 TEST(FunctionalTest, MemberFunctionBindByPassedUniquePtr) { | |
327 std::unique_ptr<Function<int()>> function1 = | |
328 WTF::bind(&A::f, WTF::passed(WTF::makeUnique<A>(10))); | |
329 EXPECT_EQ(10, (*function1)()); | |
330 } | |
331 | |
332 class Number : public RefCounted<Number> { | |
333 public: | |
334 static PassRefPtr<Number> create(int value) { | |
335 return adoptRef(new Number(value)); | |
336 } | |
337 | |
338 ~Number() { m_value = 0; } | |
339 | |
340 int value() const { return m_value; } | |
341 | |
342 private: | |
343 explicit Number(int value) : m_value(value) {} | |
344 | |
345 int m_value; | |
346 }; | |
347 | |
348 int multiplyNumberByTwo(Number* number) { | |
349 return number->value() * 2; | |
350 } | |
351 | |
352 TEST(FunctionalTest, RefCountedStorage) { | |
353 RefPtr<Number> five = Number::create(5); | |
354 EXPECT_EQ(1, five->refCount()); | |
355 std::unique_ptr<Function<int()>> multiplyFiveByTwoFunction = | |
356 bind(multiplyNumberByTwo, five); | |
357 EXPECT_EQ(2, five->refCount()); | |
358 EXPECT_EQ(10, (*multiplyFiveByTwoFunction)()); | |
359 EXPECT_EQ(2, five->refCount()); | |
360 | |
361 std::unique_ptr<Function<int()>> multiplyFourByTwoFunction = | |
362 bind(multiplyNumberByTwo, Number::create(4)); | |
363 EXPECT_EQ(8, (*multiplyFourByTwoFunction)()); | |
364 | |
365 RefPtr<Number> six = Number::create(6); | |
366 std::unique_ptr<Function<int()>> multiplySixByTwoFunction = | |
367 bind(multiplyNumberByTwo, six.release()); | |
368 EXPECT_FALSE(six); | |
369 EXPECT_EQ(12, (*multiplySixByTwoFunction)()); | |
370 } | |
371 | |
372 TEST(FunctionalTest, UnretainedWithRefCounted) { | |
373 RefPtr<Number> five = Number::create(5); | |
374 EXPECT_EQ(1, five->refCount()); | |
375 std::unique_ptr<Function<int()>> multiplyFiveByTwoFunction = | |
376 bind(multiplyNumberByTwo, WTF::unretained(five.get())); | |
377 EXPECT_EQ(1, five->refCount()); | |
378 EXPECT_EQ(10, (*multiplyFiveByTwoFunction)()); | |
379 EXPECT_EQ(1, five->refCount()); | |
380 } | |
381 | |
382 int processUnwrappedClass(const UnwrappedClass& u, int v) { | |
383 return u.value() * v; | |
384 } | |
385 | |
386 // Tests that: | |
387 // - ParamStorageTraits's wrap()/unwrap() are called, and | |
388 // - bind()'s arguments are passed as references to ParamStorageTraits::wrap() | |
389 // with no additional copies. | |
390 // This test would fail in compile if something is wrong, | |
391 // rather than in runtime. | |
392 TEST(FunctionalTest, WrapUnwrap) { | |
393 std::unique_ptr<Function<int()>> function = | |
394 bind(processUnwrappedClass, ClassToBeWrapped(3), 7); | |
395 EXPECT_EQ(21, (*function)()); | |
396 } | |
397 | |
398 TEST(FunctionalTest, WrapUnwrapInPartialBind) { | |
399 std::unique_ptr<Function<int(int)>> partiallyBoundFunction = | |
400 bind(processUnwrappedClass, ClassToBeWrapped(3)); | |
401 EXPECT_EQ(21, (*partiallyBoundFunction)(7)); | |
402 } | |
403 | |
404 bool lotsOfArguments(int first, | |
405 int second, | |
406 int third, | |
407 int fourth, | |
408 int fifth, | |
409 int sixth, | |
410 int seventh, | |
411 int eighth, | |
412 int ninth, | |
413 int tenth) { | |
414 return first == 1 && second == 2 && third == 3 && fourth == 4 && fifth == 5 && | |
415 sixth == 6 && seventh == 7 && eighth == 8 && ninth == 9 && tenth == 10; | |
416 } | |
417 | |
418 TEST(FunctionalTest, LotsOfBoundVariables) { | |
419 std::unique_ptr<Function<bool(int, int)>> eightBound = | |
420 bind(lotsOfArguments, 1, 2, 3, 4, 5, 6, 7, 8); | |
421 EXPECT_TRUE((*eightBound)(9, 10)); | |
422 | |
423 std::unique_ptr<Function<bool(int)>> nineBound = | |
424 bind(lotsOfArguments, 1, 2, 3, 4, 5, 6, 7, 8, 9); | |
425 EXPECT_TRUE((*nineBound)(10)); | |
426 | |
427 std::unique_ptr<Function<bool()>> allBound = | |
428 bind(lotsOfArguments, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); | |
429 EXPECT_TRUE((*allBound)()); | |
430 } | |
431 | |
432 class MoveOnly { | |
433 public: | |
434 explicit MoveOnly(int value) : m_value(value) {} | |
435 MoveOnly(MoveOnly&& other) : m_value(other.m_value) { | |
436 // Reset the value on move. | |
437 other.m_value = 0; | |
438 } | |
439 | |
440 int value() const { return m_value; } | |
441 | |
442 private: | |
443 MoveOnly(const MoveOnly&) = delete; | |
444 MoveOnly& operator=(const MoveOnly&) = delete; | |
445 | |
446 // Disable move-assignment, since it isn't used within bind(). | |
447 MoveOnly& operator=(MoveOnly&&) = delete; | |
448 | |
449 int m_value; | |
450 }; | |
451 | |
452 int singleMoveOnlyByRvalueReference(MoveOnly&& moveOnly) { | |
453 int value = moveOnly.value(); | |
454 MoveOnly(std::move(moveOnly)); | |
455 return value; | |
456 } | |
457 | |
458 int tripleMoveOnlysByRvalueReferences(MoveOnly&& first, | |
459 MoveOnly&& second, | |
460 MoveOnly&& third) { | |
461 int value = first.value() + second.value() + third.value(); | |
462 MoveOnly(std::move(first)); | |
463 MoveOnly(std::move(second)); | |
464 MoveOnly(std::move(third)); | |
465 return value; | |
466 } | |
467 | |
468 int singleMoveOnlyByValue(MoveOnly moveOnly) { | |
469 return moveOnly.value(); | |
470 } | |
471 | |
472 int tripleMoveOnlysByValues(MoveOnly first, MoveOnly second, MoveOnly third) { | |
473 return first.value() + second.value() + third.value(); | |
474 } | |
475 | |
476 TEST(FunctionalTest, BindMoveOnlyObjects) { | |
477 MoveOnly one(1); | |
478 std::unique_ptr<Function<int()>> bound = | |
479 bind(singleMoveOnlyByRvalueReference, WTF::passed(std::move(one))); | |
480 EXPECT_EQ(0, one.value()); // Should be moved away. | |
481 EXPECT_EQ(1, (*bound)()); | |
482 // The stored value must be cleared in the first function call. | |
483 EXPECT_EQ(0, (*bound)()); | |
484 | |
485 bound = bind(singleMoveOnlyByValue, WTF::passed(MoveOnly(1))); | |
486 EXPECT_EQ(1, (*bound)()); | |
487 EXPECT_EQ(0, (*bound)()); | |
488 | |
489 bound = bind(tripleMoveOnlysByRvalueReferences, WTF::passed(MoveOnly(1)), | |
490 WTF::passed(MoveOnly(2)), WTF::passed(MoveOnly(3))); | |
491 EXPECT_EQ(6, (*bound)()); | |
492 EXPECT_EQ(0, (*bound)()); | |
493 | |
494 bound = bind(tripleMoveOnlysByValues, WTF::passed(MoveOnly(1)), | |
495 WTF::passed(MoveOnly(2)), WTF::passed(MoveOnly(3))); | |
496 EXPECT_EQ(6, (*bound)()); | |
497 EXPECT_EQ(0, (*bound)()); | |
498 } | |
499 | |
500 class CountCopy { | |
501 public: | |
502 CountCopy() : m_copies(0) {} | |
503 CountCopy(const CountCopy& other) : m_copies(other.m_copies + 1) {} | |
504 | |
505 int copies() const { return m_copies; } | |
506 | |
507 private: | |
508 // Copy/move-assignment is not needed in the test. | |
509 CountCopy& operator=(const CountCopy&) = delete; | |
510 CountCopy& operator=(CountCopy&&) = delete; | |
511 | |
512 int m_copies; | |
513 }; | |
514 | |
515 int takeCountCopyAsConstReference(const CountCopy& counter) { | |
516 return counter.copies(); | |
517 } | |
518 | |
519 int takeCountCopyAsValue(CountCopy counter) { | |
520 return counter.copies(); | |
521 } | |
522 | |
523 TEST(FunctionalTest, CountCopiesOfBoundArguments) { | |
524 CountCopy lvalue; | |
525 std::unique_ptr<Function<int()>> bound = | |
526 bind(takeCountCopyAsConstReference, lvalue); | |
527 EXPECT_EQ(2, (*bound)()); // wrapping and unwrapping. | |
528 | |
529 bound = bind(takeCountCopyAsConstReference, CountCopy()); // Rvalue. | |
530 EXPECT_EQ(2, (*bound)()); | |
531 | |
532 bound = bind(takeCountCopyAsValue, lvalue); | |
533 // wrapping, unwrapping and copying in the final function argument. | |
534 EXPECT_EQ(3, (*bound)()); | |
535 | |
536 bound = bind(takeCountCopyAsValue, CountCopy()); | |
537 EXPECT_EQ(3, (*bound)()); | |
538 } | |
539 | |
540 TEST(FunctionalTest, MoveUnboundArgumentsByRvalueReference) { | |
541 std::unique_ptr<Function<int(MoveOnly &&)>> boundSingle = | |
542 bind(singleMoveOnlyByRvalueReference); | |
543 EXPECT_EQ(1, (*boundSingle)(MoveOnly(1))); | |
544 EXPECT_EQ(42, (*boundSingle)(MoveOnly(42))); | |
545 | |
546 std::unique_ptr<Function<int(MoveOnly&&, MoveOnly&&, MoveOnly &&)>> | |
547 boundTriple = bind(tripleMoveOnlysByRvalueReferences); | |
548 EXPECT_EQ(6, (*boundTriple)(MoveOnly(1), MoveOnly(2), MoveOnly(3))); | |
549 EXPECT_EQ(666, (*boundTriple)(MoveOnly(111), MoveOnly(222), MoveOnly(333))); | |
550 | |
551 std::unique_ptr<Function<int(MoveOnly)>> boundSingleByValue = | |
552 bind(singleMoveOnlyByValue); | |
553 EXPECT_EQ(1, (*boundSingleByValue)(MoveOnly(1))); | |
554 | |
555 std::unique_ptr<Function<int(MoveOnly, MoveOnly, MoveOnly)>> | |
556 boundTripleByValue = bind(tripleMoveOnlysByValues); | |
557 EXPECT_EQ(6, (*boundTripleByValue)(MoveOnly(1), MoveOnly(2), MoveOnly(3))); | |
558 } | |
559 | |
560 TEST(FunctionalTest, CountCopiesOfUnboundArguments) { | |
561 CountCopy lvalue; | |
562 std::unique_ptr<Function<int(const CountCopy&)>> bound1 = | |
563 bind(takeCountCopyAsConstReference); | |
564 EXPECT_EQ(0, (*bound1)(lvalue)); // No copies! | |
565 EXPECT_EQ(0, (*bound1)(CountCopy())); | |
566 | |
567 std::unique_ptr<Function<int(CountCopy)>> bound2 = bind(takeCountCopyAsValue); | |
568 // At Function::operator(), at Callback::Run() and at the destination | |
569 // function. | |
570 EXPECT_EQ(3, (*bound2)(lvalue)); | |
571 // Compiler is allowed to optimize one copy away if the argument is rvalue. | |
572 EXPECT_LE((*bound2)(CountCopy()), 2); | |
573 } | |
574 | |
575 TEST(FunctionalTest, WeakPtr) { | |
576 HasWeakPtrSupport obj; | |
577 int counter = 0; | |
578 std::unique_ptr<WTF::Closure> bound = | |
579 WTF::bind(&HasWeakPtrSupport::increment, obj.createWeakPtr(), | |
580 WTF::unretained(&counter)); | |
581 | |
582 (*bound)(); | |
583 EXPECT_FALSE(bound->isCancelled()); | |
584 EXPECT_EQ(1, counter); | |
585 | |
586 obj.revokeAll(); | |
587 EXPECT_TRUE(bound->isCancelled()); | |
588 (*bound)(); | |
589 EXPECT_EQ(1, counter); | |
590 } | |
591 | |
592 } // anonymous namespace | |
593 | |
594 } // namespace WTF | |
OLD | NEW |