arch-arm: AArch64 trap check, arbitrary ECs/Imms
[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 * Authors: Gabe Black
40 * Giacomo Travaglini
41 */
42
43 #include <gtest/gtest.h>
44
45 #include <initializer_list>
46 #include <iostream>
47 #include <vector>
48
49 #include "base/fiber.hh"
50
51 /** This test is checking if the "started" member has its expected
52 * value before and after the fiber runs. In the test an empty fiber
53 * is used since we are just interested on the _started member and
54 * nothing more.
55 */
56 TEST(Fiber, Starting)
57 {
58 class StartingFiber : public Fiber
59 {
60 public:
61 StartingFiber(Fiber *link) : Fiber(link) {}
62 void main() { /** Do nothing */ }
63 };
64
65 StartingFiber fiber(Fiber::primaryFiber());
66
67 ASSERT_FALSE(fiber.started());
68
69 fiber.run();
70
71 ASSERT_TRUE(fiber.started());
72 }
73
74 class SwitchingFiber : public Fiber
75 {
76 public:
77 const char *name;
78 std::vector<Fiber *> next;
79
80 SwitchingFiber(const char *name, std::initializer_list<Fiber *> l);
81
82 void checkExpected();
83 void main();
84 };
85
86 extern SwitchingFiber a;
87 extern SwitchingFiber b;
88 extern SwitchingFiber c;
89
90 SwitchingFiber a("A", { &b, &a, Fiber::primaryFiber(), &b, &c });
91 SwitchingFiber b("B", { &a, &c });
92 SwitchingFiber c("C", { &a, Fiber::primaryFiber(), Fiber::primaryFiber() });
93
94 std::vector<SwitchingFiber *>::iterator expectedIt;
95 std::vector<SwitchingFiber *> expected({
96 &a, &b, &a, &a, /* main Fiber, */
97 &a, &b, &c, &a, &c,
98 /* main Fiber, */ &c, &c
99 });
100
101 SwitchingFiber::SwitchingFiber(
102 const char *name, std::initializer_list<Fiber *> l) :
103 name(name), next(l)
104 {}
105
106 void
107 SwitchingFiber::checkExpected()
108 {
109 ASSERT_NE(expectedIt, expected.end());
110 SwitchingFiber *e = *expectedIt++;
111 EXPECT_EQ(e, this) << "Expected " << e->name << ", got " << name;
112 }
113
114 void
115 SwitchingFiber::main()
116 {
117 checkExpected();
118 for (auto &n : next) {
119 n->run();
120 checkExpected();
121 }
122 }
123
124 TEST(Fiber, Switching)
125 {
126 expectedIt = expected.begin();
127
128 a.run();
129 EXPECT_EQ(expectedIt - expected.begin(), 4);
130
131 a.run();
132 EXPECT_EQ(expectedIt - expected.begin(), 9);
133
134 c.run();
135 EXPECT_EQ(expectedIt - expected.begin(), 10);
136
137 EXPECT_FALSE(a.finished());
138 EXPECT_FALSE(b.finished());
139 EXPECT_FALSE(c.finished());
140
141 c.run();
142 EXPECT_EQ(expected.end(), expectedIt) <<
143 "Didn't exactly use up the expected Fiber sequence";
144
145 EXPECT_TRUE(c.finished());
146 }
147
148 int currentIndex = 0;
149
150 class LinkedFiber : public Fiber
151 {
152 public:
153 const int index;
154 LinkedFiber(Fiber *link, int index) : Fiber(link), index(index) {}
155
156 void
157 main()
158 {
159 EXPECT_EQ(currentIndex, index);
160 currentIndex++;
161 }
162 };
163
164 TEST(Fiber, Linked)
165 {
166 currentIndex = 0;
167
168 LinkedFiber lf3(Fiber::primaryFiber(), 3);
169 LinkedFiber lf2(&lf3, 2);
170 LinkedFiber lf1(&lf2, 1);
171 LinkedFiber lf0(&lf1, 0);
172
173 lf0.run();
174
175 EXPECT_EQ(currentIndex, 4);
176 }