misc: Replace enable_if<>::type with enable_if_t<>.
[gem5.git] / src / base / fiber.test.cc
1 /*
2 * Copyright (c) 2019 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright 2018 Google, Inc.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions are
18 * met: redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer;
20 * redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution;
23 * neither the name of the copyright holders nor the names of its
24 * contributors may be used to endorse or promote products derived from
25 * this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 #include <gtest/gtest.h>
41
42 #include <initializer_list>
43 #include <iostream>
44 #include <vector>
45
46 #include "base/fiber.hh"
47
48 /** This test is checking if the "started" member has its expected
49 * value before and after the fiber runs. In the test an empty fiber
50 * is used since we are just interested on the _started member and
51 * nothing more.
52 */
53 TEST(Fiber, Starting)
54 {
55 class StartingFiber : public Fiber
56 {
57 public:
58 StartingFiber(Fiber *link) : Fiber(link) {}
59 void main() { /** Do nothing */ }
60 };
61
62 StartingFiber fiber(Fiber::primaryFiber());
63
64 ASSERT_FALSE(fiber.started());
65
66 fiber.run();
67
68 ASSERT_TRUE(fiber.started());
69 }
70
71 class SwitchingFiber : public Fiber
72 {
73 public:
74 const char *name;
75 std::vector<Fiber *> next;
76
77 SwitchingFiber(const char *name, std::initializer_list<Fiber *> l);
78
79 void checkExpected();
80 void main();
81 };
82
83 extern SwitchingFiber a;
84 extern SwitchingFiber b;
85 extern SwitchingFiber c;
86
87 SwitchingFiber a("A", { &b, &a, Fiber::primaryFiber(), &b, &c });
88 SwitchingFiber b("B", { &a, &c });
89 SwitchingFiber c("C", { &a, Fiber::primaryFiber(), Fiber::primaryFiber() });
90
91 std::vector<SwitchingFiber *>::iterator expectedIt;
92 std::vector<SwitchingFiber *> expected({
93 &a, &b, &a, &a, /* main Fiber, */
94 &a, &b, &c, &a, &c,
95 /* main Fiber, */ &c, &c
96 });
97
98 SwitchingFiber::SwitchingFiber(
99 const char *name, std::initializer_list<Fiber *> l) :
100 name(name), next(l)
101 {}
102
103 void
104 SwitchingFiber::checkExpected()
105 {
106 ASSERT_NE(expectedIt, expected.end());
107 SwitchingFiber *e = *expectedIt++;
108 EXPECT_EQ(e, this) << "Expected " << e->name << ", got " << name;
109 }
110
111 void
112 SwitchingFiber::main()
113 {
114 checkExpected();
115 for (auto &n : next) {
116 n->run();
117 checkExpected();
118 }
119 }
120
121 TEST(Fiber, Switching)
122 {
123 expectedIt = expected.begin();
124
125 a.run();
126 EXPECT_EQ(expectedIt - expected.begin(), 4);
127
128 a.run();
129 EXPECT_EQ(expectedIt - expected.begin(), 9);
130
131 c.run();
132 EXPECT_EQ(expectedIt - expected.begin(), 10);
133
134 EXPECT_FALSE(a.finished());
135 EXPECT_FALSE(b.finished());
136 EXPECT_FALSE(c.finished());
137
138 c.run();
139 EXPECT_EQ(expected.end(), expectedIt) <<
140 "Didn't exactly use up the expected Fiber sequence";
141
142 EXPECT_TRUE(c.finished());
143 }
144
145 int currentIndex = 0;
146
147 class LinkedFiber : public Fiber
148 {
149 public:
150 const int index;
151 LinkedFiber(Fiber *link, int index) : Fiber(link), index(index) {}
152
153 void
154 main()
155 {
156 EXPECT_EQ(currentIndex, index);
157 currentIndex++;
158 }
159 };
160
161 TEST(Fiber, Linked)
162 {
163 currentIndex = 0;
164
165 LinkedFiber lf3(Fiber::primaryFiber(), 3);
166 LinkedFiber lf2(&lf3, 2);
167 LinkedFiber lf1(&lf2, 1);
168 LinkedFiber lf0(&lf1, 0);
169
170 lf0.run();
171
172 EXPECT_EQ(currentIndex, 4);
173 }