| 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 |