blob: f2b16c5e33ac86bfb34dd865cf6b2d1c314c13bb [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
Philipp Schrader790cb542023-07-05 21:06:52 -07008#include "gtest/gtest.h"
9
Alex Perrycb7da4b2019-08-28 19:35:56 -070010#include "aos/events/event_loop.h"
Brian Silverman4f4e0612020-08-12 19:54:41 -070011#include "aos/events/test_message_generated.h"
Austin Schuha9df9ad2021-06-16 14:49:39 -070012#include "aos/events/test_message_schema.h"
13#include "aos/events/timing_report_schema.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -070014#include "aos/flatbuffers.h"
15#include "aos/json_to_flatbuffer.h"
Austin Schuha9df9ad2021-06-16 14:49:39 -070016#include "aos/logging/log_message_schema.h"
17#include "aos/network/message_bridge_client_schema.h"
18#include "aos/network/message_bridge_server_schema.h"
19#include "aos/network/timestamp_schema.h"
Parker Schuhe4a70d62017-12-27 20:10:20 -080020
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -080021namespace aos::testing {
Parker Schuhe4a70d62017-12-27 20:10:20 -080022
23class EventLoopTestFactory {
24 public:
Alex Perrycb7da4b2019-08-28 19:35:56 -070025 EventLoopTestFactory()
Austin Schuha9df9ad2021-06-16 14:49:39 -070026 : flatbuffer_(configuration::AddSchema(
27 R"config({
Brian Silverman77162972020-08-12 19:52:40 -070028 "channels": [
29 {
30 "name": "/aos",
31 "type": "aos.logging.LogMessageFbs"
32 },
33 {
34 "name": "/aos",
35 "type": "aos.timing.Report"
36 },
37 {
38 "name": "/test",
milind945708b2021-07-03 13:30:15 -070039 "type": "aos.TestMessage",
40 "frequency": 800
Brian Silverman77162972020-08-12 19:52:40 -070041 },
42 {
43 "name": "/test1",
44 "type": "aos.TestMessage"
45 },
46 {
47 "name": "/test2",
48 "type": "aos.TestMessage"
Austin Schuhdda6db72023-06-21 17:02:34 -070049 },
50 {
51 "name": "/test3",
52 "type": "aos.TestMessage",
53 "channel_storage_duration": 10000000000
Brian Silverman77162972020-08-12 19:52:40 -070054 }
55 ]
Austin Schuha9df9ad2021-06-16 14:49:39 -070056})config",
57 {aos::FlatbufferSpan<reflection::Schema>(
58 logging::LogMessageFbsSchema()),
59 aos::FlatbufferSpan<reflection::Schema>(timing::ReportSchema()),
60 aos::FlatbufferSpan<reflection::Schema>(TestMessageSchema())})) {}
Alex Perrycb7da4b2019-08-28 19:35:56 -070061
Parker Schuhe4a70d62017-12-27 20:10:20 -080062 virtual ~EventLoopTestFactory() {}
63
Austin Schuh44019f92019-05-19 19:58:27 -070064 // Makes a connected event loop.
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080065 virtual std::unique_ptr<EventLoop> Make(std::string_view name) = 0;
Austin Schuh44019f92019-05-19 19:58:27 -070066 // Makes a primary event loop. This is the one the tests will try to use for
67 // anything blocking.
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080068 virtual std::unique_ptr<EventLoop> MakePrimary(std::string_view name) = 0;
Austin Schuh44019f92019-05-19 19:58:27 -070069
70 // Runs the loops until they quit.
71 virtual void Run() = 0;
Austin Schuh52d325c2019-06-23 18:59:06 -070072
Austin Schuh9fe68f72019-08-10 19:32:03 -070073 // Quits the loops.
74 virtual void Exit() = 0;
75
Austin Schuh52d325c2019-06-23 18:59:06 -070076 // Advances time by sleeping. Can't be called from inside a loop.
77 virtual void SleepFor(::std::chrono::nanoseconds duration) = 0;
Alex Perrycb7da4b2019-08-28 19:35:56 -070078
Austin Schuhd54780b2020-10-03 16:26:02 -070079 // Sets the config to a config with a max size with an invalid alignment.
80 void InvalidChannelAlignment() {
Austin Schuha9df9ad2021-06-16 14:49:39 -070081 flatbuffer_ = configuration::AddSchema(
82 R"config({
Austin Schuhd54780b2020-10-03 16:26:02 -070083 "channels": [
84 {
85 "name": "/aos",
86 "type": "aos.logging.LogMessageFbs"
87 },
88 {
89 "name": "/aos",
90 "type": "aos.timing.Report"
91 },
92 {
93 "name": "/test",
94 "type": "aos.TestMessage",
95 "max_size": 13
96 },
97 {
98 "name": "/test1",
99 "type": "aos.TestMessage"
100 },
101 {
102 "name": "/test2",
103 "type": "aos.TestMessage"
Austin Schuhdda6db72023-06-21 17:02:34 -0700104 },
105 {
106 "name": "/test3",
107 "type": "aos.TestMessage",
108 "channel_storage_duration": 10000000000
Austin Schuhd54780b2020-10-03 16:26:02 -0700109 }
110 ]
Austin Schuha9df9ad2021-06-16 14:49:39 -0700111})config",
112 {aos::FlatbufferSpan<reflection::Schema>(
113 logging::LogMessageFbsSchema()),
114 aos::FlatbufferSpan<reflection::Schema>(timing::ReportSchema()),
115 aos::FlatbufferSpan<reflection::Schema>(TestMessageSchema())});
Austin Schuhd54780b2020-10-03 16:26:02 -0700116 }
117
Brian Silverman77162972020-08-12 19:52:40 -0700118 void PinReads() {
119 static const std::string kJson = R"config({
120 "channels": [
121 {
122 "name": "/aos",
123 "type": "aos.logging.LogMessageFbs",
124 "read_method": "PIN",
125 "num_readers": 10
126 },
127 {
128 "name": "/aos",
129 "type": "aos.timing.Report",
130 "read_method": "PIN",
131 "num_readers": 10
132 },
133 {
134 "name": "/test",
135 "type": "aos.TestMessage",
136 "read_method": "PIN",
milind945708b2021-07-03 13:30:15 -0700137 "num_readers": 10,
138 "frequency": 800
Brian Silverman77162972020-08-12 19:52:40 -0700139 },
140 {
141 "name": "/test1",
142 "type": "aos.TestMessage",
143 "read_method": "PIN",
144 "num_readers": 10
145 },
146 {
147 "name": "/test2",
148 "type": "aos.TestMessage",
149 "read_method": "PIN",
150 "num_readers": 10
Austin Schuhdda6db72023-06-21 17:02:34 -0700151 },
152 {
153 "name": "/test3",
154 "type": "aos.TestMessage",
155 "read_method": "PIN",
156 "num_readers": 10,
157 "channel_storage_duration": 10000000000
Brian Silverman77162972020-08-12 19:52:40 -0700158 }
159 ]
160})config";
161
Austin Schuha9df9ad2021-06-16 14:49:39 -0700162 flatbuffer_ = configuration::AddSchema(
163 kJson, {aos::FlatbufferSpan<reflection::Schema>(
164 logging::LogMessageFbsSchema()),
165 aos::FlatbufferSpan<reflection::Schema>(timing::ReportSchema()),
166 aos::FlatbufferSpan<reflection::Schema>(TestMessageSchema())});
Brian Silverman77162972020-08-12 19:52:40 -0700167 }
168
Austin Schuh217a9782019-12-21 23:02:50 -0800169 void EnableNodes(std::string_view my_node) {
Brian Silverman77162972020-08-12 19:52:40 -0700170 static const std::string kJson = R"config({
Austin Schuh217a9782019-12-21 23:02:50 -0800171 "channels": [
172 {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700173 "name": "/me/aos",
Tyler Chatow67ddb032020-01-12 14:30:04 -0800174 "type": "aos.logging.LogMessageFbs",
175 "source_node": "me"
176 },
177 {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700178 "name": "/them/aos",
Tyler Chatow67ddb032020-01-12 14:30:04 -0800179 "type": "aos.logging.LogMessageFbs",
180 "source_node": "them"
181 },
182 {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700183 "name": "/me/aos",
184 "type": "aos.message_bridge.Timestamp",
185 "source_node": "me",
186 "destination_nodes": [
187 {
188 "name": "them"
189 }
190 ]
191 },
192 {
193 "name": "/them/aos",
194 "type": "aos.message_bridge.Timestamp",
195 "source_node": "them",
196 "destination_nodes": [
197 {
198 "name": "me"
199 }
200 ]
201 },
202 {
203 "name": "/me/aos",
204 "type": "aos.message_bridge.ServerStatistics",
205 "source_node": "me",
206 "frequency": 2
207 },
208 {
209 "name": "/them/aos",
210 "type": "aos.message_bridge.ServerStatistics",
211 "source_node": "them",
212 "frequency": 2
213 },
214 {
215 "name": "/me/aos",
216 "type": "aos.message_bridge.ClientStatistics",
217 "source_node": "me",
218 "frequency": 2
219 },
220 {
221 "name": "/them/aos",
222 "type": "aos.message_bridge.ClientStatistics",
223 "source_node": "them",
224 "frequency": 2
225 },
226 {
Austin Schuh217a9782019-12-21 23:02:50 -0800227 "name": "/aos",
228 "type": "aos.timing.Report",
229 "source_node": "me"
230 },
231 {
232 "name": "/test",
233 "type": "aos.TestMessage",
234 "source_node": "me"
235 },
236 {
237 "name": "/test1",
238 "type": "aos.TestMessage",
239 "source_node": "me"
240 },
241 {
242 "name": "/test2",
243 "type": "aos.TestMessage",
244 "source_node": "me"
Brian Silverman631b6262021-11-10 12:25:08 -0800245 },
246 {
247 "name": "/test_forward",
248 "type": "aos.TestMessage",
249 "source_node": "them",
250 "destination_nodes": [
251 {
252 "name": "me"
253 }
254 ]
255 },
256 {
257 "name": "/test_noforward",
258 "type": "aos.TestMessage",
259 "source_node": "them"
Austin Schuh217a9782019-12-21 23:02:50 -0800260 }
261 ],
262 "nodes": [
263 {
Austin Schuh898f4972020-01-11 17:21:25 -0800264 "name": "me",
Austin Schuh217a9782019-12-21 23:02:50 -0800265 "hostname": "myhostname"
Austin Schuh898f4972020-01-11 17:21:25 -0800266 },
267 {
268 "name": "them",
269 "hostname": "themhostname"
Austin Schuh217a9782019-12-21 23:02:50 -0800270 }
Tyler Chatow67ddb032020-01-12 14:30:04 -0800271 ],
272 "maps": [
273 {
274 "match": {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700275 "name": "/aos*",
Tyler Chatow67ddb032020-01-12 14:30:04 -0800276 "source_node": "me"
277 },
278 "rename": {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700279 "name": "/me/aos"
Tyler Chatow67ddb032020-01-12 14:30:04 -0800280 }
281 },
282 {
283 "match": {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700284 "name": "/aos*",
Tyler Chatow67ddb032020-01-12 14:30:04 -0800285 "source_node": "them"
286 },
287 "rename": {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700288 "name": "/them/aos"
Tyler Chatow67ddb032020-01-12 14:30:04 -0800289 }
290 }
Austin Schuh217a9782019-12-21 23:02:50 -0800291 ]
292})config";
293
Austin Schuh4c3b9702020-08-30 11:34:55 -0700294 flatbuffer_ = configuration::MergeConfiguration(
Austin Schuha9df9ad2021-06-16 14:49:39 -0700295 configuration::MergeConfiguration(
296 aos::FlatbufferDetachedBuffer<Configuration>(
297 JsonToFlatbuffer<Configuration>(kJson))),
298 {aos::FlatbufferSpan<reflection::Schema>(
299 logging::LogMessageFbsSchema()),
300 aos::FlatbufferSpan<reflection::Schema>(timing::ReportSchema()),
301 aos::FlatbufferSpan<reflection::Schema>(TestMessageSchema()),
302 aos::FlatbufferSpan<reflection::Schema>(
303 message_bridge::ClientStatisticsSchema()),
304 aos::FlatbufferSpan<reflection::Schema>(
305 message_bridge::ServerStatisticsSchema()),
306 aos::FlatbufferSpan<reflection::Schema>(
307 message_bridge::TimestampSchema())});
Austin Schuh217a9782019-12-21 23:02:50 -0800308
Austin Schuhac0771c2020-01-07 18:36:30 -0800309 my_node_ = configuration::GetNode(&flatbuffer_.message(), my_node);
Austin Schuh217a9782019-12-21 23:02:50 -0800310 }
311
Austin Schuhac0771c2020-01-07 18:36:30 -0800312 const Node *my_node() const { return my_node_; }
Austin Schuh217a9782019-12-21 23:02:50 -0800313
Alex Perrycb7da4b2019-08-28 19:35:56 -0700314 const Configuration *configuration() { return &flatbuffer_.message(); }
315
316 private:
317 FlatbufferDetachedBuffer<Configuration> flatbuffer_;
Austin Schuh217a9782019-12-21 23:02:50 -0800318
Austin Schuhac0771c2020-01-07 18:36:30 -0800319 const Node *my_node_ = nullptr;
Parker Schuhe4a70d62017-12-27 20:10:20 -0800320};
321
Austin Schuh6bae8252021-02-07 22:01:49 -0800322enum class DoTimingReports { kYes, kNo };
323
Brian Silverman4f4e0612020-08-12 19:54:41 -0700324class AbstractEventLoopTest
Brian Silverman77162972020-08-12 19:52:40 -0700325 : public ::testing::TestWithParam<
Austin Schuh6bae8252021-02-07 22:01:49 -0800326 std::tuple<std::function<EventLoopTestFactory *()>, ReadMethod,
327 DoTimingReports>> {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800328 public:
Brian Silverman4f4e0612020-08-12 19:54:41 -0700329 AbstractEventLoopTest() : factory_(std::get<0>(GetParam())()) {
Brian Silverman77162972020-08-12 19:52:40 -0700330 if (read_method() == ReadMethod::PIN) {
331 factory_->PinReads();
332 }
333 }
334
335 ReadMethod read_method() const { return std::get<1>(GetParam()); }
Austin Schuh6bae8252021-02-07 22:01:49 -0800336 DoTimingReports do_timing_reports() const { return std::get<2>(GetParam()); }
Parker Schuhe4a70d62017-12-27 20:10:20 -0800337
Brian Silverman4f4e0612020-08-12 19:54:41 -0700338 ::std::unique_ptr<EventLoop> Make(std::string_view name = "");
339
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800340 ::std::unique_ptr<EventLoop> MakePrimary(std::string_view name = "primary") {
341 ++event_loop_count_;
Austin Schuh6bae8252021-02-07 22:01:49 -0800342 auto result = factory_->MakePrimary(name);
343 if (do_timing_reports() == DoTimingReports::kNo) {
344 result->SkipTimingReport();
345 }
346 return result;
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800347 }
Austin Schuh44019f92019-05-19 19:58:27 -0700348
Austin Schuhd54780b2020-10-03 16:26:02 -0700349 void InvalidChannelAlignment() { factory_->InvalidChannelAlignment(); }
350
Austin Schuh217a9782019-12-21 23:02:50 -0800351 void EnableNodes(std::string_view my_node) { factory_->EnableNodes(my_node); }
352
Austin Schuh44019f92019-05-19 19:58:27 -0700353 void Run() { return factory_->Run(); }
Austin Schuh52d325c2019-06-23 18:59:06 -0700354
Austin Schuh9fe68f72019-08-10 19:32:03 -0700355 void Exit() { return factory_->Exit(); }
356
Austin Schuh52d325c2019-06-23 18:59:06 -0700357 void SleepFor(::std::chrono::nanoseconds duration) {
358 return factory_->SleepFor(duration);
359 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700360
Austin Schuh217a9782019-12-21 23:02:50 -0800361 const Configuration *configuration() { return factory_->configuration(); }
362
Austin Schuhac0771c2020-01-07 18:36:30 -0800363 const Node *my_node() const { return factory_->my_node(); }
Austin Schuh217a9782019-12-21 23:02:50 -0800364
Austin Schuh9fe68f72019-08-10 19:32:03 -0700365 // Ends the given event loop at the given time from now.
366 void EndEventLoop(EventLoop *loop, ::std::chrono::milliseconds duration) {
367 auto end_timer = loop->AddTimer([this]() { this->Exit(); });
Philipp Schradera6712522023-07-05 20:25:11 -0700368 end_timer->Schedule(loop->monotonic_now() + duration);
Austin Schuh39788ff2019-12-01 18:22:57 -0800369 end_timer->set_name("end");
Austin Schuh9fe68f72019-08-10 19:32:03 -0700370 }
371
Brian Silverman4f4e0612020-08-12 19:54:41 -0700372 // Verifies that the buffer_index values for all of the given objects are
373 // consistent.
374 void VerifyBuffers(
375 int number_buffers,
376 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>> fetchers,
377 std::vector<std::reference_wrapper<const Sender<TestMessage>>> senders);
378
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -0700379 // Helper function for testing the sent too fast check using a PhasedLoop with
380 // an interval that sends exactly at the frequency of the channel
381 void TestSentTooFastCheckEdgeCase(
382 const std::function<RawSender::Error(int, int)> expected_err,
383 const bool send_twice_at_end);
384
Parker Schuhe4a70d62017-12-27 20:10:20 -0800385 private:
Brian Silverman77162972020-08-12 19:52:40 -0700386 const ::std::unique_ptr<EventLoopTestFactory> factory_;
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800387
388 int event_loop_count_ = 0;
Parker Schuhe4a70d62017-12-27 20:10:20 -0800389};
390
Brian Silverman4f4e0612020-08-12 19:54:41 -0700391using AbstractEventLoopDeathTest = AbstractEventLoopTest;
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700392
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -0700393// Returns the frequency of the /test TestMessage channel
394int TestChannelFrequency(EventLoop *event_loop);
395// Returns the queue size of the /test TestMessage channel
396int TestChannelQueueSize(EventLoop *event_loop);
397// Sends a test message with value 0 with the given sender
398RawSender::Error SendTestMessage(aos::Sender<TestMessage> &sender);
399
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -0800400} // namespace aos::testing
Parker Schuhe4a70d62017-12-27 20:10:20 -0800401
402#endif // _AOS_EVENTS_EVENT_LOOP_PARAM_TEST_H_