blob: 1e6b3a49a905b9bc7801f901b427dcb0270065b5 [file] [log] [blame]
Alex Perrycb7da4b2019-08-28 19:35:56 -07001#include "aos/events/event_loop_param_test.h"
Parker Schuhe4a70d62017-12-27 20:10:20 -08002
Austin Schuh52d325c2019-06-23 18:59:06 -07003#include <chrono>
James Kuszmaul9f998082024-05-23 15:37:35 -07004#include <filesystem>
Brian Silverman4f4e0612020-08-12 19:54:41 -07005#include <unordered_map>
6#include <unordered_set>
Austin Schuh52d325c2019-06-23 18:59:06 -07007
Austin Schuh99f7c6a2024-06-25 22:07:44 -07008#include "absl/flags/flag.h"
9#include "absl/flags/reflection.h"
10#include "absl/log/check.h"
11#include "absl/log/log.h"
Philipp Schrader790cb542023-07-05 21:06:52 -070012#include "gmock/gmock.h"
13#include "gtest/gtest.h"
14
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -070015#include "aos/events/test_message_generated.h"
James Kuszmaulb1c11052023-11-06 13:20:53 -080016#include "aos/events/test_message_static.h"
Austin Schuh54cf95f2019-11-29 13:14:18 -080017#include "aos/flatbuffer_merge.h"
Austin Schuhad9e5eb2021-11-19 20:33:55 -080018#include "aos/logging/log_message_generated.h"
19#include "aos/logging/logging.h"
Austin Schuhcc6070c2020-10-10 20:25:56 -070020#include "aos/realtime.h"
Austin Schuh9fe68f72019-08-10 19:32:03 -070021
Stephan Pleinesf63bde82024-01-13 15:59:33 -080022namespace aos::testing {
Austin Schuh52d325c2019-06-23 18:59:06 -070023namespace {
24namespace chrono = ::std::chrono;
25} // namespace
Parker Schuhe4a70d62017-12-27 20:10:20 -080026
Brian Silverman4f4e0612020-08-12 19:54:41 -070027::std::unique_ptr<EventLoop> AbstractEventLoopTest::Make(
28 std::string_view name) {
29 std::string name_copy(name);
30 if (name == "") {
31 name_copy = "loop";
32 name_copy += std::to_string(event_loop_count_);
33 }
34 ++event_loop_count_;
Austin Schuh6bae8252021-02-07 22:01:49 -080035 auto result = factory_->Make(name_copy);
36 if (do_timing_reports() == DoTimingReports::kNo) {
37 result->SkipTimingReport();
38 }
39 return result;
Brian Silverman4f4e0612020-08-12 19:54:41 -070040}
41
42void AbstractEventLoopTest::VerifyBuffers(
43 int number_buffers,
44 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>> fetchers,
45 std::vector<std::reference_wrapper<const Sender<TestMessage>>> senders) {
46 // The buffers which are in a sender.
47 std::unordered_set<int> in_sender;
48 for (const Sender<TestMessage> &sender : senders) {
49 const int this_buffer = sender.buffer_index();
50 CHECK_GE(this_buffer, 0);
51 CHECK_LT(this_buffer, number_buffers);
52 CHECK(in_sender.insert(this_buffer).second) << ": " << this_buffer;
53 }
54
55 if (read_method() != ReadMethod::PIN) {
56 // If we're not using PIN, we can't really verify anything about what
57 // buffers the fetchers have.
58 return;
59 }
60
61 // Mapping from TestMessage::value to buffer index.
62 std::unordered_map<int, int> fetcher_values;
63 for (const Fetcher<TestMessage> &fetcher : fetchers) {
64 if (!fetcher.get()) {
65 continue;
66 }
67 const int this_buffer = fetcher.context().buffer_index;
68 CHECK_GE(this_buffer, 0);
69 CHECK_LT(this_buffer, number_buffers);
70 CHECK(in_sender.count(this_buffer) == 0) << ": " << this_buffer;
71 const auto insert_result = fetcher_values.insert(
72 std::make_pair(fetcher.get()->value(), this_buffer));
73 if (!insert_result.second) {
74 CHECK_EQ(this_buffer, insert_result.first->second);
75 }
76 }
77}
78
Austin Schuh6b6dfa52019-06-12 20:16:20 -070079// Tests that watcher can receive messages from a sender.
Parker Schuhe4a70d62017-12-27 20:10:20 -080080// Also tests that OnRun() works.
81TEST_P(AbstractEventLoopTest, Basic) {
82 auto loop1 = Make();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070083 auto loop2 = MakePrimary();
84
Alex Perrycb7da4b2019-08-28 19:35:56 -070085 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
Austin Schuh6b6dfa52019-06-12 20:16:20 -070086
87 bool happened = false;
88
89 loop2->OnRun([&]() {
90 happened = true;
91
Alex Perrycb7da4b2019-08-28 19:35:56 -070092 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
93 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
94 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -070095 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -070096 });
97
98 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070099 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -0700100 this->Exit();
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700101 });
102
103 EXPECT_FALSE(happened);
104 Run();
105 EXPECT_TRUE(happened);
106}
107
James Kuszmaulb1c11052023-11-06 13:20:53 -0800108// Tests that watcher can receive messages from a static sender.
109// This confirms that the "static" flatbuffer API works with the EventLoop
110// senders.
111TEST_P(AbstractEventLoopTest, BasicStatic) {
112 auto loop1 = Make();
113 auto loop2 = MakePrimary();
114
115 aos::Sender<TestMessageStatic> sender =
116 loop1->MakeSender<TestMessageStatic>("/test");
117
118 bool happened = false;
119
120 loop2->OnRun([&]() {
121 happened = true;
122
123 aos::Sender<TestMessageStatic>::StaticBuilder msg =
124 sender.MakeStaticBuilder();
James Kuszmauldde65632023-12-07 16:12:26 -0800125 msg->set_value(200);
James Kuszmaulb1c11052023-11-06 13:20:53 -0800126 CHECK(msg.builder()->Verify());
127 msg.CheckOk(msg.Send());
128 });
129
130 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
131 EXPECT_EQ(message.value(), 200);
132 this->Exit();
133 });
134
135 EXPECT_FALSE(happened);
136 Run();
137 EXPECT_TRUE(happened);
138}
139
James Kuszmauld4b4f1d2024-03-13 15:57:35 -0700140// Tests that a static sender's Builder object can be moved safely.
141TEST_P(AbstractEventLoopTest, StaticBuilderMoveConstructor) {
142 auto loop1 = MakePrimary();
143
144 aos::Sender<TestMessageStatic> sender =
145 loop1->MakeSender<TestMessageStatic>("/test");
146 aos::Fetcher<TestMessage> fetcher = loop1->MakeFetcher<TestMessage>("/test");
147 std::optional<aos::Sender<TestMessageStatic>::StaticBuilder> moved_to_builder;
148 {
149 aos::Sender<TestMessageStatic>::StaticBuilder moved_from_builder =
150 sender.MakeStaticBuilder();
151 moved_to_builder.emplace(std::move(moved_from_builder));
152 }
153
154 loop1->OnRun([this, &moved_to_builder]() {
155 moved_to_builder.value()->set_value(200);
156 CHECK(moved_to_builder.value().builder()->Verify());
157 moved_to_builder.value().CheckOk(moved_to_builder.value().Send());
158 this->Exit();
159 });
160
161 ASSERT_FALSE(fetcher.Fetch());
162 Run();
163 ASSERT_TRUE(fetcher.Fetch());
164 EXPECT_EQ(200, fetcher->value());
165}
166
Brian Silverman341b57e2020-06-23 16:23:18 -0700167// Tests that watcher can receive messages from a sender, sent via SendDetached.
168TEST_P(AbstractEventLoopTest, BasicSendDetached) {
169 auto loop1 = Make();
170 auto loop2 = MakePrimary();
171
172 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
173
174 FlatbufferDetachedBuffer<TestMessage> detached =
175 flatbuffers::DetachedBuffer();
176 {
177 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
178 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
179 builder.add_value(100);
180 detached = msg.Detach(builder.Finish());
181 }
182 detached = flatbuffers::DetachedBuffer();
183 {
184 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
185 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
186 builder.add_value(200);
187 detached = msg.Detach(builder.Finish());
188 }
milind1f1dca32021-07-03 13:50:07 -0700189 sender.CheckOk(sender.SendDetached(std::move(detached)));
Brian Silverman341b57e2020-06-23 16:23:18 -0700190
191 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
192 ASSERT_TRUE(fetcher.Fetch());
193 EXPECT_EQ(fetcher->value(), 200);
194}
195
Alexei Strots7cb6e0c2024-02-19 21:24:21 -0800196// Tests that fetcher can receive messages from a sender, sent via SendJson.
197TEST_P(AbstractEventLoopTest, BasicSendJson) {
198 auto loop1 = Make();
199 auto loop2 = MakePrimary();
200
201 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
202 sender.CheckOk(sender.SendJson(R"json({"value":201})json"));
203
204 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
205 ASSERT_TRUE(fetcher.Fetch());
206 EXPECT_EQ(fetcher->value(), 201);
207}
208
209// Tests that invalid JSON isn't sent.
210TEST_P(AbstractEventLoopDeathTest, InvalidSendJson) {
211 auto loop1 = Make();
212 auto loop2 = MakePrimary();
213
214 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
215 EXPECT_DEATH({ sender.CheckOk(sender.SendJson(R"json({"val)json")); },
216 "Invalid JSON");
217}
218
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800219// Verifies that a no-arg watcher will not have a data pointer.
220TEST_P(AbstractEventLoopTest, NoArgNoData) {
221 auto loop1 = Make();
222 auto loop2 = MakePrimary();
223
224 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
225
226 bool happened = false;
227
228 loop2->OnRun([&]() {
229 happened = true;
230
231 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
232 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -0700233 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800234 });
235
236 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
237 EXPECT_GT(loop2->context().size, 0u);
238 EXPECT_EQ(nullptr, loop2->context().data);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700239 EXPECT_EQ(-1, loop2->context().buffer_index);
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800240 this->Exit();
241 });
242
243 EXPECT_FALSE(happened);
244 Run();
245 EXPECT_TRUE(happened);
246}
247
Brian Silverman454bc112020-03-05 14:21:25 -0800248// Tests that no-arg watcher can receive messages from a sender.
249// Also tests that OnRun() works.
250TEST_P(AbstractEventLoopTest, BasicNoArg) {
251 auto loop1 = Make();
252 auto loop2 = MakePrimary();
253
254 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
255
256 bool happened = false;
257
258 loop2->OnRun([&]() {
259 happened = true;
260
261 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
262 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
263 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700264 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -0800265 });
266
267 aos::Fetcher<TestMessage> fetcher = loop2->MakeFetcher<TestMessage>("/test");
268 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
269 ASSERT_TRUE(fetcher.Fetch());
270 EXPECT_EQ(fetcher->value(), 200);
271 this->Exit();
272 });
273
274 EXPECT_FALSE(happened);
275 Run();
276 EXPECT_TRUE(happened);
277}
278
279// Tests that a watcher can be created with an std::function.
280TEST_P(AbstractEventLoopTest, BasicFunction) {
281 auto loop1 = Make();
282 auto loop2 = MakePrimary();
283
284 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
285
286 bool happened = false;
287
288 loop2->OnRun([&]() {
289 happened = true;
290
291 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
292 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
293 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700294 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -0800295 });
296
297 loop2->MakeWatcher("/test", std::function<void(const TestMessage &)>(
298 [&](const TestMessage &message) {
299 EXPECT_EQ(message.value(), 200);
300 this->Exit();
301 }));
302
303 EXPECT_FALSE(happened);
304 Run();
305 EXPECT_TRUE(happened);
306}
307
Brian Silverman0fc69932020-01-24 21:54:02 -0800308// Tests that watcher can receive messages from two senders.
309// Also tests that OnRun() works.
310TEST_P(AbstractEventLoopTest, BasicTwoSenders) {
311 auto loop1 = Make();
312 auto loop2 = MakePrimary();
313
314 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
315 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
316
317 bool happened = false;
318
319 loop2->OnRun([&]() {
320 happened = true;
321
322 {
323 aos::Sender<TestMessage>::Builder msg = sender1.MakeBuilder();
324 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
325 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700326 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman0fc69932020-01-24 21:54:02 -0800327 }
328 {
329 aos::Sender<TestMessage>::Builder msg = sender2.MakeBuilder();
330 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
331 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700332 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman0fc69932020-01-24 21:54:02 -0800333 }
334 });
335
336 int messages_received = 0;
337 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
338 EXPECT_EQ(message.value(), 200);
339 this->Exit();
340 ++messages_received;
341 });
342
343 EXPECT_FALSE(happened);
344 Run();
345 EXPECT_TRUE(happened);
346 EXPECT_EQ(messages_received, 2);
347}
348
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700349// Tests that a fetcher can fetch from a sender.
350// Also tests that OnRun() works.
351TEST_P(AbstractEventLoopTest, FetchWithoutRun) {
352 auto loop1 = Make();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800353 auto loop2 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -0700354 auto loop3 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800355
356 auto sender = loop1->MakeSender<TestMessage>("/test");
357
358 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
359
Austin Schuhbbce72d2019-05-26 15:11:46 -0700360 EXPECT_FALSE(fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -0800361 EXPECT_EQ(fetcher.get(), nullptr);
362
Austin Schuhad154822019-12-27 15:45:13 -0800363 EXPECT_EQ(fetcher.context().monotonic_event_time, monotonic_clock::min_time);
364 EXPECT_EQ(fetcher.context().monotonic_remote_time, monotonic_clock::min_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -0700365 EXPECT_EQ(fetcher.context().monotonic_remote_transmit_time,
366 monotonic_clock::min_time);
Austin Schuhad154822019-12-27 15:45:13 -0800367 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
368 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -0700369 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
Austin Schuh39788ff2019-12-01 18:22:57 -0800370 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
371 EXPECT_EQ(fetcher.context().size, 0u);
372 EXPECT_EQ(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700373 EXPECT_EQ(fetcher.context().buffer_index, -1);
Austin Schuhbbce72d2019-05-26 15:11:46 -0700374
Alex Perrycb7da4b2019-08-28 19:35:56 -0700375 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
376 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
377 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700378 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700379
380 EXPECT_TRUE(fetcher.Fetch());
381 ASSERT_FALSE(fetcher.get() == nullptr);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700382 EXPECT_EQ(fetcher.get()->value(), 200);
Austin Schuh39788ff2019-12-01 18:22:57 -0800383
384 const chrono::milliseconds kEpsilon(100);
385
Austin Schuhad154822019-12-27 15:45:13 -0800386 const aos::monotonic_clock::time_point monotonic_now = loop2->monotonic_now();
387 const aos::realtime_clock::time_point realtime_now = loop2->realtime_now();
388 EXPECT_EQ(fetcher.context().monotonic_event_time,
389 fetcher.context().monotonic_remote_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -0700390 EXPECT_EQ(fetcher.context().monotonic_remote_transmit_time,
391 monotonic_clock::min_time);
Austin Schuhad154822019-12-27 15:45:13 -0800392 EXPECT_EQ(fetcher.context().realtime_event_time,
393 fetcher.context().realtime_remote_time);
394
395 EXPECT_GE(fetcher.context().monotonic_event_time, monotonic_now - kEpsilon);
396 EXPECT_LE(fetcher.context().monotonic_event_time, monotonic_now + kEpsilon);
397 EXPECT_GE(fetcher.context().realtime_event_time, realtime_now - kEpsilon);
398 EXPECT_LE(fetcher.context().realtime_event_time, realtime_now + kEpsilon);
Austin Schuha9012be2021-07-21 15:19:11 -0700399 EXPECT_EQ(fetcher.context().source_boot_uuid, loop2->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -0800400 EXPECT_EQ(fetcher.context().queue_index, 0x0u);
401 EXPECT_EQ(fetcher.context().size, 20u);
402 EXPECT_NE(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700403 if (read_method() == ReadMethod::PIN) {
404 EXPECT_GE(fetcher.context().buffer_index, 0);
405 EXPECT_LT(fetcher.context().buffer_index,
406 loop2->NumberBuffers(fetcher.channel()));
407 } else {
408 EXPECT_EQ(fetcher.context().buffer_index, -1);
409 }
Parker Schuhe4a70d62017-12-27 20:10:20 -0800410}
411
Austin Schuh98ed26f2023-07-19 14:12:28 -0700412std::function<bool(const Context &)> MakeShouldFetch(
413 bool should_fetch, size_t *called_count = nullptr) {
414 return [should_fetch, called_count](const Context &) {
415 if (called_count != nullptr) {
416 (*called_count)++;
417 }
418 return should_fetch;
419 };
420}
421
422// Tests that a fetcher using FetchIf can fetch from a sender.
423TEST_P(AbstractEventLoopTest, FetchIfWithoutRun) {
424 auto loop1 = Make();
425 auto loop2 = Make();
426 auto loop3 = MakePrimary();
427
428 auto sender = loop1->MakeSender<TestMessage>("/test");
429
430 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
431
432 for (const bool should_fetch : {true, false}) {
433 EXPECT_FALSE(fetcher.FetchIf(MakeShouldFetch(should_fetch)));
434 EXPECT_EQ(fetcher.get(), nullptr);
435
436 EXPECT_EQ(fetcher.context().monotonic_event_time,
437 monotonic_clock::min_time);
438 EXPECT_EQ(fetcher.context().monotonic_remote_time,
439 monotonic_clock::min_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -0700440 EXPECT_EQ(fetcher.context().monotonic_remote_transmit_time,
441 monotonic_clock::min_time);
Austin Schuh98ed26f2023-07-19 14:12:28 -0700442 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
443 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
444 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
445 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
446 EXPECT_EQ(fetcher.context().size, 0u);
447 EXPECT_EQ(fetcher.context().data, nullptr);
448 EXPECT_EQ(fetcher.context().buffer_index, -1);
449 }
450
451 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
452 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
453 builder.add_value(200);
454 msg.CheckOk(msg.Send(builder.Finish()));
455
456 // Make sure failing to fetch won't affect anything.
457 EXPECT_FALSE(fetcher.FetchIf(MakeShouldFetch(false)));
458 EXPECT_EQ(fetcher.get(), nullptr);
459
460 EXPECT_EQ(fetcher.context().monotonic_event_time, monotonic_clock::min_time);
461 EXPECT_EQ(fetcher.context().monotonic_remote_time, monotonic_clock::min_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -0700462 EXPECT_EQ(fetcher.context().monotonic_remote_transmit_time,
463 monotonic_clock::min_time);
Austin Schuh98ed26f2023-07-19 14:12:28 -0700464 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
465 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
466 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
467 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
468 EXPECT_EQ(fetcher.context().size, 0u);
469 EXPECT_EQ(fetcher.context().data, nullptr);
470 EXPECT_EQ(fetcher.context().buffer_index, -1);
471
472 // And now confirm we succeed and everything gets set right.
473 EXPECT_TRUE(fetcher.FetchIf(MakeShouldFetch(true)));
474 ASSERT_FALSE(fetcher.get() == nullptr);
475 EXPECT_EQ(fetcher.get()->value(), 200);
476
477 const chrono::milliseconds kEpsilon(100);
478
479 const aos::monotonic_clock::time_point monotonic_now = loop2->monotonic_now();
480 const aos::realtime_clock::time_point realtime_now = loop2->realtime_now();
481 EXPECT_EQ(fetcher.context().monotonic_event_time,
482 fetcher.context().monotonic_remote_time);
483 EXPECT_EQ(fetcher.context().realtime_event_time,
484 fetcher.context().realtime_remote_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -0700485 EXPECT_EQ(fetcher.context().monotonic_remote_transmit_time,
486 monotonic_clock::min_time);
Austin Schuh98ed26f2023-07-19 14:12:28 -0700487
488 EXPECT_GE(fetcher.context().monotonic_event_time, monotonic_now - kEpsilon);
489 EXPECT_LE(fetcher.context().monotonic_event_time, monotonic_now + kEpsilon);
490 EXPECT_GE(fetcher.context().realtime_event_time, realtime_now - kEpsilon);
491 EXPECT_LE(fetcher.context().realtime_event_time, realtime_now + kEpsilon);
492 EXPECT_EQ(fetcher.context().source_boot_uuid, loop2->boot_uuid());
493 EXPECT_EQ(fetcher.context().queue_index, 0x0u);
494 EXPECT_EQ(fetcher.context().size, 20u);
495 EXPECT_NE(fetcher.context().data, nullptr);
496 if (read_method() == ReadMethod::PIN) {
497 EXPECT_GE(fetcher.context().buffer_index, 0);
498 EXPECT_LT(fetcher.context().buffer_index,
499 loop2->NumberBuffers(fetcher.channel()));
500 } else {
501 EXPECT_EQ(fetcher.context().buffer_index, -1);
502 }
503}
504
Austin Schuh3578a2e2019-05-25 18:17:59 -0700505// Tests that watcher will receive all messages sent if they are sent after
506// initialization and before running.
507TEST_P(AbstractEventLoopTest, DoubleSendAtStartup) {
508 auto loop1 = Make();
509 auto loop2 = MakePrimary();
510
511 auto sender = loop1->MakeSender<TestMessage>("/test");
512
513 ::std::vector<int> values;
514
515 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700516 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700517 if (values.size() == 2) {
Austin Schuh9fe68f72019-08-10 19:32:03 -0700518 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -0700519 }
520 });
521
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700522 // Before Run, should be ignored.
Austin Schuh3578a2e2019-05-25 18:17:59 -0700523 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700524 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
525 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
526 builder.add_value(199);
milind1f1dca32021-07-03 13:50:07 -0700527 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700528 }
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700529
530 loop2->OnRun([&]() {
Austin Schuh98ed26f2023-07-19 14:12:28 -0700531 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700532 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
533 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700534 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700535 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700536 }
537 });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700538
539 Run();
540
541 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
542}
543
544// Tests that watcher will not receive messages sent before the watcher is
545// created.
546TEST_P(AbstractEventLoopTest, DoubleSendAfterStartup) {
547 auto loop1 = Make();
548 auto loop2 = MakePrimary();
549
550 auto sender = loop1->MakeSender<TestMessage>("/test");
551
552 ::std::vector<int> values;
553
Austin Schuh98ed26f2023-07-19 14:12:28 -0700554 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700555 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
556 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700557 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700558 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700559 }
560
561 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700562 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700563 });
564
565 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700566 auto test_timer = loop2->AddTimer([this]() { this->Exit(); });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700567 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700568 test_timer->Schedule(loop2->monotonic_now(),
569 ::std::chrono::milliseconds(100));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700570 });
571
572 Run();
573 EXPECT_EQ(0, values.size());
574}
575
Austin Schuhbbce72d2019-05-26 15:11:46 -0700576// Tests that FetchNext gets all the messages sent after it is constructed.
577TEST_P(AbstractEventLoopTest, FetchNext) {
578 auto loop1 = Make();
579 auto loop2 = MakePrimary();
580
581 auto sender = loop1->MakeSender<TestMessage>("/test");
582 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
583
584 ::std::vector<int> values;
585
Austin Schuh98ed26f2023-07-19 14:12:28 -0700586 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700587 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
588 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700589 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700590 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700591 }
592
593 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700594 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700595 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700596 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700597 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700598 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700599 });
600
601 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700602 test_timer->Schedule(loop2->monotonic_now(),
603 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700604 });
605
606 Run();
607 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
608}
609
610// Tests that FetchNext gets no messages sent before it is constructed.
611TEST_P(AbstractEventLoopTest, FetchNextAfterSend) {
612 auto loop1 = Make();
613 auto loop2 = MakePrimary();
614
615 auto sender = loop1->MakeSender<TestMessage>("/test");
616
617 ::std::vector<int> values;
618
Austin Schuh98ed26f2023-07-19 14:12:28 -0700619 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700620 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
621 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700622 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700623 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700624 }
625
626 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
627
628 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700629 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700630 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700631 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700632 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700633 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700634 });
635
636 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700637 test_timer->Schedule(loop2->monotonic_now(),
638 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700639 });
640
641 Run();
642 EXPECT_THAT(0, values.size());
643}
644
Austin Schuh98ed26f2023-07-19 14:12:28 -0700645// Tests that FetchNextIf gets no messages sent before it is constructed.
646TEST_P(AbstractEventLoopTest, FetchNextIfAfterSend) {
647 auto loop1 = Make();
648 auto loop2 = MakePrimary();
649
650 auto sender = loop1->MakeSender<TestMessage>("/test");
651
652 ::std::vector<int> values;
653
654 for (int i = 200; i < 202; ++i) {
655 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
656 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
657 builder.add_value(i);
658 msg.CheckOk(msg.Send(builder.Finish()));
659 }
660
661 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
662
663 // Add a timer to actually quit.
664 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
665 while (fetcher.FetchNextIf(MakeShouldFetch(true))) {
666 values.push_back(fetcher.get()->value());
667 }
668 this->Exit();
669 });
670
671 loop2->OnRun([&test_timer, &loop2]() {
672 test_timer->Schedule(loop2->monotonic_now(),
673 ::std::chrono::milliseconds(100));
674 });
675
676 Run();
677 EXPECT_EQ(0, values.size());
678}
679
Austin Schuhbbce72d2019-05-26 15:11:46 -0700680// Tests that Fetch returns the last message created before the loop was
681// started.
682TEST_P(AbstractEventLoopTest, FetchDataFromBeforeCreation) {
683 auto loop1 = Make();
684 auto loop2 = MakePrimary();
685
686 auto sender = loop1->MakeSender<TestMessage>("/test");
687
688 ::std::vector<int> values;
689
Austin Schuh98ed26f2023-07-19 14:12:28 -0700690 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700691 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
692 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700693 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700694 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700695 }
696
697 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
698
699 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700700 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700701 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700702 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700703 }
704 // Do it again to make sure we don't double fetch.
705 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700706 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700707 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700708 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700709 });
710
711 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700712 test_timer->Schedule(loop2->monotonic_now(),
713 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700714 });
715
716 Run();
717 EXPECT_THAT(values, ::testing::ElementsAreArray({201}));
718}
719
Austin Schuh98ed26f2023-07-19 14:12:28 -0700720// Tests that FetchIf returns the last message created before the loop was
721// started.
722TEST_P(AbstractEventLoopTest, FetchIfDataFromBeforeCreation) {
723 auto loop1 = Make();
724 auto loop2 = MakePrimary();
725
726 auto sender = loop1->MakeSender<TestMessage>("/test");
727
728 ::std::vector<int> values;
729
730 for (int i = 200; i < 202; ++i) {
731 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
732 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
733 builder.add_value(i);
734 msg.CheckOk(msg.Send(builder.Finish()));
735 }
736
737 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
738
739 // Add a timer to actually quit.
740 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
741 if (fetcher.FetchIf(MakeShouldFetch(true))) {
742 values.push_back(fetcher.get()->value());
743 }
744
745 if (fetcher.FetchIf(MakeShouldFetch(false))) {
746 values.push_back(fetcher.get()->value());
747 }
748 // Do it again to make sure we don't double fetch.
749 if (fetcher.FetchIf(MakeShouldFetch(true))) {
750 values.push_back(fetcher.get()->value());
751 }
752 this->Exit();
753 });
754
755 loop2->OnRun([&test_timer, &loop2]() {
756 test_timer->Schedule(loop2->monotonic_now(),
757 ::std::chrono::milliseconds(100));
758 });
759
760 Run();
761 EXPECT_THAT(values, ::testing::ElementsAreArray({201}));
762}
763
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700764// Tests that timer handler is enabled after setup (even if it is in the past)
765// and is disabled after running
766TEST_P(AbstractEventLoopTest, CheckTimerDisabled) {
767 auto loop = MakePrimary("primary");
768
769 auto timer = loop->AddTimer([this]() {
770 LOG(INFO) << "timer called";
771 Exit();
772 });
773
774 loop->OnRun([&loop, timer]() {
775 EXPECT_TRUE(timer->IsDisabled());
Philipp Schradera6712522023-07-05 20:25:11 -0700776 timer->Schedule(loop->monotonic_now() + chrono::milliseconds(100));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700777 EXPECT_FALSE(timer->IsDisabled());
778 });
779
780 Run();
781 EXPECT_TRUE(timer->IsDisabled());
782}
783
784// Tests that timer handler is enabled after setup (even if it is in the past)
785// and is disabled after running
786TEST_P(AbstractEventLoopTest, CheckTimerRunInPastDisabled) {
787 auto loop = MakePrimary("primary");
788
789 auto timer2 = loop->AddTimer([this]() {
790 LOG(INFO) << "timer called";
791 Exit();
792 });
793
794 auto timer = loop->AddTimer([&loop, timer2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700795 timer2->Schedule(loop->monotonic_now() - chrono::nanoseconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700796 });
797
798 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700799 timer->Schedule(loop->monotonic_now() + chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700800 EXPECT_FALSE(timer->IsDisabled());
801 });
802
803 Run();
804 EXPECT_TRUE(timer2->IsDisabled());
805}
806
807// Tests that timer handler is not disabled even after calling Exit on the event
808// loop within the timer
809TEST_P(AbstractEventLoopTest, CheckTimerRepeatOnCountDisabled) {
810 auto loop = MakePrimary("primary");
811 int counter = 0;
812
813 auto timer = loop->AddTimer([&counter, this]() {
814 LOG(INFO) << "timer called";
815 counter++;
816 if (counter >= 5) {
817 Exit();
818 }
819 });
820
821 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700822 timer->Schedule(loop->monotonic_now() + chrono::seconds(1),
823 chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700824 EXPECT_FALSE(timer->IsDisabled());
825 });
826 Run();
827
828 // Sanity check
829 EXPECT_EQ(counter, 5);
830
831 // if you run the loop again, the timer will start running again
832 EXPECT_FALSE(timer->IsDisabled());
833
834 counter = 0;
835 Run();
836 timer->Disable();
837
838 EXPECT_TRUE(timer->IsDisabled());
839}
840
841// Tests that timer handler is not disabled even after calling Exit on the event
842// loop using an external timer
843TEST_P(AbstractEventLoopTest, CheckTimerRepeatTillEndTimerDisabled) {
844 auto loop = MakePrimary("primary");
845
846 auto timer = loop->AddTimer([]() { LOG(INFO) << "timer called"; });
847
848 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700849 timer->Schedule(loop->monotonic_now() + chrono::seconds(1),
850 chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700851 EXPECT_FALSE(timer->IsDisabled());
852 });
853
854 EndEventLoop(loop.get(), chrono::seconds(5));
855 Run();
856 EXPECT_FALSE(timer->IsDisabled());
857
858 timer->Disable();
859 EXPECT_TRUE(timer->IsDisabled());
860}
861
Austin Schuhbbce72d2019-05-26 15:11:46 -0700862// Tests that Fetch and FetchNext interleave as expected.
863TEST_P(AbstractEventLoopTest, FetchAndFetchNextTogether) {
864 auto loop1 = Make();
865 auto loop2 = MakePrimary();
866
867 auto sender = loop1->MakeSender<TestMessage>("/test");
868
869 ::std::vector<int> values;
870
Austin Schuh98ed26f2023-07-19 14:12:28 -0700871 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700872 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
873 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700874 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700875 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700876 }
877
878 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
879
880 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700881 auto test_timer = loop2->AddTimer([&fetcher, &values, &sender, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700882 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700883 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700884 }
885
Austin Schuh98ed26f2023-07-19 14:12:28 -0700886 for (int i = 202; i < 205; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700887 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
888 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700889 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700890 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700891 }
892
893 if (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700894 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700895 }
896
897 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700898 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700899 }
900
Austin Schuh9fe68f72019-08-10 19:32:03 -0700901 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700902 });
903
904 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700905 test_timer->Schedule(loop2->monotonic_now(),
906 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700907 });
908
909 Run();
910 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
911}
912
Austin Schuh98ed26f2023-07-19 14:12:28 -0700913// Tests that Fetch{If,} and FetchNext{If,} interleave as expected.
914TEST_P(AbstractEventLoopTest, FetchAndFetchNextIfTogether) {
915 auto loop1 = Make();
916 auto loop2 = MakePrimary();
917
918 auto sender = loop1->MakeSender<TestMessage>("/test");
919
920 ::std::vector<int> values;
921
922 for (int i = 200; i < 202; ++i) {
923 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
924 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
925 builder.add_value(i);
926 msg.CheckOk(msg.Send(builder.Finish()));
927 }
928
929 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
930
931 // Add a timer to actually quit.
932 auto test_timer = loop2->AddTimer([&fetcher, &values, &sender, this]() {
933 if (fetcher.Fetch()) {
934 values.push_back(fetcher.get()->value());
935 }
936
937 for (int i = 202; i < 205; ++i) {
938 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
939 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
940 builder.add_value(i);
941 msg.CheckOk(msg.Send(builder.Finish()));
942 }
943
944 EXPECT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false)));
945
946 if (fetcher.FetchNext()) {
947 values.push_back(fetcher.get()->value());
948 }
949
950 EXPECT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false)));
951 EXPECT_FALSE(fetcher.FetchIf(MakeShouldFetch(false)));
952
953 if (fetcher.FetchIf(MakeShouldFetch(true))) {
954 values.push_back(fetcher.get()->value());
955 }
956
957 this->Exit();
958 });
959
960 loop2->OnRun([&test_timer, &loop2]() {
961 test_timer->Schedule(loop2->monotonic_now(),
962 ::std::chrono::milliseconds(100));
963 });
964
965 Run();
966 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
967}
968
Austin Schuh3115a202019-05-27 21:02:14 -0700969// Tests that FetchNext behaves correctly when we get two messages in the queue
970// but don't consume the first until after the second has been sent.
971TEST_P(AbstractEventLoopTest, FetchNextTest) {
Austin Schuh3115a202019-05-27 21:02:14 -0700972 auto send_loop = Make();
973 auto fetch_loop = Make();
974 auto sender = send_loop->MakeSender<TestMessage>("/test");
975 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
976
977 {
Tyler Chatow67ddb032020-01-12 14:30:04 -0800978 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
979 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
980 builder.add_value(100);
milind1f1dca32021-07-03 13:50:07 -0700981 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700982 }
983
984 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700985 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
986 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
987 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700988 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700989 }
990
991 ASSERT_TRUE(fetcher.FetchNext());
992 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700993 EXPECT_EQ(100, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700994
995 ASSERT_TRUE(fetcher.FetchNext());
996 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700997 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700998
999 // When we run off the end of the queue, expect to still have the old message:
1000 ASSERT_FALSE(fetcher.FetchNext());
1001 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -07001002 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -07001003}
1004
Austin Schuh98ed26f2023-07-19 14:12:28 -07001005// Tests that FetchNext behaves correctly when we get two messages in the queue
1006// but don't consume the first until after the second has been sent.
1007TEST_P(AbstractEventLoopTest, FetchNextIfTest) {
1008 auto send_loop = Make();
1009 auto fetch_loop = Make();
1010 auto sender = send_loop->MakeSender<TestMessage>("/test");
1011 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
1012
1013 {
1014 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1015 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1016 builder.add_value(100);
1017 msg.CheckOk(msg.Send(builder.Finish()));
1018 }
1019
1020 {
1021 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1022 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1023 builder.add_value(200);
1024 msg.CheckOk(msg.Send(builder.Finish()));
1025 }
1026
1027 size_t called_count = 0;
1028 ASSERT_TRUE(fetcher.FetchNextIf(MakeShouldFetch(true, &called_count)));
1029 ASSERT_NE(nullptr, fetcher.get());
1030 EXPECT_EQ(100, fetcher.get()->value());
1031 EXPECT_EQ(called_count, 1u);
1032
1033 ASSERT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false, &called_count)));
1034 EXPECT_EQ(called_count, 2u);
1035
1036 ASSERT_TRUE(fetcher.FetchNextIf(MakeShouldFetch(true, &called_count)));
1037 ASSERT_NE(nullptr, fetcher.get());
1038 EXPECT_EQ(200, fetcher.get()->value());
1039 EXPECT_EQ(called_count, 3u);
1040
1041 // When we run off the end of the queue, expect to still have the old message:
1042 ASSERT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false, &called_count)));
1043 EXPECT_EQ(called_count, 3u);
1044 ASSERT_NE(nullptr, fetcher.get());
1045 EXPECT_EQ(200, fetcher.get()->value());
1046}
1047
Brian Silverman77162972020-08-12 19:52:40 -07001048// Verify that a fetcher still holds its data, even after falling behind.
1049TEST_P(AbstractEventLoopTest, FetcherBehindData) {
1050 auto send_loop = Make();
1051 auto fetch_loop = Make();
1052 auto sender = send_loop->MakeSender<TestMessage>("/test");
1053 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
1054 {
1055 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1056 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1057 builder.add_value(1);
milind1f1dca32021-07-03 13:50:07 -07001058 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -07001059 }
1060 ASSERT_TRUE(fetcher.Fetch());
1061 EXPECT_EQ(1, fetcher.get()->value());
1062 for (int i = 0; i < 300; ++i) {
1063 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1064 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1065 builder.add_value(i + 2);
milind1f1dca32021-07-03 13:50:07 -07001066 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -07001067 }
1068 EXPECT_EQ(1, fetcher.get()->value());
1069}
1070
1071// Try a bunch of orderings of operations with fetchers and senders. Verify that
1072// all the fetchers have the correct data at each step.
1073TEST_P(AbstractEventLoopTest, FetcherPermutations) {
1074 for (int max_save = 0; max_save < 5; ++max_save) {
1075 SCOPED_TRACE("max_save=" + std::to_string(max_save));
1076
1077 auto send_loop = Make();
1078 auto fetch_loop = Make();
1079 auto sender = send_loop->MakeSender<TestMessage>("/test");
1080 const auto send_message = [&sender](int i) {
1081 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1082 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1083 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -07001084 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -07001085 };
1086 std::vector<Fetcher<TestMessage>> fetchers;
1087 for (int i = 0; i < 10; ++i) {
1088 fetchers.emplace_back(fetch_loop->MakeFetcher<TestMessage>("/test"));
1089 }
1090 send_message(1);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001091 const auto verify_buffers = [&]() {
1092 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>>
1093 fetchers_copy;
1094 for (const auto &fetcher : fetchers) {
1095 fetchers_copy.emplace_back(fetcher);
1096 }
1097 std::vector<std::reference_wrapper<const Sender<TestMessage>>>
1098 senders_copy;
1099 senders_copy.emplace_back(sender);
1100 VerifyBuffers(send_loop->NumberBuffers(sender.channel()), fetchers_copy,
1101 senders_copy);
1102 };
Brian Silverman77162972020-08-12 19:52:40 -07001103 for (auto &fetcher : fetchers) {
1104 ASSERT_TRUE(fetcher.Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -07001105 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001106 EXPECT_EQ(1, fetcher.get()->value());
1107 }
1108
1109 for (int save = 1; save <= max_save; ++save) {
1110 SCOPED_TRACE("save=" + std::to_string(save));
1111 send_message(100 + save);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001112 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001113 for (size_t i = 0; i < fetchers.size() - save; ++i) {
1114 SCOPED_TRACE("fetcher=" + std::to_string(i));
1115 ASSERT_TRUE(fetchers[i].Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -07001116 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001117 EXPECT_EQ(100 + save, fetchers[i].get()->value());
1118 }
1119 for (size_t i = fetchers.size() - save; i < fetchers.size() - 1; ++i) {
1120 SCOPED_TRACE("fetcher=" + std::to_string(i));
1121 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
1122 }
1123 EXPECT_EQ(1, fetchers.back().get()->value());
1124 }
1125
1126 for (int i = 0; i < 300; ++i) {
1127 send_message(200 + i);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001128 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001129 }
1130
1131 for (size_t i = 0; i < fetchers.size() - max_save; ++i) {
1132 SCOPED_TRACE("fetcher=" + std::to_string(i));
1133 if (max_save > 0) {
1134 EXPECT_EQ(100 + max_save, fetchers[i].get()->value());
1135 } else {
1136 EXPECT_EQ(1, fetchers[i].get()->value());
1137 }
1138 }
1139 for (size_t i = fetchers.size() - max_save; i < fetchers.size() - 1; ++i) {
1140 SCOPED_TRACE("fetcher=" + std::to_string(i));
1141 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
1142 }
1143 EXPECT_EQ(1, fetchers.back().get()->value());
1144 }
1145}
1146
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001147// Verify that making a fetcher and watcher for "/test" succeeds.
1148TEST_P(AbstractEventLoopTest, FetcherAndWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -08001149 auto loop = Make();
1150 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001151 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Parker Schuhe4a70d62017-12-27 20:10:20 -08001152}
1153
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001154// Verify that making 2 fetchers for "/test" succeeds.
Parker Schuhe4a70d62017-12-27 20:10:20 -08001155TEST_P(AbstractEventLoopTest, TwoFetcher) {
1156 auto loop = Make();
1157 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001158 auto fetcher2 = loop->MakeFetcher<TestMessage>("/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -08001159}
1160
Alex Perrycb7da4b2019-08-28 19:35:56 -07001161// Verify that registering a watcher for an invalid channel name dies.
1162TEST_P(AbstractEventLoopDeathTest, InvalidChannelName) {
1163 auto loop = Make();
1164 EXPECT_DEATH(
1165 { loop->MakeWatcher("/test/invalid", [&](const TestMessage &) {}); },
1166 "/test/invalid");
Brian Silverman454bc112020-03-05 14:21:25 -08001167 EXPECT_DEATH(
1168 { loop->MakeNoArgWatcher<TestMessage>("/test/invalid", [&]() {}); },
1169 "/test/invalid");
Alex Perrycb7da4b2019-08-28 19:35:56 -07001170}
1171
James Kuszmaul8866e642022-06-10 16:00:36 -07001172// Verify that setting up a timer before monotonic_clock::epoch() fails.
James Kuszmaul86e86c32022-07-21 17:39:47 -07001173TEST_P(AbstractEventLoopDeathTest, NegativeTimeTimer) {
James Kuszmaul8866e642022-06-10 16:00:36 -07001174 auto loop = Make();
1175 TimerHandler *time = loop->AddTimer([]() {});
Philipp Schradera6712522023-07-05 20:25:11 -07001176 EXPECT_DEATH(
1177 time->Schedule(monotonic_clock::epoch() - std::chrono::seconds(1)),
1178 "-1.000");
James Kuszmaul8866e642022-06-10 16:00:36 -07001179}
1180
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001181// Verify that registering a watcher twice for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001182TEST_P(AbstractEventLoopDeathTest, TwoWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -08001183 auto loop = Make();
1184 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001185 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
1186 "/test");
Brian Silverman454bc112020-03-05 14:21:25 -08001187 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
1188}
1189
1190// Verify that registering a no-arg watcher twice for "/test" fails.
1191TEST_P(AbstractEventLoopDeathTest, TwoNoArgWatcher) {
1192 auto loop = Make();
1193 loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {});
1194 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
1195 "/test");
1196 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001197}
1198
Austin Schuh3115a202019-05-27 21:02:14 -07001199// Verify that SetRuntimeRealtimePriority fails while running.
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001200TEST_P(AbstractEventLoopDeathTest, SetRuntimeRealtimePriority) {
Austin Schuh3115a202019-05-27 21:02:14 -07001201 auto loop = MakePrimary();
Austin Schuh65493d62022-08-17 15:10:37 -07001202 EXPECT_EQ(0, loop->runtime_realtime_priority());
Austin Schuh3115a202019-05-27 21:02:14 -07001203 // Confirm that runtime priority calls work when not realtime.
1204 loop->SetRuntimeRealtimePriority(5);
Austin Schuh65493d62022-08-17 15:10:37 -07001205 EXPECT_EQ(5, loop->runtime_realtime_priority());
Austin Schuh3115a202019-05-27 21:02:14 -07001206
1207 loop->OnRun([&]() { loop->SetRuntimeRealtimePriority(5); });
1208
1209 EXPECT_DEATH(Run(), "realtime");
1210}
1211
Austin Schuh65493d62022-08-17 15:10:37 -07001212namespace {
1213
1214bool CpuSetEqual(const cpu_set_t &a, const cpu_set_t &b) {
1215 return CPU_EQUAL(&a, &b);
1216}
1217
1218} // namespace
1219
Brian Silverman6a54ff32020-04-28 16:41:39 -07001220// Verify that SetRuntimeAffinity fails while running.
1221TEST_P(AbstractEventLoopDeathTest, SetRuntimeAffinity) {
Austin Schuhde973292021-10-12 18:09:49 -07001222 const cpu_set_t available = GetCurrentThreadAffinity();
1223 int first_cpu = -1;
1224 for (int i = 0; i < CPU_SETSIZE; ++i) {
1225 if (CPU_ISSET(i, &available)) {
1226 first_cpu = i;
1227 break;
1228 continue;
1229 }
1230 }
1231 CHECK_NE(first_cpu, -1) << ": Default affinity has no CPUs?";
1232
Brian Silverman6a54ff32020-04-28 16:41:39 -07001233 auto loop = MakePrimary();
Austin Schuh65493d62022-08-17 15:10:37 -07001234 EXPECT_TRUE(
1235 CpuSetEqual(EventLoop::DefaultAffinity(), loop->runtime_affinity()));
1236 const cpu_set_t new_affinity = MakeCpusetFromCpus({first_cpu});
Brian Silverman6a54ff32020-04-28 16:41:39 -07001237 // Confirm that runtime priority calls work when not running.
Austin Schuh65493d62022-08-17 15:10:37 -07001238 loop->SetRuntimeAffinity(new_affinity);
1239 EXPECT_TRUE(CpuSetEqual(new_affinity, loop->runtime_affinity()));
Brian Silverman6a54ff32020-04-28 16:41:39 -07001240
Austin Schuhde973292021-10-12 18:09:49 -07001241 loop->OnRun(
1242 [&]() { loop->SetRuntimeAffinity(MakeCpusetFromCpus({first_cpu})); });
Brian Silverman6a54ff32020-04-28 16:41:39 -07001243
1244 EXPECT_DEATH(Run(), "Cannot set affinity while running");
1245}
1246
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001247// Verify that registering a watcher and a sender for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001248TEST_P(AbstractEventLoopDeathTest, WatcherAndSender) {
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001249 auto loop = Make();
1250 auto sender = loop->MakeSender<TestMessage>("/test");
1251 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
1252 "/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -08001253}
1254
Austin Schuhe516ab02020-05-06 21:37:04 -07001255// Verify that creating too many senders fails.
1256TEST_P(AbstractEventLoopDeathTest, TooManySenders) {
1257 auto loop = Make();
1258 std::vector<aos::Sender<TestMessage>> senders;
1259 for (int i = 0; i < 10; ++i) {
1260 senders.emplace_back(loop->MakeSender<TestMessage>("/test"));
1261 }
1262 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); },
1263 "Failed to create sender on \\{ \"name\": \"/test\", \"type\": "
Brian Silverman77162972020-08-12 19:52:40 -07001264 "\"aos.TestMessage\"[^}]*\\ }, too many senders.");
1265}
1266
1267// Verify that creating too many fetchers fails.
1268TEST_P(AbstractEventLoopDeathTest, TooManyFetchers) {
1269 if (read_method() != ReadMethod::PIN) {
1270 // Other read methods don't limit the number of readers, so just skip this.
1271 return;
1272 }
1273
1274 auto loop = Make();
1275 std::vector<aos::Fetcher<TestMessage>> fetchers;
1276 for (int i = 0; i < 10; ++i) {
1277 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1278 }
1279 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1280 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1281 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
1282}
1283
1284// Verify that creating too many fetchers, split between two event loops, fails.
1285TEST_P(AbstractEventLoopDeathTest, TooManyFetchersTwoLoops) {
1286 if (read_method() != ReadMethod::PIN) {
1287 // Other read methods don't limit the number of readers, so just skip this.
1288 return;
1289 }
1290
1291 auto loop = Make();
1292 auto loop2 = Make();
1293 std::vector<aos::Fetcher<TestMessage>> fetchers;
1294 for (int i = 0; i < 5; ++i) {
1295 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1296 fetchers.emplace_back(loop2->MakeFetcher<TestMessage>("/test"));
1297 }
1298 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1299 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1300 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
1301}
1302
1303// Verify that creating too many watchers fails.
1304TEST_P(AbstractEventLoopDeathTest, TooManyWatchers) {
1305 if (read_method() != ReadMethod::PIN) {
1306 // Other read methods don't limit the number of readers, so just skip this.
1307 return;
1308 }
1309
1310 std::vector<std::unique_ptr<EventLoop>> loops;
1311 for (int i = 0; i < 10; ++i) {
1312 loops.emplace_back(Make());
1313 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
1314 }
1315 EXPECT_DEATH({ Make()->MakeWatcher("/test", [](const TestMessage &) {}); },
1316 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1317 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
1318}
1319
1320// Verify that creating too many watchers and fetchers combined fails.
1321TEST_P(AbstractEventLoopDeathTest, TooManyWatchersAndFetchers) {
1322 if (read_method() != ReadMethod::PIN) {
1323 // Other read methods don't limit the number of readers, so just skip this.
1324 return;
1325 }
1326
1327 auto loop = Make();
1328 std::vector<aos::Fetcher<TestMessage>> fetchers;
1329 std::vector<std::unique_ptr<EventLoop>> loops;
1330 for (int i = 0; i < 5; ++i) {
1331 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1332 loops.emplace_back(Make());
1333 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
1334 }
1335 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1336 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1337 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
Austin Schuhe516ab02020-05-06 21:37:04 -07001338}
1339
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001340// Verify that we can't create a sender inside OnRun.
1341TEST_P(AbstractEventLoopDeathTest, SenderInOnRun) {
1342 auto loop1 = MakePrimary();
1343
1344 loop1->OnRun(
1345 [&]() { auto sender = loop1->MakeSender<TestMessage>("/test2"); });
1346
1347 EXPECT_DEATH(Run(), "running");
1348}
1349
1350// Verify that we can't create a watcher inside OnRun.
1351TEST_P(AbstractEventLoopDeathTest, WatcherInOnRun) {
1352 auto loop1 = MakePrimary();
1353
1354 loop1->OnRun(
1355 [&]() { loop1->MakeWatcher("/test", [&](const TestMessage &) {}); });
1356
1357 EXPECT_DEATH(Run(), "running");
1358}
1359
Brian Silverman454bc112020-03-05 14:21:25 -08001360// Verify that we can't create a no-arg watcher inside OnRun.
1361TEST_P(AbstractEventLoopDeathTest, NoArgWatcherInOnRun) {
1362 auto loop1 = MakePrimary();
1363
1364 loop1->OnRun(
1365 [&]() { loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {}); });
1366
1367 EXPECT_DEATH(Run(), "running");
1368}
1369
Parker Schuhe4a70d62017-12-27 20:10:20 -08001370// Verify that Quit() works when there are multiple watchers.
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001371TEST_P(AbstractEventLoopTest, MultipleWatcherQuit) {
1372 auto loop1 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -07001373 auto loop2 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -08001374
Austin Schuh3578a2e2019-05-25 18:17:59 -07001375 loop2->MakeWatcher("/test1", [&](const TestMessage &) {});
1376 loop2->MakeWatcher("/test2", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001377 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -07001378 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -07001379 });
1380
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001381 auto sender = loop1->MakeSender<TestMessage>("/test2");
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001382
1383 loop2->OnRun([&]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001384 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1385 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1386 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001387 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001388 });
Parker Schuhe4a70d62017-12-27 20:10:20 -08001389
Austin Schuh44019f92019-05-19 19:58:27 -07001390 Run();
Parker Schuhe4a70d62017-12-27 20:10:20 -08001391}
1392
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001393// Verify that AOS_LOG has the right name.
1394TEST_P(AbstractEventLoopTest, AOSLog) {
1395 auto loop2 = MakePrimary("loop1");
1396 auto loop1 = Make("loop0");
1397
1398 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1399
1400 EXPECT_FALSE(fetcher.Fetch());
1401
1402 loop2->OnRun([&]() {
1403 AOS_LOG(INFO, "Testing123");
1404 this->Exit();
1405 });
1406
1407 Run();
1408 EXPECT_TRUE(fetcher.Fetch());
1409 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1410}
1411
1412// Verify that AOS_LOG has the right name in a watcher.
1413TEST_P(AbstractEventLoopTest, AOSLogWatcher) {
1414 auto loop2 = MakePrimary("loop1");
1415 auto loop1 = Make("loop0");
1416
1417 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1418
1419 EXPECT_FALSE(fetcher.Fetch());
1420
1421 auto sender = loop1->MakeSender<TestMessage>("/test2");
1422
1423 loop2->MakeWatcher("/test2", [&](const TestMessage & /*message*/) {
1424 AOS_LOG(INFO, "Testing123");
1425 this->Exit();
1426 });
1427
1428 loop2->OnRun([&]() {
1429 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1430 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1431 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001432 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001433 });
1434
1435 Run();
1436 EXPECT_TRUE(fetcher.Fetch());
1437 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1438}
1439
1440// Verify that AOS_LOG has the right name in a timer.
1441TEST_P(AbstractEventLoopTest, AOSLogTimer) {
1442 auto loop2 = MakePrimary("loop1");
1443 auto loop1 = Make("loop0");
1444
1445 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1446
1447 EXPECT_FALSE(fetcher.Fetch());
1448
1449 auto test_timer = loop2->AddTimer([&]() {
1450 AOS_LOG(INFO, "Testing123");
1451 this->Exit();
1452 });
1453
Philipp Schradera6712522023-07-05 20:25:11 -07001454 loop2->OnRun([&]() { test_timer->Schedule(loop2->monotonic_now()); });
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001455
1456 Run();
1457 EXPECT_TRUE(fetcher.Fetch());
1458 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1459}
1460
Neil Balch229001a2018-01-07 18:22:52 -08001461// Verify that timer intervals and duration function properly.
1462TEST_P(AbstractEventLoopTest, TimerIntervalAndDuration) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001463 // Force a slower rate so we are guaranteed to have reports for our timer.
Austin Schuh99f7c6a2024-06-25 22:07:44 -07001464 absl::FlagSaver flag_saver;
1465 absl::SetFlag(&FLAGS_timing_report_ms, 2000);
Austin Schuh39788ff2019-12-01 18:22:57 -08001466
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001467 const int kCount = 5;
Neil Balch229001a2018-01-07 18:22:52 -08001468
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001469 auto loop = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001470 auto loop2 = Make();
1471
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001472 ::std::vector<::aos::monotonic_clock::time_point> times;
1473 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
1474
Austin Schuh39788ff2019-12-01 18:22:57 -08001475 Fetcher<timing::Report> report_fetcher =
1476 loop2->MakeFetcher<timing::Report>("/aos");
1477 EXPECT_FALSE(report_fetcher.Fetch());
1478
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001479 auto test_timer = loop->AddTimer([this, &times, &expected_times, &loop]() {
1480 times.push_back(loop->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001481 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07001482 EXPECT_EQ(loop->context().monotonic_remote_transmit_time,
1483 monotonic_clock::min_time);
Austin Schuhad154822019-12-27 15:45:13 -08001484 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
1485 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001486 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -08001487 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
1488 EXPECT_EQ(loop->context().size, 0u);
1489 EXPECT_EQ(loop->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001490 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001491
Austin Schuhad154822019-12-27 15:45:13 -08001492 expected_times.push_back(loop->context().monotonic_event_time);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001493 if (times.size() == kCount) {
1494 this->Exit();
1495 }
Neil Balch229001a2018-01-07 18:22:52 -08001496 });
Austin Schuh39788ff2019-12-01 18:22:57 -08001497 test_timer->set_name("Test loop");
Neil Balch229001a2018-01-07 18:22:52 -08001498
Austin Schuh39788ff2019-12-01 18:22:57 -08001499 const monotonic_clock::time_point start_time = loop->monotonic_now();
Austin Schuh52d325c2019-06-23 18:59:06 -07001500 // TODO(austin): This should be an error... Should be done in OnRun only.
Philipp Schradera6712522023-07-05 20:25:11 -07001501 test_timer->Schedule(start_time + chrono::seconds(1), chrono::seconds(1));
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001502
Austin Schuh44019f92019-05-19 19:58:27 -07001503 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001504
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001505 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001506 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
1507 ASSERT_EQ(times.size(), expected_times.size());
1508 ASSERT_EQ((times.size() % 2), 1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001509
1510 // Grab the middle sample.
1511 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
1512
1513 // Add up all the delays of all the times.
1514 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1515 for (const ::aos::monotonic_clock::time_point time : times) {
1516 sum += time - average_time;
1517 }
1518
1519 // Average and add to the middle to find the average time.
1520 sum /= times.size();
1521 average_time += sum;
1522
1523 // Compute the offset from the average and the expected average. It
1524 // should be pretty close to 0.
1525 const ::aos::monotonic_clock::duration remainder =
1526 average_time - start_time - chrono::seconds(times.size() / 2 + 1);
1527
1528 const chrono::milliseconds kEpsilon(100);
1529 EXPECT_LT(remainder, +kEpsilon);
1530 EXPECT_GT(remainder, -kEpsilon);
1531
1532 // Make sure that the average duration is close to 1 second.
1533 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1534 times.front())
1535 .count() /
1536 static_cast<double>(times.size() - 1),
1537 1.0, 0.1);
1538
1539 // Confirm that the ideal wakeup times increment correctly.
1540 for (size_t i = 1; i < expected_times.size(); ++i) {
1541 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1542 }
1543
1544 for (size_t i = 0; i < expected_times.size(); ++i) {
1545 EXPECT_EQ((expected_times[i] - start_time) % chrono::seconds(1),
1546 chrono::seconds(0));
1547 }
1548
1549 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1550 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001551
Austin Schuh6bae8252021-02-07 22:01:49 -08001552 if (do_timing_reports() == DoTimingReports::kYes) {
1553 // And, since we are here, check that the timing report makes sense.
1554 // Start by looking for our event loop's timing.
1555 FlatbufferDetachedBuffer<timing::Report> report =
1556 FlatbufferDetachedBuffer<timing::Report>::Empty();
1557 while (report_fetcher.FetchNext()) {
1558 if (report_fetcher->name()->string_view() == "primary") {
1559 report = CopyFlatBuffer(report_fetcher.get());
1560 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001561 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001562
1563 // Confirm that we have the right number of reports, and the contents are
1564 // sane.
1565 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
1566
1567 EXPECT_EQ(report.message().name()->string_view(), "primary");
1568
1569 ASSERT_NE(report.message().senders(), nullptr);
1570 EXPECT_EQ(report.message().senders()->size(), 2);
1571
1572 ASSERT_NE(report.message().timers(), nullptr);
1573 EXPECT_EQ(report.message().timers()->size(), 2);
1574
1575 EXPECT_EQ(report.message().timers()->Get(0)->name()->string_view(),
1576 "Test loop");
1577 EXPECT_GE(report.message().timers()->Get(0)->count(), 1);
1578
1579 EXPECT_EQ(report.message().timers()->Get(1)->name()->string_view(),
1580 "timing_reports");
1581 EXPECT_EQ(report.message().timers()->Get(1)->count(), 1);
1582
1583 // Make sure there is a single phased loop report with our report in it.
1584 ASSERT_EQ(report.message().phased_loops(), nullptr);
1585 } else {
1586 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001587 }
Neil Balch229001a2018-01-07 18:22:52 -08001588}
1589
James Kuszmaul762e8692023-07-31 14:57:53 -07001590// Test that setting a default version string results in it getting populated
1591// correctly.
1592TEST_P(AbstractEventLoopTest, DefaultVersionStringInTimingReport) {
Austin Schuh99f7c6a2024-06-25 22:07:44 -07001593 absl::FlagSaver flag_saver;
1594 absl::SetFlag(&FLAGS_timing_report_ms, 1000);
James Kuszmaul762e8692023-07-31 14:57:53 -07001595
1596 EventLoop::SetDefaultVersionString("default_version_string");
1597
1598 auto loop = MakePrimary();
1599
1600 Fetcher<timing::Report> report_fetcher =
1601 loop->MakeFetcher<timing::Report>("/aos");
1602
1603 TimerHandler *exit_timer = loop->AddTimer([this]() { Exit(); });
1604 loop->OnRun([exit_timer, &loop, &report_fetcher]() {
1605 report_fetcher.Fetch();
1606 exit_timer->Schedule(loop->monotonic_now() + std::chrono::seconds(2));
1607 });
1608
1609 Run();
1610
1611 bool found_primary_report = false;
1612 while (report_fetcher.FetchNext()) {
1613 if (report_fetcher->name()->string_view() == "primary") {
1614 found_primary_report = true;
1615 EXPECT_EQ("default_version_string",
1616 report_fetcher->version()->string_view());
1617 } else {
1618 FAIL() << report_fetcher->name()->string_view();
1619 }
1620 }
1621
1622 if (do_timing_reports() == DoTimingReports::kYes) {
1623 EXPECT_TRUE(found_primary_report);
1624 } else {
1625 EXPECT_FALSE(found_primary_report);
1626 }
1627}
1628
1629// Test that overriding the default version string results in it getting
1630// populated correctly.
1631TEST_P(AbstractEventLoopTest, OverrideDersionStringInTimingReport) {
Austin Schuh99f7c6a2024-06-25 22:07:44 -07001632 absl::FlagSaver flag_saver;
1633 absl::SetFlag(&FLAGS_timing_report_ms, 1000);
James Kuszmaul762e8692023-07-31 14:57:53 -07001634
1635 EventLoop::SetDefaultVersionString("default_version_string");
1636
1637 auto loop = MakePrimary();
1638 loop->SetVersionString("override_version");
1639
1640 Fetcher<timing::Report> report_fetcher =
1641 loop->MakeFetcher<timing::Report>("/aos");
1642
1643 TimerHandler *exit_timer = loop->AddTimer([this]() { Exit(); });
1644 loop->OnRun([exit_timer, &loop, &report_fetcher]() {
1645 report_fetcher.Fetch();
1646 exit_timer->Schedule(loop->monotonic_now() + std::chrono::seconds(2));
1647 });
1648
1649 Run();
1650
1651 bool found_primary_report = false;
1652 while (report_fetcher.FetchNext()) {
1653 if (report_fetcher->name()->string_view() == "primary") {
1654 found_primary_report = true;
1655 EXPECT_EQ("override_version", report_fetcher->version()->string_view());
1656 } else {
1657 FAIL() << report_fetcher->name()->string_view();
1658 }
1659 }
1660
1661 if (do_timing_reports() == DoTimingReports::kYes) {
1662 EXPECT_TRUE(found_primary_report);
1663 } else {
1664 EXPECT_FALSE(found_primary_report);
1665 }
1666}
1667
Neil Balch229001a2018-01-07 18:22:52 -08001668// Verify that we can change a timer's parameters during execution.
1669TEST_P(AbstractEventLoopTest, TimerChangeParameters) {
Austin Schuh44019f92019-05-19 19:58:27 -07001670 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001671 loop->SetRuntimeRealtimePriority(1);
Austin Schuh7f20f512021-01-31 17:56:16 -08001672 std::vector<monotonic_clock::time_point> iteration_list;
Neil Balch229001a2018-01-07 18:22:52 -08001673
1674 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001675 ScopedNotRealtime nrt;
Austin Schuh7f20f512021-01-31 17:56:16 -08001676 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001677 });
1678
Austin Schuh7f20f512021-01-31 17:56:16 -08001679 monotonic_clock::time_point s;
1680 auto modifier_timer = loop->AddTimer([&test_timer, &s]() {
Philipp Schradera6712522023-07-05 20:25:11 -07001681 test_timer->Schedule(s + chrono::milliseconds(1750),
1682 chrono::milliseconds(600));
Neil Balch229001a2018-01-07 18:22:52 -08001683 });
1684
Austin Schuh7f20f512021-01-31 17:56:16 -08001685 s = loop->monotonic_now();
Philipp Schradera6712522023-07-05 20:25:11 -07001686 test_timer->Schedule(s, chrono::milliseconds(500));
1687 modifier_timer->Schedule(s + chrono::milliseconds(1250));
Austin Schuhd892f102021-10-12 18:01:46 -07001688 EndEventLoop(loop.get(), chrono::milliseconds(3950));
Austin Schuh44019f92019-05-19 19:58:27 -07001689 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001690
Austin Schuhd892f102021-10-12 18:01:46 -07001691 EXPECT_THAT(
1692 iteration_list,
1693 ::testing::ElementsAre(
1694 s, s + chrono::milliseconds(500), s + chrono::milliseconds(1000),
1695 s + chrono::milliseconds(1750), s + chrono::milliseconds(2350),
1696 s + chrono::milliseconds(2950), s + chrono::milliseconds(3550)));
Neil Balch229001a2018-01-07 18:22:52 -08001697}
1698
1699// Verify that we can disable a timer during execution.
1700TEST_P(AbstractEventLoopTest, TimerDisable) {
Austin Schuh44019f92019-05-19 19:58:27 -07001701 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001702 loop->SetRuntimeRealtimePriority(1);
Neil Balch229001a2018-01-07 18:22:52 -08001703 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
1704
1705 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001706 ScopedNotRealtime nrt;
Austin Schuhd892f102021-10-12 18:01:46 -07001707 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001708 });
1709
Tyler Chatow67ddb032020-01-12 14:30:04 -08001710 auto ender_timer = loop->AddTimer([&test_timer]() { test_timer->Disable(); });
Neil Balch229001a2018-01-07 18:22:52 -08001711
Austin Schuhd892f102021-10-12 18:01:46 -07001712 monotonic_clock::time_point s = loop->monotonic_now();
Philipp Schradera6712522023-07-05 20:25:11 -07001713 test_timer->Schedule(s, ::std::chrono::milliseconds(500));
1714 ender_timer->Schedule(s + ::std::chrono::milliseconds(1250));
Austin Schuh73d99502021-12-08 12:05:39 -08001715 EndEventLoop(loop.get(), ::std::chrono::milliseconds(2000));
Austin Schuh44019f92019-05-19 19:58:27 -07001716 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001717
Austin Schuhd892f102021-10-12 18:01:46 -07001718 EXPECT_THAT(iteration_list,
Austin Schuh73d99502021-12-08 12:05:39 -08001719 ::testing::ElementsAre(s, s + chrono::milliseconds(500),
1720 s + chrono::milliseconds(1000)));
Neil Balch229001a2018-01-07 18:22:52 -08001721}
Austin Schuh7267c532019-05-19 19:55:53 -07001722
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001723// Verify that a timer can disable itself.
1724//
1725// TODO(Brian): Do something similar with phased loops, both with a quick
1726// handler and a handler that would miss a cycle except it got deferred. Current
1727// behavior doing that is a mess.
1728TEST_P(AbstractEventLoopTest, TimerDisableSelf) {
1729 auto loop = MakePrimary();
1730
1731 int count = 0;
1732 aos::TimerHandler *test_timer;
1733 test_timer = loop->AddTimer([&count, &test_timer]() {
1734 ++count;
1735 test_timer->Disable();
1736 });
1737
Philipp Schradera6712522023-07-05 20:25:11 -07001738 test_timer->Schedule(loop->monotonic_now(), ::std::chrono::milliseconds(20));
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001739 EndEventLoop(loop.get(), ::std::chrono::milliseconds(80));
1740 Run();
1741
1742 EXPECT_EQ(count, 1);
1743}
1744
Brian Silvermanbd405c02020-06-23 16:25:23 -07001745// Verify that we can disable a timer during execution of another timer
1746// scheduled for the same time, with one ordering of creation for the timers.
1747//
1748// Also schedule some more events to reshuffle the heap in EventLoop used for
1749// tracking events to change up the order. This used to segfault
1750// SimulatedEventLoop.
1751TEST_P(AbstractEventLoopTest, TimerDisableOther) {
1752 for (bool creation_order : {true, false}) {
1753 for (bool setup_order : {true, false}) {
1754 for (int shuffle_events = 0; shuffle_events < 5; ++shuffle_events) {
1755 auto loop = MakePrimary();
1756 aos::TimerHandler *test_timer, *ender_timer;
1757 if (creation_order) {
1758 test_timer = loop->AddTimer([]() {});
1759 ender_timer =
1760 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1761 } else {
1762 ender_timer =
1763 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1764 test_timer = loop->AddTimer([]() {});
1765 }
1766
1767 const auto start = loop->monotonic_now();
1768
1769 for (int i = 0; i < shuffle_events; ++i) {
Philipp Schradera6712522023-07-05 20:25:11 -07001770 loop->AddTimer([]() {})->Schedule(start +
1771 std::chrono::milliseconds(10));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001772 }
1773
1774 if (setup_order) {
Philipp Schradera6712522023-07-05 20:25:11 -07001775 test_timer->Schedule(start + ::std::chrono::milliseconds(20));
1776 ender_timer->Schedule(start + ::std::chrono::milliseconds(20));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001777 } else {
Philipp Schradera6712522023-07-05 20:25:11 -07001778 ender_timer->Schedule(start + ::std::chrono::milliseconds(20));
1779 test_timer->Schedule(start + ::std::chrono::milliseconds(20));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001780 }
1781 EndEventLoop(loop.get(), ::std::chrono::milliseconds(40));
1782 Run();
1783 }
1784 }
1785 }
1786}
1787
Austin Schuh54cf95f2019-11-29 13:14:18 -08001788// Verifies that the event loop implementations detect when Channel is not a
Brian Silverman631b6262021-11-10 12:25:08 -08001789// pointer into configuration(), or a name doesn't map to a channel in
1790// configuration().
Austin Schuh54cf95f2019-11-29 13:14:18 -08001791TEST_P(AbstractEventLoopDeathTest, InvalidChannel) {
1792 auto loop = MakePrimary();
1793
Tyler Chatow67ddb032020-01-12 14:30:04 -08001794 const Channel *channel = configuration::GetChannel(
1795 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
Austin Schuh54cf95f2019-11-29 13:14:18 -08001796
1797 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1798
1799 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001800 loop->MakeRawSender(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001801 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1802
1803 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001804 loop->MakeSender<TestMessage>("/testbad"),
1805 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1806 " not found in config");
1807
1808 EXPECT_FALSE(loop->TryMakeSender<TestMessage>("/testbad"));
1809
1810 EXPECT_DEATH(
1811 loop->MakeRawFetcher(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001812 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1813
1814 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001815 loop->MakeFetcher<TestMessage>("/testbad"),
1816 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1817 " not found in config");
1818
1819 EXPECT_FALSE(loop->TryMakeFetcher<TestMessage>("/testbad").valid());
1820
1821 EXPECT_DEATH(
Austin Schuh54cf95f2019-11-29 13:14:18 -08001822 {
1823 loop->MakeRawWatcher(&channel_copy.message(),
1824 [](const Context, const void *) {});
1825 },
1826 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
Brian Silverman631b6262021-11-10 12:25:08 -08001827
1828 EXPECT_DEATH(
1829 { loop->MakeWatcher("/testbad", [](const TestMessage &) {}); },
1830 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1831 " not found in config");
1832}
1833
1834// Verifies that the event loop handles a channel which is not readable or
1835// writable on the current node nicely.
1836TEST_P(AbstractEventLoopDeathTest, InaccessibleChannel) {
1837 EnableNodes("me");
1838 auto loop = MakePrimary("me");
1839 auto loop2 = Make("them");
1840
1841 const Channel *channel = configuration::GetChannel(
1842 loop->configuration(), "/test_noforward", "aos.TestMessage", "", nullptr);
1843
1844 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1845
1846 EXPECT_DEATH(
1847 loop2->MakeSender<TestMessage>("/test_forward"),
1848 "Channel"
1849 " \\{ \"name\": \"/test_forward\", \"type\": \"aos.TestMessage\" \\}"
1850 " is not able to be sent on this node");
1851
1852 EXPECT_FALSE(loop2->TryMakeSender<TestMessage>("/test_forward"));
1853
1854 EXPECT_DEATH(
1855 loop2->MakeRawFetcher(channel),
1856 "Channel"
1857 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1858 " is not able to be fetched on this node");
1859
1860 EXPECT_DEATH(
1861 loop2->MakeFetcher<TestMessage>("/test_noforward"),
1862 "Channel"
1863 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1864 " is not able to be fetched on this node");
1865
1866 EXPECT_FALSE(loop2->TryMakeFetcher<TestMessage>("/test_noforward").valid());
1867
1868 EXPECT_DEATH(
1869 { loop2->MakeRawWatcher(channel, [](const Context, const void *) {}); },
1870 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1871 "\"source_node\": \"them\" \\}"
1872 " is not able to be watched on this node");
1873
1874 EXPECT_DEATH(
1875 { loop2->MakeWatcher("/test_noforward", [](const TestMessage &) {}); },
1876 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1877 "\"source_node\": \"them\" \\}"
1878 " is not able to be watched on this node");
Austin Schuh54cf95f2019-11-29 13:14:18 -08001879}
1880
Austin Schuhd54780b2020-10-03 16:26:02 -07001881// Verifies that the event loop implementations detect when Channel has an
1882// invalid alignment.
1883TEST_P(AbstractEventLoopDeathTest, InvalidChannelAlignment) {
1884 const char *const kError = "multiple of alignment";
1885 InvalidChannelAlignment();
1886
1887 auto loop = MakePrimary();
1888
1889 const Channel *channel = configuration::GetChannel(
1890 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
1891
1892 EXPECT_DEATH({ loop->MakeRawSender(channel); }, kError);
1893 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); }, kError);
1894
1895 EXPECT_DEATH({ loop->MakeRawFetcher(channel); }, kError);
1896 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); }, kError);
1897
1898 EXPECT_DEATH(
1899 { loop->MakeRawWatcher(channel, [](const Context &, const void *) {}); },
1900 kError);
1901 EXPECT_DEATH({ loop->MakeRawNoArgWatcher(channel, [](const Context &) {}); },
1902 kError);
1903
1904 EXPECT_DEATH({ loop->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
1905 kError);
1906 EXPECT_DEATH({ loop->MakeWatcher("/test", [](const TestMessage &) {}); },
1907 kError);
1908}
1909
Brian Silverman454bc112020-03-05 14:21:25 -08001910// Verify that the send time on a message is roughly right when using a watcher.
Austin Schuh7267c532019-05-19 19:55:53 -07001911TEST_P(AbstractEventLoopTest, MessageSendTime) {
Austin Schuh44019f92019-05-19 19:58:27 -07001912 auto loop1 = MakePrimary();
Austin Schuh7267c532019-05-19 19:55:53 -07001913 auto loop2 = Make();
Austin Schuhad154822019-12-27 15:45:13 -08001914 auto sender = loop2->MakeSender<TestMessage>("/test");
Austin Schuh7267c532019-05-19 19:55:53 -07001915 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
1916
1917 auto test_timer = loop1->AddTimer([&sender]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001918 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1919 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1920 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001921 msg.CheckOk(msg.Send(builder.Finish()));
Alex Perrycb7da4b2019-08-28 19:35:56 -07001922 });
1923
Austin Schuhad154822019-12-27 15:45:13 -08001924 bool triggered = false;
Brian Silverman454bc112020-03-05 14:21:25 -08001925 loop1->MakeWatcher("/test", [&](const TestMessage &msg) {
Austin Schuhad154822019-12-27 15:45:13 -08001926 // Confirm that the data pointer makes sense from a watcher, and all the
1927 // timestamps look right.
1928 EXPECT_GT(&msg, loop1->context().data);
1929 EXPECT_EQ(loop1->context().monotonic_remote_time,
1930 loop1->context().monotonic_event_time);
1931 EXPECT_EQ(loop1->context().realtime_remote_time,
1932 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001933 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhac6d89e2024-03-27 14:56:09 -07001934 EXPECT_EQ(loop1->context().monotonic_remote_transmit_time,
1935 monotonic_clock::min_time);
Austin Schuhad154822019-12-27 15:45:13 -08001936
1937 const aos::monotonic_clock::time_point monotonic_now =
1938 loop1->monotonic_now();
Tyler Chatow67ddb032020-01-12 14:30:04 -08001939 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08001940
1941 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1942 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1943 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1944 monotonic_now);
1945 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1946 realtime_now);
1947
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001948 EXPECT_LT(&msg, reinterpret_cast<const void *>(
1949 reinterpret_cast<const char *>(loop1->context().data) +
Austin Schuhad154822019-12-27 15:45:13 -08001950 loop1->context().size));
Brian Silverman4f4e0612020-08-12 19:54:41 -07001951 if (read_method() == ReadMethod::PIN) {
1952 EXPECT_GE(loop1->context().buffer_index, 0);
1953 EXPECT_LT(loop1->context().buffer_index,
1954 loop1->NumberBuffers(
1955 configuration::GetChannel(loop1->configuration(), "/test",
1956 "aos.TestMessage", "", nullptr)));
1957 } else {
1958 EXPECT_EQ(-1, loop1->context().buffer_index);
1959 }
Austin Schuhad154822019-12-27 15:45:13 -08001960 triggered = true;
Austin Schuh7267c532019-05-19 19:55:53 -07001961 });
1962
Philipp Schradera6712522023-07-05 20:25:11 -07001963 test_timer->Schedule(loop1->monotonic_now() + ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07001964
1965 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
Austin Schuh44019f92019-05-19 19:58:27 -07001966 Run();
Austin Schuh7267c532019-05-19 19:55:53 -07001967
Austin Schuhad154822019-12-27 15:45:13 -08001968 EXPECT_TRUE(triggered);
1969
Brian Silverman454bc112020-03-05 14:21:25 -08001970 ASSERT_TRUE(fetcher.Fetch());
1971
1972 monotonic_clock::duration monotonic_time_offset =
1973 fetcher.context().monotonic_event_time -
1974 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1975 realtime_clock::duration realtime_time_offset =
1976 fetcher.context().realtime_event_time -
1977 (loop1->realtime_now() - ::std::chrono::seconds(1));
1978
1979 EXPECT_EQ(fetcher.context().realtime_event_time,
1980 fetcher.context().realtime_remote_time);
1981 EXPECT_EQ(fetcher.context().monotonic_event_time,
1982 fetcher.context().monotonic_remote_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07001983 EXPECT_EQ(fetcher.context().monotonic_remote_transmit_time,
1984 monotonic_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001985 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001986
1987 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1988 << ": Got "
1989 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1990 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1991 // Confirm that the data pointer makes sense.
1992 EXPECT_GT(fetcher.get(), fetcher.context().data);
1993 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001994 reinterpret_cast<const void *>(
1995 reinterpret_cast<const char *>(fetcher.context().data) +
Brian Silverman454bc112020-03-05 14:21:25 -08001996 fetcher.context().size));
1997 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1998 << ": Got "
1999 << fetcher.context().monotonic_event_time.time_since_epoch().count()
2000 << " expected " << loop1->monotonic_now().time_since_epoch().count();
2001
2002 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
2003 << ": Got "
2004 << fetcher.context().realtime_event_time.time_since_epoch().count()
2005 << " expected " << loop1->realtime_now().time_since_epoch().count();
2006 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
2007 << ": Got "
2008 << fetcher.context().realtime_event_time.time_since_epoch().count()
2009 << " expected " << loop1->realtime_now().time_since_epoch().count();
2010}
2011
2012// Verify that the send time on a message is roughly right when using a no-arg
2013// watcher. To get a message, we need to use a fetcher to actually access the
2014// message. This is also the main use case for no-arg fetchers.
2015TEST_P(AbstractEventLoopTest, MessageSendTimeNoArg) {
2016 auto loop1 = MakePrimary();
2017 auto loop2 = Make();
2018 auto sender = loop2->MakeSender<TestMessage>("/test");
2019 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
2020
2021 auto test_timer = loop1->AddTimer([&sender]() {
2022 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2023 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2024 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07002025 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -08002026 });
2027
2028 bool triggered = false;
2029 loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {
2030 // Confirm that we can indeed use a fetcher on this channel from this
2031 // context, and it results in a sane data pointer and timestamps.
2032 ASSERT_TRUE(fetcher.Fetch());
2033
2034 EXPECT_EQ(loop1->context().monotonic_remote_time,
2035 loop1->context().monotonic_event_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07002036 EXPECT_EQ(loop1->context().monotonic_remote_transmit_time,
2037 monotonic_clock::min_time);
Brian Silverman454bc112020-03-05 14:21:25 -08002038 EXPECT_EQ(loop1->context().realtime_remote_time,
2039 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002040 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08002041
2042 const aos::monotonic_clock::time_point monotonic_now =
2043 loop1->monotonic_now();
2044 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
2045
2046 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
2047 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
2048 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
2049 monotonic_now);
2050 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
2051 realtime_now);
2052
2053 triggered = true;
2054 });
2055
Philipp Schradera6712522023-07-05 20:25:11 -07002056 test_timer->Schedule(loop1->monotonic_now() + ::std::chrono::seconds(1));
Brian Silverman454bc112020-03-05 14:21:25 -08002057
2058 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
2059 Run();
2060
2061 ASSERT_TRUE(triggered);
Austin Schuh7267c532019-05-19 19:55:53 -07002062
Alex Perrycb7da4b2019-08-28 19:35:56 -07002063 monotonic_clock::duration monotonic_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08002064 fetcher.context().monotonic_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07002065 (loop1->monotonic_now() - ::std::chrono::seconds(1));
2066 realtime_clock::duration realtime_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08002067 fetcher.context().realtime_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07002068 (loop1->realtime_now() - ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07002069
Austin Schuhad154822019-12-27 15:45:13 -08002070 EXPECT_EQ(fetcher.context().realtime_event_time,
2071 fetcher.context().realtime_remote_time);
2072 EXPECT_EQ(fetcher.context().monotonic_event_time,
2073 fetcher.context().monotonic_remote_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07002074 EXPECT_EQ(fetcher.context().monotonic_remote_transmit_time,
2075 monotonic_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002076 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08002077
Alex Perrycb7da4b2019-08-28 19:35:56 -07002078 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
2079 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002080 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh52d325c2019-06-23 18:59:06 -07002081 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07002082 // Confirm that the data pointer makes sense.
2083 EXPECT_GT(fetcher.get(), fetcher.context().data);
2084 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07002085 reinterpret_cast<const void *>(
2086 reinterpret_cast<const char *>(fetcher.context().data) +
Alex Perrycb7da4b2019-08-28 19:35:56 -07002087 fetcher.context().size));
2088 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
2089 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002090 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh7267c532019-05-19 19:55:53 -07002091 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07002092
2093 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
2094 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002095 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07002096 << " expected " << loop1->realtime_now().time_since_epoch().count();
2097 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
2098 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002099 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07002100 << " expected " << loop1->realtime_now().time_since_epoch().count();
Austin Schuh7267c532019-05-19 19:55:53 -07002101}
2102
Austin Schuh52d325c2019-06-23 18:59:06 -07002103// Tests that a couple phased loops run in a row result in the correct offset
2104// and period.
2105TEST_P(AbstractEventLoopTest, PhasedLoopTest) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07002106 // Force a slower rate so we are guaranteed to have reports for our phased
Austin Schuh39788ff2019-12-01 18:22:57 -08002107 // loop.
Austin Schuh99f7c6a2024-06-25 22:07:44 -07002108 absl::FlagSaver flag_saver;
2109 absl::SetFlag(&FLAGS_timing_report_ms, 2000);
Austin Schuh39788ff2019-12-01 18:22:57 -08002110
Austin Schuh52d325c2019-06-23 18:59:06 -07002111 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2112 const int kCount = 5;
2113
2114 auto loop1 = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08002115 auto loop2 = Make();
2116
2117 Fetcher<timing::Report> report_fetcher =
2118 loop2->MakeFetcher<timing::Report>("/aos");
2119 EXPECT_FALSE(report_fetcher.Fetch());
Austin Schuh52d325c2019-06-23 18:59:06 -07002120
2121 // Collect up a couple of samples.
2122 ::std::vector<::aos::monotonic_clock::time_point> times;
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002123 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
Austin Schuh52d325c2019-06-23 18:59:06 -07002124
2125 // Run kCount iterations.
Austin Schuh39788ff2019-12-01 18:22:57 -08002126 loop1
2127 ->AddPhasedLoop(
2128 [&times, &expected_times, &loop1, this](int count) {
2129 EXPECT_EQ(count, 1);
2130 times.push_back(loop1->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08002131 expected_times.push_back(loop1->context().monotonic_event_time);
Austin Schuh39788ff2019-12-01 18:22:57 -08002132
Austin Schuhad154822019-12-27 15:45:13 -08002133 EXPECT_EQ(loop1->context().monotonic_remote_time,
2134 monotonic_clock::min_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07002135 EXPECT_EQ(loop1->context().monotonic_remote_transmit_time,
2136 monotonic_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002137 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08002138 EXPECT_EQ(loop1->context().realtime_event_time,
2139 realtime_clock::min_time);
2140 EXPECT_EQ(loop1->context().realtime_remote_time,
Austin Schuh39788ff2019-12-01 18:22:57 -08002141 realtime_clock::min_time);
2142 EXPECT_EQ(loop1->context().queue_index, 0xffffffffu);
2143 EXPECT_EQ(loop1->context().size, 0u);
2144 EXPECT_EQ(loop1->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07002145 EXPECT_EQ(loop1->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08002146
2147 if (times.size() == kCount) {
2148 LOG(INFO) << "Exiting";
2149 this->Exit();
2150 }
2151 },
2152 chrono::seconds(1), kOffset)
2153 ->set_name("Test loop");
Austin Schuh52d325c2019-06-23 18:59:06 -07002154
2155 // Add a delay to make sure that delay during startup doesn't result in a
2156 // "missed cycle".
2157 SleepFor(chrono::seconds(2));
2158
2159 Run();
2160
2161 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07002162 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
2163 ASSERT_EQ(times.size(), expected_times.size());
2164 ASSERT_EQ((times.size() % 2), 1);
Austin Schuh52d325c2019-06-23 18:59:06 -07002165
2166 // Grab the middle sample.
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002167 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
Austin Schuh52d325c2019-06-23 18:59:06 -07002168
2169 // Add up all the delays of all the times.
2170 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
2171 for (const ::aos::monotonic_clock::time_point time : times) {
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002172 sum += time - average_time;
Austin Schuh52d325c2019-06-23 18:59:06 -07002173 }
2174
2175 // Average and add to the middle to find the average time.
2176 sum /= times.size();
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002177 average_time += sum;
Austin Schuh52d325c2019-06-23 18:59:06 -07002178
2179 // Compute the offset from the start of the second of the average time. This
2180 // should be pretty close to the offset.
2181 const ::aos::monotonic_clock::duration remainder =
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002182 average_time.time_since_epoch() -
2183 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
Austin Schuh52d325c2019-06-23 18:59:06 -07002184
2185 const chrono::milliseconds kEpsilon(100);
2186 EXPECT_LT(remainder, kOffset + kEpsilon);
2187 EXPECT_GT(remainder, kOffset - kEpsilon);
2188
2189 // Make sure that the average duration is close to 1 second.
2190 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
2191 times.front())
2192 .count() /
2193 static_cast<double>(times.size() - 1),
2194 1.0, 0.1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002195
2196 // Confirm that the ideal wakeup times increment correctly.
2197 for (size_t i = 1; i < expected_times.size(); ++i) {
2198 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
2199 }
2200
2201 for (size_t i = 0; i < expected_times.size(); ++i) {
2202 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
2203 kOffset);
2204 }
2205
2206 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
2207 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08002208
Austin Schuh6bae8252021-02-07 22:01:49 -08002209 if (do_timing_reports() == DoTimingReports::kYes) {
2210 // And, since we are here, check that the timing report makes sense.
2211 // Start by looking for our event loop's timing.
2212 FlatbufferDetachedBuffer<timing::Report> report =
2213 FlatbufferDetachedBuffer<timing::Report>::Empty();
2214 while (report_fetcher.FetchNext()) {
2215 if (report_fetcher->name()->string_view() == "primary") {
2216 report = CopyFlatBuffer(report_fetcher.get());
2217 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002218 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002219
2220 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
2221
2222 EXPECT_EQ(report.message().name()->string_view(), "primary");
2223
2224 ASSERT_NE(report.message().senders(), nullptr);
2225 EXPECT_EQ(report.message().senders()->size(), 2);
2226
2227 ASSERT_NE(report.message().timers(), nullptr);
2228 EXPECT_EQ(report.message().timers()->size(), 1);
2229
2230 // Make sure there is a single phased loop report with our report in it.
2231 ASSERT_NE(report.message().phased_loops(), nullptr);
2232 ASSERT_EQ(report.message().phased_loops()->size(), 1);
2233 EXPECT_EQ(report.message().phased_loops()->Get(0)->name()->string_view(),
2234 "Test loop");
2235 EXPECT_GE(report.message().phased_loops()->Get(0)->count(), 1);
2236 } else {
2237 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002238 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002239}
2240
Milind Upadhyay42589bb2021-05-19 20:05:16 -07002241// Tests that a phased loop responds correctly to a changing offset.
2242TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetTest) {
2243 // Force a slower rate so we are guaranteed to have reports for our phased
2244 // loop.
Austin Schuh99f7c6a2024-06-25 22:07:44 -07002245 absl::FlagSaver flag_saver;
2246 absl::SetFlag(&FLAGS_timing_report_ms, 2000);
Milind Upadhyay42589bb2021-05-19 20:05:16 -07002247
2248 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2249 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2250 const int kCount = 5;
2251
2252 auto loop1 = MakePrimary();
2253
2254 // Collect up a couple of samples.
2255 ::std::vector<::aos::monotonic_clock::time_point> times;
2256 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
2257
2258 PhasedLoopHandler *phased_loop;
2259
2260 // Run kCount iterations.
2261 phased_loop = loop1->AddPhasedLoop(
2262 [&phased_loop, &times, &expected_times, &loop1, this, kOffset,
2263 kInterval](int count) {
2264 EXPECT_EQ(count, 1);
2265 times.push_back(loop1->monotonic_now());
2266
2267 expected_times.push_back(loop1->context().monotonic_event_time);
2268
2269 phased_loop->set_interval_and_offset(
2270 kInterval, kOffset - chrono::milliseconds(times.size()));
2271 LOG(INFO) << "new offset: "
2272 << (kOffset - chrono::milliseconds(times.size())).count();
2273
2274 if (times.size() == kCount) {
2275 LOG(INFO) << "Exiting";
2276 this->Exit();
2277 }
2278 },
2279 kInterval, kOffset);
2280 phased_loop->set_name("Test loop");
2281
2282 // Add a delay to make sure that delay during startup doesn't result in a
2283 // "missed cycle".
2284 SleepFor(chrono::seconds(2));
2285
2286 Run();
2287 // Confirm that we got both the right number of samples, and it's odd.
2288 EXPECT_EQ(times.size(), static_cast<size_t>(kCount));
2289 EXPECT_EQ(times.size(), expected_times.size());
2290 EXPECT_EQ((times.size() % 2), 1);
2291
2292 // Grab the middle sample.
2293 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
2294
2295 // Add up all the delays of all the times.
2296 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
2297 for (const ::aos::monotonic_clock::time_point time : times) {
2298 sum += time - average_time;
2299 }
2300
2301 // Average and add to the middle to find the average time.
2302 sum /= times.size();
2303 average_time += sum;
2304
2305 // Compute the offset from the start of the second of the average time. This
2306 // should be pretty close to the offset.
2307 const ::aos::monotonic_clock::duration remainder =
2308 average_time.time_since_epoch() -
2309 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
2310
2311 const chrono::milliseconds kEpsilon(100);
2312 EXPECT_LT(remainder, kOffset + kEpsilon);
2313 EXPECT_GT(remainder, kOffset - kEpsilon);
2314
2315 // Make sure that the average duration is close to 1 second.
2316 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
2317 times.front())
2318 .count() /
2319 static_cast<double>(times.size() - 1),
2320 1.0, 0.1);
2321
2322 // Confirm that the ideal wakeup times increment correctly.
2323 for (size_t i = 1; i < expected_times.size(); ++i) {
2324 LOG(INFO) << i - 1 << ": " << expected_times[i - 1] << ", " << i << ": "
2325 << expected_times[i];
2326 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1) -
2327 chrono::milliseconds(1));
2328 }
2329
2330 for (size_t i = 0; i < expected_times.size(); ++i) {
2331 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
2332 kOffset - chrono::milliseconds(i));
2333 }
2334
2335 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
2336 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
2337}
2338
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002339// Tests that a phased loop responds correctly to a changing offset; sweep
2340// across a variety of potential offset changes, to ensure that we are
2341// exercising a variety of potential cases.
2342TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetSweep) {
2343 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2344 const int kCount = 5;
2345
2346 auto loop1 = MakePrimary();
2347
2348 std::vector<aos::monotonic_clock::duration> offset_options;
2349 for (int ii = 0; ii < kCount; ++ii) {
2350 offset_options.push_back(ii * kInterval / kCount);
2351 }
2352 std::vector<aos::monotonic_clock::duration> offset_sweep;
2353 // Run over all the pair-wise combinations of offsets.
2354 for (int ii = 0; ii < kCount; ++ii) {
2355 for (int jj = 0; jj < kCount; ++jj) {
2356 offset_sweep.push_back(offset_options.at(ii));
2357 offset_sweep.push_back(offset_options.at(jj));
2358 }
2359 }
2360
2361 std::vector<::aos::monotonic_clock::time_point> expected_times;
2362
2363 PhasedLoopHandler *phased_loop;
2364
2365 // Run kCount iterations.
2366 size_t counter = 0;
2367 phased_loop = loop1->AddPhasedLoop(
2368 [&phased_loop, &expected_times, &loop1, this, kInterval, &counter,
2369 offset_sweep](int count) {
2370 EXPECT_EQ(count, 1);
2371 expected_times.push_back(loop1->context().monotonic_event_time);
2372
2373 counter++;
2374
2375 if (counter == offset_sweep.size()) {
2376 LOG(INFO) << "Exiting";
2377 this->Exit();
2378 return;
2379 }
2380
2381 phased_loop->set_interval_and_offset(kInterval,
2382 offset_sweep.at(counter));
2383 },
2384 kInterval, offset_sweep.at(0));
2385
2386 Run();
2387 ASSERT_EQ(expected_times.size(), offset_sweep.size());
2388 for (size_t ii = 1; ii < expected_times.size(); ++ii) {
2389 EXPECT_LE(expected_times.at(ii) - expected_times.at(ii - 1), kInterval);
2390 }
2391}
2392
2393// Tests that a phased loop responds correctly to being rescheduled with now
2394// equal to a time in the past.
2395TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleInPast) {
2396 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2397 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2398
2399 auto loop1 = MakePrimary();
2400
2401 std::vector<::aos::monotonic_clock::time_point> expected_times;
2402
2403 PhasedLoopHandler *phased_loop;
2404
2405 int expected_count = 1;
2406
2407 // Set up a timer that will get run immediately after the phased loop and
2408 // which will attempt to reschedule the phased loop to just before now. This
2409 // should succeed, but will result in 0 cycles elapsing.
2410 TimerHandler *manager_timer =
2411 loop1->AddTimer([&phased_loop, &loop1, &expected_count, this]() {
2412 if (expected_count == 0) {
2413 LOG(INFO) << "Exiting";
2414 this->Exit();
2415 return;
2416 }
2417 phased_loop->Reschedule(loop1->context().monotonic_event_time -
2418 std::chrono::nanoseconds(1));
2419 expected_count = 0;
2420 });
2421
2422 phased_loop = loop1->AddPhasedLoop(
2423 [&expected_count, &expected_times, &loop1, manager_timer](int count) {
2424 EXPECT_EQ(count, expected_count);
2425 expected_times.push_back(loop1->context().monotonic_event_time);
2426
Philipp Schradera6712522023-07-05 20:25:11 -07002427 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002428 },
2429 kInterval, kOffset);
2430 phased_loop->set_name("Test loop");
2431 manager_timer->set_name("Manager timer");
2432
2433 Run();
2434
2435 ASSERT_EQ(2u, expected_times.size());
2436 ASSERT_EQ(expected_times[0], expected_times[1]);
2437}
2438
2439// Tests that a phased loop responds correctly to being rescheduled at the time
2440// when it should be triggering (it should kick the trigger to the next cycle).
2441TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleNow) {
2442 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2443 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2444
2445 auto loop1 = MakePrimary();
2446
2447 std::vector<::aos::monotonic_clock::time_point> expected_times;
2448
2449 PhasedLoopHandler *phased_loop;
2450
2451 bool should_exit = false;
2452 // Set up a timer that will get run immediately after the phased loop and
2453 // which will attempt to reschedule the phased loop to now. This should
2454 // succeed, but will result in no change to the expected behavior (since this
2455 // is the same thing that is actually done internally).
2456 TimerHandler *manager_timer =
2457 loop1->AddTimer([&phased_loop, &loop1, &should_exit, this]() {
2458 if (should_exit) {
2459 LOG(INFO) << "Exiting";
2460 this->Exit();
2461 return;
2462 }
2463 phased_loop->Reschedule(loop1->context().monotonic_event_time);
2464 should_exit = true;
2465 });
2466
2467 phased_loop = loop1->AddPhasedLoop(
2468 [&expected_times, &loop1, manager_timer](int count) {
2469 EXPECT_EQ(count, 1);
2470 expected_times.push_back(loop1->context().monotonic_event_time);
2471
Philipp Schradera6712522023-07-05 20:25:11 -07002472 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002473 },
2474 kInterval, kOffset);
2475 phased_loop->set_name("Test loop");
2476 manager_timer->set_name("Manager timer");
2477
2478 Run();
2479
2480 ASSERT_EQ(2u, expected_times.size());
2481 ASSERT_EQ(expected_times[0] + kInterval, expected_times[1]);
2482}
2483
2484// Tests that a phased loop responds correctly to being rescheduled at a time in
2485// the distant future.
2486TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleFuture) {
2487 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2488 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2489
2490 auto loop1 = MakePrimary();
2491
2492 std::vector<::aos::monotonic_clock::time_point> expected_times;
2493
2494 PhasedLoopHandler *phased_loop;
2495
2496 bool should_exit = false;
2497 int expected_count = 1;
2498 TimerHandler *manager_timer = loop1->AddTimer(
2499 [&expected_count, &phased_loop, &loop1, &should_exit, this, kInterval]() {
2500 if (should_exit) {
2501 LOG(INFO) << "Exiting";
2502 this->Exit();
2503 return;
2504 }
2505 expected_count = 10;
2506 // Knock off 1 ns, since the scheduler rounds up when it is
2507 // scheduled to exactly a loop time.
2508 phased_loop->Reschedule(loop1->context().monotonic_event_time +
2509 kInterval * expected_count -
2510 std::chrono::nanoseconds(1));
2511 should_exit = true;
2512 });
2513
2514 phased_loop = loop1->AddPhasedLoop(
2515 [&expected_times, &loop1, manager_timer, &expected_count](int count) {
2516 EXPECT_EQ(count, expected_count);
2517 expected_times.push_back(loop1->context().monotonic_event_time);
2518
Philipp Schradera6712522023-07-05 20:25:11 -07002519 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002520 },
2521 kInterval, kOffset);
2522 phased_loop->set_name("Test loop");
2523 manager_timer->set_name("Manager timer");
2524
2525 Run();
2526
2527 ASSERT_EQ(2u, expected_times.size());
2528 ASSERT_EQ(expected_times[0] + expected_count * kInterval, expected_times[1]);
2529}
2530
2531// Tests that a phased loop responds correctly to having its phase offset
2532// incremented and then being scheduled after a set time, exercising a pattern
2533// where a phased loop's offset is changed while trying to maintain the trigger
2534// at a consistent period.
2535TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleWithLaterOffset) {
2536 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2537 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2538
2539 auto loop1 = MakePrimary();
2540
2541 std::vector<::aos::monotonic_clock::time_point> expected_times;
2542
2543 PhasedLoopHandler *phased_loop;
2544
2545 bool should_exit = false;
2546 TimerHandler *manager_timer = loop1->AddTimer(
2547 [&phased_loop, &loop1, &should_exit, this, kInterval, kOffset]() {
2548 if (should_exit) {
2549 LOG(INFO) << "Exiting";
2550 this->Exit();
2551 return;
2552 }
2553 // Schedule the next callback to be strictly later than the current time
2554 // + interval / 2, to ensure a consistent frequency.
2555 monotonic_clock::time_point half_time =
2556 loop1->context().monotonic_event_time + kInterval / 2;
2557 phased_loop->set_interval_and_offset(
2558 kInterval, kOffset + std::chrono::nanoseconds(1), half_time);
2559 phased_loop->Reschedule(half_time);
2560 should_exit = true;
2561 });
2562
2563 phased_loop = loop1->AddPhasedLoop(
2564 [&expected_times, &loop1, manager_timer](int count) {
2565 EXPECT_EQ(1, count);
2566 expected_times.push_back(loop1->context().monotonic_event_time);
2567
Philipp Schradera6712522023-07-05 20:25:11 -07002568 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002569 },
2570 kInterval, kOffset);
2571 phased_loop->set_name("Test loop");
2572 manager_timer->set_name("Manager timer");
2573
2574 Run();
2575
2576 ASSERT_EQ(2u, expected_times.size());
2577 ASSERT_EQ(expected_times[0] + kInterval + std::chrono::nanoseconds(1),
2578 expected_times[1]);
2579}
2580
2581// Tests that a phased loop responds correctly to having its phase offset
2582// decremented and then being scheduled after a set time, exercising a pattern
2583// where a phased loop's offset is changed while trying to maintain the trigger
2584// at a consistent period.
2585TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleWithEarlierOffset) {
2586 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2587 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2588
2589 auto loop1 = MakePrimary();
2590
2591 std::vector<::aos::monotonic_clock::time_point> expected_times;
2592
2593 PhasedLoopHandler *phased_loop;
2594
2595 bool should_exit = false;
2596 TimerHandler *manager_timer = loop1->AddTimer(
2597 [&phased_loop, &loop1, &should_exit, this, kInterval, kOffset]() {
2598 if (should_exit) {
2599 LOG(INFO) << "Exiting";
2600 this->Exit();
2601 return;
2602 }
2603 // Schedule the next callback to be strictly later than the current time
2604 // + interval / 2, to ensure a consistent frequency.
2605 const aos::monotonic_clock::time_point half_time =
2606 loop1->context().monotonic_event_time + kInterval / 2;
2607 phased_loop->set_interval_and_offset(
2608 kInterval, kOffset - std::chrono::nanoseconds(1), half_time);
2609 phased_loop->Reschedule(half_time);
2610 should_exit = true;
2611 });
2612
2613 phased_loop = loop1->AddPhasedLoop(
2614 [&expected_times, &loop1, manager_timer](int count) {
2615 EXPECT_EQ(1, count);
2616 expected_times.push_back(loop1->context().monotonic_event_time);
2617
Philipp Schradera6712522023-07-05 20:25:11 -07002618 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002619 },
2620 kInterval, kOffset);
2621 phased_loop->set_name("Test loop");
2622 manager_timer->set_name("Manager timer");
2623
2624 Run();
2625
2626 ASSERT_EQ(2u, expected_times.size());
2627 ASSERT_EQ(expected_times[0] + kInterval - std::chrono::nanoseconds(1),
2628 expected_times[1]);
2629}
2630
Austin Schuh39788ff2019-12-01 18:22:57 -08002631// Tests that senders count correctly in the timing report.
2632TEST_P(AbstractEventLoopTest, SenderTimingReport) {
Austin Schuh99f7c6a2024-06-25 22:07:44 -07002633 absl::FlagSaver flag_saver;
2634 absl::SetFlag(&FLAGS_timing_report_ms, 1000);
Austin Schuh39788ff2019-12-01 18:22:57 -08002635 auto loop1 = MakePrimary();
2636
2637 auto loop2 = Make("watcher_loop");
2638 loop2->MakeWatcher("/test", [](const TestMessage &) {});
2639
2640 auto loop3 = Make();
2641
2642 Fetcher<timing::Report> report_fetcher =
2643 loop3->MakeFetcher<timing::Report>("/aos");
2644 EXPECT_FALSE(report_fetcher.Fetch());
2645
2646 auto sender = loop1->MakeSender<TestMessage>("/test");
2647
James Kuszmaul78514332022-04-06 15:08:34 -07002648 // Sanity check channel frequencies to ensure that we've designed the test
2649 // correctly.
2650 ASSERT_EQ(800, sender.channel()->frequency());
Austin Schuhfff9c3a2023-06-16 18:48:23 -07002651 ASSERT_EQ(2000000000, configuration::ChannelStorageDuration(
2652 loop1->configuration(), sender.channel())
2653 .count());
James Kuszmaul78514332022-04-06 15:08:34 -07002654 constexpr int kMaxAllowedMessages = 800 * 2;
2655 constexpr int kSendMessages = kMaxAllowedMessages * 2;
2656 constexpr int kDroppedMessages = kSendMessages - kMaxAllowedMessages;
2657
Austin Schuh39788ff2019-12-01 18:22:57 -08002658 // Add a timer to actually quit.
2659 auto test_timer = loop1->AddTimer([&sender]() {
James Kuszmaul78514332022-04-06 15:08:34 -07002660 for (int i = 0; i < kSendMessages; ++i) {
Austin Schuh39788ff2019-12-01 18:22:57 -08002661 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2662 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2663 builder.add_value(200 + i);
James Kuszmaul78514332022-04-06 15:08:34 -07002664 if (i < kMaxAllowedMessages) {
2665 msg.CheckOk(msg.Send(builder.Finish()));
2666 } else {
2667 EXPECT_EQ(RawSender::Error::kMessagesSentTooFast,
2668 msg.Send(builder.Finish()));
2669 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002670 }
2671 });
2672
2673 // Quit after 1 timing report, mid way through the next cycle.
2674 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2675
2676 loop1->OnRun([&test_timer, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002677 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1500));
Austin Schuh39788ff2019-12-01 18:22:57 -08002678 });
2679
2680 Run();
2681
Austin Schuh6bae8252021-02-07 22:01:49 -08002682 if (do_timing_reports() == DoTimingReports::kYes) {
2683 // And, since we are here, check that the timing report makes sense.
2684 // Start by looking for our event loop's timing.
2685 FlatbufferDetachedBuffer<timing::Report> primary_report =
2686 FlatbufferDetachedBuffer<timing::Report>::Empty();
2687 while (report_fetcher.FetchNext()) {
Austin Schuh8902fa52021-03-14 22:39:24 -07002688 VLOG(1) << "Report " << FlatbufferToJson(report_fetcher.get());
Austin Schuh6bae8252021-02-07 22:01:49 -08002689 if (report_fetcher->name()->string_view() == "primary") {
2690 primary_report = CopyFlatBuffer(report_fetcher.get());
2691 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002692 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002693
Austin Schuh8902fa52021-03-14 22:39:24 -07002694 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
Austin Schuh6bae8252021-02-07 22:01:49 -08002695
2696 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2697
2698 ASSERT_NE(primary_report.message().senders(), nullptr);
2699 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2700
2701 // Confirm that the sender looks sane.
2702 EXPECT_EQ(
2703 loop1->configuration()
2704 ->channels()
2705 ->Get(primary_report.message().senders()->Get(0)->channel_index())
2706 ->name()
2707 ->string_view(),
2708 "/test");
James Kuszmaul78514332022-04-06 15:08:34 -07002709 EXPECT_EQ(primary_report.message().senders()->Get(0)->count(),
2710 kMaxAllowedMessages);
2711 ASSERT_TRUE(primary_report.message().senders()->Get(0)->has_error_counts());
2712 ASSERT_EQ(
2713 primary_report.message().senders()->Get(0)->error_counts()->size(), 2u);
2714 EXPECT_EQ(
2715 primary_report.message()
2716 .senders()
2717 ->Get(0)
2718 ->error_counts()
2719 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2720 ->count(),
2721 kDroppedMessages)
2722 << aos::FlatbufferToJson(primary_report);
2723 EXPECT_EQ(primary_report.message()
2724 .senders()
2725 ->Get(0)
2726 ->error_counts()
2727 ->Get(static_cast<size_t>(timing::SendError::INVALID_REDZONE))
2728 ->count(),
2729 0);
Austin Schuh6bae8252021-02-07 22:01:49 -08002730
2731 // Confirm that the timing primary_report sender looks sane.
2732 EXPECT_EQ(
2733 loop1->configuration()
2734 ->channels()
2735 ->Get(primary_report.message().senders()->Get(1)->channel_index())
2736 ->name()
2737 ->string_view(),
2738 "/aos");
2739 EXPECT_EQ(primary_report.message().senders()->Get(1)->count(), 1);
2740
2741 ASSERT_NE(primary_report.message().timers(), nullptr);
2742 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2743
2744 // Make sure there are no phased loops or watchers.
2745 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2746 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2747 } else {
2748 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002749 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002750}
2751
James Kuszmaul93abac12022-04-14 15:05:10 -07002752// Tests that the RawSender::Send(void*, size_t) overload tracks things properly
2753// in its timing report.
2754TEST_P(AbstractEventLoopTest, CopySenderTimingReport) {
Austin Schuh99f7c6a2024-06-25 22:07:44 -07002755 absl::FlagSaver flag_saver;
2756 absl::SetFlag(&FLAGS_timing_report_ms, 1000);
James Kuszmaul93abac12022-04-14 15:05:10 -07002757 auto loop1 = Make();
2758 auto loop2 = MakePrimary();
2759
2760 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2761 JsonToFlatbuffer<TestMessage>("{}");
2762
2763 std::unique_ptr<aos::RawSender> sender =
2764 loop2->MakeRawSender(configuration::GetChannel(
2765 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
2766
2767 Fetcher<timing::Report> report_fetcher =
2768 loop1->MakeFetcher<timing::Report>("/aos");
2769 EXPECT_FALSE(report_fetcher.Fetch());
2770
2771 loop2->OnRun([&]() {
2772 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
2773 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2774 RawSender::Error::kOk);
2775 }
2776 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2777 RawSender::Error::kMessagesSentTooFast);
2778 });
2779 // Quit after 1 timing report, mid way through the next cycle.
2780 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
2781
2782 Run();
2783
2784 if (do_timing_reports() == DoTimingReports::kYes) {
2785 // Check that the sent too fast actually got recorded by the timing report.
2786 FlatbufferDetachedBuffer<timing::Report> primary_report =
2787 FlatbufferDetachedBuffer<timing::Report>::Empty();
2788 while (report_fetcher.FetchNext()) {
2789 if (report_fetcher->name()->string_view() == "primary") {
2790 primary_report = CopyFlatBuffer(report_fetcher.get());
2791 }
2792 }
2793
2794 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2795
2796 ASSERT_NE(primary_report.message().senders(), nullptr);
2797 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2798 EXPECT_EQ(
2799 primary_report.message()
2800 .senders()
2801 ->Get(0)
2802 ->error_counts()
2803 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2804 ->count(),
2805 1);
2806 }
2807}
2808
Austin Schuhe0ab4de2023-05-03 08:05:08 -07002809// Tests that the RawSender::Send(SharedSpan) overload works.
2810TEST_P(AbstractEventLoopTest, SharedSenderTimingReport) {
Austin Schuh99f7c6a2024-06-25 22:07:44 -07002811 absl::FlagSaver flag_saver;
2812 absl::SetFlag(&FLAGS_timing_report_ms, 1000);
Austin Schuhe0ab4de2023-05-03 08:05:08 -07002813 auto loop1 = Make();
2814 auto loop2 = MakePrimary();
2815
2816 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2817 JsonToFlatbuffer<TestMessage>("{}");
2818
2819 std::unique_ptr<aos::RawSender> sender =
2820 loop2->MakeRawSender(configuration::GetChannel(
2821 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
2822
2823 Fetcher<timing::Report> report_fetcher =
2824 loop1->MakeFetcher<timing::Report>("/aos");
2825 EXPECT_FALSE(report_fetcher.Fetch());
2826
2827 loop2->OnRun([&]() {
2828 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
2829 auto shared_span = MakeSharedSpan(kMessage.span().size());
2830 memcpy(shared_span.second.data(), kMessage.span().data(),
2831 kMessage.span().size());
2832 EXPECT_EQ(sender->Send(std::move(shared_span.first)),
2833 RawSender::Error::kOk);
2834 }
2835 auto shared_span = MakeSharedSpan(kMessage.span().size());
2836 memcpy(shared_span.second.data(), kMessage.span().data(),
2837 kMessage.span().size());
2838 EXPECT_EQ(sender->Send(std::move(shared_span.first)),
2839 RawSender::Error::kMessagesSentTooFast);
2840 });
2841 // Quit after 1 timing report, mid way through the next cycle.
2842 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
2843
2844 Run();
2845
2846 if (do_timing_reports() == DoTimingReports::kYes) {
2847 // Check that the sent too fast actually got recorded by the timing report.
2848 FlatbufferDetachedBuffer<timing::Report> primary_report =
2849 FlatbufferDetachedBuffer<timing::Report>::Empty();
2850 while (report_fetcher.FetchNext()) {
2851 if (report_fetcher->name()->string_view() == "primary") {
2852 primary_report = CopyFlatBuffer(report_fetcher.get());
2853 }
2854 }
2855
2856 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2857
2858 ASSERT_NE(primary_report.message().senders(), nullptr);
2859 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2860 EXPECT_EQ(
2861 primary_report.message()
2862 .senders()
2863 ->Get(0)
2864 ->error_counts()
2865 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2866 ->count(),
2867 1);
2868 }
2869}
2870
Austin Schuh39788ff2019-12-01 18:22:57 -08002871// Tests that senders count correctly in the timing report.
2872TEST_P(AbstractEventLoopTest, WatcherTimingReport) {
Austin Schuh99f7c6a2024-06-25 22:07:44 -07002873 absl::SetFlag(&FLAGS_timing_report_ms, 1000);
Austin Schuh39788ff2019-12-01 18:22:57 -08002874 auto loop1 = MakePrimary();
2875 loop1->MakeWatcher("/test", [](const TestMessage &) {});
2876
2877 auto loop2 = Make("sender_loop");
2878
2879 auto loop3 = Make();
2880
2881 Fetcher<timing::Report> report_fetcher =
2882 loop3->MakeFetcher<timing::Report>("/aos");
2883 EXPECT_FALSE(report_fetcher.Fetch());
2884
2885 auto sender = loop2->MakeSender<TestMessage>("/test");
2886
2887 // Add a timer to actually quit.
2888 auto test_timer = loop1->AddTimer([&sender]() {
2889 for (int i = 0; i < 10; ++i) {
2890 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2891 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2892 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002893 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002894 }
2895 });
2896
2897 // Quit after 1 timing report, mid way through the next cycle.
2898 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2899
2900 loop1->OnRun([&test_timer, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002901 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1500));
Austin Schuh39788ff2019-12-01 18:22:57 -08002902 });
2903
2904 Run();
2905
Austin Schuh6bae8252021-02-07 22:01:49 -08002906 if (do_timing_reports() == DoTimingReports::kYes) {
2907 // And, since we are here, check that the timing report makes sense.
2908 // Start by looking for our event loop's timing.
2909 FlatbufferDetachedBuffer<timing::Report> primary_report =
2910 FlatbufferDetachedBuffer<timing::Report>::Empty();
2911 while (report_fetcher.FetchNext()) {
2912 LOG(INFO) << "Report " << FlatbufferToJson(report_fetcher.get());
2913 if (report_fetcher->name()->string_view() == "primary") {
2914 primary_report = CopyFlatBuffer(report_fetcher.get());
2915 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002916 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002917
2918 // Check the watcher report.
2919 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2920
2921 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2922
2923 // Just the timing report timer.
2924 ASSERT_NE(primary_report.message().timers(), nullptr);
2925 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2926
2927 // No phased loops
2928 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2929
2930 ASSERT_NE(primary_report.message().watchers(), nullptr);
2931 ASSERT_EQ(primary_report.message().watchers()->size(), 1);
2932 EXPECT_EQ(primary_report.message().watchers()->Get(0)->count(), 10);
2933 } else {
2934 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002935 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002936}
2937
2938// Tests that fetchers count correctly in the timing report.
2939TEST_P(AbstractEventLoopTest, FetcherTimingReport) {
Austin Schuh99f7c6a2024-06-25 22:07:44 -07002940 absl::SetFlag(&FLAGS_timing_report_ms, 1000);
Austin Schuh39788ff2019-12-01 18:22:57 -08002941 auto loop1 = MakePrimary();
2942 auto loop2 = Make("sender_loop");
2943
2944 auto loop3 = Make();
2945
2946 Fetcher<timing::Report> report_fetcher =
2947 loop3->MakeFetcher<timing::Report>("/aos");
2948 EXPECT_FALSE(report_fetcher.Fetch());
2949
2950 auto sender = loop2->MakeSender<TestMessage>("/test");
2951 auto fetcher1 = loop1->MakeFetcher<TestMessage>("/test");
2952 auto fetcher2 = loop1->MakeFetcher<TestMessage>("/test");
2953 fetcher1.Fetch();
2954 fetcher2.Fetch();
2955
2956 // Add a timer to actually quit.
2957 auto test_timer = loop1->AddTimer([&sender]() {
2958 for (int i = 0; i < 10; ++i) {
2959 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2960 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2961 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002962 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002963 }
2964 });
2965
2966 auto test_timer2 = loop1->AddTimer([&fetcher1, &fetcher2]() {
2967 fetcher1.Fetch();
2968 while (fetcher2.FetchNext()) {
2969 }
2970 });
2971
2972 // Quit after 1 timing report, mid way through the next cycle.
2973 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2974
2975 loop1->OnRun([test_timer, test_timer2, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002976 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1400));
2977 test_timer2->Schedule(loop1->monotonic_now() + chrono::milliseconds(1600));
Austin Schuh39788ff2019-12-01 18:22:57 -08002978 });
2979
2980 Run();
2981
Austin Schuh6bae8252021-02-07 22:01:49 -08002982 if (do_timing_reports() == DoTimingReports::kYes) {
2983 // And, since we are here, check that the timing report makes sense.
2984 // Start by looking for our event loop's timing.
2985 FlatbufferDetachedBuffer<timing::Report> primary_report =
2986 FlatbufferDetachedBuffer<timing::Report>::Empty();
2987 while (report_fetcher.FetchNext()) {
2988 if (report_fetcher->name()->string_view() == "primary") {
2989 primary_report = CopyFlatBuffer(report_fetcher.get());
2990 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002991 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002992
2993 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2994
2995 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2996
2997 ASSERT_NE(primary_report.message().senders(), nullptr);
2998 EXPECT_EQ(primary_report.message().senders()->size(), 2);
2999
3000 ASSERT_NE(primary_report.message().timers(), nullptr);
3001 EXPECT_EQ(primary_report.message().timers()->size(), 4);
3002
3003 // Make sure there are no phased loops or watchers.
3004 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
3005 ASSERT_EQ(primary_report.message().watchers(), nullptr);
3006
3007 // Now look at the fetchrs.
3008 ASSERT_NE(primary_report.message().fetchers(), nullptr);
3009 ASSERT_EQ(primary_report.message().fetchers()->size(), 2);
3010
3011 EXPECT_EQ(primary_report.message().fetchers()->Get(0)->count(), 1);
3012 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->average(),
3013 0.1);
3014 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->min(),
3015 0.1);
3016 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->max(),
3017 0.1);
3018 EXPECT_EQ(primary_report.message()
3019 .fetchers()
3020 ->Get(0)
3021 ->latency()
3022 ->standard_deviation(),
3023 0.0);
3024
3025 EXPECT_EQ(primary_report.message().fetchers()->Get(1)->count(), 10);
3026 } else {
3027 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08003028 }
Austin Schuh52d325c2019-06-23 18:59:06 -07003029}
3030
Austin Schuh67420a42019-12-21 21:55:04 -08003031// Tests that a raw watcher and raw fetcher can receive messages from a raw
3032// sender without messing up offsets.
3033TEST_P(AbstractEventLoopTest, RawBasic) {
3034 auto loop1 = Make();
3035 auto loop2 = MakePrimary();
3036 auto loop3 = Make();
3037
Austin Schuha9df9ad2021-06-16 14:49:39 -07003038 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3039 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuh67420a42019-12-21 21:55:04 -08003040
3041 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003042 loop1->MakeRawSender(configuration::GetChannel(
3043 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08003044
3045 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003046 loop3->MakeRawFetcher(configuration::GetChannel(
3047 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08003048
Austin Schuha9df9ad2021-06-16 14:49:39 -07003049 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07003050 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
3051 RawSender::Error::kOk);
Austin Schuha9df9ad2021-06-16 14:49:39 -07003052 });
Austin Schuh67420a42019-12-21 21:55:04 -08003053
3054 bool happened = false;
3055 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08003056 configuration::GetChannel(loop2->configuration(), "/test",
3057 "aos.TestMessage", "", nullptr),
Austin Schuha9df9ad2021-06-16 14:49:39 -07003058 [this, &kMessage, &fetcher, &happened](const Context &context,
3059 const void *message) {
Austin Schuh67420a42019-12-21 21:55:04 -08003060 happened = true;
Austin Schuha9df9ad2021-06-16 14:49:39 -07003061 EXPECT_EQ(
3062 kMessage.span(),
3063 absl::Span<const uint8_t>(
3064 reinterpret_cast<const uint8_t *>(message), context.size));
3065 EXPECT_EQ(message, context.data);
Austin Schuh67420a42019-12-21 21:55:04 -08003066
3067 ASSERT_TRUE(fetcher->Fetch());
3068
Austin Schuha9df9ad2021-06-16 14:49:39 -07003069 EXPECT_EQ(kMessage.span(),
3070 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
3071 fetcher->context().data),
3072 fetcher->context().size));
Austin Schuh67420a42019-12-21 21:55:04 -08003073
3074 this->Exit();
3075 });
3076
3077 EXPECT_FALSE(happened);
3078 Run();
3079 EXPECT_TRUE(happened);
3080}
3081
Austin Schuhad154822019-12-27 15:45:13 -08003082// Tests that a raw watcher and raw fetcher can receive messages from a raw
Brian Silvermanbf889922021-11-10 12:41:57 -08003083// sender without messing up offsets, using the RawSpan overload.
3084TEST_P(AbstractEventLoopTest, RawBasicSharedSpan) {
3085 auto loop1 = Make();
3086 auto loop2 = MakePrimary();
3087 auto loop3 = Make();
3088
3089 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3090 JsonToFlatbuffer<TestMessage>("{}");
3091
3092 std::unique_ptr<aos::RawSender> sender =
3093 loop1->MakeRawSender(configuration::GetChannel(
3094 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
3095
3096 std::unique_ptr<aos::RawFetcher> fetcher =
3097 loop3->MakeRawFetcher(configuration::GetChannel(
3098 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
3099
3100 loop2->OnRun([&]() {
Austin Schuhe0ab4de2023-05-03 08:05:08 -07003101 auto shared_span = MakeSharedSpan(kMessage.span().size());
3102 memcpy(shared_span.second.data(), kMessage.span().data(),
3103 kMessage.span().size());
3104 sender->CheckOk(sender->Send(std::move(shared_span.first)));
Brian Silvermanbf889922021-11-10 12:41:57 -08003105 });
3106
3107 bool happened = false;
3108 loop2->MakeRawWatcher(
3109 configuration::GetChannel(loop2->configuration(), "/test",
3110 "aos.TestMessage", "", nullptr),
3111 [this, &kMessage, &fetcher, &happened](const Context &context,
3112 const void *message) {
3113 happened = true;
3114 EXPECT_EQ(
3115 kMessage.span(),
3116 absl::Span<const uint8_t>(
3117 reinterpret_cast<const uint8_t *>(message), context.size));
3118 EXPECT_EQ(message, context.data);
3119
3120 ASSERT_TRUE(fetcher->Fetch());
3121
3122 EXPECT_EQ(kMessage.span(),
3123 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
3124 fetcher->context().data),
3125 fetcher->context().size));
3126
3127 this->Exit();
3128 });
3129
3130 EXPECT_FALSE(happened);
3131 Run();
3132 EXPECT_TRUE(happened);
3133}
3134
3135// Tests that a raw watcher and raw fetcher can receive messages from a raw
Austin Schuhad154822019-12-27 15:45:13 -08003136// sender with remote times filled out.
3137TEST_P(AbstractEventLoopTest, RawRemoteTimes) {
3138 auto loop1 = Make();
3139 auto loop2 = MakePrimary();
3140 auto loop3 = Make();
3141
Austin Schuha9df9ad2021-06-16 14:49:39 -07003142 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3143 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08003144
3145 const aos::monotonic_clock::time_point monotonic_remote_time =
3146 aos::monotonic_clock::time_point(chrono::seconds(1501));
3147 const aos::realtime_clock::time_point realtime_remote_time =
3148 aos::realtime_clock::time_point(chrono::seconds(3132));
Austin Schuhac6d89e2024-03-27 14:56:09 -07003149 const aos::monotonic_clock::time_point monotonic_remote_transmit_time =
3150 aos::monotonic_clock::time_point(chrono::seconds(1601));
Austin Schuhb5c6f972021-03-14 21:53:07 -07003151 const uint32_t remote_queue_index = 0x254971;
Austin Schuha9012be2021-07-21 15:19:11 -07003152 const UUID source_boot_uuid = UUID::Random();
Austin Schuhad154822019-12-27 15:45:13 -08003153
3154 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003155 loop1->MakeRawSender(configuration::GetChannel(
3156 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08003157
3158 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003159 loop3->MakeRawFetcher(configuration::GetChannel(
3160 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08003161
3162 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07003163 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size(),
3164 monotonic_remote_time, realtime_remote_time,
Austin Schuhac6d89e2024-03-27 14:56:09 -07003165 monotonic_remote_transmit_time, remote_queue_index,
3166 source_boot_uuid),
milind1f1dca32021-07-03 13:50:07 -07003167 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08003168 });
3169
3170 bool happened = false;
3171 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08003172 configuration::GetChannel(loop2->configuration(), "/test",
3173 "aos.TestMessage", "", nullptr),
Austin Schuhac6d89e2024-03-27 14:56:09 -07003174 [this, monotonic_remote_time, realtime_remote_time,
3175 monotonic_remote_transmit_time, source_boot_uuid, remote_queue_index,
3176 &fetcher, &happened](const Context &context, const void * /*message*/) {
Austin Schuhad154822019-12-27 15:45:13 -08003177 happened = true;
3178 EXPECT_EQ(monotonic_remote_time, context.monotonic_remote_time);
3179 EXPECT_EQ(realtime_remote_time, context.realtime_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07003180 EXPECT_EQ(source_boot_uuid, context.source_boot_uuid);
Austin Schuhb5c6f972021-03-14 21:53:07 -07003181 EXPECT_EQ(remote_queue_index, context.remote_queue_index);
Austin Schuhad154822019-12-27 15:45:13 -08003182
3183 ASSERT_TRUE(fetcher->Fetch());
3184 EXPECT_EQ(monotonic_remote_time,
3185 fetcher->context().monotonic_remote_time);
3186 EXPECT_EQ(realtime_remote_time,
3187 fetcher->context().realtime_remote_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07003188 EXPECT_EQ(monotonic_remote_transmit_time,
3189 fetcher->context().monotonic_remote_transmit_time);
Austin Schuhad154822019-12-27 15:45:13 -08003190
3191 this->Exit();
3192 });
3193
3194 EXPECT_FALSE(happened);
3195 Run();
3196 EXPECT_TRUE(happened);
Austin Schuhac6d89e2024-03-27 14:56:09 -07003197
3198 // Confirm everything goes back.
3199 EXPECT_EQ(loop2->context().monotonic_event_time, monotonic_clock::min_time);
3200 EXPECT_EQ(loop2->context().monotonic_remote_time, monotonic_clock::min_time);
3201 EXPECT_EQ(loop2->context().monotonic_remote_transmit_time,
3202 monotonic_clock::min_time);
3203 EXPECT_EQ(loop2->context().realtime_event_time, realtime_clock::min_time);
3204 EXPECT_EQ(loop2->context().realtime_remote_time, realtime_clock::min_time);
3205 EXPECT_EQ(loop2->context().source_boot_uuid, loop2->boot_uuid());
3206 EXPECT_EQ(loop2->context().queue_index, 0xffffffffu);
3207 EXPECT_EQ(loop2->context().size, 0u);
3208 EXPECT_EQ(loop2->context().data, nullptr);
3209 EXPECT_EQ(loop2->context().buffer_index, -1);
Austin Schuhad154822019-12-27 15:45:13 -08003210}
3211
3212// Tests that a raw sender fills out sent data.
3213TEST_P(AbstractEventLoopTest, RawSenderSentData) {
3214 auto loop1 = MakePrimary();
3215
Austin Schuha9df9ad2021-06-16 14:49:39 -07003216 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3217 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08003218
3219 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003220 loop1->MakeRawSender(configuration::GetChannel(
3221 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08003222
Tyler Chatow67ddb032020-01-12 14:30:04 -08003223 const aos::monotonic_clock::time_point monotonic_now = loop1->monotonic_now();
3224 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08003225
milind1f1dca32021-07-03 13:50:07 -07003226 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
3227 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08003228
3229 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
3230 EXPECT_LE(sender->monotonic_sent_time(),
3231 monotonic_now + chrono::milliseconds(100));
3232 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
3233 EXPECT_LE(sender->realtime_sent_time(),
3234 realtime_now + chrono::milliseconds(100));
3235 EXPECT_EQ(sender->sent_queue_index(), 0u);
3236
milind1f1dca32021-07-03 13:50:07 -07003237 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
3238 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08003239
3240 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
3241 EXPECT_LE(sender->monotonic_sent_time(),
3242 monotonic_now + chrono::milliseconds(100));
3243 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
3244 EXPECT_LE(sender->realtime_sent_time(),
3245 realtime_now + chrono::milliseconds(100));
3246 EXPECT_EQ(sender->sent_queue_index(), 1u);
3247}
3248
Austin Schuh217a9782019-12-21 23:02:50 -08003249// Tests that not setting up nodes results in no node.
3250TEST_P(AbstractEventLoopTest, NoNode) {
3251 auto loop1 = Make();
3252 auto loop2 = MakePrimary();
3253
3254 EXPECT_EQ(loop1->node(), nullptr);
3255 EXPECT_EQ(loop2->node(), nullptr);
3256}
3257
3258// Tests that setting up nodes results in node being set.
3259TEST_P(AbstractEventLoopTest, Node) {
3260 EnableNodes("me");
3261
3262 auto loop1 = Make();
3263 auto loop2 = MakePrimary();
3264
3265 EXPECT_NE(loop1->node(), nullptr);
3266 EXPECT_NE(loop2->node(), nullptr);
3267}
3268
3269// Tests that watchers work with a node setup.
3270TEST_P(AbstractEventLoopTest, NodeWatcher) {
3271 EnableNodes("me");
3272
3273 auto loop1 = Make();
3274 auto loop2 = Make();
3275 loop1->MakeWatcher("/test", [](const TestMessage &) {});
Tyler Chatow67ddb032020-01-12 14:30:04 -08003276 loop2->MakeRawWatcher(
3277 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
3278 nullptr),
3279 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08003280}
3281
Brian Silverman454bc112020-03-05 14:21:25 -08003282// Tests that no-arg watchers work with a node setup.
3283TEST_P(AbstractEventLoopTest, NodeNoArgWatcher) {
3284 EnableNodes("me");
3285
3286 auto loop1 = Make();
3287 auto loop2 = Make();
3288 loop1->MakeWatcher("/test", [](const TestMessage &) {});
3289 loop2->MakeRawNoArgWatcher(
3290 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
3291 nullptr),
3292 [](const Context &) {});
3293}
3294
Austin Schuh217a9782019-12-21 23:02:50 -08003295// Tests that fetcher work with a node setup.
3296TEST_P(AbstractEventLoopTest, NodeFetcher) {
3297 EnableNodes("me");
3298 auto loop1 = Make();
3299
3300 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
Tyler Chatow67ddb032020-01-12 14:30:04 -08003301 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
3302 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08003303}
3304
3305// Tests that sender work with a node setup.
3306TEST_P(AbstractEventLoopTest, NodeSender) {
3307 EnableNodes("me");
3308 auto loop1 = Make();
3309
3310 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
3311}
3312
Austin Schuhcc6070c2020-10-10 20:25:56 -07003313// Tests that a non-realtime event loop timer is marked non-realtime.
3314TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopTimer) {
3315 auto loop1 = MakePrimary();
3316
3317 // Add a timer to actually quit.
3318 auto test_timer = loop1->AddTimer([this]() {
3319 CheckNotRealtime();
3320 this->Exit();
3321 });
3322
3323 loop1->OnRun([&test_timer, &loop1]() {
3324 CheckNotRealtime();
Philipp Schradera6712522023-07-05 20:25:11 -07003325 test_timer->Schedule(loop1->monotonic_now(),
3326 ::std::chrono::milliseconds(100));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003327 });
3328
3329 Run();
3330}
3331
3332// Tests that a realtime event loop timer is marked realtime.
Austin Schuh9b1d6282022-06-10 17:03:21 -07003333TEST_P(AbstractEventLoopTest, RealtimeSend) {
3334 auto loop1 = MakePrimary();
3335
3336 loop1->SetRuntimeRealtimePriority(1);
3337
3338 auto sender = loop1->MakeSender<TestMessage>("/test2");
3339
3340 loop1->OnRun([&]() {
3341 CheckRealtime();
3342
3343 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3344 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
3345 builder.add_value(200);
3346 msg.CheckOk(msg.Send(builder.Finish()));
3347
3348 this->Exit();
3349 });
3350
3351 Run();
3352}
3353
3354// Tests that a realtime event loop timer is marked realtime.
Austin Schuhcc6070c2020-10-10 20:25:56 -07003355TEST_P(AbstractEventLoopTest, RealtimeEventLoopTimer) {
3356 auto loop1 = MakePrimary();
3357
3358 loop1->SetRuntimeRealtimePriority(1);
3359
3360 // Add a timer to actually quit.
3361 auto test_timer = loop1->AddTimer([this]() {
3362 CheckRealtime();
3363 this->Exit();
3364 });
3365
3366 loop1->OnRun([&test_timer, &loop1]() {
3367 CheckRealtime();
Philipp Schradera6712522023-07-05 20:25:11 -07003368 test_timer->Schedule(loop1->monotonic_now(),
3369 ::std::chrono::milliseconds(100));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003370 });
3371
3372 Run();
3373}
3374
3375// Tests that a non-realtime event loop phased loop is marked non-realtime.
3376TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopPhasedLoop) {
3377 auto loop1 = MakePrimary();
3378
3379 // Add a timer to actually quit.
3380 loop1->AddPhasedLoop(
3381 [this](int) {
3382 CheckNotRealtime();
3383 this->Exit();
3384 },
3385 chrono::seconds(1), chrono::seconds(0));
3386
3387 Run();
3388}
3389
3390// Tests that a realtime event loop phased loop is marked realtime.
3391TEST_P(AbstractEventLoopTest, RealtimeEventLoopPhasedLoop) {
3392 auto loop1 = MakePrimary();
3393
3394 loop1->SetRuntimeRealtimePriority(1);
3395
3396 // Add a timer to actually quit.
3397 loop1->AddPhasedLoop(
3398 [this](int) {
3399 CheckRealtime();
3400 this->Exit();
3401 },
3402 chrono::seconds(1), chrono::seconds(0));
3403
3404 Run();
3405}
3406
3407// Tests that a non-realtime event loop watcher is marked non-realtime.
3408TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopWatcher) {
3409 auto loop1 = MakePrimary();
3410 auto loop2 = Make();
3411
3412 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
3413
3414 loop1->OnRun([&]() {
3415 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3416 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07003417 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003418 });
3419
3420 loop1->MakeWatcher("/test", [&](const TestMessage &) {
3421 CheckNotRealtime();
3422 this->Exit();
3423 });
3424
3425 Run();
3426}
3427
3428// Tests that a realtime event loop watcher is marked realtime.
3429TEST_P(AbstractEventLoopTest, RealtimeEventLoopWatcher) {
3430 auto loop1 = MakePrimary();
3431 auto loop2 = Make();
3432
3433 loop1->SetRuntimeRealtimePriority(1);
3434
3435 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
3436
3437 loop1->OnRun([&]() {
3438 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3439 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07003440 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003441 });
3442
3443 loop1->MakeWatcher("/test", [&](const TestMessage &) {
3444 CheckRealtime();
3445 this->Exit();
3446 });
3447
3448 Run();
3449}
3450
Austin Schuha9012be2021-07-21 15:19:11 -07003451// Tests that event loop's context's monotonic time is set to a value on OnRun.
3452TEST_P(AbstractEventLoopTest, SetContextOnRun) {
3453 auto loop = MakePrimary();
3454
Austin Schuh0debde12022-08-17 16:25:17 -07003455 EXPECT_EQ(loop->context().monotonic_event_time, monotonic_clock::min_time);
3456 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07003457 EXPECT_EQ(loop->context().monotonic_remote_transmit_time,
3458 monotonic_clock::min_time);
Austin Schuh0debde12022-08-17 16:25:17 -07003459 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3460 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3461 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3462 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
3463 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
3464 EXPECT_EQ(loop->context().size, 0u);
3465 EXPECT_EQ(loop->context().data, nullptr);
3466 EXPECT_EQ(loop->context().buffer_index, -1);
3467
Austin Schuha9012be2021-07-21 15:19:11 -07003468 // We want to check that monotonic event time is before monotonic now
3469 // called inside of callback, but after time point obtained callback.
3470 aos::monotonic_clock::time_point monotonic_event_time_on_run;
3471
3472 loop->OnRun([&]() {
3473 monotonic_event_time_on_run = loop->context().monotonic_event_time;
3474 EXPECT_LE(monotonic_event_time_on_run, loop->monotonic_now());
3475 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07003476 EXPECT_EQ(loop->context().monotonic_remote_transmit_time,
3477 monotonic_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07003478 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3479 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3480 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3481 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
Austin Schuh0debde12022-08-17 16:25:17 -07003482 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
Austin Schuha9012be2021-07-21 15:19:11 -07003483 EXPECT_EQ(loop->context().size, 0u);
3484 EXPECT_EQ(loop->context().data, nullptr);
3485 EXPECT_EQ(loop->context().buffer_index, -1);
3486 });
3487
3488 EndEventLoop(loop.get(), ::std::chrono::milliseconds(200));
3489
3490 const aos::monotonic_clock::time_point before_run_time =
3491 loop->monotonic_now();
3492 Run();
3493 EXPECT_GE(monotonic_event_time_on_run, before_run_time);
Austin Schuh0debde12022-08-17 16:25:17 -07003494
3495 EXPECT_EQ(loop->context().monotonic_event_time, monotonic_clock::min_time);
3496 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -07003497 EXPECT_EQ(loop->context().monotonic_remote_transmit_time,
3498 monotonic_clock::min_time);
Austin Schuh0debde12022-08-17 16:25:17 -07003499 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3500 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3501 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3502 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
3503 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
3504 EXPECT_EQ(loop->context().size, 0u);
3505 EXPECT_EQ(loop->context().data, nullptr);
3506 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuha9012be2021-07-21 15:19:11 -07003507}
3508
Austin Schuh217a9782019-12-21 23:02:50 -08003509// Tests that watchers fail when created on the wrong node.
3510TEST_P(AbstractEventLoopDeathTest, NodeWatcher) {
3511 EnableNodes("them");
3512
3513 auto loop1 = Make();
3514 auto loop2 = Make();
3515 EXPECT_DEATH({ loop1->MakeWatcher("/test", [](const TestMessage &) {}); },
3516 "node");
3517 EXPECT_DEATH(
3518 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08003519 loop2->MakeRawWatcher(
3520 configuration::GetChannel(configuration(), "/test",
3521 "aos.TestMessage", "", nullptr),
3522 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08003523 },
3524 "node");
Brian Silverman454bc112020-03-05 14:21:25 -08003525 EXPECT_DEATH({ loop1->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
3526 "node");
3527 EXPECT_DEATH(
3528 {
3529 loop2->MakeRawNoArgWatcher(
3530 configuration::GetChannel(configuration(), "/test",
3531 "aos.TestMessage", "", nullptr),
3532 [](const Context &) {});
3533 },
3534 "node");
Austin Schuh217a9782019-12-21 23:02:50 -08003535}
3536
3537// Tests that fetchers fail when created on the wrong node.
3538TEST_P(AbstractEventLoopDeathTest, NodeFetcher) {
3539 EnableNodes("them");
3540 auto loop1 = Make();
3541
3542 EXPECT_DEATH({ auto fetcher = loop1->MakeFetcher<TestMessage>("/test"); },
3543 "node");
3544 EXPECT_DEATH(
3545 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08003546 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
3547 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08003548 },
3549 "node");
3550}
3551
3552// Tests that senders fail when created on the wrong node.
3553TEST_P(AbstractEventLoopDeathTest, NodeSender) {
3554 EnableNodes("them");
3555 auto loop1 = Make();
3556
3557 EXPECT_DEATH(
3558 {
3559 aos::Sender<TestMessage> sender =
3560 loop1->MakeSender<TestMessage>("/test");
3561 },
3562 "node");
3563
3564 // Note: Creating raw senders is always supported. Right now, this lets us
3565 // use them to create message_gateway.
3566}
3567
Brian Silverman341b57e2020-06-23 16:23:18 -07003568// Tests creating multiple Builders from a single Sender at the same time.
3569TEST_P(AbstractEventLoopDeathTest, MultipleBuilders) {
3570 auto loop1 = Make();
3571 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
3572
3573 { auto builder = sender.MakeBuilder(); }
3574 {
3575 auto builder = sender.MakeBuilder();
3576 builder.MakeBuilder<TestMessage>().Finish();
3577 }
3578 {
3579 // Creating this after the first one was destroyed should be fine.
3580 auto builder = sender.MakeBuilder();
3581 builder.MakeBuilder<TestMessage>().Finish();
3582 // But not a second one.
3583 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
James Kuszmaulb1c11052023-11-06 13:20:53 -08003584 "May not have multiple active allocators");
Brian Silverman341b57e2020-06-23 16:23:18 -07003585 }
3586
3587 FlatbufferDetachedBuffer<TestMessage> detached =
3588 flatbuffers::DetachedBuffer();
3589 {
3590 auto builder = sender.MakeBuilder();
3591 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
3592 }
3593 {
3594 // This is the second one, after the detached one, so it should fail.
3595 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
James Kuszmaulb1c11052023-11-06 13:20:53 -08003596 "May not have multiple active allocators");
Brian Silverman341b57e2020-06-23 16:23:18 -07003597 }
3598
3599 // Clear the detached one, and then we should be able to create another.
3600 detached = flatbuffers::DetachedBuffer();
3601 {
3602 auto builder = sender.MakeBuilder();
3603 builder.MakeBuilder<TestMessage>().Finish();
3604 }
3605
3606 // And then detach another one.
3607 {
3608 auto builder = sender.MakeBuilder();
3609 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
3610 }
3611}
3612
3613// Tests sending a buffer detached from a different builder.
3614TEST_P(AbstractEventLoopDeathTest, WrongDetachedBuffer) {
3615 auto loop1 = Make();
3616 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
3617 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
3618
3619 auto builder = sender1.MakeBuilder();
3620 FlatbufferDetachedBuffer<TestMessage> detached =
3621 builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
milind1f1dca32021-07-03 13:50:07 -07003622 EXPECT_DEATH(sender2.CheckOk(sender2.SendDetached(std::move(detached))),
Brian Silverman341b57e2020-06-23 16:23:18 -07003623 "May only send the buffer detached from this Sender");
3624}
3625
James Kuszmaul762e8692023-07-31 14:57:53 -07003626// Tests that senders fail when created on the wrong node.
3627TEST_P(AbstractEventLoopDeathTest, SetVersionWhileRunning) {
3628 auto loop1 = MakePrimary();
3629
3630 loop1->OnRun([&loop1, this]() {
3631 EXPECT_DEATH({ loop1->SetVersionString("abcdef"); },
3632 "timing report while running");
3633 Exit();
3634 });
3635
3636 Run();
3637}
3638
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003639int TestChannelFrequency(EventLoop *event_loop) {
3640 return event_loop->GetChannel<TestMessage>("/test")->frequency();
3641}
3642
3643int TestChannelQueueSize(EventLoop *event_loop) {
Austin Schuhfff9c3a2023-06-16 18:48:23 -07003644 return configuration::QueueSize(event_loop->configuration(),
3645 event_loop->GetChannel<TestMessage>("/test"));
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003646}
3647
3648RawSender::Error SendTestMessage(aos::Sender<TestMessage> &sender) {
3649 aos::Sender<TestMessage>::Builder builder = sender.MakeBuilder();
3650 TestMessage::Builder test_message_builder =
3651 builder.MakeBuilder<TestMessage>();
3652 test_message_builder.add_value(0);
3653 return builder.Send(test_message_builder.Finish());
3654}
3655
3656// Test that sending messages too fast returns
3657// RawSender::Error::kMessagesSentTooFast.
3658TEST_P(AbstractEventLoopTest, SendingMessagesTooFast) {
3659 auto event_loop = MakePrimary();
Austin Schuh63756be2024-02-05 19:51:20 -08003660 event_loop->SetRuntimeRealtimePriority(5);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003661
3662 auto sender = event_loop->MakeSender<TestMessage>("/test");
3663
3664 // Send one message in the beginning, then wait until the
3665 // channel_storage_duration is almost done and start sending messages rapidly,
3666 // having some come in the next chanel_storage_duration. The queue_size is
3667 // 1600, so the 1601st message will be the last valid one (the initial message
3668 // having being sent more than a channel_storage_duration ago), and trying to
3669 // send the 1602nd message should return
3670 // RawSender::Error::kMessagesSentTooFast.
3671 EXPECT_EQ(SendTestMessage(sender), RawSender::Error::kOk);
3672 int msgs_sent = 1;
3673 const int queue_size = TestChannelQueueSize(event_loop.get());
3674
Austin Schuh63756be2024-02-05 19:51:20 -08003675 const int messages_per_ms = 2;
3676 const auto kRepeatOffset = std::chrono::milliseconds(10);
3677 const auto base_offset =
3678 configuration::ChannelStorageDuration(event_loop->configuration(),
3679 sender.channel()) -
3680 (std::chrono::milliseconds(1) * (queue_size / 2) / messages_per_ms);
3681
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003682 const auto timer = event_loop->AddTimer([&]() {
Austin Schuh63756be2024-02-05 19:51:20 -08003683 // Send in bursts to reduce scheduler load to make the test more
3684 // reproducible.
3685 for (int i = 0; i < messages_per_ms * kRepeatOffset.count(); ++i) {
3686 const bool done = (msgs_sent == queue_size + 1);
3687 ASSERT_EQ(SendTestMessage(sender),
3688 done ? RawSender::Error::kMessagesSentTooFast
3689 : RawSender::Error::kOk);
3690 msgs_sent++;
3691 if (done) {
3692 Exit();
3693 return;
3694 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003695 }
3696 });
3697
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003698 event_loop->OnRun([&event_loop, &timer, &base_offset, &kRepeatOffset]() {
Philipp Schradera6712522023-07-05 20:25:11 -07003699 timer->Schedule(event_loop->monotonic_now() + base_offset, kRepeatOffset);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003700 });
3701
3702 Run();
3703}
3704
3705// Tests that we are able to send messages successfully after sending messages
3706// too fast and waiting while continuously attempting to send messages.
3707// Also tests that SendFailureCounter is working correctly in this
3708// situation
3709TEST_P(AbstractEventLoopTest, SendingAfterSendingTooFast) {
3710 auto event_loop = MakePrimary();
Austin Schuh63756be2024-02-05 19:51:20 -08003711 event_loop->SetRuntimeRealtimePriority(5);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003712
3713 auto sender = event_loop->MakeSender<TestMessage>("/test");
3714
Austin Schuh0e96d372023-05-08 10:10:21 -07003715 // We are sending bunches of messages at 100 Hz, so we will be sending too
3716 // fast after queue_size (800) ms. After this, keep sending messages, and
3717 // exactly a channel storage duration (2s) after we send the first message we
3718 // should be able to successfully send a message.
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003719
Austin Schuh0e96d372023-05-08 10:10:21 -07003720 const std::chrono::milliseconds kInterval = std::chrono::milliseconds(10);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003721 const monotonic_clock::duration channel_storage_duration =
Austin Schuhfff9c3a2023-06-16 18:48:23 -07003722 configuration::ChannelStorageDuration(event_loop->configuration(),
3723 sender.channel());
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003724 const int queue_size = TestChannelQueueSize(event_loop.get());
3725
3726 int msgs_sent = 0;
3727 SendFailureCounter counter;
3728 auto start = monotonic_clock::min_time;
3729
3730 event_loop->AddPhasedLoop(
Austin Schuh0e96d372023-05-08 10:10:21 -07003731 [&](int elapsed_cycles) {
3732 // The queue is setup for 800 messages/sec. We want to fill that up at
3733 // a rate of 2000 messages/sec so we make sure we fill it up.
3734 for (int i = 0; i < 2 * kInterval.count() * elapsed_cycles; ++i) {
3735 const auto actual_err = SendTestMessage(sender);
3736 const bool done_waiting = (start != monotonic_clock::min_time &&
3737 sender.monotonic_sent_time() >=
3738 (start + channel_storage_duration));
3739 const auto expected_err =
3740 (msgs_sent < queue_size || done_waiting
3741 ? RawSender::Error::kOk
3742 : RawSender::Error::kMessagesSentTooFast);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003743
Austin Schuh0e96d372023-05-08 10:10:21 -07003744 if (start == monotonic_clock::min_time) {
3745 start = sender.monotonic_sent_time();
3746 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003747
Austin Schuh0e96d372023-05-08 10:10:21 -07003748 ASSERT_EQ(actual_err, expected_err);
3749 counter.Count(actual_err);
3750 msgs_sent++;
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003751
Austin Schuh0e96d372023-05-08 10:10:21 -07003752 EXPECT_EQ(counter.failures(),
3753 msgs_sent <= queue_size
3754 ? 0
3755 : (msgs_sent - queue_size) -
3756 (actual_err == RawSender::Error::kOk ? 1 : 0));
3757 EXPECT_EQ(counter.just_failed(), actual_err != RawSender::Error::kOk);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003758
Austin Schuh0e96d372023-05-08 10:10:21 -07003759 if (done_waiting) {
3760 Exit();
3761 return;
3762 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003763 }
3764 },
3765 kInterval);
3766 Run();
3767}
3768
3769// Tests that RawSender::Error::kMessagesSentTooFast is returned
3770// when messages are sent too fast from senders in different loops
3771TEST_P(AbstractEventLoopTest, SendingTooFastWithMultipleLoops) {
3772 auto loop1 = MakePrimary();
3773 auto loop2 = Make();
3774
3775 auto sender1 = loop1->MakeSender<TestMessage>("/test");
3776 auto sender2 = loop2->MakeSender<TestMessage>("/test");
3777
3778 // Send queue_size messages split between the senders.
3779 const int queue_size = TestChannelQueueSize(loop1.get());
3780 for (int i = 0; i < queue_size / 2; i++) {
3781 ASSERT_EQ(SendTestMessage(sender1), RawSender::Error::kOk);
3782 ASSERT_EQ(SendTestMessage(sender2), RawSender::Error::kOk);
3783 }
3784
3785 // Since queue_size messages have been sent, this should return an error
3786 EXPECT_EQ(SendTestMessage(sender2), RawSender::Error::kMessagesSentTooFast);
3787}
3788
Austin Schuhdda6db72023-06-21 17:02:34 -07003789// Tests that a longer storage durations store more messages.
3790TEST_P(AbstractEventLoopTest, SendingTooFastWithLongDuration) {
3791 auto loop1 = MakePrimary();
3792
3793 auto sender1 = loop1->MakeSender<TestMessage>("/test3");
3794
3795 // Send queue_size messages split between the senders.
3796 const int queue_size =
3797 configuration::QueueSize(loop1->configuration(), sender1.channel());
3798 EXPECT_EQ(queue_size, 100 * 10);
3799 for (int i = 0; i < queue_size; i++) {
3800 ASSERT_EQ(SendTestMessage(sender1), RawSender::Error::kOk);
3801 }
3802
3803 // Since queue_size messages have been sent, and little time has elapsed,
3804 // this should return an error.
3805 EXPECT_EQ(SendTestMessage(sender1), RawSender::Error::kMessagesSentTooFast);
3806}
3807
James Kuszmaul9f998082024-05-23 15:37:35 -07003808// Tests that we can exit with a default constructor and that Run() will
3809// indicate a successful exit.
3810TEST_P(AbstractEventLoopTest, ExitHandleExitSuccessful) {
3811 auto loop = MakePrimary();
3812 std::unique_ptr<ExitHandle> exit_handle = MakeExitHandle();
3813 bool happened = false;
3814
3815 loop->OnRun([&exit_handle, &happened]() {
3816 happened = true;
3817 exit_handle->Exit();
3818 });
3819
3820 EXPECT_TRUE(Run().has_value());
3821 EXPECT_TRUE(happened);
3822}
3823
3824// Tests that we can exit with an error Status and have that returned via the
3825// Run() method.
3826TEST_P(AbstractEventLoopTest, ExitHandleExitFailure) {
3827 auto loop = MakePrimary();
3828 std::unique_ptr<ExitHandle> exit_handle = MakeExitHandle();
3829 bool happened = false;
3830
3831 loop->OnRun([&exit_handle, &happened]() {
3832 happened = true;
3833 exit_handle->Exit(Error::MakeUnexpectedError("Hello, World!"));
3834 // The second Exit() should not affect the final return value.
3835 exit_handle->Exit(Error::MakeUnexpectedError("Hello, World! 2"));
3836 });
3837 const int line = __LINE__ - 4;
3838
3839 Result<void> status = Run();
3840
3841 EXPECT_TRUE(happened);
3842 EXPECT_FALSE(status.has_value());
3843 EXPECT_EQ(std::string("Hello, World!"), status.error().message());
3844 ASSERT_TRUE(status.error().source_location().has_value());
3845 EXPECT_EQ(std::string("event_loop_param_test.cc"),
3846 std::filesystem::path(status.error().source_location()->file_name())
3847 .filename());
3848 EXPECT_EQ(line, status.error().source_location()->line());
3849}
3850
Stephan Pleinesf63bde82024-01-13 15:59:33 -08003851} // namespace aos::testing