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