blob: 49755401c466b416c3f56078a1cd0cc17b2fc44d [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>
James Kuszmaul9f998082024-05-23 15:37:35 -07004#include <filesystem>
Brian Silverman4f4e0612020-08-12 19:54:41 -07005#include <unordered_map>
6#include <unordered_set>
Austin Schuh52d325c2019-06-23 18:59:06 -07007
Philipp Schrader790cb542023-07-05 21:06:52 -07008#include "glog/logging.h"
9#include "gmock/gmock.h"
10#include "gtest/gtest.h"
11
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -070012#include "aos/events/test_message_generated.h"
James Kuszmaulb1c11052023-11-06 13:20:53 -080013#include "aos/events/test_message_static.h"
Austin Schuh54cf95f2019-11-29 13:14:18 -080014#include "aos/flatbuffer_merge.h"
Austin Schuhad9e5eb2021-11-19 20:33:55 -080015#include "aos/logging/log_message_generated.h"
16#include "aos/logging/logging.h"
Austin Schuhcc6070c2020-10-10 20:25:56 -070017#include "aos/realtime.h"
Austin Schuh9fe68f72019-08-10 19:32:03 -070018
Stephan Pleinesf63bde82024-01-13 15:59:33 -080019namespace aos::testing {
Austin Schuh52d325c2019-06-23 18:59:06 -070020namespace {
21namespace chrono = ::std::chrono;
22} // namespace
Parker Schuhe4a70d62017-12-27 20:10:20 -080023
Brian Silverman4f4e0612020-08-12 19:54:41 -070024::std::unique_ptr<EventLoop> AbstractEventLoopTest::Make(
25 std::string_view name) {
26 std::string name_copy(name);
27 if (name == "") {
28 name_copy = "loop";
29 name_copy += std::to_string(event_loop_count_);
30 }
31 ++event_loop_count_;
Austin Schuh6bae8252021-02-07 22:01:49 -080032 auto result = factory_->Make(name_copy);
33 if (do_timing_reports() == DoTimingReports::kNo) {
34 result->SkipTimingReport();
35 }
36 return result;
Brian Silverman4f4e0612020-08-12 19:54:41 -070037}
38
39void AbstractEventLoopTest::VerifyBuffers(
40 int number_buffers,
41 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>> fetchers,
42 std::vector<std::reference_wrapper<const Sender<TestMessage>>> senders) {
43 // The buffers which are in a sender.
44 std::unordered_set<int> in_sender;
45 for (const Sender<TestMessage> &sender : senders) {
46 const int this_buffer = sender.buffer_index();
47 CHECK_GE(this_buffer, 0);
48 CHECK_LT(this_buffer, number_buffers);
49 CHECK(in_sender.insert(this_buffer).second) << ": " << this_buffer;
50 }
51
52 if (read_method() != ReadMethod::PIN) {
53 // If we're not using PIN, we can't really verify anything about what
54 // buffers the fetchers have.
55 return;
56 }
57
58 // Mapping from TestMessage::value to buffer index.
59 std::unordered_map<int, int> fetcher_values;
60 for (const Fetcher<TestMessage> &fetcher : fetchers) {
61 if (!fetcher.get()) {
62 continue;
63 }
64 const int this_buffer = fetcher.context().buffer_index;
65 CHECK_GE(this_buffer, 0);
66 CHECK_LT(this_buffer, number_buffers);
67 CHECK(in_sender.count(this_buffer) == 0) << ": " << this_buffer;
68 const auto insert_result = fetcher_values.insert(
69 std::make_pair(fetcher.get()->value(), this_buffer));
70 if (!insert_result.second) {
71 CHECK_EQ(this_buffer, insert_result.first->second);
72 }
73 }
74}
75
Austin Schuh6b6dfa52019-06-12 20:16:20 -070076// Tests that watcher can receive messages from a sender.
Parker Schuhe4a70d62017-12-27 20:10:20 -080077// Also tests that OnRun() works.
78TEST_P(AbstractEventLoopTest, Basic) {
79 auto loop1 = Make();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070080 auto loop2 = MakePrimary();
81
Alex Perrycb7da4b2019-08-28 19:35:56 -070082 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
Austin Schuh6b6dfa52019-06-12 20:16:20 -070083
84 bool happened = false;
85
86 loop2->OnRun([&]() {
87 happened = true;
88
Alex Perrycb7da4b2019-08-28 19:35:56 -070089 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
90 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
91 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -070092 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -070093 });
94
95 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070096 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -070097 this->Exit();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070098 });
99
100 EXPECT_FALSE(happened);
101 Run();
102 EXPECT_TRUE(happened);
103}
104
James Kuszmaulb1c11052023-11-06 13:20:53 -0800105// Tests that watcher can receive messages from a static sender.
106// This confirms that the "static" flatbuffer API works with the EventLoop
107// senders.
108TEST_P(AbstractEventLoopTest, BasicStatic) {
109 auto loop1 = Make();
110 auto loop2 = MakePrimary();
111
112 aos::Sender<TestMessageStatic> sender =
113 loop1->MakeSender<TestMessageStatic>("/test");
114
115 bool happened = false;
116
117 loop2->OnRun([&]() {
118 happened = true;
119
120 aos::Sender<TestMessageStatic>::StaticBuilder msg =
121 sender.MakeStaticBuilder();
James Kuszmauldde65632023-12-07 16:12:26 -0800122 msg->set_value(200);
James Kuszmaulb1c11052023-11-06 13:20:53 -0800123 CHECK(msg.builder()->Verify());
124 msg.CheckOk(msg.Send());
125 });
126
127 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
128 EXPECT_EQ(message.value(), 200);
129 this->Exit();
130 });
131
132 EXPECT_FALSE(happened);
133 Run();
134 EXPECT_TRUE(happened);
135}
136
James Kuszmauld4b4f1d2024-03-13 15:57:35 -0700137// Tests that a static sender's Builder object can be moved safely.
138TEST_P(AbstractEventLoopTest, StaticBuilderMoveConstructor) {
139 auto loop1 = MakePrimary();
140
141 aos::Sender<TestMessageStatic> sender =
142 loop1->MakeSender<TestMessageStatic>("/test");
143 aos::Fetcher<TestMessage> fetcher = loop1->MakeFetcher<TestMessage>("/test");
144 std::optional<aos::Sender<TestMessageStatic>::StaticBuilder> moved_to_builder;
145 {
146 aos::Sender<TestMessageStatic>::StaticBuilder moved_from_builder =
147 sender.MakeStaticBuilder();
148 moved_to_builder.emplace(std::move(moved_from_builder));
149 }
150
151 loop1->OnRun([this, &moved_to_builder]() {
152 moved_to_builder.value()->set_value(200);
153 CHECK(moved_to_builder.value().builder()->Verify());
154 moved_to_builder.value().CheckOk(moved_to_builder.value().Send());
155 this->Exit();
156 });
157
158 ASSERT_FALSE(fetcher.Fetch());
159 Run();
160 ASSERT_TRUE(fetcher.Fetch());
161 EXPECT_EQ(200, fetcher->value());
162}
163
Brian Silverman341b57e2020-06-23 16:23:18 -0700164// Tests that watcher can receive messages from a sender, sent via SendDetached.
165TEST_P(AbstractEventLoopTest, BasicSendDetached) {
166 auto loop1 = Make();
167 auto loop2 = MakePrimary();
168
169 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
170
171 FlatbufferDetachedBuffer<TestMessage> detached =
172 flatbuffers::DetachedBuffer();
173 {
174 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
175 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
176 builder.add_value(100);
177 detached = msg.Detach(builder.Finish());
178 }
179 detached = flatbuffers::DetachedBuffer();
180 {
181 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
182 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
183 builder.add_value(200);
184 detached = msg.Detach(builder.Finish());
185 }
milind1f1dca32021-07-03 13:50:07 -0700186 sender.CheckOk(sender.SendDetached(std::move(detached)));
Brian Silverman341b57e2020-06-23 16:23:18 -0700187
188 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
189 ASSERT_TRUE(fetcher.Fetch());
190 EXPECT_EQ(fetcher->value(), 200);
191}
192
Alexei Strots7cb6e0c2024-02-19 21:24:21 -0800193// Tests that fetcher can receive messages from a sender, sent via SendJson.
194TEST_P(AbstractEventLoopTest, BasicSendJson) {
195 auto loop1 = Make();
196 auto loop2 = MakePrimary();
197
198 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
199 sender.CheckOk(sender.SendJson(R"json({"value":201})json"));
200
201 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
202 ASSERT_TRUE(fetcher.Fetch());
203 EXPECT_EQ(fetcher->value(), 201);
204}
205
206// Tests that invalid JSON isn't sent.
207TEST_P(AbstractEventLoopDeathTest, InvalidSendJson) {
208 auto loop1 = Make();
209 auto loop2 = MakePrimary();
210
211 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
212 EXPECT_DEATH({ sender.CheckOk(sender.SendJson(R"json({"val)json")); },
213 "Invalid JSON");
214}
215
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800216// Verifies that a no-arg watcher will not have a data pointer.
217TEST_P(AbstractEventLoopTest, NoArgNoData) {
218 auto loop1 = Make();
219 auto loop2 = MakePrimary();
220
221 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
222
223 bool happened = false;
224
225 loop2->OnRun([&]() {
226 happened = true;
227
228 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
229 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -0700230 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800231 });
232
233 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
234 EXPECT_GT(loop2->context().size, 0u);
235 EXPECT_EQ(nullptr, loop2->context().data);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700236 EXPECT_EQ(-1, loop2->context().buffer_index);
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800237 this->Exit();
238 });
239
240 EXPECT_FALSE(happened);
241 Run();
242 EXPECT_TRUE(happened);
243}
244
Brian Silverman454bc112020-03-05 14:21:25 -0800245// Tests that no-arg watcher can receive messages from a sender.
246// Also tests that OnRun() works.
247TEST_P(AbstractEventLoopTest, BasicNoArg) {
248 auto loop1 = Make();
249 auto loop2 = MakePrimary();
250
251 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
252
253 bool happened = false;
254
255 loop2->OnRun([&]() {
256 happened = true;
257
258 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
259 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
260 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700261 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -0800262 });
263
264 aos::Fetcher<TestMessage> fetcher = loop2->MakeFetcher<TestMessage>("/test");
265 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
266 ASSERT_TRUE(fetcher.Fetch());
267 EXPECT_EQ(fetcher->value(), 200);
268 this->Exit();
269 });
270
271 EXPECT_FALSE(happened);
272 Run();
273 EXPECT_TRUE(happened);
274}
275
276// Tests that a watcher can be created with an std::function.
277TEST_P(AbstractEventLoopTest, BasicFunction) {
278 auto loop1 = Make();
279 auto loop2 = MakePrimary();
280
281 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
282
283 bool happened = false;
284
285 loop2->OnRun([&]() {
286 happened = true;
287
288 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
289 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
290 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700291 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -0800292 });
293
294 loop2->MakeWatcher("/test", std::function<void(const TestMessage &)>(
295 [&](const TestMessage &message) {
296 EXPECT_EQ(message.value(), 200);
297 this->Exit();
298 }));
299
300 EXPECT_FALSE(happened);
301 Run();
302 EXPECT_TRUE(happened);
303}
304
Brian Silverman0fc69932020-01-24 21:54:02 -0800305// Tests that watcher can receive messages from two senders.
306// Also tests that OnRun() works.
307TEST_P(AbstractEventLoopTest, BasicTwoSenders) {
308 auto loop1 = Make();
309 auto loop2 = MakePrimary();
310
311 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
312 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
313
314 bool happened = false;
315
316 loop2->OnRun([&]() {
317 happened = true;
318
319 {
320 aos::Sender<TestMessage>::Builder msg = sender1.MakeBuilder();
321 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
322 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700323 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman0fc69932020-01-24 21:54:02 -0800324 }
325 {
326 aos::Sender<TestMessage>::Builder msg = sender2.MakeBuilder();
327 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
328 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700329 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman0fc69932020-01-24 21:54:02 -0800330 }
331 });
332
333 int messages_received = 0;
334 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
335 EXPECT_EQ(message.value(), 200);
336 this->Exit();
337 ++messages_received;
338 });
339
340 EXPECT_FALSE(happened);
341 Run();
342 EXPECT_TRUE(happened);
343 EXPECT_EQ(messages_received, 2);
344}
345
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700346// Tests that a fetcher can fetch from a sender.
347// Also tests that OnRun() works.
348TEST_P(AbstractEventLoopTest, FetchWithoutRun) {
349 auto loop1 = Make();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800350 auto loop2 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -0700351 auto loop3 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800352
353 auto sender = loop1->MakeSender<TestMessage>("/test");
354
355 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
356
Austin Schuhbbce72d2019-05-26 15:11:46 -0700357 EXPECT_FALSE(fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -0800358 EXPECT_EQ(fetcher.get(), nullptr);
359
Austin Schuhad154822019-12-27 15:45:13 -0800360 EXPECT_EQ(fetcher.context().monotonic_event_time, monotonic_clock::min_time);
361 EXPECT_EQ(fetcher.context().monotonic_remote_time, monotonic_clock::min_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -0700362 EXPECT_EQ(fetcher.context().monotonic_remote_transmit_time,
363 monotonic_clock::min_time);
Austin Schuhad154822019-12-27 15:45:13 -0800364 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
365 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -0700366 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
Austin Schuh39788ff2019-12-01 18:22:57 -0800367 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
368 EXPECT_EQ(fetcher.context().size, 0u);
369 EXPECT_EQ(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700370 EXPECT_EQ(fetcher.context().buffer_index, -1);
Austin Schuhbbce72d2019-05-26 15:11:46 -0700371
Alex Perrycb7da4b2019-08-28 19:35:56 -0700372 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
373 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
374 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700375 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700376
377 EXPECT_TRUE(fetcher.Fetch());
378 ASSERT_FALSE(fetcher.get() == nullptr);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700379 EXPECT_EQ(fetcher.get()->value(), 200);
Austin Schuh39788ff2019-12-01 18:22:57 -0800380
381 const chrono::milliseconds kEpsilon(100);
382
Austin Schuhad154822019-12-27 15:45:13 -0800383 const aos::monotonic_clock::time_point monotonic_now = loop2->monotonic_now();
384 const aos::realtime_clock::time_point realtime_now = loop2->realtime_now();
385 EXPECT_EQ(fetcher.context().monotonic_event_time,
386 fetcher.context().monotonic_remote_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -0700387 EXPECT_EQ(fetcher.context().monotonic_remote_transmit_time,
388 monotonic_clock::min_time);
Austin Schuhad154822019-12-27 15:45:13 -0800389 EXPECT_EQ(fetcher.context().realtime_event_time,
390 fetcher.context().realtime_remote_time);
391
392 EXPECT_GE(fetcher.context().monotonic_event_time, monotonic_now - kEpsilon);
393 EXPECT_LE(fetcher.context().monotonic_event_time, monotonic_now + kEpsilon);
394 EXPECT_GE(fetcher.context().realtime_event_time, realtime_now - kEpsilon);
395 EXPECT_LE(fetcher.context().realtime_event_time, realtime_now + kEpsilon);
Austin Schuha9012be2021-07-21 15:19:11 -0700396 EXPECT_EQ(fetcher.context().source_boot_uuid, loop2->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -0800397 EXPECT_EQ(fetcher.context().queue_index, 0x0u);
398 EXPECT_EQ(fetcher.context().size, 20u);
399 EXPECT_NE(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700400 if (read_method() == ReadMethod::PIN) {
401 EXPECT_GE(fetcher.context().buffer_index, 0);
402 EXPECT_LT(fetcher.context().buffer_index,
403 loop2->NumberBuffers(fetcher.channel()));
404 } else {
405 EXPECT_EQ(fetcher.context().buffer_index, -1);
406 }
Parker Schuhe4a70d62017-12-27 20:10:20 -0800407}
408
Austin Schuh98ed26f2023-07-19 14:12:28 -0700409std::function<bool(const Context &)> MakeShouldFetch(
410 bool should_fetch, size_t *called_count = nullptr) {
411 return [should_fetch, called_count](const Context &) {
412 if (called_count != nullptr) {
413 (*called_count)++;
414 }
415 return should_fetch;
416 };
417}
418
419// Tests that a fetcher using FetchIf can fetch from a sender.
420TEST_P(AbstractEventLoopTest, FetchIfWithoutRun) {
421 auto loop1 = Make();
422 auto loop2 = Make();
423 auto loop3 = MakePrimary();
424
425 auto sender = loop1->MakeSender<TestMessage>("/test");
426
427 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
428
429 for (const bool should_fetch : {true, false}) {
430 EXPECT_FALSE(fetcher.FetchIf(MakeShouldFetch(should_fetch)));
431 EXPECT_EQ(fetcher.get(), nullptr);
432
433 EXPECT_EQ(fetcher.context().monotonic_event_time,
434 monotonic_clock::min_time);
435 EXPECT_EQ(fetcher.context().monotonic_remote_time,
436 monotonic_clock::min_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -0700437 EXPECT_EQ(fetcher.context().monotonic_remote_transmit_time,
438 monotonic_clock::min_time);
Austin Schuh98ed26f2023-07-19 14:12:28 -0700439 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
440 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
441 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
442 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
443 EXPECT_EQ(fetcher.context().size, 0u);
444 EXPECT_EQ(fetcher.context().data, nullptr);
445 EXPECT_EQ(fetcher.context().buffer_index, -1);
446 }
447
448 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
449 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
450 builder.add_value(200);
451 msg.CheckOk(msg.Send(builder.Finish()));
452
453 // Make sure failing to fetch won't affect anything.
454 EXPECT_FALSE(fetcher.FetchIf(MakeShouldFetch(false)));
455 EXPECT_EQ(fetcher.get(), nullptr);
456
457 EXPECT_EQ(fetcher.context().monotonic_event_time, monotonic_clock::min_time);
458 EXPECT_EQ(fetcher.context().monotonic_remote_time, monotonic_clock::min_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -0700459 EXPECT_EQ(fetcher.context().monotonic_remote_transmit_time,
460 monotonic_clock::min_time);
Austin Schuh98ed26f2023-07-19 14:12:28 -0700461 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
462 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
463 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
464 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
465 EXPECT_EQ(fetcher.context().size, 0u);
466 EXPECT_EQ(fetcher.context().data, nullptr);
467 EXPECT_EQ(fetcher.context().buffer_index, -1);
468
469 // And now confirm we succeed and everything gets set right.
470 EXPECT_TRUE(fetcher.FetchIf(MakeShouldFetch(true)));
471 ASSERT_FALSE(fetcher.get() == nullptr);
472 EXPECT_EQ(fetcher.get()->value(), 200);
473
474 const chrono::milliseconds kEpsilon(100);
475
476 const aos::monotonic_clock::time_point monotonic_now = loop2->monotonic_now();
477 const aos::realtime_clock::time_point realtime_now = loop2->realtime_now();
478 EXPECT_EQ(fetcher.context().monotonic_event_time,
479 fetcher.context().monotonic_remote_time);
480 EXPECT_EQ(fetcher.context().realtime_event_time,
481 fetcher.context().realtime_remote_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -0700482 EXPECT_EQ(fetcher.context().monotonic_remote_transmit_time,
483 monotonic_clock::min_time);
Austin Schuh98ed26f2023-07-19 14:12:28 -0700484
485 EXPECT_GE(fetcher.context().monotonic_event_time, monotonic_now - kEpsilon);
486 EXPECT_LE(fetcher.context().monotonic_event_time, monotonic_now + kEpsilon);
487 EXPECT_GE(fetcher.context().realtime_event_time, realtime_now - kEpsilon);
488 EXPECT_LE(fetcher.context().realtime_event_time, realtime_now + kEpsilon);
489 EXPECT_EQ(fetcher.context().source_boot_uuid, loop2->boot_uuid());
490 EXPECT_EQ(fetcher.context().queue_index, 0x0u);
491 EXPECT_EQ(fetcher.context().size, 20u);
492 EXPECT_NE(fetcher.context().data, nullptr);
493 if (read_method() == ReadMethod::PIN) {
494 EXPECT_GE(fetcher.context().buffer_index, 0);
495 EXPECT_LT(fetcher.context().buffer_index,
496 loop2->NumberBuffers(fetcher.channel()));
497 } else {
498 EXPECT_EQ(fetcher.context().buffer_index, -1);
499 }
500}
501
Austin Schuh3578a2e2019-05-25 18:17:59 -0700502// Tests that watcher will receive all messages sent if they are sent after
503// initialization and before running.
504TEST_P(AbstractEventLoopTest, DoubleSendAtStartup) {
505 auto loop1 = Make();
506 auto loop2 = MakePrimary();
507
508 auto sender = loop1->MakeSender<TestMessage>("/test");
509
510 ::std::vector<int> values;
511
512 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700513 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700514 if (values.size() == 2) {
Austin Schuh9fe68f72019-08-10 19:32:03 -0700515 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -0700516 }
517 });
518
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700519 // Before Run, should be ignored.
Austin Schuh3578a2e2019-05-25 18:17:59 -0700520 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700521 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
522 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
523 builder.add_value(199);
milind1f1dca32021-07-03 13:50:07 -0700524 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700525 }
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700526
527 loop2->OnRun([&]() {
Austin Schuh98ed26f2023-07-19 14:12:28 -0700528 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700529 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
530 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700531 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700532 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700533 }
534 });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700535
536 Run();
537
538 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
539}
540
541// Tests that watcher will not receive messages sent before the watcher is
542// created.
543TEST_P(AbstractEventLoopTest, DoubleSendAfterStartup) {
544 auto loop1 = Make();
545 auto loop2 = MakePrimary();
546
547 auto sender = loop1->MakeSender<TestMessage>("/test");
548
549 ::std::vector<int> values;
550
Austin Schuh98ed26f2023-07-19 14:12:28 -0700551 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700552 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
553 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700554 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700555 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700556 }
557
558 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700559 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700560 });
561
562 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700563 auto test_timer = loop2->AddTimer([this]() { this->Exit(); });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700564 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700565 test_timer->Schedule(loop2->monotonic_now(),
566 ::std::chrono::milliseconds(100));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700567 });
568
569 Run();
570 EXPECT_EQ(0, values.size());
571}
572
Austin Schuhbbce72d2019-05-26 15:11:46 -0700573// Tests that FetchNext gets all the messages sent after it is constructed.
574TEST_P(AbstractEventLoopTest, FetchNext) {
575 auto loop1 = Make();
576 auto loop2 = MakePrimary();
577
578 auto sender = loop1->MakeSender<TestMessage>("/test");
579 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
580
581 ::std::vector<int> values;
582
Austin Schuh98ed26f2023-07-19 14:12:28 -0700583 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700584 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
585 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700586 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700587 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700588 }
589
590 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700591 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700592 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700593 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700594 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700595 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700596 });
597
598 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700599 test_timer->Schedule(loop2->monotonic_now(),
600 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700601 });
602
603 Run();
604 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
605}
606
607// Tests that FetchNext gets no messages sent before it is constructed.
608TEST_P(AbstractEventLoopTest, FetchNextAfterSend) {
609 auto loop1 = Make();
610 auto loop2 = MakePrimary();
611
612 auto sender = loop1->MakeSender<TestMessage>("/test");
613
614 ::std::vector<int> values;
615
Austin Schuh98ed26f2023-07-19 14:12:28 -0700616 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700617 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
618 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700619 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700620 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700621 }
622
623 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
624
625 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700626 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700627 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700628 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700629 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700630 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700631 });
632
633 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700634 test_timer->Schedule(loop2->monotonic_now(),
635 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700636 });
637
638 Run();
639 EXPECT_THAT(0, values.size());
640}
641
Austin Schuh98ed26f2023-07-19 14:12:28 -0700642// Tests that FetchNextIf gets no messages sent before it is constructed.
643TEST_P(AbstractEventLoopTest, FetchNextIfAfterSend) {
644 auto loop1 = Make();
645 auto loop2 = MakePrimary();
646
647 auto sender = loop1->MakeSender<TestMessage>("/test");
648
649 ::std::vector<int> values;
650
651 for (int i = 200; i < 202; ++i) {
652 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
653 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
654 builder.add_value(i);
655 msg.CheckOk(msg.Send(builder.Finish()));
656 }
657
658 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
659
660 // Add a timer to actually quit.
661 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
662 while (fetcher.FetchNextIf(MakeShouldFetch(true))) {
663 values.push_back(fetcher.get()->value());
664 }
665 this->Exit();
666 });
667
668 loop2->OnRun([&test_timer, &loop2]() {
669 test_timer->Schedule(loop2->monotonic_now(),
670 ::std::chrono::milliseconds(100));
671 });
672
673 Run();
674 EXPECT_EQ(0, values.size());
675}
676
Austin Schuhbbce72d2019-05-26 15:11:46 -0700677// Tests that Fetch returns the last message created before the loop was
678// started.
679TEST_P(AbstractEventLoopTest, FetchDataFromBeforeCreation) {
680 auto loop1 = Make();
681 auto loop2 = MakePrimary();
682
683 auto sender = loop1->MakeSender<TestMessage>("/test");
684
685 ::std::vector<int> values;
686
Austin Schuh98ed26f2023-07-19 14:12:28 -0700687 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700688 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
689 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700690 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700691 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700692 }
693
694 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
695
696 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700697 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700698 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700699 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700700 }
701 // Do it again to make sure we don't double fetch.
702 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700703 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700704 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700705 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700706 });
707
708 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700709 test_timer->Schedule(loop2->monotonic_now(),
710 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700711 });
712
713 Run();
714 EXPECT_THAT(values, ::testing::ElementsAreArray({201}));
715}
716
Austin Schuh98ed26f2023-07-19 14:12:28 -0700717// Tests that FetchIf returns the last message created before the loop was
718// started.
719TEST_P(AbstractEventLoopTest, FetchIfDataFromBeforeCreation) {
720 auto loop1 = Make();
721 auto loop2 = MakePrimary();
722
723 auto sender = loop1->MakeSender<TestMessage>("/test");
724
725 ::std::vector<int> values;
726
727 for (int i = 200; i < 202; ++i) {
728 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
729 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
730 builder.add_value(i);
731 msg.CheckOk(msg.Send(builder.Finish()));
732 }
733
734 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
735
736 // Add a timer to actually quit.
737 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
738 if (fetcher.FetchIf(MakeShouldFetch(true))) {
739 values.push_back(fetcher.get()->value());
740 }
741
742 if (fetcher.FetchIf(MakeShouldFetch(false))) {
743 values.push_back(fetcher.get()->value());
744 }
745 // Do it again to make sure we don't double fetch.
746 if (fetcher.FetchIf(MakeShouldFetch(true))) {
747 values.push_back(fetcher.get()->value());
748 }
749 this->Exit();
750 });
751
752 loop2->OnRun([&test_timer, &loop2]() {
753 test_timer->Schedule(loop2->monotonic_now(),
754 ::std::chrono::milliseconds(100));
755 });
756
757 Run();
758 EXPECT_THAT(values, ::testing::ElementsAreArray({201}));
759}
760
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700761// Tests that timer handler is enabled after setup (even if it is in the past)
762// and is disabled after running
763TEST_P(AbstractEventLoopTest, CheckTimerDisabled) {
764 auto loop = MakePrimary("primary");
765
766 auto timer = loop->AddTimer([this]() {
767 LOG(INFO) << "timer called";
768 Exit();
769 });
770
771 loop->OnRun([&loop, timer]() {
772 EXPECT_TRUE(timer->IsDisabled());
Philipp Schradera6712522023-07-05 20:25:11 -0700773 timer->Schedule(loop->monotonic_now() + chrono::milliseconds(100));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700774 EXPECT_FALSE(timer->IsDisabled());
775 });
776
777 Run();
778 EXPECT_TRUE(timer->IsDisabled());
779}
780
781// Tests that timer handler is enabled after setup (even if it is in the past)
782// and is disabled after running
783TEST_P(AbstractEventLoopTest, CheckTimerRunInPastDisabled) {
784 auto loop = MakePrimary("primary");
785
786 auto timer2 = loop->AddTimer([this]() {
787 LOG(INFO) << "timer called";
788 Exit();
789 });
790
791 auto timer = loop->AddTimer([&loop, timer2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700792 timer2->Schedule(loop->monotonic_now() - chrono::nanoseconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700793 });
794
795 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700796 timer->Schedule(loop->monotonic_now() + chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700797 EXPECT_FALSE(timer->IsDisabled());
798 });
799
800 Run();
801 EXPECT_TRUE(timer2->IsDisabled());
802}
803
804// Tests that timer handler is not disabled even after calling Exit on the event
805// loop within the timer
806TEST_P(AbstractEventLoopTest, CheckTimerRepeatOnCountDisabled) {
807 auto loop = MakePrimary("primary");
808 int counter = 0;
809
810 auto timer = loop->AddTimer([&counter, this]() {
811 LOG(INFO) << "timer called";
812 counter++;
813 if (counter >= 5) {
814 Exit();
815 }
816 });
817
818 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700819 timer->Schedule(loop->monotonic_now() + chrono::seconds(1),
820 chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700821 EXPECT_FALSE(timer->IsDisabled());
822 });
823 Run();
824
825 // Sanity check
826 EXPECT_EQ(counter, 5);
827
828 // if you run the loop again, the timer will start running again
829 EXPECT_FALSE(timer->IsDisabled());
830
831 counter = 0;
832 Run();
833 timer->Disable();
834
835 EXPECT_TRUE(timer->IsDisabled());
836}
837
838// Tests that timer handler is not disabled even after calling Exit on the event
839// loop using an external timer
840TEST_P(AbstractEventLoopTest, CheckTimerRepeatTillEndTimerDisabled) {
841 auto loop = MakePrimary("primary");
842
843 auto timer = loop->AddTimer([]() { LOG(INFO) << "timer called"; });
844
845 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700846 timer->Schedule(loop->monotonic_now() + chrono::seconds(1),
847 chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700848 EXPECT_FALSE(timer->IsDisabled());
849 });
850
851 EndEventLoop(loop.get(), chrono::seconds(5));
852 Run();
853 EXPECT_FALSE(timer->IsDisabled());
854
855 timer->Disable();
856 EXPECT_TRUE(timer->IsDisabled());
857}
858
Austin Schuhbbce72d2019-05-26 15:11:46 -0700859// Tests that Fetch and FetchNext interleave as expected.
860TEST_P(AbstractEventLoopTest, FetchAndFetchNextTogether) {
861 auto loop1 = Make();
862 auto loop2 = MakePrimary();
863
864 auto sender = loop1->MakeSender<TestMessage>("/test");
865
866 ::std::vector<int> values;
867
Austin Schuh98ed26f2023-07-19 14:12:28 -0700868 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700869 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
870 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700871 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700872 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700873 }
874
875 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
876
877 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700878 auto test_timer = loop2->AddTimer([&fetcher, &values, &sender, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700879 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700880 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700881 }
882
Austin Schuh98ed26f2023-07-19 14:12:28 -0700883 for (int i = 202; i < 205; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700884 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
885 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700886 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700887 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700888 }
889
890 if (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700891 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700892 }
893
894 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700895 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700896 }
897
Austin Schuh9fe68f72019-08-10 19:32:03 -0700898 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700899 });
900
901 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700902 test_timer->Schedule(loop2->monotonic_now(),
903 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700904 });
905
906 Run();
907 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
908}
909
Austin Schuh98ed26f2023-07-19 14:12:28 -0700910// Tests that Fetch{If,} and FetchNext{If,} interleave as expected.
911TEST_P(AbstractEventLoopTest, FetchAndFetchNextIfTogether) {
912 auto loop1 = Make();
913 auto loop2 = MakePrimary();
914
915 auto sender = loop1->MakeSender<TestMessage>("/test");
916
917 ::std::vector<int> values;
918
919 for (int i = 200; i < 202; ++i) {
920 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
921 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
922 builder.add_value(i);
923 msg.CheckOk(msg.Send(builder.Finish()));
924 }
925
926 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
927
928 // Add a timer to actually quit.
929 auto test_timer = loop2->AddTimer([&fetcher, &values, &sender, this]() {
930 if (fetcher.Fetch()) {
931 values.push_back(fetcher.get()->value());
932 }
933
934 for (int i = 202; i < 205; ++i) {
935 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
936 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
937 builder.add_value(i);
938 msg.CheckOk(msg.Send(builder.Finish()));
939 }
940
941 EXPECT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false)));
942
943 if (fetcher.FetchNext()) {
944 values.push_back(fetcher.get()->value());
945 }
946
947 EXPECT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false)));
948 EXPECT_FALSE(fetcher.FetchIf(MakeShouldFetch(false)));
949
950 if (fetcher.FetchIf(MakeShouldFetch(true))) {
951 values.push_back(fetcher.get()->value());
952 }
953
954 this->Exit();
955 });
956
957 loop2->OnRun([&test_timer, &loop2]() {
958 test_timer->Schedule(loop2->monotonic_now(),
959 ::std::chrono::milliseconds(100));
960 });
961
962 Run();
963 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
964}
965
Austin Schuh3115a202019-05-27 21:02:14 -0700966// Tests that FetchNext behaves correctly when we get two messages in the queue
967// but don't consume the first until after the second has been sent.
968TEST_P(AbstractEventLoopTest, FetchNextTest) {
Austin Schuh3115a202019-05-27 21:02:14 -0700969 auto send_loop = Make();
970 auto fetch_loop = Make();
971 auto sender = send_loop->MakeSender<TestMessage>("/test");
972 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
973
974 {
Tyler Chatow67ddb032020-01-12 14:30:04 -0800975 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
976 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
977 builder.add_value(100);
milind1f1dca32021-07-03 13:50:07 -0700978 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700979 }
980
981 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700982 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
983 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
984 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700985 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700986 }
987
988 ASSERT_TRUE(fetcher.FetchNext());
989 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700990 EXPECT_EQ(100, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700991
992 ASSERT_TRUE(fetcher.FetchNext());
993 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700994 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700995
996 // When we run off the end of the queue, expect to still have the old message:
997 ASSERT_FALSE(fetcher.FetchNext());
998 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700999 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -07001000}
1001
Austin Schuh98ed26f2023-07-19 14:12:28 -07001002// Tests that FetchNext behaves correctly when we get two messages in the queue
1003// but don't consume the first until after the second has been sent.
1004TEST_P(AbstractEventLoopTest, FetchNextIfTest) {
1005 auto send_loop = Make();
1006 auto fetch_loop = Make();
1007 auto sender = send_loop->MakeSender<TestMessage>("/test");
1008 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
1009
1010 {
1011 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1012 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1013 builder.add_value(100);
1014 msg.CheckOk(msg.Send(builder.Finish()));
1015 }
1016
1017 {
1018 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1019 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1020 builder.add_value(200);
1021 msg.CheckOk(msg.Send(builder.Finish()));
1022 }
1023
1024 size_t called_count = 0;
1025 ASSERT_TRUE(fetcher.FetchNextIf(MakeShouldFetch(true, &called_count)));
1026 ASSERT_NE(nullptr, fetcher.get());
1027 EXPECT_EQ(100, fetcher.get()->value());
1028 EXPECT_EQ(called_count, 1u);
1029
1030 ASSERT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false, &called_count)));
1031 EXPECT_EQ(called_count, 2u);
1032
1033 ASSERT_TRUE(fetcher.FetchNextIf(MakeShouldFetch(true, &called_count)));
1034 ASSERT_NE(nullptr, fetcher.get());
1035 EXPECT_EQ(200, fetcher.get()->value());
1036 EXPECT_EQ(called_count, 3u);
1037
1038 // When we run off the end of the queue, expect to still have the old message:
1039 ASSERT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false, &called_count)));
1040 EXPECT_EQ(called_count, 3u);
1041 ASSERT_NE(nullptr, fetcher.get());
1042 EXPECT_EQ(200, fetcher.get()->value());
1043}
1044
Brian Silverman77162972020-08-12 19:52:40 -07001045// Verify that a fetcher still holds its data, even after falling behind.
1046TEST_P(AbstractEventLoopTest, FetcherBehindData) {
1047 auto send_loop = Make();
1048 auto fetch_loop = Make();
1049 auto sender = send_loop->MakeSender<TestMessage>("/test");
1050 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
1051 {
1052 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1053 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1054 builder.add_value(1);
milind1f1dca32021-07-03 13:50:07 -07001055 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -07001056 }
1057 ASSERT_TRUE(fetcher.Fetch());
1058 EXPECT_EQ(1, fetcher.get()->value());
1059 for (int i = 0; i < 300; ++i) {
1060 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1061 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1062 builder.add_value(i + 2);
milind1f1dca32021-07-03 13:50:07 -07001063 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -07001064 }
1065 EXPECT_EQ(1, fetcher.get()->value());
1066}
1067
1068// Try a bunch of orderings of operations with fetchers and senders. Verify that
1069// all the fetchers have the correct data at each step.
1070TEST_P(AbstractEventLoopTest, FetcherPermutations) {
1071 for (int max_save = 0; max_save < 5; ++max_save) {
1072 SCOPED_TRACE("max_save=" + std::to_string(max_save));
1073
1074 auto send_loop = Make();
1075 auto fetch_loop = Make();
1076 auto sender = send_loop->MakeSender<TestMessage>("/test");
1077 const auto send_message = [&sender](int i) {
1078 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1079 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1080 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -07001081 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -07001082 };
1083 std::vector<Fetcher<TestMessage>> fetchers;
1084 for (int i = 0; i < 10; ++i) {
1085 fetchers.emplace_back(fetch_loop->MakeFetcher<TestMessage>("/test"));
1086 }
1087 send_message(1);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001088 const auto verify_buffers = [&]() {
1089 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>>
1090 fetchers_copy;
1091 for (const auto &fetcher : fetchers) {
1092 fetchers_copy.emplace_back(fetcher);
1093 }
1094 std::vector<std::reference_wrapper<const Sender<TestMessage>>>
1095 senders_copy;
1096 senders_copy.emplace_back(sender);
1097 VerifyBuffers(send_loop->NumberBuffers(sender.channel()), fetchers_copy,
1098 senders_copy);
1099 };
Brian Silverman77162972020-08-12 19:52:40 -07001100 for (auto &fetcher : fetchers) {
1101 ASSERT_TRUE(fetcher.Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -07001102 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001103 EXPECT_EQ(1, fetcher.get()->value());
1104 }
1105
1106 for (int save = 1; save <= max_save; ++save) {
1107 SCOPED_TRACE("save=" + std::to_string(save));
1108 send_message(100 + save);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001109 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001110 for (size_t i = 0; i < fetchers.size() - save; ++i) {
1111 SCOPED_TRACE("fetcher=" + std::to_string(i));
1112 ASSERT_TRUE(fetchers[i].Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -07001113 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001114 EXPECT_EQ(100 + save, fetchers[i].get()->value());
1115 }
1116 for (size_t i = fetchers.size() - save; i < fetchers.size() - 1; ++i) {
1117 SCOPED_TRACE("fetcher=" + std::to_string(i));
1118 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
1119 }
1120 EXPECT_EQ(1, fetchers.back().get()->value());
1121 }
1122
1123 for (int i = 0; i < 300; ++i) {
1124 send_message(200 + i);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001125 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001126 }
1127
1128 for (size_t i = 0; i < fetchers.size() - max_save; ++i) {
1129 SCOPED_TRACE("fetcher=" + std::to_string(i));
1130 if (max_save > 0) {
1131 EXPECT_EQ(100 + max_save, fetchers[i].get()->value());
1132 } else {
1133 EXPECT_EQ(1, fetchers[i].get()->value());
1134 }
1135 }
1136 for (size_t i = fetchers.size() - max_save; i < fetchers.size() - 1; ++i) {
1137 SCOPED_TRACE("fetcher=" + std::to_string(i));
1138 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
1139 }
1140 EXPECT_EQ(1, fetchers.back().get()->value());
1141 }
1142}
1143
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001144// Verify that making a fetcher and watcher for "/test" succeeds.
1145TEST_P(AbstractEventLoopTest, FetcherAndWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -08001146 auto loop = Make();
1147 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001148 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Parker Schuhe4a70d62017-12-27 20:10:20 -08001149}
1150
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001151// Verify that making 2 fetchers for "/test" succeeds.
Parker Schuhe4a70d62017-12-27 20:10:20 -08001152TEST_P(AbstractEventLoopTest, TwoFetcher) {
1153 auto loop = Make();
1154 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001155 auto fetcher2 = loop->MakeFetcher<TestMessage>("/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -08001156}
1157
Alex Perrycb7da4b2019-08-28 19:35:56 -07001158// Verify that registering a watcher for an invalid channel name dies.
1159TEST_P(AbstractEventLoopDeathTest, InvalidChannelName) {
1160 auto loop = Make();
1161 EXPECT_DEATH(
1162 { loop->MakeWatcher("/test/invalid", [&](const TestMessage &) {}); },
1163 "/test/invalid");
Brian Silverman454bc112020-03-05 14:21:25 -08001164 EXPECT_DEATH(
1165 { loop->MakeNoArgWatcher<TestMessage>("/test/invalid", [&]() {}); },
1166 "/test/invalid");
Alex Perrycb7da4b2019-08-28 19:35:56 -07001167}
1168
James Kuszmaul8866e642022-06-10 16:00:36 -07001169// Verify that setting up a timer before monotonic_clock::epoch() fails.
James Kuszmaul86e86c32022-07-21 17:39:47 -07001170TEST_P(AbstractEventLoopDeathTest, NegativeTimeTimer) {
James Kuszmaul8866e642022-06-10 16:00:36 -07001171 auto loop = Make();
1172 TimerHandler *time = loop->AddTimer([]() {});
Philipp Schradera6712522023-07-05 20:25:11 -07001173 EXPECT_DEATH(
1174 time->Schedule(monotonic_clock::epoch() - std::chrono::seconds(1)),
1175 "-1.000");
James Kuszmaul8866e642022-06-10 16:00:36 -07001176}
1177
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001178// Verify that registering a watcher twice for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001179TEST_P(AbstractEventLoopDeathTest, TwoWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -08001180 auto loop = Make();
1181 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001182 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
1183 "/test");
Brian Silverman454bc112020-03-05 14:21:25 -08001184 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
1185}
1186
1187// Verify that registering a no-arg watcher twice for "/test" fails.
1188TEST_P(AbstractEventLoopDeathTest, TwoNoArgWatcher) {
1189 auto loop = Make();
1190 loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {});
1191 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
1192 "/test");
1193 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001194}
1195
Austin Schuh3115a202019-05-27 21:02:14 -07001196// Verify that SetRuntimeRealtimePriority fails while running.
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001197TEST_P(AbstractEventLoopDeathTest, SetRuntimeRealtimePriority) {
Austin Schuh3115a202019-05-27 21:02:14 -07001198 auto loop = MakePrimary();
Austin Schuh65493d62022-08-17 15:10:37 -07001199 EXPECT_EQ(0, loop->runtime_realtime_priority());
Austin Schuh3115a202019-05-27 21:02:14 -07001200 // Confirm that runtime priority calls work when not realtime.
1201 loop->SetRuntimeRealtimePriority(5);
Austin Schuh65493d62022-08-17 15:10:37 -07001202 EXPECT_EQ(5, loop->runtime_realtime_priority());
Austin Schuh3115a202019-05-27 21:02:14 -07001203
1204 loop->OnRun([&]() { loop->SetRuntimeRealtimePriority(5); });
1205
1206 EXPECT_DEATH(Run(), "realtime");
1207}
1208
Austin Schuh65493d62022-08-17 15:10:37 -07001209namespace {
1210
1211bool CpuSetEqual(const cpu_set_t &a, const cpu_set_t &b) {
1212 return CPU_EQUAL(&a, &b);
1213}
1214
1215} // namespace
1216
Brian Silverman6a54ff32020-04-28 16:41:39 -07001217// Verify that SetRuntimeAffinity fails while running.
1218TEST_P(AbstractEventLoopDeathTest, SetRuntimeAffinity) {
Austin Schuhde973292021-10-12 18:09:49 -07001219 const cpu_set_t available = GetCurrentThreadAffinity();
1220 int first_cpu = -1;
1221 for (int i = 0; i < CPU_SETSIZE; ++i) {
1222 if (CPU_ISSET(i, &available)) {
1223 first_cpu = i;
1224 break;
1225 continue;
1226 }
1227 }
1228 CHECK_NE(first_cpu, -1) << ": Default affinity has no CPUs?";
1229
Brian Silverman6a54ff32020-04-28 16:41:39 -07001230 auto loop = MakePrimary();
Austin Schuh65493d62022-08-17 15:10:37 -07001231 EXPECT_TRUE(
1232 CpuSetEqual(EventLoop::DefaultAffinity(), loop->runtime_affinity()));
1233 const cpu_set_t new_affinity = MakeCpusetFromCpus({first_cpu});
Brian Silverman6a54ff32020-04-28 16:41:39 -07001234 // Confirm that runtime priority calls work when not running.
Austin Schuh65493d62022-08-17 15:10:37 -07001235 loop->SetRuntimeAffinity(new_affinity);
1236 EXPECT_TRUE(CpuSetEqual(new_affinity, loop->runtime_affinity()));
Brian Silverman6a54ff32020-04-28 16:41:39 -07001237
Austin Schuhde973292021-10-12 18:09:49 -07001238 loop->OnRun(
1239 [&]() { loop->SetRuntimeAffinity(MakeCpusetFromCpus({first_cpu})); });
Brian Silverman6a54ff32020-04-28 16:41:39 -07001240
1241 EXPECT_DEATH(Run(), "Cannot set affinity while running");
1242}
1243
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001244// Verify that registering a watcher and a sender for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001245TEST_P(AbstractEventLoopDeathTest, WatcherAndSender) {
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001246 auto loop = Make();
1247 auto sender = loop->MakeSender<TestMessage>("/test");
1248 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
1249 "/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -08001250}
1251
Austin Schuhe516ab02020-05-06 21:37:04 -07001252// Verify that creating too many senders fails.
1253TEST_P(AbstractEventLoopDeathTest, TooManySenders) {
1254 auto loop = Make();
1255 std::vector<aos::Sender<TestMessage>> senders;
1256 for (int i = 0; i < 10; ++i) {
1257 senders.emplace_back(loop->MakeSender<TestMessage>("/test"));
1258 }
1259 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); },
1260 "Failed to create sender on \\{ \"name\": \"/test\", \"type\": "
Brian Silverman77162972020-08-12 19:52:40 -07001261 "\"aos.TestMessage\"[^}]*\\ }, too many senders.");
1262}
1263
1264// Verify that creating too many fetchers fails.
1265TEST_P(AbstractEventLoopDeathTest, TooManyFetchers) {
1266 if (read_method() != ReadMethod::PIN) {
1267 // Other read methods don't limit the number of readers, so just skip this.
1268 return;
1269 }
1270
1271 auto loop = Make();
1272 std::vector<aos::Fetcher<TestMessage>> fetchers;
1273 for (int i = 0; i < 10; ++i) {
1274 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1275 }
1276 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1277 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1278 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
1279}
1280
1281// Verify that creating too many fetchers, split between two event loops, fails.
1282TEST_P(AbstractEventLoopDeathTest, TooManyFetchersTwoLoops) {
1283 if (read_method() != ReadMethod::PIN) {
1284 // Other read methods don't limit the number of readers, so just skip this.
1285 return;
1286 }
1287
1288 auto loop = Make();
1289 auto loop2 = Make();
1290 std::vector<aos::Fetcher<TestMessage>> fetchers;
1291 for (int i = 0; i < 5; ++i) {
1292 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1293 fetchers.emplace_back(loop2->MakeFetcher<TestMessage>("/test"));
1294 }
1295 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1296 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1297 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
1298}
1299
1300// Verify that creating too many watchers fails.
1301TEST_P(AbstractEventLoopDeathTest, TooManyWatchers) {
1302 if (read_method() != ReadMethod::PIN) {
1303 // Other read methods don't limit the number of readers, so just skip this.
1304 return;
1305 }
1306
1307 std::vector<std::unique_ptr<EventLoop>> loops;
1308 for (int i = 0; i < 10; ++i) {
1309 loops.emplace_back(Make());
1310 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
1311 }
1312 EXPECT_DEATH({ Make()->MakeWatcher("/test", [](const TestMessage &) {}); },
1313 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1314 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
1315}
1316
1317// Verify that creating too many watchers and fetchers combined fails.
1318TEST_P(AbstractEventLoopDeathTest, TooManyWatchersAndFetchers) {
1319 if (read_method() != ReadMethod::PIN) {
1320 // Other read methods don't limit the number of readers, so just skip this.
1321 return;
1322 }
1323
1324 auto loop = Make();
1325 std::vector<aos::Fetcher<TestMessage>> fetchers;
1326 std::vector<std::unique_ptr<EventLoop>> loops;
1327 for (int i = 0; i < 5; ++i) {
1328 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1329 loops.emplace_back(Make());
1330 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
1331 }
1332 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1333 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1334 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
Austin Schuhe516ab02020-05-06 21:37:04 -07001335}
1336
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001337// Verify that we can't create a sender inside OnRun.
1338TEST_P(AbstractEventLoopDeathTest, SenderInOnRun) {
1339 auto loop1 = MakePrimary();
1340
1341 loop1->OnRun(
1342 [&]() { auto sender = loop1->MakeSender<TestMessage>("/test2"); });
1343
1344 EXPECT_DEATH(Run(), "running");
1345}
1346
1347// Verify that we can't create a watcher inside OnRun.
1348TEST_P(AbstractEventLoopDeathTest, WatcherInOnRun) {
1349 auto loop1 = MakePrimary();
1350
1351 loop1->OnRun(
1352 [&]() { loop1->MakeWatcher("/test", [&](const TestMessage &) {}); });
1353
1354 EXPECT_DEATH(Run(), "running");
1355}
1356
Brian Silverman454bc112020-03-05 14:21:25 -08001357// Verify that we can't create a no-arg watcher inside OnRun.
1358TEST_P(AbstractEventLoopDeathTest, NoArgWatcherInOnRun) {
1359 auto loop1 = MakePrimary();
1360
1361 loop1->OnRun(
1362 [&]() { loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {}); });
1363
1364 EXPECT_DEATH(Run(), "running");
1365}
1366
Parker Schuhe4a70d62017-12-27 20:10:20 -08001367// Verify that Quit() works when there are multiple watchers.
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001368TEST_P(AbstractEventLoopTest, MultipleWatcherQuit) {
1369 auto loop1 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -07001370 auto loop2 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -08001371
Austin Schuh3578a2e2019-05-25 18:17:59 -07001372 loop2->MakeWatcher("/test1", [&](const TestMessage &) {});
1373 loop2->MakeWatcher("/test2", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001374 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -07001375 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -07001376 });
1377
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001378 auto sender = loop1->MakeSender<TestMessage>("/test2");
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001379
1380 loop2->OnRun([&]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001381 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1382 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1383 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001384 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001385 });
Parker Schuhe4a70d62017-12-27 20:10:20 -08001386
Austin Schuh44019f92019-05-19 19:58:27 -07001387 Run();
Parker Schuhe4a70d62017-12-27 20:10:20 -08001388}
1389
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001390// Verify that AOS_LOG has the right name.
1391TEST_P(AbstractEventLoopTest, AOSLog) {
1392 auto loop2 = MakePrimary("loop1");
1393 auto loop1 = Make("loop0");
1394
1395 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1396
1397 EXPECT_FALSE(fetcher.Fetch());
1398
1399 loop2->OnRun([&]() {
1400 AOS_LOG(INFO, "Testing123");
1401 this->Exit();
1402 });
1403
1404 Run();
1405 EXPECT_TRUE(fetcher.Fetch());
1406 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1407}
1408
1409// Verify that AOS_LOG has the right name in a watcher.
1410TEST_P(AbstractEventLoopTest, AOSLogWatcher) {
1411 auto loop2 = MakePrimary("loop1");
1412 auto loop1 = Make("loop0");
1413
1414 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1415
1416 EXPECT_FALSE(fetcher.Fetch());
1417
1418 auto sender = loop1->MakeSender<TestMessage>("/test2");
1419
1420 loop2->MakeWatcher("/test2", [&](const TestMessage & /*message*/) {
1421 AOS_LOG(INFO, "Testing123");
1422 this->Exit();
1423 });
1424
1425 loop2->OnRun([&]() {
1426 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1427 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1428 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001429 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001430 });
1431
1432 Run();
1433 EXPECT_TRUE(fetcher.Fetch());
1434 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1435}
1436
1437// Verify that AOS_LOG has the right name in a timer.
1438TEST_P(AbstractEventLoopTest, AOSLogTimer) {
1439 auto loop2 = MakePrimary("loop1");
1440 auto loop1 = Make("loop0");
1441
1442 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1443
1444 EXPECT_FALSE(fetcher.Fetch());
1445
1446 auto test_timer = loop2->AddTimer([&]() {
1447 AOS_LOG(INFO, "Testing123");
1448 this->Exit();
1449 });
1450
Philipp Schradera6712522023-07-05 20:25:11 -07001451 loop2->OnRun([&]() { test_timer->Schedule(loop2->monotonic_now()); });
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001452
1453 Run();
1454 EXPECT_TRUE(fetcher.Fetch());
1455 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1456}
1457
Neil Balch229001a2018-01-07 18:22:52 -08001458// Verify that timer intervals and duration function properly.
1459TEST_P(AbstractEventLoopTest, TimerIntervalAndDuration) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001460 // Force a slower rate so we are guaranteed to have reports for our timer.
Austin Schuh39788ff2019-12-01 18:22:57 -08001461 FLAGS_timing_report_ms = 2000;
1462
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001463 const int kCount = 5;
Neil Balch229001a2018-01-07 18:22:52 -08001464
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001465 auto loop = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001466 auto loop2 = Make();
1467
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001468 ::std::vector<::aos::monotonic_clock::time_point> times;
1469 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
1470
Austin Schuh39788ff2019-12-01 18:22:57 -08001471 Fetcher<timing::Report> report_fetcher =
1472 loop2->MakeFetcher<timing::Report>("/aos");
1473 EXPECT_FALSE(report_fetcher.Fetch());
1474
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001475 auto test_timer = loop->AddTimer([this, &times, &expected_times, &loop]() {
1476 times.push_back(loop->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001477 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07001478 EXPECT_EQ(loop->context().monotonic_remote_transmit_time,
1479 monotonic_clock::min_time);
Austin Schuhad154822019-12-27 15:45:13 -08001480 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
1481 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001482 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -08001483 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
1484 EXPECT_EQ(loop->context().size, 0u);
1485 EXPECT_EQ(loop->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001486 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001487
Austin Schuhad154822019-12-27 15:45:13 -08001488 expected_times.push_back(loop->context().monotonic_event_time);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001489 if (times.size() == kCount) {
1490 this->Exit();
1491 }
Neil Balch229001a2018-01-07 18:22:52 -08001492 });
Austin Schuh39788ff2019-12-01 18:22:57 -08001493 test_timer->set_name("Test loop");
Neil Balch229001a2018-01-07 18:22:52 -08001494
Austin Schuh39788ff2019-12-01 18:22:57 -08001495 const monotonic_clock::time_point start_time = loop->monotonic_now();
Austin Schuh52d325c2019-06-23 18:59:06 -07001496 // TODO(austin): This should be an error... Should be done in OnRun only.
Philipp Schradera6712522023-07-05 20:25:11 -07001497 test_timer->Schedule(start_time + chrono::seconds(1), chrono::seconds(1));
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001498
Austin Schuh44019f92019-05-19 19:58:27 -07001499 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001500
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001501 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001502 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
1503 ASSERT_EQ(times.size(), expected_times.size());
1504 ASSERT_EQ((times.size() % 2), 1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001505
1506 // Grab the middle sample.
1507 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
1508
1509 // Add up all the delays of all the times.
1510 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1511 for (const ::aos::monotonic_clock::time_point time : times) {
1512 sum += time - average_time;
1513 }
1514
1515 // Average and add to the middle to find the average time.
1516 sum /= times.size();
1517 average_time += sum;
1518
1519 // Compute the offset from the average and the expected average. It
1520 // should be pretty close to 0.
1521 const ::aos::monotonic_clock::duration remainder =
1522 average_time - start_time - chrono::seconds(times.size() / 2 + 1);
1523
1524 const chrono::milliseconds kEpsilon(100);
1525 EXPECT_LT(remainder, +kEpsilon);
1526 EXPECT_GT(remainder, -kEpsilon);
1527
1528 // Make sure that the average duration is close to 1 second.
1529 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1530 times.front())
1531 .count() /
1532 static_cast<double>(times.size() - 1),
1533 1.0, 0.1);
1534
1535 // Confirm that the ideal wakeup times increment correctly.
1536 for (size_t i = 1; i < expected_times.size(); ++i) {
1537 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1538 }
1539
1540 for (size_t i = 0; i < expected_times.size(); ++i) {
1541 EXPECT_EQ((expected_times[i] - start_time) % chrono::seconds(1),
1542 chrono::seconds(0));
1543 }
1544
1545 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1546 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001547
Austin Schuh6bae8252021-02-07 22:01:49 -08001548 if (do_timing_reports() == DoTimingReports::kYes) {
1549 // And, since we are here, check that the timing report makes sense.
1550 // Start by looking for our event loop's timing.
1551 FlatbufferDetachedBuffer<timing::Report> report =
1552 FlatbufferDetachedBuffer<timing::Report>::Empty();
1553 while (report_fetcher.FetchNext()) {
1554 if (report_fetcher->name()->string_view() == "primary") {
1555 report = CopyFlatBuffer(report_fetcher.get());
1556 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001557 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001558
1559 // Confirm that we have the right number of reports, and the contents are
1560 // sane.
1561 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
1562
1563 EXPECT_EQ(report.message().name()->string_view(), "primary");
1564
1565 ASSERT_NE(report.message().senders(), nullptr);
1566 EXPECT_EQ(report.message().senders()->size(), 2);
1567
1568 ASSERT_NE(report.message().timers(), nullptr);
1569 EXPECT_EQ(report.message().timers()->size(), 2);
1570
1571 EXPECT_EQ(report.message().timers()->Get(0)->name()->string_view(),
1572 "Test loop");
1573 EXPECT_GE(report.message().timers()->Get(0)->count(), 1);
1574
1575 EXPECT_EQ(report.message().timers()->Get(1)->name()->string_view(),
1576 "timing_reports");
1577 EXPECT_EQ(report.message().timers()->Get(1)->count(), 1);
1578
1579 // Make sure there is a single phased loop report with our report in it.
1580 ASSERT_EQ(report.message().phased_loops(), nullptr);
1581 } else {
1582 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001583 }
Neil Balch229001a2018-01-07 18:22:52 -08001584}
1585
James Kuszmaul762e8692023-07-31 14:57:53 -07001586// Test that setting a default version string results in it getting populated
1587// correctly.
1588TEST_P(AbstractEventLoopTest, DefaultVersionStringInTimingReport) {
1589 gflags::FlagSaver flag_saver;
1590 FLAGS_timing_report_ms = 1000;
1591
1592 EventLoop::SetDefaultVersionString("default_version_string");
1593
1594 auto loop = MakePrimary();
1595
1596 Fetcher<timing::Report> report_fetcher =
1597 loop->MakeFetcher<timing::Report>("/aos");
1598
1599 TimerHandler *exit_timer = loop->AddTimer([this]() { Exit(); });
1600 loop->OnRun([exit_timer, &loop, &report_fetcher]() {
1601 report_fetcher.Fetch();
1602 exit_timer->Schedule(loop->monotonic_now() + std::chrono::seconds(2));
1603 });
1604
1605 Run();
1606
1607 bool found_primary_report = false;
1608 while (report_fetcher.FetchNext()) {
1609 if (report_fetcher->name()->string_view() == "primary") {
1610 found_primary_report = true;
1611 EXPECT_EQ("default_version_string",
1612 report_fetcher->version()->string_view());
1613 } else {
1614 FAIL() << report_fetcher->name()->string_view();
1615 }
1616 }
1617
1618 if (do_timing_reports() == DoTimingReports::kYes) {
1619 EXPECT_TRUE(found_primary_report);
1620 } else {
1621 EXPECT_FALSE(found_primary_report);
1622 }
1623}
1624
1625// Test that overriding the default version string results in it getting
1626// populated correctly.
1627TEST_P(AbstractEventLoopTest, OverrideDersionStringInTimingReport) {
1628 gflags::FlagSaver flag_saver;
1629 FLAGS_timing_report_ms = 1000;
1630
1631 EventLoop::SetDefaultVersionString("default_version_string");
1632
1633 auto loop = MakePrimary();
1634 loop->SetVersionString("override_version");
1635
1636 Fetcher<timing::Report> report_fetcher =
1637 loop->MakeFetcher<timing::Report>("/aos");
1638
1639 TimerHandler *exit_timer = loop->AddTimer([this]() { Exit(); });
1640 loop->OnRun([exit_timer, &loop, &report_fetcher]() {
1641 report_fetcher.Fetch();
1642 exit_timer->Schedule(loop->monotonic_now() + std::chrono::seconds(2));
1643 });
1644
1645 Run();
1646
1647 bool found_primary_report = false;
1648 while (report_fetcher.FetchNext()) {
1649 if (report_fetcher->name()->string_view() == "primary") {
1650 found_primary_report = true;
1651 EXPECT_EQ("override_version", report_fetcher->version()->string_view());
1652 } else {
1653 FAIL() << report_fetcher->name()->string_view();
1654 }
1655 }
1656
1657 if (do_timing_reports() == DoTimingReports::kYes) {
1658 EXPECT_TRUE(found_primary_report);
1659 } else {
1660 EXPECT_FALSE(found_primary_report);
1661 }
1662}
1663
Neil Balch229001a2018-01-07 18:22:52 -08001664// Verify that we can change a timer's parameters during execution.
1665TEST_P(AbstractEventLoopTest, TimerChangeParameters) {
Austin Schuh44019f92019-05-19 19:58:27 -07001666 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001667 loop->SetRuntimeRealtimePriority(1);
Austin Schuh7f20f512021-01-31 17:56:16 -08001668 std::vector<monotonic_clock::time_point> iteration_list;
Neil Balch229001a2018-01-07 18:22:52 -08001669
1670 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001671 ScopedNotRealtime nrt;
Austin Schuh7f20f512021-01-31 17:56:16 -08001672 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001673 });
1674
Austin Schuh7f20f512021-01-31 17:56:16 -08001675 monotonic_clock::time_point s;
1676 auto modifier_timer = loop->AddTimer([&test_timer, &s]() {
Philipp Schradera6712522023-07-05 20:25:11 -07001677 test_timer->Schedule(s + chrono::milliseconds(1750),
1678 chrono::milliseconds(600));
Neil Balch229001a2018-01-07 18:22:52 -08001679 });
1680
Austin Schuh7f20f512021-01-31 17:56:16 -08001681 s = loop->monotonic_now();
Philipp Schradera6712522023-07-05 20:25:11 -07001682 test_timer->Schedule(s, chrono::milliseconds(500));
1683 modifier_timer->Schedule(s + chrono::milliseconds(1250));
Austin Schuhd892f102021-10-12 18:01:46 -07001684 EndEventLoop(loop.get(), chrono::milliseconds(3950));
Austin Schuh44019f92019-05-19 19:58:27 -07001685 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001686
Austin Schuhd892f102021-10-12 18:01:46 -07001687 EXPECT_THAT(
1688 iteration_list,
1689 ::testing::ElementsAre(
1690 s, s + chrono::milliseconds(500), s + chrono::milliseconds(1000),
1691 s + chrono::milliseconds(1750), s + chrono::milliseconds(2350),
1692 s + chrono::milliseconds(2950), s + chrono::milliseconds(3550)));
Neil Balch229001a2018-01-07 18:22:52 -08001693}
1694
1695// Verify that we can disable a timer during execution.
1696TEST_P(AbstractEventLoopTest, TimerDisable) {
Austin Schuh44019f92019-05-19 19:58:27 -07001697 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001698 loop->SetRuntimeRealtimePriority(1);
Neil Balch229001a2018-01-07 18:22:52 -08001699 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
1700
1701 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001702 ScopedNotRealtime nrt;
Austin Schuhd892f102021-10-12 18:01:46 -07001703 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001704 });
1705
Tyler Chatow67ddb032020-01-12 14:30:04 -08001706 auto ender_timer = loop->AddTimer([&test_timer]() { test_timer->Disable(); });
Neil Balch229001a2018-01-07 18:22:52 -08001707
Austin Schuhd892f102021-10-12 18:01:46 -07001708 monotonic_clock::time_point s = loop->monotonic_now();
Philipp Schradera6712522023-07-05 20:25:11 -07001709 test_timer->Schedule(s, ::std::chrono::milliseconds(500));
1710 ender_timer->Schedule(s + ::std::chrono::milliseconds(1250));
Austin Schuh73d99502021-12-08 12:05:39 -08001711 EndEventLoop(loop.get(), ::std::chrono::milliseconds(2000));
Austin Schuh44019f92019-05-19 19:58:27 -07001712 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001713
Austin Schuhd892f102021-10-12 18:01:46 -07001714 EXPECT_THAT(iteration_list,
Austin Schuh73d99502021-12-08 12:05:39 -08001715 ::testing::ElementsAre(s, s + chrono::milliseconds(500),
1716 s + chrono::milliseconds(1000)));
Neil Balch229001a2018-01-07 18:22:52 -08001717}
Austin Schuh7267c532019-05-19 19:55:53 -07001718
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001719// Verify that a timer can disable itself.
1720//
1721// TODO(Brian): Do something similar with phased loops, both with a quick
1722// handler and a handler that would miss a cycle except it got deferred. Current
1723// behavior doing that is a mess.
1724TEST_P(AbstractEventLoopTest, TimerDisableSelf) {
1725 auto loop = MakePrimary();
1726
1727 int count = 0;
1728 aos::TimerHandler *test_timer;
1729 test_timer = loop->AddTimer([&count, &test_timer]() {
1730 ++count;
1731 test_timer->Disable();
1732 });
1733
Philipp Schradera6712522023-07-05 20:25:11 -07001734 test_timer->Schedule(loop->monotonic_now(), ::std::chrono::milliseconds(20));
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001735 EndEventLoop(loop.get(), ::std::chrono::milliseconds(80));
1736 Run();
1737
1738 EXPECT_EQ(count, 1);
1739}
1740
Brian Silvermanbd405c02020-06-23 16:25:23 -07001741// Verify that we can disable a timer during execution of another timer
1742// scheduled for the same time, with one ordering of creation for the timers.
1743//
1744// Also schedule some more events to reshuffle the heap in EventLoop used for
1745// tracking events to change up the order. This used to segfault
1746// SimulatedEventLoop.
1747TEST_P(AbstractEventLoopTest, TimerDisableOther) {
1748 for (bool creation_order : {true, false}) {
1749 for (bool setup_order : {true, false}) {
1750 for (int shuffle_events = 0; shuffle_events < 5; ++shuffle_events) {
1751 auto loop = MakePrimary();
1752 aos::TimerHandler *test_timer, *ender_timer;
1753 if (creation_order) {
1754 test_timer = loop->AddTimer([]() {});
1755 ender_timer =
1756 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1757 } else {
1758 ender_timer =
1759 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1760 test_timer = loop->AddTimer([]() {});
1761 }
1762
1763 const auto start = loop->monotonic_now();
1764
1765 for (int i = 0; i < shuffle_events; ++i) {
Philipp Schradera6712522023-07-05 20:25:11 -07001766 loop->AddTimer([]() {})->Schedule(start +
1767 std::chrono::milliseconds(10));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001768 }
1769
1770 if (setup_order) {
Philipp Schradera6712522023-07-05 20:25:11 -07001771 test_timer->Schedule(start + ::std::chrono::milliseconds(20));
1772 ender_timer->Schedule(start + ::std::chrono::milliseconds(20));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001773 } else {
Philipp Schradera6712522023-07-05 20:25:11 -07001774 ender_timer->Schedule(start + ::std::chrono::milliseconds(20));
1775 test_timer->Schedule(start + ::std::chrono::milliseconds(20));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001776 }
1777 EndEventLoop(loop.get(), ::std::chrono::milliseconds(40));
1778 Run();
1779 }
1780 }
1781 }
1782}
1783
Austin Schuh54cf95f2019-11-29 13:14:18 -08001784// Verifies that the event loop implementations detect when Channel is not a
Brian Silverman631b6262021-11-10 12:25:08 -08001785// pointer into configuration(), or a name doesn't map to a channel in
1786// configuration().
Austin Schuh54cf95f2019-11-29 13:14:18 -08001787TEST_P(AbstractEventLoopDeathTest, InvalidChannel) {
1788 auto loop = MakePrimary();
1789
Tyler Chatow67ddb032020-01-12 14:30:04 -08001790 const Channel *channel = configuration::GetChannel(
1791 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
Austin Schuh54cf95f2019-11-29 13:14:18 -08001792
1793 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1794
1795 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001796 loop->MakeRawSender(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001797 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1798
1799 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001800 loop->MakeSender<TestMessage>("/testbad"),
1801 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1802 " not found in config");
1803
1804 EXPECT_FALSE(loop->TryMakeSender<TestMessage>("/testbad"));
1805
1806 EXPECT_DEATH(
1807 loop->MakeRawFetcher(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001808 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1809
1810 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001811 loop->MakeFetcher<TestMessage>("/testbad"),
1812 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1813 " not found in config");
1814
1815 EXPECT_FALSE(loop->TryMakeFetcher<TestMessage>("/testbad").valid());
1816
1817 EXPECT_DEATH(
Austin Schuh54cf95f2019-11-29 13:14:18 -08001818 {
1819 loop->MakeRawWatcher(&channel_copy.message(),
1820 [](const Context, const void *) {});
1821 },
1822 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
Brian Silverman631b6262021-11-10 12:25:08 -08001823
1824 EXPECT_DEATH(
1825 { loop->MakeWatcher("/testbad", [](const TestMessage &) {}); },
1826 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1827 " not found in config");
1828}
1829
1830// Verifies that the event loop handles a channel which is not readable or
1831// writable on the current node nicely.
1832TEST_P(AbstractEventLoopDeathTest, InaccessibleChannel) {
1833 EnableNodes("me");
1834 auto loop = MakePrimary("me");
1835 auto loop2 = Make("them");
1836
1837 const Channel *channel = configuration::GetChannel(
1838 loop->configuration(), "/test_noforward", "aos.TestMessage", "", nullptr);
1839
1840 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1841
1842 EXPECT_DEATH(
1843 loop2->MakeSender<TestMessage>("/test_forward"),
1844 "Channel"
1845 " \\{ \"name\": \"/test_forward\", \"type\": \"aos.TestMessage\" \\}"
1846 " is not able to be sent on this node");
1847
1848 EXPECT_FALSE(loop2->TryMakeSender<TestMessage>("/test_forward"));
1849
1850 EXPECT_DEATH(
1851 loop2->MakeRawFetcher(channel),
1852 "Channel"
1853 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1854 " is not able to be fetched on this node");
1855
1856 EXPECT_DEATH(
1857 loop2->MakeFetcher<TestMessage>("/test_noforward"),
1858 "Channel"
1859 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1860 " is not able to be fetched on this node");
1861
1862 EXPECT_FALSE(loop2->TryMakeFetcher<TestMessage>("/test_noforward").valid());
1863
1864 EXPECT_DEATH(
1865 { loop2->MakeRawWatcher(channel, [](const Context, const void *) {}); },
1866 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1867 "\"source_node\": \"them\" \\}"
1868 " is not able to be watched on this node");
1869
1870 EXPECT_DEATH(
1871 { loop2->MakeWatcher("/test_noforward", [](const TestMessage &) {}); },
1872 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1873 "\"source_node\": \"them\" \\}"
1874 " is not able to be watched on this node");
Austin Schuh54cf95f2019-11-29 13:14:18 -08001875}
1876
Austin Schuhd54780b2020-10-03 16:26:02 -07001877// Verifies that the event loop implementations detect when Channel has an
1878// invalid alignment.
1879TEST_P(AbstractEventLoopDeathTest, InvalidChannelAlignment) {
1880 const char *const kError = "multiple of alignment";
1881 InvalidChannelAlignment();
1882
1883 auto loop = MakePrimary();
1884
1885 const Channel *channel = configuration::GetChannel(
1886 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
1887
1888 EXPECT_DEATH({ loop->MakeRawSender(channel); }, kError);
1889 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); }, kError);
1890
1891 EXPECT_DEATH({ loop->MakeRawFetcher(channel); }, kError);
1892 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); }, kError);
1893
1894 EXPECT_DEATH(
1895 { loop->MakeRawWatcher(channel, [](const Context &, const void *) {}); },
1896 kError);
1897 EXPECT_DEATH({ loop->MakeRawNoArgWatcher(channel, [](const Context &) {}); },
1898 kError);
1899
1900 EXPECT_DEATH({ loop->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
1901 kError);
1902 EXPECT_DEATH({ loop->MakeWatcher("/test", [](const TestMessage &) {}); },
1903 kError);
1904}
1905
Brian Silverman454bc112020-03-05 14:21:25 -08001906// Verify that the send time on a message is roughly right when using a watcher.
Austin Schuh7267c532019-05-19 19:55:53 -07001907TEST_P(AbstractEventLoopTest, MessageSendTime) {
Austin Schuh44019f92019-05-19 19:58:27 -07001908 auto loop1 = MakePrimary();
Austin Schuh7267c532019-05-19 19:55:53 -07001909 auto loop2 = Make();
Austin Schuhad154822019-12-27 15:45:13 -08001910 auto sender = loop2->MakeSender<TestMessage>("/test");
Austin Schuh7267c532019-05-19 19:55:53 -07001911 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
1912
1913 auto test_timer = loop1->AddTimer([&sender]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001914 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1915 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1916 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001917 msg.CheckOk(msg.Send(builder.Finish()));
Alex Perrycb7da4b2019-08-28 19:35:56 -07001918 });
1919
Austin Schuhad154822019-12-27 15:45:13 -08001920 bool triggered = false;
Brian Silverman454bc112020-03-05 14:21:25 -08001921 loop1->MakeWatcher("/test", [&](const TestMessage &msg) {
Austin Schuhad154822019-12-27 15:45:13 -08001922 // Confirm that the data pointer makes sense from a watcher, and all the
1923 // timestamps look right.
1924 EXPECT_GT(&msg, loop1->context().data);
1925 EXPECT_EQ(loop1->context().monotonic_remote_time,
1926 loop1->context().monotonic_event_time);
1927 EXPECT_EQ(loop1->context().realtime_remote_time,
1928 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001929 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhac6d89e2024-03-27 14:56:09 -07001930 EXPECT_EQ(loop1->context().monotonic_remote_transmit_time,
1931 monotonic_clock::min_time);
Austin Schuhad154822019-12-27 15:45:13 -08001932
1933 const aos::monotonic_clock::time_point monotonic_now =
1934 loop1->monotonic_now();
Tyler Chatow67ddb032020-01-12 14:30:04 -08001935 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08001936
1937 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1938 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1939 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1940 monotonic_now);
1941 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1942 realtime_now);
1943
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001944 EXPECT_LT(&msg, reinterpret_cast<const void *>(
1945 reinterpret_cast<const char *>(loop1->context().data) +
Austin Schuhad154822019-12-27 15:45:13 -08001946 loop1->context().size));
Brian Silverman4f4e0612020-08-12 19:54:41 -07001947 if (read_method() == ReadMethod::PIN) {
1948 EXPECT_GE(loop1->context().buffer_index, 0);
1949 EXPECT_LT(loop1->context().buffer_index,
1950 loop1->NumberBuffers(
1951 configuration::GetChannel(loop1->configuration(), "/test",
1952 "aos.TestMessage", "", nullptr)));
1953 } else {
1954 EXPECT_EQ(-1, loop1->context().buffer_index);
1955 }
Austin Schuhad154822019-12-27 15:45:13 -08001956 triggered = true;
Austin Schuh7267c532019-05-19 19:55:53 -07001957 });
1958
Philipp Schradera6712522023-07-05 20:25:11 -07001959 test_timer->Schedule(loop1->monotonic_now() + ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07001960
1961 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
Austin Schuh44019f92019-05-19 19:58:27 -07001962 Run();
Austin Schuh7267c532019-05-19 19:55:53 -07001963
Austin Schuhad154822019-12-27 15:45:13 -08001964 EXPECT_TRUE(triggered);
1965
Brian Silverman454bc112020-03-05 14:21:25 -08001966 ASSERT_TRUE(fetcher.Fetch());
1967
1968 monotonic_clock::duration monotonic_time_offset =
1969 fetcher.context().monotonic_event_time -
1970 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1971 realtime_clock::duration realtime_time_offset =
1972 fetcher.context().realtime_event_time -
1973 (loop1->realtime_now() - ::std::chrono::seconds(1));
1974
1975 EXPECT_EQ(fetcher.context().realtime_event_time,
1976 fetcher.context().realtime_remote_time);
1977 EXPECT_EQ(fetcher.context().monotonic_event_time,
1978 fetcher.context().monotonic_remote_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07001979 EXPECT_EQ(fetcher.context().monotonic_remote_transmit_time,
1980 monotonic_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001981 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001982
1983 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1984 << ": Got "
1985 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1986 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1987 // Confirm that the data pointer makes sense.
1988 EXPECT_GT(fetcher.get(), fetcher.context().data);
1989 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001990 reinterpret_cast<const void *>(
1991 reinterpret_cast<const char *>(fetcher.context().data) +
Brian Silverman454bc112020-03-05 14:21:25 -08001992 fetcher.context().size));
1993 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1994 << ": Got "
1995 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1996 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1997
1998 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1999 << ": Got "
2000 << fetcher.context().realtime_event_time.time_since_epoch().count()
2001 << " expected " << loop1->realtime_now().time_since_epoch().count();
2002 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
2003 << ": Got "
2004 << fetcher.context().realtime_event_time.time_since_epoch().count()
2005 << " expected " << loop1->realtime_now().time_since_epoch().count();
2006}
2007
2008// Verify that the send time on a message is roughly right when using a no-arg
2009// watcher. To get a message, we need to use a fetcher to actually access the
2010// message. This is also the main use case for no-arg fetchers.
2011TEST_P(AbstractEventLoopTest, MessageSendTimeNoArg) {
2012 auto loop1 = MakePrimary();
2013 auto loop2 = Make();
2014 auto sender = loop2->MakeSender<TestMessage>("/test");
2015 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
2016
2017 auto test_timer = loop1->AddTimer([&sender]() {
2018 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2019 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2020 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07002021 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -08002022 });
2023
2024 bool triggered = false;
2025 loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {
2026 // Confirm that we can indeed use a fetcher on this channel from this
2027 // context, and it results in a sane data pointer and timestamps.
2028 ASSERT_TRUE(fetcher.Fetch());
2029
2030 EXPECT_EQ(loop1->context().monotonic_remote_time,
2031 loop1->context().monotonic_event_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07002032 EXPECT_EQ(loop1->context().monotonic_remote_transmit_time,
2033 monotonic_clock::min_time);
Brian Silverman454bc112020-03-05 14:21:25 -08002034 EXPECT_EQ(loop1->context().realtime_remote_time,
2035 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002036 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08002037
2038 const aos::monotonic_clock::time_point monotonic_now =
2039 loop1->monotonic_now();
2040 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
2041
2042 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
2043 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
2044 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
2045 monotonic_now);
2046 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
2047 realtime_now);
2048
2049 triggered = true;
2050 });
2051
Philipp Schradera6712522023-07-05 20:25:11 -07002052 test_timer->Schedule(loop1->monotonic_now() + ::std::chrono::seconds(1));
Brian Silverman454bc112020-03-05 14:21:25 -08002053
2054 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
2055 Run();
2056
2057 ASSERT_TRUE(triggered);
Austin Schuh7267c532019-05-19 19:55:53 -07002058
Alex Perrycb7da4b2019-08-28 19:35:56 -07002059 monotonic_clock::duration monotonic_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08002060 fetcher.context().monotonic_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07002061 (loop1->monotonic_now() - ::std::chrono::seconds(1));
2062 realtime_clock::duration realtime_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08002063 fetcher.context().realtime_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07002064 (loop1->realtime_now() - ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07002065
Austin Schuhad154822019-12-27 15:45:13 -08002066 EXPECT_EQ(fetcher.context().realtime_event_time,
2067 fetcher.context().realtime_remote_time);
2068 EXPECT_EQ(fetcher.context().monotonic_event_time,
2069 fetcher.context().monotonic_remote_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07002070 EXPECT_EQ(fetcher.context().monotonic_remote_transmit_time,
2071 monotonic_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002072 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08002073
Alex Perrycb7da4b2019-08-28 19:35:56 -07002074 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
2075 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002076 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh52d325c2019-06-23 18:59:06 -07002077 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07002078 // Confirm that the data pointer makes sense.
2079 EXPECT_GT(fetcher.get(), fetcher.context().data);
2080 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07002081 reinterpret_cast<const void *>(
2082 reinterpret_cast<const char *>(fetcher.context().data) +
Alex Perrycb7da4b2019-08-28 19:35:56 -07002083 fetcher.context().size));
2084 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
2085 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002086 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh7267c532019-05-19 19:55:53 -07002087 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07002088
2089 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
2090 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002091 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07002092 << " expected " << loop1->realtime_now().time_since_epoch().count();
2093 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
2094 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002095 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07002096 << " expected " << loop1->realtime_now().time_since_epoch().count();
Austin Schuh7267c532019-05-19 19:55:53 -07002097}
2098
Austin Schuh52d325c2019-06-23 18:59:06 -07002099// Tests that a couple phased loops run in a row result in the correct offset
2100// and period.
2101TEST_P(AbstractEventLoopTest, PhasedLoopTest) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07002102 // Force a slower rate so we are guaranteed to have reports for our phased
Austin Schuh39788ff2019-12-01 18:22:57 -08002103 // loop.
2104 FLAGS_timing_report_ms = 2000;
2105
Austin Schuh52d325c2019-06-23 18:59:06 -07002106 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2107 const int kCount = 5;
2108
2109 auto loop1 = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08002110 auto loop2 = Make();
2111
2112 Fetcher<timing::Report> report_fetcher =
2113 loop2->MakeFetcher<timing::Report>("/aos");
2114 EXPECT_FALSE(report_fetcher.Fetch());
Austin Schuh52d325c2019-06-23 18:59:06 -07002115
2116 // Collect up a couple of samples.
2117 ::std::vector<::aos::monotonic_clock::time_point> times;
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002118 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
Austin Schuh52d325c2019-06-23 18:59:06 -07002119
2120 // Run kCount iterations.
Austin Schuh39788ff2019-12-01 18:22:57 -08002121 loop1
2122 ->AddPhasedLoop(
2123 [&times, &expected_times, &loop1, this](int count) {
2124 EXPECT_EQ(count, 1);
2125 times.push_back(loop1->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08002126 expected_times.push_back(loop1->context().monotonic_event_time);
Austin Schuh39788ff2019-12-01 18:22:57 -08002127
Austin Schuhad154822019-12-27 15:45:13 -08002128 EXPECT_EQ(loop1->context().monotonic_remote_time,
2129 monotonic_clock::min_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07002130 EXPECT_EQ(loop1->context().monotonic_remote_transmit_time,
2131 monotonic_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002132 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08002133 EXPECT_EQ(loop1->context().realtime_event_time,
2134 realtime_clock::min_time);
2135 EXPECT_EQ(loop1->context().realtime_remote_time,
Austin Schuh39788ff2019-12-01 18:22:57 -08002136 realtime_clock::min_time);
2137 EXPECT_EQ(loop1->context().queue_index, 0xffffffffu);
2138 EXPECT_EQ(loop1->context().size, 0u);
2139 EXPECT_EQ(loop1->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07002140 EXPECT_EQ(loop1->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08002141
2142 if (times.size() == kCount) {
2143 LOG(INFO) << "Exiting";
2144 this->Exit();
2145 }
2146 },
2147 chrono::seconds(1), kOffset)
2148 ->set_name("Test loop");
Austin Schuh52d325c2019-06-23 18:59:06 -07002149
2150 // Add a delay to make sure that delay during startup doesn't result in a
2151 // "missed cycle".
2152 SleepFor(chrono::seconds(2));
2153
2154 Run();
2155
2156 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07002157 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
2158 ASSERT_EQ(times.size(), expected_times.size());
2159 ASSERT_EQ((times.size() % 2), 1);
Austin Schuh52d325c2019-06-23 18:59:06 -07002160
2161 // Grab the middle sample.
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002162 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
Austin Schuh52d325c2019-06-23 18:59:06 -07002163
2164 // Add up all the delays of all the times.
2165 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
2166 for (const ::aos::monotonic_clock::time_point time : times) {
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002167 sum += time - average_time;
Austin Schuh52d325c2019-06-23 18:59:06 -07002168 }
2169
2170 // Average and add to the middle to find the average time.
2171 sum /= times.size();
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002172 average_time += sum;
Austin Schuh52d325c2019-06-23 18:59:06 -07002173
2174 // Compute the offset from the start of the second of the average time. This
2175 // should be pretty close to the offset.
2176 const ::aos::monotonic_clock::duration remainder =
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002177 average_time.time_since_epoch() -
2178 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
Austin Schuh52d325c2019-06-23 18:59:06 -07002179
2180 const chrono::milliseconds kEpsilon(100);
2181 EXPECT_LT(remainder, kOffset + kEpsilon);
2182 EXPECT_GT(remainder, kOffset - kEpsilon);
2183
2184 // Make sure that the average duration is close to 1 second.
2185 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
2186 times.front())
2187 .count() /
2188 static_cast<double>(times.size() - 1),
2189 1.0, 0.1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002190
2191 // Confirm that the ideal wakeup times increment correctly.
2192 for (size_t i = 1; i < expected_times.size(); ++i) {
2193 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
2194 }
2195
2196 for (size_t i = 0; i < expected_times.size(); ++i) {
2197 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
2198 kOffset);
2199 }
2200
2201 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
2202 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08002203
Austin Schuh6bae8252021-02-07 22:01:49 -08002204 if (do_timing_reports() == DoTimingReports::kYes) {
2205 // And, since we are here, check that the timing report makes sense.
2206 // Start by looking for our event loop's timing.
2207 FlatbufferDetachedBuffer<timing::Report> report =
2208 FlatbufferDetachedBuffer<timing::Report>::Empty();
2209 while (report_fetcher.FetchNext()) {
2210 if (report_fetcher->name()->string_view() == "primary") {
2211 report = CopyFlatBuffer(report_fetcher.get());
2212 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002213 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002214
2215 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
2216
2217 EXPECT_EQ(report.message().name()->string_view(), "primary");
2218
2219 ASSERT_NE(report.message().senders(), nullptr);
2220 EXPECT_EQ(report.message().senders()->size(), 2);
2221
2222 ASSERT_NE(report.message().timers(), nullptr);
2223 EXPECT_EQ(report.message().timers()->size(), 1);
2224
2225 // Make sure there is a single phased loop report with our report in it.
2226 ASSERT_NE(report.message().phased_loops(), nullptr);
2227 ASSERT_EQ(report.message().phased_loops()->size(), 1);
2228 EXPECT_EQ(report.message().phased_loops()->Get(0)->name()->string_view(),
2229 "Test loop");
2230 EXPECT_GE(report.message().phased_loops()->Get(0)->count(), 1);
2231 } else {
2232 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002233 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002234}
2235
Milind Upadhyay42589bb2021-05-19 20:05:16 -07002236// Tests that a phased loop responds correctly to a changing offset.
2237TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetTest) {
2238 // Force a slower rate so we are guaranteed to have reports for our phased
2239 // loop.
2240 FLAGS_timing_report_ms = 2000;
2241
2242 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2243 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2244 const int kCount = 5;
2245
2246 auto loop1 = MakePrimary();
2247
2248 // Collect up a couple of samples.
2249 ::std::vector<::aos::monotonic_clock::time_point> times;
2250 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
2251
2252 PhasedLoopHandler *phased_loop;
2253
2254 // Run kCount iterations.
2255 phased_loop = loop1->AddPhasedLoop(
2256 [&phased_loop, &times, &expected_times, &loop1, this, kOffset,
2257 kInterval](int count) {
2258 EXPECT_EQ(count, 1);
2259 times.push_back(loop1->monotonic_now());
2260
2261 expected_times.push_back(loop1->context().monotonic_event_time);
2262
2263 phased_loop->set_interval_and_offset(
2264 kInterval, kOffset - chrono::milliseconds(times.size()));
2265 LOG(INFO) << "new offset: "
2266 << (kOffset - chrono::milliseconds(times.size())).count();
2267
2268 if (times.size() == kCount) {
2269 LOG(INFO) << "Exiting";
2270 this->Exit();
2271 }
2272 },
2273 kInterval, kOffset);
2274 phased_loop->set_name("Test loop");
2275
2276 // Add a delay to make sure that delay during startup doesn't result in a
2277 // "missed cycle".
2278 SleepFor(chrono::seconds(2));
2279
2280 Run();
2281 // Confirm that we got both the right number of samples, and it's odd.
2282 EXPECT_EQ(times.size(), static_cast<size_t>(kCount));
2283 EXPECT_EQ(times.size(), expected_times.size());
2284 EXPECT_EQ((times.size() % 2), 1);
2285
2286 // Grab the middle sample.
2287 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
2288
2289 // Add up all the delays of all the times.
2290 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
2291 for (const ::aos::monotonic_clock::time_point time : times) {
2292 sum += time - average_time;
2293 }
2294
2295 // Average and add to the middle to find the average time.
2296 sum /= times.size();
2297 average_time += sum;
2298
2299 // Compute the offset from the start of the second of the average time. This
2300 // should be pretty close to the offset.
2301 const ::aos::monotonic_clock::duration remainder =
2302 average_time.time_since_epoch() -
2303 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
2304
2305 const chrono::milliseconds kEpsilon(100);
2306 EXPECT_LT(remainder, kOffset + kEpsilon);
2307 EXPECT_GT(remainder, kOffset - kEpsilon);
2308
2309 // Make sure that the average duration is close to 1 second.
2310 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
2311 times.front())
2312 .count() /
2313 static_cast<double>(times.size() - 1),
2314 1.0, 0.1);
2315
2316 // Confirm that the ideal wakeup times increment correctly.
2317 for (size_t i = 1; i < expected_times.size(); ++i) {
2318 LOG(INFO) << i - 1 << ": " << expected_times[i - 1] << ", " << i << ": "
2319 << expected_times[i];
2320 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1) -
2321 chrono::milliseconds(1));
2322 }
2323
2324 for (size_t i = 0; i < expected_times.size(); ++i) {
2325 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
2326 kOffset - chrono::milliseconds(i));
2327 }
2328
2329 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
2330 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
2331}
2332
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002333// Tests that a phased loop responds correctly to a changing offset; sweep
2334// across a variety of potential offset changes, to ensure that we are
2335// exercising a variety of potential cases.
2336TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetSweep) {
2337 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2338 const int kCount = 5;
2339
2340 auto loop1 = MakePrimary();
2341
2342 std::vector<aos::monotonic_clock::duration> offset_options;
2343 for (int ii = 0; ii < kCount; ++ii) {
2344 offset_options.push_back(ii * kInterval / kCount);
2345 }
2346 std::vector<aos::monotonic_clock::duration> offset_sweep;
2347 // Run over all the pair-wise combinations of offsets.
2348 for (int ii = 0; ii < kCount; ++ii) {
2349 for (int jj = 0; jj < kCount; ++jj) {
2350 offset_sweep.push_back(offset_options.at(ii));
2351 offset_sweep.push_back(offset_options.at(jj));
2352 }
2353 }
2354
2355 std::vector<::aos::monotonic_clock::time_point> expected_times;
2356
2357 PhasedLoopHandler *phased_loop;
2358
2359 // Run kCount iterations.
2360 size_t counter = 0;
2361 phased_loop = loop1->AddPhasedLoop(
2362 [&phased_loop, &expected_times, &loop1, this, kInterval, &counter,
2363 offset_sweep](int count) {
2364 EXPECT_EQ(count, 1);
2365 expected_times.push_back(loop1->context().monotonic_event_time);
2366
2367 counter++;
2368
2369 if (counter == offset_sweep.size()) {
2370 LOG(INFO) << "Exiting";
2371 this->Exit();
2372 return;
2373 }
2374
2375 phased_loop->set_interval_and_offset(kInterval,
2376 offset_sweep.at(counter));
2377 },
2378 kInterval, offset_sweep.at(0));
2379
2380 Run();
2381 ASSERT_EQ(expected_times.size(), offset_sweep.size());
2382 for (size_t ii = 1; ii < expected_times.size(); ++ii) {
2383 EXPECT_LE(expected_times.at(ii) - expected_times.at(ii - 1), kInterval);
2384 }
2385}
2386
2387// Tests that a phased loop responds correctly to being rescheduled with now
2388// equal to a time in the past.
2389TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleInPast) {
2390 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2391 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2392
2393 auto loop1 = MakePrimary();
2394
2395 std::vector<::aos::monotonic_clock::time_point> expected_times;
2396
2397 PhasedLoopHandler *phased_loop;
2398
2399 int expected_count = 1;
2400
2401 // Set up a timer that will get run immediately after the phased loop and
2402 // which will attempt to reschedule the phased loop to just before now. This
2403 // should succeed, but will result in 0 cycles elapsing.
2404 TimerHandler *manager_timer =
2405 loop1->AddTimer([&phased_loop, &loop1, &expected_count, this]() {
2406 if (expected_count == 0) {
2407 LOG(INFO) << "Exiting";
2408 this->Exit();
2409 return;
2410 }
2411 phased_loop->Reschedule(loop1->context().monotonic_event_time -
2412 std::chrono::nanoseconds(1));
2413 expected_count = 0;
2414 });
2415
2416 phased_loop = loop1->AddPhasedLoop(
2417 [&expected_count, &expected_times, &loop1, manager_timer](int count) {
2418 EXPECT_EQ(count, expected_count);
2419 expected_times.push_back(loop1->context().monotonic_event_time);
2420
Philipp Schradera6712522023-07-05 20:25:11 -07002421 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002422 },
2423 kInterval, kOffset);
2424 phased_loop->set_name("Test loop");
2425 manager_timer->set_name("Manager timer");
2426
2427 Run();
2428
2429 ASSERT_EQ(2u, expected_times.size());
2430 ASSERT_EQ(expected_times[0], expected_times[1]);
2431}
2432
2433// Tests that a phased loop responds correctly to being rescheduled at the time
2434// when it should be triggering (it should kick the trigger to the next cycle).
2435TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleNow) {
2436 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2437 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2438
2439 auto loop1 = MakePrimary();
2440
2441 std::vector<::aos::monotonic_clock::time_point> expected_times;
2442
2443 PhasedLoopHandler *phased_loop;
2444
2445 bool should_exit = false;
2446 // Set up a timer that will get run immediately after the phased loop and
2447 // which will attempt to reschedule the phased loop to now. This should
2448 // succeed, but will result in no change to the expected behavior (since this
2449 // is the same thing that is actually done internally).
2450 TimerHandler *manager_timer =
2451 loop1->AddTimer([&phased_loop, &loop1, &should_exit, this]() {
2452 if (should_exit) {
2453 LOG(INFO) << "Exiting";
2454 this->Exit();
2455 return;
2456 }
2457 phased_loop->Reschedule(loop1->context().monotonic_event_time);
2458 should_exit = true;
2459 });
2460
2461 phased_loop = loop1->AddPhasedLoop(
2462 [&expected_times, &loop1, manager_timer](int count) {
2463 EXPECT_EQ(count, 1);
2464 expected_times.push_back(loop1->context().monotonic_event_time);
2465
Philipp Schradera6712522023-07-05 20:25:11 -07002466 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002467 },
2468 kInterval, kOffset);
2469 phased_loop->set_name("Test loop");
2470 manager_timer->set_name("Manager timer");
2471
2472 Run();
2473
2474 ASSERT_EQ(2u, expected_times.size());
2475 ASSERT_EQ(expected_times[0] + kInterval, expected_times[1]);
2476}
2477
2478// Tests that a phased loop responds correctly to being rescheduled at a time in
2479// the distant future.
2480TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleFuture) {
2481 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2482 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2483
2484 auto loop1 = MakePrimary();
2485
2486 std::vector<::aos::monotonic_clock::time_point> expected_times;
2487
2488 PhasedLoopHandler *phased_loop;
2489
2490 bool should_exit = false;
2491 int expected_count = 1;
2492 TimerHandler *manager_timer = loop1->AddTimer(
2493 [&expected_count, &phased_loop, &loop1, &should_exit, this, kInterval]() {
2494 if (should_exit) {
2495 LOG(INFO) << "Exiting";
2496 this->Exit();
2497 return;
2498 }
2499 expected_count = 10;
2500 // Knock off 1 ns, since the scheduler rounds up when it is
2501 // scheduled to exactly a loop time.
2502 phased_loop->Reschedule(loop1->context().monotonic_event_time +
2503 kInterval * expected_count -
2504 std::chrono::nanoseconds(1));
2505 should_exit = true;
2506 });
2507
2508 phased_loop = loop1->AddPhasedLoop(
2509 [&expected_times, &loop1, manager_timer, &expected_count](int count) {
2510 EXPECT_EQ(count, expected_count);
2511 expected_times.push_back(loop1->context().monotonic_event_time);
2512
Philipp Schradera6712522023-07-05 20:25:11 -07002513 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002514 },
2515 kInterval, kOffset);
2516 phased_loop->set_name("Test loop");
2517 manager_timer->set_name("Manager timer");
2518
2519 Run();
2520
2521 ASSERT_EQ(2u, expected_times.size());
2522 ASSERT_EQ(expected_times[0] + expected_count * kInterval, expected_times[1]);
2523}
2524
2525// Tests that a phased loop responds correctly to having its phase offset
2526// incremented and then being scheduled after a set time, exercising a pattern
2527// where a phased loop's offset is changed while trying to maintain the trigger
2528// at a consistent period.
2529TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleWithLaterOffset) {
2530 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2531 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2532
2533 auto loop1 = MakePrimary();
2534
2535 std::vector<::aos::monotonic_clock::time_point> expected_times;
2536
2537 PhasedLoopHandler *phased_loop;
2538
2539 bool should_exit = false;
2540 TimerHandler *manager_timer = loop1->AddTimer(
2541 [&phased_loop, &loop1, &should_exit, this, kInterval, kOffset]() {
2542 if (should_exit) {
2543 LOG(INFO) << "Exiting";
2544 this->Exit();
2545 return;
2546 }
2547 // Schedule the next callback to be strictly later than the current time
2548 // + interval / 2, to ensure a consistent frequency.
2549 monotonic_clock::time_point half_time =
2550 loop1->context().monotonic_event_time + kInterval / 2;
2551 phased_loop->set_interval_and_offset(
2552 kInterval, kOffset + std::chrono::nanoseconds(1), half_time);
2553 phased_loop->Reschedule(half_time);
2554 should_exit = true;
2555 });
2556
2557 phased_loop = loop1->AddPhasedLoop(
2558 [&expected_times, &loop1, manager_timer](int count) {
2559 EXPECT_EQ(1, count);
2560 expected_times.push_back(loop1->context().monotonic_event_time);
2561
Philipp Schradera6712522023-07-05 20:25:11 -07002562 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002563 },
2564 kInterval, kOffset);
2565 phased_loop->set_name("Test loop");
2566 manager_timer->set_name("Manager timer");
2567
2568 Run();
2569
2570 ASSERT_EQ(2u, expected_times.size());
2571 ASSERT_EQ(expected_times[0] + kInterval + std::chrono::nanoseconds(1),
2572 expected_times[1]);
2573}
2574
2575// Tests that a phased loop responds correctly to having its phase offset
2576// decremented and then being scheduled after a set time, exercising a pattern
2577// where a phased loop's offset is changed while trying to maintain the trigger
2578// at a consistent period.
2579TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleWithEarlierOffset) {
2580 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2581 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2582
2583 auto loop1 = MakePrimary();
2584
2585 std::vector<::aos::monotonic_clock::time_point> expected_times;
2586
2587 PhasedLoopHandler *phased_loop;
2588
2589 bool should_exit = false;
2590 TimerHandler *manager_timer = loop1->AddTimer(
2591 [&phased_loop, &loop1, &should_exit, this, kInterval, kOffset]() {
2592 if (should_exit) {
2593 LOG(INFO) << "Exiting";
2594 this->Exit();
2595 return;
2596 }
2597 // Schedule the next callback to be strictly later than the current time
2598 // + interval / 2, to ensure a consistent frequency.
2599 const aos::monotonic_clock::time_point half_time =
2600 loop1->context().monotonic_event_time + kInterval / 2;
2601 phased_loop->set_interval_and_offset(
2602 kInterval, kOffset - std::chrono::nanoseconds(1), half_time);
2603 phased_loop->Reschedule(half_time);
2604 should_exit = true;
2605 });
2606
2607 phased_loop = loop1->AddPhasedLoop(
2608 [&expected_times, &loop1, manager_timer](int count) {
2609 EXPECT_EQ(1, count);
2610 expected_times.push_back(loop1->context().monotonic_event_time);
2611
Philipp Schradera6712522023-07-05 20:25:11 -07002612 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002613 },
2614 kInterval, kOffset);
2615 phased_loop->set_name("Test loop");
2616 manager_timer->set_name("Manager timer");
2617
2618 Run();
2619
2620 ASSERT_EQ(2u, expected_times.size());
2621 ASSERT_EQ(expected_times[0] + kInterval - std::chrono::nanoseconds(1),
2622 expected_times[1]);
2623}
2624
Austin Schuh39788ff2019-12-01 18:22:57 -08002625// Tests that senders count correctly in the timing report.
2626TEST_P(AbstractEventLoopTest, SenderTimingReport) {
2627 FLAGS_timing_report_ms = 1000;
2628 auto loop1 = MakePrimary();
2629
2630 auto loop2 = Make("watcher_loop");
2631 loop2->MakeWatcher("/test", [](const TestMessage &) {});
2632
2633 auto loop3 = Make();
2634
2635 Fetcher<timing::Report> report_fetcher =
2636 loop3->MakeFetcher<timing::Report>("/aos");
2637 EXPECT_FALSE(report_fetcher.Fetch());
2638
2639 auto sender = loop1->MakeSender<TestMessage>("/test");
2640
James Kuszmaul78514332022-04-06 15:08:34 -07002641 // Sanity check channel frequencies to ensure that we've designed the test
2642 // correctly.
2643 ASSERT_EQ(800, sender.channel()->frequency());
Austin Schuhfff9c3a2023-06-16 18:48:23 -07002644 ASSERT_EQ(2000000000, configuration::ChannelStorageDuration(
2645 loop1->configuration(), sender.channel())
2646 .count());
James Kuszmaul78514332022-04-06 15:08:34 -07002647 constexpr int kMaxAllowedMessages = 800 * 2;
2648 constexpr int kSendMessages = kMaxAllowedMessages * 2;
2649 constexpr int kDroppedMessages = kSendMessages - kMaxAllowedMessages;
2650
Austin Schuh39788ff2019-12-01 18:22:57 -08002651 // Add a timer to actually quit.
2652 auto test_timer = loop1->AddTimer([&sender]() {
James Kuszmaul78514332022-04-06 15:08:34 -07002653 for (int i = 0; i < kSendMessages; ++i) {
Austin Schuh39788ff2019-12-01 18:22:57 -08002654 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2655 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2656 builder.add_value(200 + i);
James Kuszmaul78514332022-04-06 15:08:34 -07002657 if (i < kMaxAllowedMessages) {
2658 msg.CheckOk(msg.Send(builder.Finish()));
2659 } else {
2660 EXPECT_EQ(RawSender::Error::kMessagesSentTooFast,
2661 msg.Send(builder.Finish()));
2662 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002663 }
2664 });
2665
2666 // Quit after 1 timing report, mid way through the next cycle.
2667 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2668
2669 loop1->OnRun([&test_timer, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002670 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1500));
Austin Schuh39788ff2019-12-01 18:22:57 -08002671 });
2672
2673 Run();
2674
Austin Schuh6bae8252021-02-07 22:01:49 -08002675 if (do_timing_reports() == DoTimingReports::kYes) {
2676 // And, since we are here, check that the timing report makes sense.
2677 // Start by looking for our event loop's timing.
2678 FlatbufferDetachedBuffer<timing::Report> primary_report =
2679 FlatbufferDetachedBuffer<timing::Report>::Empty();
2680 while (report_fetcher.FetchNext()) {
Austin Schuh8902fa52021-03-14 22:39:24 -07002681 VLOG(1) << "Report " << FlatbufferToJson(report_fetcher.get());
Austin Schuh6bae8252021-02-07 22:01:49 -08002682 if (report_fetcher->name()->string_view() == "primary") {
2683 primary_report = CopyFlatBuffer(report_fetcher.get());
2684 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002685 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002686
Austin Schuh8902fa52021-03-14 22:39:24 -07002687 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
Austin Schuh6bae8252021-02-07 22:01:49 -08002688
2689 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2690
2691 ASSERT_NE(primary_report.message().senders(), nullptr);
2692 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2693
2694 // Confirm that the sender looks sane.
2695 EXPECT_EQ(
2696 loop1->configuration()
2697 ->channels()
2698 ->Get(primary_report.message().senders()->Get(0)->channel_index())
2699 ->name()
2700 ->string_view(),
2701 "/test");
James Kuszmaul78514332022-04-06 15:08:34 -07002702 EXPECT_EQ(primary_report.message().senders()->Get(0)->count(),
2703 kMaxAllowedMessages);
2704 ASSERT_TRUE(primary_report.message().senders()->Get(0)->has_error_counts());
2705 ASSERT_EQ(
2706 primary_report.message().senders()->Get(0)->error_counts()->size(), 2u);
2707 EXPECT_EQ(
2708 primary_report.message()
2709 .senders()
2710 ->Get(0)
2711 ->error_counts()
2712 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2713 ->count(),
2714 kDroppedMessages)
2715 << aos::FlatbufferToJson(primary_report);
2716 EXPECT_EQ(primary_report.message()
2717 .senders()
2718 ->Get(0)
2719 ->error_counts()
2720 ->Get(static_cast<size_t>(timing::SendError::INVALID_REDZONE))
2721 ->count(),
2722 0);
Austin Schuh6bae8252021-02-07 22:01:49 -08002723
2724 // Confirm that the timing primary_report sender looks sane.
2725 EXPECT_EQ(
2726 loop1->configuration()
2727 ->channels()
2728 ->Get(primary_report.message().senders()->Get(1)->channel_index())
2729 ->name()
2730 ->string_view(),
2731 "/aos");
2732 EXPECT_EQ(primary_report.message().senders()->Get(1)->count(), 1);
2733
2734 ASSERT_NE(primary_report.message().timers(), nullptr);
2735 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2736
2737 // Make sure there are no phased loops or watchers.
2738 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2739 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2740 } else {
2741 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002742 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002743}
2744
James Kuszmaul93abac12022-04-14 15:05:10 -07002745// Tests that the RawSender::Send(void*, size_t) overload tracks things properly
2746// in its timing report.
2747TEST_P(AbstractEventLoopTest, CopySenderTimingReport) {
2748 gflags::FlagSaver flag_saver;
2749 FLAGS_timing_report_ms = 1000;
2750 auto loop1 = Make();
2751 auto loop2 = MakePrimary();
2752
2753 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2754 JsonToFlatbuffer<TestMessage>("{}");
2755
2756 std::unique_ptr<aos::RawSender> sender =
2757 loop2->MakeRawSender(configuration::GetChannel(
2758 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
2759
2760 Fetcher<timing::Report> report_fetcher =
2761 loop1->MakeFetcher<timing::Report>("/aos");
2762 EXPECT_FALSE(report_fetcher.Fetch());
2763
2764 loop2->OnRun([&]() {
2765 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
2766 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2767 RawSender::Error::kOk);
2768 }
2769 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2770 RawSender::Error::kMessagesSentTooFast);
2771 });
2772 // Quit after 1 timing report, mid way through the next cycle.
2773 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
2774
2775 Run();
2776
2777 if (do_timing_reports() == DoTimingReports::kYes) {
2778 // Check that the sent too fast actually got recorded by the timing report.
2779 FlatbufferDetachedBuffer<timing::Report> primary_report =
2780 FlatbufferDetachedBuffer<timing::Report>::Empty();
2781 while (report_fetcher.FetchNext()) {
2782 if (report_fetcher->name()->string_view() == "primary") {
2783 primary_report = CopyFlatBuffer(report_fetcher.get());
2784 }
2785 }
2786
2787 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2788
2789 ASSERT_NE(primary_report.message().senders(), nullptr);
2790 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2791 EXPECT_EQ(
2792 primary_report.message()
2793 .senders()
2794 ->Get(0)
2795 ->error_counts()
2796 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2797 ->count(),
2798 1);
2799 }
2800}
2801
Austin Schuhe0ab4de2023-05-03 08:05:08 -07002802// Tests that the RawSender::Send(SharedSpan) overload works.
2803TEST_P(AbstractEventLoopTest, SharedSenderTimingReport) {
2804 gflags::FlagSaver flag_saver;
2805 FLAGS_timing_report_ms = 1000;
2806 auto loop1 = Make();
2807 auto loop2 = MakePrimary();
2808
2809 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2810 JsonToFlatbuffer<TestMessage>("{}");
2811
2812 std::unique_ptr<aos::RawSender> sender =
2813 loop2->MakeRawSender(configuration::GetChannel(
2814 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
2815
2816 Fetcher<timing::Report> report_fetcher =
2817 loop1->MakeFetcher<timing::Report>("/aos");
2818 EXPECT_FALSE(report_fetcher.Fetch());
2819
2820 loop2->OnRun([&]() {
2821 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
2822 auto shared_span = MakeSharedSpan(kMessage.span().size());
2823 memcpy(shared_span.second.data(), kMessage.span().data(),
2824 kMessage.span().size());
2825 EXPECT_EQ(sender->Send(std::move(shared_span.first)),
2826 RawSender::Error::kOk);
2827 }
2828 auto shared_span = MakeSharedSpan(kMessage.span().size());
2829 memcpy(shared_span.second.data(), kMessage.span().data(),
2830 kMessage.span().size());
2831 EXPECT_EQ(sender->Send(std::move(shared_span.first)),
2832 RawSender::Error::kMessagesSentTooFast);
2833 });
2834 // Quit after 1 timing report, mid way through the next cycle.
2835 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
2836
2837 Run();
2838
2839 if (do_timing_reports() == DoTimingReports::kYes) {
2840 // Check that the sent too fast actually got recorded by the timing report.
2841 FlatbufferDetachedBuffer<timing::Report> primary_report =
2842 FlatbufferDetachedBuffer<timing::Report>::Empty();
2843 while (report_fetcher.FetchNext()) {
2844 if (report_fetcher->name()->string_view() == "primary") {
2845 primary_report = CopyFlatBuffer(report_fetcher.get());
2846 }
2847 }
2848
2849 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2850
2851 ASSERT_NE(primary_report.message().senders(), nullptr);
2852 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2853 EXPECT_EQ(
2854 primary_report.message()
2855 .senders()
2856 ->Get(0)
2857 ->error_counts()
2858 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2859 ->count(),
2860 1);
2861 }
2862}
2863
Austin Schuh39788ff2019-12-01 18:22:57 -08002864// Tests that senders count correctly in the timing report.
2865TEST_P(AbstractEventLoopTest, WatcherTimingReport) {
2866 FLAGS_timing_report_ms = 1000;
2867 auto loop1 = MakePrimary();
2868 loop1->MakeWatcher("/test", [](const TestMessage &) {});
2869
2870 auto loop2 = Make("sender_loop");
2871
2872 auto loop3 = Make();
2873
2874 Fetcher<timing::Report> report_fetcher =
2875 loop3->MakeFetcher<timing::Report>("/aos");
2876 EXPECT_FALSE(report_fetcher.Fetch());
2877
2878 auto sender = loop2->MakeSender<TestMessage>("/test");
2879
2880 // Add a timer to actually quit.
2881 auto test_timer = loop1->AddTimer([&sender]() {
2882 for (int i = 0; i < 10; ++i) {
2883 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2884 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2885 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002886 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002887 }
2888 });
2889
2890 // Quit after 1 timing report, mid way through the next cycle.
2891 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2892
2893 loop1->OnRun([&test_timer, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002894 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1500));
Austin Schuh39788ff2019-12-01 18:22:57 -08002895 });
2896
2897 Run();
2898
Austin Schuh6bae8252021-02-07 22:01:49 -08002899 if (do_timing_reports() == DoTimingReports::kYes) {
2900 // And, since we are here, check that the timing report makes sense.
2901 // Start by looking for our event loop's timing.
2902 FlatbufferDetachedBuffer<timing::Report> primary_report =
2903 FlatbufferDetachedBuffer<timing::Report>::Empty();
2904 while (report_fetcher.FetchNext()) {
2905 LOG(INFO) << "Report " << FlatbufferToJson(report_fetcher.get());
2906 if (report_fetcher->name()->string_view() == "primary") {
2907 primary_report = CopyFlatBuffer(report_fetcher.get());
2908 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002909 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002910
2911 // Check the watcher report.
2912 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2913
2914 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2915
2916 // Just the timing report timer.
2917 ASSERT_NE(primary_report.message().timers(), nullptr);
2918 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2919
2920 // No phased loops
2921 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2922
2923 ASSERT_NE(primary_report.message().watchers(), nullptr);
2924 ASSERT_EQ(primary_report.message().watchers()->size(), 1);
2925 EXPECT_EQ(primary_report.message().watchers()->Get(0)->count(), 10);
2926 } else {
2927 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002928 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002929}
2930
2931// Tests that fetchers count correctly in the timing report.
2932TEST_P(AbstractEventLoopTest, FetcherTimingReport) {
2933 FLAGS_timing_report_ms = 1000;
2934 auto loop1 = MakePrimary();
2935 auto loop2 = Make("sender_loop");
2936
2937 auto loop3 = Make();
2938
2939 Fetcher<timing::Report> report_fetcher =
2940 loop3->MakeFetcher<timing::Report>("/aos");
2941 EXPECT_FALSE(report_fetcher.Fetch());
2942
2943 auto sender = loop2->MakeSender<TestMessage>("/test");
2944 auto fetcher1 = loop1->MakeFetcher<TestMessage>("/test");
2945 auto fetcher2 = loop1->MakeFetcher<TestMessage>("/test");
2946 fetcher1.Fetch();
2947 fetcher2.Fetch();
2948
2949 // Add a timer to actually quit.
2950 auto test_timer = loop1->AddTimer([&sender]() {
2951 for (int i = 0; i < 10; ++i) {
2952 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2953 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2954 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002955 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002956 }
2957 });
2958
2959 auto test_timer2 = loop1->AddTimer([&fetcher1, &fetcher2]() {
2960 fetcher1.Fetch();
2961 while (fetcher2.FetchNext()) {
2962 }
2963 });
2964
2965 // Quit after 1 timing report, mid way through the next cycle.
2966 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2967
2968 loop1->OnRun([test_timer, test_timer2, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002969 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1400));
2970 test_timer2->Schedule(loop1->monotonic_now() + chrono::milliseconds(1600));
Austin Schuh39788ff2019-12-01 18:22:57 -08002971 });
2972
2973 Run();
2974
Austin Schuh6bae8252021-02-07 22:01:49 -08002975 if (do_timing_reports() == DoTimingReports::kYes) {
2976 // And, since we are here, check that the timing report makes sense.
2977 // Start by looking for our event loop's timing.
2978 FlatbufferDetachedBuffer<timing::Report> primary_report =
2979 FlatbufferDetachedBuffer<timing::Report>::Empty();
2980 while (report_fetcher.FetchNext()) {
2981 if (report_fetcher->name()->string_view() == "primary") {
2982 primary_report = CopyFlatBuffer(report_fetcher.get());
2983 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002984 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002985
2986 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2987
2988 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2989
2990 ASSERT_NE(primary_report.message().senders(), nullptr);
2991 EXPECT_EQ(primary_report.message().senders()->size(), 2);
2992
2993 ASSERT_NE(primary_report.message().timers(), nullptr);
2994 EXPECT_EQ(primary_report.message().timers()->size(), 4);
2995
2996 // Make sure there are no phased loops or watchers.
2997 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2998 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2999
3000 // Now look at the fetchrs.
3001 ASSERT_NE(primary_report.message().fetchers(), nullptr);
3002 ASSERT_EQ(primary_report.message().fetchers()->size(), 2);
3003
3004 EXPECT_EQ(primary_report.message().fetchers()->Get(0)->count(), 1);
3005 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->average(),
3006 0.1);
3007 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->min(),
3008 0.1);
3009 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->max(),
3010 0.1);
3011 EXPECT_EQ(primary_report.message()
3012 .fetchers()
3013 ->Get(0)
3014 ->latency()
3015 ->standard_deviation(),
3016 0.0);
3017
3018 EXPECT_EQ(primary_report.message().fetchers()->Get(1)->count(), 10);
3019 } else {
3020 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08003021 }
Austin Schuh52d325c2019-06-23 18:59:06 -07003022}
3023
Austin Schuh67420a42019-12-21 21:55:04 -08003024// Tests that a raw watcher and raw fetcher can receive messages from a raw
3025// sender without messing up offsets.
3026TEST_P(AbstractEventLoopTest, RawBasic) {
3027 auto loop1 = Make();
3028 auto loop2 = MakePrimary();
3029 auto loop3 = Make();
3030
Austin Schuha9df9ad2021-06-16 14:49:39 -07003031 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3032 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuh67420a42019-12-21 21:55:04 -08003033
3034 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003035 loop1->MakeRawSender(configuration::GetChannel(
3036 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08003037
3038 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003039 loop3->MakeRawFetcher(configuration::GetChannel(
3040 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08003041
Austin Schuha9df9ad2021-06-16 14:49:39 -07003042 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07003043 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
3044 RawSender::Error::kOk);
Austin Schuha9df9ad2021-06-16 14:49:39 -07003045 });
Austin Schuh67420a42019-12-21 21:55:04 -08003046
3047 bool happened = false;
3048 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08003049 configuration::GetChannel(loop2->configuration(), "/test",
3050 "aos.TestMessage", "", nullptr),
Austin Schuha9df9ad2021-06-16 14:49:39 -07003051 [this, &kMessage, &fetcher, &happened](const Context &context,
3052 const void *message) {
Austin Schuh67420a42019-12-21 21:55:04 -08003053 happened = true;
Austin Schuha9df9ad2021-06-16 14:49:39 -07003054 EXPECT_EQ(
3055 kMessage.span(),
3056 absl::Span<const uint8_t>(
3057 reinterpret_cast<const uint8_t *>(message), context.size));
3058 EXPECT_EQ(message, context.data);
Austin Schuh67420a42019-12-21 21:55:04 -08003059
3060 ASSERT_TRUE(fetcher->Fetch());
3061
Austin Schuha9df9ad2021-06-16 14:49:39 -07003062 EXPECT_EQ(kMessage.span(),
3063 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
3064 fetcher->context().data),
3065 fetcher->context().size));
Austin Schuh67420a42019-12-21 21:55:04 -08003066
3067 this->Exit();
3068 });
3069
3070 EXPECT_FALSE(happened);
3071 Run();
3072 EXPECT_TRUE(happened);
3073}
3074
Austin Schuhad154822019-12-27 15:45:13 -08003075// Tests that a raw watcher and raw fetcher can receive messages from a raw
Brian Silvermanbf889922021-11-10 12:41:57 -08003076// sender without messing up offsets, using the RawSpan overload.
3077TEST_P(AbstractEventLoopTest, RawBasicSharedSpan) {
3078 auto loop1 = Make();
3079 auto loop2 = MakePrimary();
3080 auto loop3 = Make();
3081
3082 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3083 JsonToFlatbuffer<TestMessage>("{}");
3084
3085 std::unique_ptr<aos::RawSender> sender =
3086 loop1->MakeRawSender(configuration::GetChannel(
3087 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
3088
3089 std::unique_ptr<aos::RawFetcher> fetcher =
3090 loop3->MakeRawFetcher(configuration::GetChannel(
3091 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
3092
3093 loop2->OnRun([&]() {
Austin Schuhe0ab4de2023-05-03 08:05:08 -07003094 auto shared_span = MakeSharedSpan(kMessage.span().size());
3095 memcpy(shared_span.second.data(), kMessage.span().data(),
3096 kMessage.span().size());
3097 sender->CheckOk(sender->Send(std::move(shared_span.first)));
Brian Silvermanbf889922021-11-10 12:41:57 -08003098 });
3099
3100 bool happened = false;
3101 loop2->MakeRawWatcher(
3102 configuration::GetChannel(loop2->configuration(), "/test",
3103 "aos.TestMessage", "", nullptr),
3104 [this, &kMessage, &fetcher, &happened](const Context &context,
3105 const void *message) {
3106 happened = true;
3107 EXPECT_EQ(
3108 kMessage.span(),
3109 absl::Span<const uint8_t>(
3110 reinterpret_cast<const uint8_t *>(message), context.size));
3111 EXPECT_EQ(message, context.data);
3112
3113 ASSERT_TRUE(fetcher->Fetch());
3114
3115 EXPECT_EQ(kMessage.span(),
3116 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
3117 fetcher->context().data),
3118 fetcher->context().size));
3119
3120 this->Exit();
3121 });
3122
3123 EXPECT_FALSE(happened);
3124 Run();
3125 EXPECT_TRUE(happened);
3126}
3127
3128// Tests that a raw watcher and raw fetcher can receive messages from a raw
Austin Schuhad154822019-12-27 15:45:13 -08003129// sender with remote times filled out.
3130TEST_P(AbstractEventLoopTest, RawRemoteTimes) {
3131 auto loop1 = Make();
3132 auto loop2 = MakePrimary();
3133 auto loop3 = Make();
3134
Austin Schuha9df9ad2021-06-16 14:49:39 -07003135 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3136 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08003137
3138 const aos::monotonic_clock::time_point monotonic_remote_time =
3139 aos::monotonic_clock::time_point(chrono::seconds(1501));
3140 const aos::realtime_clock::time_point realtime_remote_time =
3141 aos::realtime_clock::time_point(chrono::seconds(3132));
Austin Schuhac6d89e2024-03-27 14:56:09 -07003142 const aos::monotonic_clock::time_point monotonic_remote_transmit_time =
3143 aos::monotonic_clock::time_point(chrono::seconds(1601));
Austin Schuhb5c6f972021-03-14 21:53:07 -07003144 const uint32_t remote_queue_index = 0x254971;
Austin Schuha9012be2021-07-21 15:19:11 -07003145 const UUID source_boot_uuid = UUID::Random();
Austin Schuhad154822019-12-27 15:45:13 -08003146
3147 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003148 loop1->MakeRawSender(configuration::GetChannel(
3149 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08003150
3151 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003152 loop3->MakeRawFetcher(configuration::GetChannel(
3153 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08003154
3155 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07003156 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size(),
3157 monotonic_remote_time, realtime_remote_time,
Austin Schuhac6d89e2024-03-27 14:56:09 -07003158 monotonic_remote_transmit_time, remote_queue_index,
3159 source_boot_uuid),
milind1f1dca32021-07-03 13:50:07 -07003160 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08003161 });
3162
3163 bool happened = false;
3164 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08003165 configuration::GetChannel(loop2->configuration(), "/test",
3166 "aos.TestMessage", "", nullptr),
Austin Schuhac6d89e2024-03-27 14:56:09 -07003167 [this, monotonic_remote_time, realtime_remote_time,
3168 monotonic_remote_transmit_time, source_boot_uuid, remote_queue_index,
3169 &fetcher, &happened](const Context &context, const void * /*message*/) {
Austin Schuhad154822019-12-27 15:45:13 -08003170 happened = true;
3171 EXPECT_EQ(monotonic_remote_time, context.monotonic_remote_time);
3172 EXPECT_EQ(realtime_remote_time, context.realtime_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07003173 EXPECT_EQ(source_boot_uuid, context.source_boot_uuid);
Austin Schuhb5c6f972021-03-14 21:53:07 -07003174 EXPECT_EQ(remote_queue_index, context.remote_queue_index);
Austin Schuhad154822019-12-27 15:45:13 -08003175
3176 ASSERT_TRUE(fetcher->Fetch());
3177 EXPECT_EQ(monotonic_remote_time,
3178 fetcher->context().monotonic_remote_time);
3179 EXPECT_EQ(realtime_remote_time,
3180 fetcher->context().realtime_remote_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07003181 EXPECT_EQ(monotonic_remote_transmit_time,
3182 fetcher->context().monotonic_remote_transmit_time);
Austin Schuhad154822019-12-27 15:45:13 -08003183
3184 this->Exit();
3185 });
3186
3187 EXPECT_FALSE(happened);
3188 Run();
3189 EXPECT_TRUE(happened);
Austin Schuhac6d89e2024-03-27 14:56:09 -07003190
3191 // Confirm everything goes back.
3192 EXPECT_EQ(loop2->context().monotonic_event_time, monotonic_clock::min_time);
3193 EXPECT_EQ(loop2->context().monotonic_remote_time, monotonic_clock::min_time);
3194 EXPECT_EQ(loop2->context().monotonic_remote_transmit_time,
3195 monotonic_clock::min_time);
3196 EXPECT_EQ(loop2->context().realtime_event_time, realtime_clock::min_time);
3197 EXPECT_EQ(loop2->context().realtime_remote_time, realtime_clock::min_time);
3198 EXPECT_EQ(loop2->context().source_boot_uuid, loop2->boot_uuid());
3199 EXPECT_EQ(loop2->context().queue_index, 0xffffffffu);
3200 EXPECT_EQ(loop2->context().size, 0u);
3201 EXPECT_EQ(loop2->context().data, nullptr);
3202 EXPECT_EQ(loop2->context().buffer_index, -1);
Austin Schuhad154822019-12-27 15:45:13 -08003203}
3204
3205// Tests that a raw sender fills out sent data.
3206TEST_P(AbstractEventLoopTest, RawSenderSentData) {
3207 auto loop1 = MakePrimary();
3208
Austin Schuha9df9ad2021-06-16 14:49:39 -07003209 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3210 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08003211
3212 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003213 loop1->MakeRawSender(configuration::GetChannel(
3214 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08003215
Tyler Chatow67ddb032020-01-12 14:30:04 -08003216 const aos::monotonic_clock::time_point monotonic_now = loop1->monotonic_now();
3217 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08003218
milind1f1dca32021-07-03 13:50:07 -07003219 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
3220 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08003221
3222 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
3223 EXPECT_LE(sender->monotonic_sent_time(),
3224 monotonic_now + chrono::milliseconds(100));
3225 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
3226 EXPECT_LE(sender->realtime_sent_time(),
3227 realtime_now + chrono::milliseconds(100));
3228 EXPECT_EQ(sender->sent_queue_index(), 0u);
3229
milind1f1dca32021-07-03 13:50:07 -07003230 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
3231 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08003232
3233 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
3234 EXPECT_LE(sender->monotonic_sent_time(),
3235 monotonic_now + chrono::milliseconds(100));
3236 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
3237 EXPECT_LE(sender->realtime_sent_time(),
3238 realtime_now + chrono::milliseconds(100));
3239 EXPECT_EQ(sender->sent_queue_index(), 1u);
3240}
3241
Austin Schuh217a9782019-12-21 23:02:50 -08003242// Tests that not setting up nodes results in no node.
3243TEST_P(AbstractEventLoopTest, NoNode) {
3244 auto loop1 = Make();
3245 auto loop2 = MakePrimary();
3246
3247 EXPECT_EQ(loop1->node(), nullptr);
3248 EXPECT_EQ(loop2->node(), nullptr);
3249}
3250
3251// Tests that setting up nodes results in node being set.
3252TEST_P(AbstractEventLoopTest, Node) {
3253 EnableNodes("me");
3254
3255 auto loop1 = Make();
3256 auto loop2 = MakePrimary();
3257
3258 EXPECT_NE(loop1->node(), nullptr);
3259 EXPECT_NE(loop2->node(), nullptr);
3260}
3261
3262// Tests that watchers work with a node setup.
3263TEST_P(AbstractEventLoopTest, NodeWatcher) {
3264 EnableNodes("me");
3265
3266 auto loop1 = Make();
3267 auto loop2 = Make();
3268 loop1->MakeWatcher("/test", [](const TestMessage &) {});
Tyler Chatow67ddb032020-01-12 14:30:04 -08003269 loop2->MakeRawWatcher(
3270 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
3271 nullptr),
3272 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08003273}
3274
Brian Silverman454bc112020-03-05 14:21:25 -08003275// Tests that no-arg watchers work with a node setup.
3276TEST_P(AbstractEventLoopTest, NodeNoArgWatcher) {
3277 EnableNodes("me");
3278
3279 auto loop1 = Make();
3280 auto loop2 = Make();
3281 loop1->MakeWatcher("/test", [](const TestMessage &) {});
3282 loop2->MakeRawNoArgWatcher(
3283 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
3284 nullptr),
3285 [](const Context &) {});
3286}
3287
Austin Schuh217a9782019-12-21 23:02:50 -08003288// Tests that fetcher work with a node setup.
3289TEST_P(AbstractEventLoopTest, NodeFetcher) {
3290 EnableNodes("me");
3291 auto loop1 = Make();
3292
3293 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
Tyler Chatow67ddb032020-01-12 14:30:04 -08003294 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
3295 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08003296}
3297
3298// Tests that sender work with a node setup.
3299TEST_P(AbstractEventLoopTest, NodeSender) {
3300 EnableNodes("me");
3301 auto loop1 = Make();
3302
3303 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
3304}
3305
Austin Schuhcc6070c2020-10-10 20:25:56 -07003306// Tests that a non-realtime event loop timer is marked non-realtime.
3307TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopTimer) {
3308 auto loop1 = MakePrimary();
3309
3310 // Add a timer to actually quit.
3311 auto test_timer = loop1->AddTimer([this]() {
3312 CheckNotRealtime();
3313 this->Exit();
3314 });
3315
3316 loop1->OnRun([&test_timer, &loop1]() {
3317 CheckNotRealtime();
Philipp Schradera6712522023-07-05 20:25:11 -07003318 test_timer->Schedule(loop1->monotonic_now(),
3319 ::std::chrono::milliseconds(100));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003320 });
3321
3322 Run();
3323}
3324
3325// Tests that a realtime event loop timer is marked realtime.
Austin Schuh9b1d6282022-06-10 17:03:21 -07003326TEST_P(AbstractEventLoopTest, RealtimeSend) {
3327 auto loop1 = MakePrimary();
3328
3329 loop1->SetRuntimeRealtimePriority(1);
3330
3331 auto sender = loop1->MakeSender<TestMessage>("/test2");
3332
3333 loop1->OnRun([&]() {
3334 CheckRealtime();
3335
3336 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3337 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
3338 builder.add_value(200);
3339 msg.CheckOk(msg.Send(builder.Finish()));
3340
3341 this->Exit();
3342 });
3343
3344 Run();
3345}
3346
3347// Tests that a realtime event loop timer is marked realtime.
Austin Schuhcc6070c2020-10-10 20:25:56 -07003348TEST_P(AbstractEventLoopTest, RealtimeEventLoopTimer) {
3349 auto loop1 = MakePrimary();
3350
3351 loop1->SetRuntimeRealtimePriority(1);
3352
3353 // Add a timer to actually quit.
3354 auto test_timer = loop1->AddTimer([this]() {
3355 CheckRealtime();
3356 this->Exit();
3357 });
3358
3359 loop1->OnRun([&test_timer, &loop1]() {
3360 CheckRealtime();
Philipp Schradera6712522023-07-05 20:25:11 -07003361 test_timer->Schedule(loop1->monotonic_now(),
3362 ::std::chrono::milliseconds(100));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003363 });
3364
3365 Run();
3366}
3367
3368// Tests that a non-realtime event loop phased loop is marked non-realtime.
3369TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopPhasedLoop) {
3370 auto loop1 = MakePrimary();
3371
3372 // Add a timer to actually quit.
3373 loop1->AddPhasedLoop(
3374 [this](int) {
3375 CheckNotRealtime();
3376 this->Exit();
3377 },
3378 chrono::seconds(1), chrono::seconds(0));
3379
3380 Run();
3381}
3382
3383// Tests that a realtime event loop phased loop is marked realtime.
3384TEST_P(AbstractEventLoopTest, RealtimeEventLoopPhasedLoop) {
3385 auto loop1 = MakePrimary();
3386
3387 loop1->SetRuntimeRealtimePriority(1);
3388
3389 // Add a timer to actually quit.
3390 loop1->AddPhasedLoop(
3391 [this](int) {
3392 CheckRealtime();
3393 this->Exit();
3394 },
3395 chrono::seconds(1), chrono::seconds(0));
3396
3397 Run();
3398}
3399
3400// Tests that a non-realtime event loop watcher is marked non-realtime.
3401TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopWatcher) {
3402 auto loop1 = MakePrimary();
3403 auto loop2 = Make();
3404
3405 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
3406
3407 loop1->OnRun([&]() {
3408 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3409 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07003410 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003411 });
3412
3413 loop1->MakeWatcher("/test", [&](const TestMessage &) {
3414 CheckNotRealtime();
3415 this->Exit();
3416 });
3417
3418 Run();
3419}
3420
3421// Tests that a realtime event loop watcher is marked realtime.
3422TEST_P(AbstractEventLoopTest, RealtimeEventLoopWatcher) {
3423 auto loop1 = MakePrimary();
3424 auto loop2 = Make();
3425
3426 loop1->SetRuntimeRealtimePriority(1);
3427
3428 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
3429
3430 loop1->OnRun([&]() {
3431 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3432 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07003433 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003434 });
3435
3436 loop1->MakeWatcher("/test", [&](const TestMessage &) {
3437 CheckRealtime();
3438 this->Exit();
3439 });
3440
3441 Run();
3442}
3443
Austin Schuha9012be2021-07-21 15:19:11 -07003444// Tests that event loop's context's monotonic time is set to a value on OnRun.
3445TEST_P(AbstractEventLoopTest, SetContextOnRun) {
3446 auto loop = MakePrimary();
3447
Austin Schuh0debde12022-08-17 16:25:17 -07003448 EXPECT_EQ(loop->context().monotonic_event_time, monotonic_clock::min_time);
3449 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07003450 EXPECT_EQ(loop->context().monotonic_remote_transmit_time,
3451 monotonic_clock::min_time);
Austin Schuh0debde12022-08-17 16:25:17 -07003452 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3453 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3454 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3455 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
3456 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
3457 EXPECT_EQ(loop->context().size, 0u);
3458 EXPECT_EQ(loop->context().data, nullptr);
3459 EXPECT_EQ(loop->context().buffer_index, -1);
3460
Austin Schuha9012be2021-07-21 15:19:11 -07003461 // We want to check that monotonic event time is before monotonic now
3462 // called inside of callback, but after time point obtained callback.
3463 aos::monotonic_clock::time_point monotonic_event_time_on_run;
3464
3465 loop->OnRun([&]() {
3466 monotonic_event_time_on_run = loop->context().monotonic_event_time;
3467 EXPECT_LE(monotonic_event_time_on_run, loop->monotonic_now());
3468 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07003469 EXPECT_EQ(loop->context().monotonic_remote_transmit_time,
3470 monotonic_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07003471 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3472 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3473 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3474 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
Austin Schuh0debde12022-08-17 16:25:17 -07003475 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
Austin Schuha9012be2021-07-21 15:19:11 -07003476 EXPECT_EQ(loop->context().size, 0u);
3477 EXPECT_EQ(loop->context().data, nullptr);
3478 EXPECT_EQ(loop->context().buffer_index, -1);
3479 });
3480
3481 EndEventLoop(loop.get(), ::std::chrono::milliseconds(200));
3482
3483 const aos::monotonic_clock::time_point before_run_time =
3484 loop->monotonic_now();
3485 Run();
3486 EXPECT_GE(monotonic_event_time_on_run, before_run_time);
Austin Schuh0debde12022-08-17 16:25:17 -07003487
3488 EXPECT_EQ(loop->context().monotonic_event_time, monotonic_clock::min_time);
3489 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07003490 EXPECT_EQ(loop->context().monotonic_remote_transmit_time,
3491 monotonic_clock::min_time);
Austin Schuh0debde12022-08-17 16:25:17 -07003492 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3493 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3494 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3495 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
3496 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
3497 EXPECT_EQ(loop->context().size, 0u);
3498 EXPECT_EQ(loop->context().data, nullptr);
3499 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuha9012be2021-07-21 15:19:11 -07003500}
3501
Austin Schuh217a9782019-12-21 23:02:50 -08003502// Tests that watchers fail when created on the wrong node.
3503TEST_P(AbstractEventLoopDeathTest, NodeWatcher) {
3504 EnableNodes("them");
3505
3506 auto loop1 = Make();
3507 auto loop2 = Make();
3508 EXPECT_DEATH({ loop1->MakeWatcher("/test", [](const TestMessage &) {}); },
3509 "node");
3510 EXPECT_DEATH(
3511 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08003512 loop2->MakeRawWatcher(
3513 configuration::GetChannel(configuration(), "/test",
3514 "aos.TestMessage", "", nullptr),
3515 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08003516 },
3517 "node");
Brian Silverman454bc112020-03-05 14:21:25 -08003518 EXPECT_DEATH({ loop1->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
3519 "node");
3520 EXPECT_DEATH(
3521 {
3522 loop2->MakeRawNoArgWatcher(
3523 configuration::GetChannel(configuration(), "/test",
3524 "aos.TestMessage", "", nullptr),
3525 [](const Context &) {});
3526 },
3527 "node");
Austin Schuh217a9782019-12-21 23:02:50 -08003528}
3529
3530// Tests that fetchers fail when created on the wrong node.
3531TEST_P(AbstractEventLoopDeathTest, NodeFetcher) {
3532 EnableNodes("them");
3533 auto loop1 = Make();
3534
3535 EXPECT_DEATH({ auto fetcher = loop1->MakeFetcher<TestMessage>("/test"); },
3536 "node");
3537 EXPECT_DEATH(
3538 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08003539 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
3540 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08003541 },
3542 "node");
3543}
3544
3545// Tests that senders fail when created on the wrong node.
3546TEST_P(AbstractEventLoopDeathTest, NodeSender) {
3547 EnableNodes("them");
3548 auto loop1 = Make();
3549
3550 EXPECT_DEATH(
3551 {
3552 aos::Sender<TestMessage> sender =
3553 loop1->MakeSender<TestMessage>("/test");
3554 },
3555 "node");
3556
3557 // Note: Creating raw senders is always supported. Right now, this lets us
3558 // use them to create message_gateway.
3559}
3560
Brian Silverman341b57e2020-06-23 16:23:18 -07003561// Tests creating multiple Builders from a single Sender at the same time.
3562TEST_P(AbstractEventLoopDeathTest, MultipleBuilders) {
3563 auto loop1 = Make();
3564 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
3565
3566 { auto builder = sender.MakeBuilder(); }
3567 {
3568 auto builder = sender.MakeBuilder();
3569 builder.MakeBuilder<TestMessage>().Finish();
3570 }
3571 {
3572 // Creating this after the first one was destroyed should be fine.
3573 auto builder = sender.MakeBuilder();
3574 builder.MakeBuilder<TestMessage>().Finish();
3575 // But not a second one.
3576 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
James Kuszmaulb1c11052023-11-06 13:20:53 -08003577 "May not have multiple active allocators");
Brian Silverman341b57e2020-06-23 16:23:18 -07003578 }
3579
3580 FlatbufferDetachedBuffer<TestMessage> detached =
3581 flatbuffers::DetachedBuffer();
3582 {
3583 auto builder = sender.MakeBuilder();
3584 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
3585 }
3586 {
3587 // This is the second one, after the detached one, so it should fail.
3588 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
James Kuszmaulb1c11052023-11-06 13:20:53 -08003589 "May not have multiple active allocators");
Brian Silverman341b57e2020-06-23 16:23:18 -07003590 }
3591
3592 // Clear the detached one, and then we should be able to create another.
3593 detached = flatbuffers::DetachedBuffer();
3594 {
3595 auto builder = sender.MakeBuilder();
3596 builder.MakeBuilder<TestMessage>().Finish();
3597 }
3598
3599 // And then detach another one.
3600 {
3601 auto builder = sender.MakeBuilder();
3602 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
3603 }
3604}
3605
3606// Tests sending a buffer detached from a different builder.
3607TEST_P(AbstractEventLoopDeathTest, WrongDetachedBuffer) {
3608 auto loop1 = Make();
3609 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
3610 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
3611
3612 auto builder = sender1.MakeBuilder();
3613 FlatbufferDetachedBuffer<TestMessage> detached =
3614 builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
milind1f1dca32021-07-03 13:50:07 -07003615 EXPECT_DEATH(sender2.CheckOk(sender2.SendDetached(std::move(detached))),
Brian Silverman341b57e2020-06-23 16:23:18 -07003616 "May only send the buffer detached from this Sender");
3617}
3618
James Kuszmaul762e8692023-07-31 14:57:53 -07003619// Tests that senders fail when created on the wrong node.
3620TEST_P(AbstractEventLoopDeathTest, SetVersionWhileRunning) {
3621 auto loop1 = MakePrimary();
3622
3623 loop1->OnRun([&loop1, this]() {
3624 EXPECT_DEATH({ loop1->SetVersionString("abcdef"); },
3625 "timing report while running");
3626 Exit();
3627 });
3628
3629 Run();
3630}
3631
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003632int TestChannelFrequency(EventLoop *event_loop) {
3633 return event_loop->GetChannel<TestMessage>("/test")->frequency();
3634}
3635
3636int TestChannelQueueSize(EventLoop *event_loop) {
Austin Schuhfff9c3a2023-06-16 18:48:23 -07003637 return configuration::QueueSize(event_loop->configuration(),
3638 event_loop->GetChannel<TestMessage>("/test"));
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003639}
3640
3641RawSender::Error SendTestMessage(aos::Sender<TestMessage> &sender) {
3642 aos::Sender<TestMessage>::Builder builder = sender.MakeBuilder();
3643 TestMessage::Builder test_message_builder =
3644 builder.MakeBuilder<TestMessage>();
3645 test_message_builder.add_value(0);
3646 return builder.Send(test_message_builder.Finish());
3647}
3648
3649// Test that sending messages too fast returns
3650// RawSender::Error::kMessagesSentTooFast.
3651TEST_P(AbstractEventLoopTest, SendingMessagesTooFast) {
3652 auto event_loop = MakePrimary();
Austin Schuh63756be2024-02-05 19:51:20 -08003653 event_loop->SetRuntimeRealtimePriority(5);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003654
3655 auto sender = event_loop->MakeSender<TestMessage>("/test");
3656
3657 // Send one message in the beginning, then wait until the
3658 // channel_storage_duration is almost done and start sending messages rapidly,
3659 // having some come in the next chanel_storage_duration. The queue_size is
3660 // 1600, so the 1601st message will be the last valid one (the initial message
3661 // having being sent more than a channel_storage_duration ago), and trying to
3662 // send the 1602nd message should return
3663 // RawSender::Error::kMessagesSentTooFast.
3664 EXPECT_EQ(SendTestMessage(sender), RawSender::Error::kOk);
3665 int msgs_sent = 1;
3666 const int queue_size = TestChannelQueueSize(event_loop.get());
3667
Austin Schuh63756be2024-02-05 19:51:20 -08003668 const int messages_per_ms = 2;
3669 const auto kRepeatOffset = std::chrono::milliseconds(10);
3670 const auto base_offset =
3671 configuration::ChannelStorageDuration(event_loop->configuration(),
3672 sender.channel()) -
3673 (std::chrono::milliseconds(1) * (queue_size / 2) / messages_per_ms);
3674
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003675 const auto timer = event_loop->AddTimer([&]() {
Austin Schuh63756be2024-02-05 19:51:20 -08003676 // Send in bursts to reduce scheduler load to make the test more
3677 // reproducible.
3678 for (int i = 0; i < messages_per_ms * kRepeatOffset.count(); ++i) {
3679 const bool done = (msgs_sent == queue_size + 1);
3680 ASSERT_EQ(SendTestMessage(sender),
3681 done ? RawSender::Error::kMessagesSentTooFast
3682 : RawSender::Error::kOk);
3683 msgs_sent++;
3684 if (done) {
3685 Exit();
3686 return;
3687 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003688 }
3689 });
3690
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003691 event_loop->OnRun([&event_loop, &timer, &base_offset, &kRepeatOffset]() {
Philipp Schradera6712522023-07-05 20:25:11 -07003692 timer->Schedule(event_loop->monotonic_now() + base_offset, kRepeatOffset);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003693 });
3694
3695 Run();
3696}
3697
3698// Tests that we are able to send messages successfully after sending messages
3699// too fast and waiting while continuously attempting to send messages.
3700// Also tests that SendFailureCounter is working correctly in this
3701// situation
3702TEST_P(AbstractEventLoopTest, SendingAfterSendingTooFast) {
3703 auto event_loop = MakePrimary();
Austin Schuh63756be2024-02-05 19:51:20 -08003704 event_loop->SetRuntimeRealtimePriority(5);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003705
3706 auto sender = event_loop->MakeSender<TestMessage>("/test");
3707
Austin Schuh0e96d372023-05-08 10:10:21 -07003708 // We are sending bunches of messages at 100 Hz, so we will be sending too
3709 // fast after queue_size (800) ms. After this, keep sending messages, and
3710 // exactly a channel storage duration (2s) after we send the first message we
3711 // should be able to successfully send a message.
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003712
Austin Schuh0e96d372023-05-08 10:10:21 -07003713 const std::chrono::milliseconds kInterval = std::chrono::milliseconds(10);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003714 const monotonic_clock::duration channel_storage_duration =
Austin Schuhfff9c3a2023-06-16 18:48:23 -07003715 configuration::ChannelStorageDuration(event_loop->configuration(),
3716 sender.channel());
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003717 const int queue_size = TestChannelQueueSize(event_loop.get());
3718
3719 int msgs_sent = 0;
3720 SendFailureCounter counter;
3721 auto start = monotonic_clock::min_time;
3722
3723 event_loop->AddPhasedLoop(
Austin Schuh0e96d372023-05-08 10:10:21 -07003724 [&](int elapsed_cycles) {
3725 // The queue is setup for 800 messages/sec. We want to fill that up at
3726 // a rate of 2000 messages/sec so we make sure we fill it up.
3727 for (int i = 0; i < 2 * kInterval.count() * elapsed_cycles; ++i) {
3728 const auto actual_err = SendTestMessage(sender);
3729 const bool done_waiting = (start != monotonic_clock::min_time &&
3730 sender.monotonic_sent_time() >=
3731 (start + channel_storage_duration));
3732 const auto expected_err =
3733 (msgs_sent < queue_size || done_waiting
3734 ? RawSender::Error::kOk
3735 : RawSender::Error::kMessagesSentTooFast);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003736
Austin Schuh0e96d372023-05-08 10:10:21 -07003737 if (start == monotonic_clock::min_time) {
3738 start = sender.monotonic_sent_time();
3739 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003740
Austin Schuh0e96d372023-05-08 10:10:21 -07003741 ASSERT_EQ(actual_err, expected_err);
3742 counter.Count(actual_err);
3743 msgs_sent++;
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003744
Austin Schuh0e96d372023-05-08 10:10:21 -07003745 EXPECT_EQ(counter.failures(),
3746 msgs_sent <= queue_size
3747 ? 0
3748 : (msgs_sent - queue_size) -
3749 (actual_err == RawSender::Error::kOk ? 1 : 0));
3750 EXPECT_EQ(counter.just_failed(), actual_err != RawSender::Error::kOk);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003751
Austin Schuh0e96d372023-05-08 10:10:21 -07003752 if (done_waiting) {
3753 Exit();
3754 return;
3755 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003756 }
3757 },
3758 kInterval);
3759 Run();
3760}
3761
3762// Tests that RawSender::Error::kMessagesSentTooFast is returned
3763// when messages are sent too fast from senders in different loops
3764TEST_P(AbstractEventLoopTest, SendingTooFastWithMultipleLoops) {
3765 auto loop1 = MakePrimary();
3766 auto loop2 = Make();
3767
3768 auto sender1 = loop1->MakeSender<TestMessage>("/test");
3769 auto sender2 = loop2->MakeSender<TestMessage>("/test");
3770
3771 // Send queue_size messages split between the senders.
3772 const int queue_size = TestChannelQueueSize(loop1.get());
3773 for (int i = 0; i < queue_size / 2; i++) {
3774 ASSERT_EQ(SendTestMessage(sender1), RawSender::Error::kOk);
3775 ASSERT_EQ(SendTestMessage(sender2), RawSender::Error::kOk);
3776 }
3777
3778 // Since queue_size messages have been sent, this should return an error
3779 EXPECT_EQ(SendTestMessage(sender2), RawSender::Error::kMessagesSentTooFast);
3780}
3781
Austin Schuhdda6db72023-06-21 17:02:34 -07003782// Tests that a longer storage durations store more messages.
3783TEST_P(AbstractEventLoopTest, SendingTooFastWithLongDuration) {
3784 auto loop1 = MakePrimary();
3785
3786 auto sender1 = loop1->MakeSender<TestMessage>("/test3");
3787
3788 // Send queue_size messages split between the senders.
3789 const int queue_size =
3790 configuration::QueueSize(loop1->configuration(), sender1.channel());
3791 EXPECT_EQ(queue_size, 100 * 10);
3792 for (int i = 0; i < queue_size; i++) {
3793 ASSERT_EQ(SendTestMessage(sender1), RawSender::Error::kOk);
3794 }
3795
3796 // Since queue_size messages have been sent, and little time has elapsed,
3797 // this should return an error.
3798 EXPECT_EQ(SendTestMessage(sender1), RawSender::Error::kMessagesSentTooFast);
3799}
3800
James Kuszmaul9f998082024-05-23 15:37:35 -07003801// Tests that we can exit with a default constructor and that Run() will
3802// indicate a successful exit.
3803TEST_P(AbstractEventLoopTest, ExitHandleExitSuccessful) {
3804 auto loop = MakePrimary();
3805 std::unique_ptr<ExitHandle> exit_handle = MakeExitHandle();
3806 bool happened = false;
3807
3808 loop->OnRun([&exit_handle, &happened]() {
3809 happened = true;
3810 exit_handle->Exit();
3811 });
3812
3813 EXPECT_TRUE(Run().has_value());
3814 EXPECT_TRUE(happened);
3815}
3816
3817// Tests that we can exit with an error Status and have that returned via the
3818// Run() method.
3819TEST_P(AbstractEventLoopTest, ExitHandleExitFailure) {
3820 auto loop = MakePrimary();
3821 std::unique_ptr<ExitHandle> exit_handle = MakeExitHandle();
3822 bool happened = false;
3823
3824 loop->OnRun([&exit_handle, &happened]() {
3825 happened = true;
3826 exit_handle->Exit(Error::MakeUnexpectedError("Hello, World!"));
3827 // The second Exit() should not affect the final return value.
3828 exit_handle->Exit(Error::MakeUnexpectedError("Hello, World! 2"));
3829 });
3830 const int line = __LINE__ - 4;
3831
3832 Result<void> status = Run();
3833
3834 EXPECT_TRUE(happened);
3835 EXPECT_FALSE(status.has_value());
3836 EXPECT_EQ(std::string("Hello, World!"), status.error().message());
3837 ASSERT_TRUE(status.error().source_location().has_value());
3838 EXPECT_EQ(std::string("event_loop_param_test.cc"),
3839 std::filesystem::path(status.error().source_location()->file_name())
3840 .filename());
3841 EXPECT_EQ(line, status.error().source_location()->line());
3842}
3843
Stephan Pleinesf63bde82024-01-13 15:59:33 -08003844} // namespace aos::testing