1// Copyright 2016 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/auto_call.h>
6#include <fbl/type_support.h>
7#include <unittest/unittest.h>
8
9static volatile int test_func_count;
10
11__NO_INLINE static void test_func()
12{
13    test_func_count++;
14}
15
16static bool auto_call_test()
17{
18//    extern int foo();
19//    int a;
20//
21//    auto ac = MakeAutoCall([&](){ a = 1; });
22//    auto ac2 = MakeAutoCall(foo);
23//
24//    auto func = [&](){ a = 2; };
25//    AutoCall<decltype(bleh)> ac3(func);
26//    AutoCall<decltype(&foo)> ac4(&foo);
27//
28//    // abort the call
29//    ac2.cancel();
30
31    BEGIN_TEST;
32
33    // mark as volatile to make sure it generates code
34    volatile int a;
35
36    // call a lambda
37    {
38        a = 0;
39        auto ac = fbl::MakeAutoCall([&](){ a++; });
40        EXPECT_EQ(a, 0, "autocall hasn't run");
41    }
42    EXPECT_EQ(a, 1, "autocall has run");
43
44    {
45        a = 0;
46        auto ac = fbl::MakeAutoCall([&](){ a++; });
47        EXPECT_EQ(a, 0, "autocall hasn't run");
48
49        ac.cancel();
50        EXPECT_EQ(a, 0, "autocall still hasn't run");
51
52        ac.call();
53        EXPECT_EQ(a, 0, "autocall still hasn't run");
54    }
55    EXPECT_EQ(a, 0, "autocall still hasn't run");
56
57    {
58        a = 0;
59        auto ac = fbl::MakeAutoCall([&](){ a++; });
60        EXPECT_EQ(a, 0, "autocall hasn't run");
61
62        ac.call();
63        EXPECT_EQ(a, 1, "autocall should have run\n");
64
65        ac.cancel();
66        EXPECT_EQ(a, 1, "autocall ran only once\n");
67    }
68    EXPECT_EQ(a, 1, "autocall ran only once\n");
69
70    // call a regular function
71    {
72        test_func_count = 0;
73        auto ac = fbl::MakeAutoCall(&test_func);
74        EXPECT_EQ(test_func_count, 0, "autocall hasn't run");
75    }
76    EXPECT_EQ(test_func_count, 1, "autocall has run");
77
78    // move constructor
79    {
80        a = 0;
81        auto ac = fbl::MakeAutoCall([&](){ a++; });
82        auto ac2 = fbl::move(ac);
83        EXPECT_EQ(a, 0, "autocall hasn't run");
84    }
85    EXPECT_EQ(a, 1, "autocall has run once");
86
87    // move assignment
88    {
89        test_func_count = 0;
90        auto ac = fbl::MakeAutoCall(&test_func);
91        auto ac2 = fbl::MakeAutoCall(&test_func);
92        EXPECT_EQ(test_func_count, 0, "autocall hasn't run");
93        ac2 = fbl::move(ac);
94        EXPECT_EQ(test_func_count, 1, "autocall has run once");
95    }
96    EXPECT_EQ(test_func_count, 2, "autocall has run twice");
97    END_TEST;
98}
99
100BEGIN_TEST_CASE(auto_call_tests)
101RUN_NAMED_TEST("Auto call test", auto_call_test)
102END_TEST_CASE(auto_call_tests);
103