blob: 4885f5c1fd915a67edce35a2a782fbe97ccdf9c2 [file] [log] [blame]
Alex Perrycb7da4b2019-08-28 19:35:56 -07001#include "aos/events/event_loop_param_test.h"
Parker Schuhe4a70d62017-12-27 20:10:20 -08002
Austin Schuh52d325c2019-06-23 18:59:06 -07003#include <chrono>
Brian Silverman4f4e0612020-08-12 19:54:41 -07004#include <unordered_map>
5#include <unordered_set>
Austin Schuh52d325c2019-06-23 18:59:06 -07006
Philipp Schrader790cb542023-07-05 21:06:52 -07007#include "glog/logging.h"
8#include "gmock/gmock.h"
9#include "gtest/gtest.h"
10
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -070011#include "aos/events/test_message_generated.h"
James Kuszmaulb1c11052023-11-06 13:20:53 -080012#include "aos/events/test_message_static.h"
Austin Schuh54cf95f2019-11-29 13:14:18 -080013#include "aos/flatbuffer_merge.h"
Austin Schuhad9e5eb2021-11-19 20:33:55 -080014#include "aos/logging/log_message_generated.h"
15#include "aos/logging/logging.h"
Austin Schuhcc6070c2020-10-10 20:25:56 -070016#include "aos/realtime.h"
Austin Schuh9fe68f72019-08-10 19:32:03 -070017
Stephan Pleinesf63bde82024-01-13 15:59:33 -080018namespace aos::testing {
Austin Schuh52d325c2019-06-23 18:59:06 -070019namespace {
20namespace chrono = ::std::chrono;
21} // namespace
Parker Schuhe4a70d62017-12-27 20:10:20 -080022
Brian Silverman4f4e0612020-08-12 19:54:41 -070023::std::unique_ptr<EventLoop> AbstractEventLoopTest::Make(
24 std::string_view name) {
25 std::string name_copy(name);
26 if (name == "") {
27 name_copy = "loop";
28 name_copy += std::to_string(event_loop_count_);
29 }
30 ++event_loop_count_;
Austin Schuh6bae8252021-02-07 22:01:49 -080031 auto result = factory_->Make(name_copy);
32 if (do_timing_reports() == DoTimingReports::kNo) {
33 result->SkipTimingReport();
34 }
35 return result;
Brian Silverman4f4e0612020-08-12 19:54:41 -070036}
37
38void AbstractEventLoopTest::VerifyBuffers(
39 int number_buffers,
40 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>> fetchers,
41 std::vector<std::reference_wrapper<const Sender<TestMessage>>> senders) {
42 // The buffers which are in a sender.
43 std::unordered_set<int> in_sender;
44 for (const Sender<TestMessage> &sender : senders) {
45 const int this_buffer = sender.buffer_index();
46 CHECK_GE(this_buffer, 0);
47 CHECK_LT(this_buffer, number_buffers);
48 CHECK(in_sender.insert(this_buffer).second) << ": " << this_buffer;
49 }
50
51 if (read_method() != ReadMethod::PIN) {
52 // If we're not using PIN, we can't really verify anything about what
53 // buffers the fetchers have.
54 return;
55 }
56
57 // Mapping from TestMessage::value to buffer index.
58 std::unordered_map<int, int> fetcher_values;
59 for (const Fetcher<TestMessage> &fetcher : fetchers) {
60 if (!fetcher.get()) {
61 continue;
62 }
63 const int this_buffer = fetcher.context().buffer_index;
64 CHECK_GE(this_buffer, 0);
65 CHECK_LT(this_buffer, number_buffers);
66 CHECK(in_sender.count(this_buffer) == 0) << ": " << this_buffer;
67 const auto insert_result = fetcher_values.insert(
68 std::make_pair(fetcher.get()->value(), this_buffer));
69 if (!insert_result.second) {
70 CHECK_EQ(this_buffer, insert_result.first->second);
71 }
72 }
73}
74
Austin Schuh6b6dfa52019-06-12 20:16:20 -070075// Tests that watcher can receive messages from a sender.
Parker Schuhe4a70d62017-12-27 20:10:20 -080076// Also tests that OnRun() works.
77TEST_P(AbstractEventLoopTest, Basic) {
78 auto loop1 = Make();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070079 auto loop2 = MakePrimary();
80
Alex Perrycb7da4b2019-08-28 19:35:56 -070081 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
Austin Schuh6b6dfa52019-06-12 20:16:20 -070082
83 bool happened = false;
84
85 loop2->OnRun([&]() {
86 happened = true;
87
Alex Perrycb7da4b2019-08-28 19:35:56 -070088 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
89 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
90 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -070091 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -070092 });
93
94 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070095 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -070096 this->Exit();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070097 });
98
99 EXPECT_FALSE(happened);
100 Run();
101 EXPECT_TRUE(happened);
102}
103
James Kuszmaulb1c11052023-11-06 13:20:53 -0800104// Tests that watcher can receive messages from a static sender.
105// This confirms that the "static" flatbuffer API works with the EventLoop
106// senders.
107TEST_P(AbstractEventLoopTest, BasicStatic) {
108 auto loop1 = Make();
109 auto loop2 = MakePrimary();
110
111 aos::Sender<TestMessageStatic> sender =
112 loop1->MakeSender<TestMessageStatic>("/test");
113
114 bool happened = false;
115
116 loop2->OnRun([&]() {
117 happened = true;
118
119 aos::Sender<TestMessageStatic>::StaticBuilder msg =
120 sender.MakeStaticBuilder();
James Kuszmauldde65632023-12-07 16:12:26 -0800121 msg->set_value(200);
James Kuszmaulb1c11052023-11-06 13:20:53 -0800122 CHECK(msg.builder()->Verify());
123 msg.CheckOk(msg.Send());
124 });
125
126 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
127 EXPECT_EQ(message.value(), 200);
128 this->Exit();
129 });
130
131 EXPECT_FALSE(happened);
132 Run();
133 EXPECT_TRUE(happened);
134}
135
James Kuszmauld4b4f1d2024-03-13 15:57:35 -0700136// Tests that a static sender's Builder object can be moved safely.
137TEST_P(AbstractEventLoopTest, StaticBuilderMoveConstructor) {
138 auto loop1 = MakePrimary();
139
140 aos::Sender<TestMessageStatic> sender =
141 loop1->MakeSender<TestMessageStatic>("/test");
142 aos::Fetcher<TestMessage> fetcher = loop1->MakeFetcher<TestMessage>("/test");
143 std::optional<aos::Sender<TestMessageStatic>::StaticBuilder> moved_to_builder;
144 {
145 aos::Sender<TestMessageStatic>::StaticBuilder moved_from_builder =
146 sender.MakeStaticBuilder();
147 moved_to_builder.emplace(std::move(moved_from_builder));
148 }
149
150 loop1->OnRun([this, &moved_to_builder]() {
151 moved_to_builder.value()->set_value(200);
152 CHECK(moved_to_builder.value().builder()->Verify());
153 moved_to_builder.value().CheckOk(moved_to_builder.value().Send());
154 this->Exit();
155 });
156
157 ASSERT_FALSE(fetcher.Fetch());
158 Run();
159 ASSERT_TRUE(fetcher.Fetch());
160 EXPECT_EQ(200, fetcher->value());
161}
162
Brian Silverman341b57e2020-06-23 16:23:18 -0700163// Tests that watcher can receive messages from a sender, sent via SendDetached.
164TEST_P(AbstractEventLoopTest, BasicSendDetached) {
165 auto loop1 = Make();
166 auto loop2 = MakePrimary();
167
168 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
169
170 FlatbufferDetachedBuffer<TestMessage> detached =
171 flatbuffers::DetachedBuffer();
172 {
173 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
174 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
175 builder.add_value(100);
176 detached = msg.Detach(builder.Finish());
177 }
178 detached = flatbuffers::DetachedBuffer();
179 {
180 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
181 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
182 builder.add_value(200);
183 detached = msg.Detach(builder.Finish());
184 }
milind1f1dca32021-07-03 13:50:07 -0700185 sender.CheckOk(sender.SendDetached(std::move(detached)));
Brian Silverman341b57e2020-06-23 16:23:18 -0700186
187 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
188 ASSERT_TRUE(fetcher.Fetch());
189 EXPECT_EQ(fetcher->value(), 200);
190}
191
Alexei Strots7cb6e0c2024-02-19 21:24:21 -0800192// Tests that fetcher can receive messages from a sender, sent via SendJson.
193TEST_P(AbstractEventLoopTest, BasicSendJson) {
194 auto loop1 = Make();
195 auto loop2 = MakePrimary();
196
197 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
198 sender.CheckOk(sender.SendJson(R"json({"value":201})json"));
199
200 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
201 ASSERT_TRUE(fetcher.Fetch());
202 EXPECT_EQ(fetcher->value(), 201);
203}
204
205// Tests that invalid JSON isn't sent.
206TEST_P(AbstractEventLoopDeathTest, InvalidSendJson) {
207 auto loop1 = Make();
208 auto loop2 = MakePrimary();
209
210 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
211 EXPECT_DEATH({ sender.CheckOk(sender.SendJson(R"json({"val)json")); },
212 "Invalid JSON");
213}
214
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800215// Verifies that a no-arg watcher will not have a data pointer.
216TEST_P(AbstractEventLoopTest, NoArgNoData) {
217 auto loop1 = Make();
218 auto loop2 = MakePrimary();
219
220 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
221
222 bool happened = false;
223
224 loop2->OnRun([&]() {
225 happened = true;
226
227 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
228 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -0700229 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800230 });
231
232 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
233 EXPECT_GT(loop2->context().size, 0u);
234 EXPECT_EQ(nullptr, loop2->context().data);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700235 EXPECT_EQ(-1, loop2->context().buffer_index);
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800236 this->Exit();
237 });
238
239 EXPECT_FALSE(happened);
240 Run();
241 EXPECT_TRUE(happened);
242}
243
Brian Silverman454bc112020-03-05 14:21:25 -0800244// Tests that no-arg watcher can receive messages from a sender.
245// Also tests that OnRun() works.
246TEST_P(AbstractEventLoopTest, BasicNoArg) {
247 auto loop1 = Make();
248 auto loop2 = MakePrimary();
249
250 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
251
252 bool happened = false;
253
254 loop2->OnRun([&]() {
255 happened = true;
256
257 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
258 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
259 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700260 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -0800261 });
262
263 aos::Fetcher<TestMessage> fetcher = loop2->MakeFetcher<TestMessage>("/test");
264 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
265 ASSERT_TRUE(fetcher.Fetch());
266 EXPECT_EQ(fetcher->value(), 200);
267 this->Exit();
268 });
269
270 EXPECT_FALSE(happened);
271 Run();
272 EXPECT_TRUE(happened);
273}
274
275// Tests that a watcher can be created with an std::function.
276TEST_P(AbstractEventLoopTest, BasicFunction) {
277 auto loop1 = Make();
278 auto loop2 = MakePrimary();
279
280 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
281
282 bool happened = false;
283
284 loop2->OnRun([&]() {
285 happened = true;
286
287 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
288 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
289 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700290 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -0800291 });
292
293 loop2->MakeWatcher("/test", std::function<void(const TestMessage &)>(
294 [&](const TestMessage &message) {
295 EXPECT_EQ(message.value(), 200);
296 this->Exit();
297 }));
298
299 EXPECT_FALSE(happened);
300 Run();
301 EXPECT_TRUE(happened);
302}
303
Brian Silverman0fc69932020-01-24 21:54:02 -0800304// Tests that watcher can receive messages from two senders.
305// Also tests that OnRun() works.
306TEST_P(AbstractEventLoopTest, BasicTwoSenders) {
307 auto loop1 = Make();
308 auto loop2 = MakePrimary();
309
310 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
311 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
312
313 bool happened = false;
314
315 loop2->OnRun([&]() {
316 happened = true;
317
318 {
319 aos::Sender<TestMessage>::Builder msg = sender1.MakeBuilder();
320 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
321 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700322 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman0fc69932020-01-24 21:54:02 -0800323 }
324 {
325 aos::Sender<TestMessage>::Builder msg = sender2.MakeBuilder();
326 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
327 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700328 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman0fc69932020-01-24 21:54:02 -0800329 }
330 });
331
332 int messages_received = 0;
333 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
334 EXPECT_EQ(message.value(), 200);
335 this->Exit();
336 ++messages_received;
337 });
338
339 EXPECT_FALSE(happened);
340 Run();
341 EXPECT_TRUE(happened);
342 EXPECT_EQ(messages_received, 2);
343}
344
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700345// Tests that a fetcher can fetch from a sender.
346// Also tests that OnRun() works.
347TEST_P(AbstractEventLoopTest, FetchWithoutRun) {
348 auto loop1 = Make();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800349 auto loop2 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -0700350 auto loop3 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800351
352 auto sender = loop1->MakeSender<TestMessage>("/test");
353
354 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
355
Austin Schuhbbce72d2019-05-26 15:11:46 -0700356 EXPECT_FALSE(fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -0800357 EXPECT_EQ(fetcher.get(), nullptr);
358
Austin Schuhad154822019-12-27 15:45:13 -0800359 EXPECT_EQ(fetcher.context().monotonic_event_time, monotonic_clock::min_time);
360 EXPECT_EQ(fetcher.context().monotonic_remote_time, monotonic_clock::min_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -0700361 EXPECT_EQ(fetcher.context().monotonic_remote_transmit_time,
362 monotonic_clock::min_time);
Austin Schuhad154822019-12-27 15:45:13 -0800363 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
364 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -0700365 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
Austin Schuh39788ff2019-12-01 18:22:57 -0800366 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
367 EXPECT_EQ(fetcher.context().size, 0u);
368 EXPECT_EQ(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700369 EXPECT_EQ(fetcher.context().buffer_index, -1);
Austin Schuhbbce72d2019-05-26 15:11:46 -0700370
Alex Perrycb7da4b2019-08-28 19:35:56 -0700371 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
372 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
373 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700374 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700375
376 EXPECT_TRUE(fetcher.Fetch());
377 ASSERT_FALSE(fetcher.get() == nullptr);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700378 EXPECT_EQ(fetcher.get()->value(), 200);
Austin Schuh39788ff2019-12-01 18:22:57 -0800379
380 const chrono::milliseconds kEpsilon(100);
381
Austin Schuhad154822019-12-27 15:45:13 -0800382 const aos::monotonic_clock::time_point monotonic_now = loop2->monotonic_now();
383 const aos::realtime_clock::time_point realtime_now = loop2->realtime_now();
384 EXPECT_EQ(fetcher.context().monotonic_event_time,
385 fetcher.context().monotonic_remote_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -0700386 EXPECT_EQ(fetcher.context().monotonic_remote_transmit_time,
387 monotonic_clock::min_time);
Austin Schuhad154822019-12-27 15:45:13 -0800388 EXPECT_EQ(fetcher.context().realtime_event_time,
389 fetcher.context().realtime_remote_time);
390
391 EXPECT_GE(fetcher.context().monotonic_event_time, monotonic_now - kEpsilon);
392 EXPECT_LE(fetcher.context().monotonic_event_time, monotonic_now + kEpsilon);
393 EXPECT_GE(fetcher.context().realtime_event_time, realtime_now - kEpsilon);
394 EXPECT_LE(fetcher.context().realtime_event_time, realtime_now + kEpsilon);
Austin Schuha9012be2021-07-21 15:19:11 -0700395 EXPECT_EQ(fetcher.context().source_boot_uuid, loop2->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -0800396 EXPECT_EQ(fetcher.context().queue_index, 0x0u);
397 EXPECT_EQ(fetcher.context().size, 20u);
398 EXPECT_NE(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700399 if (read_method() == ReadMethod::PIN) {
400 EXPECT_GE(fetcher.context().buffer_index, 0);
401 EXPECT_LT(fetcher.context().buffer_index,
402 loop2->NumberBuffers(fetcher.channel()));
403 } else {
404 EXPECT_EQ(fetcher.context().buffer_index, -1);
405 }
Parker Schuhe4a70d62017-12-27 20:10:20 -0800406}
407
Austin Schuh98ed26f2023-07-19 14:12:28 -0700408std::function<bool(const Context &)> MakeShouldFetch(
409 bool should_fetch, size_t *called_count = nullptr) {
410 return [should_fetch, called_count](const Context &) {
411 if (called_count != nullptr) {
412 (*called_count)++;
413 }
414 return should_fetch;
415 };
416}
417
418// Tests that a fetcher using FetchIf can fetch from a sender.
419TEST_P(AbstractEventLoopTest, FetchIfWithoutRun) {
420 auto loop1 = Make();
421 auto loop2 = Make();
422 auto loop3 = MakePrimary();
423
424 auto sender = loop1->MakeSender<TestMessage>("/test");
425
426 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
427
428 for (const bool should_fetch : {true, false}) {
429 EXPECT_FALSE(fetcher.FetchIf(MakeShouldFetch(should_fetch)));
430 EXPECT_EQ(fetcher.get(), nullptr);
431
432 EXPECT_EQ(fetcher.context().monotonic_event_time,
433 monotonic_clock::min_time);
434 EXPECT_EQ(fetcher.context().monotonic_remote_time,
435 monotonic_clock::min_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -0700436 EXPECT_EQ(fetcher.context().monotonic_remote_transmit_time,
437 monotonic_clock::min_time);
Austin Schuh98ed26f2023-07-19 14:12:28 -0700438 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
439 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
440 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
441 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
442 EXPECT_EQ(fetcher.context().size, 0u);
443 EXPECT_EQ(fetcher.context().data, nullptr);
444 EXPECT_EQ(fetcher.context().buffer_index, -1);
445 }
446
447 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
448 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
449 builder.add_value(200);
450 msg.CheckOk(msg.Send(builder.Finish()));
451
452 // Make sure failing to fetch won't affect anything.
453 EXPECT_FALSE(fetcher.FetchIf(MakeShouldFetch(false)));
454 EXPECT_EQ(fetcher.get(), nullptr);
455
456 EXPECT_EQ(fetcher.context().monotonic_event_time, monotonic_clock::min_time);
457 EXPECT_EQ(fetcher.context().monotonic_remote_time, monotonic_clock::min_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -0700458 EXPECT_EQ(fetcher.context().monotonic_remote_transmit_time,
459 monotonic_clock::min_time);
Austin Schuh98ed26f2023-07-19 14:12:28 -0700460 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
461 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
462 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
463 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
464 EXPECT_EQ(fetcher.context().size, 0u);
465 EXPECT_EQ(fetcher.context().data, nullptr);
466 EXPECT_EQ(fetcher.context().buffer_index, -1);
467
468 // And now confirm we succeed and everything gets set right.
469 EXPECT_TRUE(fetcher.FetchIf(MakeShouldFetch(true)));
470 ASSERT_FALSE(fetcher.get() == nullptr);
471 EXPECT_EQ(fetcher.get()->value(), 200);
472
473 const chrono::milliseconds kEpsilon(100);
474
475 const aos::monotonic_clock::time_point monotonic_now = loop2->monotonic_now();
476 const aos::realtime_clock::time_point realtime_now = loop2->realtime_now();
477 EXPECT_EQ(fetcher.context().monotonic_event_time,
478 fetcher.context().monotonic_remote_time);
479 EXPECT_EQ(fetcher.context().realtime_event_time,
480 fetcher.context().realtime_remote_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -0700481 EXPECT_EQ(fetcher.context().monotonic_remote_transmit_time,
482 monotonic_clock::min_time);
Austin Schuh98ed26f2023-07-19 14:12:28 -0700483
484 EXPECT_GE(fetcher.context().monotonic_event_time, monotonic_now - kEpsilon);
485 EXPECT_LE(fetcher.context().monotonic_event_time, monotonic_now + kEpsilon);
486 EXPECT_GE(fetcher.context().realtime_event_time, realtime_now - kEpsilon);
487 EXPECT_LE(fetcher.context().realtime_event_time, realtime_now + kEpsilon);
488 EXPECT_EQ(fetcher.context().source_boot_uuid, loop2->boot_uuid());
489 EXPECT_EQ(fetcher.context().queue_index, 0x0u);
490 EXPECT_EQ(fetcher.context().size, 20u);
491 EXPECT_NE(fetcher.context().data, nullptr);
492 if (read_method() == ReadMethod::PIN) {
493 EXPECT_GE(fetcher.context().buffer_index, 0);
494 EXPECT_LT(fetcher.context().buffer_index,
495 loop2->NumberBuffers(fetcher.channel()));
496 } else {
497 EXPECT_EQ(fetcher.context().buffer_index, -1);
498 }
499}
500
Austin Schuh3578a2e2019-05-25 18:17:59 -0700501// Tests that watcher will receive all messages sent if they are sent after
502// initialization and before running.
503TEST_P(AbstractEventLoopTest, DoubleSendAtStartup) {
504 auto loop1 = Make();
505 auto loop2 = MakePrimary();
506
507 auto sender = loop1->MakeSender<TestMessage>("/test");
508
509 ::std::vector<int> values;
510
511 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700512 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700513 if (values.size() == 2) {
Austin Schuh9fe68f72019-08-10 19:32:03 -0700514 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -0700515 }
516 });
517
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700518 // Before Run, should be ignored.
Austin Schuh3578a2e2019-05-25 18:17:59 -0700519 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700520 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
521 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
522 builder.add_value(199);
milind1f1dca32021-07-03 13:50:07 -0700523 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700524 }
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700525
526 loop2->OnRun([&]() {
Austin Schuh98ed26f2023-07-19 14:12:28 -0700527 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700528 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
529 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700530 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700531 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700532 }
533 });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700534
535 Run();
536
537 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
538}
539
540// Tests that watcher will not receive messages sent before the watcher is
541// created.
542TEST_P(AbstractEventLoopTest, DoubleSendAfterStartup) {
543 auto loop1 = Make();
544 auto loop2 = MakePrimary();
545
546 auto sender = loop1->MakeSender<TestMessage>("/test");
547
548 ::std::vector<int> values;
549
Austin Schuh98ed26f2023-07-19 14:12:28 -0700550 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700551 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
552 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700553 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700554 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700555 }
556
557 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700558 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700559 });
560
561 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700562 auto test_timer = loop2->AddTimer([this]() { this->Exit(); });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700563 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700564 test_timer->Schedule(loop2->monotonic_now(),
565 ::std::chrono::milliseconds(100));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700566 });
567
568 Run();
569 EXPECT_EQ(0, values.size());
570}
571
Austin Schuhbbce72d2019-05-26 15:11:46 -0700572// Tests that FetchNext gets all the messages sent after it is constructed.
573TEST_P(AbstractEventLoopTest, FetchNext) {
574 auto loop1 = Make();
575 auto loop2 = MakePrimary();
576
577 auto sender = loop1->MakeSender<TestMessage>("/test");
578 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
579
580 ::std::vector<int> values;
581
Austin Schuh98ed26f2023-07-19 14:12:28 -0700582 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700583 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
584 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700585 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700586 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700587 }
588
589 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700590 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700591 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700592 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700593 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700594 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700595 });
596
597 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700598 test_timer->Schedule(loop2->monotonic_now(),
599 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700600 });
601
602 Run();
603 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
604}
605
606// Tests that FetchNext gets no messages sent before it is constructed.
607TEST_P(AbstractEventLoopTest, FetchNextAfterSend) {
608 auto loop1 = Make();
609 auto loop2 = MakePrimary();
610
611 auto sender = loop1->MakeSender<TestMessage>("/test");
612
613 ::std::vector<int> values;
614
Austin Schuh98ed26f2023-07-19 14:12:28 -0700615 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700616 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
617 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700618 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700619 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700620 }
621
622 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
623
624 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700625 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700626 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700627 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700628 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700629 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700630 });
631
632 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700633 test_timer->Schedule(loop2->monotonic_now(),
634 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700635 });
636
637 Run();
638 EXPECT_THAT(0, values.size());
639}
640
Austin Schuh98ed26f2023-07-19 14:12:28 -0700641// Tests that FetchNextIf gets no messages sent before it is constructed.
642TEST_P(AbstractEventLoopTest, FetchNextIfAfterSend) {
643 auto loop1 = Make();
644 auto loop2 = MakePrimary();
645
646 auto sender = loop1->MakeSender<TestMessage>("/test");
647
648 ::std::vector<int> values;
649
650 for (int i = 200; i < 202; ++i) {
651 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
652 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
653 builder.add_value(i);
654 msg.CheckOk(msg.Send(builder.Finish()));
655 }
656
657 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
658
659 // Add a timer to actually quit.
660 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
661 while (fetcher.FetchNextIf(MakeShouldFetch(true))) {
662 values.push_back(fetcher.get()->value());
663 }
664 this->Exit();
665 });
666
667 loop2->OnRun([&test_timer, &loop2]() {
668 test_timer->Schedule(loop2->monotonic_now(),
669 ::std::chrono::milliseconds(100));
670 });
671
672 Run();
673 EXPECT_EQ(0, values.size());
674}
675
Austin Schuhbbce72d2019-05-26 15:11:46 -0700676// Tests that Fetch returns the last message created before the loop was
677// started.
678TEST_P(AbstractEventLoopTest, FetchDataFromBeforeCreation) {
679 auto loop1 = Make();
680 auto loop2 = MakePrimary();
681
682 auto sender = loop1->MakeSender<TestMessage>("/test");
683
684 ::std::vector<int> values;
685
Austin Schuh98ed26f2023-07-19 14:12:28 -0700686 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700687 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
688 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700689 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700690 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700691 }
692
693 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
694
695 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700696 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700697 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700698 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700699 }
700 // Do it again to make sure we don't double fetch.
701 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700702 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700703 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700704 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700705 });
706
707 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700708 test_timer->Schedule(loop2->monotonic_now(),
709 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700710 });
711
712 Run();
713 EXPECT_THAT(values, ::testing::ElementsAreArray({201}));
714}
715
Austin Schuh98ed26f2023-07-19 14:12:28 -0700716// Tests that FetchIf returns the last message created before the loop was
717// started.
718TEST_P(AbstractEventLoopTest, FetchIfDataFromBeforeCreation) {
719 auto loop1 = Make();
720 auto loop2 = MakePrimary();
721
722 auto sender = loop1->MakeSender<TestMessage>("/test");
723
724 ::std::vector<int> values;
725
726 for (int i = 200; i < 202; ++i) {
727 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
728 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
729 builder.add_value(i);
730 msg.CheckOk(msg.Send(builder.Finish()));
731 }
732
733 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
734
735 // Add a timer to actually quit.
736 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
737 if (fetcher.FetchIf(MakeShouldFetch(true))) {
738 values.push_back(fetcher.get()->value());
739 }
740
741 if (fetcher.FetchIf(MakeShouldFetch(false))) {
742 values.push_back(fetcher.get()->value());
743 }
744 // Do it again to make sure we don't double fetch.
745 if (fetcher.FetchIf(MakeShouldFetch(true))) {
746 values.push_back(fetcher.get()->value());
747 }
748 this->Exit();
749 });
750
751 loop2->OnRun([&test_timer, &loop2]() {
752 test_timer->Schedule(loop2->monotonic_now(),
753 ::std::chrono::milliseconds(100));
754 });
755
756 Run();
757 EXPECT_THAT(values, ::testing::ElementsAreArray({201}));
758}
759
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700760// Tests that timer handler is enabled after setup (even if it is in the past)
761// and is disabled after running
762TEST_P(AbstractEventLoopTest, CheckTimerDisabled) {
763 auto loop = MakePrimary("primary");
764
765 auto timer = loop->AddTimer([this]() {
766 LOG(INFO) << "timer called";
767 Exit();
768 });
769
770 loop->OnRun([&loop, timer]() {
771 EXPECT_TRUE(timer->IsDisabled());
Philipp Schradera6712522023-07-05 20:25:11 -0700772 timer->Schedule(loop->monotonic_now() + chrono::milliseconds(100));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700773 EXPECT_FALSE(timer->IsDisabled());
774 });
775
776 Run();
777 EXPECT_TRUE(timer->IsDisabled());
778}
779
780// Tests that timer handler is enabled after setup (even if it is in the past)
781// and is disabled after running
782TEST_P(AbstractEventLoopTest, CheckTimerRunInPastDisabled) {
783 auto loop = MakePrimary("primary");
784
785 auto timer2 = loop->AddTimer([this]() {
786 LOG(INFO) << "timer called";
787 Exit();
788 });
789
790 auto timer = loop->AddTimer([&loop, timer2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700791 timer2->Schedule(loop->monotonic_now() - chrono::nanoseconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700792 });
793
794 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700795 timer->Schedule(loop->monotonic_now() + chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700796 EXPECT_FALSE(timer->IsDisabled());
797 });
798
799 Run();
800 EXPECT_TRUE(timer2->IsDisabled());
801}
802
803// Tests that timer handler is not disabled even after calling Exit on the event
804// loop within the timer
805TEST_P(AbstractEventLoopTest, CheckTimerRepeatOnCountDisabled) {
806 auto loop = MakePrimary("primary");
807 int counter = 0;
808
809 auto timer = loop->AddTimer([&counter, this]() {
810 LOG(INFO) << "timer called";
811 counter++;
812 if (counter >= 5) {
813 Exit();
814 }
815 });
816
817 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700818 timer->Schedule(loop->monotonic_now() + chrono::seconds(1),
819 chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700820 EXPECT_FALSE(timer->IsDisabled());
821 });
822 Run();
823
824 // Sanity check
825 EXPECT_EQ(counter, 5);
826
827 // if you run the loop again, the timer will start running again
828 EXPECT_FALSE(timer->IsDisabled());
829
830 counter = 0;
831 Run();
832 timer->Disable();
833
834 EXPECT_TRUE(timer->IsDisabled());
835}
836
837// Tests that timer handler is not disabled even after calling Exit on the event
838// loop using an external timer
839TEST_P(AbstractEventLoopTest, CheckTimerRepeatTillEndTimerDisabled) {
840 auto loop = MakePrimary("primary");
841
842 auto timer = loop->AddTimer([]() { LOG(INFO) << "timer called"; });
843
844 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700845 timer->Schedule(loop->monotonic_now() + chrono::seconds(1),
846 chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700847 EXPECT_FALSE(timer->IsDisabled());
848 });
849
850 EndEventLoop(loop.get(), chrono::seconds(5));
851 Run();
852 EXPECT_FALSE(timer->IsDisabled());
853
854 timer->Disable();
855 EXPECT_TRUE(timer->IsDisabled());
856}
857
Austin Schuhbbce72d2019-05-26 15:11:46 -0700858// Tests that Fetch and FetchNext interleave as expected.
859TEST_P(AbstractEventLoopTest, FetchAndFetchNextTogether) {
860 auto loop1 = Make();
861 auto loop2 = MakePrimary();
862
863 auto sender = loop1->MakeSender<TestMessage>("/test");
864
865 ::std::vector<int> values;
866
Austin Schuh98ed26f2023-07-19 14:12:28 -0700867 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700868 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
869 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700870 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700871 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700872 }
873
874 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
875
876 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700877 auto test_timer = loop2->AddTimer([&fetcher, &values, &sender, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700878 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700879 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700880 }
881
Austin Schuh98ed26f2023-07-19 14:12:28 -0700882 for (int i = 202; i < 205; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700883 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
884 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700885 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700886 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700887 }
888
889 if (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700890 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700891 }
892
893 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700894 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700895 }
896
Austin Schuh9fe68f72019-08-10 19:32:03 -0700897 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700898 });
899
900 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700901 test_timer->Schedule(loop2->monotonic_now(),
902 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700903 });
904
905 Run();
906 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
907}
908
Austin Schuh98ed26f2023-07-19 14:12:28 -0700909// Tests that Fetch{If,} and FetchNext{If,} interleave as expected.
910TEST_P(AbstractEventLoopTest, FetchAndFetchNextIfTogether) {
911 auto loop1 = Make();
912 auto loop2 = MakePrimary();
913
914 auto sender = loop1->MakeSender<TestMessage>("/test");
915
916 ::std::vector<int> values;
917
918 for (int i = 200; i < 202; ++i) {
919 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
920 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
921 builder.add_value(i);
922 msg.CheckOk(msg.Send(builder.Finish()));
923 }
924
925 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
926
927 // Add a timer to actually quit.
928 auto test_timer = loop2->AddTimer([&fetcher, &values, &sender, this]() {
929 if (fetcher.Fetch()) {
930 values.push_back(fetcher.get()->value());
931 }
932
933 for (int i = 202; i < 205; ++i) {
934 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
935 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
936 builder.add_value(i);
937 msg.CheckOk(msg.Send(builder.Finish()));
938 }
939
940 EXPECT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false)));
941
942 if (fetcher.FetchNext()) {
943 values.push_back(fetcher.get()->value());
944 }
945
946 EXPECT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false)));
947 EXPECT_FALSE(fetcher.FetchIf(MakeShouldFetch(false)));
948
949 if (fetcher.FetchIf(MakeShouldFetch(true))) {
950 values.push_back(fetcher.get()->value());
951 }
952
953 this->Exit();
954 });
955
956 loop2->OnRun([&test_timer, &loop2]() {
957 test_timer->Schedule(loop2->monotonic_now(),
958 ::std::chrono::milliseconds(100));
959 });
960
961 Run();
962 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
963}
964
Austin Schuh3115a202019-05-27 21:02:14 -0700965// Tests that FetchNext behaves correctly when we get two messages in the queue
966// but don't consume the first until after the second has been sent.
967TEST_P(AbstractEventLoopTest, FetchNextTest) {
Austin Schuh3115a202019-05-27 21:02:14 -0700968 auto send_loop = Make();
969 auto fetch_loop = Make();
970 auto sender = send_loop->MakeSender<TestMessage>("/test");
971 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
972
973 {
Tyler Chatow67ddb032020-01-12 14:30:04 -0800974 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
975 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
976 builder.add_value(100);
milind1f1dca32021-07-03 13:50:07 -0700977 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700978 }
979
980 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700981 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
982 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
983 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700984 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700985 }
986
987 ASSERT_TRUE(fetcher.FetchNext());
988 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700989 EXPECT_EQ(100, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700990
991 ASSERT_TRUE(fetcher.FetchNext());
992 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700993 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700994
995 // When we run off the end of the queue, expect to still have the old message:
996 ASSERT_FALSE(fetcher.FetchNext());
997 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700998 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700999}
1000
Austin Schuh98ed26f2023-07-19 14:12:28 -07001001// Tests that FetchNext behaves correctly when we get two messages in the queue
1002// but don't consume the first until after the second has been sent.
1003TEST_P(AbstractEventLoopTest, FetchNextIfTest) {
1004 auto send_loop = Make();
1005 auto fetch_loop = Make();
1006 auto sender = send_loop->MakeSender<TestMessage>("/test");
1007 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
1008
1009 {
1010 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1011 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1012 builder.add_value(100);
1013 msg.CheckOk(msg.Send(builder.Finish()));
1014 }
1015
1016 {
1017 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1018 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1019 builder.add_value(200);
1020 msg.CheckOk(msg.Send(builder.Finish()));
1021 }
1022
1023 size_t called_count = 0;
1024 ASSERT_TRUE(fetcher.FetchNextIf(MakeShouldFetch(true, &called_count)));
1025 ASSERT_NE(nullptr, fetcher.get());
1026 EXPECT_EQ(100, fetcher.get()->value());
1027 EXPECT_EQ(called_count, 1u);
1028
1029 ASSERT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false, &called_count)));
1030 EXPECT_EQ(called_count, 2u);
1031
1032 ASSERT_TRUE(fetcher.FetchNextIf(MakeShouldFetch(true, &called_count)));
1033 ASSERT_NE(nullptr, fetcher.get());
1034 EXPECT_EQ(200, fetcher.get()->value());
1035 EXPECT_EQ(called_count, 3u);
1036
1037 // When we run off the end of the queue, expect to still have the old message:
1038 ASSERT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false, &called_count)));
1039 EXPECT_EQ(called_count, 3u);
1040 ASSERT_NE(nullptr, fetcher.get());
1041 EXPECT_EQ(200, fetcher.get()->value());
1042}
1043
Brian Silverman77162972020-08-12 19:52:40 -07001044// Verify that a fetcher still holds its data, even after falling behind.
1045TEST_P(AbstractEventLoopTest, FetcherBehindData) {
1046 auto send_loop = Make();
1047 auto fetch_loop = Make();
1048 auto sender = send_loop->MakeSender<TestMessage>("/test");
1049 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
1050 {
1051 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1052 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1053 builder.add_value(1);
milind1f1dca32021-07-03 13:50:07 -07001054 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -07001055 }
1056 ASSERT_TRUE(fetcher.Fetch());
1057 EXPECT_EQ(1, fetcher.get()->value());
1058 for (int i = 0; i < 300; ++i) {
1059 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1060 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1061 builder.add_value(i + 2);
milind1f1dca32021-07-03 13:50:07 -07001062 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -07001063 }
1064 EXPECT_EQ(1, fetcher.get()->value());
1065}
1066
1067// Try a bunch of orderings of operations with fetchers and senders. Verify that
1068// all the fetchers have the correct data at each step.
1069TEST_P(AbstractEventLoopTest, FetcherPermutations) {
1070 for (int max_save = 0; max_save < 5; ++max_save) {
1071 SCOPED_TRACE("max_save=" + std::to_string(max_save));
1072
1073 auto send_loop = Make();
1074 auto fetch_loop = Make();
1075 auto sender = send_loop->MakeSender<TestMessage>("/test");
1076 const auto send_message = [&sender](int i) {
1077 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1078 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1079 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -07001080 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -07001081 };
1082 std::vector<Fetcher<TestMessage>> fetchers;
1083 for (int i = 0; i < 10; ++i) {
1084 fetchers.emplace_back(fetch_loop->MakeFetcher<TestMessage>("/test"));
1085 }
1086 send_message(1);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001087 const auto verify_buffers = [&]() {
1088 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>>
1089 fetchers_copy;
1090 for (const auto &fetcher : fetchers) {
1091 fetchers_copy.emplace_back(fetcher);
1092 }
1093 std::vector<std::reference_wrapper<const Sender<TestMessage>>>
1094 senders_copy;
1095 senders_copy.emplace_back(sender);
1096 VerifyBuffers(send_loop->NumberBuffers(sender.channel()), fetchers_copy,
1097 senders_copy);
1098 };
Brian Silverman77162972020-08-12 19:52:40 -07001099 for (auto &fetcher : fetchers) {
1100 ASSERT_TRUE(fetcher.Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -07001101 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001102 EXPECT_EQ(1, fetcher.get()->value());
1103 }
1104
1105 for (int save = 1; save <= max_save; ++save) {
1106 SCOPED_TRACE("save=" + std::to_string(save));
1107 send_message(100 + save);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001108 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001109 for (size_t i = 0; i < fetchers.size() - save; ++i) {
1110 SCOPED_TRACE("fetcher=" + std::to_string(i));
1111 ASSERT_TRUE(fetchers[i].Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -07001112 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001113 EXPECT_EQ(100 + save, fetchers[i].get()->value());
1114 }
1115 for (size_t i = fetchers.size() - save; i < fetchers.size() - 1; ++i) {
1116 SCOPED_TRACE("fetcher=" + std::to_string(i));
1117 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
1118 }
1119 EXPECT_EQ(1, fetchers.back().get()->value());
1120 }
1121
1122 for (int i = 0; i < 300; ++i) {
1123 send_message(200 + i);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001124 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001125 }
1126
1127 for (size_t i = 0; i < fetchers.size() - max_save; ++i) {
1128 SCOPED_TRACE("fetcher=" + std::to_string(i));
1129 if (max_save > 0) {
1130 EXPECT_EQ(100 + max_save, fetchers[i].get()->value());
1131 } else {
1132 EXPECT_EQ(1, fetchers[i].get()->value());
1133 }
1134 }
1135 for (size_t i = fetchers.size() - max_save; i < fetchers.size() - 1; ++i) {
1136 SCOPED_TRACE("fetcher=" + std::to_string(i));
1137 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
1138 }
1139 EXPECT_EQ(1, fetchers.back().get()->value());
1140 }
1141}
1142
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001143// Verify that making a fetcher and watcher for "/test" succeeds.
1144TEST_P(AbstractEventLoopTest, FetcherAndWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -08001145 auto loop = Make();
1146 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001147 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Parker Schuhe4a70d62017-12-27 20:10:20 -08001148}
1149
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001150// Verify that making 2 fetchers for "/test" succeeds.
Parker Schuhe4a70d62017-12-27 20:10:20 -08001151TEST_P(AbstractEventLoopTest, TwoFetcher) {
1152 auto loop = Make();
1153 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001154 auto fetcher2 = loop->MakeFetcher<TestMessage>("/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -08001155}
1156
Alex Perrycb7da4b2019-08-28 19:35:56 -07001157// Verify that registering a watcher for an invalid channel name dies.
1158TEST_P(AbstractEventLoopDeathTest, InvalidChannelName) {
1159 auto loop = Make();
1160 EXPECT_DEATH(
1161 { loop->MakeWatcher("/test/invalid", [&](const TestMessage &) {}); },
1162 "/test/invalid");
Brian Silverman454bc112020-03-05 14:21:25 -08001163 EXPECT_DEATH(
1164 { loop->MakeNoArgWatcher<TestMessage>("/test/invalid", [&]() {}); },
1165 "/test/invalid");
Alex Perrycb7da4b2019-08-28 19:35:56 -07001166}
1167
James Kuszmaul8866e642022-06-10 16:00:36 -07001168// Verify that setting up a timer before monotonic_clock::epoch() fails.
James Kuszmaul86e86c32022-07-21 17:39:47 -07001169TEST_P(AbstractEventLoopDeathTest, NegativeTimeTimer) {
James Kuszmaul8866e642022-06-10 16:00:36 -07001170 auto loop = Make();
1171 TimerHandler *time = loop->AddTimer([]() {});
Philipp Schradera6712522023-07-05 20:25:11 -07001172 EXPECT_DEATH(
1173 time->Schedule(monotonic_clock::epoch() - std::chrono::seconds(1)),
1174 "-1.000");
James Kuszmaul8866e642022-06-10 16:00:36 -07001175}
1176
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001177// Verify that registering a watcher twice for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001178TEST_P(AbstractEventLoopDeathTest, TwoWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -08001179 auto loop = Make();
1180 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001181 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
1182 "/test");
Brian Silverman454bc112020-03-05 14:21:25 -08001183 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
1184}
1185
1186// Verify that registering a no-arg watcher twice for "/test" fails.
1187TEST_P(AbstractEventLoopDeathTest, TwoNoArgWatcher) {
1188 auto loop = Make();
1189 loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {});
1190 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
1191 "/test");
1192 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001193}
1194
Austin Schuh3115a202019-05-27 21:02:14 -07001195// Verify that SetRuntimeRealtimePriority fails while running.
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001196TEST_P(AbstractEventLoopDeathTest, SetRuntimeRealtimePriority) {
Austin Schuh3115a202019-05-27 21:02:14 -07001197 auto loop = MakePrimary();
Austin Schuh65493d62022-08-17 15:10:37 -07001198 EXPECT_EQ(0, loop->runtime_realtime_priority());
Austin Schuh3115a202019-05-27 21:02:14 -07001199 // Confirm that runtime priority calls work when not realtime.
1200 loop->SetRuntimeRealtimePriority(5);
Austin Schuh65493d62022-08-17 15:10:37 -07001201 EXPECT_EQ(5, loop->runtime_realtime_priority());
Austin Schuh3115a202019-05-27 21:02:14 -07001202
1203 loop->OnRun([&]() { loop->SetRuntimeRealtimePriority(5); });
1204
1205 EXPECT_DEATH(Run(), "realtime");
1206}
1207
Austin Schuh65493d62022-08-17 15:10:37 -07001208namespace {
1209
1210bool CpuSetEqual(const cpu_set_t &a, const cpu_set_t &b) {
1211 return CPU_EQUAL(&a, &b);
1212}
1213
1214} // namespace
1215
Brian Silverman6a54ff32020-04-28 16:41:39 -07001216// Verify that SetRuntimeAffinity fails while running.
1217TEST_P(AbstractEventLoopDeathTest, SetRuntimeAffinity) {
Austin Schuhde973292021-10-12 18:09:49 -07001218 const cpu_set_t available = GetCurrentThreadAffinity();
1219 int first_cpu = -1;
1220 for (int i = 0; i < CPU_SETSIZE; ++i) {
1221 if (CPU_ISSET(i, &available)) {
1222 first_cpu = i;
1223 break;
1224 continue;
1225 }
1226 }
1227 CHECK_NE(first_cpu, -1) << ": Default affinity has no CPUs?";
1228
Brian Silverman6a54ff32020-04-28 16:41:39 -07001229 auto loop = MakePrimary();
Austin Schuh65493d62022-08-17 15:10:37 -07001230 EXPECT_TRUE(
1231 CpuSetEqual(EventLoop::DefaultAffinity(), loop->runtime_affinity()));
1232 const cpu_set_t new_affinity = MakeCpusetFromCpus({first_cpu});
Brian Silverman6a54ff32020-04-28 16:41:39 -07001233 // Confirm that runtime priority calls work when not running.
Austin Schuh65493d62022-08-17 15:10:37 -07001234 loop->SetRuntimeAffinity(new_affinity);
1235 EXPECT_TRUE(CpuSetEqual(new_affinity, loop->runtime_affinity()));
Brian Silverman6a54ff32020-04-28 16:41:39 -07001236
Austin Schuhde973292021-10-12 18:09:49 -07001237 loop->OnRun(
1238 [&]() { loop->SetRuntimeAffinity(MakeCpusetFromCpus({first_cpu})); });
Brian Silverman6a54ff32020-04-28 16:41:39 -07001239
1240 EXPECT_DEATH(Run(), "Cannot set affinity while running");
1241}
1242
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001243// Verify that registering a watcher and a sender for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001244TEST_P(AbstractEventLoopDeathTest, WatcherAndSender) {
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001245 auto loop = Make();
1246 auto sender = loop->MakeSender<TestMessage>("/test");
1247 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
1248 "/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -08001249}
1250
Austin Schuhe516ab02020-05-06 21:37:04 -07001251// Verify that creating too many senders fails.
1252TEST_P(AbstractEventLoopDeathTest, TooManySenders) {
1253 auto loop = Make();
1254 std::vector<aos::Sender<TestMessage>> senders;
1255 for (int i = 0; i < 10; ++i) {
1256 senders.emplace_back(loop->MakeSender<TestMessage>("/test"));
1257 }
1258 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); },
1259 "Failed to create sender on \\{ \"name\": \"/test\", \"type\": "
Brian Silverman77162972020-08-12 19:52:40 -07001260 "\"aos.TestMessage\"[^}]*\\ }, too many senders.");
1261}
1262
1263// Verify that creating too many fetchers fails.
1264TEST_P(AbstractEventLoopDeathTest, TooManyFetchers) {
1265 if (read_method() != ReadMethod::PIN) {
1266 // Other read methods don't limit the number of readers, so just skip this.
1267 return;
1268 }
1269
1270 auto loop = Make();
1271 std::vector<aos::Fetcher<TestMessage>> fetchers;
1272 for (int i = 0; i < 10; ++i) {
1273 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1274 }
1275 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1276 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1277 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
1278}
1279
1280// Verify that creating too many fetchers, split between two event loops, fails.
1281TEST_P(AbstractEventLoopDeathTest, TooManyFetchersTwoLoops) {
1282 if (read_method() != ReadMethod::PIN) {
1283 // Other read methods don't limit the number of readers, so just skip this.
1284 return;
1285 }
1286
1287 auto loop = Make();
1288 auto loop2 = Make();
1289 std::vector<aos::Fetcher<TestMessage>> fetchers;
1290 for (int i = 0; i < 5; ++i) {
1291 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1292 fetchers.emplace_back(loop2->MakeFetcher<TestMessage>("/test"));
1293 }
1294 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1295 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1296 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
1297}
1298
1299// Verify that creating too many watchers fails.
1300TEST_P(AbstractEventLoopDeathTest, TooManyWatchers) {
1301 if (read_method() != ReadMethod::PIN) {
1302 // Other read methods don't limit the number of readers, so just skip this.
1303 return;
1304 }
1305
1306 std::vector<std::unique_ptr<EventLoop>> loops;
1307 for (int i = 0; i < 10; ++i) {
1308 loops.emplace_back(Make());
1309 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
1310 }
1311 EXPECT_DEATH({ Make()->MakeWatcher("/test", [](const TestMessage &) {}); },
1312 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1313 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
1314}
1315
1316// Verify that creating too many watchers and fetchers combined fails.
1317TEST_P(AbstractEventLoopDeathTest, TooManyWatchersAndFetchers) {
1318 if (read_method() != ReadMethod::PIN) {
1319 // Other read methods don't limit the number of readers, so just skip this.
1320 return;
1321 }
1322
1323 auto loop = Make();
1324 std::vector<aos::Fetcher<TestMessage>> fetchers;
1325 std::vector<std::unique_ptr<EventLoop>> loops;
1326 for (int i = 0; i < 5; ++i) {
1327 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1328 loops.emplace_back(Make());
1329 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
1330 }
1331 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1332 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1333 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
Austin Schuhe516ab02020-05-06 21:37:04 -07001334}
1335
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001336// Verify that we can't create a sender inside OnRun.
1337TEST_P(AbstractEventLoopDeathTest, SenderInOnRun) {
1338 auto loop1 = MakePrimary();
1339
1340 loop1->OnRun(
1341 [&]() { auto sender = loop1->MakeSender<TestMessage>("/test2"); });
1342
1343 EXPECT_DEATH(Run(), "running");
1344}
1345
1346// Verify that we can't create a watcher inside OnRun.
1347TEST_P(AbstractEventLoopDeathTest, WatcherInOnRun) {
1348 auto loop1 = MakePrimary();
1349
1350 loop1->OnRun(
1351 [&]() { loop1->MakeWatcher("/test", [&](const TestMessage &) {}); });
1352
1353 EXPECT_DEATH(Run(), "running");
1354}
1355
Brian Silverman454bc112020-03-05 14:21:25 -08001356// Verify that we can't create a no-arg watcher inside OnRun.
1357TEST_P(AbstractEventLoopDeathTest, NoArgWatcherInOnRun) {
1358 auto loop1 = MakePrimary();
1359
1360 loop1->OnRun(
1361 [&]() { loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {}); });
1362
1363 EXPECT_DEATH(Run(), "running");
1364}
1365
Parker Schuhe4a70d62017-12-27 20:10:20 -08001366// Verify that Quit() works when there are multiple watchers.
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001367TEST_P(AbstractEventLoopTest, MultipleWatcherQuit) {
1368 auto loop1 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -07001369 auto loop2 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -08001370
Austin Schuh3578a2e2019-05-25 18:17:59 -07001371 loop2->MakeWatcher("/test1", [&](const TestMessage &) {});
1372 loop2->MakeWatcher("/test2", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001373 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -07001374 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -07001375 });
1376
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001377 auto sender = loop1->MakeSender<TestMessage>("/test2");
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001378
1379 loop2->OnRun([&]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001380 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1381 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1382 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001383 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001384 });
Parker Schuhe4a70d62017-12-27 20:10:20 -08001385
Austin Schuh44019f92019-05-19 19:58:27 -07001386 Run();
Parker Schuhe4a70d62017-12-27 20:10:20 -08001387}
1388
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001389// Verify that AOS_LOG has the right name.
1390TEST_P(AbstractEventLoopTest, AOSLog) {
1391 auto loop2 = MakePrimary("loop1");
1392 auto loop1 = Make("loop0");
1393
1394 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1395
1396 EXPECT_FALSE(fetcher.Fetch());
1397
1398 loop2->OnRun([&]() {
1399 AOS_LOG(INFO, "Testing123");
1400 this->Exit();
1401 });
1402
1403 Run();
1404 EXPECT_TRUE(fetcher.Fetch());
1405 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1406}
1407
1408// Verify that AOS_LOG has the right name in a watcher.
1409TEST_P(AbstractEventLoopTest, AOSLogWatcher) {
1410 auto loop2 = MakePrimary("loop1");
1411 auto loop1 = Make("loop0");
1412
1413 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1414
1415 EXPECT_FALSE(fetcher.Fetch());
1416
1417 auto sender = loop1->MakeSender<TestMessage>("/test2");
1418
1419 loop2->MakeWatcher("/test2", [&](const TestMessage & /*message*/) {
1420 AOS_LOG(INFO, "Testing123");
1421 this->Exit();
1422 });
1423
1424 loop2->OnRun([&]() {
1425 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1426 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1427 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001428 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001429 });
1430
1431 Run();
1432 EXPECT_TRUE(fetcher.Fetch());
1433 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1434}
1435
1436// Verify that AOS_LOG has the right name in a timer.
1437TEST_P(AbstractEventLoopTest, AOSLogTimer) {
1438 auto loop2 = MakePrimary("loop1");
1439 auto loop1 = Make("loop0");
1440
1441 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1442
1443 EXPECT_FALSE(fetcher.Fetch());
1444
1445 auto test_timer = loop2->AddTimer([&]() {
1446 AOS_LOG(INFO, "Testing123");
1447 this->Exit();
1448 });
1449
Philipp Schradera6712522023-07-05 20:25:11 -07001450 loop2->OnRun([&]() { test_timer->Schedule(loop2->monotonic_now()); });
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001451
1452 Run();
1453 EXPECT_TRUE(fetcher.Fetch());
1454 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1455}
1456
Neil Balch229001a2018-01-07 18:22:52 -08001457// Verify that timer intervals and duration function properly.
1458TEST_P(AbstractEventLoopTest, TimerIntervalAndDuration) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001459 // Force a slower rate so we are guaranteed to have reports for our timer.
Austin Schuh39788ff2019-12-01 18:22:57 -08001460 FLAGS_timing_report_ms = 2000;
1461
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001462 const int kCount = 5;
Neil Balch229001a2018-01-07 18:22:52 -08001463
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001464 auto loop = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001465 auto loop2 = Make();
1466
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001467 ::std::vector<::aos::monotonic_clock::time_point> times;
1468 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
1469
Austin Schuh39788ff2019-12-01 18:22:57 -08001470 Fetcher<timing::Report> report_fetcher =
1471 loop2->MakeFetcher<timing::Report>("/aos");
1472 EXPECT_FALSE(report_fetcher.Fetch());
1473
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001474 auto test_timer = loop->AddTimer([this, &times, &expected_times, &loop]() {
1475 times.push_back(loop->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001476 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07001477 EXPECT_EQ(loop->context().monotonic_remote_transmit_time,
1478 monotonic_clock::min_time);
Austin Schuhad154822019-12-27 15:45:13 -08001479 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
1480 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001481 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -08001482 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
1483 EXPECT_EQ(loop->context().size, 0u);
1484 EXPECT_EQ(loop->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001485 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001486
Austin Schuhad154822019-12-27 15:45:13 -08001487 expected_times.push_back(loop->context().monotonic_event_time);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001488 if (times.size() == kCount) {
1489 this->Exit();
1490 }
Neil Balch229001a2018-01-07 18:22:52 -08001491 });
Austin Schuh39788ff2019-12-01 18:22:57 -08001492 test_timer->set_name("Test loop");
Neil Balch229001a2018-01-07 18:22:52 -08001493
Austin Schuh39788ff2019-12-01 18:22:57 -08001494 const monotonic_clock::time_point start_time = loop->monotonic_now();
Austin Schuh52d325c2019-06-23 18:59:06 -07001495 // TODO(austin): This should be an error... Should be done in OnRun only.
Philipp Schradera6712522023-07-05 20:25:11 -07001496 test_timer->Schedule(start_time + chrono::seconds(1), chrono::seconds(1));
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001497
Austin Schuh44019f92019-05-19 19:58:27 -07001498 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001499
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001500 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001501 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
1502 ASSERT_EQ(times.size(), expected_times.size());
1503 ASSERT_EQ((times.size() % 2), 1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001504
1505 // Grab the middle sample.
1506 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
1507
1508 // Add up all the delays of all the times.
1509 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1510 for (const ::aos::monotonic_clock::time_point time : times) {
1511 sum += time - average_time;
1512 }
1513
1514 // Average and add to the middle to find the average time.
1515 sum /= times.size();
1516 average_time += sum;
1517
1518 // Compute the offset from the average and the expected average. It
1519 // should be pretty close to 0.
1520 const ::aos::monotonic_clock::duration remainder =
1521 average_time - start_time - chrono::seconds(times.size() / 2 + 1);
1522
1523 const chrono::milliseconds kEpsilon(100);
1524 EXPECT_LT(remainder, +kEpsilon);
1525 EXPECT_GT(remainder, -kEpsilon);
1526
1527 // Make sure that the average duration is close to 1 second.
1528 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1529 times.front())
1530 .count() /
1531 static_cast<double>(times.size() - 1),
1532 1.0, 0.1);
1533
1534 // Confirm that the ideal wakeup times increment correctly.
1535 for (size_t i = 1; i < expected_times.size(); ++i) {
1536 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1537 }
1538
1539 for (size_t i = 0; i < expected_times.size(); ++i) {
1540 EXPECT_EQ((expected_times[i] - start_time) % chrono::seconds(1),
1541 chrono::seconds(0));
1542 }
1543
1544 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1545 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001546
Austin Schuh6bae8252021-02-07 22:01:49 -08001547 if (do_timing_reports() == DoTimingReports::kYes) {
1548 // And, since we are here, check that the timing report makes sense.
1549 // Start by looking for our event loop's timing.
1550 FlatbufferDetachedBuffer<timing::Report> report =
1551 FlatbufferDetachedBuffer<timing::Report>::Empty();
1552 while (report_fetcher.FetchNext()) {
1553 if (report_fetcher->name()->string_view() == "primary") {
1554 report = CopyFlatBuffer(report_fetcher.get());
1555 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001556 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001557
1558 // Confirm that we have the right number of reports, and the contents are
1559 // sane.
1560 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
1561
1562 EXPECT_EQ(report.message().name()->string_view(), "primary");
1563
1564 ASSERT_NE(report.message().senders(), nullptr);
1565 EXPECT_EQ(report.message().senders()->size(), 2);
1566
1567 ASSERT_NE(report.message().timers(), nullptr);
1568 EXPECT_EQ(report.message().timers()->size(), 2);
1569
1570 EXPECT_EQ(report.message().timers()->Get(0)->name()->string_view(),
1571 "Test loop");
1572 EXPECT_GE(report.message().timers()->Get(0)->count(), 1);
1573
1574 EXPECT_EQ(report.message().timers()->Get(1)->name()->string_view(),
1575 "timing_reports");
1576 EXPECT_EQ(report.message().timers()->Get(1)->count(), 1);
1577
1578 // Make sure there is a single phased loop report with our report in it.
1579 ASSERT_EQ(report.message().phased_loops(), nullptr);
1580 } else {
1581 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001582 }
Neil Balch229001a2018-01-07 18:22:52 -08001583}
1584
James Kuszmaul762e8692023-07-31 14:57:53 -07001585// Test that setting a default version string results in it getting populated
1586// correctly.
1587TEST_P(AbstractEventLoopTest, DefaultVersionStringInTimingReport) {
1588 gflags::FlagSaver flag_saver;
1589 FLAGS_timing_report_ms = 1000;
1590
1591 EventLoop::SetDefaultVersionString("default_version_string");
1592
1593 auto loop = MakePrimary();
1594
1595 Fetcher<timing::Report> report_fetcher =
1596 loop->MakeFetcher<timing::Report>("/aos");
1597
1598 TimerHandler *exit_timer = loop->AddTimer([this]() { Exit(); });
1599 loop->OnRun([exit_timer, &loop, &report_fetcher]() {
1600 report_fetcher.Fetch();
1601 exit_timer->Schedule(loop->monotonic_now() + std::chrono::seconds(2));
1602 });
1603
1604 Run();
1605
1606 bool found_primary_report = false;
1607 while (report_fetcher.FetchNext()) {
1608 if (report_fetcher->name()->string_view() == "primary") {
1609 found_primary_report = true;
1610 EXPECT_EQ("default_version_string",
1611 report_fetcher->version()->string_view());
1612 } else {
1613 FAIL() << report_fetcher->name()->string_view();
1614 }
1615 }
1616
1617 if (do_timing_reports() == DoTimingReports::kYes) {
1618 EXPECT_TRUE(found_primary_report);
1619 } else {
1620 EXPECT_FALSE(found_primary_report);
1621 }
1622}
1623
1624// Test that overriding the default version string results in it getting
1625// populated correctly.
1626TEST_P(AbstractEventLoopTest, OverrideDersionStringInTimingReport) {
1627 gflags::FlagSaver flag_saver;
1628 FLAGS_timing_report_ms = 1000;
1629
1630 EventLoop::SetDefaultVersionString("default_version_string");
1631
1632 auto loop = MakePrimary();
1633 loop->SetVersionString("override_version");
1634
1635 Fetcher<timing::Report> report_fetcher =
1636 loop->MakeFetcher<timing::Report>("/aos");
1637
1638 TimerHandler *exit_timer = loop->AddTimer([this]() { Exit(); });
1639 loop->OnRun([exit_timer, &loop, &report_fetcher]() {
1640 report_fetcher.Fetch();
1641 exit_timer->Schedule(loop->monotonic_now() + std::chrono::seconds(2));
1642 });
1643
1644 Run();
1645
1646 bool found_primary_report = false;
1647 while (report_fetcher.FetchNext()) {
1648 if (report_fetcher->name()->string_view() == "primary") {
1649 found_primary_report = true;
1650 EXPECT_EQ("override_version", report_fetcher->version()->string_view());
1651 } else {
1652 FAIL() << report_fetcher->name()->string_view();
1653 }
1654 }
1655
1656 if (do_timing_reports() == DoTimingReports::kYes) {
1657 EXPECT_TRUE(found_primary_report);
1658 } else {
1659 EXPECT_FALSE(found_primary_report);
1660 }
1661}
1662
Neil Balch229001a2018-01-07 18:22:52 -08001663// Verify that we can change a timer's parameters during execution.
1664TEST_P(AbstractEventLoopTest, TimerChangeParameters) {
Austin Schuh44019f92019-05-19 19:58:27 -07001665 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001666 loop->SetRuntimeRealtimePriority(1);
Austin Schuh7f20f512021-01-31 17:56:16 -08001667 std::vector<monotonic_clock::time_point> iteration_list;
Neil Balch229001a2018-01-07 18:22:52 -08001668
1669 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001670 ScopedNotRealtime nrt;
Austin Schuh7f20f512021-01-31 17:56:16 -08001671 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001672 });
1673
Austin Schuh7f20f512021-01-31 17:56:16 -08001674 monotonic_clock::time_point s;
1675 auto modifier_timer = loop->AddTimer([&test_timer, &s]() {
Philipp Schradera6712522023-07-05 20:25:11 -07001676 test_timer->Schedule(s + chrono::milliseconds(1750),
1677 chrono::milliseconds(600));
Neil Balch229001a2018-01-07 18:22:52 -08001678 });
1679
Austin Schuh7f20f512021-01-31 17:56:16 -08001680 s = loop->monotonic_now();
Philipp Schradera6712522023-07-05 20:25:11 -07001681 test_timer->Schedule(s, chrono::milliseconds(500));
1682 modifier_timer->Schedule(s + chrono::milliseconds(1250));
Austin Schuhd892f102021-10-12 18:01:46 -07001683 EndEventLoop(loop.get(), chrono::milliseconds(3950));
Austin Schuh44019f92019-05-19 19:58:27 -07001684 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001685
Austin Schuhd892f102021-10-12 18:01:46 -07001686 EXPECT_THAT(
1687 iteration_list,
1688 ::testing::ElementsAre(
1689 s, s + chrono::milliseconds(500), s + chrono::milliseconds(1000),
1690 s + chrono::milliseconds(1750), s + chrono::milliseconds(2350),
1691 s + chrono::milliseconds(2950), s + chrono::milliseconds(3550)));
Neil Balch229001a2018-01-07 18:22:52 -08001692}
1693
1694// Verify that we can disable a timer during execution.
1695TEST_P(AbstractEventLoopTest, TimerDisable) {
Austin Schuh44019f92019-05-19 19:58:27 -07001696 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001697 loop->SetRuntimeRealtimePriority(1);
Neil Balch229001a2018-01-07 18:22:52 -08001698 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
1699
1700 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001701 ScopedNotRealtime nrt;
Austin Schuhd892f102021-10-12 18:01:46 -07001702 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001703 });
1704
Tyler Chatow67ddb032020-01-12 14:30:04 -08001705 auto ender_timer = loop->AddTimer([&test_timer]() { test_timer->Disable(); });
Neil Balch229001a2018-01-07 18:22:52 -08001706
Austin Schuhd892f102021-10-12 18:01:46 -07001707 monotonic_clock::time_point s = loop->monotonic_now();
Philipp Schradera6712522023-07-05 20:25:11 -07001708 test_timer->Schedule(s, ::std::chrono::milliseconds(500));
1709 ender_timer->Schedule(s + ::std::chrono::milliseconds(1250));
Austin Schuh73d99502021-12-08 12:05:39 -08001710 EndEventLoop(loop.get(), ::std::chrono::milliseconds(2000));
Austin Schuh44019f92019-05-19 19:58:27 -07001711 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001712
Austin Schuhd892f102021-10-12 18:01:46 -07001713 EXPECT_THAT(iteration_list,
Austin Schuh73d99502021-12-08 12:05:39 -08001714 ::testing::ElementsAre(s, s + chrono::milliseconds(500),
1715 s + chrono::milliseconds(1000)));
Neil Balch229001a2018-01-07 18:22:52 -08001716}
Austin Schuh7267c532019-05-19 19:55:53 -07001717
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001718// Verify that a timer can disable itself.
1719//
1720// TODO(Brian): Do something similar with phased loops, both with a quick
1721// handler and a handler that would miss a cycle except it got deferred. Current
1722// behavior doing that is a mess.
1723TEST_P(AbstractEventLoopTest, TimerDisableSelf) {
1724 auto loop = MakePrimary();
1725
1726 int count = 0;
1727 aos::TimerHandler *test_timer;
1728 test_timer = loop->AddTimer([&count, &test_timer]() {
1729 ++count;
1730 test_timer->Disable();
1731 });
1732
Philipp Schradera6712522023-07-05 20:25:11 -07001733 test_timer->Schedule(loop->monotonic_now(), ::std::chrono::milliseconds(20));
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001734 EndEventLoop(loop.get(), ::std::chrono::milliseconds(80));
1735 Run();
1736
1737 EXPECT_EQ(count, 1);
1738}
1739
Brian Silvermanbd405c02020-06-23 16:25:23 -07001740// Verify that we can disable a timer during execution of another timer
1741// scheduled for the same time, with one ordering of creation for the timers.
1742//
1743// Also schedule some more events to reshuffle the heap in EventLoop used for
1744// tracking events to change up the order. This used to segfault
1745// SimulatedEventLoop.
1746TEST_P(AbstractEventLoopTest, TimerDisableOther) {
1747 for (bool creation_order : {true, false}) {
1748 for (bool setup_order : {true, false}) {
1749 for (int shuffle_events = 0; shuffle_events < 5; ++shuffle_events) {
1750 auto loop = MakePrimary();
1751 aos::TimerHandler *test_timer, *ender_timer;
1752 if (creation_order) {
1753 test_timer = loop->AddTimer([]() {});
1754 ender_timer =
1755 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1756 } else {
1757 ender_timer =
1758 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1759 test_timer = loop->AddTimer([]() {});
1760 }
1761
1762 const auto start = loop->monotonic_now();
1763
1764 for (int i = 0; i < shuffle_events; ++i) {
Philipp Schradera6712522023-07-05 20:25:11 -07001765 loop->AddTimer([]() {})->Schedule(start +
1766 std::chrono::milliseconds(10));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001767 }
1768
1769 if (setup_order) {
Philipp Schradera6712522023-07-05 20:25:11 -07001770 test_timer->Schedule(start + ::std::chrono::milliseconds(20));
1771 ender_timer->Schedule(start + ::std::chrono::milliseconds(20));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001772 } else {
Philipp Schradera6712522023-07-05 20:25:11 -07001773 ender_timer->Schedule(start + ::std::chrono::milliseconds(20));
1774 test_timer->Schedule(start + ::std::chrono::milliseconds(20));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001775 }
1776 EndEventLoop(loop.get(), ::std::chrono::milliseconds(40));
1777 Run();
1778 }
1779 }
1780 }
1781}
1782
Austin Schuh54cf95f2019-11-29 13:14:18 -08001783// Verifies that the event loop implementations detect when Channel is not a
Brian Silverman631b6262021-11-10 12:25:08 -08001784// pointer into configuration(), or a name doesn't map to a channel in
1785// configuration().
Austin Schuh54cf95f2019-11-29 13:14:18 -08001786TEST_P(AbstractEventLoopDeathTest, InvalidChannel) {
1787 auto loop = MakePrimary();
1788
Tyler Chatow67ddb032020-01-12 14:30:04 -08001789 const Channel *channel = configuration::GetChannel(
1790 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
Austin Schuh54cf95f2019-11-29 13:14:18 -08001791
1792 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1793
1794 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001795 loop->MakeRawSender(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001796 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1797
1798 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001799 loop->MakeSender<TestMessage>("/testbad"),
1800 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1801 " not found in config");
1802
1803 EXPECT_FALSE(loop->TryMakeSender<TestMessage>("/testbad"));
1804
1805 EXPECT_DEATH(
1806 loop->MakeRawFetcher(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001807 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1808
1809 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001810 loop->MakeFetcher<TestMessage>("/testbad"),
1811 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1812 " not found in config");
1813
1814 EXPECT_FALSE(loop->TryMakeFetcher<TestMessage>("/testbad").valid());
1815
1816 EXPECT_DEATH(
Austin Schuh54cf95f2019-11-29 13:14:18 -08001817 {
1818 loop->MakeRawWatcher(&channel_copy.message(),
1819 [](const Context, const void *) {});
1820 },
1821 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
Brian Silverman631b6262021-11-10 12:25:08 -08001822
1823 EXPECT_DEATH(
1824 { loop->MakeWatcher("/testbad", [](const TestMessage &) {}); },
1825 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1826 " not found in config");
1827}
1828
1829// Verifies that the event loop handles a channel which is not readable or
1830// writable on the current node nicely.
1831TEST_P(AbstractEventLoopDeathTest, InaccessibleChannel) {
1832 EnableNodes("me");
1833 auto loop = MakePrimary("me");
1834 auto loop2 = Make("them");
1835
1836 const Channel *channel = configuration::GetChannel(
1837 loop->configuration(), "/test_noforward", "aos.TestMessage", "", nullptr);
1838
1839 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1840
1841 EXPECT_DEATH(
1842 loop2->MakeSender<TestMessage>("/test_forward"),
1843 "Channel"
1844 " \\{ \"name\": \"/test_forward\", \"type\": \"aos.TestMessage\" \\}"
1845 " is not able to be sent on this node");
1846
1847 EXPECT_FALSE(loop2->TryMakeSender<TestMessage>("/test_forward"));
1848
1849 EXPECT_DEATH(
1850 loop2->MakeRawFetcher(channel),
1851 "Channel"
1852 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1853 " is not able to be fetched on this node");
1854
1855 EXPECT_DEATH(
1856 loop2->MakeFetcher<TestMessage>("/test_noforward"),
1857 "Channel"
1858 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1859 " is not able to be fetched on this node");
1860
1861 EXPECT_FALSE(loop2->TryMakeFetcher<TestMessage>("/test_noforward").valid());
1862
1863 EXPECT_DEATH(
1864 { loop2->MakeRawWatcher(channel, [](const Context, const void *) {}); },
1865 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1866 "\"source_node\": \"them\" \\}"
1867 " is not able to be watched on this node");
1868
1869 EXPECT_DEATH(
1870 { loop2->MakeWatcher("/test_noforward", [](const TestMessage &) {}); },
1871 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1872 "\"source_node\": \"them\" \\}"
1873 " is not able to be watched on this node");
Austin Schuh54cf95f2019-11-29 13:14:18 -08001874}
1875
Austin Schuhd54780b2020-10-03 16:26:02 -07001876// Verifies that the event loop implementations detect when Channel has an
1877// invalid alignment.
1878TEST_P(AbstractEventLoopDeathTest, InvalidChannelAlignment) {
1879 const char *const kError = "multiple of alignment";
1880 InvalidChannelAlignment();
1881
1882 auto loop = MakePrimary();
1883
1884 const Channel *channel = configuration::GetChannel(
1885 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
1886
1887 EXPECT_DEATH({ loop->MakeRawSender(channel); }, kError);
1888 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); }, kError);
1889
1890 EXPECT_DEATH({ loop->MakeRawFetcher(channel); }, kError);
1891 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); }, kError);
1892
1893 EXPECT_DEATH(
1894 { loop->MakeRawWatcher(channel, [](const Context &, const void *) {}); },
1895 kError);
1896 EXPECT_DEATH({ loop->MakeRawNoArgWatcher(channel, [](const Context &) {}); },
1897 kError);
1898
1899 EXPECT_DEATH({ loop->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
1900 kError);
1901 EXPECT_DEATH({ loop->MakeWatcher("/test", [](const TestMessage &) {}); },
1902 kError);
1903}
1904
Brian Silverman454bc112020-03-05 14:21:25 -08001905// Verify that the send time on a message is roughly right when using a watcher.
Austin Schuh7267c532019-05-19 19:55:53 -07001906TEST_P(AbstractEventLoopTest, MessageSendTime) {
Austin Schuh44019f92019-05-19 19:58:27 -07001907 auto loop1 = MakePrimary();
Austin Schuh7267c532019-05-19 19:55:53 -07001908 auto loop2 = Make();
Austin Schuhad154822019-12-27 15:45:13 -08001909 auto sender = loop2->MakeSender<TestMessage>("/test");
Austin Schuh7267c532019-05-19 19:55:53 -07001910 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
1911
1912 auto test_timer = loop1->AddTimer([&sender]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001913 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1914 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1915 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001916 msg.CheckOk(msg.Send(builder.Finish()));
Alex Perrycb7da4b2019-08-28 19:35:56 -07001917 });
1918
Austin Schuhad154822019-12-27 15:45:13 -08001919 bool triggered = false;
Brian Silverman454bc112020-03-05 14:21:25 -08001920 loop1->MakeWatcher("/test", [&](const TestMessage &msg) {
Austin Schuhad154822019-12-27 15:45:13 -08001921 // Confirm that the data pointer makes sense from a watcher, and all the
1922 // timestamps look right.
1923 EXPECT_GT(&msg, loop1->context().data);
1924 EXPECT_EQ(loop1->context().monotonic_remote_time,
1925 loop1->context().monotonic_event_time);
1926 EXPECT_EQ(loop1->context().realtime_remote_time,
1927 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001928 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhac6d89e2024-03-27 14:56:09 -07001929 EXPECT_EQ(loop1->context().monotonic_remote_transmit_time,
1930 monotonic_clock::min_time);
Austin Schuhad154822019-12-27 15:45:13 -08001931
1932 const aos::monotonic_clock::time_point monotonic_now =
1933 loop1->monotonic_now();
Tyler Chatow67ddb032020-01-12 14:30:04 -08001934 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08001935
1936 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1937 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1938 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1939 monotonic_now);
1940 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1941 realtime_now);
1942
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001943 EXPECT_LT(&msg, reinterpret_cast<const void *>(
1944 reinterpret_cast<const char *>(loop1->context().data) +
Austin Schuhad154822019-12-27 15:45:13 -08001945 loop1->context().size));
Brian Silverman4f4e0612020-08-12 19:54:41 -07001946 if (read_method() == ReadMethod::PIN) {
1947 EXPECT_GE(loop1->context().buffer_index, 0);
1948 EXPECT_LT(loop1->context().buffer_index,
1949 loop1->NumberBuffers(
1950 configuration::GetChannel(loop1->configuration(), "/test",
1951 "aos.TestMessage", "", nullptr)));
1952 } else {
1953 EXPECT_EQ(-1, loop1->context().buffer_index);
1954 }
Austin Schuhad154822019-12-27 15:45:13 -08001955 triggered = true;
Austin Schuh7267c532019-05-19 19:55:53 -07001956 });
1957
Philipp Schradera6712522023-07-05 20:25:11 -07001958 test_timer->Schedule(loop1->monotonic_now() + ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07001959
1960 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
Austin Schuh44019f92019-05-19 19:58:27 -07001961 Run();
Austin Schuh7267c532019-05-19 19:55:53 -07001962
Austin Schuhad154822019-12-27 15:45:13 -08001963 EXPECT_TRUE(triggered);
1964
Brian Silverman454bc112020-03-05 14:21:25 -08001965 ASSERT_TRUE(fetcher.Fetch());
1966
1967 monotonic_clock::duration monotonic_time_offset =
1968 fetcher.context().monotonic_event_time -
1969 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1970 realtime_clock::duration realtime_time_offset =
1971 fetcher.context().realtime_event_time -
1972 (loop1->realtime_now() - ::std::chrono::seconds(1));
1973
1974 EXPECT_EQ(fetcher.context().realtime_event_time,
1975 fetcher.context().realtime_remote_time);
1976 EXPECT_EQ(fetcher.context().monotonic_event_time,
1977 fetcher.context().monotonic_remote_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07001978 EXPECT_EQ(fetcher.context().monotonic_remote_transmit_time,
1979 monotonic_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001980 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001981
1982 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1983 << ": Got "
1984 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1985 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1986 // Confirm that the data pointer makes sense.
1987 EXPECT_GT(fetcher.get(), fetcher.context().data);
1988 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001989 reinterpret_cast<const void *>(
1990 reinterpret_cast<const char *>(fetcher.context().data) +
Brian Silverman454bc112020-03-05 14:21:25 -08001991 fetcher.context().size));
1992 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1993 << ": Got "
1994 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1995 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1996
1997 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1998 << ": Got "
1999 << fetcher.context().realtime_event_time.time_since_epoch().count()
2000 << " expected " << loop1->realtime_now().time_since_epoch().count();
2001 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
2002 << ": Got "
2003 << fetcher.context().realtime_event_time.time_since_epoch().count()
2004 << " expected " << loop1->realtime_now().time_since_epoch().count();
2005}
2006
2007// Verify that the send time on a message is roughly right when using a no-arg
2008// watcher. To get a message, we need to use a fetcher to actually access the
2009// message. This is also the main use case for no-arg fetchers.
2010TEST_P(AbstractEventLoopTest, MessageSendTimeNoArg) {
2011 auto loop1 = MakePrimary();
2012 auto loop2 = Make();
2013 auto sender = loop2->MakeSender<TestMessage>("/test");
2014 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
2015
2016 auto test_timer = loop1->AddTimer([&sender]() {
2017 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2018 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2019 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07002020 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -08002021 });
2022
2023 bool triggered = false;
2024 loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {
2025 // Confirm that we can indeed use a fetcher on this channel from this
2026 // context, and it results in a sane data pointer and timestamps.
2027 ASSERT_TRUE(fetcher.Fetch());
2028
2029 EXPECT_EQ(loop1->context().monotonic_remote_time,
2030 loop1->context().monotonic_event_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07002031 EXPECT_EQ(loop1->context().monotonic_remote_transmit_time,
2032 monotonic_clock::min_time);
Brian Silverman454bc112020-03-05 14:21:25 -08002033 EXPECT_EQ(loop1->context().realtime_remote_time,
2034 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002035 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08002036
2037 const aos::monotonic_clock::time_point monotonic_now =
2038 loop1->monotonic_now();
2039 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
2040
2041 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
2042 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
2043 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
2044 monotonic_now);
2045 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
2046 realtime_now);
2047
2048 triggered = true;
2049 });
2050
Philipp Schradera6712522023-07-05 20:25:11 -07002051 test_timer->Schedule(loop1->monotonic_now() + ::std::chrono::seconds(1));
Brian Silverman454bc112020-03-05 14:21:25 -08002052
2053 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
2054 Run();
2055
2056 ASSERT_TRUE(triggered);
Austin Schuh7267c532019-05-19 19:55:53 -07002057
Alex Perrycb7da4b2019-08-28 19:35:56 -07002058 monotonic_clock::duration monotonic_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08002059 fetcher.context().monotonic_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07002060 (loop1->monotonic_now() - ::std::chrono::seconds(1));
2061 realtime_clock::duration realtime_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08002062 fetcher.context().realtime_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07002063 (loop1->realtime_now() - ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07002064
Austin Schuhad154822019-12-27 15:45:13 -08002065 EXPECT_EQ(fetcher.context().realtime_event_time,
2066 fetcher.context().realtime_remote_time);
2067 EXPECT_EQ(fetcher.context().monotonic_event_time,
2068 fetcher.context().monotonic_remote_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07002069 EXPECT_EQ(fetcher.context().monotonic_remote_transmit_time,
2070 monotonic_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002071 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08002072
Alex Perrycb7da4b2019-08-28 19:35:56 -07002073 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
2074 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002075 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh52d325c2019-06-23 18:59:06 -07002076 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07002077 // Confirm that the data pointer makes sense.
2078 EXPECT_GT(fetcher.get(), fetcher.context().data);
2079 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07002080 reinterpret_cast<const void *>(
2081 reinterpret_cast<const char *>(fetcher.context().data) +
Alex Perrycb7da4b2019-08-28 19:35:56 -07002082 fetcher.context().size));
2083 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
2084 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002085 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh7267c532019-05-19 19:55:53 -07002086 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07002087
2088 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
2089 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002090 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07002091 << " expected " << loop1->realtime_now().time_since_epoch().count();
2092 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
2093 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002094 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07002095 << " expected " << loop1->realtime_now().time_since_epoch().count();
Austin Schuh7267c532019-05-19 19:55:53 -07002096}
2097
Austin Schuh52d325c2019-06-23 18:59:06 -07002098// Tests that a couple phased loops run in a row result in the correct offset
2099// and period.
2100TEST_P(AbstractEventLoopTest, PhasedLoopTest) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07002101 // Force a slower rate so we are guaranteed to have reports for our phased
Austin Schuh39788ff2019-12-01 18:22:57 -08002102 // loop.
2103 FLAGS_timing_report_ms = 2000;
2104
Austin Schuh52d325c2019-06-23 18:59:06 -07002105 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2106 const int kCount = 5;
2107
2108 auto loop1 = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08002109 auto loop2 = Make();
2110
2111 Fetcher<timing::Report> report_fetcher =
2112 loop2->MakeFetcher<timing::Report>("/aos");
2113 EXPECT_FALSE(report_fetcher.Fetch());
Austin Schuh52d325c2019-06-23 18:59:06 -07002114
2115 // Collect up a couple of samples.
2116 ::std::vector<::aos::monotonic_clock::time_point> times;
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002117 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
Austin Schuh52d325c2019-06-23 18:59:06 -07002118
2119 // Run kCount iterations.
Austin Schuh39788ff2019-12-01 18:22:57 -08002120 loop1
2121 ->AddPhasedLoop(
2122 [&times, &expected_times, &loop1, this](int count) {
2123 EXPECT_EQ(count, 1);
2124 times.push_back(loop1->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08002125 expected_times.push_back(loop1->context().monotonic_event_time);
Austin Schuh39788ff2019-12-01 18:22:57 -08002126
Austin Schuhad154822019-12-27 15:45:13 -08002127 EXPECT_EQ(loop1->context().monotonic_remote_time,
2128 monotonic_clock::min_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07002129 EXPECT_EQ(loop1->context().monotonic_remote_transmit_time,
2130 monotonic_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002131 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08002132 EXPECT_EQ(loop1->context().realtime_event_time,
2133 realtime_clock::min_time);
2134 EXPECT_EQ(loop1->context().realtime_remote_time,
Austin Schuh39788ff2019-12-01 18:22:57 -08002135 realtime_clock::min_time);
2136 EXPECT_EQ(loop1->context().queue_index, 0xffffffffu);
2137 EXPECT_EQ(loop1->context().size, 0u);
2138 EXPECT_EQ(loop1->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07002139 EXPECT_EQ(loop1->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08002140
2141 if (times.size() == kCount) {
2142 LOG(INFO) << "Exiting";
2143 this->Exit();
2144 }
2145 },
2146 chrono::seconds(1), kOffset)
2147 ->set_name("Test loop");
Austin Schuh52d325c2019-06-23 18:59:06 -07002148
2149 // Add a delay to make sure that delay during startup doesn't result in a
2150 // "missed cycle".
2151 SleepFor(chrono::seconds(2));
2152
2153 Run();
2154
2155 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07002156 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
2157 ASSERT_EQ(times.size(), expected_times.size());
2158 ASSERT_EQ((times.size() % 2), 1);
Austin Schuh52d325c2019-06-23 18:59:06 -07002159
2160 // Grab the middle sample.
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002161 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
Austin Schuh52d325c2019-06-23 18:59:06 -07002162
2163 // Add up all the delays of all the times.
2164 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
2165 for (const ::aos::monotonic_clock::time_point time : times) {
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002166 sum += time - average_time;
Austin Schuh52d325c2019-06-23 18:59:06 -07002167 }
2168
2169 // Average and add to the middle to find the average time.
2170 sum /= times.size();
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002171 average_time += sum;
Austin Schuh52d325c2019-06-23 18:59:06 -07002172
2173 // Compute the offset from the start of the second of the average time. This
2174 // should be pretty close to the offset.
2175 const ::aos::monotonic_clock::duration remainder =
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002176 average_time.time_since_epoch() -
2177 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
Austin Schuh52d325c2019-06-23 18:59:06 -07002178
2179 const chrono::milliseconds kEpsilon(100);
2180 EXPECT_LT(remainder, kOffset + kEpsilon);
2181 EXPECT_GT(remainder, kOffset - kEpsilon);
2182
2183 // Make sure that the average duration is close to 1 second.
2184 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
2185 times.front())
2186 .count() /
2187 static_cast<double>(times.size() - 1),
2188 1.0, 0.1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002189
2190 // Confirm that the ideal wakeup times increment correctly.
2191 for (size_t i = 1; i < expected_times.size(); ++i) {
2192 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
2193 }
2194
2195 for (size_t i = 0; i < expected_times.size(); ++i) {
2196 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
2197 kOffset);
2198 }
2199
2200 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
2201 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08002202
Austin Schuh6bae8252021-02-07 22:01:49 -08002203 if (do_timing_reports() == DoTimingReports::kYes) {
2204 // And, since we are here, check that the timing report makes sense.
2205 // Start by looking for our event loop's timing.
2206 FlatbufferDetachedBuffer<timing::Report> report =
2207 FlatbufferDetachedBuffer<timing::Report>::Empty();
2208 while (report_fetcher.FetchNext()) {
2209 if (report_fetcher->name()->string_view() == "primary") {
2210 report = CopyFlatBuffer(report_fetcher.get());
2211 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002212 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002213
2214 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
2215
2216 EXPECT_EQ(report.message().name()->string_view(), "primary");
2217
2218 ASSERT_NE(report.message().senders(), nullptr);
2219 EXPECT_EQ(report.message().senders()->size(), 2);
2220
2221 ASSERT_NE(report.message().timers(), nullptr);
2222 EXPECT_EQ(report.message().timers()->size(), 1);
2223
2224 // Make sure there is a single phased loop report with our report in it.
2225 ASSERT_NE(report.message().phased_loops(), nullptr);
2226 ASSERT_EQ(report.message().phased_loops()->size(), 1);
2227 EXPECT_EQ(report.message().phased_loops()->Get(0)->name()->string_view(),
2228 "Test loop");
2229 EXPECT_GE(report.message().phased_loops()->Get(0)->count(), 1);
2230 } else {
2231 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002232 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002233}
2234
Milind Upadhyay42589bb2021-05-19 20:05:16 -07002235// Tests that a phased loop responds correctly to a changing offset.
2236TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetTest) {
2237 // Force a slower rate so we are guaranteed to have reports for our phased
2238 // loop.
2239 FLAGS_timing_report_ms = 2000;
2240
2241 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2242 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2243 const int kCount = 5;
2244
2245 auto loop1 = MakePrimary();
2246
2247 // Collect up a couple of samples.
2248 ::std::vector<::aos::monotonic_clock::time_point> times;
2249 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
2250
2251 PhasedLoopHandler *phased_loop;
2252
2253 // Run kCount iterations.
2254 phased_loop = loop1->AddPhasedLoop(
2255 [&phased_loop, &times, &expected_times, &loop1, this, kOffset,
2256 kInterval](int count) {
2257 EXPECT_EQ(count, 1);
2258 times.push_back(loop1->monotonic_now());
2259
2260 expected_times.push_back(loop1->context().monotonic_event_time);
2261
2262 phased_loop->set_interval_and_offset(
2263 kInterval, kOffset - chrono::milliseconds(times.size()));
2264 LOG(INFO) << "new offset: "
2265 << (kOffset - chrono::milliseconds(times.size())).count();
2266
2267 if (times.size() == kCount) {
2268 LOG(INFO) << "Exiting";
2269 this->Exit();
2270 }
2271 },
2272 kInterval, kOffset);
2273 phased_loop->set_name("Test loop");
2274
2275 // Add a delay to make sure that delay during startup doesn't result in a
2276 // "missed cycle".
2277 SleepFor(chrono::seconds(2));
2278
2279 Run();
2280 // Confirm that we got both the right number of samples, and it's odd.
2281 EXPECT_EQ(times.size(), static_cast<size_t>(kCount));
2282 EXPECT_EQ(times.size(), expected_times.size());
2283 EXPECT_EQ((times.size() % 2), 1);
2284
2285 // Grab the middle sample.
2286 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
2287
2288 // Add up all the delays of all the times.
2289 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
2290 for (const ::aos::monotonic_clock::time_point time : times) {
2291 sum += time - average_time;
2292 }
2293
2294 // Average and add to the middle to find the average time.
2295 sum /= times.size();
2296 average_time += sum;
2297
2298 // Compute the offset from the start of the second of the average time. This
2299 // should be pretty close to the offset.
2300 const ::aos::monotonic_clock::duration remainder =
2301 average_time.time_since_epoch() -
2302 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
2303
2304 const chrono::milliseconds kEpsilon(100);
2305 EXPECT_LT(remainder, kOffset + kEpsilon);
2306 EXPECT_GT(remainder, kOffset - kEpsilon);
2307
2308 // Make sure that the average duration is close to 1 second.
2309 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
2310 times.front())
2311 .count() /
2312 static_cast<double>(times.size() - 1),
2313 1.0, 0.1);
2314
2315 // Confirm that the ideal wakeup times increment correctly.
2316 for (size_t i = 1; i < expected_times.size(); ++i) {
2317 LOG(INFO) << i - 1 << ": " << expected_times[i - 1] << ", " << i << ": "
2318 << expected_times[i];
2319 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1) -
2320 chrono::milliseconds(1));
2321 }
2322
2323 for (size_t i = 0; i < expected_times.size(); ++i) {
2324 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
2325 kOffset - chrono::milliseconds(i));
2326 }
2327
2328 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
2329 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
2330}
2331
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002332// Tests that a phased loop responds correctly to a changing offset; sweep
2333// across a variety of potential offset changes, to ensure that we are
2334// exercising a variety of potential cases.
2335TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetSweep) {
2336 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2337 const int kCount = 5;
2338
2339 auto loop1 = MakePrimary();
2340
2341 std::vector<aos::monotonic_clock::duration> offset_options;
2342 for (int ii = 0; ii < kCount; ++ii) {
2343 offset_options.push_back(ii * kInterval / kCount);
2344 }
2345 std::vector<aos::monotonic_clock::duration> offset_sweep;
2346 // Run over all the pair-wise combinations of offsets.
2347 for (int ii = 0; ii < kCount; ++ii) {
2348 for (int jj = 0; jj < kCount; ++jj) {
2349 offset_sweep.push_back(offset_options.at(ii));
2350 offset_sweep.push_back(offset_options.at(jj));
2351 }
2352 }
2353
2354 std::vector<::aos::monotonic_clock::time_point> expected_times;
2355
2356 PhasedLoopHandler *phased_loop;
2357
2358 // Run kCount iterations.
2359 size_t counter = 0;
2360 phased_loop = loop1->AddPhasedLoop(
2361 [&phased_loop, &expected_times, &loop1, this, kInterval, &counter,
2362 offset_sweep](int count) {
2363 EXPECT_EQ(count, 1);
2364 expected_times.push_back(loop1->context().monotonic_event_time);
2365
2366 counter++;
2367
2368 if (counter == offset_sweep.size()) {
2369 LOG(INFO) << "Exiting";
2370 this->Exit();
2371 return;
2372 }
2373
2374 phased_loop->set_interval_and_offset(kInterval,
2375 offset_sweep.at(counter));
2376 },
2377 kInterval, offset_sweep.at(0));
2378
2379 Run();
2380 ASSERT_EQ(expected_times.size(), offset_sweep.size());
2381 for (size_t ii = 1; ii < expected_times.size(); ++ii) {
2382 EXPECT_LE(expected_times.at(ii) - expected_times.at(ii - 1), kInterval);
2383 }
2384}
2385
2386// Tests that a phased loop responds correctly to being rescheduled with now
2387// equal to a time in the past.
2388TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleInPast) {
2389 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2390 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2391
2392 auto loop1 = MakePrimary();
2393
2394 std::vector<::aos::monotonic_clock::time_point> expected_times;
2395
2396 PhasedLoopHandler *phased_loop;
2397
2398 int expected_count = 1;
2399
2400 // Set up a timer that will get run immediately after the phased loop and
2401 // which will attempt to reschedule the phased loop to just before now. This
2402 // should succeed, but will result in 0 cycles elapsing.
2403 TimerHandler *manager_timer =
2404 loop1->AddTimer([&phased_loop, &loop1, &expected_count, this]() {
2405 if (expected_count == 0) {
2406 LOG(INFO) << "Exiting";
2407 this->Exit();
2408 return;
2409 }
2410 phased_loop->Reschedule(loop1->context().monotonic_event_time -
2411 std::chrono::nanoseconds(1));
2412 expected_count = 0;
2413 });
2414
2415 phased_loop = loop1->AddPhasedLoop(
2416 [&expected_count, &expected_times, &loop1, manager_timer](int count) {
2417 EXPECT_EQ(count, expected_count);
2418 expected_times.push_back(loop1->context().monotonic_event_time);
2419
Philipp Schradera6712522023-07-05 20:25:11 -07002420 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002421 },
2422 kInterval, kOffset);
2423 phased_loop->set_name("Test loop");
2424 manager_timer->set_name("Manager timer");
2425
2426 Run();
2427
2428 ASSERT_EQ(2u, expected_times.size());
2429 ASSERT_EQ(expected_times[0], expected_times[1]);
2430}
2431
2432// Tests that a phased loop responds correctly to being rescheduled at the time
2433// when it should be triggering (it should kick the trigger to the next cycle).
2434TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleNow) {
2435 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2436 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2437
2438 auto loop1 = MakePrimary();
2439
2440 std::vector<::aos::monotonic_clock::time_point> expected_times;
2441
2442 PhasedLoopHandler *phased_loop;
2443
2444 bool should_exit = false;
2445 // Set up a timer that will get run immediately after the phased loop and
2446 // which will attempt to reschedule the phased loop to now. This should
2447 // succeed, but will result in no change to the expected behavior (since this
2448 // is the same thing that is actually done internally).
2449 TimerHandler *manager_timer =
2450 loop1->AddTimer([&phased_loop, &loop1, &should_exit, this]() {
2451 if (should_exit) {
2452 LOG(INFO) << "Exiting";
2453 this->Exit();
2454 return;
2455 }
2456 phased_loop->Reschedule(loop1->context().monotonic_event_time);
2457 should_exit = true;
2458 });
2459
2460 phased_loop = loop1->AddPhasedLoop(
2461 [&expected_times, &loop1, manager_timer](int count) {
2462 EXPECT_EQ(count, 1);
2463 expected_times.push_back(loop1->context().monotonic_event_time);
2464
Philipp Schradera6712522023-07-05 20:25:11 -07002465 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002466 },
2467 kInterval, kOffset);
2468 phased_loop->set_name("Test loop");
2469 manager_timer->set_name("Manager timer");
2470
2471 Run();
2472
2473 ASSERT_EQ(2u, expected_times.size());
2474 ASSERT_EQ(expected_times[0] + kInterval, expected_times[1]);
2475}
2476
2477// Tests that a phased loop responds correctly to being rescheduled at a time in
2478// the distant future.
2479TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleFuture) {
2480 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2481 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2482
2483 auto loop1 = MakePrimary();
2484
2485 std::vector<::aos::monotonic_clock::time_point> expected_times;
2486
2487 PhasedLoopHandler *phased_loop;
2488
2489 bool should_exit = false;
2490 int expected_count = 1;
2491 TimerHandler *manager_timer = loop1->AddTimer(
2492 [&expected_count, &phased_loop, &loop1, &should_exit, this, kInterval]() {
2493 if (should_exit) {
2494 LOG(INFO) << "Exiting";
2495 this->Exit();
2496 return;
2497 }
2498 expected_count = 10;
2499 // Knock off 1 ns, since the scheduler rounds up when it is
2500 // scheduled to exactly a loop time.
2501 phased_loop->Reschedule(loop1->context().monotonic_event_time +
2502 kInterval * expected_count -
2503 std::chrono::nanoseconds(1));
2504 should_exit = true;
2505 });
2506
2507 phased_loop = loop1->AddPhasedLoop(
2508 [&expected_times, &loop1, manager_timer, &expected_count](int count) {
2509 EXPECT_EQ(count, expected_count);
2510 expected_times.push_back(loop1->context().monotonic_event_time);
2511
Philipp Schradera6712522023-07-05 20:25:11 -07002512 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002513 },
2514 kInterval, kOffset);
2515 phased_loop->set_name("Test loop");
2516 manager_timer->set_name("Manager timer");
2517
2518 Run();
2519
2520 ASSERT_EQ(2u, expected_times.size());
2521 ASSERT_EQ(expected_times[0] + expected_count * kInterval, expected_times[1]);
2522}
2523
2524// Tests that a phased loop responds correctly to having its phase offset
2525// incremented and then being scheduled after a set time, exercising a pattern
2526// where a phased loop's offset is changed while trying to maintain the trigger
2527// at a consistent period.
2528TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleWithLaterOffset) {
2529 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2530 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2531
2532 auto loop1 = MakePrimary();
2533
2534 std::vector<::aos::monotonic_clock::time_point> expected_times;
2535
2536 PhasedLoopHandler *phased_loop;
2537
2538 bool should_exit = false;
2539 TimerHandler *manager_timer = loop1->AddTimer(
2540 [&phased_loop, &loop1, &should_exit, this, kInterval, kOffset]() {
2541 if (should_exit) {
2542 LOG(INFO) << "Exiting";
2543 this->Exit();
2544 return;
2545 }
2546 // Schedule the next callback to be strictly later than the current time
2547 // + interval / 2, to ensure a consistent frequency.
2548 monotonic_clock::time_point half_time =
2549 loop1->context().monotonic_event_time + kInterval / 2;
2550 phased_loop->set_interval_and_offset(
2551 kInterval, kOffset + std::chrono::nanoseconds(1), half_time);
2552 phased_loop->Reschedule(half_time);
2553 should_exit = true;
2554 });
2555
2556 phased_loop = loop1->AddPhasedLoop(
2557 [&expected_times, &loop1, manager_timer](int count) {
2558 EXPECT_EQ(1, count);
2559 expected_times.push_back(loop1->context().monotonic_event_time);
2560
Philipp Schradera6712522023-07-05 20:25:11 -07002561 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002562 },
2563 kInterval, kOffset);
2564 phased_loop->set_name("Test loop");
2565 manager_timer->set_name("Manager timer");
2566
2567 Run();
2568
2569 ASSERT_EQ(2u, expected_times.size());
2570 ASSERT_EQ(expected_times[0] + kInterval + std::chrono::nanoseconds(1),
2571 expected_times[1]);
2572}
2573
2574// Tests that a phased loop responds correctly to having its phase offset
2575// decremented and then being scheduled after a set time, exercising a pattern
2576// where a phased loop's offset is changed while trying to maintain the trigger
2577// at a consistent period.
2578TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleWithEarlierOffset) {
2579 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2580 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2581
2582 auto loop1 = MakePrimary();
2583
2584 std::vector<::aos::monotonic_clock::time_point> expected_times;
2585
2586 PhasedLoopHandler *phased_loop;
2587
2588 bool should_exit = false;
2589 TimerHandler *manager_timer = loop1->AddTimer(
2590 [&phased_loop, &loop1, &should_exit, this, kInterval, kOffset]() {
2591 if (should_exit) {
2592 LOG(INFO) << "Exiting";
2593 this->Exit();
2594 return;
2595 }
2596 // Schedule the next callback to be strictly later than the current time
2597 // + interval / 2, to ensure a consistent frequency.
2598 const aos::monotonic_clock::time_point half_time =
2599 loop1->context().monotonic_event_time + kInterval / 2;
2600 phased_loop->set_interval_and_offset(
2601 kInterval, kOffset - std::chrono::nanoseconds(1), half_time);
2602 phased_loop->Reschedule(half_time);
2603 should_exit = true;
2604 });
2605
2606 phased_loop = loop1->AddPhasedLoop(
2607 [&expected_times, &loop1, manager_timer](int count) {
2608 EXPECT_EQ(1, count);
2609 expected_times.push_back(loop1->context().monotonic_event_time);
2610
Philipp Schradera6712522023-07-05 20:25:11 -07002611 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002612 },
2613 kInterval, kOffset);
2614 phased_loop->set_name("Test loop");
2615 manager_timer->set_name("Manager timer");
2616
2617 Run();
2618
2619 ASSERT_EQ(2u, expected_times.size());
2620 ASSERT_EQ(expected_times[0] + kInterval - std::chrono::nanoseconds(1),
2621 expected_times[1]);
2622}
2623
Austin Schuh39788ff2019-12-01 18:22:57 -08002624// Tests that senders count correctly in the timing report.
2625TEST_P(AbstractEventLoopTest, SenderTimingReport) {
2626 FLAGS_timing_report_ms = 1000;
2627 auto loop1 = MakePrimary();
2628
2629 auto loop2 = Make("watcher_loop");
2630 loop2->MakeWatcher("/test", [](const TestMessage &) {});
2631
2632 auto loop3 = Make();
2633
2634 Fetcher<timing::Report> report_fetcher =
2635 loop3->MakeFetcher<timing::Report>("/aos");
2636 EXPECT_FALSE(report_fetcher.Fetch());
2637
2638 auto sender = loop1->MakeSender<TestMessage>("/test");
2639
James Kuszmaul78514332022-04-06 15:08:34 -07002640 // Sanity check channel frequencies to ensure that we've designed the test
2641 // correctly.
2642 ASSERT_EQ(800, sender.channel()->frequency());
Austin Schuhfff9c3a2023-06-16 18:48:23 -07002643 ASSERT_EQ(2000000000, configuration::ChannelStorageDuration(
2644 loop1->configuration(), sender.channel())
2645 .count());
James Kuszmaul78514332022-04-06 15:08:34 -07002646 constexpr int kMaxAllowedMessages = 800 * 2;
2647 constexpr int kSendMessages = kMaxAllowedMessages * 2;
2648 constexpr int kDroppedMessages = kSendMessages - kMaxAllowedMessages;
2649
Austin Schuh39788ff2019-12-01 18:22:57 -08002650 // Add a timer to actually quit.
2651 auto test_timer = loop1->AddTimer([&sender]() {
James Kuszmaul78514332022-04-06 15:08:34 -07002652 for (int i = 0; i < kSendMessages; ++i) {
Austin Schuh39788ff2019-12-01 18:22:57 -08002653 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2654 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2655 builder.add_value(200 + i);
James Kuszmaul78514332022-04-06 15:08:34 -07002656 if (i < kMaxAllowedMessages) {
2657 msg.CheckOk(msg.Send(builder.Finish()));
2658 } else {
2659 EXPECT_EQ(RawSender::Error::kMessagesSentTooFast,
2660 msg.Send(builder.Finish()));
2661 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002662 }
2663 });
2664
2665 // Quit after 1 timing report, mid way through the next cycle.
2666 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2667
2668 loop1->OnRun([&test_timer, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002669 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1500));
Austin Schuh39788ff2019-12-01 18:22:57 -08002670 });
2671
2672 Run();
2673
Austin Schuh6bae8252021-02-07 22:01:49 -08002674 if (do_timing_reports() == DoTimingReports::kYes) {
2675 // And, since we are here, check that the timing report makes sense.
2676 // Start by looking for our event loop's timing.
2677 FlatbufferDetachedBuffer<timing::Report> primary_report =
2678 FlatbufferDetachedBuffer<timing::Report>::Empty();
2679 while (report_fetcher.FetchNext()) {
Austin Schuh8902fa52021-03-14 22:39:24 -07002680 VLOG(1) << "Report " << FlatbufferToJson(report_fetcher.get());
Austin Schuh6bae8252021-02-07 22:01:49 -08002681 if (report_fetcher->name()->string_view() == "primary") {
2682 primary_report = CopyFlatBuffer(report_fetcher.get());
2683 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002684 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002685
Austin Schuh8902fa52021-03-14 22:39:24 -07002686 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
Austin Schuh6bae8252021-02-07 22:01:49 -08002687
2688 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2689
2690 ASSERT_NE(primary_report.message().senders(), nullptr);
2691 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2692
2693 // Confirm that the sender looks sane.
2694 EXPECT_EQ(
2695 loop1->configuration()
2696 ->channels()
2697 ->Get(primary_report.message().senders()->Get(0)->channel_index())
2698 ->name()
2699 ->string_view(),
2700 "/test");
James Kuszmaul78514332022-04-06 15:08:34 -07002701 EXPECT_EQ(primary_report.message().senders()->Get(0)->count(),
2702 kMaxAllowedMessages);
2703 ASSERT_TRUE(primary_report.message().senders()->Get(0)->has_error_counts());
2704 ASSERT_EQ(
2705 primary_report.message().senders()->Get(0)->error_counts()->size(), 2u);
2706 EXPECT_EQ(
2707 primary_report.message()
2708 .senders()
2709 ->Get(0)
2710 ->error_counts()
2711 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2712 ->count(),
2713 kDroppedMessages)
2714 << aos::FlatbufferToJson(primary_report);
2715 EXPECT_EQ(primary_report.message()
2716 .senders()
2717 ->Get(0)
2718 ->error_counts()
2719 ->Get(static_cast<size_t>(timing::SendError::INVALID_REDZONE))
2720 ->count(),
2721 0);
Austin Schuh6bae8252021-02-07 22:01:49 -08002722
2723 // Confirm that the timing primary_report sender looks sane.
2724 EXPECT_EQ(
2725 loop1->configuration()
2726 ->channels()
2727 ->Get(primary_report.message().senders()->Get(1)->channel_index())
2728 ->name()
2729 ->string_view(),
2730 "/aos");
2731 EXPECT_EQ(primary_report.message().senders()->Get(1)->count(), 1);
2732
2733 ASSERT_NE(primary_report.message().timers(), nullptr);
2734 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2735
2736 // Make sure there are no phased loops or watchers.
2737 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2738 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2739 } else {
2740 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002741 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002742}
2743
James Kuszmaul93abac12022-04-14 15:05:10 -07002744// Tests that the RawSender::Send(void*, size_t) overload tracks things properly
2745// in its timing report.
2746TEST_P(AbstractEventLoopTest, CopySenderTimingReport) {
2747 gflags::FlagSaver flag_saver;
2748 FLAGS_timing_report_ms = 1000;
2749 auto loop1 = Make();
2750 auto loop2 = MakePrimary();
2751
2752 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2753 JsonToFlatbuffer<TestMessage>("{}");
2754
2755 std::unique_ptr<aos::RawSender> sender =
2756 loop2->MakeRawSender(configuration::GetChannel(
2757 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
2758
2759 Fetcher<timing::Report> report_fetcher =
2760 loop1->MakeFetcher<timing::Report>("/aos");
2761 EXPECT_FALSE(report_fetcher.Fetch());
2762
2763 loop2->OnRun([&]() {
2764 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
2765 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2766 RawSender::Error::kOk);
2767 }
2768 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2769 RawSender::Error::kMessagesSentTooFast);
2770 });
2771 // Quit after 1 timing report, mid way through the next cycle.
2772 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
2773
2774 Run();
2775
2776 if (do_timing_reports() == DoTimingReports::kYes) {
2777 // Check that the sent too fast actually got recorded by the timing report.
2778 FlatbufferDetachedBuffer<timing::Report> primary_report =
2779 FlatbufferDetachedBuffer<timing::Report>::Empty();
2780 while (report_fetcher.FetchNext()) {
2781 if (report_fetcher->name()->string_view() == "primary") {
2782 primary_report = CopyFlatBuffer(report_fetcher.get());
2783 }
2784 }
2785
2786 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2787
2788 ASSERT_NE(primary_report.message().senders(), nullptr);
2789 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2790 EXPECT_EQ(
2791 primary_report.message()
2792 .senders()
2793 ->Get(0)
2794 ->error_counts()
2795 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2796 ->count(),
2797 1);
2798 }
2799}
2800
Austin Schuhe0ab4de2023-05-03 08:05:08 -07002801// Tests that the RawSender::Send(SharedSpan) overload works.
2802TEST_P(AbstractEventLoopTest, SharedSenderTimingReport) {
2803 gflags::FlagSaver flag_saver;
2804 FLAGS_timing_report_ms = 1000;
2805 auto loop1 = Make();
2806 auto loop2 = MakePrimary();
2807
2808 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2809 JsonToFlatbuffer<TestMessage>("{}");
2810
2811 std::unique_ptr<aos::RawSender> sender =
2812 loop2->MakeRawSender(configuration::GetChannel(
2813 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
2814
2815 Fetcher<timing::Report> report_fetcher =
2816 loop1->MakeFetcher<timing::Report>("/aos");
2817 EXPECT_FALSE(report_fetcher.Fetch());
2818
2819 loop2->OnRun([&]() {
2820 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
2821 auto shared_span = MakeSharedSpan(kMessage.span().size());
2822 memcpy(shared_span.second.data(), kMessage.span().data(),
2823 kMessage.span().size());
2824 EXPECT_EQ(sender->Send(std::move(shared_span.first)),
2825 RawSender::Error::kOk);
2826 }
2827 auto shared_span = MakeSharedSpan(kMessage.span().size());
2828 memcpy(shared_span.second.data(), kMessage.span().data(),
2829 kMessage.span().size());
2830 EXPECT_EQ(sender->Send(std::move(shared_span.first)),
2831 RawSender::Error::kMessagesSentTooFast);
2832 });
2833 // Quit after 1 timing report, mid way through the next cycle.
2834 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
2835
2836 Run();
2837
2838 if (do_timing_reports() == DoTimingReports::kYes) {
2839 // Check that the sent too fast actually got recorded by the timing report.
2840 FlatbufferDetachedBuffer<timing::Report> primary_report =
2841 FlatbufferDetachedBuffer<timing::Report>::Empty();
2842 while (report_fetcher.FetchNext()) {
2843 if (report_fetcher->name()->string_view() == "primary") {
2844 primary_report = CopyFlatBuffer(report_fetcher.get());
2845 }
2846 }
2847
2848 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2849
2850 ASSERT_NE(primary_report.message().senders(), nullptr);
2851 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2852 EXPECT_EQ(
2853 primary_report.message()
2854 .senders()
2855 ->Get(0)
2856 ->error_counts()
2857 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2858 ->count(),
2859 1);
2860 }
2861}
2862
Austin Schuh39788ff2019-12-01 18:22:57 -08002863// Tests that senders count correctly in the timing report.
2864TEST_P(AbstractEventLoopTest, WatcherTimingReport) {
2865 FLAGS_timing_report_ms = 1000;
2866 auto loop1 = MakePrimary();
2867 loop1->MakeWatcher("/test", [](const TestMessage &) {});
2868
2869 auto loop2 = Make("sender_loop");
2870
2871 auto loop3 = Make();
2872
2873 Fetcher<timing::Report> report_fetcher =
2874 loop3->MakeFetcher<timing::Report>("/aos");
2875 EXPECT_FALSE(report_fetcher.Fetch());
2876
2877 auto sender = loop2->MakeSender<TestMessage>("/test");
2878
2879 // Add a timer to actually quit.
2880 auto test_timer = loop1->AddTimer([&sender]() {
2881 for (int i = 0; i < 10; ++i) {
2882 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2883 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2884 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002885 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002886 }
2887 });
2888
2889 // Quit after 1 timing report, mid way through the next cycle.
2890 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2891
2892 loop1->OnRun([&test_timer, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002893 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1500));
Austin Schuh39788ff2019-12-01 18:22:57 -08002894 });
2895
2896 Run();
2897
Austin Schuh6bae8252021-02-07 22:01:49 -08002898 if (do_timing_reports() == DoTimingReports::kYes) {
2899 // And, since we are here, check that the timing report makes sense.
2900 // Start by looking for our event loop's timing.
2901 FlatbufferDetachedBuffer<timing::Report> primary_report =
2902 FlatbufferDetachedBuffer<timing::Report>::Empty();
2903 while (report_fetcher.FetchNext()) {
2904 LOG(INFO) << "Report " << FlatbufferToJson(report_fetcher.get());
2905 if (report_fetcher->name()->string_view() == "primary") {
2906 primary_report = CopyFlatBuffer(report_fetcher.get());
2907 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002908 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002909
2910 // Check the watcher report.
2911 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2912
2913 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2914
2915 // Just the timing report timer.
2916 ASSERT_NE(primary_report.message().timers(), nullptr);
2917 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2918
2919 // No phased loops
2920 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2921
2922 ASSERT_NE(primary_report.message().watchers(), nullptr);
2923 ASSERT_EQ(primary_report.message().watchers()->size(), 1);
2924 EXPECT_EQ(primary_report.message().watchers()->Get(0)->count(), 10);
2925 } else {
2926 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002927 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002928}
2929
2930// Tests that fetchers count correctly in the timing report.
2931TEST_P(AbstractEventLoopTest, FetcherTimingReport) {
2932 FLAGS_timing_report_ms = 1000;
2933 auto loop1 = MakePrimary();
2934 auto loop2 = Make("sender_loop");
2935
2936 auto loop3 = Make();
2937
2938 Fetcher<timing::Report> report_fetcher =
2939 loop3->MakeFetcher<timing::Report>("/aos");
2940 EXPECT_FALSE(report_fetcher.Fetch());
2941
2942 auto sender = loop2->MakeSender<TestMessage>("/test");
2943 auto fetcher1 = loop1->MakeFetcher<TestMessage>("/test");
2944 auto fetcher2 = loop1->MakeFetcher<TestMessage>("/test");
2945 fetcher1.Fetch();
2946 fetcher2.Fetch();
2947
2948 // Add a timer to actually quit.
2949 auto test_timer = loop1->AddTimer([&sender]() {
2950 for (int i = 0; i < 10; ++i) {
2951 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2952 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2953 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002954 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002955 }
2956 });
2957
2958 auto test_timer2 = loop1->AddTimer([&fetcher1, &fetcher2]() {
2959 fetcher1.Fetch();
2960 while (fetcher2.FetchNext()) {
2961 }
2962 });
2963
2964 // Quit after 1 timing report, mid way through the next cycle.
2965 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2966
2967 loop1->OnRun([test_timer, test_timer2, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002968 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1400));
2969 test_timer2->Schedule(loop1->monotonic_now() + chrono::milliseconds(1600));
Austin Schuh39788ff2019-12-01 18:22:57 -08002970 });
2971
2972 Run();
2973
Austin Schuh6bae8252021-02-07 22:01:49 -08002974 if (do_timing_reports() == DoTimingReports::kYes) {
2975 // And, since we are here, check that the timing report makes sense.
2976 // Start by looking for our event loop's timing.
2977 FlatbufferDetachedBuffer<timing::Report> primary_report =
2978 FlatbufferDetachedBuffer<timing::Report>::Empty();
2979 while (report_fetcher.FetchNext()) {
2980 if (report_fetcher->name()->string_view() == "primary") {
2981 primary_report = CopyFlatBuffer(report_fetcher.get());
2982 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002983 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002984
2985 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2986
2987 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2988
2989 ASSERT_NE(primary_report.message().senders(), nullptr);
2990 EXPECT_EQ(primary_report.message().senders()->size(), 2);
2991
2992 ASSERT_NE(primary_report.message().timers(), nullptr);
2993 EXPECT_EQ(primary_report.message().timers()->size(), 4);
2994
2995 // Make sure there are no phased loops or watchers.
2996 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2997 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2998
2999 // Now look at the fetchrs.
3000 ASSERT_NE(primary_report.message().fetchers(), nullptr);
3001 ASSERT_EQ(primary_report.message().fetchers()->size(), 2);
3002
3003 EXPECT_EQ(primary_report.message().fetchers()->Get(0)->count(), 1);
3004 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->average(),
3005 0.1);
3006 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->min(),
3007 0.1);
3008 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->max(),
3009 0.1);
3010 EXPECT_EQ(primary_report.message()
3011 .fetchers()
3012 ->Get(0)
3013 ->latency()
3014 ->standard_deviation(),
3015 0.0);
3016
3017 EXPECT_EQ(primary_report.message().fetchers()->Get(1)->count(), 10);
3018 } else {
3019 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08003020 }
Austin Schuh52d325c2019-06-23 18:59:06 -07003021}
3022
Austin Schuh67420a42019-12-21 21:55:04 -08003023// Tests that a raw watcher and raw fetcher can receive messages from a raw
3024// sender without messing up offsets.
3025TEST_P(AbstractEventLoopTest, RawBasic) {
3026 auto loop1 = Make();
3027 auto loop2 = MakePrimary();
3028 auto loop3 = Make();
3029
Austin Schuha9df9ad2021-06-16 14:49:39 -07003030 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3031 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuh67420a42019-12-21 21:55:04 -08003032
3033 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003034 loop1->MakeRawSender(configuration::GetChannel(
3035 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08003036
3037 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003038 loop3->MakeRawFetcher(configuration::GetChannel(
3039 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08003040
Austin Schuha9df9ad2021-06-16 14:49:39 -07003041 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07003042 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
3043 RawSender::Error::kOk);
Austin Schuha9df9ad2021-06-16 14:49:39 -07003044 });
Austin Schuh67420a42019-12-21 21:55:04 -08003045
3046 bool happened = false;
3047 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08003048 configuration::GetChannel(loop2->configuration(), "/test",
3049 "aos.TestMessage", "", nullptr),
Austin Schuha9df9ad2021-06-16 14:49:39 -07003050 [this, &kMessage, &fetcher, &happened](const Context &context,
3051 const void *message) {
Austin Schuh67420a42019-12-21 21:55:04 -08003052 happened = true;
Austin Schuha9df9ad2021-06-16 14:49:39 -07003053 EXPECT_EQ(
3054 kMessage.span(),
3055 absl::Span<const uint8_t>(
3056 reinterpret_cast<const uint8_t *>(message), context.size));
3057 EXPECT_EQ(message, context.data);
Austin Schuh67420a42019-12-21 21:55:04 -08003058
3059 ASSERT_TRUE(fetcher->Fetch());
3060
Austin Schuha9df9ad2021-06-16 14:49:39 -07003061 EXPECT_EQ(kMessage.span(),
3062 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
3063 fetcher->context().data),
3064 fetcher->context().size));
Austin Schuh67420a42019-12-21 21:55:04 -08003065
3066 this->Exit();
3067 });
3068
3069 EXPECT_FALSE(happened);
3070 Run();
3071 EXPECT_TRUE(happened);
3072}
3073
Austin Schuhad154822019-12-27 15:45:13 -08003074// Tests that a raw watcher and raw fetcher can receive messages from a raw
Brian Silvermanbf889922021-11-10 12:41:57 -08003075// sender without messing up offsets, using the RawSpan overload.
3076TEST_P(AbstractEventLoopTest, RawBasicSharedSpan) {
3077 auto loop1 = Make();
3078 auto loop2 = MakePrimary();
3079 auto loop3 = Make();
3080
3081 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3082 JsonToFlatbuffer<TestMessage>("{}");
3083
3084 std::unique_ptr<aos::RawSender> sender =
3085 loop1->MakeRawSender(configuration::GetChannel(
3086 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
3087
3088 std::unique_ptr<aos::RawFetcher> fetcher =
3089 loop3->MakeRawFetcher(configuration::GetChannel(
3090 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
3091
3092 loop2->OnRun([&]() {
Austin Schuhe0ab4de2023-05-03 08:05:08 -07003093 auto shared_span = MakeSharedSpan(kMessage.span().size());
3094 memcpy(shared_span.second.data(), kMessage.span().data(),
3095 kMessage.span().size());
3096 sender->CheckOk(sender->Send(std::move(shared_span.first)));
Brian Silvermanbf889922021-11-10 12:41:57 -08003097 });
3098
3099 bool happened = false;
3100 loop2->MakeRawWatcher(
3101 configuration::GetChannel(loop2->configuration(), "/test",
3102 "aos.TestMessage", "", nullptr),
3103 [this, &kMessage, &fetcher, &happened](const Context &context,
3104 const void *message) {
3105 happened = true;
3106 EXPECT_EQ(
3107 kMessage.span(),
3108 absl::Span<const uint8_t>(
3109 reinterpret_cast<const uint8_t *>(message), context.size));
3110 EXPECT_EQ(message, context.data);
3111
3112 ASSERT_TRUE(fetcher->Fetch());
3113
3114 EXPECT_EQ(kMessage.span(),
3115 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
3116 fetcher->context().data),
3117 fetcher->context().size));
3118
3119 this->Exit();
3120 });
3121
3122 EXPECT_FALSE(happened);
3123 Run();
3124 EXPECT_TRUE(happened);
3125}
3126
3127// Tests that a raw watcher and raw fetcher can receive messages from a raw
Austin Schuhad154822019-12-27 15:45:13 -08003128// sender with remote times filled out.
3129TEST_P(AbstractEventLoopTest, RawRemoteTimes) {
3130 auto loop1 = Make();
3131 auto loop2 = MakePrimary();
3132 auto loop3 = Make();
3133
Austin Schuha9df9ad2021-06-16 14:49:39 -07003134 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3135 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08003136
3137 const aos::monotonic_clock::time_point monotonic_remote_time =
3138 aos::monotonic_clock::time_point(chrono::seconds(1501));
3139 const aos::realtime_clock::time_point realtime_remote_time =
3140 aos::realtime_clock::time_point(chrono::seconds(3132));
Austin Schuhac6d89e2024-03-27 14:56:09 -07003141 const aos::monotonic_clock::time_point monotonic_remote_transmit_time =
3142 aos::monotonic_clock::time_point(chrono::seconds(1601));
Austin Schuhb5c6f972021-03-14 21:53:07 -07003143 const uint32_t remote_queue_index = 0x254971;
Austin Schuha9012be2021-07-21 15:19:11 -07003144 const UUID source_boot_uuid = UUID::Random();
Austin Schuhad154822019-12-27 15:45:13 -08003145
3146 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003147 loop1->MakeRawSender(configuration::GetChannel(
3148 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08003149
3150 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003151 loop3->MakeRawFetcher(configuration::GetChannel(
3152 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08003153
3154 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07003155 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size(),
3156 monotonic_remote_time, realtime_remote_time,
Austin Schuhac6d89e2024-03-27 14:56:09 -07003157 monotonic_remote_transmit_time, remote_queue_index,
3158 source_boot_uuid),
milind1f1dca32021-07-03 13:50:07 -07003159 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08003160 });
3161
3162 bool happened = false;
3163 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08003164 configuration::GetChannel(loop2->configuration(), "/test",
3165 "aos.TestMessage", "", nullptr),
Austin Schuhac6d89e2024-03-27 14:56:09 -07003166 [this, monotonic_remote_time, realtime_remote_time,
3167 monotonic_remote_transmit_time, source_boot_uuid, remote_queue_index,
3168 &fetcher, &happened](const Context &context, const void * /*message*/) {
Austin Schuhad154822019-12-27 15:45:13 -08003169 happened = true;
3170 EXPECT_EQ(monotonic_remote_time, context.monotonic_remote_time);
3171 EXPECT_EQ(realtime_remote_time, context.realtime_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07003172 EXPECT_EQ(source_boot_uuid, context.source_boot_uuid);
Austin Schuhb5c6f972021-03-14 21:53:07 -07003173 EXPECT_EQ(remote_queue_index, context.remote_queue_index);
Austin Schuhad154822019-12-27 15:45:13 -08003174
3175 ASSERT_TRUE(fetcher->Fetch());
3176 EXPECT_EQ(monotonic_remote_time,
3177 fetcher->context().monotonic_remote_time);
3178 EXPECT_EQ(realtime_remote_time,
3179 fetcher->context().realtime_remote_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07003180 EXPECT_EQ(monotonic_remote_transmit_time,
3181 fetcher->context().monotonic_remote_transmit_time);
Austin Schuhad154822019-12-27 15:45:13 -08003182
3183 this->Exit();
3184 });
3185
3186 EXPECT_FALSE(happened);
3187 Run();
3188 EXPECT_TRUE(happened);
Austin Schuhac6d89e2024-03-27 14:56:09 -07003189
3190 // Confirm everything goes back.
3191 EXPECT_EQ(loop2->context().monotonic_event_time, monotonic_clock::min_time);
3192 EXPECT_EQ(loop2->context().monotonic_remote_time, monotonic_clock::min_time);
3193 EXPECT_EQ(loop2->context().monotonic_remote_transmit_time,
3194 monotonic_clock::min_time);
3195 EXPECT_EQ(loop2->context().realtime_event_time, realtime_clock::min_time);
3196 EXPECT_EQ(loop2->context().realtime_remote_time, realtime_clock::min_time);
3197 EXPECT_EQ(loop2->context().source_boot_uuid, loop2->boot_uuid());
3198 EXPECT_EQ(loop2->context().queue_index, 0xffffffffu);
3199 EXPECT_EQ(loop2->context().size, 0u);
3200 EXPECT_EQ(loop2->context().data, nullptr);
3201 EXPECT_EQ(loop2->context().buffer_index, -1);
Austin Schuhad154822019-12-27 15:45:13 -08003202}
3203
3204// Tests that a raw sender fills out sent data.
3205TEST_P(AbstractEventLoopTest, RawSenderSentData) {
3206 auto loop1 = MakePrimary();
3207
Austin Schuha9df9ad2021-06-16 14:49:39 -07003208 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3209 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08003210
3211 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003212 loop1->MakeRawSender(configuration::GetChannel(
3213 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08003214
Tyler Chatow67ddb032020-01-12 14:30:04 -08003215 const aos::monotonic_clock::time_point monotonic_now = loop1->monotonic_now();
3216 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08003217
milind1f1dca32021-07-03 13:50:07 -07003218 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
3219 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08003220
3221 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
3222 EXPECT_LE(sender->monotonic_sent_time(),
3223 monotonic_now + chrono::milliseconds(100));
3224 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
3225 EXPECT_LE(sender->realtime_sent_time(),
3226 realtime_now + chrono::milliseconds(100));
3227 EXPECT_EQ(sender->sent_queue_index(), 0u);
3228
milind1f1dca32021-07-03 13:50:07 -07003229 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
3230 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08003231
3232 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
3233 EXPECT_LE(sender->monotonic_sent_time(),
3234 monotonic_now + chrono::milliseconds(100));
3235 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
3236 EXPECT_LE(sender->realtime_sent_time(),
3237 realtime_now + chrono::milliseconds(100));
3238 EXPECT_EQ(sender->sent_queue_index(), 1u);
3239}
3240
Austin Schuh217a9782019-12-21 23:02:50 -08003241// Tests that not setting up nodes results in no node.
3242TEST_P(AbstractEventLoopTest, NoNode) {
3243 auto loop1 = Make();
3244 auto loop2 = MakePrimary();
3245
3246 EXPECT_EQ(loop1->node(), nullptr);
3247 EXPECT_EQ(loop2->node(), nullptr);
3248}
3249
3250// Tests that setting up nodes results in node being set.
3251TEST_P(AbstractEventLoopTest, Node) {
3252 EnableNodes("me");
3253
3254 auto loop1 = Make();
3255 auto loop2 = MakePrimary();
3256
3257 EXPECT_NE(loop1->node(), nullptr);
3258 EXPECT_NE(loop2->node(), nullptr);
3259}
3260
3261// Tests that watchers work with a node setup.
3262TEST_P(AbstractEventLoopTest, NodeWatcher) {
3263 EnableNodes("me");
3264
3265 auto loop1 = Make();
3266 auto loop2 = Make();
3267 loop1->MakeWatcher("/test", [](const TestMessage &) {});
Tyler Chatow67ddb032020-01-12 14:30:04 -08003268 loop2->MakeRawWatcher(
3269 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
3270 nullptr),
3271 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08003272}
3273
Brian Silverman454bc112020-03-05 14:21:25 -08003274// Tests that no-arg watchers work with a node setup.
3275TEST_P(AbstractEventLoopTest, NodeNoArgWatcher) {
3276 EnableNodes("me");
3277
3278 auto loop1 = Make();
3279 auto loop2 = Make();
3280 loop1->MakeWatcher("/test", [](const TestMessage &) {});
3281 loop2->MakeRawNoArgWatcher(
3282 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
3283 nullptr),
3284 [](const Context &) {});
3285}
3286
Austin Schuh217a9782019-12-21 23:02:50 -08003287// Tests that fetcher work with a node setup.
3288TEST_P(AbstractEventLoopTest, NodeFetcher) {
3289 EnableNodes("me");
3290 auto loop1 = Make();
3291
3292 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
Tyler Chatow67ddb032020-01-12 14:30:04 -08003293 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
3294 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08003295}
3296
3297// Tests that sender work with a node setup.
3298TEST_P(AbstractEventLoopTest, NodeSender) {
3299 EnableNodes("me");
3300 auto loop1 = Make();
3301
3302 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
3303}
3304
Austin Schuhcc6070c2020-10-10 20:25:56 -07003305// Tests that a non-realtime event loop timer is marked non-realtime.
3306TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopTimer) {
3307 auto loop1 = MakePrimary();
3308
3309 // Add a timer to actually quit.
3310 auto test_timer = loop1->AddTimer([this]() {
3311 CheckNotRealtime();
3312 this->Exit();
3313 });
3314
3315 loop1->OnRun([&test_timer, &loop1]() {
3316 CheckNotRealtime();
Philipp Schradera6712522023-07-05 20:25:11 -07003317 test_timer->Schedule(loop1->monotonic_now(),
3318 ::std::chrono::milliseconds(100));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003319 });
3320
3321 Run();
3322}
3323
3324// Tests that a realtime event loop timer is marked realtime.
Austin Schuh9b1d6282022-06-10 17:03:21 -07003325TEST_P(AbstractEventLoopTest, RealtimeSend) {
3326 auto loop1 = MakePrimary();
3327
3328 loop1->SetRuntimeRealtimePriority(1);
3329
3330 auto sender = loop1->MakeSender<TestMessage>("/test2");
3331
3332 loop1->OnRun([&]() {
3333 CheckRealtime();
3334
3335 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3336 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
3337 builder.add_value(200);
3338 msg.CheckOk(msg.Send(builder.Finish()));
3339
3340 this->Exit();
3341 });
3342
3343 Run();
3344}
3345
3346// Tests that a realtime event loop timer is marked realtime.
Austin Schuhcc6070c2020-10-10 20:25:56 -07003347TEST_P(AbstractEventLoopTest, RealtimeEventLoopTimer) {
3348 auto loop1 = MakePrimary();
3349
3350 loop1->SetRuntimeRealtimePriority(1);
3351
3352 // Add a timer to actually quit.
3353 auto test_timer = loop1->AddTimer([this]() {
3354 CheckRealtime();
3355 this->Exit();
3356 });
3357
3358 loop1->OnRun([&test_timer, &loop1]() {
3359 CheckRealtime();
Philipp Schradera6712522023-07-05 20:25:11 -07003360 test_timer->Schedule(loop1->monotonic_now(),
3361 ::std::chrono::milliseconds(100));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003362 });
3363
3364 Run();
3365}
3366
3367// Tests that a non-realtime event loop phased loop is marked non-realtime.
3368TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopPhasedLoop) {
3369 auto loop1 = MakePrimary();
3370
3371 // Add a timer to actually quit.
3372 loop1->AddPhasedLoop(
3373 [this](int) {
3374 CheckNotRealtime();
3375 this->Exit();
3376 },
3377 chrono::seconds(1), chrono::seconds(0));
3378
3379 Run();
3380}
3381
3382// Tests that a realtime event loop phased loop is marked realtime.
3383TEST_P(AbstractEventLoopTest, RealtimeEventLoopPhasedLoop) {
3384 auto loop1 = MakePrimary();
3385
3386 loop1->SetRuntimeRealtimePriority(1);
3387
3388 // Add a timer to actually quit.
3389 loop1->AddPhasedLoop(
3390 [this](int) {
3391 CheckRealtime();
3392 this->Exit();
3393 },
3394 chrono::seconds(1), chrono::seconds(0));
3395
3396 Run();
3397}
3398
3399// Tests that a non-realtime event loop watcher is marked non-realtime.
3400TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopWatcher) {
3401 auto loop1 = MakePrimary();
3402 auto loop2 = Make();
3403
3404 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
3405
3406 loop1->OnRun([&]() {
3407 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3408 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07003409 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003410 });
3411
3412 loop1->MakeWatcher("/test", [&](const TestMessage &) {
3413 CheckNotRealtime();
3414 this->Exit();
3415 });
3416
3417 Run();
3418}
3419
3420// Tests that a realtime event loop watcher is marked realtime.
3421TEST_P(AbstractEventLoopTest, RealtimeEventLoopWatcher) {
3422 auto loop1 = MakePrimary();
3423 auto loop2 = Make();
3424
3425 loop1->SetRuntimeRealtimePriority(1);
3426
3427 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
3428
3429 loop1->OnRun([&]() {
3430 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3431 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07003432 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003433 });
3434
3435 loop1->MakeWatcher("/test", [&](const TestMessage &) {
3436 CheckRealtime();
3437 this->Exit();
3438 });
3439
3440 Run();
3441}
3442
Austin Schuha9012be2021-07-21 15:19:11 -07003443// Tests that event loop's context's monotonic time is set to a value on OnRun.
3444TEST_P(AbstractEventLoopTest, SetContextOnRun) {
3445 auto loop = MakePrimary();
3446
Austin Schuh0debde12022-08-17 16:25:17 -07003447 EXPECT_EQ(loop->context().monotonic_event_time, monotonic_clock::min_time);
3448 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07003449 EXPECT_EQ(loop->context().monotonic_remote_transmit_time,
3450 monotonic_clock::min_time);
Austin Schuh0debde12022-08-17 16:25:17 -07003451 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3452 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3453 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3454 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
3455 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
3456 EXPECT_EQ(loop->context().size, 0u);
3457 EXPECT_EQ(loop->context().data, nullptr);
3458 EXPECT_EQ(loop->context().buffer_index, -1);
3459
Austin Schuha9012be2021-07-21 15:19:11 -07003460 // We want to check that monotonic event time is before monotonic now
3461 // called inside of callback, but after time point obtained callback.
3462 aos::monotonic_clock::time_point monotonic_event_time_on_run;
3463
3464 loop->OnRun([&]() {
3465 monotonic_event_time_on_run = loop->context().monotonic_event_time;
3466 EXPECT_LE(monotonic_event_time_on_run, loop->monotonic_now());
3467 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07003468 EXPECT_EQ(loop->context().monotonic_remote_transmit_time,
3469 monotonic_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07003470 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3471 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3472 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3473 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
Austin Schuh0debde12022-08-17 16:25:17 -07003474 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
Austin Schuha9012be2021-07-21 15:19:11 -07003475 EXPECT_EQ(loop->context().size, 0u);
3476 EXPECT_EQ(loop->context().data, nullptr);
3477 EXPECT_EQ(loop->context().buffer_index, -1);
3478 });
3479
3480 EndEventLoop(loop.get(), ::std::chrono::milliseconds(200));
3481
3482 const aos::monotonic_clock::time_point before_run_time =
3483 loop->monotonic_now();
3484 Run();
3485 EXPECT_GE(monotonic_event_time_on_run, before_run_time);
Austin Schuh0debde12022-08-17 16:25:17 -07003486
3487 EXPECT_EQ(loop->context().monotonic_event_time, monotonic_clock::min_time);
3488 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07003489 EXPECT_EQ(loop->context().monotonic_remote_transmit_time,
3490 monotonic_clock::min_time);
Austin Schuh0debde12022-08-17 16:25:17 -07003491 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3492 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3493 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3494 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
3495 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
3496 EXPECT_EQ(loop->context().size, 0u);
3497 EXPECT_EQ(loop->context().data, nullptr);
3498 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuha9012be2021-07-21 15:19:11 -07003499}
3500
Austin Schuh217a9782019-12-21 23:02:50 -08003501// Tests that watchers fail when created on the wrong node.
3502TEST_P(AbstractEventLoopDeathTest, NodeWatcher) {
3503 EnableNodes("them");
3504
3505 auto loop1 = Make();
3506 auto loop2 = Make();
3507 EXPECT_DEATH({ loop1->MakeWatcher("/test", [](const TestMessage &) {}); },
3508 "node");
3509 EXPECT_DEATH(
3510 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08003511 loop2->MakeRawWatcher(
3512 configuration::GetChannel(configuration(), "/test",
3513 "aos.TestMessage", "", nullptr),
3514 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08003515 },
3516 "node");
Brian Silverman454bc112020-03-05 14:21:25 -08003517 EXPECT_DEATH({ loop1->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
3518 "node");
3519 EXPECT_DEATH(
3520 {
3521 loop2->MakeRawNoArgWatcher(
3522 configuration::GetChannel(configuration(), "/test",
3523 "aos.TestMessage", "", nullptr),
3524 [](const Context &) {});
3525 },
3526 "node");
Austin Schuh217a9782019-12-21 23:02:50 -08003527}
3528
3529// Tests that fetchers fail when created on the wrong node.
3530TEST_P(AbstractEventLoopDeathTest, NodeFetcher) {
3531 EnableNodes("them");
3532 auto loop1 = Make();
3533
3534 EXPECT_DEATH({ auto fetcher = loop1->MakeFetcher<TestMessage>("/test"); },
3535 "node");
3536 EXPECT_DEATH(
3537 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08003538 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
3539 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08003540 },
3541 "node");
3542}
3543
3544// Tests that senders fail when created on the wrong node.
3545TEST_P(AbstractEventLoopDeathTest, NodeSender) {
3546 EnableNodes("them");
3547 auto loop1 = Make();
3548
3549 EXPECT_DEATH(
3550 {
3551 aos::Sender<TestMessage> sender =
3552 loop1->MakeSender<TestMessage>("/test");
3553 },
3554 "node");
3555
3556 // Note: Creating raw senders is always supported. Right now, this lets us
3557 // use them to create message_gateway.
3558}
3559
Brian Silverman341b57e2020-06-23 16:23:18 -07003560// Tests creating multiple Builders from a single Sender at the same time.
3561TEST_P(AbstractEventLoopDeathTest, MultipleBuilders) {
3562 auto loop1 = Make();
3563 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
3564
3565 { auto builder = sender.MakeBuilder(); }
3566 {
3567 auto builder = sender.MakeBuilder();
3568 builder.MakeBuilder<TestMessage>().Finish();
3569 }
3570 {
3571 // Creating this after the first one was destroyed should be fine.
3572 auto builder = sender.MakeBuilder();
3573 builder.MakeBuilder<TestMessage>().Finish();
3574 // But not a second one.
3575 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
James Kuszmaulb1c11052023-11-06 13:20:53 -08003576 "May not have multiple active allocators");
Brian Silverman341b57e2020-06-23 16:23:18 -07003577 }
3578
3579 FlatbufferDetachedBuffer<TestMessage> detached =
3580 flatbuffers::DetachedBuffer();
3581 {
3582 auto builder = sender.MakeBuilder();
3583 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
3584 }
3585 {
3586 // This is the second one, after the detached one, so it should fail.
3587 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
James Kuszmaulb1c11052023-11-06 13:20:53 -08003588 "May not have multiple active allocators");
Brian Silverman341b57e2020-06-23 16:23:18 -07003589 }
3590
3591 // Clear the detached one, and then we should be able to create another.
3592 detached = flatbuffers::DetachedBuffer();
3593 {
3594 auto builder = sender.MakeBuilder();
3595 builder.MakeBuilder<TestMessage>().Finish();
3596 }
3597
3598 // And then detach another one.
3599 {
3600 auto builder = sender.MakeBuilder();
3601 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
3602 }
3603}
3604
3605// Tests sending a buffer detached from a different builder.
3606TEST_P(AbstractEventLoopDeathTest, WrongDetachedBuffer) {
3607 auto loop1 = Make();
3608 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
3609 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
3610
3611 auto builder = sender1.MakeBuilder();
3612 FlatbufferDetachedBuffer<TestMessage> detached =
3613 builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
milind1f1dca32021-07-03 13:50:07 -07003614 EXPECT_DEATH(sender2.CheckOk(sender2.SendDetached(std::move(detached))),
Brian Silverman341b57e2020-06-23 16:23:18 -07003615 "May only send the buffer detached from this Sender");
3616}
3617
James Kuszmaul762e8692023-07-31 14:57:53 -07003618// Tests that senders fail when created on the wrong node.
3619TEST_P(AbstractEventLoopDeathTest, SetVersionWhileRunning) {
3620 auto loop1 = MakePrimary();
3621
3622 loop1->OnRun([&loop1, this]() {
3623 EXPECT_DEATH({ loop1->SetVersionString("abcdef"); },
3624 "timing report while running");
3625 Exit();
3626 });
3627
3628 Run();
3629}
3630
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003631int TestChannelFrequency(EventLoop *event_loop) {
3632 return event_loop->GetChannel<TestMessage>("/test")->frequency();
3633}
3634
3635int TestChannelQueueSize(EventLoop *event_loop) {
Austin Schuhfff9c3a2023-06-16 18:48:23 -07003636 return configuration::QueueSize(event_loop->configuration(),
3637 event_loop->GetChannel<TestMessage>("/test"));
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003638}
3639
3640RawSender::Error SendTestMessage(aos::Sender<TestMessage> &sender) {
3641 aos::Sender<TestMessage>::Builder builder = sender.MakeBuilder();
3642 TestMessage::Builder test_message_builder =
3643 builder.MakeBuilder<TestMessage>();
3644 test_message_builder.add_value(0);
3645 return builder.Send(test_message_builder.Finish());
3646}
3647
3648// Test that sending messages too fast returns
3649// RawSender::Error::kMessagesSentTooFast.
3650TEST_P(AbstractEventLoopTest, SendingMessagesTooFast) {
3651 auto event_loop = MakePrimary();
Austin Schuh63756be2024-02-05 19:51:20 -08003652 event_loop->SetRuntimeRealtimePriority(5);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003653
3654 auto sender = event_loop->MakeSender<TestMessage>("/test");
3655
3656 // Send one message in the beginning, then wait until the
3657 // channel_storage_duration is almost done and start sending messages rapidly,
3658 // having some come in the next chanel_storage_duration. The queue_size is
3659 // 1600, so the 1601st message will be the last valid one (the initial message
3660 // having being sent more than a channel_storage_duration ago), and trying to
3661 // send the 1602nd message should return
3662 // RawSender::Error::kMessagesSentTooFast.
3663 EXPECT_EQ(SendTestMessage(sender), RawSender::Error::kOk);
3664 int msgs_sent = 1;
3665 const int queue_size = TestChannelQueueSize(event_loop.get());
3666
Austin Schuh63756be2024-02-05 19:51:20 -08003667 const int messages_per_ms = 2;
3668 const auto kRepeatOffset = std::chrono::milliseconds(10);
3669 const auto base_offset =
3670 configuration::ChannelStorageDuration(event_loop->configuration(),
3671 sender.channel()) -
3672 (std::chrono::milliseconds(1) * (queue_size / 2) / messages_per_ms);
3673
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003674 const auto timer = event_loop->AddTimer([&]() {
Austin Schuh63756be2024-02-05 19:51:20 -08003675 // Send in bursts to reduce scheduler load to make the test more
3676 // reproducible.
3677 for (int i = 0; i < messages_per_ms * kRepeatOffset.count(); ++i) {
3678 const bool done = (msgs_sent == queue_size + 1);
3679 ASSERT_EQ(SendTestMessage(sender),
3680 done ? RawSender::Error::kMessagesSentTooFast
3681 : RawSender::Error::kOk);
3682 msgs_sent++;
3683 if (done) {
3684 Exit();
3685 return;
3686 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003687 }
3688 });
3689
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003690 event_loop->OnRun([&event_loop, &timer, &base_offset, &kRepeatOffset]() {
Philipp Schradera6712522023-07-05 20:25:11 -07003691 timer->Schedule(event_loop->monotonic_now() + base_offset, kRepeatOffset);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003692 });
3693
3694 Run();
3695}
3696
3697// Tests that we are able to send messages successfully after sending messages
3698// too fast and waiting while continuously attempting to send messages.
3699// Also tests that SendFailureCounter is working correctly in this
3700// situation
3701TEST_P(AbstractEventLoopTest, SendingAfterSendingTooFast) {
3702 auto event_loop = MakePrimary();
Austin Schuh63756be2024-02-05 19:51:20 -08003703 event_loop->SetRuntimeRealtimePriority(5);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003704
3705 auto sender = event_loop->MakeSender<TestMessage>("/test");
3706
Austin Schuh0e96d372023-05-08 10:10:21 -07003707 // We are sending bunches of messages at 100 Hz, so we will be sending too
3708 // fast after queue_size (800) ms. After this, keep sending messages, and
3709 // exactly a channel storage duration (2s) after we send the first message we
3710 // should be able to successfully send a message.
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003711
Austin Schuh0e96d372023-05-08 10:10:21 -07003712 const std::chrono::milliseconds kInterval = std::chrono::milliseconds(10);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003713 const monotonic_clock::duration channel_storage_duration =
Austin Schuhfff9c3a2023-06-16 18:48:23 -07003714 configuration::ChannelStorageDuration(event_loop->configuration(),
3715 sender.channel());
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003716 const int queue_size = TestChannelQueueSize(event_loop.get());
3717
3718 int msgs_sent = 0;
3719 SendFailureCounter counter;
3720 auto start = monotonic_clock::min_time;
3721
3722 event_loop->AddPhasedLoop(
Austin Schuh0e96d372023-05-08 10:10:21 -07003723 [&](int elapsed_cycles) {
3724 // The queue is setup for 800 messages/sec. We want to fill that up at
3725 // a rate of 2000 messages/sec so we make sure we fill it up.
3726 for (int i = 0; i < 2 * kInterval.count() * elapsed_cycles; ++i) {
3727 const auto actual_err = SendTestMessage(sender);
3728 const bool done_waiting = (start != monotonic_clock::min_time &&
3729 sender.monotonic_sent_time() >=
3730 (start + channel_storage_duration));
3731 const auto expected_err =
3732 (msgs_sent < queue_size || done_waiting
3733 ? RawSender::Error::kOk
3734 : RawSender::Error::kMessagesSentTooFast);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003735
Austin Schuh0e96d372023-05-08 10:10:21 -07003736 if (start == monotonic_clock::min_time) {
3737 start = sender.monotonic_sent_time();
3738 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003739
Austin Schuh0e96d372023-05-08 10:10:21 -07003740 ASSERT_EQ(actual_err, expected_err);
3741 counter.Count(actual_err);
3742 msgs_sent++;
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003743
Austin Schuh0e96d372023-05-08 10:10:21 -07003744 EXPECT_EQ(counter.failures(),
3745 msgs_sent <= queue_size
3746 ? 0
3747 : (msgs_sent - queue_size) -
3748 (actual_err == RawSender::Error::kOk ? 1 : 0));
3749 EXPECT_EQ(counter.just_failed(), actual_err != RawSender::Error::kOk);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003750
Austin Schuh0e96d372023-05-08 10:10:21 -07003751 if (done_waiting) {
3752 Exit();
3753 return;
3754 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003755 }
3756 },
3757 kInterval);
3758 Run();
3759}
3760
3761// Tests that RawSender::Error::kMessagesSentTooFast is returned
3762// when messages are sent too fast from senders in different loops
3763TEST_P(AbstractEventLoopTest, SendingTooFastWithMultipleLoops) {
3764 auto loop1 = MakePrimary();
3765 auto loop2 = Make();
3766
3767 auto sender1 = loop1->MakeSender<TestMessage>("/test");
3768 auto sender2 = loop2->MakeSender<TestMessage>("/test");
3769
3770 // Send queue_size messages split between the senders.
3771 const int queue_size = TestChannelQueueSize(loop1.get());
3772 for (int i = 0; i < queue_size / 2; i++) {
3773 ASSERT_EQ(SendTestMessage(sender1), RawSender::Error::kOk);
3774 ASSERT_EQ(SendTestMessage(sender2), RawSender::Error::kOk);
3775 }
3776
3777 // Since queue_size messages have been sent, this should return an error
3778 EXPECT_EQ(SendTestMessage(sender2), RawSender::Error::kMessagesSentTooFast);
3779}
3780
Austin Schuhdda6db72023-06-21 17:02:34 -07003781// Tests that a longer storage durations store more messages.
3782TEST_P(AbstractEventLoopTest, SendingTooFastWithLongDuration) {
3783 auto loop1 = MakePrimary();
3784
3785 auto sender1 = loop1->MakeSender<TestMessage>("/test3");
3786
3787 // Send queue_size messages split between the senders.
3788 const int queue_size =
3789 configuration::QueueSize(loop1->configuration(), sender1.channel());
3790 EXPECT_EQ(queue_size, 100 * 10);
3791 for (int i = 0; i < queue_size; i++) {
3792 ASSERT_EQ(SendTestMessage(sender1), RawSender::Error::kOk);
3793 }
3794
3795 // Since queue_size messages have been sent, and little time has elapsed,
3796 // this should return an error.
3797 EXPECT_EQ(SendTestMessage(sender1), RawSender::Error::kMessagesSentTooFast);
3798}
3799
Stephan Pleinesf63bde82024-01-13 15:59:33 -08003800} // namespace aos::testing