blob: 0cbb5feea5b746ff5d5a958cf8691f0cfab1a83a [file] [log] [blame]
Parker Schuhe4a70d62017-12-27 20:10:20 -08001#ifndef _AOS_EVENTS_EVENT_LOOP_PARAM_TEST_H_
2#define _AOS_EVENTS_EVENT_LOOP_PARAM_TEST_H_
3
Brian Silverman4f4e0612020-08-12 19:54:41 -07004#include <initializer_list>
Austin Schuh5f1cc5c2019-12-01 18:01:11 -08005#include <string_view>
Neil Balch229001a2018-01-07 18:22:52 -08006#include <vector>
7
Alex Perrycb7da4b2019-08-28 19:35:56 -07008#include "aos/events/event_loop.h"
Brian Silverman4f4e0612020-08-12 19:54:41 -07009#include "aos/events/test_message_generated.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -070010#include "aos/flatbuffers.h"
11#include "aos/json_to_flatbuffer.h"
Parker Schuhe4a70d62017-12-27 20:10:20 -080012#include "gtest/gtest.h"
13
14namespace aos {
15namespace testing {
16
17class EventLoopTestFactory {
18 public:
Alex Perrycb7da4b2019-08-28 19:35:56 -070019 EventLoopTestFactory()
Brian Silverman77162972020-08-12 19:52:40 -070020 : flatbuffer_(JsonToFlatbuffer<Configuration>(R"config({
21 "channels": [
22 {
23 "name": "/aos",
24 "type": "aos.logging.LogMessageFbs"
25 },
26 {
27 "name": "/aos",
28 "type": "aos.timing.Report"
29 },
30 {
31 "name": "/test",
32 "type": "aos.TestMessage"
33 },
34 {
35 "name": "/test1",
36 "type": "aos.TestMessage"
37 },
38 {
39 "name": "/test2",
40 "type": "aos.TestMessage"
41 }
42 ]
43})config")) {}
Alex Perrycb7da4b2019-08-28 19:35:56 -070044
Parker Schuhe4a70d62017-12-27 20:10:20 -080045 virtual ~EventLoopTestFactory() {}
46
Austin Schuh44019f92019-05-19 19:58:27 -070047 // Makes a connected event loop.
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080048 virtual std::unique_ptr<EventLoop> Make(std::string_view name) = 0;
Austin Schuh44019f92019-05-19 19:58:27 -070049 // Makes a primary event loop. This is the one the tests will try to use for
50 // anything blocking.
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080051 virtual std::unique_ptr<EventLoop> MakePrimary(std::string_view name) = 0;
Austin Schuh44019f92019-05-19 19:58:27 -070052
53 // Runs the loops until they quit.
54 virtual void Run() = 0;
Austin Schuh52d325c2019-06-23 18:59:06 -070055
Austin Schuh9fe68f72019-08-10 19:32:03 -070056 // Quits the loops.
57 virtual void Exit() = 0;
58
Austin Schuh52d325c2019-06-23 18:59:06 -070059 // Advances time by sleeping. Can't be called from inside a loop.
60 virtual void SleepFor(::std::chrono::nanoseconds duration) = 0;
Alex Perrycb7da4b2019-08-28 19:35:56 -070061
Austin Schuhd54780b2020-10-03 16:26:02 -070062 // Sets the config to a config with a max size with an invalid alignment.
63 void InvalidChannelAlignment() {
64 flatbuffer_ = JsonToFlatbuffer<Configuration>(R"config({
65 "channels": [
66 {
67 "name": "/aos",
68 "type": "aos.logging.LogMessageFbs"
69 },
70 {
71 "name": "/aos",
72 "type": "aos.timing.Report"
73 },
74 {
75 "name": "/test",
76 "type": "aos.TestMessage",
77 "max_size": 13
78 },
79 {
80 "name": "/test1",
81 "type": "aos.TestMessage"
82 },
83 {
84 "name": "/test2",
85 "type": "aos.TestMessage"
86 }
87 ]
88})config");
89 }
90
Brian Silverman77162972020-08-12 19:52:40 -070091 void PinReads() {
92 static const std::string kJson = R"config({
93 "channels": [
94 {
95 "name": "/aos",
96 "type": "aos.logging.LogMessageFbs",
97 "read_method": "PIN",
98 "num_readers": 10
99 },
100 {
101 "name": "/aos",
102 "type": "aos.timing.Report",
103 "read_method": "PIN",
104 "num_readers": 10
105 },
106 {
107 "name": "/test",
108 "type": "aos.TestMessage",
109 "read_method": "PIN",
110 "num_readers": 10
111 },
112 {
113 "name": "/test1",
114 "type": "aos.TestMessage",
115 "read_method": "PIN",
116 "num_readers": 10
117 },
118 {
119 "name": "/test2",
120 "type": "aos.TestMessage",
121 "read_method": "PIN",
122 "num_readers": 10
123 }
124 ]
125})config";
126
127 flatbuffer_ = FlatbufferDetachedBuffer<Configuration>(
128 JsonToFlatbuffer(kJson, Configuration::MiniReflectTypeTable()));
129 }
130
Austin Schuh217a9782019-12-21 23:02:50 -0800131 void EnableNodes(std::string_view my_node) {
Brian Silverman77162972020-08-12 19:52:40 -0700132 static const std::string kJson = R"config({
Austin Schuh217a9782019-12-21 23:02:50 -0800133 "channels": [
134 {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700135 "name": "/me/aos",
Tyler Chatow67ddb032020-01-12 14:30:04 -0800136 "type": "aos.logging.LogMessageFbs",
137 "source_node": "me"
138 },
139 {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700140 "name": "/them/aos",
Tyler Chatow67ddb032020-01-12 14:30:04 -0800141 "type": "aos.logging.LogMessageFbs",
142 "source_node": "them"
143 },
144 {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700145 "name": "/me/aos",
146 "type": "aos.message_bridge.Timestamp",
147 "source_node": "me",
148 "destination_nodes": [
149 {
150 "name": "them"
151 }
152 ]
153 },
154 {
155 "name": "/them/aos",
156 "type": "aos.message_bridge.Timestamp",
157 "source_node": "them",
158 "destination_nodes": [
159 {
160 "name": "me"
161 }
162 ]
163 },
164 {
165 "name": "/me/aos",
166 "type": "aos.message_bridge.ServerStatistics",
167 "source_node": "me",
168 "frequency": 2
169 },
170 {
171 "name": "/them/aos",
172 "type": "aos.message_bridge.ServerStatistics",
173 "source_node": "them",
174 "frequency": 2
175 },
176 {
177 "name": "/me/aos",
178 "type": "aos.message_bridge.ClientStatistics",
179 "source_node": "me",
180 "frequency": 2
181 },
182 {
183 "name": "/them/aos",
184 "type": "aos.message_bridge.ClientStatistics",
185 "source_node": "them",
186 "frequency": 2
187 },
188 {
Austin Schuh217a9782019-12-21 23:02:50 -0800189 "name": "/aos",
190 "type": "aos.timing.Report",
191 "source_node": "me"
192 },
193 {
194 "name": "/test",
195 "type": "aos.TestMessage",
196 "source_node": "me"
197 },
198 {
199 "name": "/test1",
200 "type": "aos.TestMessage",
201 "source_node": "me"
202 },
203 {
204 "name": "/test2",
205 "type": "aos.TestMessage",
206 "source_node": "me"
207 }
208 ],
209 "nodes": [
210 {
Austin Schuh898f4972020-01-11 17:21:25 -0800211 "name": "me",
Austin Schuh217a9782019-12-21 23:02:50 -0800212 "hostname": "myhostname"
Austin Schuh898f4972020-01-11 17:21:25 -0800213 },
214 {
215 "name": "them",
216 "hostname": "themhostname"
Austin Schuh217a9782019-12-21 23:02:50 -0800217 }
Tyler Chatow67ddb032020-01-12 14:30:04 -0800218 ],
219 "maps": [
220 {
221 "match": {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700222 "name": "/aos*",
Tyler Chatow67ddb032020-01-12 14:30:04 -0800223 "source_node": "me"
224 },
225 "rename": {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700226 "name": "/me/aos"
Tyler Chatow67ddb032020-01-12 14:30:04 -0800227 }
228 },
229 {
230 "match": {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700231 "name": "/aos*",
Tyler Chatow67ddb032020-01-12 14:30:04 -0800232 "source_node": "them"
233 },
234 "rename": {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700235 "name": "/them/aos"
Tyler Chatow67ddb032020-01-12 14:30:04 -0800236 }
237 }
Austin Schuh217a9782019-12-21 23:02:50 -0800238 ]
239})config";
240
Austin Schuh4c3b9702020-08-30 11:34:55 -0700241 flatbuffer_ = configuration::MergeConfiguration(
242 FlatbufferDetachedBuffer<Configuration>(
243 JsonToFlatbuffer(kJson, Configuration::MiniReflectTypeTable())));
Austin Schuh217a9782019-12-21 23:02:50 -0800244
Austin Schuhac0771c2020-01-07 18:36:30 -0800245 my_node_ = configuration::GetNode(&flatbuffer_.message(), my_node);
Austin Schuh217a9782019-12-21 23:02:50 -0800246 }
247
Austin Schuhac0771c2020-01-07 18:36:30 -0800248 const Node *my_node() const { return my_node_; }
Austin Schuh217a9782019-12-21 23:02:50 -0800249
Alex Perrycb7da4b2019-08-28 19:35:56 -0700250 const Configuration *configuration() { return &flatbuffer_.message(); }
251
252 private:
253 FlatbufferDetachedBuffer<Configuration> flatbuffer_;
Austin Schuh217a9782019-12-21 23:02:50 -0800254
Austin Schuhac0771c2020-01-07 18:36:30 -0800255 const Node *my_node_ = nullptr;
Parker Schuhe4a70d62017-12-27 20:10:20 -0800256};
257
Austin Schuh6bae8252021-02-07 22:01:49 -0800258enum class DoTimingReports { kYes, kNo };
259
Brian Silverman4f4e0612020-08-12 19:54:41 -0700260class AbstractEventLoopTest
Brian Silverman77162972020-08-12 19:52:40 -0700261 : public ::testing::TestWithParam<
Austin Schuh6bae8252021-02-07 22:01:49 -0800262 std::tuple<std::function<EventLoopTestFactory *()>, ReadMethod,
263 DoTimingReports>> {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800264 public:
Brian Silverman4f4e0612020-08-12 19:54:41 -0700265 AbstractEventLoopTest() : factory_(std::get<0>(GetParam())()) {
Brian Silverman77162972020-08-12 19:52:40 -0700266 if (read_method() == ReadMethod::PIN) {
267 factory_->PinReads();
268 }
269 }
270
271 ReadMethod read_method() const { return std::get<1>(GetParam()); }
Austin Schuh6bae8252021-02-07 22:01:49 -0800272 DoTimingReports do_timing_reports() const { return std::get<2>(GetParam()); }
Parker Schuhe4a70d62017-12-27 20:10:20 -0800273
Brian Silverman4f4e0612020-08-12 19:54:41 -0700274 ::std::unique_ptr<EventLoop> Make(std::string_view name = "");
275
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800276 ::std::unique_ptr<EventLoop> MakePrimary(std::string_view name = "primary") {
277 ++event_loop_count_;
Austin Schuh6bae8252021-02-07 22:01:49 -0800278 auto result = factory_->MakePrimary(name);
279 if (do_timing_reports() == DoTimingReports::kNo) {
280 result->SkipTimingReport();
281 }
282 return result;
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800283 }
Austin Schuh44019f92019-05-19 19:58:27 -0700284
Austin Schuhd54780b2020-10-03 16:26:02 -0700285 void InvalidChannelAlignment() { factory_->InvalidChannelAlignment(); }
286
Austin Schuh217a9782019-12-21 23:02:50 -0800287 void EnableNodes(std::string_view my_node) { factory_->EnableNodes(my_node); }
288
Austin Schuh44019f92019-05-19 19:58:27 -0700289 void Run() { return factory_->Run(); }
Austin Schuh52d325c2019-06-23 18:59:06 -0700290
Austin Schuh9fe68f72019-08-10 19:32:03 -0700291 void Exit() { return factory_->Exit(); }
292
Austin Schuh52d325c2019-06-23 18:59:06 -0700293 void SleepFor(::std::chrono::nanoseconds duration) {
294 return factory_->SleepFor(duration);
295 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700296
Austin Schuh217a9782019-12-21 23:02:50 -0800297 const Configuration *configuration() { return factory_->configuration(); }
298
Austin Schuhac0771c2020-01-07 18:36:30 -0800299 const Node *my_node() const { return factory_->my_node(); }
Austin Schuh217a9782019-12-21 23:02:50 -0800300
Austin Schuh9fe68f72019-08-10 19:32:03 -0700301 // Ends the given event loop at the given time from now.
302 void EndEventLoop(EventLoop *loop, ::std::chrono::milliseconds duration) {
303 auto end_timer = loop->AddTimer([this]() { this->Exit(); });
Austin Schuh7d87b672019-12-01 20:23:49 -0800304 end_timer->Setup(loop->monotonic_now() + duration);
Austin Schuh39788ff2019-12-01 18:22:57 -0800305 end_timer->set_name("end");
Austin Schuh9fe68f72019-08-10 19:32:03 -0700306 }
307
Brian Silverman4f4e0612020-08-12 19:54:41 -0700308 // Verifies that the buffer_index values for all of the given objects are
309 // consistent.
310 void VerifyBuffers(
311 int number_buffers,
312 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>> fetchers,
313 std::vector<std::reference_wrapper<const Sender<TestMessage>>> senders);
314
Parker Schuhe4a70d62017-12-27 20:10:20 -0800315 private:
Brian Silverman77162972020-08-12 19:52:40 -0700316 const ::std::unique_ptr<EventLoopTestFactory> factory_;
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800317
318 int event_loop_count_ = 0;
Parker Schuhe4a70d62017-12-27 20:10:20 -0800319};
320
Brian Silverman4f4e0612020-08-12 19:54:41 -0700321using AbstractEventLoopDeathTest = AbstractEventLoopTest;
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700322
Parker Schuhe4a70d62017-12-27 20:10:20 -0800323} // namespace testing
324} // namespace aos
325
326#endif // _AOS_EVENTS_EVENT_LOOP_PARAM_TEST_H_