fiber.test.cc revision 13465:dee578a46d87
1/*
2 * Copyright 2018 Google, Inc.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met: redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer;
8 * redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution;
11 * neither the name of the copyright holders nor the names of its
12 * contributors may be used to endorse or promote products derived from
13 * this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 * Authors: Gabe Black
28 */
29
30#include <gtest/gtest.h>
31
32#include <initializer_list>
33#include <iostream>
34#include <vector>
35
36#include "base/fiber.hh"
37
38class TestFiber : public Fiber
39{
40  public:
41    const char *name;
42    std::vector<Fiber *> next;
43
44    TestFiber(const char *name, std::initializer_list<Fiber *> l);
45
46    void checkExpected();
47    void main();
48};
49
50extern TestFiber a;
51extern TestFiber b;
52extern TestFiber c;
53
54TestFiber a("A", { &b, &a, Fiber::primaryFiber(), &b, &c });
55TestFiber b("B", { &a, &c });
56TestFiber c("C", { &a, Fiber::primaryFiber(), Fiber::primaryFiber() });
57
58std::vector<TestFiber *>::iterator expectedIt;
59std::vector<TestFiber *> expected({
60    &a, &b, &a, &a, /* main Fiber, */
61    &a, &b, &c, &a, &c,
62    /* main Fiber, */ &c, &c
63});
64
65TestFiber::TestFiber(
66        const char *name, std::initializer_list<Fiber *> l) :
67    name(name), next(l)
68{}
69
70void
71TestFiber::checkExpected()
72{
73    ASSERT_NE(expectedIt, expected.end());
74    TestFiber *e = *expectedIt++;
75    EXPECT_EQ(e, this) << "Expected " << e->name << ", got " << name;
76}
77
78void
79TestFiber::main()
80{
81    checkExpected();
82    for (auto &n : next) {
83        n->run();
84        checkExpected();
85    }
86}
87
88TEST(Fiber, Switching)
89{
90    expectedIt = expected.begin();
91
92    a.run();
93    EXPECT_EQ(expectedIt - expected.begin(), 4);
94
95    a.run();
96    EXPECT_EQ(expectedIt - expected.begin(), 9);
97
98    c.run();
99    EXPECT_EQ(expectedIt - expected.begin(), 10);
100
101    EXPECT_FALSE(a.finished());
102    EXPECT_FALSE(b.finished());
103    EXPECT_FALSE(c.finished());
104
105    c.run();
106    EXPECT_EQ(expected.end(), expectedIt) <<
107        "Didn't exactly use up the expected Fiber sequence";
108
109    EXPECT_TRUE(c.finished());
110}
111
112int currentIndex = 0;
113
114class LinkedFiber : public Fiber
115{
116  public:
117    const int index;
118    LinkedFiber(Fiber *link, int index) : Fiber(link), index(index) {}
119
120    void
121    main()
122    {
123        EXPECT_EQ(currentIndex, index);
124        currentIndex++;
125    }
126};
127
128TEST(Fiber, Linked)
129{
130    currentIndex = 0;
131
132    LinkedFiber lf3(Fiber::primaryFiber(), 3);
133    LinkedFiber lf2(&lf3, 2);
134    LinkedFiber lf1(&lf2, 1);
135    LinkedFiber lf0(&lf1, 0);
136
137    lf0.run();
138
139    EXPECT_EQ(currentIndex, 4);
140}
141