1// Copyright 2017 The Fuchsia 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 <fbl/function.h> 6#include <fbl/vector.h> 7#include <unittest/unittest.h> 8 9namespace fbl { 10namespace tests { 11namespace { 12 13using Closure = void(); 14using BinaryOp = int(int a, int b); 15using MoveOp = fbl::unique_ptr<int>(fbl::unique_ptr<int> value); 16 17// A big object which causes a function target to be heap allocated. 18struct Big { 19 int data[64]{}; 20}; 21 22// An object that looks like an "empty" std::function. 23template<typename> struct EmptyFunction; 24template<typename R, typename... Args> struct EmptyFunction<R(Args...)> { 25 R operator()(Args... args) const { return fptr(args...); } 26 bool operator==(decltype(nullptr)) const { return true; } 27 28 R (*fptr)(Args...) = nullptr; 29}; 30 31constexpr size_t HugeCallableSize = sizeof(Big) + sizeof(void*) * 4; 32 33template <typename ClosureFunction> 34bool closure() { 35 BEGIN_TEST; 36 37 // default initialization 38 ClosureFunction fdefault; 39 EXPECT_FALSE(!!fdefault); 40 41 // nullptr initialization 42 ClosureFunction fnull(nullptr); 43 EXPECT_FALSE(!!fnull); 44 45 // null function pointer initialization 46 Closure* fptr = nullptr; 47 ClosureFunction ffunc(fptr); 48 EXPECT_FALSE(!!ffunc); 49 50 // "empty std::function" initialization 51 EmptyFunction<Closure> empty; 52 ClosureFunction fwrapper(empty); 53 EXPECT_FALSE(!!fwrapper); 54 55 // inline callable initialization 56 int finline_value = 0; 57 ClosureFunction finline([&finline_value] { finline_value++; }); 58 EXPECT_TRUE(!!finline); 59 finline(); 60 EXPECT_EQ(1, finline_value); 61 finline(); 62 EXPECT_EQ(2, finline_value); 63 64 // heap callable initialization 65 int fheap_value = 0; 66 ClosureFunction fheap([&fheap_value, big = Big() ] { fheap_value++; }); 67 EXPECT_TRUE(!!fheap); 68 fheap(); 69 EXPECT_EQ(1, fheap_value); 70 fheap(); 71 EXPECT_EQ(2, fheap_value); 72 73 // move initialization of a nullptr 74 ClosureFunction fnull2(fbl::move(fnull)); 75 EXPECT_FALSE(!!fnull2); 76 77 // move initialization of an inline callable 78 ClosureFunction finline2(fbl::move(finline)); 79 EXPECT_TRUE(!!finline2); 80 EXPECT_FALSE(!!finline); 81 finline2(); 82 EXPECT_EQ(3, finline_value); 83 finline2(); 84 EXPECT_EQ(4, finline_value); 85 86 // move initialization of a heap callable 87 ClosureFunction fheap2(fbl::move(fheap)); 88 EXPECT_TRUE(!!fheap2); 89 EXPECT_FALSE(!!fheap); 90 fheap2(); 91 EXPECT_EQ(3, fheap_value); 92 fheap2(); 93 EXPECT_EQ(4, fheap_value); 94 95 // inline mutable lambda 96 int fmutinline_value = 0; 97 ClosureFunction fmutinline([&fmutinline_value, x = 1 ]() mutable { 98 x *= 2; 99 fmutinline_value = x; 100 }); 101 EXPECT_TRUE(!!fmutinline); 102 fmutinline(); 103 EXPECT_EQ(2, fmutinline_value); 104 fmutinline(); 105 EXPECT_EQ(4, fmutinline_value); 106 107 // heap-allocated mutable lambda 108 int fmutheap_value = 0; 109 ClosureFunction fmutheap([&fmutheap_value, big = Big(), x = 1 ]() mutable { 110 x *= 2; 111 fmutheap_value = x; 112 }); 113 EXPECT_TRUE(!!fmutheap); 114 fmutheap(); 115 EXPECT_EQ(2, fmutheap_value); 116 fmutheap(); 117 EXPECT_EQ(4, fmutheap_value); 118 119 // move assignment of non-null 120 ClosureFunction fnew([] {}); 121 fnew = fbl::move(finline2); 122 EXPECT_TRUE(!!fnew); 123 fnew(); 124 EXPECT_EQ(5, finline_value); 125 fnew(); 126 EXPECT_EQ(6, finline_value); 127 128 // move assignment of null 129 fnew = fbl::move(fnull); 130 EXPECT_FALSE(!!fnew); 131 132 // callable assignment with operator= 133 int fnew_value = 0; 134 fnew = [&fnew_value] { fnew_value++; }; 135 EXPECT_TRUE(!!fnew); 136 fnew(); 137 EXPECT_EQ(1, fnew_value); 138 fnew(); 139 EXPECT_EQ(2, fnew_value); 140 141 // callable assignment with SetTarget 142 fnew.SetTarget([&fnew_value] { fnew_value *= 2; }); 143 EXPECT_TRUE(!!fnew); 144 fnew(); 145 EXPECT_EQ(4, fnew_value); 146 fnew(); 147 EXPECT_EQ(8, fnew_value); 148 149 // nullptr assignment 150 fnew = nullptr; 151 EXPECT_FALSE(!!fnew); 152 153 // swap (currently null) 154 fnew.swap(fheap2); 155 EXPECT_TRUE(!!fnew); 156 EXPECT_FALSE(!!fheap); 157 fnew(); 158 EXPECT_EQ(5, fheap_value); 159 fnew(); 160 EXPECT_EQ(6, fheap_value); 161 162 // swap with self 163 fnew.swap(fnew); 164 EXPECT_TRUE(!!fnew); 165 fnew(); 166 EXPECT_EQ(7, fheap_value); 167 fnew(); 168 EXPECT_EQ(8, fheap_value); 169 170 // swap with non-null 171 fnew.swap(fmutinline); 172 EXPECT_TRUE(!!fmutinline); 173 EXPECT_TRUE(!!fnew); 174 fmutinline(); 175 EXPECT_EQ(9, fheap_value); 176 fmutinline(); 177 EXPECT_EQ(10, fheap_value); 178 fnew(); 179 EXPECT_EQ(8, fmutinline_value); 180 fnew(); 181 EXPECT_EQ(16, fmutinline_value); 182 183 // nullptr comparison operators 184 EXPECT_TRUE(fnull == nullptr); 185 EXPECT_FALSE(fnull != nullptr); 186 EXPECT_TRUE(nullptr == fnull); 187 EXPECT_FALSE(nullptr != fnull); 188 EXPECT_FALSE(fnew == nullptr); 189 EXPECT_TRUE(fnew != nullptr); 190 EXPECT_FALSE(nullptr == fnew); 191 EXPECT_TRUE(nullptr != fnew); 192 193 // null function pointer assignment 194 fnew = fptr; 195 EXPECT_FALSE(!!fnew); 196 197 // "empty std::function" assignment 198 fmutinline = empty; 199 EXPECT_FALSE(!!fmutinline); 200 201 // alloc checking constructor, inline 202 AllocChecker ac1; 203 int fcheck_value = 0; 204 ClosureFunction fcheckinline([&fcheck_value] { fcheck_value++; }, &ac1); 205 EXPECT_TRUE(!!fcheckinline); 206 EXPECT_TRUE(ac1.check()); 207 fcheckinline(); 208 EXPECT_EQ(1, fcheck_value); 209 210 // alloc checking set target, inline 211 AllocChecker ac2; 212 fcheckinline.SetTarget([&fcheck_value] { fcheck_value *= 3; }, &ac2); 213 EXPECT_TRUE(!!fcheckinline); 214 EXPECT_TRUE(ac2.check()); 215 fcheckinline(); 216 EXPECT_EQ(3, fcheck_value); 217 218 // alloc checking constructor, heap allocated 219 AllocChecker ac3; 220 ClosureFunction fcheckheap([&fcheck_value, big = Big() ] { fcheck_value++; }, &ac3); 221 EXPECT_TRUE(!!fcheckheap); 222 EXPECT_TRUE(ac3.check()); 223 fcheckheap(); 224 EXPECT_EQ(4, fcheck_value); 225 226 // alloc checking set target, heap allocated 227 AllocChecker ac4; 228 fcheckheap.SetTarget([&fcheck_value, big = Big() ] { fcheck_value *= 3; }, &ac4); 229 EXPECT_TRUE(!!fcheckheap); 230 EXPECT_TRUE(ac4.check()); 231 fcheckheap(); 232 EXPECT_EQ(12, fcheck_value); 233 234 END_TEST; 235} 236 237template <typename BinaryOpFunction> 238bool binary_op() { 239 BEGIN_TEST; 240 241 // default initialization 242 BinaryOpFunction fdefault; 243 EXPECT_FALSE(!!fdefault); 244 245 // nullptr initialization 246 BinaryOpFunction fnull(nullptr); 247 EXPECT_FALSE(!!fnull); 248 249 // null function pointer initialization 250 BinaryOp* fptr = nullptr; 251 BinaryOpFunction ffunc(fptr); 252 EXPECT_FALSE(!!ffunc); 253 254 // "empty std::function" initialization 255 EmptyFunction<BinaryOp> empty; 256 BinaryOpFunction fwrapper(empty); 257 EXPECT_FALSE(!!fwrapper); 258 259 // inline callable initialization 260 int finline_value = 0; 261 BinaryOpFunction finline([&finline_value](int a, int b) { 262 finline_value++; 263 return a + b; 264 }); 265 EXPECT_TRUE(!!finline); 266 EXPECT_EQ(10, finline(3, 7)); 267 EXPECT_EQ(1, finline_value); 268 EXPECT_EQ(10, finline(3, 7)); 269 EXPECT_EQ(2, finline_value); 270 271 // heap callable initialization 272 int fheap_value = 0; 273 BinaryOpFunction fheap([&fheap_value, big = Big() ](int a, int b) { 274 fheap_value++; 275 return a + b; 276 }); 277 EXPECT_TRUE(!!fheap); 278 EXPECT_EQ(10, fheap(3, 7)); 279 EXPECT_EQ(1, fheap_value); 280 EXPECT_EQ(10, fheap(3, 7)); 281 EXPECT_EQ(2, fheap_value); 282 283 // move initialization of a nullptr 284 BinaryOpFunction fnull2(fbl::move(fnull)); 285 EXPECT_FALSE(!!fnull2); 286 287 // move initialization of an inline callable 288 BinaryOpFunction finline2(fbl::move(finline)); 289 EXPECT_TRUE(!!finline2); 290 EXPECT_FALSE(!!finline); 291 EXPECT_EQ(10, finline2(3, 7)); 292 EXPECT_EQ(3, finline_value); 293 EXPECT_EQ(10, finline2(3, 7)); 294 EXPECT_EQ(4, finline_value); 295 296 // move initialization of a heap callable 297 BinaryOpFunction fheap2(fbl::move(fheap)); 298 EXPECT_TRUE(!!fheap2); 299 EXPECT_FALSE(!!fheap); 300 EXPECT_EQ(10, fheap2(3, 7)); 301 EXPECT_EQ(3, fheap_value); 302 EXPECT_EQ(10, fheap2(3, 7)); 303 EXPECT_EQ(4, fheap_value); 304 305 // inline mutable lambda 306 int fmutinline_value = 0; 307 BinaryOpFunction fmutinline([&fmutinline_value, x = 1 ](int a, int b) mutable { 308 x *= 2; 309 fmutinline_value = x; 310 return a + b; 311 }); 312 EXPECT_TRUE(!!fmutinline); 313 EXPECT_EQ(10, fmutinline(3, 7)); 314 EXPECT_EQ(2, fmutinline_value); 315 EXPECT_EQ(10, fmutinline(3, 7)); 316 EXPECT_EQ(4, fmutinline_value); 317 318 // heap-allocated mutable lambda 319 int fmutheap_value = 0; 320 BinaryOpFunction fmutheap([&fmutheap_value, big = Big(), x = 1 ](int a, int b) mutable { 321 x *= 2; 322 fmutheap_value = x; 323 return a + b; 324 }); 325 EXPECT_TRUE(!!fmutheap); 326 EXPECT_EQ(10, fmutheap(3, 7)); 327 EXPECT_EQ(2, fmutheap_value); 328 EXPECT_EQ(10, fmutheap(3, 7)); 329 EXPECT_EQ(4, fmutheap_value); 330 331 // move assignment of non-null 332 BinaryOpFunction fnew([](int a, int b) { return 0; }); 333 fnew = fbl::move(finline2); 334 EXPECT_TRUE(!!fnew); 335 EXPECT_EQ(10, fnew(3, 7)); 336 EXPECT_EQ(5, finline_value); 337 EXPECT_EQ(10, fnew(3, 7)); 338 EXPECT_EQ(6, finline_value); 339 340 // move assignment of null 341 fnew = fbl::move(fnull); 342 EXPECT_FALSE(!!fnew); 343 344 // callable assignment with operator= 345 int fnew_value = 0; 346 fnew = [&fnew_value](int a, int b) { 347 fnew_value++; 348 return a + b; 349 }; 350 EXPECT_TRUE(!!fnew); 351 EXPECT_EQ(10, fnew(3, 7)); 352 EXPECT_EQ(1, fnew_value); 353 EXPECT_EQ(10, fnew(3, 7)); 354 EXPECT_EQ(2, fnew_value); 355 356 // callable assignment with SetTarget 357 fnew.SetTarget([&fnew_value](int a, int b) { 358 fnew_value *= 2; 359 return a + b; 360 }); 361 EXPECT_TRUE(!!fnew); 362 EXPECT_EQ(10, fnew(3, 7)); 363 EXPECT_EQ(4, fnew_value); 364 EXPECT_EQ(10, fnew(3, 7)); 365 EXPECT_EQ(8, fnew_value); 366 367 // nullptr assignment 368 fnew = nullptr; 369 EXPECT_FALSE(!!fnew); 370 371 // swap (currently null) 372 fnew.swap(fheap2); 373 EXPECT_TRUE(!!fnew); 374 EXPECT_FALSE(!!fheap); 375 EXPECT_EQ(10, fnew(3, 7)); 376 EXPECT_EQ(5, fheap_value); 377 EXPECT_EQ(10, fnew(3, 7)); 378 EXPECT_EQ(6, fheap_value); 379 380 // swap with self 381 fnew.swap(fnew); 382 EXPECT_TRUE(!!fnew); 383 EXPECT_EQ(10, fnew(3, 7)); 384 EXPECT_EQ(7, fheap_value); 385 EXPECT_EQ(10, fnew(3, 7)); 386 EXPECT_EQ(8, fheap_value); 387 388 // swap with non-null 389 fnew.swap(fmutinline); 390 EXPECT_TRUE(!!fmutinline); 391 EXPECT_TRUE(!!fnew); 392 EXPECT_EQ(10, fmutinline(3, 7)); 393 EXPECT_EQ(9, fheap_value); 394 EXPECT_EQ(10, fmutinline(3, 7)); 395 EXPECT_EQ(10, fheap_value); 396 EXPECT_EQ(10, fnew(3, 7)); 397 EXPECT_EQ(8, fmutinline_value); 398 EXPECT_EQ(10, fnew(3, 7)); 399 EXPECT_EQ(16, fmutinline_value); 400 401 // nullptr comparison operators 402 EXPECT_TRUE(fnull == nullptr); 403 EXPECT_FALSE(fnull != nullptr); 404 EXPECT_TRUE(nullptr == fnull); 405 EXPECT_FALSE(nullptr != fnull); 406 EXPECT_FALSE(fnew == nullptr); 407 EXPECT_TRUE(fnew != nullptr); 408 EXPECT_FALSE(nullptr == fnew); 409 EXPECT_TRUE(nullptr != fnew); 410 411 // null function pointer assignment 412 fnew = fptr; 413 EXPECT_FALSE(!!fnew); 414 415 // "empty std::function" assignment 416 fmutinline = empty; 417 EXPECT_FALSE(!!fmutinline); 418 419 // alloc checking constructor, inline 420 AllocChecker ac1; 421 int fcheck_value = 0; 422 BinaryOpFunction fcheckinline([&fcheck_value](int a, int b) { 423 fcheck_value++; 424 return a + b; 425 }, 426 &ac1); 427 EXPECT_TRUE(!!fcheckinline); 428 EXPECT_TRUE(ac1.check()); 429 EXPECT_EQ(10, fcheckinline(3, 7)); 430 EXPECT_EQ(1, fcheck_value); 431 432 // alloc checking set target, inline 433 AllocChecker ac2; 434 fcheckinline.SetTarget([&fcheck_value](int a, int b) { 435 fcheck_value *= 3; 436 return a + b; 437 }, 438 &ac2); 439 EXPECT_TRUE(!!fcheckinline); 440 EXPECT_TRUE(ac2.check()); 441 EXPECT_EQ(10, fcheckinline(3, 7)); 442 EXPECT_EQ(3, fcheck_value); 443 444 // alloc checking constructor, heap allocated 445 AllocChecker ac3; 446 BinaryOpFunction fcheckheap([&fcheck_value, big = Big() ](int a, int b) { 447 fcheck_value++; 448 return a + b; 449 }, 450 &ac3); 451 EXPECT_TRUE(!!fcheckheap); 452 EXPECT_TRUE(ac3.check()); 453 EXPECT_EQ(10, fcheckheap(3, 7)); 454 EXPECT_EQ(4, fcheck_value); 455 456 // alloc checking set target, heap allocated 457 AllocChecker ac4; 458 fcheckheap.SetTarget([&fcheck_value, big = Big() ](int a, int b) { 459 fcheck_value *= 3; 460 return a + b; 461 }, 462 &ac4); 463 EXPECT_TRUE(!!fcheckheap); 464 EXPECT_TRUE(ac4.check()); 465 EXPECT_EQ(10, fcheckheap(3, 7)); 466 EXPECT_EQ(12, fcheck_value); 467 468 END_TEST; 469} 470 471bool sized_function_size_bounds() { 472 BEGIN_TEST; 473 474 auto empty = [] {}; 475 fbl::SizedFunction<Closure, sizeof(empty)> fempty(fbl::move(empty)); 476 static_assert(sizeof(fempty) >= sizeof(empty), "size bounds"); 477 478 auto small = [ x = 1, y = 2 ] { 479 (void)x; // suppress unused lambda capture warning 480 (void)y; 481 }; 482 fbl::SizedFunction<Closure, sizeof(small)> fsmall(fbl::move(small)); 483 static_assert(sizeof(fsmall) >= sizeof(small), "size bounds"); 484 fsmall = [] {}; 485 486 auto big = [ big = Big(), x = 1 ] { (void)x; }; 487 fbl::SizedFunction<Closure, sizeof(big)> fbig(fbl::move(big)); 488 static_assert(sizeof(fbig) >= sizeof(big), "size bounds"); 489 fbig = [ x = 1, y = 2 ] { 490 (void)x; 491 (void)y; 492 }; 493 fbig = [] {}; 494 495 // These statements do compile though the lambda will be copied to the heap 496 // when they exceed the inline size. 497 fempty = [ x = 1, y = 2 ] { 498 (void)x; 499 (void)y; 500 }; 501 fsmall = [ big = Big(), x = 1 ] { (void)x; }; 502 fbig = [ big = Big(), x = 1, y = 2 ] { 503 (void)x; 504 (void)y; 505 }; 506 507 END_TEST; 508} 509 510bool inline_function_size_bounds() { 511 BEGIN_TEST; 512 513 auto empty = [] {}; 514 fbl::InlineFunction<Closure, sizeof(empty)> fempty(fbl::move(empty)); 515 static_assert(sizeof(fempty) >= sizeof(empty), "size bounds"); 516 517 auto small = [ x = 1, y = 2 ] { 518 (void)x; // suppress unused lambda capture warning 519 (void)y; 520 }; 521 fbl::InlineFunction<Closure, sizeof(small)> fsmall(fbl::move(small)); 522 static_assert(sizeof(fsmall) >= sizeof(small), "size bounds"); 523 fsmall = [] {}; 524 525 auto big = [ big = Big(), x = 1 ] { (void)x; }; 526 fbl::InlineFunction<Closure, sizeof(big)> fbig(fbl::move(big)); 527 static_assert(sizeof(fbig) >= sizeof(big), "size bounds"); 528 fbig = [ x = 1, y = 2 ] { 529 (void)x; 530 (void)y; 531 }; 532 fbig = [] {}; 533 534// These statements do not compile because the lambdas are too big to fit. 535#if 0 536 fempty = [ x = 1, y = 2 ] { 537 (void)x; 538 (void)y; 539 }; 540 fsmall = [ big = Big(), x = 1 ] { (void)x; }; 541 fbig = [ big = Big(), x = 1, y = 2 ] { 542 (void)x; 543 (void)y; 544 }; 545#endif 546 547 END_TEST; 548} 549 550bool move_only_argument_and_result() { 551 BEGIN_TEST; 552 553 fbl::unique_ptr<int> arg(new int()); 554 fbl::Function<MoveOp> f([](fbl::unique_ptr<int> value) { 555 *value += 1; 556 return value; 557 }); 558 arg = f(fbl::move(arg)); 559 EXPECT_EQ(1, *arg); 560 arg = f(fbl::move(arg)); 561 EXPECT_EQ(2, *arg); 562 563 END_TEST; 564} 565 566void implicit_construction_helper(fbl::Closure closure) {} 567 568bool implicit_construction() { 569 BEGIN_TEST; 570 571 // ensure we can implicitly construct from nullptr 572 implicit_construction_helper(nullptr); 573 574 // ensure we can implicitly construct from a lambda 575 implicit_construction_helper([] {}); 576 577 END_TEST; 578} 579 580struct Obj { 581 void Call() { 582 calls++; 583 } 584 585 int AddOne(int x) { 586 calls++; 587 return x + 1; 588 } 589 590 int Sum(int a, int b, int c) { 591 calls++; 592 return a + b + c; 593 } 594 595 fbl::unique_ptr<int> AddAndReturn(fbl::unique_ptr<int> value) { 596 (*value)++; 597 return value; 598 } 599 600 uint32_t calls = 0; 601}; 602 603bool bind_member() { 604 BEGIN_TEST; 605 606 Obj obj; 607 auto move_only_value = fbl::make_unique<int>(4); 608 609 BindMember(&obj, &Obj::Call)(); 610 EXPECT_EQ(23, BindMember(&obj, &Obj::AddOne)(22)); 611 EXPECT_EQ(6, BindMember(&obj, &Obj::Sum)(1, 2, 3)); 612 move_only_value = BindMember(&obj, &Obj::AddAndReturn)(fbl::move(move_only_value)); 613 EXPECT_EQ(5, *move_only_value); 614 EXPECT_EQ(3, obj.calls); 615 616 END_TEST; 617} 618 619// Test the internal IsNull mechanism. 620struct Nullable { 621 bool is_null; 622 bool operator==(decltype(nullptr)) const { return is_null; } 623}; 624 625struct NotNullable {}; 626 627struct NonBoolNull { 628 void operator==(decltype(nullptr)) const {} 629}; 630 631bool null_check() { 632 BEGIN_TEST; 633 634 EXPECT_TRUE(fbl::internal::IsNull(nullptr)); 635 636 Nullable nf = {false}; 637 EXPECT_FALSE(fbl::internal::IsNull(nf)); 638 639 Nullable nt = {true}; 640 EXPECT_TRUE(fbl::internal::IsNull(nt)); 641 642 NotNullable nn; 643 EXPECT_FALSE(fbl::internal::IsNull(nn)); 644 645 NonBoolNull nbn; 646 EXPECT_FALSE(fbl::internal::IsNull(nbn)); 647 648 END_TEST; 649} 650 651// This is the code which is included in <function.h>. 652namespace example { 653using FoldFunction = fbl::Function<int(int value, int item)>; 654 655int FoldVector(const fbl::Vector<int>& in, int value, const FoldFunction& f) { 656 for (auto& item : in) { 657 value = f(value, item); 658 } 659 return value; 660} 661 662int SumItem(int value, int item) { 663 return value + item; 664} 665 666int Sum(const fbl::Vector<int>& in) { 667 // bind to a function pointer 668 FoldFunction sum(&SumItem); 669 return FoldVector(in, 0, sum); 670} 671 672int AlternatingSum(const fbl::Vector<int>& in) { 673 // bind to a lambda 674 int sign = 1; 675 FoldFunction alternating_sum([&sign](int value, int item) { 676 value += sign * item; 677 sign *= -1; 678 return value; 679 }); 680 return FoldVector(in, 0, alternating_sum); 681} 682 683class Accumulator { 684public: 685 void Add(int value) { 686 sum += value; 687 } 688 689 int sum = 0; 690}; 691 692void CountToTen(fbl::Function<void(int)> function) { 693 for (int i = 1; i <= 10; i++) { 694 function(i); 695 } 696} 697 698int SumToTen() { 699 Accumulator accum; 700 CountToTen(fbl::BindMember(&accum, &Accumulator::Add)); 701 return accum.sum; 702} 703 704} // namespace example 705 706bool example_code() { 707 BEGIN_TEST; 708 709 fbl::Vector<int> in; 710 for (int i = 0; i < 10; i++) { 711 fbl::AllocChecker ac; 712 in.push_back(i, &ac); 713 EXPECT_TRUE(ac.check()); 714 } 715 716 EXPECT_EQ(45, example::Sum(in)); 717 EXPECT_EQ(-5, example::AlternatingSum(in)); 718 EXPECT_EQ(55, example::SumToTen()); 719 720 END_TEST; 721} 722 723} // namespace 724 725BEGIN_TEST_CASE(function_tests) 726RUN_TEST((closure<fbl::Function<Closure>>)) 727RUN_TEST((binary_op<fbl::Function<BinaryOp>>)) 728RUN_TEST((closure<fbl::SizedFunction<Closure, 0u>>)) 729RUN_TEST((binary_op<fbl::SizedFunction<BinaryOp, 0u>>)) 730RUN_TEST((closure<fbl::SizedFunction<Closure, HugeCallableSize>>)) 731RUN_TEST((binary_op<fbl::SizedFunction<BinaryOp, HugeCallableSize>>)) 732RUN_TEST((closure<fbl::InlineFunction<Closure, HugeCallableSize>>)) 733RUN_TEST((binary_op<fbl::InlineFunction<BinaryOp, HugeCallableSize>>)) 734RUN_TEST(sized_function_size_bounds); 735RUN_TEST(inline_function_size_bounds); 736RUN_TEST(move_only_argument_and_result); 737RUN_TEST(implicit_construction); 738RUN_TEST(bind_member); 739RUN_TEST(null_check); 740RUN_TEST(example_code); 741END_TEST_CASE(function_tests) 742 743} // namespace tests 744} // namespace fbl 745