blob: d2d3aa9ab98165247f8e1949c6d34a4a951423df [file] [log] [blame]
Alex Perrycb7da4b2019-08-28 19:35:56 -07001#include "aos/events/event_loop_param_test.h"
Parker Schuhe4a70d62017-12-27 20:10:20 -08002
Austin Schuh52d325c2019-06-23 18:59:06 -07003#include <chrono>
Brian Silverman4f4e0612020-08-12 19:54:41 -07004#include <unordered_map>
5#include <unordered_set>
Austin Schuh52d325c2019-06-23 18:59:06 -07006
Philipp Schrader790cb542023-07-05 21:06:52 -07007#include "glog/logging.h"
8#include "gmock/gmock.h"
9#include "gtest/gtest.h"
10
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -070011#include "aos/events/test_message_generated.h"
James Kuszmaulb1c11052023-11-06 13:20:53 -080012#include "aos/events/test_message_static.h"
Austin Schuh54cf95f2019-11-29 13:14:18 -080013#include "aos/flatbuffer_merge.h"
Austin Schuhad9e5eb2021-11-19 20:33:55 -080014#include "aos/logging/log_message_generated.h"
15#include "aos/logging/logging.h"
Austin Schuhcc6070c2020-10-10 20:25:56 -070016#include "aos/realtime.h"
Austin Schuh9fe68f72019-08-10 19:32:03 -070017
Stephan Pleinesf63bde82024-01-13 15:59:33 -080018namespace aos::testing {
Austin Schuh52d325c2019-06-23 18:59:06 -070019namespace {
20namespace chrono = ::std::chrono;
21} // namespace
Parker Schuhe4a70d62017-12-27 20:10:20 -080022
Brian Silverman4f4e0612020-08-12 19:54:41 -070023::std::unique_ptr<EventLoop> AbstractEventLoopTest::Make(
24 std::string_view name) {
25 std::string name_copy(name);
26 if (name == "") {
27 name_copy = "loop";
28 name_copy += std::to_string(event_loop_count_);
29 }
30 ++event_loop_count_;
Austin Schuh6bae8252021-02-07 22:01:49 -080031 auto result = factory_->Make(name_copy);
32 if (do_timing_reports() == DoTimingReports::kNo) {
33 result->SkipTimingReport();
34 }
35 return result;
Brian Silverman4f4e0612020-08-12 19:54:41 -070036}
37
38void AbstractEventLoopTest::VerifyBuffers(
39 int number_buffers,
40 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>> fetchers,
41 std::vector<std::reference_wrapper<const Sender<TestMessage>>> senders) {
42 // The buffers which are in a sender.
43 std::unordered_set<int> in_sender;
44 for (const Sender<TestMessage> &sender : senders) {
45 const int this_buffer = sender.buffer_index();
46 CHECK_GE(this_buffer, 0);
47 CHECK_LT(this_buffer, number_buffers);
48 CHECK(in_sender.insert(this_buffer).second) << ": " << this_buffer;
49 }
50
51 if (read_method() != ReadMethod::PIN) {
52 // If we're not using PIN, we can't really verify anything about what
53 // buffers the fetchers have.
54 return;
55 }
56
57 // Mapping from TestMessage::value to buffer index.
58 std::unordered_map<int, int> fetcher_values;
59 for (const Fetcher<TestMessage> &fetcher : fetchers) {
60 if (!fetcher.get()) {
61 continue;
62 }
63 const int this_buffer = fetcher.context().buffer_index;
64 CHECK_GE(this_buffer, 0);
65 CHECK_LT(this_buffer, number_buffers);
66 CHECK(in_sender.count(this_buffer) == 0) << ": " << this_buffer;
67 const auto insert_result = fetcher_values.insert(
68 std::make_pair(fetcher.get()->value(), this_buffer));
69 if (!insert_result.second) {
70 CHECK_EQ(this_buffer, insert_result.first->second);
71 }
72 }
73}
74
Austin Schuh6b6dfa52019-06-12 20:16:20 -070075// Tests that watcher can receive messages from a sender.
Parker Schuhe4a70d62017-12-27 20:10:20 -080076// Also tests that OnRun() works.
77TEST_P(AbstractEventLoopTest, Basic) {
78 auto loop1 = Make();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070079 auto loop2 = MakePrimary();
80
Alex Perrycb7da4b2019-08-28 19:35:56 -070081 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
Austin Schuh6b6dfa52019-06-12 20:16:20 -070082
83 bool happened = false;
84
85 loop2->OnRun([&]() {
86 happened = true;
87
Alex Perrycb7da4b2019-08-28 19:35:56 -070088 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
89 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
90 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -070091 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -070092 });
93
94 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070095 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -070096 this->Exit();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070097 });
98
99 EXPECT_FALSE(happened);
100 Run();
101 EXPECT_TRUE(happened);
102}
103
James Kuszmaulb1c11052023-11-06 13:20:53 -0800104// Tests that watcher can receive messages from a static sender.
105// This confirms that the "static" flatbuffer API works with the EventLoop
106// senders.
107TEST_P(AbstractEventLoopTest, BasicStatic) {
108 auto loop1 = Make();
109 auto loop2 = MakePrimary();
110
111 aos::Sender<TestMessageStatic> sender =
112 loop1->MakeSender<TestMessageStatic>("/test");
113
114 bool happened = false;
115
116 loop2->OnRun([&]() {
117 happened = true;
118
119 aos::Sender<TestMessageStatic>::StaticBuilder msg =
120 sender.MakeStaticBuilder();
James Kuszmauldde65632023-12-07 16:12:26 -0800121 msg->set_value(200);
James Kuszmaulb1c11052023-11-06 13:20:53 -0800122 CHECK(msg.builder()->Verify());
123 msg.CheckOk(msg.Send());
124 });
125
126 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
127 EXPECT_EQ(message.value(), 200);
128 this->Exit();
129 });
130
131 EXPECT_FALSE(happened);
132 Run();
133 EXPECT_TRUE(happened);
134}
135
James Kuszmauld4b4f1d2024-03-13 15:57:35 -0700136// Tests that a static sender's Builder object can be moved safely.
137TEST_P(AbstractEventLoopTest, StaticBuilderMoveConstructor) {
138 auto loop1 = MakePrimary();
139
140 aos::Sender<TestMessageStatic> sender =
141 loop1->MakeSender<TestMessageStatic>("/test");
142 aos::Fetcher<TestMessage> fetcher = loop1->MakeFetcher<TestMessage>("/test");
143 std::optional<aos::Sender<TestMessageStatic>::StaticBuilder> moved_to_builder;
144 {
145 aos::Sender<TestMessageStatic>::StaticBuilder moved_from_builder =
146 sender.MakeStaticBuilder();
147 moved_to_builder.emplace(std::move(moved_from_builder));
148 }
149
150 loop1->OnRun([this, &moved_to_builder]() {
151 moved_to_builder.value()->set_value(200);
152 CHECK(moved_to_builder.value().builder()->Verify());
153 moved_to_builder.value().CheckOk(moved_to_builder.value().Send());
154 this->Exit();
155 });
156
157 ASSERT_FALSE(fetcher.Fetch());
158 Run();
159 ASSERT_TRUE(fetcher.Fetch());
160 EXPECT_EQ(200, fetcher->value());
161}
162
Brian Silverman341b57e2020-06-23 16:23:18 -0700163// Tests that watcher can receive messages from a sender, sent via SendDetached.
164TEST_P(AbstractEventLoopTest, BasicSendDetached) {
165 auto loop1 = Make();
166 auto loop2 = MakePrimary();
167
168 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
169
170 FlatbufferDetachedBuffer<TestMessage> detached =
171 flatbuffers::DetachedBuffer();
172 {
173 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
174 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
175 builder.add_value(100);
176 detached = msg.Detach(builder.Finish());
177 }
178 detached = flatbuffers::DetachedBuffer();
179 {
180 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
181 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
182 builder.add_value(200);
183 detached = msg.Detach(builder.Finish());
184 }
milind1f1dca32021-07-03 13:50:07 -0700185 sender.CheckOk(sender.SendDetached(std::move(detached)));
Brian Silverman341b57e2020-06-23 16:23:18 -0700186
187 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
188 ASSERT_TRUE(fetcher.Fetch());
189 EXPECT_EQ(fetcher->value(), 200);
190}
191
Alexei Strots7cb6e0c2024-02-19 21:24:21 -0800192// Tests that fetcher can receive messages from a sender, sent via SendJson.
193TEST_P(AbstractEventLoopTest, BasicSendJson) {
194 auto loop1 = Make();
195 auto loop2 = MakePrimary();
196
197 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
198 sender.CheckOk(sender.SendJson(R"json({"value":201})json"));
199
200 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
201 ASSERT_TRUE(fetcher.Fetch());
202 EXPECT_EQ(fetcher->value(), 201);
203}
204
205// Tests that invalid JSON isn't sent.
206TEST_P(AbstractEventLoopDeathTest, InvalidSendJson) {
207 auto loop1 = Make();
208 auto loop2 = MakePrimary();
209
210 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
211 EXPECT_DEATH({ sender.CheckOk(sender.SendJson(R"json({"val)json")); },
212 "Invalid JSON");
213}
214
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800215// Verifies that a no-arg watcher will not have a data pointer.
216TEST_P(AbstractEventLoopTest, NoArgNoData) {
217 auto loop1 = Make();
218 auto loop2 = MakePrimary();
219
220 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
221
222 bool happened = false;
223
224 loop2->OnRun([&]() {
225 happened = true;
226
227 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
228 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -0700229 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800230 });
231
232 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
233 EXPECT_GT(loop2->context().size, 0u);
234 EXPECT_EQ(nullptr, loop2->context().data);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700235 EXPECT_EQ(-1, loop2->context().buffer_index);
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800236 this->Exit();
237 });
238
239 EXPECT_FALSE(happened);
240 Run();
241 EXPECT_TRUE(happened);
242}
243
Brian Silverman454bc112020-03-05 14:21:25 -0800244// Tests that no-arg watcher can receive messages from a sender.
245// Also tests that OnRun() works.
246TEST_P(AbstractEventLoopTest, BasicNoArg) {
247 auto loop1 = Make();
248 auto loop2 = MakePrimary();
249
250 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
251
252 bool happened = false;
253
254 loop2->OnRun([&]() {
255 happened = true;
256
257 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
258 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
259 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700260 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -0800261 });
262
263 aos::Fetcher<TestMessage> fetcher = loop2->MakeFetcher<TestMessage>("/test");
264 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
265 ASSERT_TRUE(fetcher.Fetch());
266 EXPECT_EQ(fetcher->value(), 200);
267 this->Exit();
268 });
269
270 EXPECT_FALSE(happened);
271 Run();
272 EXPECT_TRUE(happened);
273}
274
275// Tests that a watcher can be created with an std::function.
276TEST_P(AbstractEventLoopTest, BasicFunction) {
277 auto loop1 = Make();
278 auto loop2 = MakePrimary();
279
280 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
281
282 bool happened = false;
283
284 loop2->OnRun([&]() {
285 happened = true;
286
287 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
288 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
289 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700290 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -0800291 });
292
293 loop2->MakeWatcher("/test", std::function<void(const TestMessage &)>(
294 [&](const TestMessage &message) {
295 EXPECT_EQ(message.value(), 200);
296 this->Exit();
297 }));
298
299 EXPECT_FALSE(happened);
300 Run();
301 EXPECT_TRUE(happened);
302}
303
Brian Silverman0fc69932020-01-24 21:54:02 -0800304// Tests that watcher can receive messages from two senders.
305// Also tests that OnRun() works.
306TEST_P(AbstractEventLoopTest, BasicTwoSenders) {
307 auto loop1 = Make();
308 auto loop2 = MakePrimary();
309
310 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
311 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
312
313 bool happened = false;
314
315 loop2->OnRun([&]() {
316 happened = true;
317
318 {
319 aos::Sender<TestMessage>::Builder msg = sender1.MakeBuilder();
320 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
321 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700322 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman0fc69932020-01-24 21:54:02 -0800323 }
324 {
325 aos::Sender<TestMessage>::Builder msg = sender2.MakeBuilder();
326 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
327 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700328 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman0fc69932020-01-24 21:54:02 -0800329 }
330 });
331
332 int messages_received = 0;
333 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
334 EXPECT_EQ(message.value(), 200);
335 this->Exit();
336 ++messages_received;
337 });
338
339 EXPECT_FALSE(happened);
340 Run();
341 EXPECT_TRUE(happened);
342 EXPECT_EQ(messages_received, 2);
343}
344
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700345// Tests that a fetcher can fetch from a sender.
346// Also tests that OnRun() works.
347TEST_P(AbstractEventLoopTest, FetchWithoutRun) {
348 auto loop1 = Make();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800349 auto loop2 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -0700350 auto loop3 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800351
352 auto sender = loop1->MakeSender<TestMessage>("/test");
353
354 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
355
Austin Schuhbbce72d2019-05-26 15:11:46 -0700356 EXPECT_FALSE(fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -0800357 EXPECT_EQ(fetcher.get(), nullptr);
358
Austin Schuhad154822019-12-27 15:45:13 -0800359 EXPECT_EQ(fetcher.context().monotonic_event_time, monotonic_clock::min_time);
360 EXPECT_EQ(fetcher.context().monotonic_remote_time, monotonic_clock::min_time);
361 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
362 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -0700363 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
Austin Schuh39788ff2019-12-01 18:22:57 -0800364 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
365 EXPECT_EQ(fetcher.context().size, 0u);
366 EXPECT_EQ(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700367 EXPECT_EQ(fetcher.context().buffer_index, -1);
Austin Schuhbbce72d2019-05-26 15:11:46 -0700368
Alex Perrycb7da4b2019-08-28 19:35:56 -0700369 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
370 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
371 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700372 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700373
374 EXPECT_TRUE(fetcher.Fetch());
375 ASSERT_FALSE(fetcher.get() == nullptr);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700376 EXPECT_EQ(fetcher.get()->value(), 200);
Austin Schuh39788ff2019-12-01 18:22:57 -0800377
378 const chrono::milliseconds kEpsilon(100);
379
Austin Schuhad154822019-12-27 15:45:13 -0800380 const aos::monotonic_clock::time_point monotonic_now = loop2->monotonic_now();
381 const aos::realtime_clock::time_point realtime_now = loop2->realtime_now();
382 EXPECT_EQ(fetcher.context().monotonic_event_time,
383 fetcher.context().monotonic_remote_time);
384 EXPECT_EQ(fetcher.context().realtime_event_time,
385 fetcher.context().realtime_remote_time);
386
387 EXPECT_GE(fetcher.context().monotonic_event_time, monotonic_now - kEpsilon);
388 EXPECT_LE(fetcher.context().monotonic_event_time, monotonic_now + kEpsilon);
389 EXPECT_GE(fetcher.context().realtime_event_time, realtime_now - kEpsilon);
390 EXPECT_LE(fetcher.context().realtime_event_time, realtime_now + kEpsilon);
Austin Schuha9012be2021-07-21 15:19:11 -0700391 EXPECT_EQ(fetcher.context().source_boot_uuid, loop2->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -0800392 EXPECT_EQ(fetcher.context().queue_index, 0x0u);
393 EXPECT_EQ(fetcher.context().size, 20u);
394 EXPECT_NE(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700395 if (read_method() == ReadMethod::PIN) {
396 EXPECT_GE(fetcher.context().buffer_index, 0);
397 EXPECT_LT(fetcher.context().buffer_index,
398 loop2->NumberBuffers(fetcher.channel()));
399 } else {
400 EXPECT_EQ(fetcher.context().buffer_index, -1);
401 }
Parker Schuhe4a70d62017-12-27 20:10:20 -0800402}
403
Austin Schuh98ed26f2023-07-19 14:12:28 -0700404std::function<bool(const Context &)> MakeShouldFetch(
405 bool should_fetch, size_t *called_count = nullptr) {
406 return [should_fetch, called_count](const Context &) {
407 if (called_count != nullptr) {
408 (*called_count)++;
409 }
410 return should_fetch;
411 };
412}
413
414// Tests that a fetcher using FetchIf can fetch from a sender.
415TEST_P(AbstractEventLoopTest, FetchIfWithoutRun) {
416 auto loop1 = Make();
417 auto loop2 = Make();
418 auto loop3 = MakePrimary();
419
420 auto sender = loop1->MakeSender<TestMessage>("/test");
421
422 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
423
424 for (const bool should_fetch : {true, false}) {
425 EXPECT_FALSE(fetcher.FetchIf(MakeShouldFetch(should_fetch)));
426 EXPECT_EQ(fetcher.get(), nullptr);
427
428 EXPECT_EQ(fetcher.context().monotonic_event_time,
429 monotonic_clock::min_time);
430 EXPECT_EQ(fetcher.context().monotonic_remote_time,
431 monotonic_clock::min_time);
432 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
433 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
434 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
435 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
436 EXPECT_EQ(fetcher.context().size, 0u);
437 EXPECT_EQ(fetcher.context().data, nullptr);
438 EXPECT_EQ(fetcher.context().buffer_index, -1);
439 }
440
441 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
442 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
443 builder.add_value(200);
444 msg.CheckOk(msg.Send(builder.Finish()));
445
446 // Make sure failing to fetch won't affect anything.
447 EXPECT_FALSE(fetcher.FetchIf(MakeShouldFetch(false)));
448 EXPECT_EQ(fetcher.get(), nullptr);
449
450 EXPECT_EQ(fetcher.context().monotonic_event_time, monotonic_clock::min_time);
451 EXPECT_EQ(fetcher.context().monotonic_remote_time, monotonic_clock::min_time);
452 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
453 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
454 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
455 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
456 EXPECT_EQ(fetcher.context().size, 0u);
457 EXPECT_EQ(fetcher.context().data, nullptr);
458 EXPECT_EQ(fetcher.context().buffer_index, -1);
459
460 // And now confirm we succeed and everything gets set right.
461 EXPECT_TRUE(fetcher.FetchIf(MakeShouldFetch(true)));
462 ASSERT_FALSE(fetcher.get() == nullptr);
463 EXPECT_EQ(fetcher.get()->value(), 200);
464
465 const chrono::milliseconds kEpsilon(100);
466
467 const aos::monotonic_clock::time_point monotonic_now = loop2->monotonic_now();
468 const aos::realtime_clock::time_point realtime_now = loop2->realtime_now();
469 EXPECT_EQ(fetcher.context().monotonic_event_time,
470 fetcher.context().monotonic_remote_time);
471 EXPECT_EQ(fetcher.context().realtime_event_time,
472 fetcher.context().realtime_remote_time);
473
474 EXPECT_GE(fetcher.context().monotonic_event_time, monotonic_now - kEpsilon);
475 EXPECT_LE(fetcher.context().monotonic_event_time, monotonic_now + kEpsilon);
476 EXPECT_GE(fetcher.context().realtime_event_time, realtime_now - kEpsilon);
477 EXPECT_LE(fetcher.context().realtime_event_time, realtime_now + kEpsilon);
478 EXPECT_EQ(fetcher.context().source_boot_uuid, loop2->boot_uuid());
479 EXPECT_EQ(fetcher.context().queue_index, 0x0u);
480 EXPECT_EQ(fetcher.context().size, 20u);
481 EXPECT_NE(fetcher.context().data, nullptr);
482 if (read_method() == ReadMethod::PIN) {
483 EXPECT_GE(fetcher.context().buffer_index, 0);
484 EXPECT_LT(fetcher.context().buffer_index,
485 loop2->NumberBuffers(fetcher.channel()));
486 } else {
487 EXPECT_EQ(fetcher.context().buffer_index, -1);
488 }
489}
490
Austin Schuh3578a2e2019-05-25 18:17:59 -0700491// Tests that watcher will receive all messages sent if they are sent after
492// initialization and before running.
493TEST_P(AbstractEventLoopTest, DoubleSendAtStartup) {
494 auto loop1 = Make();
495 auto loop2 = MakePrimary();
496
497 auto sender = loop1->MakeSender<TestMessage>("/test");
498
499 ::std::vector<int> values;
500
501 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700502 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700503 if (values.size() == 2) {
Austin Schuh9fe68f72019-08-10 19:32:03 -0700504 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -0700505 }
506 });
507
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700508 // Before Run, should be ignored.
Austin Schuh3578a2e2019-05-25 18:17:59 -0700509 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700510 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
511 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
512 builder.add_value(199);
milind1f1dca32021-07-03 13:50:07 -0700513 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700514 }
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700515
516 loop2->OnRun([&]() {
Austin Schuh98ed26f2023-07-19 14:12:28 -0700517 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700518 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
519 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700520 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700521 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700522 }
523 });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700524
525 Run();
526
527 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
528}
529
530// Tests that watcher will not receive messages sent before the watcher is
531// created.
532TEST_P(AbstractEventLoopTest, DoubleSendAfterStartup) {
533 auto loop1 = Make();
534 auto loop2 = MakePrimary();
535
536 auto sender = loop1->MakeSender<TestMessage>("/test");
537
538 ::std::vector<int> values;
539
Austin Schuh98ed26f2023-07-19 14:12:28 -0700540 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700541 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
542 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700543 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700544 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700545 }
546
547 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700548 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700549 });
550
551 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700552 auto test_timer = loop2->AddTimer([this]() { this->Exit(); });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700553 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700554 test_timer->Schedule(loop2->monotonic_now(),
555 ::std::chrono::milliseconds(100));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700556 });
557
558 Run();
559 EXPECT_EQ(0, values.size());
560}
561
Austin Schuhbbce72d2019-05-26 15:11:46 -0700562// Tests that FetchNext gets all the messages sent after it is constructed.
563TEST_P(AbstractEventLoopTest, FetchNext) {
564 auto loop1 = Make();
565 auto loop2 = MakePrimary();
566
567 auto sender = loop1->MakeSender<TestMessage>("/test");
568 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
569
570 ::std::vector<int> values;
571
Austin Schuh98ed26f2023-07-19 14:12:28 -0700572 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700573 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
574 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700575 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700576 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700577 }
578
579 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700580 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700581 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700582 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700583 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700584 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700585 });
586
587 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700588 test_timer->Schedule(loop2->monotonic_now(),
589 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700590 });
591
592 Run();
593 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
594}
595
596// Tests that FetchNext gets no messages sent before it is constructed.
597TEST_P(AbstractEventLoopTest, FetchNextAfterSend) {
598 auto loop1 = Make();
599 auto loop2 = MakePrimary();
600
601 auto sender = loop1->MakeSender<TestMessage>("/test");
602
603 ::std::vector<int> values;
604
Austin Schuh98ed26f2023-07-19 14:12:28 -0700605 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700606 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
607 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700608 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700609 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700610 }
611
612 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
613
614 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700615 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700616 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700617 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700618 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700619 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700620 });
621
622 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700623 test_timer->Schedule(loop2->monotonic_now(),
624 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700625 });
626
627 Run();
628 EXPECT_THAT(0, values.size());
629}
630
Austin Schuh98ed26f2023-07-19 14:12:28 -0700631// Tests that FetchNextIf gets no messages sent before it is constructed.
632TEST_P(AbstractEventLoopTest, FetchNextIfAfterSend) {
633 auto loop1 = Make();
634 auto loop2 = MakePrimary();
635
636 auto sender = loop1->MakeSender<TestMessage>("/test");
637
638 ::std::vector<int> values;
639
640 for (int i = 200; i < 202; ++i) {
641 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
642 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
643 builder.add_value(i);
644 msg.CheckOk(msg.Send(builder.Finish()));
645 }
646
647 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
648
649 // Add a timer to actually quit.
650 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
651 while (fetcher.FetchNextIf(MakeShouldFetch(true))) {
652 values.push_back(fetcher.get()->value());
653 }
654 this->Exit();
655 });
656
657 loop2->OnRun([&test_timer, &loop2]() {
658 test_timer->Schedule(loop2->monotonic_now(),
659 ::std::chrono::milliseconds(100));
660 });
661
662 Run();
663 EXPECT_EQ(0, values.size());
664}
665
Austin Schuhbbce72d2019-05-26 15:11:46 -0700666// Tests that Fetch returns the last message created before the loop was
667// started.
668TEST_P(AbstractEventLoopTest, FetchDataFromBeforeCreation) {
669 auto loop1 = Make();
670 auto loop2 = MakePrimary();
671
672 auto sender = loop1->MakeSender<TestMessage>("/test");
673
674 ::std::vector<int> values;
675
Austin Schuh98ed26f2023-07-19 14:12:28 -0700676 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700677 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
678 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700679 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700680 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700681 }
682
683 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
684
685 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700686 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700687 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700688 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700689 }
690 // Do it again to make sure we don't double fetch.
691 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700692 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700693 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700694 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700695 });
696
697 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700698 test_timer->Schedule(loop2->monotonic_now(),
699 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700700 });
701
702 Run();
703 EXPECT_THAT(values, ::testing::ElementsAreArray({201}));
704}
705
Austin Schuh98ed26f2023-07-19 14:12:28 -0700706// Tests that FetchIf returns the last message created before the loop was
707// started.
708TEST_P(AbstractEventLoopTest, FetchIfDataFromBeforeCreation) {
709 auto loop1 = Make();
710 auto loop2 = MakePrimary();
711
712 auto sender = loop1->MakeSender<TestMessage>("/test");
713
714 ::std::vector<int> values;
715
716 for (int i = 200; i < 202; ++i) {
717 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
718 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
719 builder.add_value(i);
720 msg.CheckOk(msg.Send(builder.Finish()));
721 }
722
723 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
724
725 // Add a timer to actually quit.
726 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
727 if (fetcher.FetchIf(MakeShouldFetch(true))) {
728 values.push_back(fetcher.get()->value());
729 }
730
731 if (fetcher.FetchIf(MakeShouldFetch(false))) {
732 values.push_back(fetcher.get()->value());
733 }
734 // Do it again to make sure we don't double fetch.
735 if (fetcher.FetchIf(MakeShouldFetch(true))) {
736 values.push_back(fetcher.get()->value());
737 }
738 this->Exit();
739 });
740
741 loop2->OnRun([&test_timer, &loop2]() {
742 test_timer->Schedule(loop2->monotonic_now(),
743 ::std::chrono::milliseconds(100));
744 });
745
746 Run();
747 EXPECT_THAT(values, ::testing::ElementsAreArray({201}));
748}
749
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700750// Tests that timer handler is enabled after setup (even if it is in the past)
751// and is disabled after running
752TEST_P(AbstractEventLoopTest, CheckTimerDisabled) {
753 auto loop = MakePrimary("primary");
754
755 auto timer = loop->AddTimer([this]() {
756 LOG(INFO) << "timer called";
757 Exit();
758 });
759
760 loop->OnRun([&loop, timer]() {
761 EXPECT_TRUE(timer->IsDisabled());
Philipp Schradera6712522023-07-05 20:25:11 -0700762 timer->Schedule(loop->monotonic_now() + chrono::milliseconds(100));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700763 EXPECT_FALSE(timer->IsDisabled());
764 });
765
766 Run();
767 EXPECT_TRUE(timer->IsDisabled());
768}
769
770// Tests that timer handler is enabled after setup (even if it is in the past)
771// and is disabled after running
772TEST_P(AbstractEventLoopTest, CheckTimerRunInPastDisabled) {
773 auto loop = MakePrimary("primary");
774
775 auto timer2 = loop->AddTimer([this]() {
776 LOG(INFO) << "timer called";
777 Exit();
778 });
779
780 auto timer = loop->AddTimer([&loop, timer2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700781 timer2->Schedule(loop->monotonic_now() - chrono::nanoseconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700782 });
783
784 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700785 timer->Schedule(loop->monotonic_now() + chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700786 EXPECT_FALSE(timer->IsDisabled());
787 });
788
789 Run();
790 EXPECT_TRUE(timer2->IsDisabled());
791}
792
793// Tests that timer handler is not disabled even after calling Exit on the event
794// loop within the timer
795TEST_P(AbstractEventLoopTest, CheckTimerRepeatOnCountDisabled) {
796 auto loop = MakePrimary("primary");
797 int counter = 0;
798
799 auto timer = loop->AddTimer([&counter, this]() {
800 LOG(INFO) << "timer called";
801 counter++;
802 if (counter >= 5) {
803 Exit();
804 }
805 });
806
807 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700808 timer->Schedule(loop->monotonic_now() + chrono::seconds(1),
809 chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700810 EXPECT_FALSE(timer->IsDisabled());
811 });
812 Run();
813
814 // Sanity check
815 EXPECT_EQ(counter, 5);
816
817 // if you run the loop again, the timer will start running again
818 EXPECT_FALSE(timer->IsDisabled());
819
820 counter = 0;
821 Run();
822 timer->Disable();
823
824 EXPECT_TRUE(timer->IsDisabled());
825}
826
827// Tests that timer handler is not disabled even after calling Exit on the event
828// loop using an external timer
829TEST_P(AbstractEventLoopTest, CheckTimerRepeatTillEndTimerDisabled) {
830 auto loop = MakePrimary("primary");
831
832 auto timer = loop->AddTimer([]() { LOG(INFO) << "timer called"; });
833
834 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700835 timer->Schedule(loop->monotonic_now() + chrono::seconds(1),
836 chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700837 EXPECT_FALSE(timer->IsDisabled());
838 });
839
840 EndEventLoop(loop.get(), chrono::seconds(5));
841 Run();
842 EXPECT_FALSE(timer->IsDisabled());
843
844 timer->Disable();
845 EXPECT_TRUE(timer->IsDisabled());
846}
847
Austin Schuhbbce72d2019-05-26 15:11:46 -0700848// Tests that Fetch and FetchNext interleave as expected.
849TEST_P(AbstractEventLoopTest, FetchAndFetchNextTogether) {
850 auto loop1 = Make();
851 auto loop2 = MakePrimary();
852
853 auto sender = loop1->MakeSender<TestMessage>("/test");
854
855 ::std::vector<int> values;
856
Austin Schuh98ed26f2023-07-19 14:12:28 -0700857 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700858 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
859 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700860 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700861 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700862 }
863
864 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
865
866 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700867 auto test_timer = loop2->AddTimer([&fetcher, &values, &sender, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700868 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700869 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700870 }
871
Austin Schuh98ed26f2023-07-19 14:12:28 -0700872 for (int i = 202; i < 205; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700873 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
874 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700875 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700876 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700877 }
878
879 if (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700880 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700881 }
882
883 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700884 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700885 }
886
Austin Schuh9fe68f72019-08-10 19:32:03 -0700887 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700888 });
889
890 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700891 test_timer->Schedule(loop2->monotonic_now(),
892 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700893 });
894
895 Run();
896 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
897}
898
Austin Schuh98ed26f2023-07-19 14:12:28 -0700899// Tests that Fetch{If,} and FetchNext{If,} interleave as expected.
900TEST_P(AbstractEventLoopTest, FetchAndFetchNextIfTogether) {
901 auto loop1 = Make();
902 auto loop2 = MakePrimary();
903
904 auto sender = loop1->MakeSender<TestMessage>("/test");
905
906 ::std::vector<int> values;
907
908 for (int i = 200; i < 202; ++i) {
909 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
910 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
911 builder.add_value(i);
912 msg.CheckOk(msg.Send(builder.Finish()));
913 }
914
915 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
916
917 // Add a timer to actually quit.
918 auto test_timer = loop2->AddTimer([&fetcher, &values, &sender, this]() {
919 if (fetcher.Fetch()) {
920 values.push_back(fetcher.get()->value());
921 }
922
923 for (int i = 202; i < 205; ++i) {
924 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
925 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
926 builder.add_value(i);
927 msg.CheckOk(msg.Send(builder.Finish()));
928 }
929
930 EXPECT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false)));
931
932 if (fetcher.FetchNext()) {
933 values.push_back(fetcher.get()->value());
934 }
935
936 EXPECT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false)));
937 EXPECT_FALSE(fetcher.FetchIf(MakeShouldFetch(false)));
938
939 if (fetcher.FetchIf(MakeShouldFetch(true))) {
940 values.push_back(fetcher.get()->value());
941 }
942
943 this->Exit();
944 });
945
946 loop2->OnRun([&test_timer, &loop2]() {
947 test_timer->Schedule(loop2->monotonic_now(),
948 ::std::chrono::milliseconds(100));
949 });
950
951 Run();
952 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
953}
954
Austin Schuh3115a202019-05-27 21:02:14 -0700955// Tests that FetchNext behaves correctly when we get two messages in the queue
956// but don't consume the first until after the second has been sent.
957TEST_P(AbstractEventLoopTest, FetchNextTest) {
Austin Schuh3115a202019-05-27 21:02:14 -0700958 auto send_loop = Make();
959 auto fetch_loop = Make();
960 auto sender = send_loop->MakeSender<TestMessage>("/test");
961 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
962
963 {
Tyler Chatow67ddb032020-01-12 14:30:04 -0800964 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
965 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
966 builder.add_value(100);
milind1f1dca32021-07-03 13:50:07 -0700967 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700968 }
969
970 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700971 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
972 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
973 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700974 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700975 }
976
977 ASSERT_TRUE(fetcher.FetchNext());
978 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700979 EXPECT_EQ(100, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700980
981 ASSERT_TRUE(fetcher.FetchNext());
982 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700983 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700984
985 // When we run off the end of the queue, expect to still have the old message:
986 ASSERT_FALSE(fetcher.FetchNext());
987 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700988 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700989}
990
Austin Schuh98ed26f2023-07-19 14:12:28 -0700991// Tests that FetchNext behaves correctly when we get two messages in the queue
992// but don't consume the first until after the second has been sent.
993TEST_P(AbstractEventLoopTest, FetchNextIfTest) {
994 auto send_loop = Make();
995 auto fetch_loop = Make();
996 auto sender = send_loop->MakeSender<TestMessage>("/test");
997 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
998
999 {
1000 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1001 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1002 builder.add_value(100);
1003 msg.CheckOk(msg.Send(builder.Finish()));
1004 }
1005
1006 {
1007 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1008 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1009 builder.add_value(200);
1010 msg.CheckOk(msg.Send(builder.Finish()));
1011 }
1012
1013 size_t called_count = 0;
1014 ASSERT_TRUE(fetcher.FetchNextIf(MakeShouldFetch(true, &called_count)));
1015 ASSERT_NE(nullptr, fetcher.get());
1016 EXPECT_EQ(100, fetcher.get()->value());
1017 EXPECT_EQ(called_count, 1u);
1018
1019 ASSERT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false, &called_count)));
1020 EXPECT_EQ(called_count, 2u);
1021
1022 ASSERT_TRUE(fetcher.FetchNextIf(MakeShouldFetch(true, &called_count)));
1023 ASSERT_NE(nullptr, fetcher.get());
1024 EXPECT_EQ(200, fetcher.get()->value());
1025 EXPECT_EQ(called_count, 3u);
1026
1027 // When we run off the end of the queue, expect to still have the old message:
1028 ASSERT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false, &called_count)));
1029 EXPECT_EQ(called_count, 3u);
1030 ASSERT_NE(nullptr, fetcher.get());
1031 EXPECT_EQ(200, fetcher.get()->value());
1032}
1033
Brian Silverman77162972020-08-12 19:52:40 -07001034// Verify that a fetcher still holds its data, even after falling behind.
1035TEST_P(AbstractEventLoopTest, FetcherBehindData) {
1036 auto send_loop = Make();
1037 auto fetch_loop = Make();
1038 auto sender = send_loop->MakeSender<TestMessage>("/test");
1039 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
1040 {
1041 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1042 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1043 builder.add_value(1);
milind1f1dca32021-07-03 13:50:07 -07001044 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -07001045 }
1046 ASSERT_TRUE(fetcher.Fetch());
1047 EXPECT_EQ(1, fetcher.get()->value());
1048 for (int i = 0; i < 300; ++i) {
1049 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1050 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1051 builder.add_value(i + 2);
milind1f1dca32021-07-03 13:50:07 -07001052 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -07001053 }
1054 EXPECT_EQ(1, fetcher.get()->value());
1055}
1056
1057// Try a bunch of orderings of operations with fetchers and senders. Verify that
1058// all the fetchers have the correct data at each step.
1059TEST_P(AbstractEventLoopTest, FetcherPermutations) {
1060 for (int max_save = 0; max_save < 5; ++max_save) {
1061 SCOPED_TRACE("max_save=" + std::to_string(max_save));
1062
1063 auto send_loop = Make();
1064 auto fetch_loop = Make();
1065 auto sender = send_loop->MakeSender<TestMessage>("/test");
1066 const auto send_message = [&sender](int i) {
1067 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1068 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1069 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -07001070 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -07001071 };
1072 std::vector<Fetcher<TestMessage>> fetchers;
1073 for (int i = 0; i < 10; ++i) {
1074 fetchers.emplace_back(fetch_loop->MakeFetcher<TestMessage>("/test"));
1075 }
1076 send_message(1);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001077 const auto verify_buffers = [&]() {
1078 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>>
1079 fetchers_copy;
1080 for (const auto &fetcher : fetchers) {
1081 fetchers_copy.emplace_back(fetcher);
1082 }
1083 std::vector<std::reference_wrapper<const Sender<TestMessage>>>
1084 senders_copy;
1085 senders_copy.emplace_back(sender);
1086 VerifyBuffers(send_loop->NumberBuffers(sender.channel()), fetchers_copy,
1087 senders_copy);
1088 };
Brian Silverman77162972020-08-12 19:52:40 -07001089 for (auto &fetcher : fetchers) {
1090 ASSERT_TRUE(fetcher.Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -07001091 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001092 EXPECT_EQ(1, fetcher.get()->value());
1093 }
1094
1095 for (int save = 1; save <= max_save; ++save) {
1096 SCOPED_TRACE("save=" + std::to_string(save));
1097 send_message(100 + save);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001098 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001099 for (size_t i = 0; i < fetchers.size() - save; ++i) {
1100 SCOPED_TRACE("fetcher=" + std::to_string(i));
1101 ASSERT_TRUE(fetchers[i].Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -07001102 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001103 EXPECT_EQ(100 + save, fetchers[i].get()->value());
1104 }
1105 for (size_t i = fetchers.size() - save; i < fetchers.size() - 1; ++i) {
1106 SCOPED_TRACE("fetcher=" + std::to_string(i));
1107 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
1108 }
1109 EXPECT_EQ(1, fetchers.back().get()->value());
1110 }
1111
1112 for (int i = 0; i < 300; ++i) {
1113 send_message(200 + i);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001114 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001115 }
1116
1117 for (size_t i = 0; i < fetchers.size() - max_save; ++i) {
1118 SCOPED_TRACE("fetcher=" + std::to_string(i));
1119 if (max_save > 0) {
1120 EXPECT_EQ(100 + max_save, fetchers[i].get()->value());
1121 } else {
1122 EXPECT_EQ(1, fetchers[i].get()->value());
1123 }
1124 }
1125 for (size_t i = fetchers.size() - max_save; i < fetchers.size() - 1; ++i) {
1126 SCOPED_TRACE("fetcher=" + std::to_string(i));
1127 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
1128 }
1129 EXPECT_EQ(1, fetchers.back().get()->value());
1130 }
1131}
1132
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001133// Verify that making a fetcher and watcher for "/test" succeeds.
1134TEST_P(AbstractEventLoopTest, FetcherAndWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -08001135 auto loop = Make();
1136 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001137 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Parker Schuhe4a70d62017-12-27 20:10:20 -08001138}
1139
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001140// Verify that making 2 fetchers for "/test" succeeds.
Parker Schuhe4a70d62017-12-27 20:10:20 -08001141TEST_P(AbstractEventLoopTest, TwoFetcher) {
1142 auto loop = Make();
1143 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001144 auto fetcher2 = loop->MakeFetcher<TestMessage>("/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -08001145}
1146
Alex Perrycb7da4b2019-08-28 19:35:56 -07001147// Verify that registering a watcher for an invalid channel name dies.
1148TEST_P(AbstractEventLoopDeathTest, InvalidChannelName) {
1149 auto loop = Make();
1150 EXPECT_DEATH(
1151 { loop->MakeWatcher("/test/invalid", [&](const TestMessage &) {}); },
1152 "/test/invalid");
Brian Silverman454bc112020-03-05 14:21:25 -08001153 EXPECT_DEATH(
1154 { loop->MakeNoArgWatcher<TestMessage>("/test/invalid", [&]() {}); },
1155 "/test/invalid");
Alex Perrycb7da4b2019-08-28 19:35:56 -07001156}
1157
James Kuszmaul8866e642022-06-10 16:00:36 -07001158// Verify that setting up a timer before monotonic_clock::epoch() fails.
James Kuszmaul86e86c32022-07-21 17:39:47 -07001159TEST_P(AbstractEventLoopDeathTest, NegativeTimeTimer) {
James Kuszmaul8866e642022-06-10 16:00:36 -07001160 auto loop = Make();
1161 TimerHandler *time = loop->AddTimer([]() {});
Philipp Schradera6712522023-07-05 20:25:11 -07001162 EXPECT_DEATH(
1163 time->Schedule(monotonic_clock::epoch() - std::chrono::seconds(1)),
1164 "-1.000");
James Kuszmaul8866e642022-06-10 16:00:36 -07001165}
1166
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001167// Verify that registering a watcher twice for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001168TEST_P(AbstractEventLoopDeathTest, TwoWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -08001169 auto loop = Make();
1170 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001171 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
1172 "/test");
Brian Silverman454bc112020-03-05 14:21:25 -08001173 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
1174}
1175
1176// Verify that registering a no-arg watcher twice for "/test" fails.
1177TEST_P(AbstractEventLoopDeathTest, TwoNoArgWatcher) {
1178 auto loop = Make();
1179 loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {});
1180 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
1181 "/test");
1182 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001183}
1184
Austin Schuh3115a202019-05-27 21:02:14 -07001185// Verify that SetRuntimeRealtimePriority fails while running.
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001186TEST_P(AbstractEventLoopDeathTest, SetRuntimeRealtimePriority) {
Austin Schuh3115a202019-05-27 21:02:14 -07001187 auto loop = MakePrimary();
Austin Schuh65493d62022-08-17 15:10:37 -07001188 EXPECT_EQ(0, loop->runtime_realtime_priority());
Austin Schuh3115a202019-05-27 21:02:14 -07001189 // Confirm that runtime priority calls work when not realtime.
1190 loop->SetRuntimeRealtimePriority(5);
Austin Schuh65493d62022-08-17 15:10:37 -07001191 EXPECT_EQ(5, loop->runtime_realtime_priority());
Austin Schuh3115a202019-05-27 21:02:14 -07001192
1193 loop->OnRun([&]() { loop->SetRuntimeRealtimePriority(5); });
1194
1195 EXPECT_DEATH(Run(), "realtime");
1196}
1197
Austin Schuh65493d62022-08-17 15:10:37 -07001198namespace {
1199
1200bool CpuSetEqual(const cpu_set_t &a, const cpu_set_t &b) {
1201 return CPU_EQUAL(&a, &b);
1202}
1203
1204} // namespace
1205
Brian Silverman6a54ff32020-04-28 16:41:39 -07001206// Verify that SetRuntimeAffinity fails while running.
1207TEST_P(AbstractEventLoopDeathTest, SetRuntimeAffinity) {
Austin Schuhde973292021-10-12 18:09:49 -07001208 const cpu_set_t available = GetCurrentThreadAffinity();
1209 int first_cpu = -1;
1210 for (int i = 0; i < CPU_SETSIZE; ++i) {
1211 if (CPU_ISSET(i, &available)) {
1212 first_cpu = i;
1213 break;
1214 continue;
1215 }
1216 }
1217 CHECK_NE(first_cpu, -1) << ": Default affinity has no CPUs?";
1218
Brian Silverman6a54ff32020-04-28 16:41:39 -07001219 auto loop = MakePrimary();
Austin Schuh65493d62022-08-17 15:10:37 -07001220 EXPECT_TRUE(
1221 CpuSetEqual(EventLoop::DefaultAffinity(), loop->runtime_affinity()));
1222 const cpu_set_t new_affinity = MakeCpusetFromCpus({first_cpu});
Brian Silverman6a54ff32020-04-28 16:41:39 -07001223 // Confirm that runtime priority calls work when not running.
Austin Schuh65493d62022-08-17 15:10:37 -07001224 loop->SetRuntimeAffinity(new_affinity);
1225 EXPECT_TRUE(CpuSetEqual(new_affinity, loop->runtime_affinity()));
Brian Silverman6a54ff32020-04-28 16:41:39 -07001226
Austin Schuhde973292021-10-12 18:09:49 -07001227 loop->OnRun(
1228 [&]() { loop->SetRuntimeAffinity(MakeCpusetFromCpus({first_cpu})); });
Brian Silverman6a54ff32020-04-28 16:41:39 -07001229
1230 EXPECT_DEATH(Run(), "Cannot set affinity while running");
1231}
1232
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001233// Verify that registering a watcher and a sender for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001234TEST_P(AbstractEventLoopDeathTest, WatcherAndSender) {
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001235 auto loop = Make();
1236 auto sender = loop->MakeSender<TestMessage>("/test");
1237 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
1238 "/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -08001239}
1240
Austin Schuhe516ab02020-05-06 21:37:04 -07001241// Verify that creating too many senders fails.
1242TEST_P(AbstractEventLoopDeathTest, TooManySenders) {
1243 auto loop = Make();
1244 std::vector<aos::Sender<TestMessage>> senders;
1245 for (int i = 0; i < 10; ++i) {
1246 senders.emplace_back(loop->MakeSender<TestMessage>("/test"));
1247 }
1248 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); },
1249 "Failed to create sender on \\{ \"name\": \"/test\", \"type\": "
Brian Silverman77162972020-08-12 19:52:40 -07001250 "\"aos.TestMessage\"[^}]*\\ }, too many senders.");
1251}
1252
1253// Verify that creating too many fetchers fails.
1254TEST_P(AbstractEventLoopDeathTest, TooManyFetchers) {
1255 if (read_method() != ReadMethod::PIN) {
1256 // Other read methods don't limit the number of readers, so just skip this.
1257 return;
1258 }
1259
1260 auto loop = Make();
1261 std::vector<aos::Fetcher<TestMessage>> fetchers;
1262 for (int i = 0; i < 10; ++i) {
1263 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1264 }
1265 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1266 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1267 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
1268}
1269
1270// Verify that creating too many fetchers, split between two event loops, fails.
1271TEST_P(AbstractEventLoopDeathTest, TooManyFetchersTwoLoops) {
1272 if (read_method() != ReadMethod::PIN) {
1273 // Other read methods don't limit the number of readers, so just skip this.
1274 return;
1275 }
1276
1277 auto loop = Make();
1278 auto loop2 = Make();
1279 std::vector<aos::Fetcher<TestMessage>> fetchers;
1280 for (int i = 0; i < 5; ++i) {
1281 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1282 fetchers.emplace_back(loop2->MakeFetcher<TestMessage>("/test"));
1283 }
1284 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1285 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1286 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
1287}
1288
1289// Verify that creating too many watchers fails.
1290TEST_P(AbstractEventLoopDeathTest, TooManyWatchers) {
1291 if (read_method() != ReadMethod::PIN) {
1292 // Other read methods don't limit the number of readers, so just skip this.
1293 return;
1294 }
1295
1296 std::vector<std::unique_ptr<EventLoop>> loops;
1297 for (int i = 0; i < 10; ++i) {
1298 loops.emplace_back(Make());
1299 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
1300 }
1301 EXPECT_DEATH({ Make()->MakeWatcher("/test", [](const TestMessage &) {}); },
1302 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1303 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
1304}
1305
1306// Verify that creating too many watchers and fetchers combined fails.
1307TEST_P(AbstractEventLoopDeathTest, TooManyWatchersAndFetchers) {
1308 if (read_method() != ReadMethod::PIN) {
1309 // Other read methods don't limit the number of readers, so just skip this.
1310 return;
1311 }
1312
1313 auto loop = Make();
1314 std::vector<aos::Fetcher<TestMessage>> fetchers;
1315 std::vector<std::unique_ptr<EventLoop>> loops;
1316 for (int i = 0; i < 5; ++i) {
1317 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1318 loops.emplace_back(Make());
1319 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
1320 }
1321 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1322 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1323 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
Austin Schuhe516ab02020-05-06 21:37:04 -07001324}
1325
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001326// Verify that we can't create a sender inside OnRun.
1327TEST_P(AbstractEventLoopDeathTest, SenderInOnRun) {
1328 auto loop1 = MakePrimary();
1329
1330 loop1->OnRun(
1331 [&]() { auto sender = loop1->MakeSender<TestMessage>("/test2"); });
1332
1333 EXPECT_DEATH(Run(), "running");
1334}
1335
1336// Verify that we can't create a watcher inside OnRun.
1337TEST_P(AbstractEventLoopDeathTest, WatcherInOnRun) {
1338 auto loop1 = MakePrimary();
1339
1340 loop1->OnRun(
1341 [&]() { loop1->MakeWatcher("/test", [&](const TestMessage &) {}); });
1342
1343 EXPECT_DEATH(Run(), "running");
1344}
1345
Brian Silverman454bc112020-03-05 14:21:25 -08001346// Verify that we can't create a no-arg watcher inside OnRun.
1347TEST_P(AbstractEventLoopDeathTest, NoArgWatcherInOnRun) {
1348 auto loop1 = MakePrimary();
1349
1350 loop1->OnRun(
1351 [&]() { loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {}); });
1352
1353 EXPECT_DEATH(Run(), "running");
1354}
1355
Parker Schuhe4a70d62017-12-27 20:10:20 -08001356// Verify that Quit() works when there are multiple watchers.
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001357TEST_P(AbstractEventLoopTest, MultipleWatcherQuit) {
1358 auto loop1 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -07001359 auto loop2 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -08001360
Austin Schuh3578a2e2019-05-25 18:17:59 -07001361 loop2->MakeWatcher("/test1", [&](const TestMessage &) {});
1362 loop2->MakeWatcher("/test2", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001363 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -07001364 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -07001365 });
1366
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001367 auto sender = loop1->MakeSender<TestMessage>("/test2");
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001368
1369 loop2->OnRun([&]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001370 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1371 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1372 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001373 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001374 });
Parker Schuhe4a70d62017-12-27 20:10:20 -08001375
Austin Schuh44019f92019-05-19 19:58:27 -07001376 Run();
Parker Schuhe4a70d62017-12-27 20:10:20 -08001377}
1378
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001379// Verify that AOS_LOG has the right name.
1380TEST_P(AbstractEventLoopTest, AOSLog) {
1381 auto loop2 = MakePrimary("loop1");
1382 auto loop1 = Make("loop0");
1383
1384 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1385
1386 EXPECT_FALSE(fetcher.Fetch());
1387
1388 loop2->OnRun([&]() {
1389 AOS_LOG(INFO, "Testing123");
1390 this->Exit();
1391 });
1392
1393 Run();
1394 EXPECT_TRUE(fetcher.Fetch());
1395 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1396}
1397
1398// Verify that AOS_LOG has the right name in a watcher.
1399TEST_P(AbstractEventLoopTest, AOSLogWatcher) {
1400 auto loop2 = MakePrimary("loop1");
1401 auto loop1 = Make("loop0");
1402
1403 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1404
1405 EXPECT_FALSE(fetcher.Fetch());
1406
1407 auto sender = loop1->MakeSender<TestMessage>("/test2");
1408
1409 loop2->MakeWatcher("/test2", [&](const TestMessage & /*message*/) {
1410 AOS_LOG(INFO, "Testing123");
1411 this->Exit();
1412 });
1413
1414 loop2->OnRun([&]() {
1415 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1416 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1417 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001418 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001419 });
1420
1421 Run();
1422 EXPECT_TRUE(fetcher.Fetch());
1423 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1424}
1425
1426// Verify that AOS_LOG has the right name in a timer.
1427TEST_P(AbstractEventLoopTest, AOSLogTimer) {
1428 auto loop2 = MakePrimary("loop1");
1429 auto loop1 = Make("loop0");
1430
1431 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1432
1433 EXPECT_FALSE(fetcher.Fetch());
1434
1435 auto test_timer = loop2->AddTimer([&]() {
1436 AOS_LOG(INFO, "Testing123");
1437 this->Exit();
1438 });
1439
Philipp Schradera6712522023-07-05 20:25:11 -07001440 loop2->OnRun([&]() { test_timer->Schedule(loop2->monotonic_now()); });
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001441
1442 Run();
1443 EXPECT_TRUE(fetcher.Fetch());
1444 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1445}
1446
Neil Balch229001a2018-01-07 18:22:52 -08001447// Verify that timer intervals and duration function properly.
1448TEST_P(AbstractEventLoopTest, TimerIntervalAndDuration) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001449 // Force a slower rate so we are guaranteed to have reports for our timer.
Austin Schuh39788ff2019-12-01 18:22:57 -08001450 FLAGS_timing_report_ms = 2000;
1451
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001452 const int kCount = 5;
Neil Balch229001a2018-01-07 18:22:52 -08001453
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001454 auto loop = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001455 auto loop2 = Make();
1456
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001457 ::std::vector<::aos::monotonic_clock::time_point> times;
1458 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
1459
Austin Schuh39788ff2019-12-01 18:22:57 -08001460 Fetcher<timing::Report> report_fetcher =
1461 loop2->MakeFetcher<timing::Report>("/aos");
1462 EXPECT_FALSE(report_fetcher.Fetch());
1463
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001464 auto test_timer = loop->AddTimer([this, &times, &expected_times, &loop]() {
1465 times.push_back(loop->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001466 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
1467 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
1468 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001469 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -08001470 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
1471 EXPECT_EQ(loop->context().size, 0u);
1472 EXPECT_EQ(loop->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001473 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001474
Austin Schuhad154822019-12-27 15:45:13 -08001475 expected_times.push_back(loop->context().monotonic_event_time);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001476 if (times.size() == kCount) {
1477 this->Exit();
1478 }
Neil Balch229001a2018-01-07 18:22:52 -08001479 });
Austin Schuh39788ff2019-12-01 18:22:57 -08001480 test_timer->set_name("Test loop");
Neil Balch229001a2018-01-07 18:22:52 -08001481
Austin Schuh39788ff2019-12-01 18:22:57 -08001482 const monotonic_clock::time_point start_time = loop->monotonic_now();
Austin Schuh52d325c2019-06-23 18:59:06 -07001483 // TODO(austin): This should be an error... Should be done in OnRun only.
Philipp Schradera6712522023-07-05 20:25:11 -07001484 test_timer->Schedule(start_time + chrono::seconds(1), chrono::seconds(1));
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001485
Austin Schuh44019f92019-05-19 19:58:27 -07001486 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001487
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001488 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001489 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
1490 ASSERT_EQ(times.size(), expected_times.size());
1491 ASSERT_EQ((times.size() % 2), 1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001492
1493 // Grab the middle sample.
1494 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
1495
1496 // Add up all the delays of all the times.
1497 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1498 for (const ::aos::monotonic_clock::time_point time : times) {
1499 sum += time - average_time;
1500 }
1501
1502 // Average and add to the middle to find the average time.
1503 sum /= times.size();
1504 average_time += sum;
1505
1506 // Compute the offset from the average and the expected average. It
1507 // should be pretty close to 0.
1508 const ::aos::monotonic_clock::duration remainder =
1509 average_time - start_time - chrono::seconds(times.size() / 2 + 1);
1510
1511 const chrono::milliseconds kEpsilon(100);
1512 EXPECT_LT(remainder, +kEpsilon);
1513 EXPECT_GT(remainder, -kEpsilon);
1514
1515 // Make sure that the average duration is close to 1 second.
1516 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1517 times.front())
1518 .count() /
1519 static_cast<double>(times.size() - 1),
1520 1.0, 0.1);
1521
1522 // Confirm that the ideal wakeup times increment correctly.
1523 for (size_t i = 1; i < expected_times.size(); ++i) {
1524 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1525 }
1526
1527 for (size_t i = 0; i < expected_times.size(); ++i) {
1528 EXPECT_EQ((expected_times[i] - start_time) % chrono::seconds(1),
1529 chrono::seconds(0));
1530 }
1531
1532 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1533 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001534
Austin Schuh6bae8252021-02-07 22:01:49 -08001535 if (do_timing_reports() == DoTimingReports::kYes) {
1536 // And, since we are here, check that the timing report makes sense.
1537 // Start by looking for our event loop's timing.
1538 FlatbufferDetachedBuffer<timing::Report> report =
1539 FlatbufferDetachedBuffer<timing::Report>::Empty();
1540 while (report_fetcher.FetchNext()) {
1541 if (report_fetcher->name()->string_view() == "primary") {
1542 report = CopyFlatBuffer(report_fetcher.get());
1543 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001544 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001545
1546 // Confirm that we have the right number of reports, and the contents are
1547 // sane.
1548 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
1549
1550 EXPECT_EQ(report.message().name()->string_view(), "primary");
1551
1552 ASSERT_NE(report.message().senders(), nullptr);
1553 EXPECT_EQ(report.message().senders()->size(), 2);
1554
1555 ASSERT_NE(report.message().timers(), nullptr);
1556 EXPECT_EQ(report.message().timers()->size(), 2);
1557
1558 EXPECT_EQ(report.message().timers()->Get(0)->name()->string_view(),
1559 "Test loop");
1560 EXPECT_GE(report.message().timers()->Get(0)->count(), 1);
1561
1562 EXPECT_EQ(report.message().timers()->Get(1)->name()->string_view(),
1563 "timing_reports");
1564 EXPECT_EQ(report.message().timers()->Get(1)->count(), 1);
1565
1566 // Make sure there is a single phased loop report with our report in it.
1567 ASSERT_EQ(report.message().phased_loops(), nullptr);
1568 } else {
1569 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001570 }
Neil Balch229001a2018-01-07 18:22:52 -08001571}
1572
James Kuszmaul762e8692023-07-31 14:57:53 -07001573// Test that setting a default version string results in it getting populated
1574// correctly.
1575TEST_P(AbstractEventLoopTest, DefaultVersionStringInTimingReport) {
1576 gflags::FlagSaver flag_saver;
1577 FLAGS_timing_report_ms = 1000;
1578
1579 EventLoop::SetDefaultVersionString("default_version_string");
1580
1581 auto loop = MakePrimary();
1582
1583 Fetcher<timing::Report> report_fetcher =
1584 loop->MakeFetcher<timing::Report>("/aos");
1585
1586 TimerHandler *exit_timer = loop->AddTimer([this]() { Exit(); });
1587 loop->OnRun([exit_timer, &loop, &report_fetcher]() {
1588 report_fetcher.Fetch();
1589 exit_timer->Schedule(loop->monotonic_now() + std::chrono::seconds(2));
1590 });
1591
1592 Run();
1593
1594 bool found_primary_report = false;
1595 while (report_fetcher.FetchNext()) {
1596 if (report_fetcher->name()->string_view() == "primary") {
1597 found_primary_report = true;
1598 EXPECT_EQ("default_version_string",
1599 report_fetcher->version()->string_view());
1600 } else {
1601 FAIL() << report_fetcher->name()->string_view();
1602 }
1603 }
1604
1605 if (do_timing_reports() == DoTimingReports::kYes) {
1606 EXPECT_TRUE(found_primary_report);
1607 } else {
1608 EXPECT_FALSE(found_primary_report);
1609 }
1610}
1611
1612// Test that overriding the default version string results in it getting
1613// populated correctly.
1614TEST_P(AbstractEventLoopTest, OverrideDersionStringInTimingReport) {
1615 gflags::FlagSaver flag_saver;
1616 FLAGS_timing_report_ms = 1000;
1617
1618 EventLoop::SetDefaultVersionString("default_version_string");
1619
1620 auto loop = MakePrimary();
1621 loop->SetVersionString("override_version");
1622
1623 Fetcher<timing::Report> report_fetcher =
1624 loop->MakeFetcher<timing::Report>("/aos");
1625
1626 TimerHandler *exit_timer = loop->AddTimer([this]() { Exit(); });
1627 loop->OnRun([exit_timer, &loop, &report_fetcher]() {
1628 report_fetcher.Fetch();
1629 exit_timer->Schedule(loop->monotonic_now() + std::chrono::seconds(2));
1630 });
1631
1632 Run();
1633
1634 bool found_primary_report = false;
1635 while (report_fetcher.FetchNext()) {
1636 if (report_fetcher->name()->string_view() == "primary") {
1637 found_primary_report = true;
1638 EXPECT_EQ("override_version", report_fetcher->version()->string_view());
1639 } else {
1640 FAIL() << report_fetcher->name()->string_view();
1641 }
1642 }
1643
1644 if (do_timing_reports() == DoTimingReports::kYes) {
1645 EXPECT_TRUE(found_primary_report);
1646 } else {
1647 EXPECT_FALSE(found_primary_report);
1648 }
1649}
1650
Neil Balch229001a2018-01-07 18:22:52 -08001651// Verify that we can change a timer's parameters during execution.
1652TEST_P(AbstractEventLoopTest, TimerChangeParameters) {
Austin Schuh44019f92019-05-19 19:58:27 -07001653 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001654 loop->SetRuntimeRealtimePriority(1);
Austin Schuh7f20f512021-01-31 17:56:16 -08001655 std::vector<monotonic_clock::time_point> iteration_list;
Neil Balch229001a2018-01-07 18:22:52 -08001656
1657 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001658 ScopedNotRealtime nrt;
Austin Schuh7f20f512021-01-31 17:56:16 -08001659 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001660 });
1661
Austin Schuh7f20f512021-01-31 17:56:16 -08001662 monotonic_clock::time_point s;
1663 auto modifier_timer = loop->AddTimer([&test_timer, &s]() {
Philipp Schradera6712522023-07-05 20:25:11 -07001664 test_timer->Schedule(s + chrono::milliseconds(1750),
1665 chrono::milliseconds(600));
Neil Balch229001a2018-01-07 18:22:52 -08001666 });
1667
Austin Schuh7f20f512021-01-31 17:56:16 -08001668 s = loop->monotonic_now();
Philipp Schradera6712522023-07-05 20:25:11 -07001669 test_timer->Schedule(s, chrono::milliseconds(500));
1670 modifier_timer->Schedule(s + chrono::milliseconds(1250));
Austin Schuhd892f102021-10-12 18:01:46 -07001671 EndEventLoop(loop.get(), chrono::milliseconds(3950));
Austin Schuh44019f92019-05-19 19:58:27 -07001672 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001673
Austin Schuhd892f102021-10-12 18:01:46 -07001674 EXPECT_THAT(
1675 iteration_list,
1676 ::testing::ElementsAre(
1677 s, s + chrono::milliseconds(500), s + chrono::milliseconds(1000),
1678 s + chrono::milliseconds(1750), s + chrono::milliseconds(2350),
1679 s + chrono::milliseconds(2950), s + chrono::milliseconds(3550)));
Neil Balch229001a2018-01-07 18:22:52 -08001680}
1681
1682// Verify that we can disable a timer during execution.
1683TEST_P(AbstractEventLoopTest, TimerDisable) {
Austin Schuh44019f92019-05-19 19:58:27 -07001684 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001685 loop->SetRuntimeRealtimePriority(1);
Neil Balch229001a2018-01-07 18:22:52 -08001686 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
1687
1688 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001689 ScopedNotRealtime nrt;
Austin Schuhd892f102021-10-12 18:01:46 -07001690 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001691 });
1692
Tyler Chatow67ddb032020-01-12 14:30:04 -08001693 auto ender_timer = loop->AddTimer([&test_timer]() { test_timer->Disable(); });
Neil Balch229001a2018-01-07 18:22:52 -08001694
Austin Schuhd892f102021-10-12 18:01:46 -07001695 monotonic_clock::time_point s = loop->monotonic_now();
Philipp Schradera6712522023-07-05 20:25:11 -07001696 test_timer->Schedule(s, ::std::chrono::milliseconds(500));
1697 ender_timer->Schedule(s + ::std::chrono::milliseconds(1250));
Austin Schuh73d99502021-12-08 12:05:39 -08001698 EndEventLoop(loop.get(), ::std::chrono::milliseconds(2000));
Austin Schuh44019f92019-05-19 19:58:27 -07001699 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001700
Austin Schuhd892f102021-10-12 18:01:46 -07001701 EXPECT_THAT(iteration_list,
Austin Schuh73d99502021-12-08 12:05:39 -08001702 ::testing::ElementsAre(s, s + chrono::milliseconds(500),
1703 s + chrono::milliseconds(1000)));
Neil Balch229001a2018-01-07 18:22:52 -08001704}
Austin Schuh7267c532019-05-19 19:55:53 -07001705
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001706// Verify that a timer can disable itself.
1707//
1708// TODO(Brian): Do something similar with phased loops, both with a quick
1709// handler and a handler that would miss a cycle except it got deferred. Current
1710// behavior doing that is a mess.
1711TEST_P(AbstractEventLoopTest, TimerDisableSelf) {
1712 auto loop = MakePrimary();
1713
1714 int count = 0;
1715 aos::TimerHandler *test_timer;
1716 test_timer = loop->AddTimer([&count, &test_timer]() {
1717 ++count;
1718 test_timer->Disable();
1719 });
1720
Philipp Schradera6712522023-07-05 20:25:11 -07001721 test_timer->Schedule(loop->monotonic_now(), ::std::chrono::milliseconds(20));
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001722 EndEventLoop(loop.get(), ::std::chrono::milliseconds(80));
1723 Run();
1724
1725 EXPECT_EQ(count, 1);
1726}
1727
Brian Silvermanbd405c02020-06-23 16:25:23 -07001728// Verify that we can disable a timer during execution of another timer
1729// scheduled for the same time, with one ordering of creation for the timers.
1730//
1731// Also schedule some more events to reshuffle the heap in EventLoop used for
1732// tracking events to change up the order. This used to segfault
1733// SimulatedEventLoop.
1734TEST_P(AbstractEventLoopTest, TimerDisableOther) {
1735 for (bool creation_order : {true, false}) {
1736 for (bool setup_order : {true, false}) {
1737 for (int shuffle_events = 0; shuffle_events < 5; ++shuffle_events) {
1738 auto loop = MakePrimary();
1739 aos::TimerHandler *test_timer, *ender_timer;
1740 if (creation_order) {
1741 test_timer = loop->AddTimer([]() {});
1742 ender_timer =
1743 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1744 } else {
1745 ender_timer =
1746 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1747 test_timer = loop->AddTimer([]() {});
1748 }
1749
1750 const auto start = loop->monotonic_now();
1751
1752 for (int i = 0; i < shuffle_events; ++i) {
Philipp Schradera6712522023-07-05 20:25:11 -07001753 loop->AddTimer([]() {})->Schedule(start +
1754 std::chrono::milliseconds(10));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001755 }
1756
1757 if (setup_order) {
Philipp Schradera6712522023-07-05 20:25:11 -07001758 test_timer->Schedule(start + ::std::chrono::milliseconds(20));
1759 ender_timer->Schedule(start + ::std::chrono::milliseconds(20));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001760 } else {
Philipp Schradera6712522023-07-05 20:25:11 -07001761 ender_timer->Schedule(start + ::std::chrono::milliseconds(20));
1762 test_timer->Schedule(start + ::std::chrono::milliseconds(20));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001763 }
1764 EndEventLoop(loop.get(), ::std::chrono::milliseconds(40));
1765 Run();
1766 }
1767 }
1768 }
1769}
1770
Austin Schuh54cf95f2019-11-29 13:14:18 -08001771// Verifies that the event loop implementations detect when Channel is not a
Brian Silverman631b6262021-11-10 12:25:08 -08001772// pointer into configuration(), or a name doesn't map to a channel in
1773// configuration().
Austin Schuh54cf95f2019-11-29 13:14:18 -08001774TEST_P(AbstractEventLoopDeathTest, InvalidChannel) {
1775 auto loop = MakePrimary();
1776
Tyler Chatow67ddb032020-01-12 14:30:04 -08001777 const Channel *channel = configuration::GetChannel(
1778 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
Austin Schuh54cf95f2019-11-29 13:14:18 -08001779
1780 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1781
1782 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001783 loop->MakeRawSender(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001784 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1785
1786 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001787 loop->MakeSender<TestMessage>("/testbad"),
1788 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1789 " not found in config");
1790
1791 EXPECT_FALSE(loop->TryMakeSender<TestMessage>("/testbad"));
1792
1793 EXPECT_DEATH(
1794 loop->MakeRawFetcher(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001795 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1796
1797 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001798 loop->MakeFetcher<TestMessage>("/testbad"),
1799 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1800 " not found in config");
1801
1802 EXPECT_FALSE(loop->TryMakeFetcher<TestMessage>("/testbad").valid());
1803
1804 EXPECT_DEATH(
Austin Schuh54cf95f2019-11-29 13:14:18 -08001805 {
1806 loop->MakeRawWatcher(&channel_copy.message(),
1807 [](const Context, const void *) {});
1808 },
1809 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
Brian Silverman631b6262021-11-10 12:25:08 -08001810
1811 EXPECT_DEATH(
1812 { loop->MakeWatcher("/testbad", [](const TestMessage &) {}); },
1813 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1814 " not found in config");
1815}
1816
1817// Verifies that the event loop handles a channel which is not readable or
1818// writable on the current node nicely.
1819TEST_P(AbstractEventLoopDeathTest, InaccessibleChannel) {
1820 EnableNodes("me");
1821 auto loop = MakePrimary("me");
1822 auto loop2 = Make("them");
1823
1824 const Channel *channel = configuration::GetChannel(
1825 loop->configuration(), "/test_noforward", "aos.TestMessage", "", nullptr);
1826
1827 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1828
1829 EXPECT_DEATH(
1830 loop2->MakeSender<TestMessage>("/test_forward"),
1831 "Channel"
1832 " \\{ \"name\": \"/test_forward\", \"type\": \"aos.TestMessage\" \\}"
1833 " is not able to be sent on this node");
1834
1835 EXPECT_FALSE(loop2->TryMakeSender<TestMessage>("/test_forward"));
1836
1837 EXPECT_DEATH(
1838 loop2->MakeRawFetcher(channel),
1839 "Channel"
1840 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1841 " is not able to be fetched on this node");
1842
1843 EXPECT_DEATH(
1844 loop2->MakeFetcher<TestMessage>("/test_noforward"),
1845 "Channel"
1846 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1847 " is not able to be fetched on this node");
1848
1849 EXPECT_FALSE(loop2->TryMakeFetcher<TestMessage>("/test_noforward").valid());
1850
1851 EXPECT_DEATH(
1852 { loop2->MakeRawWatcher(channel, [](const Context, const void *) {}); },
1853 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1854 "\"source_node\": \"them\" \\}"
1855 " is not able to be watched on this node");
1856
1857 EXPECT_DEATH(
1858 { loop2->MakeWatcher("/test_noforward", [](const TestMessage &) {}); },
1859 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1860 "\"source_node\": \"them\" \\}"
1861 " is not able to be watched on this node");
Austin Schuh54cf95f2019-11-29 13:14:18 -08001862}
1863
Austin Schuhd54780b2020-10-03 16:26:02 -07001864// Verifies that the event loop implementations detect when Channel has an
1865// invalid alignment.
1866TEST_P(AbstractEventLoopDeathTest, InvalidChannelAlignment) {
1867 const char *const kError = "multiple of alignment";
1868 InvalidChannelAlignment();
1869
1870 auto loop = MakePrimary();
1871
1872 const Channel *channel = configuration::GetChannel(
1873 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
1874
1875 EXPECT_DEATH({ loop->MakeRawSender(channel); }, kError);
1876 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); }, kError);
1877
1878 EXPECT_DEATH({ loop->MakeRawFetcher(channel); }, kError);
1879 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); }, kError);
1880
1881 EXPECT_DEATH(
1882 { loop->MakeRawWatcher(channel, [](const Context &, const void *) {}); },
1883 kError);
1884 EXPECT_DEATH({ loop->MakeRawNoArgWatcher(channel, [](const Context &) {}); },
1885 kError);
1886
1887 EXPECT_DEATH({ loop->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
1888 kError);
1889 EXPECT_DEATH({ loop->MakeWatcher("/test", [](const TestMessage &) {}); },
1890 kError);
1891}
1892
Brian Silverman454bc112020-03-05 14:21:25 -08001893// Verify that the send time on a message is roughly right when using a watcher.
Austin Schuh7267c532019-05-19 19:55:53 -07001894TEST_P(AbstractEventLoopTest, MessageSendTime) {
Austin Schuh44019f92019-05-19 19:58:27 -07001895 auto loop1 = MakePrimary();
Austin Schuh7267c532019-05-19 19:55:53 -07001896 auto loop2 = Make();
Austin Schuhad154822019-12-27 15:45:13 -08001897 auto sender = loop2->MakeSender<TestMessage>("/test");
Austin Schuh7267c532019-05-19 19:55:53 -07001898 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
1899
1900 auto test_timer = loop1->AddTimer([&sender]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001901 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1902 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1903 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001904 msg.CheckOk(msg.Send(builder.Finish()));
Alex Perrycb7da4b2019-08-28 19:35:56 -07001905 });
1906
Austin Schuhad154822019-12-27 15:45:13 -08001907 bool triggered = false;
Brian Silverman454bc112020-03-05 14:21:25 -08001908 loop1->MakeWatcher("/test", [&](const TestMessage &msg) {
Austin Schuhad154822019-12-27 15:45:13 -08001909 // Confirm that the data pointer makes sense from a watcher, and all the
1910 // timestamps look right.
1911 EXPECT_GT(&msg, loop1->context().data);
1912 EXPECT_EQ(loop1->context().monotonic_remote_time,
1913 loop1->context().monotonic_event_time);
1914 EXPECT_EQ(loop1->context().realtime_remote_time,
1915 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001916 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001917
1918 const aos::monotonic_clock::time_point monotonic_now =
1919 loop1->monotonic_now();
Tyler Chatow67ddb032020-01-12 14:30:04 -08001920 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08001921
1922 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1923 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1924 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1925 monotonic_now);
1926 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1927 realtime_now);
1928
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001929 EXPECT_LT(&msg, reinterpret_cast<const void *>(
1930 reinterpret_cast<const char *>(loop1->context().data) +
Austin Schuhad154822019-12-27 15:45:13 -08001931 loop1->context().size));
Brian Silverman4f4e0612020-08-12 19:54:41 -07001932 if (read_method() == ReadMethod::PIN) {
1933 EXPECT_GE(loop1->context().buffer_index, 0);
1934 EXPECT_LT(loop1->context().buffer_index,
1935 loop1->NumberBuffers(
1936 configuration::GetChannel(loop1->configuration(), "/test",
1937 "aos.TestMessage", "", nullptr)));
1938 } else {
1939 EXPECT_EQ(-1, loop1->context().buffer_index);
1940 }
Austin Schuhad154822019-12-27 15:45:13 -08001941 triggered = true;
Austin Schuh7267c532019-05-19 19:55:53 -07001942 });
1943
Philipp Schradera6712522023-07-05 20:25:11 -07001944 test_timer->Schedule(loop1->monotonic_now() + ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07001945
1946 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
Austin Schuh44019f92019-05-19 19:58:27 -07001947 Run();
Austin Schuh7267c532019-05-19 19:55:53 -07001948
Austin Schuhad154822019-12-27 15:45:13 -08001949 EXPECT_TRUE(triggered);
1950
Brian Silverman454bc112020-03-05 14:21:25 -08001951 ASSERT_TRUE(fetcher.Fetch());
1952
1953 monotonic_clock::duration monotonic_time_offset =
1954 fetcher.context().monotonic_event_time -
1955 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1956 realtime_clock::duration realtime_time_offset =
1957 fetcher.context().realtime_event_time -
1958 (loop1->realtime_now() - ::std::chrono::seconds(1));
1959
1960 EXPECT_EQ(fetcher.context().realtime_event_time,
1961 fetcher.context().realtime_remote_time);
1962 EXPECT_EQ(fetcher.context().monotonic_event_time,
1963 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001964 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001965
1966 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1967 << ": Got "
1968 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1969 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1970 // Confirm that the data pointer makes sense.
1971 EXPECT_GT(fetcher.get(), fetcher.context().data);
1972 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001973 reinterpret_cast<const void *>(
1974 reinterpret_cast<const char *>(fetcher.context().data) +
Brian Silverman454bc112020-03-05 14:21:25 -08001975 fetcher.context().size));
1976 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1977 << ": Got "
1978 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1979 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1980
1981 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1982 << ": Got "
1983 << fetcher.context().realtime_event_time.time_since_epoch().count()
1984 << " expected " << loop1->realtime_now().time_since_epoch().count();
1985 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1986 << ": Got "
1987 << fetcher.context().realtime_event_time.time_since_epoch().count()
1988 << " expected " << loop1->realtime_now().time_since_epoch().count();
1989}
1990
1991// Verify that the send time on a message is roughly right when using a no-arg
1992// watcher. To get a message, we need to use a fetcher to actually access the
1993// message. This is also the main use case for no-arg fetchers.
1994TEST_P(AbstractEventLoopTest, MessageSendTimeNoArg) {
1995 auto loop1 = MakePrimary();
1996 auto loop2 = Make();
1997 auto sender = loop2->MakeSender<TestMessage>("/test");
1998 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
1999
2000 auto test_timer = loop1->AddTimer([&sender]() {
2001 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2002 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2003 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07002004 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -08002005 });
2006
2007 bool triggered = false;
2008 loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {
2009 // Confirm that we can indeed use a fetcher on this channel from this
2010 // context, and it results in a sane data pointer and timestamps.
2011 ASSERT_TRUE(fetcher.Fetch());
2012
2013 EXPECT_EQ(loop1->context().monotonic_remote_time,
2014 loop1->context().monotonic_event_time);
2015 EXPECT_EQ(loop1->context().realtime_remote_time,
2016 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002017 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08002018
2019 const aos::monotonic_clock::time_point monotonic_now =
2020 loop1->monotonic_now();
2021 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
2022
2023 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
2024 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
2025 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
2026 monotonic_now);
2027 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
2028 realtime_now);
2029
2030 triggered = true;
2031 });
2032
Philipp Schradera6712522023-07-05 20:25:11 -07002033 test_timer->Schedule(loop1->monotonic_now() + ::std::chrono::seconds(1));
Brian Silverman454bc112020-03-05 14:21:25 -08002034
2035 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
2036 Run();
2037
2038 ASSERT_TRUE(triggered);
Austin Schuh7267c532019-05-19 19:55:53 -07002039
Alex Perrycb7da4b2019-08-28 19:35:56 -07002040 monotonic_clock::duration monotonic_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08002041 fetcher.context().monotonic_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07002042 (loop1->monotonic_now() - ::std::chrono::seconds(1));
2043 realtime_clock::duration realtime_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08002044 fetcher.context().realtime_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07002045 (loop1->realtime_now() - ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07002046
Austin Schuhad154822019-12-27 15:45:13 -08002047 EXPECT_EQ(fetcher.context().realtime_event_time,
2048 fetcher.context().realtime_remote_time);
2049 EXPECT_EQ(fetcher.context().monotonic_event_time,
2050 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002051 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08002052
Alex Perrycb7da4b2019-08-28 19:35:56 -07002053 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
2054 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002055 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh52d325c2019-06-23 18:59:06 -07002056 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07002057 // Confirm that the data pointer makes sense.
2058 EXPECT_GT(fetcher.get(), fetcher.context().data);
2059 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07002060 reinterpret_cast<const void *>(
2061 reinterpret_cast<const char *>(fetcher.context().data) +
Alex Perrycb7da4b2019-08-28 19:35:56 -07002062 fetcher.context().size));
2063 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
2064 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002065 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh7267c532019-05-19 19:55:53 -07002066 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07002067
2068 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
2069 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002070 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07002071 << " expected " << loop1->realtime_now().time_since_epoch().count();
2072 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
2073 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002074 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07002075 << " expected " << loop1->realtime_now().time_since_epoch().count();
Austin Schuh7267c532019-05-19 19:55:53 -07002076}
2077
Austin Schuh52d325c2019-06-23 18:59:06 -07002078// Tests that a couple phased loops run in a row result in the correct offset
2079// and period.
2080TEST_P(AbstractEventLoopTest, PhasedLoopTest) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07002081 // Force a slower rate so we are guaranteed to have reports for our phased
Austin Schuh39788ff2019-12-01 18:22:57 -08002082 // loop.
2083 FLAGS_timing_report_ms = 2000;
2084
Austin Schuh52d325c2019-06-23 18:59:06 -07002085 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2086 const int kCount = 5;
2087
2088 auto loop1 = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08002089 auto loop2 = Make();
2090
2091 Fetcher<timing::Report> report_fetcher =
2092 loop2->MakeFetcher<timing::Report>("/aos");
2093 EXPECT_FALSE(report_fetcher.Fetch());
Austin Schuh52d325c2019-06-23 18:59:06 -07002094
2095 // Collect up a couple of samples.
2096 ::std::vector<::aos::monotonic_clock::time_point> times;
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002097 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
Austin Schuh52d325c2019-06-23 18:59:06 -07002098
2099 // Run kCount iterations.
Austin Schuh39788ff2019-12-01 18:22:57 -08002100 loop1
2101 ->AddPhasedLoop(
2102 [&times, &expected_times, &loop1, this](int count) {
2103 EXPECT_EQ(count, 1);
2104 times.push_back(loop1->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08002105 expected_times.push_back(loop1->context().monotonic_event_time);
Austin Schuh39788ff2019-12-01 18:22:57 -08002106
Austin Schuhad154822019-12-27 15:45:13 -08002107 EXPECT_EQ(loop1->context().monotonic_remote_time,
2108 monotonic_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002109 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08002110 EXPECT_EQ(loop1->context().realtime_event_time,
2111 realtime_clock::min_time);
2112 EXPECT_EQ(loop1->context().realtime_remote_time,
Austin Schuh39788ff2019-12-01 18:22:57 -08002113 realtime_clock::min_time);
2114 EXPECT_EQ(loop1->context().queue_index, 0xffffffffu);
2115 EXPECT_EQ(loop1->context().size, 0u);
2116 EXPECT_EQ(loop1->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07002117 EXPECT_EQ(loop1->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08002118
2119 if (times.size() == kCount) {
2120 LOG(INFO) << "Exiting";
2121 this->Exit();
2122 }
2123 },
2124 chrono::seconds(1), kOffset)
2125 ->set_name("Test loop");
Austin Schuh52d325c2019-06-23 18:59:06 -07002126
2127 // Add a delay to make sure that delay during startup doesn't result in a
2128 // "missed cycle".
2129 SleepFor(chrono::seconds(2));
2130
2131 Run();
2132
2133 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07002134 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
2135 ASSERT_EQ(times.size(), expected_times.size());
2136 ASSERT_EQ((times.size() % 2), 1);
Austin Schuh52d325c2019-06-23 18:59:06 -07002137
2138 // Grab the middle sample.
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002139 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
Austin Schuh52d325c2019-06-23 18:59:06 -07002140
2141 // Add up all the delays of all the times.
2142 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
2143 for (const ::aos::monotonic_clock::time_point time : times) {
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002144 sum += time - average_time;
Austin Schuh52d325c2019-06-23 18:59:06 -07002145 }
2146
2147 // Average and add to the middle to find the average time.
2148 sum /= times.size();
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002149 average_time += sum;
Austin Schuh52d325c2019-06-23 18:59:06 -07002150
2151 // Compute the offset from the start of the second of the average time. This
2152 // should be pretty close to the offset.
2153 const ::aos::monotonic_clock::duration remainder =
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002154 average_time.time_since_epoch() -
2155 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
Austin Schuh52d325c2019-06-23 18:59:06 -07002156
2157 const chrono::milliseconds kEpsilon(100);
2158 EXPECT_LT(remainder, kOffset + kEpsilon);
2159 EXPECT_GT(remainder, kOffset - kEpsilon);
2160
2161 // Make sure that the average duration is close to 1 second.
2162 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
2163 times.front())
2164 .count() /
2165 static_cast<double>(times.size() - 1),
2166 1.0, 0.1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002167
2168 // Confirm that the ideal wakeup times increment correctly.
2169 for (size_t i = 1; i < expected_times.size(); ++i) {
2170 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
2171 }
2172
2173 for (size_t i = 0; i < expected_times.size(); ++i) {
2174 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
2175 kOffset);
2176 }
2177
2178 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
2179 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08002180
Austin Schuh6bae8252021-02-07 22:01:49 -08002181 if (do_timing_reports() == DoTimingReports::kYes) {
2182 // And, since we are here, check that the timing report makes sense.
2183 // Start by looking for our event loop's timing.
2184 FlatbufferDetachedBuffer<timing::Report> report =
2185 FlatbufferDetachedBuffer<timing::Report>::Empty();
2186 while (report_fetcher.FetchNext()) {
2187 if (report_fetcher->name()->string_view() == "primary") {
2188 report = CopyFlatBuffer(report_fetcher.get());
2189 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002190 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002191
2192 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
2193
2194 EXPECT_EQ(report.message().name()->string_view(), "primary");
2195
2196 ASSERT_NE(report.message().senders(), nullptr);
2197 EXPECT_EQ(report.message().senders()->size(), 2);
2198
2199 ASSERT_NE(report.message().timers(), nullptr);
2200 EXPECT_EQ(report.message().timers()->size(), 1);
2201
2202 // Make sure there is a single phased loop report with our report in it.
2203 ASSERT_NE(report.message().phased_loops(), nullptr);
2204 ASSERT_EQ(report.message().phased_loops()->size(), 1);
2205 EXPECT_EQ(report.message().phased_loops()->Get(0)->name()->string_view(),
2206 "Test loop");
2207 EXPECT_GE(report.message().phased_loops()->Get(0)->count(), 1);
2208 } else {
2209 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002210 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002211}
2212
Milind Upadhyay42589bb2021-05-19 20:05:16 -07002213// Tests that a phased loop responds correctly to a changing offset.
2214TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetTest) {
2215 // Force a slower rate so we are guaranteed to have reports for our phased
2216 // loop.
2217 FLAGS_timing_report_ms = 2000;
2218
2219 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2220 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2221 const int kCount = 5;
2222
2223 auto loop1 = MakePrimary();
2224
2225 // Collect up a couple of samples.
2226 ::std::vector<::aos::monotonic_clock::time_point> times;
2227 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
2228
2229 PhasedLoopHandler *phased_loop;
2230
2231 // Run kCount iterations.
2232 phased_loop = loop1->AddPhasedLoop(
2233 [&phased_loop, &times, &expected_times, &loop1, this, kOffset,
2234 kInterval](int count) {
2235 EXPECT_EQ(count, 1);
2236 times.push_back(loop1->monotonic_now());
2237
2238 expected_times.push_back(loop1->context().monotonic_event_time);
2239
2240 phased_loop->set_interval_and_offset(
2241 kInterval, kOffset - chrono::milliseconds(times.size()));
2242 LOG(INFO) << "new offset: "
2243 << (kOffset - chrono::milliseconds(times.size())).count();
2244
2245 if (times.size() == kCount) {
2246 LOG(INFO) << "Exiting";
2247 this->Exit();
2248 }
2249 },
2250 kInterval, kOffset);
2251 phased_loop->set_name("Test loop");
2252
2253 // Add a delay to make sure that delay during startup doesn't result in a
2254 // "missed cycle".
2255 SleepFor(chrono::seconds(2));
2256
2257 Run();
2258 // Confirm that we got both the right number of samples, and it's odd.
2259 EXPECT_EQ(times.size(), static_cast<size_t>(kCount));
2260 EXPECT_EQ(times.size(), expected_times.size());
2261 EXPECT_EQ((times.size() % 2), 1);
2262
2263 // Grab the middle sample.
2264 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
2265
2266 // Add up all the delays of all the times.
2267 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
2268 for (const ::aos::monotonic_clock::time_point time : times) {
2269 sum += time - average_time;
2270 }
2271
2272 // Average and add to the middle to find the average time.
2273 sum /= times.size();
2274 average_time += sum;
2275
2276 // Compute the offset from the start of the second of the average time. This
2277 // should be pretty close to the offset.
2278 const ::aos::monotonic_clock::duration remainder =
2279 average_time.time_since_epoch() -
2280 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
2281
2282 const chrono::milliseconds kEpsilon(100);
2283 EXPECT_LT(remainder, kOffset + kEpsilon);
2284 EXPECT_GT(remainder, kOffset - kEpsilon);
2285
2286 // Make sure that the average duration is close to 1 second.
2287 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
2288 times.front())
2289 .count() /
2290 static_cast<double>(times.size() - 1),
2291 1.0, 0.1);
2292
2293 // Confirm that the ideal wakeup times increment correctly.
2294 for (size_t i = 1; i < expected_times.size(); ++i) {
2295 LOG(INFO) << i - 1 << ": " << expected_times[i - 1] << ", " << i << ": "
2296 << expected_times[i];
2297 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1) -
2298 chrono::milliseconds(1));
2299 }
2300
2301 for (size_t i = 0; i < expected_times.size(); ++i) {
2302 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
2303 kOffset - chrono::milliseconds(i));
2304 }
2305
2306 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
2307 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
2308}
2309
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002310// Tests that a phased loop responds correctly to a changing offset; sweep
2311// across a variety of potential offset changes, to ensure that we are
2312// exercising a variety of potential cases.
2313TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetSweep) {
2314 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2315 const int kCount = 5;
2316
2317 auto loop1 = MakePrimary();
2318
2319 std::vector<aos::monotonic_clock::duration> offset_options;
2320 for (int ii = 0; ii < kCount; ++ii) {
2321 offset_options.push_back(ii * kInterval / kCount);
2322 }
2323 std::vector<aos::monotonic_clock::duration> offset_sweep;
2324 // Run over all the pair-wise combinations of offsets.
2325 for (int ii = 0; ii < kCount; ++ii) {
2326 for (int jj = 0; jj < kCount; ++jj) {
2327 offset_sweep.push_back(offset_options.at(ii));
2328 offset_sweep.push_back(offset_options.at(jj));
2329 }
2330 }
2331
2332 std::vector<::aos::monotonic_clock::time_point> expected_times;
2333
2334 PhasedLoopHandler *phased_loop;
2335
2336 // Run kCount iterations.
2337 size_t counter = 0;
2338 phased_loop = loop1->AddPhasedLoop(
2339 [&phased_loop, &expected_times, &loop1, this, kInterval, &counter,
2340 offset_sweep](int count) {
2341 EXPECT_EQ(count, 1);
2342 expected_times.push_back(loop1->context().monotonic_event_time);
2343
2344 counter++;
2345
2346 if (counter == offset_sweep.size()) {
2347 LOG(INFO) << "Exiting";
2348 this->Exit();
2349 return;
2350 }
2351
2352 phased_loop->set_interval_and_offset(kInterval,
2353 offset_sweep.at(counter));
2354 },
2355 kInterval, offset_sweep.at(0));
2356
2357 Run();
2358 ASSERT_EQ(expected_times.size(), offset_sweep.size());
2359 for (size_t ii = 1; ii < expected_times.size(); ++ii) {
2360 EXPECT_LE(expected_times.at(ii) - expected_times.at(ii - 1), kInterval);
2361 }
2362}
2363
2364// Tests that a phased loop responds correctly to being rescheduled with now
2365// equal to a time in the past.
2366TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleInPast) {
2367 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2368 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2369
2370 auto loop1 = MakePrimary();
2371
2372 std::vector<::aos::monotonic_clock::time_point> expected_times;
2373
2374 PhasedLoopHandler *phased_loop;
2375
2376 int expected_count = 1;
2377
2378 // Set up a timer that will get run immediately after the phased loop and
2379 // which will attempt to reschedule the phased loop to just before now. This
2380 // should succeed, but will result in 0 cycles elapsing.
2381 TimerHandler *manager_timer =
2382 loop1->AddTimer([&phased_loop, &loop1, &expected_count, this]() {
2383 if (expected_count == 0) {
2384 LOG(INFO) << "Exiting";
2385 this->Exit();
2386 return;
2387 }
2388 phased_loop->Reschedule(loop1->context().monotonic_event_time -
2389 std::chrono::nanoseconds(1));
2390 expected_count = 0;
2391 });
2392
2393 phased_loop = loop1->AddPhasedLoop(
2394 [&expected_count, &expected_times, &loop1, manager_timer](int count) {
2395 EXPECT_EQ(count, expected_count);
2396 expected_times.push_back(loop1->context().monotonic_event_time);
2397
Philipp Schradera6712522023-07-05 20:25:11 -07002398 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002399 },
2400 kInterval, kOffset);
2401 phased_loop->set_name("Test loop");
2402 manager_timer->set_name("Manager timer");
2403
2404 Run();
2405
2406 ASSERT_EQ(2u, expected_times.size());
2407 ASSERT_EQ(expected_times[0], expected_times[1]);
2408}
2409
2410// Tests that a phased loop responds correctly to being rescheduled at the time
2411// when it should be triggering (it should kick the trigger to the next cycle).
2412TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleNow) {
2413 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2414 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2415
2416 auto loop1 = MakePrimary();
2417
2418 std::vector<::aos::monotonic_clock::time_point> expected_times;
2419
2420 PhasedLoopHandler *phased_loop;
2421
2422 bool should_exit = false;
2423 // Set up a timer that will get run immediately after the phased loop and
2424 // which will attempt to reschedule the phased loop to now. This should
2425 // succeed, but will result in no change to the expected behavior (since this
2426 // is the same thing that is actually done internally).
2427 TimerHandler *manager_timer =
2428 loop1->AddTimer([&phased_loop, &loop1, &should_exit, this]() {
2429 if (should_exit) {
2430 LOG(INFO) << "Exiting";
2431 this->Exit();
2432 return;
2433 }
2434 phased_loop->Reschedule(loop1->context().monotonic_event_time);
2435 should_exit = true;
2436 });
2437
2438 phased_loop = loop1->AddPhasedLoop(
2439 [&expected_times, &loop1, manager_timer](int count) {
2440 EXPECT_EQ(count, 1);
2441 expected_times.push_back(loop1->context().monotonic_event_time);
2442
Philipp Schradera6712522023-07-05 20:25:11 -07002443 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002444 },
2445 kInterval, kOffset);
2446 phased_loop->set_name("Test loop");
2447 manager_timer->set_name("Manager timer");
2448
2449 Run();
2450
2451 ASSERT_EQ(2u, expected_times.size());
2452 ASSERT_EQ(expected_times[0] + kInterval, expected_times[1]);
2453}
2454
2455// Tests that a phased loop responds correctly to being rescheduled at a time in
2456// the distant future.
2457TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleFuture) {
2458 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2459 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2460
2461 auto loop1 = MakePrimary();
2462
2463 std::vector<::aos::monotonic_clock::time_point> expected_times;
2464
2465 PhasedLoopHandler *phased_loop;
2466
2467 bool should_exit = false;
2468 int expected_count = 1;
2469 TimerHandler *manager_timer = loop1->AddTimer(
2470 [&expected_count, &phased_loop, &loop1, &should_exit, this, kInterval]() {
2471 if (should_exit) {
2472 LOG(INFO) << "Exiting";
2473 this->Exit();
2474 return;
2475 }
2476 expected_count = 10;
2477 // Knock off 1 ns, since the scheduler rounds up when it is
2478 // scheduled to exactly a loop time.
2479 phased_loop->Reschedule(loop1->context().monotonic_event_time +
2480 kInterval * expected_count -
2481 std::chrono::nanoseconds(1));
2482 should_exit = true;
2483 });
2484
2485 phased_loop = loop1->AddPhasedLoop(
2486 [&expected_times, &loop1, manager_timer, &expected_count](int count) {
2487 EXPECT_EQ(count, expected_count);
2488 expected_times.push_back(loop1->context().monotonic_event_time);
2489
Philipp Schradera6712522023-07-05 20:25:11 -07002490 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002491 },
2492 kInterval, kOffset);
2493 phased_loop->set_name("Test loop");
2494 manager_timer->set_name("Manager timer");
2495
2496 Run();
2497
2498 ASSERT_EQ(2u, expected_times.size());
2499 ASSERT_EQ(expected_times[0] + expected_count * kInterval, expected_times[1]);
2500}
2501
2502// Tests that a phased loop responds correctly to having its phase offset
2503// incremented and then being scheduled after a set time, exercising a pattern
2504// where a phased loop's offset is changed while trying to maintain the trigger
2505// at a consistent period.
2506TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleWithLaterOffset) {
2507 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2508 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2509
2510 auto loop1 = MakePrimary();
2511
2512 std::vector<::aos::monotonic_clock::time_point> expected_times;
2513
2514 PhasedLoopHandler *phased_loop;
2515
2516 bool should_exit = false;
2517 TimerHandler *manager_timer = loop1->AddTimer(
2518 [&phased_loop, &loop1, &should_exit, this, kInterval, kOffset]() {
2519 if (should_exit) {
2520 LOG(INFO) << "Exiting";
2521 this->Exit();
2522 return;
2523 }
2524 // Schedule the next callback to be strictly later than the current time
2525 // + interval / 2, to ensure a consistent frequency.
2526 monotonic_clock::time_point half_time =
2527 loop1->context().monotonic_event_time + kInterval / 2;
2528 phased_loop->set_interval_and_offset(
2529 kInterval, kOffset + std::chrono::nanoseconds(1), half_time);
2530 phased_loop->Reschedule(half_time);
2531 should_exit = true;
2532 });
2533
2534 phased_loop = loop1->AddPhasedLoop(
2535 [&expected_times, &loop1, manager_timer](int count) {
2536 EXPECT_EQ(1, count);
2537 expected_times.push_back(loop1->context().monotonic_event_time);
2538
Philipp Schradera6712522023-07-05 20:25:11 -07002539 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002540 },
2541 kInterval, kOffset);
2542 phased_loop->set_name("Test loop");
2543 manager_timer->set_name("Manager timer");
2544
2545 Run();
2546
2547 ASSERT_EQ(2u, expected_times.size());
2548 ASSERT_EQ(expected_times[0] + kInterval + std::chrono::nanoseconds(1),
2549 expected_times[1]);
2550}
2551
2552// Tests that a phased loop responds correctly to having its phase offset
2553// decremented and then being scheduled after a set time, exercising a pattern
2554// where a phased loop's offset is changed while trying to maintain the trigger
2555// at a consistent period.
2556TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleWithEarlierOffset) {
2557 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2558 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2559
2560 auto loop1 = MakePrimary();
2561
2562 std::vector<::aos::monotonic_clock::time_point> expected_times;
2563
2564 PhasedLoopHandler *phased_loop;
2565
2566 bool should_exit = false;
2567 TimerHandler *manager_timer = loop1->AddTimer(
2568 [&phased_loop, &loop1, &should_exit, this, kInterval, kOffset]() {
2569 if (should_exit) {
2570 LOG(INFO) << "Exiting";
2571 this->Exit();
2572 return;
2573 }
2574 // Schedule the next callback to be strictly later than the current time
2575 // + interval / 2, to ensure a consistent frequency.
2576 const aos::monotonic_clock::time_point half_time =
2577 loop1->context().monotonic_event_time + kInterval / 2;
2578 phased_loop->set_interval_and_offset(
2579 kInterval, kOffset - std::chrono::nanoseconds(1), half_time);
2580 phased_loop->Reschedule(half_time);
2581 should_exit = true;
2582 });
2583
2584 phased_loop = loop1->AddPhasedLoop(
2585 [&expected_times, &loop1, manager_timer](int count) {
2586 EXPECT_EQ(1, count);
2587 expected_times.push_back(loop1->context().monotonic_event_time);
2588
Philipp Schradera6712522023-07-05 20:25:11 -07002589 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002590 },
2591 kInterval, kOffset);
2592 phased_loop->set_name("Test loop");
2593 manager_timer->set_name("Manager timer");
2594
2595 Run();
2596
2597 ASSERT_EQ(2u, expected_times.size());
2598 ASSERT_EQ(expected_times[0] + kInterval - std::chrono::nanoseconds(1),
2599 expected_times[1]);
2600}
2601
Austin Schuh39788ff2019-12-01 18:22:57 -08002602// Tests that senders count correctly in the timing report.
2603TEST_P(AbstractEventLoopTest, SenderTimingReport) {
2604 FLAGS_timing_report_ms = 1000;
2605 auto loop1 = MakePrimary();
2606
2607 auto loop2 = Make("watcher_loop");
2608 loop2->MakeWatcher("/test", [](const TestMessage &) {});
2609
2610 auto loop3 = Make();
2611
2612 Fetcher<timing::Report> report_fetcher =
2613 loop3->MakeFetcher<timing::Report>("/aos");
2614 EXPECT_FALSE(report_fetcher.Fetch());
2615
2616 auto sender = loop1->MakeSender<TestMessage>("/test");
2617
James Kuszmaul78514332022-04-06 15:08:34 -07002618 // Sanity check channel frequencies to ensure that we've designed the test
2619 // correctly.
2620 ASSERT_EQ(800, sender.channel()->frequency());
Austin Schuhfff9c3a2023-06-16 18:48:23 -07002621 ASSERT_EQ(2000000000, configuration::ChannelStorageDuration(
2622 loop1->configuration(), sender.channel())
2623 .count());
James Kuszmaul78514332022-04-06 15:08:34 -07002624 constexpr int kMaxAllowedMessages = 800 * 2;
2625 constexpr int kSendMessages = kMaxAllowedMessages * 2;
2626 constexpr int kDroppedMessages = kSendMessages - kMaxAllowedMessages;
2627
Austin Schuh39788ff2019-12-01 18:22:57 -08002628 // Add a timer to actually quit.
2629 auto test_timer = loop1->AddTimer([&sender]() {
James Kuszmaul78514332022-04-06 15:08:34 -07002630 for (int i = 0; i < kSendMessages; ++i) {
Austin Schuh39788ff2019-12-01 18:22:57 -08002631 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2632 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2633 builder.add_value(200 + i);
James Kuszmaul78514332022-04-06 15:08:34 -07002634 if (i < kMaxAllowedMessages) {
2635 msg.CheckOk(msg.Send(builder.Finish()));
2636 } else {
2637 EXPECT_EQ(RawSender::Error::kMessagesSentTooFast,
2638 msg.Send(builder.Finish()));
2639 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002640 }
2641 });
2642
2643 // Quit after 1 timing report, mid way through the next cycle.
2644 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2645
2646 loop1->OnRun([&test_timer, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002647 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1500));
Austin Schuh39788ff2019-12-01 18:22:57 -08002648 });
2649
2650 Run();
2651
Austin Schuh6bae8252021-02-07 22:01:49 -08002652 if (do_timing_reports() == DoTimingReports::kYes) {
2653 // And, since we are here, check that the timing report makes sense.
2654 // Start by looking for our event loop's timing.
2655 FlatbufferDetachedBuffer<timing::Report> primary_report =
2656 FlatbufferDetachedBuffer<timing::Report>::Empty();
2657 while (report_fetcher.FetchNext()) {
Austin Schuh8902fa52021-03-14 22:39:24 -07002658 VLOG(1) << "Report " << FlatbufferToJson(report_fetcher.get());
Austin Schuh6bae8252021-02-07 22:01:49 -08002659 if (report_fetcher->name()->string_view() == "primary") {
2660 primary_report = CopyFlatBuffer(report_fetcher.get());
2661 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002662 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002663
Austin Schuh8902fa52021-03-14 22:39:24 -07002664 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
Austin Schuh6bae8252021-02-07 22:01:49 -08002665
2666 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2667
2668 ASSERT_NE(primary_report.message().senders(), nullptr);
2669 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2670
2671 // Confirm that the sender looks sane.
2672 EXPECT_EQ(
2673 loop1->configuration()
2674 ->channels()
2675 ->Get(primary_report.message().senders()->Get(0)->channel_index())
2676 ->name()
2677 ->string_view(),
2678 "/test");
James Kuszmaul78514332022-04-06 15:08:34 -07002679 EXPECT_EQ(primary_report.message().senders()->Get(0)->count(),
2680 kMaxAllowedMessages);
2681 ASSERT_TRUE(primary_report.message().senders()->Get(0)->has_error_counts());
2682 ASSERT_EQ(
2683 primary_report.message().senders()->Get(0)->error_counts()->size(), 2u);
2684 EXPECT_EQ(
2685 primary_report.message()
2686 .senders()
2687 ->Get(0)
2688 ->error_counts()
2689 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2690 ->count(),
2691 kDroppedMessages)
2692 << aos::FlatbufferToJson(primary_report);
2693 EXPECT_EQ(primary_report.message()
2694 .senders()
2695 ->Get(0)
2696 ->error_counts()
2697 ->Get(static_cast<size_t>(timing::SendError::INVALID_REDZONE))
2698 ->count(),
2699 0);
Austin Schuh6bae8252021-02-07 22:01:49 -08002700
2701 // Confirm that the timing primary_report sender looks sane.
2702 EXPECT_EQ(
2703 loop1->configuration()
2704 ->channels()
2705 ->Get(primary_report.message().senders()->Get(1)->channel_index())
2706 ->name()
2707 ->string_view(),
2708 "/aos");
2709 EXPECT_EQ(primary_report.message().senders()->Get(1)->count(), 1);
2710
2711 ASSERT_NE(primary_report.message().timers(), nullptr);
2712 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2713
2714 // Make sure there are no phased loops or watchers.
2715 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2716 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2717 } else {
2718 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002719 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002720}
2721
James Kuszmaul93abac12022-04-14 15:05:10 -07002722// Tests that the RawSender::Send(void*, size_t) overload tracks things properly
2723// in its timing report.
2724TEST_P(AbstractEventLoopTest, CopySenderTimingReport) {
2725 gflags::FlagSaver flag_saver;
2726 FLAGS_timing_report_ms = 1000;
2727 auto loop1 = Make();
2728 auto loop2 = MakePrimary();
2729
2730 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2731 JsonToFlatbuffer<TestMessage>("{}");
2732
2733 std::unique_ptr<aos::RawSender> sender =
2734 loop2->MakeRawSender(configuration::GetChannel(
2735 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
2736
2737 Fetcher<timing::Report> report_fetcher =
2738 loop1->MakeFetcher<timing::Report>("/aos");
2739 EXPECT_FALSE(report_fetcher.Fetch());
2740
2741 loop2->OnRun([&]() {
2742 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
2743 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2744 RawSender::Error::kOk);
2745 }
2746 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2747 RawSender::Error::kMessagesSentTooFast);
2748 });
2749 // Quit after 1 timing report, mid way through the next cycle.
2750 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
2751
2752 Run();
2753
2754 if (do_timing_reports() == DoTimingReports::kYes) {
2755 // Check that the sent too fast actually got recorded by the timing report.
2756 FlatbufferDetachedBuffer<timing::Report> primary_report =
2757 FlatbufferDetachedBuffer<timing::Report>::Empty();
2758 while (report_fetcher.FetchNext()) {
2759 if (report_fetcher->name()->string_view() == "primary") {
2760 primary_report = CopyFlatBuffer(report_fetcher.get());
2761 }
2762 }
2763
2764 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2765
2766 ASSERT_NE(primary_report.message().senders(), nullptr);
2767 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2768 EXPECT_EQ(
2769 primary_report.message()
2770 .senders()
2771 ->Get(0)
2772 ->error_counts()
2773 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2774 ->count(),
2775 1);
2776 }
2777}
2778
Austin Schuhe0ab4de2023-05-03 08:05:08 -07002779// Tests that the RawSender::Send(SharedSpan) overload works.
2780TEST_P(AbstractEventLoopTest, SharedSenderTimingReport) {
2781 gflags::FlagSaver flag_saver;
2782 FLAGS_timing_report_ms = 1000;
2783 auto loop1 = Make();
2784 auto loop2 = MakePrimary();
2785
2786 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2787 JsonToFlatbuffer<TestMessage>("{}");
2788
2789 std::unique_ptr<aos::RawSender> sender =
2790 loop2->MakeRawSender(configuration::GetChannel(
2791 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
2792
2793 Fetcher<timing::Report> report_fetcher =
2794 loop1->MakeFetcher<timing::Report>("/aos");
2795 EXPECT_FALSE(report_fetcher.Fetch());
2796
2797 loop2->OnRun([&]() {
2798 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
2799 auto shared_span = MakeSharedSpan(kMessage.span().size());
2800 memcpy(shared_span.second.data(), kMessage.span().data(),
2801 kMessage.span().size());
2802 EXPECT_EQ(sender->Send(std::move(shared_span.first)),
2803 RawSender::Error::kOk);
2804 }
2805 auto shared_span = MakeSharedSpan(kMessage.span().size());
2806 memcpy(shared_span.second.data(), kMessage.span().data(),
2807 kMessage.span().size());
2808 EXPECT_EQ(sender->Send(std::move(shared_span.first)),
2809 RawSender::Error::kMessagesSentTooFast);
2810 });
2811 // Quit after 1 timing report, mid way through the next cycle.
2812 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
2813
2814 Run();
2815
2816 if (do_timing_reports() == DoTimingReports::kYes) {
2817 // Check that the sent too fast actually got recorded by the timing report.
2818 FlatbufferDetachedBuffer<timing::Report> primary_report =
2819 FlatbufferDetachedBuffer<timing::Report>::Empty();
2820 while (report_fetcher.FetchNext()) {
2821 if (report_fetcher->name()->string_view() == "primary") {
2822 primary_report = CopyFlatBuffer(report_fetcher.get());
2823 }
2824 }
2825
2826 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2827
2828 ASSERT_NE(primary_report.message().senders(), nullptr);
2829 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2830 EXPECT_EQ(
2831 primary_report.message()
2832 .senders()
2833 ->Get(0)
2834 ->error_counts()
2835 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2836 ->count(),
2837 1);
2838 }
2839}
2840
Austin Schuh39788ff2019-12-01 18:22:57 -08002841// Tests that senders count correctly in the timing report.
2842TEST_P(AbstractEventLoopTest, WatcherTimingReport) {
2843 FLAGS_timing_report_ms = 1000;
2844 auto loop1 = MakePrimary();
2845 loop1->MakeWatcher("/test", [](const TestMessage &) {});
2846
2847 auto loop2 = Make("sender_loop");
2848
2849 auto loop3 = Make();
2850
2851 Fetcher<timing::Report> report_fetcher =
2852 loop3->MakeFetcher<timing::Report>("/aos");
2853 EXPECT_FALSE(report_fetcher.Fetch());
2854
2855 auto sender = loop2->MakeSender<TestMessage>("/test");
2856
2857 // Add a timer to actually quit.
2858 auto test_timer = loop1->AddTimer([&sender]() {
2859 for (int i = 0; i < 10; ++i) {
2860 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2861 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2862 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002863 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002864 }
2865 });
2866
2867 // Quit after 1 timing report, mid way through the next cycle.
2868 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2869
2870 loop1->OnRun([&test_timer, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002871 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1500));
Austin Schuh39788ff2019-12-01 18:22:57 -08002872 });
2873
2874 Run();
2875
Austin Schuh6bae8252021-02-07 22:01:49 -08002876 if (do_timing_reports() == DoTimingReports::kYes) {
2877 // And, since we are here, check that the timing report makes sense.
2878 // Start by looking for our event loop's timing.
2879 FlatbufferDetachedBuffer<timing::Report> primary_report =
2880 FlatbufferDetachedBuffer<timing::Report>::Empty();
2881 while (report_fetcher.FetchNext()) {
2882 LOG(INFO) << "Report " << FlatbufferToJson(report_fetcher.get());
2883 if (report_fetcher->name()->string_view() == "primary") {
2884 primary_report = CopyFlatBuffer(report_fetcher.get());
2885 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002886 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002887
2888 // Check the watcher report.
2889 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2890
2891 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2892
2893 // Just the timing report timer.
2894 ASSERT_NE(primary_report.message().timers(), nullptr);
2895 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2896
2897 // No phased loops
2898 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2899
2900 ASSERT_NE(primary_report.message().watchers(), nullptr);
2901 ASSERT_EQ(primary_report.message().watchers()->size(), 1);
2902 EXPECT_EQ(primary_report.message().watchers()->Get(0)->count(), 10);
2903 } else {
2904 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002905 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002906}
2907
2908// Tests that fetchers count correctly in the timing report.
2909TEST_P(AbstractEventLoopTest, FetcherTimingReport) {
2910 FLAGS_timing_report_ms = 1000;
2911 auto loop1 = MakePrimary();
2912 auto loop2 = Make("sender_loop");
2913
2914 auto loop3 = Make();
2915
2916 Fetcher<timing::Report> report_fetcher =
2917 loop3->MakeFetcher<timing::Report>("/aos");
2918 EXPECT_FALSE(report_fetcher.Fetch());
2919
2920 auto sender = loop2->MakeSender<TestMessage>("/test");
2921 auto fetcher1 = loop1->MakeFetcher<TestMessage>("/test");
2922 auto fetcher2 = loop1->MakeFetcher<TestMessage>("/test");
2923 fetcher1.Fetch();
2924 fetcher2.Fetch();
2925
2926 // Add a timer to actually quit.
2927 auto test_timer = loop1->AddTimer([&sender]() {
2928 for (int i = 0; i < 10; ++i) {
2929 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2930 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2931 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002932 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002933 }
2934 });
2935
2936 auto test_timer2 = loop1->AddTimer([&fetcher1, &fetcher2]() {
2937 fetcher1.Fetch();
2938 while (fetcher2.FetchNext()) {
2939 }
2940 });
2941
2942 // Quit after 1 timing report, mid way through the next cycle.
2943 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2944
2945 loop1->OnRun([test_timer, test_timer2, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002946 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1400));
2947 test_timer2->Schedule(loop1->monotonic_now() + chrono::milliseconds(1600));
Austin Schuh39788ff2019-12-01 18:22:57 -08002948 });
2949
2950 Run();
2951
Austin Schuh6bae8252021-02-07 22:01:49 -08002952 if (do_timing_reports() == DoTimingReports::kYes) {
2953 // And, since we are here, check that the timing report makes sense.
2954 // Start by looking for our event loop's timing.
2955 FlatbufferDetachedBuffer<timing::Report> primary_report =
2956 FlatbufferDetachedBuffer<timing::Report>::Empty();
2957 while (report_fetcher.FetchNext()) {
2958 if (report_fetcher->name()->string_view() == "primary") {
2959 primary_report = CopyFlatBuffer(report_fetcher.get());
2960 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002961 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002962
2963 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2964
2965 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2966
2967 ASSERT_NE(primary_report.message().senders(), nullptr);
2968 EXPECT_EQ(primary_report.message().senders()->size(), 2);
2969
2970 ASSERT_NE(primary_report.message().timers(), nullptr);
2971 EXPECT_EQ(primary_report.message().timers()->size(), 4);
2972
2973 // Make sure there are no phased loops or watchers.
2974 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2975 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2976
2977 // Now look at the fetchrs.
2978 ASSERT_NE(primary_report.message().fetchers(), nullptr);
2979 ASSERT_EQ(primary_report.message().fetchers()->size(), 2);
2980
2981 EXPECT_EQ(primary_report.message().fetchers()->Get(0)->count(), 1);
2982 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->average(),
2983 0.1);
2984 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->min(),
2985 0.1);
2986 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->max(),
2987 0.1);
2988 EXPECT_EQ(primary_report.message()
2989 .fetchers()
2990 ->Get(0)
2991 ->latency()
2992 ->standard_deviation(),
2993 0.0);
2994
2995 EXPECT_EQ(primary_report.message().fetchers()->Get(1)->count(), 10);
2996 } else {
2997 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002998 }
Austin Schuh52d325c2019-06-23 18:59:06 -07002999}
3000
Austin Schuh67420a42019-12-21 21:55:04 -08003001// Tests that a raw watcher and raw fetcher can receive messages from a raw
3002// sender without messing up offsets.
3003TEST_P(AbstractEventLoopTest, RawBasic) {
3004 auto loop1 = Make();
3005 auto loop2 = MakePrimary();
3006 auto loop3 = Make();
3007
Austin Schuha9df9ad2021-06-16 14:49:39 -07003008 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3009 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuh67420a42019-12-21 21:55:04 -08003010
3011 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003012 loop1->MakeRawSender(configuration::GetChannel(
3013 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08003014
3015 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003016 loop3->MakeRawFetcher(configuration::GetChannel(
3017 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08003018
Austin Schuha9df9ad2021-06-16 14:49:39 -07003019 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07003020 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
3021 RawSender::Error::kOk);
Austin Schuha9df9ad2021-06-16 14:49:39 -07003022 });
Austin Schuh67420a42019-12-21 21:55:04 -08003023
3024 bool happened = false;
3025 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08003026 configuration::GetChannel(loop2->configuration(), "/test",
3027 "aos.TestMessage", "", nullptr),
Austin Schuha9df9ad2021-06-16 14:49:39 -07003028 [this, &kMessage, &fetcher, &happened](const Context &context,
3029 const void *message) {
Austin Schuh67420a42019-12-21 21:55:04 -08003030 happened = true;
Austin Schuha9df9ad2021-06-16 14:49:39 -07003031 EXPECT_EQ(
3032 kMessage.span(),
3033 absl::Span<const uint8_t>(
3034 reinterpret_cast<const uint8_t *>(message), context.size));
3035 EXPECT_EQ(message, context.data);
Austin Schuh67420a42019-12-21 21:55:04 -08003036
3037 ASSERT_TRUE(fetcher->Fetch());
3038
Austin Schuha9df9ad2021-06-16 14:49:39 -07003039 EXPECT_EQ(kMessage.span(),
3040 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
3041 fetcher->context().data),
3042 fetcher->context().size));
Austin Schuh67420a42019-12-21 21:55:04 -08003043
3044 this->Exit();
3045 });
3046
3047 EXPECT_FALSE(happened);
3048 Run();
3049 EXPECT_TRUE(happened);
3050}
3051
Austin Schuhad154822019-12-27 15:45:13 -08003052// Tests that a raw watcher and raw fetcher can receive messages from a raw
Brian Silvermanbf889922021-11-10 12:41:57 -08003053// sender without messing up offsets, using the RawSpan overload.
3054TEST_P(AbstractEventLoopTest, RawBasicSharedSpan) {
3055 auto loop1 = Make();
3056 auto loop2 = MakePrimary();
3057 auto loop3 = Make();
3058
3059 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3060 JsonToFlatbuffer<TestMessage>("{}");
3061
3062 std::unique_ptr<aos::RawSender> sender =
3063 loop1->MakeRawSender(configuration::GetChannel(
3064 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
3065
3066 std::unique_ptr<aos::RawFetcher> fetcher =
3067 loop3->MakeRawFetcher(configuration::GetChannel(
3068 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
3069
3070 loop2->OnRun([&]() {
Austin Schuhe0ab4de2023-05-03 08:05:08 -07003071 auto shared_span = MakeSharedSpan(kMessage.span().size());
3072 memcpy(shared_span.second.data(), kMessage.span().data(),
3073 kMessage.span().size());
3074 sender->CheckOk(sender->Send(std::move(shared_span.first)));
Brian Silvermanbf889922021-11-10 12:41:57 -08003075 });
3076
3077 bool happened = false;
3078 loop2->MakeRawWatcher(
3079 configuration::GetChannel(loop2->configuration(), "/test",
3080 "aos.TestMessage", "", nullptr),
3081 [this, &kMessage, &fetcher, &happened](const Context &context,
3082 const void *message) {
3083 happened = true;
3084 EXPECT_EQ(
3085 kMessage.span(),
3086 absl::Span<const uint8_t>(
3087 reinterpret_cast<const uint8_t *>(message), context.size));
3088 EXPECT_EQ(message, context.data);
3089
3090 ASSERT_TRUE(fetcher->Fetch());
3091
3092 EXPECT_EQ(kMessage.span(),
3093 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
3094 fetcher->context().data),
3095 fetcher->context().size));
3096
3097 this->Exit();
3098 });
3099
3100 EXPECT_FALSE(happened);
3101 Run();
3102 EXPECT_TRUE(happened);
3103}
3104
3105// Tests that a raw watcher and raw fetcher can receive messages from a raw
Austin Schuhad154822019-12-27 15:45:13 -08003106// sender with remote times filled out.
3107TEST_P(AbstractEventLoopTest, RawRemoteTimes) {
3108 auto loop1 = Make();
3109 auto loop2 = MakePrimary();
3110 auto loop3 = Make();
3111
Austin Schuha9df9ad2021-06-16 14:49:39 -07003112 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3113 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08003114
3115 const aos::monotonic_clock::time_point monotonic_remote_time =
3116 aos::monotonic_clock::time_point(chrono::seconds(1501));
3117 const aos::realtime_clock::time_point realtime_remote_time =
3118 aos::realtime_clock::time_point(chrono::seconds(3132));
Austin Schuhb5c6f972021-03-14 21:53:07 -07003119 const uint32_t remote_queue_index = 0x254971;
Austin Schuha9012be2021-07-21 15:19:11 -07003120 const UUID source_boot_uuid = UUID::Random();
Austin Schuhad154822019-12-27 15:45:13 -08003121
3122 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003123 loop1->MakeRawSender(configuration::GetChannel(
3124 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08003125
3126 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003127 loop3->MakeRawFetcher(configuration::GetChannel(
3128 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08003129
3130 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07003131 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size(),
3132 monotonic_remote_time, realtime_remote_time,
3133 remote_queue_index, source_boot_uuid),
3134 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08003135 });
3136
3137 bool happened = false;
3138 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08003139 configuration::GetChannel(loop2->configuration(), "/test",
3140 "aos.TestMessage", "", nullptr),
Austin Schuha9012be2021-07-21 15:19:11 -07003141 [this, monotonic_remote_time, realtime_remote_time, source_boot_uuid,
Austin Schuhb5c6f972021-03-14 21:53:07 -07003142 remote_queue_index, &fetcher,
3143 &happened](const Context &context, const void * /*message*/) {
Austin Schuhad154822019-12-27 15:45:13 -08003144 happened = true;
3145 EXPECT_EQ(monotonic_remote_time, context.monotonic_remote_time);
3146 EXPECT_EQ(realtime_remote_time, context.realtime_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07003147 EXPECT_EQ(source_boot_uuid, context.source_boot_uuid);
Austin Schuhb5c6f972021-03-14 21:53:07 -07003148 EXPECT_EQ(remote_queue_index, context.remote_queue_index);
Austin Schuhad154822019-12-27 15:45:13 -08003149
3150 ASSERT_TRUE(fetcher->Fetch());
3151 EXPECT_EQ(monotonic_remote_time,
3152 fetcher->context().monotonic_remote_time);
3153 EXPECT_EQ(realtime_remote_time,
3154 fetcher->context().realtime_remote_time);
3155
3156 this->Exit();
3157 });
3158
3159 EXPECT_FALSE(happened);
3160 Run();
3161 EXPECT_TRUE(happened);
3162}
3163
3164// Tests that a raw sender fills out sent data.
3165TEST_P(AbstractEventLoopTest, RawSenderSentData) {
3166 auto loop1 = MakePrimary();
3167
Austin Schuha9df9ad2021-06-16 14:49:39 -07003168 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3169 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08003170
3171 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003172 loop1->MakeRawSender(configuration::GetChannel(
3173 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08003174
Tyler Chatow67ddb032020-01-12 14:30:04 -08003175 const aos::monotonic_clock::time_point monotonic_now = loop1->monotonic_now();
3176 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08003177
milind1f1dca32021-07-03 13:50:07 -07003178 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
3179 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08003180
3181 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
3182 EXPECT_LE(sender->monotonic_sent_time(),
3183 monotonic_now + chrono::milliseconds(100));
3184 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
3185 EXPECT_LE(sender->realtime_sent_time(),
3186 realtime_now + chrono::milliseconds(100));
3187 EXPECT_EQ(sender->sent_queue_index(), 0u);
3188
milind1f1dca32021-07-03 13:50:07 -07003189 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
3190 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08003191
3192 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
3193 EXPECT_LE(sender->monotonic_sent_time(),
3194 monotonic_now + chrono::milliseconds(100));
3195 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
3196 EXPECT_LE(sender->realtime_sent_time(),
3197 realtime_now + chrono::milliseconds(100));
3198 EXPECT_EQ(sender->sent_queue_index(), 1u);
3199}
3200
Austin Schuh217a9782019-12-21 23:02:50 -08003201// Tests that not setting up nodes results in no node.
3202TEST_P(AbstractEventLoopTest, NoNode) {
3203 auto loop1 = Make();
3204 auto loop2 = MakePrimary();
3205
3206 EXPECT_EQ(loop1->node(), nullptr);
3207 EXPECT_EQ(loop2->node(), nullptr);
3208}
3209
3210// Tests that setting up nodes results in node being set.
3211TEST_P(AbstractEventLoopTest, Node) {
3212 EnableNodes("me");
3213
3214 auto loop1 = Make();
3215 auto loop2 = MakePrimary();
3216
3217 EXPECT_NE(loop1->node(), nullptr);
3218 EXPECT_NE(loop2->node(), nullptr);
3219}
3220
3221// Tests that watchers work with a node setup.
3222TEST_P(AbstractEventLoopTest, NodeWatcher) {
3223 EnableNodes("me");
3224
3225 auto loop1 = Make();
3226 auto loop2 = Make();
3227 loop1->MakeWatcher("/test", [](const TestMessage &) {});
Tyler Chatow67ddb032020-01-12 14:30:04 -08003228 loop2->MakeRawWatcher(
3229 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
3230 nullptr),
3231 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08003232}
3233
Brian Silverman454bc112020-03-05 14:21:25 -08003234// Tests that no-arg watchers work with a node setup.
3235TEST_P(AbstractEventLoopTest, NodeNoArgWatcher) {
3236 EnableNodes("me");
3237
3238 auto loop1 = Make();
3239 auto loop2 = Make();
3240 loop1->MakeWatcher("/test", [](const TestMessage &) {});
3241 loop2->MakeRawNoArgWatcher(
3242 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
3243 nullptr),
3244 [](const Context &) {});
3245}
3246
Austin Schuh217a9782019-12-21 23:02:50 -08003247// Tests that fetcher work with a node setup.
3248TEST_P(AbstractEventLoopTest, NodeFetcher) {
3249 EnableNodes("me");
3250 auto loop1 = Make();
3251
3252 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
Tyler Chatow67ddb032020-01-12 14:30:04 -08003253 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
3254 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08003255}
3256
3257// Tests that sender work with a node setup.
3258TEST_P(AbstractEventLoopTest, NodeSender) {
3259 EnableNodes("me");
3260 auto loop1 = Make();
3261
3262 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
3263}
3264
Austin Schuhcc6070c2020-10-10 20:25:56 -07003265// Tests that a non-realtime event loop timer is marked non-realtime.
3266TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopTimer) {
3267 auto loop1 = MakePrimary();
3268
3269 // Add a timer to actually quit.
3270 auto test_timer = loop1->AddTimer([this]() {
3271 CheckNotRealtime();
3272 this->Exit();
3273 });
3274
3275 loop1->OnRun([&test_timer, &loop1]() {
3276 CheckNotRealtime();
Philipp Schradera6712522023-07-05 20:25:11 -07003277 test_timer->Schedule(loop1->monotonic_now(),
3278 ::std::chrono::milliseconds(100));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003279 });
3280
3281 Run();
3282}
3283
3284// Tests that a realtime event loop timer is marked realtime.
Austin Schuh9b1d6282022-06-10 17:03:21 -07003285TEST_P(AbstractEventLoopTest, RealtimeSend) {
3286 auto loop1 = MakePrimary();
3287
3288 loop1->SetRuntimeRealtimePriority(1);
3289
3290 auto sender = loop1->MakeSender<TestMessage>("/test2");
3291
3292 loop1->OnRun([&]() {
3293 CheckRealtime();
3294
3295 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3296 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
3297 builder.add_value(200);
3298 msg.CheckOk(msg.Send(builder.Finish()));
3299
3300 this->Exit();
3301 });
3302
3303 Run();
3304}
3305
3306// Tests that a realtime event loop timer is marked realtime.
Austin Schuhcc6070c2020-10-10 20:25:56 -07003307TEST_P(AbstractEventLoopTest, RealtimeEventLoopTimer) {
3308 auto loop1 = MakePrimary();
3309
3310 loop1->SetRuntimeRealtimePriority(1);
3311
3312 // Add a timer to actually quit.
3313 auto test_timer = loop1->AddTimer([this]() {
3314 CheckRealtime();
3315 this->Exit();
3316 });
3317
3318 loop1->OnRun([&test_timer, &loop1]() {
3319 CheckRealtime();
Philipp Schradera6712522023-07-05 20:25:11 -07003320 test_timer->Schedule(loop1->monotonic_now(),
3321 ::std::chrono::milliseconds(100));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003322 });
3323
3324 Run();
3325}
3326
3327// Tests that a non-realtime event loop phased loop is marked non-realtime.
3328TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopPhasedLoop) {
3329 auto loop1 = MakePrimary();
3330
3331 // Add a timer to actually quit.
3332 loop1->AddPhasedLoop(
3333 [this](int) {
3334 CheckNotRealtime();
3335 this->Exit();
3336 },
3337 chrono::seconds(1), chrono::seconds(0));
3338
3339 Run();
3340}
3341
3342// Tests that a realtime event loop phased loop is marked realtime.
3343TEST_P(AbstractEventLoopTest, RealtimeEventLoopPhasedLoop) {
3344 auto loop1 = MakePrimary();
3345
3346 loop1->SetRuntimeRealtimePriority(1);
3347
3348 // Add a timer to actually quit.
3349 loop1->AddPhasedLoop(
3350 [this](int) {
3351 CheckRealtime();
3352 this->Exit();
3353 },
3354 chrono::seconds(1), chrono::seconds(0));
3355
3356 Run();
3357}
3358
3359// Tests that a non-realtime event loop watcher is marked non-realtime.
3360TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopWatcher) {
3361 auto loop1 = MakePrimary();
3362 auto loop2 = Make();
3363
3364 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
3365
3366 loop1->OnRun([&]() {
3367 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3368 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07003369 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003370 });
3371
3372 loop1->MakeWatcher("/test", [&](const TestMessage &) {
3373 CheckNotRealtime();
3374 this->Exit();
3375 });
3376
3377 Run();
3378}
3379
3380// Tests that a realtime event loop watcher is marked realtime.
3381TEST_P(AbstractEventLoopTest, RealtimeEventLoopWatcher) {
3382 auto loop1 = MakePrimary();
3383 auto loop2 = Make();
3384
3385 loop1->SetRuntimeRealtimePriority(1);
3386
3387 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
3388
3389 loop1->OnRun([&]() {
3390 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3391 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07003392 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003393 });
3394
3395 loop1->MakeWatcher("/test", [&](const TestMessage &) {
3396 CheckRealtime();
3397 this->Exit();
3398 });
3399
3400 Run();
3401}
3402
Austin Schuha9012be2021-07-21 15:19:11 -07003403// Tests that event loop's context's monotonic time is set to a value on OnRun.
3404TEST_P(AbstractEventLoopTest, SetContextOnRun) {
3405 auto loop = MakePrimary();
3406
Austin Schuh0debde12022-08-17 16:25:17 -07003407 EXPECT_EQ(loop->context().monotonic_event_time, monotonic_clock::min_time);
3408 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3409 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3410 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3411 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3412 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
3413 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
3414 EXPECT_EQ(loop->context().size, 0u);
3415 EXPECT_EQ(loop->context().data, nullptr);
3416 EXPECT_EQ(loop->context().buffer_index, -1);
3417
Austin Schuha9012be2021-07-21 15:19:11 -07003418 // We want to check that monotonic event time is before monotonic now
3419 // called inside of callback, but after time point obtained callback.
3420 aos::monotonic_clock::time_point monotonic_event_time_on_run;
3421
3422 loop->OnRun([&]() {
3423 monotonic_event_time_on_run = loop->context().monotonic_event_time;
3424 EXPECT_LE(monotonic_event_time_on_run, loop->monotonic_now());
3425 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3426 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3427 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3428 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3429 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
Austin Schuh0debde12022-08-17 16:25:17 -07003430 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
Austin Schuha9012be2021-07-21 15:19:11 -07003431 EXPECT_EQ(loop->context().size, 0u);
3432 EXPECT_EQ(loop->context().data, nullptr);
3433 EXPECT_EQ(loop->context().buffer_index, -1);
3434 });
3435
3436 EndEventLoop(loop.get(), ::std::chrono::milliseconds(200));
3437
3438 const aos::monotonic_clock::time_point before_run_time =
3439 loop->monotonic_now();
3440 Run();
3441 EXPECT_GE(monotonic_event_time_on_run, before_run_time);
Austin Schuh0debde12022-08-17 16:25:17 -07003442
3443 EXPECT_EQ(loop->context().monotonic_event_time, monotonic_clock::min_time);
3444 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3445 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3446 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3447 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3448 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
3449 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
3450 EXPECT_EQ(loop->context().size, 0u);
3451 EXPECT_EQ(loop->context().data, nullptr);
3452 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuha9012be2021-07-21 15:19:11 -07003453}
3454
Austin Schuh217a9782019-12-21 23:02:50 -08003455// Tests that watchers fail when created on the wrong node.
3456TEST_P(AbstractEventLoopDeathTest, NodeWatcher) {
3457 EnableNodes("them");
3458
3459 auto loop1 = Make();
3460 auto loop2 = Make();
3461 EXPECT_DEATH({ loop1->MakeWatcher("/test", [](const TestMessage &) {}); },
3462 "node");
3463 EXPECT_DEATH(
3464 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08003465 loop2->MakeRawWatcher(
3466 configuration::GetChannel(configuration(), "/test",
3467 "aos.TestMessage", "", nullptr),
3468 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08003469 },
3470 "node");
Brian Silverman454bc112020-03-05 14:21:25 -08003471 EXPECT_DEATH({ loop1->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
3472 "node");
3473 EXPECT_DEATH(
3474 {
3475 loop2->MakeRawNoArgWatcher(
3476 configuration::GetChannel(configuration(), "/test",
3477 "aos.TestMessage", "", nullptr),
3478 [](const Context &) {});
3479 },
3480 "node");
Austin Schuh217a9782019-12-21 23:02:50 -08003481}
3482
3483// Tests that fetchers fail when created on the wrong node.
3484TEST_P(AbstractEventLoopDeathTest, NodeFetcher) {
3485 EnableNodes("them");
3486 auto loop1 = Make();
3487
3488 EXPECT_DEATH({ auto fetcher = loop1->MakeFetcher<TestMessage>("/test"); },
3489 "node");
3490 EXPECT_DEATH(
3491 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08003492 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
3493 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08003494 },
3495 "node");
3496}
3497
3498// Tests that senders fail when created on the wrong node.
3499TEST_P(AbstractEventLoopDeathTest, NodeSender) {
3500 EnableNodes("them");
3501 auto loop1 = Make();
3502
3503 EXPECT_DEATH(
3504 {
3505 aos::Sender<TestMessage> sender =
3506 loop1->MakeSender<TestMessage>("/test");
3507 },
3508 "node");
3509
3510 // Note: Creating raw senders is always supported. Right now, this lets us
3511 // use them to create message_gateway.
3512}
3513
Brian Silverman341b57e2020-06-23 16:23:18 -07003514// Tests creating multiple Builders from a single Sender at the same time.
3515TEST_P(AbstractEventLoopDeathTest, MultipleBuilders) {
3516 auto loop1 = Make();
3517 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
3518
3519 { auto builder = sender.MakeBuilder(); }
3520 {
3521 auto builder = sender.MakeBuilder();
3522 builder.MakeBuilder<TestMessage>().Finish();
3523 }
3524 {
3525 // Creating this after the first one was destroyed should be fine.
3526 auto builder = sender.MakeBuilder();
3527 builder.MakeBuilder<TestMessage>().Finish();
3528 // But not a second one.
3529 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
James Kuszmaulb1c11052023-11-06 13:20:53 -08003530 "May not have multiple active allocators");
Brian Silverman341b57e2020-06-23 16:23:18 -07003531 }
3532
3533 FlatbufferDetachedBuffer<TestMessage> detached =
3534 flatbuffers::DetachedBuffer();
3535 {
3536 auto builder = sender.MakeBuilder();
3537 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
3538 }
3539 {
3540 // This is the second one, after the detached one, so it should fail.
3541 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
James Kuszmaulb1c11052023-11-06 13:20:53 -08003542 "May not have multiple active allocators");
Brian Silverman341b57e2020-06-23 16:23:18 -07003543 }
3544
3545 // Clear the detached one, and then we should be able to create another.
3546 detached = flatbuffers::DetachedBuffer();
3547 {
3548 auto builder = sender.MakeBuilder();
3549 builder.MakeBuilder<TestMessage>().Finish();
3550 }
3551
3552 // And then detach another one.
3553 {
3554 auto builder = sender.MakeBuilder();
3555 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
3556 }
3557}
3558
3559// Tests sending a buffer detached from a different builder.
3560TEST_P(AbstractEventLoopDeathTest, WrongDetachedBuffer) {
3561 auto loop1 = Make();
3562 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
3563 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
3564
3565 auto builder = sender1.MakeBuilder();
3566 FlatbufferDetachedBuffer<TestMessage> detached =
3567 builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
milind1f1dca32021-07-03 13:50:07 -07003568 EXPECT_DEATH(sender2.CheckOk(sender2.SendDetached(std::move(detached))),
Brian Silverman341b57e2020-06-23 16:23:18 -07003569 "May only send the buffer detached from this Sender");
3570}
3571
James Kuszmaul762e8692023-07-31 14:57:53 -07003572// Tests that senders fail when created on the wrong node.
3573TEST_P(AbstractEventLoopDeathTest, SetVersionWhileRunning) {
3574 auto loop1 = MakePrimary();
3575
3576 loop1->OnRun([&loop1, this]() {
3577 EXPECT_DEATH({ loop1->SetVersionString("abcdef"); },
3578 "timing report while running");
3579 Exit();
3580 });
3581
3582 Run();
3583}
3584
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003585int TestChannelFrequency(EventLoop *event_loop) {
3586 return event_loop->GetChannel<TestMessage>("/test")->frequency();
3587}
3588
3589int TestChannelQueueSize(EventLoop *event_loop) {
Austin Schuhfff9c3a2023-06-16 18:48:23 -07003590 return configuration::QueueSize(event_loop->configuration(),
3591 event_loop->GetChannel<TestMessage>("/test"));
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003592}
3593
3594RawSender::Error SendTestMessage(aos::Sender<TestMessage> &sender) {
3595 aos::Sender<TestMessage>::Builder builder = sender.MakeBuilder();
3596 TestMessage::Builder test_message_builder =
3597 builder.MakeBuilder<TestMessage>();
3598 test_message_builder.add_value(0);
3599 return builder.Send(test_message_builder.Finish());
3600}
3601
3602// Test that sending messages too fast returns
3603// RawSender::Error::kMessagesSentTooFast.
3604TEST_P(AbstractEventLoopTest, SendingMessagesTooFast) {
3605 auto event_loop = MakePrimary();
Austin Schuh63756be2024-02-05 19:51:20 -08003606 event_loop->SetRuntimeRealtimePriority(5);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003607
3608 auto sender = event_loop->MakeSender<TestMessage>("/test");
3609
3610 // Send one message in the beginning, then wait until the
3611 // channel_storage_duration is almost done and start sending messages rapidly,
3612 // having some come in the next chanel_storage_duration. The queue_size is
3613 // 1600, so the 1601st message will be the last valid one (the initial message
3614 // having being sent more than a channel_storage_duration ago), and trying to
3615 // send the 1602nd message should return
3616 // RawSender::Error::kMessagesSentTooFast.
3617 EXPECT_EQ(SendTestMessage(sender), RawSender::Error::kOk);
3618 int msgs_sent = 1;
3619 const int queue_size = TestChannelQueueSize(event_loop.get());
3620
Austin Schuh63756be2024-02-05 19:51:20 -08003621 const int messages_per_ms = 2;
3622 const auto kRepeatOffset = std::chrono::milliseconds(10);
3623 const auto base_offset =
3624 configuration::ChannelStorageDuration(event_loop->configuration(),
3625 sender.channel()) -
3626 (std::chrono::milliseconds(1) * (queue_size / 2) / messages_per_ms);
3627
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003628 const auto timer = event_loop->AddTimer([&]() {
Austin Schuh63756be2024-02-05 19:51:20 -08003629 // Send in bursts to reduce scheduler load to make the test more
3630 // reproducible.
3631 for (int i = 0; i < messages_per_ms * kRepeatOffset.count(); ++i) {
3632 const bool done = (msgs_sent == queue_size + 1);
3633 ASSERT_EQ(SendTestMessage(sender),
3634 done ? RawSender::Error::kMessagesSentTooFast
3635 : RawSender::Error::kOk);
3636 msgs_sent++;
3637 if (done) {
3638 Exit();
3639 return;
3640 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003641 }
3642 });
3643
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003644 event_loop->OnRun([&event_loop, &timer, &base_offset, &kRepeatOffset]() {
Philipp Schradera6712522023-07-05 20:25:11 -07003645 timer->Schedule(event_loop->monotonic_now() + base_offset, kRepeatOffset);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003646 });
3647
3648 Run();
3649}
3650
3651// Tests that we are able to send messages successfully after sending messages
3652// too fast and waiting while continuously attempting to send messages.
3653// Also tests that SendFailureCounter is working correctly in this
3654// situation
3655TEST_P(AbstractEventLoopTest, SendingAfterSendingTooFast) {
3656 auto event_loop = MakePrimary();
Austin Schuh63756be2024-02-05 19:51:20 -08003657 event_loop->SetRuntimeRealtimePriority(5);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003658
3659 auto sender = event_loop->MakeSender<TestMessage>("/test");
3660
Austin Schuh0e96d372023-05-08 10:10:21 -07003661 // We are sending bunches of messages at 100 Hz, so we will be sending too
3662 // fast after queue_size (800) ms. After this, keep sending messages, and
3663 // exactly a channel storage duration (2s) after we send the first message we
3664 // should be able to successfully send a message.
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003665
Austin Schuh0e96d372023-05-08 10:10:21 -07003666 const std::chrono::milliseconds kInterval = std::chrono::milliseconds(10);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003667 const monotonic_clock::duration channel_storage_duration =
Austin Schuhfff9c3a2023-06-16 18:48:23 -07003668 configuration::ChannelStorageDuration(event_loop->configuration(),
3669 sender.channel());
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003670 const int queue_size = TestChannelQueueSize(event_loop.get());
3671
3672 int msgs_sent = 0;
3673 SendFailureCounter counter;
3674 auto start = monotonic_clock::min_time;
3675
3676 event_loop->AddPhasedLoop(
Austin Schuh0e96d372023-05-08 10:10:21 -07003677 [&](int elapsed_cycles) {
3678 // The queue is setup for 800 messages/sec. We want to fill that up at
3679 // a rate of 2000 messages/sec so we make sure we fill it up.
3680 for (int i = 0; i < 2 * kInterval.count() * elapsed_cycles; ++i) {
3681 const auto actual_err = SendTestMessage(sender);
3682 const bool done_waiting = (start != monotonic_clock::min_time &&
3683 sender.monotonic_sent_time() >=
3684 (start + channel_storage_duration));
3685 const auto expected_err =
3686 (msgs_sent < queue_size || done_waiting
3687 ? RawSender::Error::kOk
3688 : RawSender::Error::kMessagesSentTooFast);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003689
Austin Schuh0e96d372023-05-08 10:10:21 -07003690 if (start == monotonic_clock::min_time) {
3691 start = sender.monotonic_sent_time();
3692 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003693
Austin Schuh0e96d372023-05-08 10:10:21 -07003694 ASSERT_EQ(actual_err, expected_err);
3695 counter.Count(actual_err);
3696 msgs_sent++;
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003697
Austin Schuh0e96d372023-05-08 10:10:21 -07003698 EXPECT_EQ(counter.failures(),
3699 msgs_sent <= queue_size
3700 ? 0
3701 : (msgs_sent - queue_size) -
3702 (actual_err == RawSender::Error::kOk ? 1 : 0));
3703 EXPECT_EQ(counter.just_failed(), actual_err != RawSender::Error::kOk);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003704
Austin Schuh0e96d372023-05-08 10:10:21 -07003705 if (done_waiting) {
3706 Exit();
3707 return;
3708 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003709 }
3710 },
3711 kInterval);
3712 Run();
3713}
3714
3715// Tests that RawSender::Error::kMessagesSentTooFast is returned
3716// when messages are sent too fast from senders in different loops
3717TEST_P(AbstractEventLoopTest, SendingTooFastWithMultipleLoops) {
3718 auto loop1 = MakePrimary();
3719 auto loop2 = Make();
3720
3721 auto sender1 = loop1->MakeSender<TestMessage>("/test");
3722 auto sender2 = loop2->MakeSender<TestMessage>("/test");
3723
3724 // Send queue_size messages split between the senders.
3725 const int queue_size = TestChannelQueueSize(loop1.get());
3726 for (int i = 0; i < queue_size / 2; i++) {
3727 ASSERT_EQ(SendTestMessage(sender1), RawSender::Error::kOk);
3728 ASSERT_EQ(SendTestMessage(sender2), RawSender::Error::kOk);
3729 }
3730
3731 // Since queue_size messages have been sent, this should return an error
3732 EXPECT_EQ(SendTestMessage(sender2), RawSender::Error::kMessagesSentTooFast);
3733}
3734
Austin Schuhdda6db72023-06-21 17:02:34 -07003735// Tests that a longer storage durations store more messages.
3736TEST_P(AbstractEventLoopTest, SendingTooFastWithLongDuration) {
3737 auto loop1 = MakePrimary();
3738
3739 auto sender1 = loop1->MakeSender<TestMessage>("/test3");
3740
3741 // Send queue_size messages split between the senders.
3742 const int queue_size =
3743 configuration::QueueSize(loop1->configuration(), sender1.channel());
3744 EXPECT_EQ(queue_size, 100 * 10);
3745 for (int i = 0; i < queue_size; i++) {
3746 ASSERT_EQ(SendTestMessage(sender1), RawSender::Error::kOk);
3747 }
3748
3749 // Since queue_size messages have been sent, and little time has elapsed,
3750 // this should return an error.
3751 EXPECT_EQ(SendTestMessage(sender1), RawSender::Error::kMessagesSentTooFast);
3752}
3753
Stephan Pleinesf63bde82024-01-13 15:59:33 -08003754} // namespace aos::testing