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