blob: d466a1e6f27fec59549d8c1478f02998eb9fcfd6 [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
21namespace aos {
22namespace testing {
23
24class EventLoopTestFactory {
25 public:
Alex Perrycb7da4b2019-08-28 19:35:56 -070026 EventLoopTestFactory()
Austin Schuha9df9ad2021-06-16 14:49:39 -070027 : flatbuffer_(configuration::AddSchema(
28 R"config({
Brian Silverman77162972020-08-12 19:52:40 -070029 "channels": [
30 {
31 "name": "/aos",
32 "type": "aos.logging.LogMessageFbs"
33 },
34 {
35 "name": "/aos",
36 "type": "aos.timing.Report"
37 },
38 {
39 "name": "/test",
milind945708b2021-07-03 13:30:15 -070040 "type": "aos.TestMessage",
41 "frequency": 800
Brian Silverman77162972020-08-12 19:52:40 -070042 },
43 {
44 "name": "/test1",
45 "type": "aos.TestMessage"
46 },
47 {
48 "name": "/test2",
49 "type": "aos.TestMessage"
Austin Schuhdda6db72023-06-21 17:02:34 -070050 },
51 {
52 "name": "/test3",
53 "type": "aos.TestMessage",
54 "channel_storage_duration": 10000000000
Brian Silverman77162972020-08-12 19:52:40 -070055 }
56 ]
Austin Schuha9df9ad2021-06-16 14:49:39 -070057})config",
58 {aos::FlatbufferSpan<reflection::Schema>(
59 logging::LogMessageFbsSchema()),
60 aos::FlatbufferSpan<reflection::Schema>(timing::ReportSchema()),
61 aos::FlatbufferSpan<reflection::Schema>(TestMessageSchema())})) {}
Alex Perrycb7da4b2019-08-28 19:35:56 -070062
Parker Schuhe4a70d62017-12-27 20:10:20 -080063 virtual ~EventLoopTestFactory() {}
64
Austin Schuh44019f92019-05-19 19:58:27 -070065 // Makes a connected event loop.
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080066 virtual std::unique_ptr<EventLoop> Make(std::string_view name) = 0;
Austin Schuh44019f92019-05-19 19:58:27 -070067 // Makes a primary event loop. This is the one the tests will try to use for
68 // anything blocking.
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080069 virtual std::unique_ptr<EventLoop> MakePrimary(std::string_view name) = 0;
Austin Schuh44019f92019-05-19 19:58:27 -070070
71 // Runs the loops until they quit.
72 virtual void Run() = 0;
Austin Schuh52d325c2019-06-23 18:59:06 -070073
Austin Schuh9fe68f72019-08-10 19:32:03 -070074 // Quits the loops.
75 virtual void Exit() = 0;
76
Austin Schuh52d325c2019-06-23 18:59:06 -070077 // Advances time by sleeping. Can't be called from inside a loop.
78 virtual void SleepFor(::std::chrono::nanoseconds duration) = 0;
Alex Perrycb7da4b2019-08-28 19:35:56 -070079
Austin Schuhd54780b2020-10-03 16:26:02 -070080 // Sets the config to a config with a max size with an invalid alignment.
81 void InvalidChannelAlignment() {
Austin Schuha9df9ad2021-06-16 14:49:39 -070082 flatbuffer_ = configuration::AddSchema(
83 R"config({
Austin Schuhd54780b2020-10-03 16:26:02 -070084 "channels": [
85 {
86 "name": "/aos",
87 "type": "aos.logging.LogMessageFbs"
88 },
89 {
90 "name": "/aos",
91 "type": "aos.timing.Report"
92 },
93 {
94 "name": "/test",
95 "type": "aos.TestMessage",
96 "max_size": 13
97 },
98 {
99 "name": "/test1",
100 "type": "aos.TestMessage"
101 },
102 {
103 "name": "/test2",
104 "type": "aos.TestMessage"
Austin Schuhdda6db72023-06-21 17:02:34 -0700105 },
106 {
107 "name": "/test3",
108 "type": "aos.TestMessage",
109 "channel_storage_duration": 10000000000
Austin Schuhd54780b2020-10-03 16:26:02 -0700110 }
111 ]
Austin Schuha9df9ad2021-06-16 14:49:39 -0700112})config",
113 {aos::FlatbufferSpan<reflection::Schema>(
114 logging::LogMessageFbsSchema()),
115 aos::FlatbufferSpan<reflection::Schema>(timing::ReportSchema()),
116 aos::FlatbufferSpan<reflection::Schema>(TestMessageSchema())});
Austin Schuhd54780b2020-10-03 16:26:02 -0700117 }
118
Brian Silverman77162972020-08-12 19:52:40 -0700119 void PinReads() {
120 static const std::string kJson = R"config({
121 "channels": [
122 {
123 "name": "/aos",
124 "type": "aos.logging.LogMessageFbs",
125 "read_method": "PIN",
126 "num_readers": 10
127 },
128 {
129 "name": "/aos",
130 "type": "aos.timing.Report",
131 "read_method": "PIN",
132 "num_readers": 10
133 },
134 {
135 "name": "/test",
136 "type": "aos.TestMessage",
137 "read_method": "PIN",
milind945708b2021-07-03 13:30:15 -0700138 "num_readers": 10,
139 "frequency": 800
Brian Silverman77162972020-08-12 19:52:40 -0700140 },
141 {
142 "name": "/test1",
143 "type": "aos.TestMessage",
144 "read_method": "PIN",
145 "num_readers": 10
146 },
147 {
148 "name": "/test2",
149 "type": "aos.TestMessage",
150 "read_method": "PIN",
151 "num_readers": 10
Austin Schuhdda6db72023-06-21 17:02:34 -0700152 },
153 {
154 "name": "/test3",
155 "type": "aos.TestMessage",
156 "read_method": "PIN",
157 "num_readers": 10,
158 "channel_storage_duration": 10000000000
Brian Silverman77162972020-08-12 19:52:40 -0700159 }
160 ]
161})config";
162
Austin Schuha9df9ad2021-06-16 14:49:39 -0700163 flatbuffer_ = configuration::AddSchema(
164 kJson, {aos::FlatbufferSpan<reflection::Schema>(
165 logging::LogMessageFbsSchema()),
166 aos::FlatbufferSpan<reflection::Schema>(timing::ReportSchema()),
167 aos::FlatbufferSpan<reflection::Schema>(TestMessageSchema())});
Brian Silverman77162972020-08-12 19:52:40 -0700168 }
169
Austin Schuh217a9782019-12-21 23:02:50 -0800170 void EnableNodes(std::string_view my_node) {
Brian Silverman77162972020-08-12 19:52:40 -0700171 static const std::string kJson = R"config({
Austin Schuh217a9782019-12-21 23:02:50 -0800172 "channels": [
173 {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700174 "name": "/me/aos",
Tyler Chatow67ddb032020-01-12 14:30:04 -0800175 "type": "aos.logging.LogMessageFbs",
176 "source_node": "me"
177 },
178 {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700179 "name": "/them/aos",
Tyler Chatow67ddb032020-01-12 14:30:04 -0800180 "type": "aos.logging.LogMessageFbs",
181 "source_node": "them"
182 },
183 {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700184 "name": "/me/aos",
185 "type": "aos.message_bridge.Timestamp",
186 "source_node": "me",
187 "destination_nodes": [
188 {
189 "name": "them"
190 }
191 ]
192 },
193 {
194 "name": "/them/aos",
195 "type": "aos.message_bridge.Timestamp",
196 "source_node": "them",
197 "destination_nodes": [
198 {
199 "name": "me"
200 }
201 ]
202 },
203 {
204 "name": "/me/aos",
205 "type": "aos.message_bridge.ServerStatistics",
206 "source_node": "me",
207 "frequency": 2
208 },
209 {
210 "name": "/them/aos",
211 "type": "aos.message_bridge.ServerStatistics",
212 "source_node": "them",
213 "frequency": 2
214 },
215 {
216 "name": "/me/aos",
217 "type": "aos.message_bridge.ClientStatistics",
218 "source_node": "me",
219 "frequency": 2
220 },
221 {
222 "name": "/them/aos",
223 "type": "aos.message_bridge.ClientStatistics",
224 "source_node": "them",
225 "frequency": 2
226 },
227 {
Austin Schuh217a9782019-12-21 23:02:50 -0800228 "name": "/aos",
229 "type": "aos.timing.Report",
230 "source_node": "me"
231 },
232 {
233 "name": "/test",
234 "type": "aos.TestMessage",
235 "source_node": "me"
236 },
237 {
238 "name": "/test1",
239 "type": "aos.TestMessage",
240 "source_node": "me"
241 },
242 {
243 "name": "/test2",
244 "type": "aos.TestMessage",
245 "source_node": "me"
Brian Silverman631b6262021-11-10 12:25:08 -0800246 },
247 {
248 "name": "/test_forward",
249 "type": "aos.TestMessage",
250 "source_node": "them",
251 "destination_nodes": [
252 {
253 "name": "me"
254 }
255 ]
256 },
257 {
258 "name": "/test_noforward",
259 "type": "aos.TestMessage",
260 "source_node": "them"
Austin Schuh217a9782019-12-21 23:02:50 -0800261 }
262 ],
263 "nodes": [
264 {
Austin Schuh898f4972020-01-11 17:21:25 -0800265 "name": "me",
Austin Schuh217a9782019-12-21 23:02:50 -0800266 "hostname": "myhostname"
Austin Schuh898f4972020-01-11 17:21:25 -0800267 },
268 {
269 "name": "them",
270 "hostname": "themhostname"
Austin Schuh217a9782019-12-21 23:02:50 -0800271 }
Tyler Chatow67ddb032020-01-12 14:30:04 -0800272 ],
273 "maps": [
274 {
275 "match": {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700276 "name": "/aos*",
Tyler Chatow67ddb032020-01-12 14:30:04 -0800277 "source_node": "me"
278 },
279 "rename": {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700280 "name": "/me/aos"
Tyler Chatow67ddb032020-01-12 14:30:04 -0800281 }
282 },
283 {
284 "match": {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700285 "name": "/aos*",
Tyler Chatow67ddb032020-01-12 14:30:04 -0800286 "source_node": "them"
287 },
288 "rename": {
Austin Schuh4c3b9702020-08-30 11:34:55 -0700289 "name": "/them/aos"
Tyler Chatow67ddb032020-01-12 14:30:04 -0800290 }
291 }
Austin Schuh217a9782019-12-21 23:02:50 -0800292 ]
293})config";
294
Austin Schuh4c3b9702020-08-30 11:34:55 -0700295 flatbuffer_ = configuration::MergeConfiguration(
Austin Schuha9df9ad2021-06-16 14:49:39 -0700296 configuration::MergeConfiguration(
297 aos::FlatbufferDetachedBuffer<Configuration>(
298 JsonToFlatbuffer<Configuration>(kJson))),
299 {aos::FlatbufferSpan<reflection::Schema>(
300 logging::LogMessageFbsSchema()),
301 aos::FlatbufferSpan<reflection::Schema>(timing::ReportSchema()),
302 aos::FlatbufferSpan<reflection::Schema>(TestMessageSchema()),
303 aos::FlatbufferSpan<reflection::Schema>(
304 message_bridge::ClientStatisticsSchema()),
305 aos::FlatbufferSpan<reflection::Schema>(
306 message_bridge::ServerStatisticsSchema()),
307 aos::FlatbufferSpan<reflection::Schema>(
308 message_bridge::TimestampSchema())});
Austin Schuh217a9782019-12-21 23:02:50 -0800309
Austin Schuhac0771c2020-01-07 18:36:30 -0800310 my_node_ = configuration::GetNode(&flatbuffer_.message(), my_node);
Austin Schuh217a9782019-12-21 23:02:50 -0800311 }
312
Austin Schuhac0771c2020-01-07 18:36:30 -0800313 const Node *my_node() const { return my_node_; }
Austin Schuh217a9782019-12-21 23:02:50 -0800314
Alex Perrycb7da4b2019-08-28 19:35:56 -0700315 const Configuration *configuration() { return &flatbuffer_.message(); }
316
317 private:
318 FlatbufferDetachedBuffer<Configuration> flatbuffer_;
Austin Schuh217a9782019-12-21 23:02:50 -0800319
Austin Schuhac0771c2020-01-07 18:36:30 -0800320 const Node *my_node_ = nullptr;
Parker Schuhe4a70d62017-12-27 20:10:20 -0800321};
322
Austin Schuh6bae8252021-02-07 22:01:49 -0800323enum class DoTimingReports { kYes, kNo };
324
Brian Silverman4f4e0612020-08-12 19:54:41 -0700325class AbstractEventLoopTest
Brian Silverman77162972020-08-12 19:52:40 -0700326 : public ::testing::TestWithParam<
Austin Schuh6bae8252021-02-07 22:01:49 -0800327 std::tuple<std::function<EventLoopTestFactory *()>, ReadMethod,
328 DoTimingReports>> {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800329 public:
Brian Silverman4f4e0612020-08-12 19:54:41 -0700330 AbstractEventLoopTest() : factory_(std::get<0>(GetParam())()) {
Brian Silverman77162972020-08-12 19:52:40 -0700331 if (read_method() == ReadMethod::PIN) {
332 factory_->PinReads();
333 }
334 }
335
336 ReadMethod read_method() const { return std::get<1>(GetParam()); }
Austin Schuh6bae8252021-02-07 22:01:49 -0800337 DoTimingReports do_timing_reports() const { return std::get<2>(GetParam()); }
Parker Schuhe4a70d62017-12-27 20:10:20 -0800338
Brian Silverman4f4e0612020-08-12 19:54:41 -0700339 ::std::unique_ptr<EventLoop> Make(std::string_view name = "");
340
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800341 ::std::unique_ptr<EventLoop> MakePrimary(std::string_view name = "primary") {
342 ++event_loop_count_;
Austin Schuh6bae8252021-02-07 22:01:49 -0800343 auto result = factory_->MakePrimary(name);
344 if (do_timing_reports() == DoTimingReports::kNo) {
345 result->SkipTimingReport();
346 }
347 return result;
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800348 }
Austin Schuh44019f92019-05-19 19:58:27 -0700349
Austin Schuhd54780b2020-10-03 16:26:02 -0700350 void InvalidChannelAlignment() { factory_->InvalidChannelAlignment(); }
351
Austin Schuh217a9782019-12-21 23:02:50 -0800352 void EnableNodes(std::string_view my_node) { factory_->EnableNodes(my_node); }
353
Austin Schuh44019f92019-05-19 19:58:27 -0700354 void Run() { return factory_->Run(); }
Austin Schuh52d325c2019-06-23 18:59:06 -0700355
Austin Schuh9fe68f72019-08-10 19:32:03 -0700356 void Exit() { return factory_->Exit(); }
357
Austin Schuh52d325c2019-06-23 18:59:06 -0700358 void SleepFor(::std::chrono::nanoseconds duration) {
359 return factory_->SleepFor(duration);
360 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700361
Austin Schuh217a9782019-12-21 23:02:50 -0800362 const Configuration *configuration() { return factory_->configuration(); }
363
Austin Schuhac0771c2020-01-07 18:36:30 -0800364 const Node *my_node() const { return factory_->my_node(); }
Austin Schuh217a9782019-12-21 23:02:50 -0800365
Austin Schuh9fe68f72019-08-10 19:32:03 -0700366 // Ends the given event loop at the given time from now.
367 void EndEventLoop(EventLoop *loop, ::std::chrono::milliseconds duration) {
368 auto end_timer = loop->AddTimer([this]() { this->Exit(); });
Philipp Schradera6712522023-07-05 20:25:11 -0700369 end_timer->Schedule(loop->monotonic_now() + duration);
Austin Schuh39788ff2019-12-01 18:22:57 -0800370 end_timer->set_name("end");
Austin Schuh9fe68f72019-08-10 19:32:03 -0700371 }
372
Brian Silverman4f4e0612020-08-12 19:54:41 -0700373 // Verifies that the buffer_index values for all of the given objects are
374 // consistent.
375 void VerifyBuffers(
376 int number_buffers,
377 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>> fetchers,
378 std::vector<std::reference_wrapper<const Sender<TestMessage>>> senders);
379
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -0700380 // Helper function for testing the sent too fast check using a PhasedLoop with
381 // an interval that sends exactly at the frequency of the channel
382 void TestSentTooFastCheckEdgeCase(
383 const std::function<RawSender::Error(int, int)> expected_err,
384 const bool send_twice_at_end);
385
Parker Schuhe4a70d62017-12-27 20:10:20 -0800386 private:
Brian Silverman77162972020-08-12 19:52:40 -0700387 const ::std::unique_ptr<EventLoopTestFactory> factory_;
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800388
389 int event_loop_count_ = 0;
Parker Schuhe4a70d62017-12-27 20:10:20 -0800390};
391
Brian Silverman4f4e0612020-08-12 19:54:41 -0700392using AbstractEventLoopDeathTest = AbstractEventLoopTest;
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700393
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -0700394// Returns the frequency of the /test TestMessage channel
395int TestChannelFrequency(EventLoop *event_loop);
396// Returns the queue size of the /test TestMessage channel
397int TestChannelQueueSize(EventLoop *event_loop);
398// Sends a test message with value 0 with the given sender
399RawSender::Error SendTestMessage(aos::Sender<TestMessage> &sender);
400
Parker Schuhe4a70d62017-12-27 20:10:20 -0800401} // namespace testing
402} // namespace aos
403
404#endif // _AOS_EVENTS_EVENT_LOOP_PARAM_TEST_H_