blob: bbba5b7b2a50e0387ac3f8cdd94c8ea7930fbba3 [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.
James Kuszmaul9f998082024-05-23 15:37:35 -070071 virtual Result<void> Run() = 0;
72
73 virtual std::unique_ptr<ExitHandle> MakeExitHandle() = 0;
Austin Schuh52d325c2019-06-23 18:59:06 -070074
Austin Schuh9fe68f72019-08-10 19:32:03 -070075 // Quits the loops.
76 virtual void Exit() = 0;
77
Austin Schuh52d325c2019-06-23 18:59:06 -070078 // Advances time by sleeping. Can't be called from inside a loop.
79 virtual void SleepFor(::std::chrono::nanoseconds duration) = 0;
Alex Perrycb7da4b2019-08-28 19:35:56 -070080
Austin Schuhd54780b2020-10-03 16:26:02 -070081 // Sets the config to a config with a max size with an invalid alignment.
82 void InvalidChannelAlignment() {
Austin Schuha9df9ad2021-06-16 14:49:39 -070083 flatbuffer_ = configuration::AddSchema(
84 R"config({
Austin Schuhd54780b2020-10-03 16:26:02 -070085 "channels": [
86 {
87 "name": "/aos",
88 "type": "aos.logging.LogMessageFbs"
89 },
90 {
91 "name": "/aos",
92 "type": "aos.timing.Report"
93 },
94 {
95 "name": "/test",
96 "type": "aos.TestMessage",
97 "max_size": 13
98 },
99 {
100 "name": "/test1",
101 "type": "aos.TestMessage"
102 },
103 {
104 "name": "/test2",
105 "type": "aos.TestMessage"
Austin Schuhdda6db72023-06-21 17:02:34 -0700106 },
107 {
108 "name": "/test3",
109 "type": "aos.TestMessage",
110 "channel_storage_duration": 10000000000
Austin Schuhd54780b2020-10-03 16:26:02 -0700111 }
112 ]
Austin Schuha9df9ad2021-06-16 14:49:39 -0700113})config",
114 {aos::FlatbufferSpan<reflection::Schema>(
115 logging::LogMessageFbsSchema()),
116 aos::FlatbufferSpan<reflection::Schema>(timing::ReportSchema()),
117 aos::FlatbufferSpan<reflection::Schema>(TestMessageSchema())});
Austin Schuhd54780b2020-10-03 16:26:02 -0700118 }
119
Brian Silverman77162972020-08-12 19:52:40 -0700120 void PinReads() {
121 static const std::string kJson = R"config({
122 "channels": [
123 {
124 "name": "/aos",
125 "type": "aos.logging.LogMessageFbs",
126 "read_method": "PIN",
127 "num_readers": 10
128 },
129 {
130 "name": "/aos",
131 "type": "aos.timing.Report",
132 "read_method": "PIN",
133 "num_readers": 10
134 },
135 {
136 "name": "/test",
137 "type": "aos.TestMessage",
138 "read_method": "PIN",
milind945708b2021-07-03 13:30:15 -0700139 "num_readers": 10,
140 "frequency": 800
Brian Silverman77162972020-08-12 19:52:40 -0700141 },
142 {
143 "name": "/test1",
144 "type": "aos.TestMessage",
145 "read_method": "PIN",
146 "num_readers": 10
147 },
148 {
149 "name": "/test2",
150 "type": "aos.TestMessage",
151 "read_method": "PIN",
152 "num_readers": 10
Austin Schuhdda6db72023-06-21 17:02:34 -0700153 },
154 {
155 "name": "/test3",
156 "type": "aos.TestMessage",
157 "read_method": "PIN",
158 "num_readers": 10,
159 "channel_storage_duration": 10000000000
Brian Silverman77162972020-08-12 19:52:40 -0700160 }
161 ]
162})config";
163
Austin Schuha9df9ad2021-06-16 14:49:39 -0700164 flatbuffer_ = configuration::AddSchema(
165 kJson, {aos::FlatbufferSpan<reflection::Schema>(
166 logging::LogMessageFbsSchema()),
167 aos::FlatbufferSpan<reflection::Schema>(timing::ReportSchema()),
168 aos::FlatbufferSpan<reflection::Schema>(TestMessageSchema())});
Brian Silverman77162972020-08-12 19:52:40 -0700169 }
170
Austin Schuh217a9782019-12-21 23:02:50 -0800171 void EnableNodes(std::string_view my_node) {
Brian Silverman77162972020-08-12 19:52:40 -0700172 static const std::string kJson = R"config({
Austin Schuh217a9782019-12-21 23:02:50 -0800173 "channels": [
174 {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700175 "name": "/me/aos",
Tyler Chatow67ddb032020-01-12 14:30:04 -0800176 "type": "aos.logging.LogMessageFbs",
177 "source_node": "me"
178 },
179 {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700180 "name": "/them/aos",
Tyler Chatow67ddb032020-01-12 14:30:04 -0800181 "type": "aos.logging.LogMessageFbs",
182 "source_node": "them"
183 },
184 {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700185 "name": "/me/aos",
186 "type": "aos.message_bridge.Timestamp",
187 "source_node": "me",
188 "destination_nodes": [
189 {
190 "name": "them"
191 }
192 ]
193 },
194 {
195 "name": "/them/aos",
196 "type": "aos.message_bridge.Timestamp",
197 "source_node": "them",
198 "destination_nodes": [
199 {
200 "name": "me"
201 }
202 ]
203 },
204 {
205 "name": "/me/aos",
206 "type": "aos.message_bridge.ServerStatistics",
207 "source_node": "me",
208 "frequency": 2
209 },
210 {
211 "name": "/them/aos",
212 "type": "aos.message_bridge.ServerStatistics",
213 "source_node": "them",
214 "frequency": 2
215 },
216 {
217 "name": "/me/aos",
218 "type": "aos.message_bridge.ClientStatistics",
219 "source_node": "me",
220 "frequency": 2
221 },
222 {
223 "name": "/them/aos",
224 "type": "aos.message_bridge.ClientStatistics",
225 "source_node": "them",
226 "frequency": 2
227 },
228 {
Austin Schuh217a9782019-12-21 23:02:50 -0800229 "name": "/aos",
230 "type": "aos.timing.Report",
231 "source_node": "me"
232 },
233 {
234 "name": "/test",
235 "type": "aos.TestMessage",
236 "source_node": "me"
237 },
238 {
239 "name": "/test1",
240 "type": "aos.TestMessage",
241 "source_node": "me"
242 },
243 {
244 "name": "/test2",
245 "type": "aos.TestMessage",
246 "source_node": "me"
Brian Silverman631b6262021-11-10 12:25:08 -0800247 },
248 {
249 "name": "/test_forward",
250 "type": "aos.TestMessage",
251 "source_node": "them",
252 "destination_nodes": [
253 {
254 "name": "me"
255 }
256 ]
257 },
258 {
259 "name": "/test_noforward",
260 "type": "aos.TestMessage",
261 "source_node": "them"
Austin Schuh217a9782019-12-21 23:02:50 -0800262 }
263 ],
264 "nodes": [
265 {
Austin Schuh898f4972020-01-11 17:21:25 -0800266 "name": "me",
Austin Schuh217a9782019-12-21 23:02:50 -0800267 "hostname": "myhostname"
Austin Schuh898f4972020-01-11 17:21:25 -0800268 },
269 {
270 "name": "them",
271 "hostname": "themhostname"
Austin Schuh217a9782019-12-21 23:02:50 -0800272 }
Tyler Chatow67ddb032020-01-12 14:30:04 -0800273 ],
274 "maps": [
275 {
276 "match": {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700277 "name": "/aos*",
Tyler Chatow67ddb032020-01-12 14:30:04 -0800278 "source_node": "me"
279 },
280 "rename": {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700281 "name": "/me/aos"
Tyler Chatow67ddb032020-01-12 14:30:04 -0800282 }
283 },
284 {
285 "match": {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700286 "name": "/aos*",
Tyler Chatow67ddb032020-01-12 14:30:04 -0800287 "source_node": "them"
288 },
289 "rename": {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700290 "name": "/them/aos"
Tyler Chatow67ddb032020-01-12 14:30:04 -0800291 }
292 }
Austin Schuh217a9782019-12-21 23:02:50 -0800293 ]
294})config";
295
Austin Schuh4c3b9702020-08-30 11:34:55 -0700296 flatbuffer_ = configuration::MergeConfiguration(
Austin Schuha9df9ad2021-06-16 14:49:39 -0700297 configuration::MergeConfiguration(
298 aos::FlatbufferDetachedBuffer<Configuration>(
299 JsonToFlatbuffer<Configuration>(kJson))),
300 {aos::FlatbufferSpan<reflection::Schema>(
301 logging::LogMessageFbsSchema()),
302 aos::FlatbufferSpan<reflection::Schema>(timing::ReportSchema()),
303 aos::FlatbufferSpan<reflection::Schema>(TestMessageSchema()),
304 aos::FlatbufferSpan<reflection::Schema>(
305 message_bridge::ClientStatisticsSchema()),
306 aos::FlatbufferSpan<reflection::Schema>(
307 message_bridge::ServerStatisticsSchema()),
308 aos::FlatbufferSpan<reflection::Schema>(
309 message_bridge::TimestampSchema())});
Austin Schuh217a9782019-12-21 23:02:50 -0800310
Austin Schuhac0771c2020-01-07 18:36:30 -0800311 my_node_ = configuration::GetNode(&flatbuffer_.message(), my_node);
Austin Schuh217a9782019-12-21 23:02:50 -0800312 }
313
Austin Schuhac0771c2020-01-07 18:36:30 -0800314 const Node *my_node() const { return my_node_; }
Austin Schuh217a9782019-12-21 23:02:50 -0800315
Alex Perrycb7da4b2019-08-28 19:35:56 -0700316 const Configuration *configuration() { return &flatbuffer_.message(); }
317
318 private:
319 FlatbufferDetachedBuffer<Configuration> flatbuffer_;
Austin Schuh217a9782019-12-21 23:02:50 -0800320
Austin Schuhac0771c2020-01-07 18:36:30 -0800321 const Node *my_node_ = nullptr;
Parker Schuhe4a70d62017-12-27 20:10:20 -0800322};
323
Austin Schuh6bae8252021-02-07 22:01:49 -0800324enum class DoTimingReports { kYes, kNo };
325
Brian Silverman4f4e0612020-08-12 19:54:41 -0700326class AbstractEventLoopTest
Brian Silverman77162972020-08-12 19:52:40 -0700327 : public ::testing::TestWithParam<
Austin Schuh6bae8252021-02-07 22:01:49 -0800328 std::tuple<std::function<EventLoopTestFactory *()>, ReadMethod,
329 DoTimingReports>> {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800330 public:
Brian Silverman4f4e0612020-08-12 19:54:41 -0700331 AbstractEventLoopTest() : factory_(std::get<0>(GetParam())()) {
Brian Silverman77162972020-08-12 19:52:40 -0700332 if (read_method() == ReadMethod::PIN) {
333 factory_->PinReads();
334 }
335 }
336
337 ReadMethod read_method() const { return std::get<1>(GetParam()); }
Austin Schuh6bae8252021-02-07 22:01:49 -0800338 DoTimingReports do_timing_reports() const { return std::get<2>(GetParam()); }
Parker Schuhe4a70d62017-12-27 20:10:20 -0800339
Brian Silverman4f4e0612020-08-12 19:54:41 -0700340 ::std::unique_ptr<EventLoop> Make(std::string_view name = "");
341
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800342 ::std::unique_ptr<EventLoop> MakePrimary(std::string_view name = "primary") {
343 ++event_loop_count_;
Austin Schuh6bae8252021-02-07 22:01:49 -0800344 auto result = factory_->MakePrimary(name);
345 if (do_timing_reports() == DoTimingReports::kNo) {
346 result->SkipTimingReport();
347 }
348 return result;
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800349 }
Austin Schuh44019f92019-05-19 19:58:27 -0700350
Austin Schuhd54780b2020-10-03 16:26:02 -0700351 void InvalidChannelAlignment() { factory_->InvalidChannelAlignment(); }
352
Austin Schuh217a9782019-12-21 23:02:50 -0800353 void EnableNodes(std::string_view my_node) { factory_->EnableNodes(my_node); }
354
James Kuszmaul9f998082024-05-23 15:37:35 -0700355 Result<void> Run() { return factory_->Run(); }
356
357 std::unique_ptr<ExitHandle> MakeExitHandle() {
358 return factory_->MakeExitHandle();
359 }
Austin Schuh52d325c2019-06-23 18:59:06 -0700360
Austin Schuh9fe68f72019-08-10 19:32:03 -0700361 void Exit() { return factory_->Exit(); }
362
Austin Schuh52d325c2019-06-23 18:59:06 -0700363 void SleepFor(::std::chrono::nanoseconds duration) {
364 return factory_->SleepFor(duration);
365 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700366
Austin Schuh217a9782019-12-21 23:02:50 -0800367 const Configuration *configuration() { return factory_->configuration(); }
368
Austin Schuhac0771c2020-01-07 18:36:30 -0800369 const Node *my_node() const { return factory_->my_node(); }
Austin Schuh217a9782019-12-21 23:02:50 -0800370
Austin Schuh9fe68f72019-08-10 19:32:03 -0700371 // Ends the given event loop at the given time from now.
372 void EndEventLoop(EventLoop *loop, ::std::chrono::milliseconds duration) {
373 auto end_timer = loop->AddTimer([this]() { this->Exit(); });
Philipp Schradera6712522023-07-05 20:25:11 -0700374 end_timer->Schedule(loop->monotonic_now() + duration);
Austin Schuh39788ff2019-12-01 18:22:57 -0800375 end_timer->set_name("end");
Austin Schuh9fe68f72019-08-10 19:32:03 -0700376 }
377
Brian Silverman4f4e0612020-08-12 19:54:41 -0700378 // Verifies that the buffer_index values for all of the given objects are
379 // consistent.
380 void VerifyBuffers(
381 int number_buffers,
382 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>> fetchers,
383 std::vector<std::reference_wrapper<const Sender<TestMessage>>> senders);
384
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -0700385 // Helper function for testing the sent too fast check using a PhasedLoop with
386 // an interval that sends exactly at the frequency of the channel
387 void TestSentTooFastCheckEdgeCase(
388 const std::function<RawSender::Error(int, int)> expected_err,
389 const bool send_twice_at_end);
390
Parker Schuhe4a70d62017-12-27 20:10:20 -0800391 private:
Brian Silverman77162972020-08-12 19:52:40 -0700392 const ::std::unique_ptr<EventLoopTestFactory> factory_;
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800393
394 int event_loop_count_ = 0;
Parker Schuhe4a70d62017-12-27 20:10:20 -0800395};
396
Brian Silverman4f4e0612020-08-12 19:54:41 -0700397using AbstractEventLoopDeathTest = AbstractEventLoopTest;
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700398
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -0700399// Returns the frequency of the /test TestMessage channel
400int TestChannelFrequency(EventLoop *event_loop);
401// Returns the queue size of the /test TestMessage channel
402int TestChannelQueueSize(EventLoop *event_loop);
403// Sends a test message with value 0 with the given sender
404RawSender::Error SendTestMessage(aos::Sender<TestMessage> &sender);
405
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -0800406} // namespace aos::testing
Parker Schuhe4a70d62017-12-27 20:10:20 -0800407
408#endif // _AOS_EVENTS_EVENT_LOOP_PARAM_TEST_H_