blob: f4f2fccb3146918e2e2af8af19d6d225e982d4ac [file] [log] [blame]
Alex Perrycb7da4b2019-08-28 19:35:56 -07001#include "aos/events/event_loop_param_test.h"
Parker Schuhe4a70d62017-12-27 20:10:20 -08002
Austin Schuh52d325c2019-06-23 18:59:06 -07003#include <chrono>
Brian Silverman4f4e0612020-08-12 19:54:41 -07004#include <unordered_map>
5#include <unordered_set>
Austin Schuh52d325c2019-06-23 18:59:06 -07006
Philipp Schrader790cb542023-07-05 21:06:52 -07007#include "glog/logging.h"
8#include "gmock/gmock.h"
9#include "gtest/gtest.h"
10
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -070011#include "aos/events/test_message_generated.h"
James Kuszmaulb1c11052023-11-06 13:20:53 -080012#include "aos/events/test_message_static.h"
Austin Schuh54cf95f2019-11-29 13:14:18 -080013#include "aos/flatbuffer_merge.h"
Austin Schuhad9e5eb2021-11-19 20:33:55 -080014#include "aos/logging/log_message_generated.h"
15#include "aos/logging/logging.h"
Austin Schuhcc6070c2020-10-10 20:25:56 -070016#include "aos/realtime.h"
Austin Schuh9fe68f72019-08-10 19:32:03 -070017
Stephan Pleinesf63bde82024-01-13 15:59:33 -080018namespace aos::testing {
Austin Schuh52d325c2019-06-23 18:59:06 -070019namespace {
20namespace chrono = ::std::chrono;
21} // namespace
Parker Schuhe4a70d62017-12-27 20:10:20 -080022
Brian Silverman4f4e0612020-08-12 19:54:41 -070023::std::unique_ptr<EventLoop> AbstractEventLoopTest::Make(
24 std::string_view name) {
25 std::string name_copy(name);
26 if (name == "") {
27 name_copy = "loop";
28 name_copy += std::to_string(event_loop_count_);
29 }
30 ++event_loop_count_;
Austin Schuh6bae8252021-02-07 22:01:49 -080031 auto result = factory_->Make(name_copy);
32 if (do_timing_reports() == DoTimingReports::kNo) {
33 result->SkipTimingReport();
34 }
35 return result;
Brian Silverman4f4e0612020-08-12 19:54:41 -070036}
37
38void AbstractEventLoopTest::VerifyBuffers(
39 int number_buffers,
40 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>> fetchers,
41 std::vector<std::reference_wrapper<const Sender<TestMessage>>> senders) {
42 // The buffers which are in a sender.
43 std::unordered_set<int> in_sender;
44 for (const Sender<TestMessage> &sender : senders) {
45 const int this_buffer = sender.buffer_index();
46 CHECK_GE(this_buffer, 0);
47 CHECK_LT(this_buffer, number_buffers);
48 CHECK(in_sender.insert(this_buffer).second) << ": " << this_buffer;
49 }
50
51 if (read_method() != ReadMethod::PIN) {
52 // If we're not using PIN, we can't really verify anything about what
53 // buffers the fetchers have.
54 return;
55 }
56
57 // Mapping from TestMessage::value to buffer index.
58 std::unordered_map<int, int> fetcher_values;
59 for (const Fetcher<TestMessage> &fetcher : fetchers) {
60 if (!fetcher.get()) {
61 continue;
62 }
63 const int this_buffer = fetcher.context().buffer_index;
64 CHECK_GE(this_buffer, 0);
65 CHECK_LT(this_buffer, number_buffers);
66 CHECK(in_sender.count(this_buffer) == 0) << ": " << this_buffer;
67 const auto insert_result = fetcher_values.insert(
68 std::make_pair(fetcher.get()->value(), this_buffer));
69 if (!insert_result.second) {
70 CHECK_EQ(this_buffer, insert_result.first->second);
71 }
72 }
73}
74
Austin Schuh6b6dfa52019-06-12 20:16:20 -070075// Tests that watcher can receive messages from a sender.
Parker Schuhe4a70d62017-12-27 20:10:20 -080076// Also tests that OnRun() works.
77TEST_P(AbstractEventLoopTest, Basic) {
78 auto loop1 = Make();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070079 auto loop2 = MakePrimary();
80
Alex Perrycb7da4b2019-08-28 19:35:56 -070081 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
Austin Schuh6b6dfa52019-06-12 20:16:20 -070082
83 bool happened = false;
84
85 loop2->OnRun([&]() {
86 happened = true;
87
Alex Perrycb7da4b2019-08-28 19:35:56 -070088 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
89 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
90 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -070091 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -070092 });
93
94 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070095 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -070096 this->Exit();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070097 });
98
99 EXPECT_FALSE(happened);
100 Run();
101 EXPECT_TRUE(happened);
102}
103
James Kuszmaulb1c11052023-11-06 13:20:53 -0800104// Tests that watcher can receive messages from a static sender.
105// This confirms that the "static" flatbuffer API works with the EventLoop
106// senders.
107TEST_P(AbstractEventLoopTest, BasicStatic) {
108 auto loop1 = Make();
109 auto loop2 = MakePrimary();
110
111 aos::Sender<TestMessageStatic> sender =
112 loop1->MakeSender<TestMessageStatic>("/test");
113
114 bool happened = false;
115
116 loop2->OnRun([&]() {
117 happened = true;
118
119 aos::Sender<TestMessageStatic>::StaticBuilder msg =
120 sender.MakeStaticBuilder();
James Kuszmauldde65632023-12-07 16:12:26 -0800121 msg->set_value(200);
James Kuszmaulb1c11052023-11-06 13:20:53 -0800122 CHECK(msg.builder()->Verify());
123 msg.CheckOk(msg.Send());
124 });
125
126 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
127 EXPECT_EQ(message.value(), 200);
128 this->Exit();
129 });
130
131 EXPECT_FALSE(happened);
132 Run();
133 EXPECT_TRUE(happened);
134}
135
Brian Silverman341b57e2020-06-23 16:23:18 -0700136// Tests that watcher can receive messages from a sender, sent via SendDetached.
137TEST_P(AbstractEventLoopTest, BasicSendDetached) {
138 auto loop1 = Make();
139 auto loop2 = MakePrimary();
140
141 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
142
143 FlatbufferDetachedBuffer<TestMessage> detached =
144 flatbuffers::DetachedBuffer();
145 {
146 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
147 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
148 builder.add_value(100);
149 detached = msg.Detach(builder.Finish());
150 }
151 detached = flatbuffers::DetachedBuffer();
152 {
153 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
154 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
155 builder.add_value(200);
156 detached = msg.Detach(builder.Finish());
157 }
milind1f1dca32021-07-03 13:50:07 -0700158 sender.CheckOk(sender.SendDetached(std::move(detached)));
Brian Silverman341b57e2020-06-23 16:23:18 -0700159
160 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
161 ASSERT_TRUE(fetcher.Fetch());
162 EXPECT_EQ(fetcher->value(), 200);
163}
164
Alexei Strots7cb6e0c2024-02-19 21:24:21 -0800165// Tests that fetcher can receive messages from a sender, sent via SendJson.
166TEST_P(AbstractEventLoopTest, BasicSendJson) {
167 auto loop1 = Make();
168 auto loop2 = MakePrimary();
169
170 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
171 sender.CheckOk(sender.SendJson(R"json({"value":201})json"));
172
173 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
174 ASSERT_TRUE(fetcher.Fetch());
175 EXPECT_EQ(fetcher->value(), 201);
176}
177
178// Tests that invalid JSON isn't sent.
179TEST_P(AbstractEventLoopDeathTest, InvalidSendJson) {
180 auto loop1 = Make();
181 auto loop2 = MakePrimary();
182
183 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
184 EXPECT_DEATH({ sender.CheckOk(sender.SendJson(R"json({"val)json")); },
185 "Invalid JSON");
186}
187
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800188// Verifies that a no-arg watcher will not have a data pointer.
189TEST_P(AbstractEventLoopTest, NoArgNoData) {
190 auto loop1 = Make();
191 auto loop2 = MakePrimary();
192
193 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
194
195 bool happened = false;
196
197 loop2->OnRun([&]() {
198 happened = true;
199
200 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
201 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -0700202 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800203 });
204
205 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
206 EXPECT_GT(loop2->context().size, 0u);
207 EXPECT_EQ(nullptr, loop2->context().data);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700208 EXPECT_EQ(-1, loop2->context().buffer_index);
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800209 this->Exit();
210 });
211
212 EXPECT_FALSE(happened);
213 Run();
214 EXPECT_TRUE(happened);
215}
216
Brian Silverman454bc112020-03-05 14:21:25 -0800217// Tests that no-arg watcher can receive messages from a sender.
218// Also tests that OnRun() works.
219TEST_P(AbstractEventLoopTest, BasicNoArg) {
220 auto loop1 = Make();
221 auto loop2 = MakePrimary();
222
223 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
224
225 bool happened = false;
226
227 loop2->OnRun([&]() {
228 happened = true;
229
230 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
231 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
232 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700233 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -0800234 });
235
236 aos::Fetcher<TestMessage> fetcher = loop2->MakeFetcher<TestMessage>("/test");
237 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
238 ASSERT_TRUE(fetcher.Fetch());
239 EXPECT_EQ(fetcher->value(), 200);
240 this->Exit();
241 });
242
243 EXPECT_FALSE(happened);
244 Run();
245 EXPECT_TRUE(happened);
246}
247
248// Tests that a watcher can be created with an std::function.
249TEST_P(AbstractEventLoopTest, BasicFunction) {
250 auto loop1 = Make();
251 auto loop2 = MakePrimary();
252
253 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
254
255 bool happened = false;
256
257 loop2->OnRun([&]() {
258 happened = true;
259
260 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
261 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
262 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700263 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -0800264 });
265
266 loop2->MakeWatcher("/test", std::function<void(const TestMessage &)>(
267 [&](const TestMessage &message) {
268 EXPECT_EQ(message.value(), 200);
269 this->Exit();
270 }));
271
272 EXPECT_FALSE(happened);
273 Run();
274 EXPECT_TRUE(happened);
275}
276
Brian Silverman0fc69932020-01-24 21:54:02 -0800277// Tests that watcher can receive messages from two senders.
278// Also tests that OnRun() works.
279TEST_P(AbstractEventLoopTest, BasicTwoSenders) {
280 auto loop1 = Make();
281 auto loop2 = MakePrimary();
282
283 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
284 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
285
286 bool happened = false;
287
288 loop2->OnRun([&]() {
289 happened = true;
290
291 {
292 aos::Sender<TestMessage>::Builder msg = sender1.MakeBuilder();
293 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
294 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700295 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman0fc69932020-01-24 21:54:02 -0800296 }
297 {
298 aos::Sender<TestMessage>::Builder msg = sender2.MakeBuilder();
299 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
300 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700301 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman0fc69932020-01-24 21:54:02 -0800302 }
303 });
304
305 int messages_received = 0;
306 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
307 EXPECT_EQ(message.value(), 200);
308 this->Exit();
309 ++messages_received;
310 });
311
312 EXPECT_FALSE(happened);
313 Run();
314 EXPECT_TRUE(happened);
315 EXPECT_EQ(messages_received, 2);
316}
317
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700318// Tests that a fetcher can fetch from a sender.
319// Also tests that OnRun() works.
320TEST_P(AbstractEventLoopTest, FetchWithoutRun) {
321 auto loop1 = Make();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800322 auto loop2 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -0700323 auto loop3 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800324
325 auto sender = loop1->MakeSender<TestMessage>("/test");
326
327 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
328
Austin Schuhbbce72d2019-05-26 15:11:46 -0700329 EXPECT_FALSE(fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -0800330 EXPECT_EQ(fetcher.get(), nullptr);
331
Austin Schuhad154822019-12-27 15:45:13 -0800332 EXPECT_EQ(fetcher.context().monotonic_event_time, monotonic_clock::min_time);
333 EXPECT_EQ(fetcher.context().monotonic_remote_time, monotonic_clock::min_time);
334 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
335 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -0700336 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
Austin Schuh39788ff2019-12-01 18:22:57 -0800337 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
338 EXPECT_EQ(fetcher.context().size, 0u);
339 EXPECT_EQ(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700340 EXPECT_EQ(fetcher.context().buffer_index, -1);
Austin Schuhbbce72d2019-05-26 15:11:46 -0700341
Alex Perrycb7da4b2019-08-28 19:35:56 -0700342 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
343 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
344 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700345 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700346
347 EXPECT_TRUE(fetcher.Fetch());
348 ASSERT_FALSE(fetcher.get() == nullptr);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700349 EXPECT_EQ(fetcher.get()->value(), 200);
Austin Schuh39788ff2019-12-01 18:22:57 -0800350
351 const chrono::milliseconds kEpsilon(100);
352
Austin Schuhad154822019-12-27 15:45:13 -0800353 const aos::monotonic_clock::time_point monotonic_now = loop2->monotonic_now();
354 const aos::realtime_clock::time_point realtime_now = loop2->realtime_now();
355 EXPECT_EQ(fetcher.context().monotonic_event_time,
356 fetcher.context().monotonic_remote_time);
357 EXPECT_EQ(fetcher.context().realtime_event_time,
358 fetcher.context().realtime_remote_time);
359
360 EXPECT_GE(fetcher.context().monotonic_event_time, monotonic_now - kEpsilon);
361 EXPECT_LE(fetcher.context().monotonic_event_time, monotonic_now + kEpsilon);
362 EXPECT_GE(fetcher.context().realtime_event_time, realtime_now - kEpsilon);
363 EXPECT_LE(fetcher.context().realtime_event_time, realtime_now + kEpsilon);
Austin Schuha9012be2021-07-21 15:19:11 -0700364 EXPECT_EQ(fetcher.context().source_boot_uuid, loop2->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -0800365 EXPECT_EQ(fetcher.context().queue_index, 0x0u);
366 EXPECT_EQ(fetcher.context().size, 20u);
367 EXPECT_NE(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700368 if (read_method() == ReadMethod::PIN) {
369 EXPECT_GE(fetcher.context().buffer_index, 0);
370 EXPECT_LT(fetcher.context().buffer_index,
371 loop2->NumberBuffers(fetcher.channel()));
372 } else {
373 EXPECT_EQ(fetcher.context().buffer_index, -1);
374 }
Parker Schuhe4a70d62017-12-27 20:10:20 -0800375}
376
Austin Schuh98ed26f2023-07-19 14:12:28 -0700377std::function<bool(const Context &)> MakeShouldFetch(
378 bool should_fetch, size_t *called_count = nullptr) {
379 return [should_fetch, called_count](const Context &) {
380 if (called_count != nullptr) {
381 (*called_count)++;
382 }
383 return should_fetch;
384 };
385}
386
387// Tests that a fetcher using FetchIf can fetch from a sender.
388TEST_P(AbstractEventLoopTest, FetchIfWithoutRun) {
389 auto loop1 = Make();
390 auto loop2 = Make();
391 auto loop3 = MakePrimary();
392
393 auto sender = loop1->MakeSender<TestMessage>("/test");
394
395 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
396
397 for (const bool should_fetch : {true, false}) {
398 EXPECT_FALSE(fetcher.FetchIf(MakeShouldFetch(should_fetch)));
399 EXPECT_EQ(fetcher.get(), nullptr);
400
401 EXPECT_EQ(fetcher.context().monotonic_event_time,
402 monotonic_clock::min_time);
403 EXPECT_EQ(fetcher.context().monotonic_remote_time,
404 monotonic_clock::min_time);
405 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
406 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
407 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
408 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
409 EXPECT_EQ(fetcher.context().size, 0u);
410 EXPECT_EQ(fetcher.context().data, nullptr);
411 EXPECT_EQ(fetcher.context().buffer_index, -1);
412 }
413
414 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
415 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
416 builder.add_value(200);
417 msg.CheckOk(msg.Send(builder.Finish()));
418
419 // Make sure failing to fetch won't affect anything.
420 EXPECT_FALSE(fetcher.FetchIf(MakeShouldFetch(false)));
421 EXPECT_EQ(fetcher.get(), nullptr);
422
423 EXPECT_EQ(fetcher.context().monotonic_event_time, monotonic_clock::min_time);
424 EXPECT_EQ(fetcher.context().monotonic_remote_time, monotonic_clock::min_time);
425 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
426 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
427 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
428 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
429 EXPECT_EQ(fetcher.context().size, 0u);
430 EXPECT_EQ(fetcher.context().data, nullptr);
431 EXPECT_EQ(fetcher.context().buffer_index, -1);
432
433 // And now confirm we succeed and everything gets set right.
434 EXPECT_TRUE(fetcher.FetchIf(MakeShouldFetch(true)));
435 ASSERT_FALSE(fetcher.get() == nullptr);
436 EXPECT_EQ(fetcher.get()->value(), 200);
437
438 const chrono::milliseconds kEpsilon(100);
439
440 const aos::monotonic_clock::time_point monotonic_now = loop2->monotonic_now();
441 const aos::realtime_clock::time_point realtime_now = loop2->realtime_now();
442 EXPECT_EQ(fetcher.context().monotonic_event_time,
443 fetcher.context().monotonic_remote_time);
444 EXPECT_EQ(fetcher.context().realtime_event_time,
445 fetcher.context().realtime_remote_time);
446
447 EXPECT_GE(fetcher.context().monotonic_event_time, monotonic_now - kEpsilon);
448 EXPECT_LE(fetcher.context().monotonic_event_time, monotonic_now + kEpsilon);
449 EXPECT_GE(fetcher.context().realtime_event_time, realtime_now - kEpsilon);
450 EXPECT_LE(fetcher.context().realtime_event_time, realtime_now + kEpsilon);
451 EXPECT_EQ(fetcher.context().source_boot_uuid, loop2->boot_uuid());
452 EXPECT_EQ(fetcher.context().queue_index, 0x0u);
453 EXPECT_EQ(fetcher.context().size, 20u);
454 EXPECT_NE(fetcher.context().data, nullptr);
455 if (read_method() == ReadMethod::PIN) {
456 EXPECT_GE(fetcher.context().buffer_index, 0);
457 EXPECT_LT(fetcher.context().buffer_index,
458 loop2->NumberBuffers(fetcher.channel()));
459 } else {
460 EXPECT_EQ(fetcher.context().buffer_index, -1);
461 }
462}
463
Austin Schuh3578a2e2019-05-25 18:17:59 -0700464// Tests that watcher will receive all messages sent if they are sent after
465// initialization and before running.
466TEST_P(AbstractEventLoopTest, DoubleSendAtStartup) {
467 auto loop1 = Make();
468 auto loop2 = MakePrimary();
469
470 auto sender = loop1->MakeSender<TestMessage>("/test");
471
472 ::std::vector<int> values;
473
474 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700475 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700476 if (values.size() == 2) {
Austin Schuh9fe68f72019-08-10 19:32:03 -0700477 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -0700478 }
479 });
480
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700481 // Before Run, should be ignored.
Austin Schuh3578a2e2019-05-25 18:17:59 -0700482 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700483 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
484 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
485 builder.add_value(199);
milind1f1dca32021-07-03 13:50:07 -0700486 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700487 }
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700488
489 loop2->OnRun([&]() {
Austin Schuh98ed26f2023-07-19 14:12:28 -0700490 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700491 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
492 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700493 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700494 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700495 }
496 });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700497
498 Run();
499
500 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
501}
502
503// Tests that watcher will not receive messages sent before the watcher is
504// created.
505TEST_P(AbstractEventLoopTest, DoubleSendAfterStartup) {
506 auto loop1 = Make();
507 auto loop2 = MakePrimary();
508
509 auto sender = loop1->MakeSender<TestMessage>("/test");
510
511 ::std::vector<int> values;
512
Austin Schuh98ed26f2023-07-19 14:12:28 -0700513 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700514 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
515 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700516 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700517 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700518 }
519
520 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700521 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700522 });
523
524 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700525 auto test_timer = loop2->AddTimer([this]() { this->Exit(); });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700526 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700527 test_timer->Schedule(loop2->monotonic_now(),
528 ::std::chrono::milliseconds(100));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700529 });
530
531 Run();
532 EXPECT_EQ(0, values.size());
533}
534
Austin Schuhbbce72d2019-05-26 15:11:46 -0700535// Tests that FetchNext gets all the messages sent after it is constructed.
536TEST_P(AbstractEventLoopTest, FetchNext) {
537 auto loop1 = Make();
538 auto loop2 = MakePrimary();
539
540 auto sender = loop1->MakeSender<TestMessage>("/test");
541 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
542
543 ::std::vector<int> values;
544
Austin Schuh98ed26f2023-07-19 14:12:28 -0700545 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700546 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
547 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700548 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700549 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700550 }
551
552 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700553 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700554 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700555 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700556 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700557 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700558 });
559
560 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700561 test_timer->Schedule(loop2->monotonic_now(),
562 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700563 });
564
565 Run();
566 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
567}
568
569// Tests that FetchNext gets no messages sent before it is constructed.
570TEST_P(AbstractEventLoopTest, FetchNextAfterSend) {
571 auto loop1 = Make();
572 auto loop2 = MakePrimary();
573
574 auto sender = loop1->MakeSender<TestMessage>("/test");
575
576 ::std::vector<int> values;
577
Austin Schuh98ed26f2023-07-19 14:12:28 -0700578 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700579 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
580 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700581 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700582 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700583 }
584
585 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
586
587 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700588 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700589 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700590 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700591 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700592 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700593 });
594
595 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700596 test_timer->Schedule(loop2->monotonic_now(),
597 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700598 });
599
600 Run();
601 EXPECT_THAT(0, values.size());
602}
603
Austin Schuh98ed26f2023-07-19 14:12:28 -0700604// Tests that FetchNextIf gets no messages sent before it is constructed.
605TEST_P(AbstractEventLoopTest, FetchNextIfAfterSend) {
606 auto loop1 = Make();
607 auto loop2 = MakePrimary();
608
609 auto sender = loop1->MakeSender<TestMessage>("/test");
610
611 ::std::vector<int> values;
612
613 for (int i = 200; i < 202; ++i) {
614 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
615 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
616 builder.add_value(i);
617 msg.CheckOk(msg.Send(builder.Finish()));
618 }
619
620 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
621
622 // Add a timer to actually quit.
623 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
624 while (fetcher.FetchNextIf(MakeShouldFetch(true))) {
625 values.push_back(fetcher.get()->value());
626 }
627 this->Exit();
628 });
629
630 loop2->OnRun([&test_timer, &loop2]() {
631 test_timer->Schedule(loop2->monotonic_now(),
632 ::std::chrono::milliseconds(100));
633 });
634
635 Run();
636 EXPECT_EQ(0, values.size());
637}
638
Austin Schuhbbce72d2019-05-26 15:11:46 -0700639// Tests that Fetch returns the last message created before the loop was
640// started.
641TEST_P(AbstractEventLoopTest, FetchDataFromBeforeCreation) {
642 auto loop1 = Make();
643 auto loop2 = MakePrimary();
644
645 auto sender = loop1->MakeSender<TestMessage>("/test");
646
647 ::std::vector<int> values;
648
Austin Schuh98ed26f2023-07-19 14:12:28 -0700649 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700650 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
651 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700652 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700653 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700654 }
655
656 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
657
658 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700659 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700660 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700661 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700662 }
663 // Do it again to make sure we don't double fetch.
664 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700665 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700666 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700667 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700668 });
669
670 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700671 test_timer->Schedule(loop2->monotonic_now(),
672 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700673 });
674
675 Run();
676 EXPECT_THAT(values, ::testing::ElementsAreArray({201}));
677}
678
Austin Schuh98ed26f2023-07-19 14:12:28 -0700679// Tests that FetchIf returns the last message created before the loop was
680// started.
681TEST_P(AbstractEventLoopTest, FetchIfDataFromBeforeCreation) {
682 auto loop1 = Make();
683 auto loop2 = MakePrimary();
684
685 auto sender = loop1->MakeSender<TestMessage>("/test");
686
687 ::std::vector<int> values;
688
689 for (int i = 200; i < 202; ++i) {
690 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
691 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
692 builder.add_value(i);
693 msg.CheckOk(msg.Send(builder.Finish()));
694 }
695
696 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
697
698 // Add a timer to actually quit.
699 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
700 if (fetcher.FetchIf(MakeShouldFetch(true))) {
701 values.push_back(fetcher.get()->value());
702 }
703
704 if (fetcher.FetchIf(MakeShouldFetch(false))) {
705 values.push_back(fetcher.get()->value());
706 }
707 // Do it again to make sure we don't double fetch.
708 if (fetcher.FetchIf(MakeShouldFetch(true))) {
709 values.push_back(fetcher.get()->value());
710 }
711 this->Exit();
712 });
713
714 loop2->OnRun([&test_timer, &loop2]() {
715 test_timer->Schedule(loop2->monotonic_now(),
716 ::std::chrono::milliseconds(100));
717 });
718
719 Run();
720 EXPECT_THAT(values, ::testing::ElementsAreArray({201}));
721}
722
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700723// Tests that timer handler is enabled after setup (even if it is in the past)
724// and is disabled after running
725TEST_P(AbstractEventLoopTest, CheckTimerDisabled) {
726 auto loop = MakePrimary("primary");
727
728 auto timer = loop->AddTimer([this]() {
729 LOG(INFO) << "timer called";
730 Exit();
731 });
732
733 loop->OnRun([&loop, timer]() {
734 EXPECT_TRUE(timer->IsDisabled());
Philipp Schradera6712522023-07-05 20:25:11 -0700735 timer->Schedule(loop->monotonic_now() + chrono::milliseconds(100));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700736 EXPECT_FALSE(timer->IsDisabled());
737 });
738
739 Run();
740 EXPECT_TRUE(timer->IsDisabled());
741}
742
743// Tests that timer handler is enabled after setup (even if it is in the past)
744// and is disabled after running
745TEST_P(AbstractEventLoopTest, CheckTimerRunInPastDisabled) {
746 auto loop = MakePrimary("primary");
747
748 auto timer2 = loop->AddTimer([this]() {
749 LOG(INFO) << "timer called";
750 Exit();
751 });
752
753 auto timer = loop->AddTimer([&loop, timer2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700754 timer2->Schedule(loop->monotonic_now() - chrono::nanoseconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700755 });
756
757 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700758 timer->Schedule(loop->monotonic_now() + chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700759 EXPECT_FALSE(timer->IsDisabled());
760 });
761
762 Run();
763 EXPECT_TRUE(timer2->IsDisabled());
764}
765
766// Tests that timer handler is not disabled even after calling Exit on the event
767// loop within the timer
768TEST_P(AbstractEventLoopTest, CheckTimerRepeatOnCountDisabled) {
769 auto loop = MakePrimary("primary");
770 int counter = 0;
771
772 auto timer = loop->AddTimer([&counter, this]() {
773 LOG(INFO) << "timer called";
774 counter++;
775 if (counter >= 5) {
776 Exit();
777 }
778 });
779
780 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700781 timer->Schedule(loop->monotonic_now() + chrono::seconds(1),
782 chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700783 EXPECT_FALSE(timer->IsDisabled());
784 });
785 Run();
786
787 // Sanity check
788 EXPECT_EQ(counter, 5);
789
790 // if you run the loop again, the timer will start running again
791 EXPECT_FALSE(timer->IsDisabled());
792
793 counter = 0;
794 Run();
795 timer->Disable();
796
797 EXPECT_TRUE(timer->IsDisabled());
798}
799
800// Tests that timer handler is not disabled even after calling Exit on the event
801// loop using an external timer
802TEST_P(AbstractEventLoopTest, CheckTimerRepeatTillEndTimerDisabled) {
803 auto loop = MakePrimary("primary");
804
805 auto timer = loop->AddTimer([]() { LOG(INFO) << "timer called"; });
806
807 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700808 timer->Schedule(loop->monotonic_now() + chrono::seconds(1),
809 chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700810 EXPECT_FALSE(timer->IsDisabled());
811 });
812
813 EndEventLoop(loop.get(), chrono::seconds(5));
814 Run();
815 EXPECT_FALSE(timer->IsDisabled());
816
817 timer->Disable();
818 EXPECT_TRUE(timer->IsDisabled());
819}
820
Austin Schuhbbce72d2019-05-26 15:11:46 -0700821// Tests that Fetch and FetchNext interleave as expected.
822TEST_P(AbstractEventLoopTest, FetchAndFetchNextTogether) {
823 auto loop1 = Make();
824 auto loop2 = MakePrimary();
825
826 auto sender = loop1->MakeSender<TestMessage>("/test");
827
828 ::std::vector<int> values;
829
Austin Schuh98ed26f2023-07-19 14:12:28 -0700830 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700831 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
832 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700833 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700834 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700835 }
836
837 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
838
839 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700840 auto test_timer = loop2->AddTimer([&fetcher, &values, &sender, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700841 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700842 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700843 }
844
Austin Schuh98ed26f2023-07-19 14:12:28 -0700845 for (int i = 202; i < 205; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700846 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
847 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700848 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700849 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700850 }
851
852 if (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700853 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700854 }
855
856 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700857 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700858 }
859
Austin Schuh9fe68f72019-08-10 19:32:03 -0700860 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700861 });
862
863 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700864 test_timer->Schedule(loop2->monotonic_now(),
865 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700866 });
867
868 Run();
869 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
870}
871
Austin Schuh98ed26f2023-07-19 14:12:28 -0700872// Tests that Fetch{If,} and FetchNext{If,} interleave as expected.
873TEST_P(AbstractEventLoopTest, FetchAndFetchNextIfTogether) {
874 auto loop1 = Make();
875 auto loop2 = MakePrimary();
876
877 auto sender = loop1->MakeSender<TestMessage>("/test");
878
879 ::std::vector<int> values;
880
881 for (int i = 200; i < 202; ++i) {
882 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
883 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
884 builder.add_value(i);
885 msg.CheckOk(msg.Send(builder.Finish()));
886 }
887
888 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
889
890 // Add a timer to actually quit.
891 auto test_timer = loop2->AddTimer([&fetcher, &values, &sender, this]() {
892 if (fetcher.Fetch()) {
893 values.push_back(fetcher.get()->value());
894 }
895
896 for (int i = 202; i < 205; ++i) {
897 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
898 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
899 builder.add_value(i);
900 msg.CheckOk(msg.Send(builder.Finish()));
901 }
902
903 EXPECT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false)));
904
905 if (fetcher.FetchNext()) {
906 values.push_back(fetcher.get()->value());
907 }
908
909 EXPECT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false)));
910 EXPECT_FALSE(fetcher.FetchIf(MakeShouldFetch(false)));
911
912 if (fetcher.FetchIf(MakeShouldFetch(true))) {
913 values.push_back(fetcher.get()->value());
914 }
915
916 this->Exit();
917 });
918
919 loop2->OnRun([&test_timer, &loop2]() {
920 test_timer->Schedule(loop2->monotonic_now(),
921 ::std::chrono::milliseconds(100));
922 });
923
924 Run();
925 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
926}
927
Austin Schuh3115a202019-05-27 21:02:14 -0700928// Tests that FetchNext behaves correctly when we get two messages in the queue
929// but don't consume the first until after the second has been sent.
930TEST_P(AbstractEventLoopTest, FetchNextTest) {
Austin Schuh3115a202019-05-27 21:02:14 -0700931 auto send_loop = Make();
932 auto fetch_loop = Make();
933 auto sender = send_loop->MakeSender<TestMessage>("/test");
934 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
935
936 {
Tyler Chatow67ddb032020-01-12 14:30:04 -0800937 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
938 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
939 builder.add_value(100);
milind1f1dca32021-07-03 13:50:07 -0700940 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700941 }
942
943 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700944 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
945 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
946 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700947 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700948 }
949
950 ASSERT_TRUE(fetcher.FetchNext());
951 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700952 EXPECT_EQ(100, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700953
954 ASSERT_TRUE(fetcher.FetchNext());
955 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700956 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700957
958 // When we run off the end of the queue, expect to still have the old message:
959 ASSERT_FALSE(fetcher.FetchNext());
960 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700961 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700962}
963
Austin Schuh98ed26f2023-07-19 14:12:28 -0700964// Tests that FetchNext behaves correctly when we get two messages in the queue
965// but don't consume the first until after the second has been sent.
966TEST_P(AbstractEventLoopTest, FetchNextIfTest) {
967 auto send_loop = Make();
968 auto fetch_loop = Make();
969 auto sender = send_loop->MakeSender<TestMessage>("/test");
970 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
971
972 {
973 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
974 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
975 builder.add_value(100);
976 msg.CheckOk(msg.Send(builder.Finish()));
977 }
978
979 {
980 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
981 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
982 builder.add_value(200);
983 msg.CheckOk(msg.Send(builder.Finish()));
984 }
985
986 size_t called_count = 0;
987 ASSERT_TRUE(fetcher.FetchNextIf(MakeShouldFetch(true, &called_count)));
988 ASSERT_NE(nullptr, fetcher.get());
989 EXPECT_EQ(100, fetcher.get()->value());
990 EXPECT_EQ(called_count, 1u);
991
992 ASSERT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false, &called_count)));
993 EXPECT_EQ(called_count, 2u);
994
995 ASSERT_TRUE(fetcher.FetchNextIf(MakeShouldFetch(true, &called_count)));
996 ASSERT_NE(nullptr, fetcher.get());
997 EXPECT_EQ(200, fetcher.get()->value());
998 EXPECT_EQ(called_count, 3u);
999
1000 // When we run off the end of the queue, expect to still have the old message:
1001 ASSERT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false, &called_count)));
1002 EXPECT_EQ(called_count, 3u);
1003 ASSERT_NE(nullptr, fetcher.get());
1004 EXPECT_EQ(200, fetcher.get()->value());
1005}
1006
Brian Silverman77162972020-08-12 19:52:40 -07001007// Verify that a fetcher still holds its data, even after falling behind.
1008TEST_P(AbstractEventLoopTest, FetcherBehindData) {
1009 auto send_loop = Make();
1010 auto fetch_loop = Make();
1011 auto sender = send_loop->MakeSender<TestMessage>("/test");
1012 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
1013 {
1014 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1015 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1016 builder.add_value(1);
milind1f1dca32021-07-03 13:50:07 -07001017 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -07001018 }
1019 ASSERT_TRUE(fetcher.Fetch());
1020 EXPECT_EQ(1, fetcher.get()->value());
1021 for (int i = 0; i < 300; ++i) {
1022 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1023 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1024 builder.add_value(i + 2);
milind1f1dca32021-07-03 13:50:07 -07001025 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -07001026 }
1027 EXPECT_EQ(1, fetcher.get()->value());
1028}
1029
1030// Try a bunch of orderings of operations with fetchers and senders. Verify that
1031// all the fetchers have the correct data at each step.
1032TEST_P(AbstractEventLoopTest, FetcherPermutations) {
1033 for (int max_save = 0; max_save < 5; ++max_save) {
1034 SCOPED_TRACE("max_save=" + std::to_string(max_save));
1035
1036 auto send_loop = Make();
1037 auto fetch_loop = Make();
1038 auto sender = send_loop->MakeSender<TestMessage>("/test");
1039 const auto send_message = [&sender](int i) {
1040 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1041 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1042 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -07001043 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -07001044 };
1045 std::vector<Fetcher<TestMessage>> fetchers;
1046 for (int i = 0; i < 10; ++i) {
1047 fetchers.emplace_back(fetch_loop->MakeFetcher<TestMessage>("/test"));
1048 }
1049 send_message(1);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001050 const auto verify_buffers = [&]() {
1051 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>>
1052 fetchers_copy;
1053 for (const auto &fetcher : fetchers) {
1054 fetchers_copy.emplace_back(fetcher);
1055 }
1056 std::vector<std::reference_wrapper<const Sender<TestMessage>>>
1057 senders_copy;
1058 senders_copy.emplace_back(sender);
1059 VerifyBuffers(send_loop->NumberBuffers(sender.channel()), fetchers_copy,
1060 senders_copy);
1061 };
Brian Silverman77162972020-08-12 19:52:40 -07001062 for (auto &fetcher : fetchers) {
1063 ASSERT_TRUE(fetcher.Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -07001064 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001065 EXPECT_EQ(1, fetcher.get()->value());
1066 }
1067
1068 for (int save = 1; save <= max_save; ++save) {
1069 SCOPED_TRACE("save=" + std::to_string(save));
1070 send_message(100 + save);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001071 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001072 for (size_t i = 0; i < fetchers.size() - save; ++i) {
1073 SCOPED_TRACE("fetcher=" + std::to_string(i));
1074 ASSERT_TRUE(fetchers[i].Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -07001075 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001076 EXPECT_EQ(100 + save, fetchers[i].get()->value());
1077 }
1078 for (size_t i = fetchers.size() - save; i < fetchers.size() - 1; ++i) {
1079 SCOPED_TRACE("fetcher=" + std::to_string(i));
1080 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
1081 }
1082 EXPECT_EQ(1, fetchers.back().get()->value());
1083 }
1084
1085 for (int i = 0; i < 300; ++i) {
1086 send_message(200 + i);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001087 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001088 }
1089
1090 for (size_t i = 0; i < fetchers.size() - max_save; ++i) {
1091 SCOPED_TRACE("fetcher=" + std::to_string(i));
1092 if (max_save > 0) {
1093 EXPECT_EQ(100 + max_save, fetchers[i].get()->value());
1094 } else {
1095 EXPECT_EQ(1, fetchers[i].get()->value());
1096 }
1097 }
1098 for (size_t i = fetchers.size() - max_save; i < fetchers.size() - 1; ++i) {
1099 SCOPED_TRACE("fetcher=" + std::to_string(i));
1100 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
1101 }
1102 EXPECT_EQ(1, fetchers.back().get()->value());
1103 }
1104}
1105
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001106// Verify that making a fetcher and watcher for "/test" succeeds.
1107TEST_P(AbstractEventLoopTest, FetcherAndWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -08001108 auto loop = Make();
1109 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001110 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Parker Schuhe4a70d62017-12-27 20:10:20 -08001111}
1112
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001113// Verify that making 2 fetchers for "/test" succeeds.
Parker Schuhe4a70d62017-12-27 20:10:20 -08001114TEST_P(AbstractEventLoopTest, TwoFetcher) {
1115 auto loop = Make();
1116 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001117 auto fetcher2 = loop->MakeFetcher<TestMessage>("/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -08001118}
1119
Alex Perrycb7da4b2019-08-28 19:35:56 -07001120// Verify that registering a watcher for an invalid channel name dies.
1121TEST_P(AbstractEventLoopDeathTest, InvalidChannelName) {
1122 auto loop = Make();
1123 EXPECT_DEATH(
1124 { loop->MakeWatcher("/test/invalid", [&](const TestMessage &) {}); },
1125 "/test/invalid");
Brian Silverman454bc112020-03-05 14:21:25 -08001126 EXPECT_DEATH(
1127 { loop->MakeNoArgWatcher<TestMessage>("/test/invalid", [&]() {}); },
1128 "/test/invalid");
Alex Perrycb7da4b2019-08-28 19:35:56 -07001129}
1130
James Kuszmaul8866e642022-06-10 16:00:36 -07001131// Verify that setting up a timer before monotonic_clock::epoch() fails.
James Kuszmaul86e86c32022-07-21 17:39:47 -07001132TEST_P(AbstractEventLoopDeathTest, NegativeTimeTimer) {
James Kuszmaul8866e642022-06-10 16:00:36 -07001133 auto loop = Make();
1134 TimerHandler *time = loop->AddTimer([]() {});
Philipp Schradera6712522023-07-05 20:25:11 -07001135 EXPECT_DEATH(
1136 time->Schedule(monotonic_clock::epoch() - std::chrono::seconds(1)),
1137 "-1.000");
James Kuszmaul8866e642022-06-10 16:00:36 -07001138}
1139
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001140// Verify that registering a watcher twice for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001141TEST_P(AbstractEventLoopDeathTest, TwoWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -08001142 auto loop = Make();
1143 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001144 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
1145 "/test");
Brian Silverman454bc112020-03-05 14:21:25 -08001146 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
1147}
1148
1149// Verify that registering a no-arg watcher twice for "/test" fails.
1150TEST_P(AbstractEventLoopDeathTest, TwoNoArgWatcher) {
1151 auto loop = Make();
1152 loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {});
1153 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
1154 "/test");
1155 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001156}
1157
Austin Schuh3115a202019-05-27 21:02:14 -07001158// Verify that SetRuntimeRealtimePriority fails while running.
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001159TEST_P(AbstractEventLoopDeathTest, SetRuntimeRealtimePriority) {
Austin Schuh3115a202019-05-27 21:02:14 -07001160 auto loop = MakePrimary();
Austin Schuh65493d62022-08-17 15:10:37 -07001161 EXPECT_EQ(0, loop->runtime_realtime_priority());
Austin Schuh3115a202019-05-27 21:02:14 -07001162 // Confirm that runtime priority calls work when not realtime.
1163 loop->SetRuntimeRealtimePriority(5);
Austin Schuh65493d62022-08-17 15:10:37 -07001164 EXPECT_EQ(5, loop->runtime_realtime_priority());
Austin Schuh3115a202019-05-27 21:02:14 -07001165
1166 loop->OnRun([&]() { loop->SetRuntimeRealtimePriority(5); });
1167
1168 EXPECT_DEATH(Run(), "realtime");
1169}
1170
Austin Schuh65493d62022-08-17 15:10:37 -07001171namespace {
1172
1173bool CpuSetEqual(const cpu_set_t &a, const cpu_set_t &b) {
1174 return CPU_EQUAL(&a, &b);
1175}
1176
1177} // namespace
1178
Brian Silverman6a54ff32020-04-28 16:41:39 -07001179// Verify that SetRuntimeAffinity fails while running.
1180TEST_P(AbstractEventLoopDeathTest, SetRuntimeAffinity) {
Austin Schuhde973292021-10-12 18:09:49 -07001181 const cpu_set_t available = GetCurrentThreadAffinity();
1182 int first_cpu = -1;
1183 for (int i = 0; i < CPU_SETSIZE; ++i) {
1184 if (CPU_ISSET(i, &available)) {
1185 first_cpu = i;
1186 break;
1187 continue;
1188 }
1189 }
1190 CHECK_NE(first_cpu, -1) << ": Default affinity has no CPUs?";
1191
Brian Silverman6a54ff32020-04-28 16:41:39 -07001192 auto loop = MakePrimary();
Austin Schuh65493d62022-08-17 15:10:37 -07001193 EXPECT_TRUE(
1194 CpuSetEqual(EventLoop::DefaultAffinity(), loop->runtime_affinity()));
1195 const cpu_set_t new_affinity = MakeCpusetFromCpus({first_cpu});
Brian Silverman6a54ff32020-04-28 16:41:39 -07001196 // Confirm that runtime priority calls work when not running.
Austin Schuh65493d62022-08-17 15:10:37 -07001197 loop->SetRuntimeAffinity(new_affinity);
1198 EXPECT_TRUE(CpuSetEqual(new_affinity, loop->runtime_affinity()));
Brian Silverman6a54ff32020-04-28 16:41:39 -07001199
Austin Schuhde973292021-10-12 18:09:49 -07001200 loop->OnRun(
1201 [&]() { loop->SetRuntimeAffinity(MakeCpusetFromCpus({first_cpu})); });
Brian Silverman6a54ff32020-04-28 16:41:39 -07001202
1203 EXPECT_DEATH(Run(), "Cannot set affinity while running");
1204}
1205
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001206// Verify that registering a watcher and a sender for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001207TEST_P(AbstractEventLoopDeathTest, WatcherAndSender) {
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001208 auto loop = Make();
1209 auto sender = loop->MakeSender<TestMessage>("/test");
1210 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
1211 "/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -08001212}
1213
Austin Schuhe516ab02020-05-06 21:37:04 -07001214// Verify that creating too many senders fails.
1215TEST_P(AbstractEventLoopDeathTest, TooManySenders) {
1216 auto loop = Make();
1217 std::vector<aos::Sender<TestMessage>> senders;
1218 for (int i = 0; i < 10; ++i) {
1219 senders.emplace_back(loop->MakeSender<TestMessage>("/test"));
1220 }
1221 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); },
1222 "Failed to create sender on \\{ \"name\": \"/test\", \"type\": "
Brian Silverman77162972020-08-12 19:52:40 -07001223 "\"aos.TestMessage\"[^}]*\\ }, too many senders.");
1224}
1225
1226// Verify that creating too many fetchers fails.
1227TEST_P(AbstractEventLoopDeathTest, TooManyFetchers) {
1228 if (read_method() != ReadMethod::PIN) {
1229 // Other read methods don't limit the number of readers, so just skip this.
1230 return;
1231 }
1232
1233 auto loop = Make();
1234 std::vector<aos::Fetcher<TestMessage>> fetchers;
1235 for (int i = 0; i < 10; ++i) {
1236 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1237 }
1238 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1239 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1240 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
1241}
1242
1243// Verify that creating too many fetchers, split between two event loops, fails.
1244TEST_P(AbstractEventLoopDeathTest, TooManyFetchersTwoLoops) {
1245 if (read_method() != ReadMethod::PIN) {
1246 // Other read methods don't limit the number of readers, so just skip this.
1247 return;
1248 }
1249
1250 auto loop = Make();
1251 auto loop2 = Make();
1252 std::vector<aos::Fetcher<TestMessage>> fetchers;
1253 for (int i = 0; i < 5; ++i) {
1254 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1255 fetchers.emplace_back(loop2->MakeFetcher<TestMessage>("/test"));
1256 }
1257 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1258 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1259 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
1260}
1261
1262// Verify that creating too many watchers fails.
1263TEST_P(AbstractEventLoopDeathTest, TooManyWatchers) {
1264 if (read_method() != ReadMethod::PIN) {
1265 // Other read methods don't limit the number of readers, so just skip this.
1266 return;
1267 }
1268
1269 std::vector<std::unique_ptr<EventLoop>> loops;
1270 for (int i = 0; i < 10; ++i) {
1271 loops.emplace_back(Make());
1272 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
1273 }
1274 EXPECT_DEATH({ Make()->MakeWatcher("/test", [](const TestMessage &) {}); },
1275 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1276 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
1277}
1278
1279// Verify that creating too many watchers and fetchers combined fails.
1280TEST_P(AbstractEventLoopDeathTest, TooManyWatchersAndFetchers) {
1281 if (read_method() != ReadMethod::PIN) {
1282 // Other read methods don't limit the number of readers, so just skip this.
1283 return;
1284 }
1285
1286 auto loop = Make();
1287 std::vector<aos::Fetcher<TestMessage>> fetchers;
1288 std::vector<std::unique_ptr<EventLoop>> loops;
1289 for (int i = 0; i < 5; ++i) {
1290 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1291 loops.emplace_back(Make());
1292 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
1293 }
1294 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1295 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1296 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
Austin Schuhe516ab02020-05-06 21:37:04 -07001297}
1298
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001299// Verify that we can't create a sender inside OnRun.
1300TEST_P(AbstractEventLoopDeathTest, SenderInOnRun) {
1301 auto loop1 = MakePrimary();
1302
1303 loop1->OnRun(
1304 [&]() { auto sender = loop1->MakeSender<TestMessage>("/test2"); });
1305
1306 EXPECT_DEATH(Run(), "running");
1307}
1308
1309// Verify that we can't create a watcher inside OnRun.
1310TEST_P(AbstractEventLoopDeathTest, WatcherInOnRun) {
1311 auto loop1 = MakePrimary();
1312
1313 loop1->OnRun(
1314 [&]() { loop1->MakeWatcher("/test", [&](const TestMessage &) {}); });
1315
1316 EXPECT_DEATH(Run(), "running");
1317}
1318
Brian Silverman454bc112020-03-05 14:21:25 -08001319// Verify that we can't create a no-arg watcher inside OnRun.
1320TEST_P(AbstractEventLoopDeathTest, NoArgWatcherInOnRun) {
1321 auto loop1 = MakePrimary();
1322
1323 loop1->OnRun(
1324 [&]() { loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {}); });
1325
1326 EXPECT_DEATH(Run(), "running");
1327}
1328
Parker Schuhe4a70d62017-12-27 20:10:20 -08001329// Verify that Quit() works when there are multiple watchers.
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001330TEST_P(AbstractEventLoopTest, MultipleWatcherQuit) {
1331 auto loop1 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -07001332 auto loop2 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -08001333
Austin Schuh3578a2e2019-05-25 18:17:59 -07001334 loop2->MakeWatcher("/test1", [&](const TestMessage &) {});
1335 loop2->MakeWatcher("/test2", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001336 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -07001337 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -07001338 });
1339
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001340 auto sender = loop1->MakeSender<TestMessage>("/test2");
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001341
1342 loop2->OnRun([&]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001343 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1344 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1345 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001346 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001347 });
Parker Schuhe4a70d62017-12-27 20:10:20 -08001348
Austin Schuh44019f92019-05-19 19:58:27 -07001349 Run();
Parker Schuhe4a70d62017-12-27 20:10:20 -08001350}
1351
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001352// Verify that AOS_LOG has the right name.
1353TEST_P(AbstractEventLoopTest, AOSLog) {
1354 auto loop2 = MakePrimary("loop1");
1355 auto loop1 = Make("loop0");
1356
1357 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1358
1359 EXPECT_FALSE(fetcher.Fetch());
1360
1361 loop2->OnRun([&]() {
1362 AOS_LOG(INFO, "Testing123");
1363 this->Exit();
1364 });
1365
1366 Run();
1367 EXPECT_TRUE(fetcher.Fetch());
1368 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1369}
1370
1371// Verify that AOS_LOG has the right name in a watcher.
1372TEST_P(AbstractEventLoopTest, AOSLogWatcher) {
1373 auto loop2 = MakePrimary("loop1");
1374 auto loop1 = Make("loop0");
1375
1376 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1377
1378 EXPECT_FALSE(fetcher.Fetch());
1379
1380 auto sender = loop1->MakeSender<TestMessage>("/test2");
1381
1382 loop2->MakeWatcher("/test2", [&](const TestMessage & /*message*/) {
1383 AOS_LOG(INFO, "Testing123");
1384 this->Exit();
1385 });
1386
1387 loop2->OnRun([&]() {
1388 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1389 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1390 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001391 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001392 });
1393
1394 Run();
1395 EXPECT_TRUE(fetcher.Fetch());
1396 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1397}
1398
1399// Verify that AOS_LOG has the right name in a timer.
1400TEST_P(AbstractEventLoopTest, AOSLogTimer) {
1401 auto loop2 = MakePrimary("loop1");
1402 auto loop1 = Make("loop0");
1403
1404 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1405
1406 EXPECT_FALSE(fetcher.Fetch());
1407
1408 auto test_timer = loop2->AddTimer([&]() {
1409 AOS_LOG(INFO, "Testing123");
1410 this->Exit();
1411 });
1412
Philipp Schradera6712522023-07-05 20:25:11 -07001413 loop2->OnRun([&]() { test_timer->Schedule(loop2->monotonic_now()); });
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001414
1415 Run();
1416 EXPECT_TRUE(fetcher.Fetch());
1417 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1418}
1419
Neil Balch229001a2018-01-07 18:22:52 -08001420// Verify that timer intervals and duration function properly.
1421TEST_P(AbstractEventLoopTest, TimerIntervalAndDuration) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001422 // Force a slower rate so we are guaranteed to have reports for our timer.
Austin Schuh39788ff2019-12-01 18:22:57 -08001423 FLAGS_timing_report_ms = 2000;
1424
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001425 const int kCount = 5;
Neil Balch229001a2018-01-07 18:22:52 -08001426
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001427 auto loop = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001428 auto loop2 = Make();
1429
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001430 ::std::vector<::aos::monotonic_clock::time_point> times;
1431 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
1432
Austin Schuh39788ff2019-12-01 18:22:57 -08001433 Fetcher<timing::Report> report_fetcher =
1434 loop2->MakeFetcher<timing::Report>("/aos");
1435 EXPECT_FALSE(report_fetcher.Fetch());
1436
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001437 auto test_timer = loop->AddTimer([this, &times, &expected_times, &loop]() {
1438 times.push_back(loop->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001439 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
1440 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
1441 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001442 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -08001443 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
1444 EXPECT_EQ(loop->context().size, 0u);
1445 EXPECT_EQ(loop->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001446 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001447
Austin Schuhad154822019-12-27 15:45:13 -08001448 expected_times.push_back(loop->context().monotonic_event_time);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001449 if (times.size() == kCount) {
1450 this->Exit();
1451 }
Neil Balch229001a2018-01-07 18:22:52 -08001452 });
Austin Schuh39788ff2019-12-01 18:22:57 -08001453 test_timer->set_name("Test loop");
Neil Balch229001a2018-01-07 18:22:52 -08001454
Austin Schuh39788ff2019-12-01 18:22:57 -08001455 const monotonic_clock::time_point start_time = loop->monotonic_now();
Austin Schuh52d325c2019-06-23 18:59:06 -07001456 // TODO(austin): This should be an error... Should be done in OnRun only.
Philipp Schradera6712522023-07-05 20:25:11 -07001457 test_timer->Schedule(start_time + chrono::seconds(1), chrono::seconds(1));
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001458
Austin Schuh44019f92019-05-19 19:58:27 -07001459 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001460
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001461 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001462 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
1463 ASSERT_EQ(times.size(), expected_times.size());
1464 ASSERT_EQ((times.size() % 2), 1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001465
1466 // Grab the middle sample.
1467 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
1468
1469 // Add up all the delays of all the times.
1470 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1471 for (const ::aos::monotonic_clock::time_point time : times) {
1472 sum += time - average_time;
1473 }
1474
1475 // Average and add to the middle to find the average time.
1476 sum /= times.size();
1477 average_time += sum;
1478
1479 // Compute the offset from the average and the expected average. It
1480 // should be pretty close to 0.
1481 const ::aos::monotonic_clock::duration remainder =
1482 average_time - start_time - chrono::seconds(times.size() / 2 + 1);
1483
1484 const chrono::milliseconds kEpsilon(100);
1485 EXPECT_LT(remainder, +kEpsilon);
1486 EXPECT_GT(remainder, -kEpsilon);
1487
1488 // Make sure that the average duration is close to 1 second.
1489 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1490 times.front())
1491 .count() /
1492 static_cast<double>(times.size() - 1),
1493 1.0, 0.1);
1494
1495 // Confirm that the ideal wakeup times increment correctly.
1496 for (size_t i = 1; i < expected_times.size(); ++i) {
1497 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1498 }
1499
1500 for (size_t i = 0; i < expected_times.size(); ++i) {
1501 EXPECT_EQ((expected_times[i] - start_time) % chrono::seconds(1),
1502 chrono::seconds(0));
1503 }
1504
1505 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1506 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001507
Austin Schuh6bae8252021-02-07 22:01:49 -08001508 if (do_timing_reports() == DoTimingReports::kYes) {
1509 // And, since we are here, check that the timing report makes sense.
1510 // Start by looking for our event loop's timing.
1511 FlatbufferDetachedBuffer<timing::Report> report =
1512 FlatbufferDetachedBuffer<timing::Report>::Empty();
1513 while (report_fetcher.FetchNext()) {
1514 if (report_fetcher->name()->string_view() == "primary") {
1515 report = CopyFlatBuffer(report_fetcher.get());
1516 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001517 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001518
1519 // Confirm that we have the right number of reports, and the contents are
1520 // sane.
1521 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
1522
1523 EXPECT_EQ(report.message().name()->string_view(), "primary");
1524
1525 ASSERT_NE(report.message().senders(), nullptr);
1526 EXPECT_EQ(report.message().senders()->size(), 2);
1527
1528 ASSERT_NE(report.message().timers(), nullptr);
1529 EXPECT_EQ(report.message().timers()->size(), 2);
1530
1531 EXPECT_EQ(report.message().timers()->Get(0)->name()->string_view(),
1532 "Test loop");
1533 EXPECT_GE(report.message().timers()->Get(0)->count(), 1);
1534
1535 EXPECT_EQ(report.message().timers()->Get(1)->name()->string_view(),
1536 "timing_reports");
1537 EXPECT_EQ(report.message().timers()->Get(1)->count(), 1);
1538
1539 // Make sure there is a single phased loop report with our report in it.
1540 ASSERT_EQ(report.message().phased_loops(), nullptr);
1541 } else {
1542 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001543 }
Neil Balch229001a2018-01-07 18:22:52 -08001544}
1545
James Kuszmaul762e8692023-07-31 14:57:53 -07001546// Test that setting a default version string results in it getting populated
1547// correctly.
1548TEST_P(AbstractEventLoopTest, DefaultVersionStringInTimingReport) {
1549 gflags::FlagSaver flag_saver;
1550 FLAGS_timing_report_ms = 1000;
1551
1552 EventLoop::SetDefaultVersionString("default_version_string");
1553
1554 auto loop = MakePrimary();
1555
1556 Fetcher<timing::Report> report_fetcher =
1557 loop->MakeFetcher<timing::Report>("/aos");
1558
1559 TimerHandler *exit_timer = loop->AddTimer([this]() { Exit(); });
1560 loop->OnRun([exit_timer, &loop, &report_fetcher]() {
1561 report_fetcher.Fetch();
1562 exit_timer->Schedule(loop->monotonic_now() + std::chrono::seconds(2));
1563 });
1564
1565 Run();
1566
1567 bool found_primary_report = false;
1568 while (report_fetcher.FetchNext()) {
1569 if (report_fetcher->name()->string_view() == "primary") {
1570 found_primary_report = true;
1571 EXPECT_EQ("default_version_string",
1572 report_fetcher->version()->string_view());
1573 } else {
1574 FAIL() << report_fetcher->name()->string_view();
1575 }
1576 }
1577
1578 if (do_timing_reports() == DoTimingReports::kYes) {
1579 EXPECT_TRUE(found_primary_report);
1580 } else {
1581 EXPECT_FALSE(found_primary_report);
1582 }
1583}
1584
1585// Test that overriding the default version string results in it getting
1586// populated correctly.
1587TEST_P(AbstractEventLoopTest, OverrideDersionStringInTimingReport) {
1588 gflags::FlagSaver flag_saver;
1589 FLAGS_timing_report_ms = 1000;
1590
1591 EventLoop::SetDefaultVersionString("default_version_string");
1592
1593 auto loop = MakePrimary();
1594 loop->SetVersionString("override_version");
1595
1596 Fetcher<timing::Report> report_fetcher =
1597 loop->MakeFetcher<timing::Report>("/aos");
1598
1599 TimerHandler *exit_timer = loop->AddTimer([this]() { Exit(); });
1600 loop->OnRun([exit_timer, &loop, &report_fetcher]() {
1601 report_fetcher.Fetch();
1602 exit_timer->Schedule(loop->monotonic_now() + std::chrono::seconds(2));
1603 });
1604
1605 Run();
1606
1607 bool found_primary_report = false;
1608 while (report_fetcher.FetchNext()) {
1609 if (report_fetcher->name()->string_view() == "primary") {
1610 found_primary_report = true;
1611 EXPECT_EQ("override_version", report_fetcher->version()->string_view());
1612 } else {
1613 FAIL() << report_fetcher->name()->string_view();
1614 }
1615 }
1616
1617 if (do_timing_reports() == DoTimingReports::kYes) {
1618 EXPECT_TRUE(found_primary_report);
1619 } else {
1620 EXPECT_FALSE(found_primary_report);
1621 }
1622}
1623
Neil Balch229001a2018-01-07 18:22:52 -08001624// Verify that we can change a timer's parameters during execution.
1625TEST_P(AbstractEventLoopTest, TimerChangeParameters) {
Austin Schuh44019f92019-05-19 19:58:27 -07001626 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001627 loop->SetRuntimeRealtimePriority(1);
Austin Schuh7f20f512021-01-31 17:56:16 -08001628 std::vector<monotonic_clock::time_point> iteration_list;
Neil Balch229001a2018-01-07 18:22:52 -08001629
1630 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001631 ScopedNotRealtime nrt;
Austin Schuh7f20f512021-01-31 17:56:16 -08001632 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001633 });
1634
Austin Schuh7f20f512021-01-31 17:56:16 -08001635 monotonic_clock::time_point s;
1636 auto modifier_timer = loop->AddTimer([&test_timer, &s]() {
Philipp Schradera6712522023-07-05 20:25:11 -07001637 test_timer->Schedule(s + chrono::milliseconds(1750),
1638 chrono::milliseconds(600));
Neil Balch229001a2018-01-07 18:22:52 -08001639 });
1640
Austin Schuh7f20f512021-01-31 17:56:16 -08001641 s = loop->monotonic_now();
Philipp Schradera6712522023-07-05 20:25:11 -07001642 test_timer->Schedule(s, chrono::milliseconds(500));
1643 modifier_timer->Schedule(s + chrono::milliseconds(1250));
Austin Schuhd892f102021-10-12 18:01:46 -07001644 EndEventLoop(loop.get(), chrono::milliseconds(3950));
Austin Schuh44019f92019-05-19 19:58:27 -07001645 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001646
Austin Schuhd892f102021-10-12 18:01:46 -07001647 EXPECT_THAT(
1648 iteration_list,
1649 ::testing::ElementsAre(
1650 s, s + chrono::milliseconds(500), s + chrono::milliseconds(1000),
1651 s + chrono::milliseconds(1750), s + chrono::milliseconds(2350),
1652 s + chrono::milliseconds(2950), s + chrono::milliseconds(3550)));
Neil Balch229001a2018-01-07 18:22:52 -08001653}
1654
1655// Verify that we can disable a timer during execution.
1656TEST_P(AbstractEventLoopTest, TimerDisable) {
Austin Schuh44019f92019-05-19 19:58:27 -07001657 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001658 loop->SetRuntimeRealtimePriority(1);
Neil Balch229001a2018-01-07 18:22:52 -08001659 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
1660
1661 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001662 ScopedNotRealtime nrt;
Austin Schuhd892f102021-10-12 18:01:46 -07001663 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001664 });
1665
Tyler Chatow67ddb032020-01-12 14:30:04 -08001666 auto ender_timer = loop->AddTimer([&test_timer]() { test_timer->Disable(); });
Neil Balch229001a2018-01-07 18:22:52 -08001667
Austin Schuhd892f102021-10-12 18:01:46 -07001668 monotonic_clock::time_point s = loop->monotonic_now();
Philipp Schradera6712522023-07-05 20:25:11 -07001669 test_timer->Schedule(s, ::std::chrono::milliseconds(500));
1670 ender_timer->Schedule(s + ::std::chrono::milliseconds(1250));
Austin Schuh73d99502021-12-08 12:05:39 -08001671 EndEventLoop(loop.get(), ::std::chrono::milliseconds(2000));
Austin Schuh44019f92019-05-19 19:58:27 -07001672 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001673
Austin Schuhd892f102021-10-12 18:01:46 -07001674 EXPECT_THAT(iteration_list,
Austin Schuh73d99502021-12-08 12:05:39 -08001675 ::testing::ElementsAre(s, s + chrono::milliseconds(500),
1676 s + chrono::milliseconds(1000)));
Neil Balch229001a2018-01-07 18:22:52 -08001677}
Austin Schuh7267c532019-05-19 19:55:53 -07001678
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001679// Verify that a timer can disable itself.
1680//
1681// TODO(Brian): Do something similar with phased loops, both with a quick
1682// handler and a handler that would miss a cycle except it got deferred. Current
1683// behavior doing that is a mess.
1684TEST_P(AbstractEventLoopTest, TimerDisableSelf) {
1685 auto loop = MakePrimary();
1686
1687 int count = 0;
1688 aos::TimerHandler *test_timer;
1689 test_timer = loop->AddTimer([&count, &test_timer]() {
1690 ++count;
1691 test_timer->Disable();
1692 });
1693
Philipp Schradera6712522023-07-05 20:25:11 -07001694 test_timer->Schedule(loop->monotonic_now(), ::std::chrono::milliseconds(20));
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001695 EndEventLoop(loop.get(), ::std::chrono::milliseconds(80));
1696 Run();
1697
1698 EXPECT_EQ(count, 1);
1699}
1700
Brian Silvermanbd405c02020-06-23 16:25:23 -07001701// Verify that we can disable a timer during execution of another timer
1702// scheduled for the same time, with one ordering of creation for the timers.
1703//
1704// Also schedule some more events to reshuffle the heap in EventLoop used for
1705// tracking events to change up the order. This used to segfault
1706// SimulatedEventLoop.
1707TEST_P(AbstractEventLoopTest, TimerDisableOther) {
1708 for (bool creation_order : {true, false}) {
1709 for (bool setup_order : {true, false}) {
1710 for (int shuffle_events = 0; shuffle_events < 5; ++shuffle_events) {
1711 auto loop = MakePrimary();
1712 aos::TimerHandler *test_timer, *ender_timer;
1713 if (creation_order) {
1714 test_timer = loop->AddTimer([]() {});
1715 ender_timer =
1716 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1717 } else {
1718 ender_timer =
1719 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1720 test_timer = loop->AddTimer([]() {});
1721 }
1722
1723 const auto start = loop->monotonic_now();
1724
1725 for (int i = 0; i < shuffle_events; ++i) {
Philipp Schradera6712522023-07-05 20:25:11 -07001726 loop->AddTimer([]() {})->Schedule(start +
1727 std::chrono::milliseconds(10));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001728 }
1729
1730 if (setup_order) {
Philipp Schradera6712522023-07-05 20:25:11 -07001731 test_timer->Schedule(start + ::std::chrono::milliseconds(20));
1732 ender_timer->Schedule(start + ::std::chrono::milliseconds(20));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001733 } else {
Philipp Schradera6712522023-07-05 20:25:11 -07001734 ender_timer->Schedule(start + ::std::chrono::milliseconds(20));
1735 test_timer->Schedule(start + ::std::chrono::milliseconds(20));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001736 }
1737 EndEventLoop(loop.get(), ::std::chrono::milliseconds(40));
1738 Run();
1739 }
1740 }
1741 }
1742}
1743
Austin Schuh54cf95f2019-11-29 13:14:18 -08001744// Verifies that the event loop implementations detect when Channel is not a
Brian Silverman631b6262021-11-10 12:25:08 -08001745// pointer into configuration(), or a name doesn't map to a channel in
1746// configuration().
Austin Schuh54cf95f2019-11-29 13:14:18 -08001747TEST_P(AbstractEventLoopDeathTest, InvalidChannel) {
1748 auto loop = MakePrimary();
1749
Tyler Chatow67ddb032020-01-12 14:30:04 -08001750 const Channel *channel = configuration::GetChannel(
1751 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
Austin Schuh54cf95f2019-11-29 13:14:18 -08001752
1753 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1754
1755 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001756 loop->MakeRawSender(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001757 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1758
1759 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001760 loop->MakeSender<TestMessage>("/testbad"),
1761 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1762 " not found in config");
1763
1764 EXPECT_FALSE(loop->TryMakeSender<TestMessage>("/testbad"));
1765
1766 EXPECT_DEATH(
1767 loop->MakeRawFetcher(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001768 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1769
1770 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001771 loop->MakeFetcher<TestMessage>("/testbad"),
1772 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1773 " not found in config");
1774
1775 EXPECT_FALSE(loop->TryMakeFetcher<TestMessage>("/testbad").valid());
1776
1777 EXPECT_DEATH(
Austin Schuh54cf95f2019-11-29 13:14:18 -08001778 {
1779 loop->MakeRawWatcher(&channel_copy.message(),
1780 [](const Context, const void *) {});
1781 },
1782 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
Brian Silverman631b6262021-11-10 12:25:08 -08001783
1784 EXPECT_DEATH(
1785 { loop->MakeWatcher("/testbad", [](const TestMessage &) {}); },
1786 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1787 " not found in config");
1788}
1789
1790// Verifies that the event loop handles a channel which is not readable or
1791// writable on the current node nicely.
1792TEST_P(AbstractEventLoopDeathTest, InaccessibleChannel) {
1793 EnableNodes("me");
1794 auto loop = MakePrimary("me");
1795 auto loop2 = Make("them");
1796
1797 const Channel *channel = configuration::GetChannel(
1798 loop->configuration(), "/test_noforward", "aos.TestMessage", "", nullptr);
1799
1800 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1801
1802 EXPECT_DEATH(
1803 loop2->MakeSender<TestMessage>("/test_forward"),
1804 "Channel"
1805 " \\{ \"name\": \"/test_forward\", \"type\": \"aos.TestMessage\" \\}"
1806 " is not able to be sent on this node");
1807
1808 EXPECT_FALSE(loop2->TryMakeSender<TestMessage>("/test_forward"));
1809
1810 EXPECT_DEATH(
1811 loop2->MakeRawFetcher(channel),
1812 "Channel"
1813 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1814 " is not able to be fetched on this node");
1815
1816 EXPECT_DEATH(
1817 loop2->MakeFetcher<TestMessage>("/test_noforward"),
1818 "Channel"
1819 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1820 " is not able to be fetched on this node");
1821
1822 EXPECT_FALSE(loop2->TryMakeFetcher<TestMessage>("/test_noforward").valid());
1823
1824 EXPECT_DEATH(
1825 { loop2->MakeRawWatcher(channel, [](const Context, const void *) {}); },
1826 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1827 "\"source_node\": \"them\" \\}"
1828 " is not able to be watched on this node");
1829
1830 EXPECT_DEATH(
1831 { loop2->MakeWatcher("/test_noforward", [](const TestMessage &) {}); },
1832 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1833 "\"source_node\": \"them\" \\}"
1834 " is not able to be watched on this node");
Austin Schuh54cf95f2019-11-29 13:14:18 -08001835}
1836
Austin Schuhd54780b2020-10-03 16:26:02 -07001837// Verifies that the event loop implementations detect when Channel has an
1838// invalid alignment.
1839TEST_P(AbstractEventLoopDeathTest, InvalidChannelAlignment) {
1840 const char *const kError = "multiple of alignment";
1841 InvalidChannelAlignment();
1842
1843 auto loop = MakePrimary();
1844
1845 const Channel *channel = configuration::GetChannel(
1846 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
1847
1848 EXPECT_DEATH({ loop->MakeRawSender(channel); }, kError);
1849 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); }, kError);
1850
1851 EXPECT_DEATH({ loop->MakeRawFetcher(channel); }, kError);
1852 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); }, kError);
1853
1854 EXPECT_DEATH(
1855 { loop->MakeRawWatcher(channel, [](const Context &, const void *) {}); },
1856 kError);
1857 EXPECT_DEATH({ loop->MakeRawNoArgWatcher(channel, [](const Context &) {}); },
1858 kError);
1859
1860 EXPECT_DEATH({ loop->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
1861 kError);
1862 EXPECT_DEATH({ loop->MakeWatcher("/test", [](const TestMessage &) {}); },
1863 kError);
1864}
1865
Brian Silverman454bc112020-03-05 14:21:25 -08001866// Verify that the send time on a message is roughly right when using a watcher.
Austin Schuh7267c532019-05-19 19:55:53 -07001867TEST_P(AbstractEventLoopTest, MessageSendTime) {
Austin Schuh44019f92019-05-19 19:58:27 -07001868 auto loop1 = MakePrimary();
Austin Schuh7267c532019-05-19 19:55:53 -07001869 auto loop2 = Make();
Austin Schuhad154822019-12-27 15:45:13 -08001870 auto sender = loop2->MakeSender<TestMessage>("/test");
Austin Schuh7267c532019-05-19 19:55:53 -07001871 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
1872
1873 auto test_timer = loop1->AddTimer([&sender]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001874 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1875 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1876 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001877 msg.CheckOk(msg.Send(builder.Finish()));
Alex Perrycb7da4b2019-08-28 19:35:56 -07001878 });
1879
Austin Schuhad154822019-12-27 15:45:13 -08001880 bool triggered = false;
Brian Silverman454bc112020-03-05 14:21:25 -08001881 loop1->MakeWatcher("/test", [&](const TestMessage &msg) {
Austin Schuhad154822019-12-27 15:45:13 -08001882 // Confirm that the data pointer makes sense from a watcher, and all the
1883 // timestamps look right.
1884 EXPECT_GT(&msg, loop1->context().data);
1885 EXPECT_EQ(loop1->context().monotonic_remote_time,
1886 loop1->context().monotonic_event_time);
1887 EXPECT_EQ(loop1->context().realtime_remote_time,
1888 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001889 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001890
1891 const aos::monotonic_clock::time_point monotonic_now =
1892 loop1->monotonic_now();
Tyler Chatow67ddb032020-01-12 14:30:04 -08001893 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08001894
1895 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1896 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1897 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1898 monotonic_now);
1899 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1900 realtime_now);
1901
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001902 EXPECT_LT(&msg, reinterpret_cast<const void *>(
1903 reinterpret_cast<const char *>(loop1->context().data) +
Austin Schuhad154822019-12-27 15:45:13 -08001904 loop1->context().size));
Brian Silverman4f4e0612020-08-12 19:54:41 -07001905 if (read_method() == ReadMethod::PIN) {
1906 EXPECT_GE(loop1->context().buffer_index, 0);
1907 EXPECT_LT(loop1->context().buffer_index,
1908 loop1->NumberBuffers(
1909 configuration::GetChannel(loop1->configuration(), "/test",
1910 "aos.TestMessage", "", nullptr)));
1911 } else {
1912 EXPECT_EQ(-1, loop1->context().buffer_index);
1913 }
Austin Schuhad154822019-12-27 15:45:13 -08001914 triggered = true;
Austin Schuh7267c532019-05-19 19:55:53 -07001915 });
1916
Philipp Schradera6712522023-07-05 20:25:11 -07001917 test_timer->Schedule(loop1->monotonic_now() + ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07001918
1919 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
Austin Schuh44019f92019-05-19 19:58:27 -07001920 Run();
Austin Schuh7267c532019-05-19 19:55:53 -07001921
Austin Schuhad154822019-12-27 15:45:13 -08001922 EXPECT_TRUE(triggered);
1923
Brian Silverman454bc112020-03-05 14:21:25 -08001924 ASSERT_TRUE(fetcher.Fetch());
1925
1926 monotonic_clock::duration monotonic_time_offset =
1927 fetcher.context().monotonic_event_time -
1928 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1929 realtime_clock::duration realtime_time_offset =
1930 fetcher.context().realtime_event_time -
1931 (loop1->realtime_now() - ::std::chrono::seconds(1));
1932
1933 EXPECT_EQ(fetcher.context().realtime_event_time,
1934 fetcher.context().realtime_remote_time);
1935 EXPECT_EQ(fetcher.context().monotonic_event_time,
1936 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001937 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001938
1939 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1940 << ": Got "
1941 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1942 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1943 // Confirm that the data pointer makes sense.
1944 EXPECT_GT(fetcher.get(), fetcher.context().data);
1945 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001946 reinterpret_cast<const void *>(
1947 reinterpret_cast<const char *>(fetcher.context().data) +
Brian Silverman454bc112020-03-05 14:21:25 -08001948 fetcher.context().size));
1949 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1950 << ": Got "
1951 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1952 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1953
1954 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1955 << ": Got "
1956 << fetcher.context().realtime_event_time.time_since_epoch().count()
1957 << " expected " << loop1->realtime_now().time_since_epoch().count();
1958 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1959 << ": Got "
1960 << fetcher.context().realtime_event_time.time_since_epoch().count()
1961 << " expected " << loop1->realtime_now().time_since_epoch().count();
1962}
1963
1964// Verify that the send time on a message is roughly right when using a no-arg
1965// watcher. To get a message, we need to use a fetcher to actually access the
1966// message. This is also the main use case for no-arg fetchers.
1967TEST_P(AbstractEventLoopTest, MessageSendTimeNoArg) {
1968 auto loop1 = MakePrimary();
1969 auto loop2 = Make();
1970 auto sender = loop2->MakeSender<TestMessage>("/test");
1971 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
1972
1973 auto test_timer = loop1->AddTimer([&sender]() {
1974 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1975 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1976 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001977 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -08001978 });
1979
1980 bool triggered = false;
1981 loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {
1982 // Confirm that we can indeed use a fetcher on this channel from this
1983 // context, and it results in a sane data pointer and timestamps.
1984 ASSERT_TRUE(fetcher.Fetch());
1985
1986 EXPECT_EQ(loop1->context().monotonic_remote_time,
1987 loop1->context().monotonic_event_time);
1988 EXPECT_EQ(loop1->context().realtime_remote_time,
1989 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001990 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001991
1992 const aos::monotonic_clock::time_point monotonic_now =
1993 loop1->monotonic_now();
1994 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
1995
1996 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1997 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1998 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1999 monotonic_now);
2000 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
2001 realtime_now);
2002
2003 triggered = true;
2004 });
2005
Philipp Schradera6712522023-07-05 20:25:11 -07002006 test_timer->Schedule(loop1->monotonic_now() + ::std::chrono::seconds(1));
Brian Silverman454bc112020-03-05 14:21:25 -08002007
2008 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
2009 Run();
2010
2011 ASSERT_TRUE(triggered);
Austin Schuh7267c532019-05-19 19:55:53 -07002012
Alex Perrycb7da4b2019-08-28 19:35:56 -07002013 monotonic_clock::duration monotonic_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08002014 fetcher.context().monotonic_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07002015 (loop1->monotonic_now() - ::std::chrono::seconds(1));
2016 realtime_clock::duration realtime_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08002017 fetcher.context().realtime_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07002018 (loop1->realtime_now() - ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07002019
Austin Schuhad154822019-12-27 15:45:13 -08002020 EXPECT_EQ(fetcher.context().realtime_event_time,
2021 fetcher.context().realtime_remote_time);
2022 EXPECT_EQ(fetcher.context().monotonic_event_time,
2023 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002024 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08002025
Alex Perrycb7da4b2019-08-28 19:35:56 -07002026 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
2027 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002028 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh52d325c2019-06-23 18:59:06 -07002029 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07002030 // Confirm that the data pointer makes sense.
2031 EXPECT_GT(fetcher.get(), fetcher.context().data);
2032 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07002033 reinterpret_cast<const void *>(
2034 reinterpret_cast<const char *>(fetcher.context().data) +
Alex Perrycb7da4b2019-08-28 19:35:56 -07002035 fetcher.context().size));
2036 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
2037 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002038 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh7267c532019-05-19 19:55:53 -07002039 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07002040
2041 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
2042 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002043 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07002044 << " expected " << loop1->realtime_now().time_since_epoch().count();
2045 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
2046 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002047 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07002048 << " expected " << loop1->realtime_now().time_since_epoch().count();
Austin Schuh7267c532019-05-19 19:55:53 -07002049}
2050
Austin Schuh52d325c2019-06-23 18:59:06 -07002051// Tests that a couple phased loops run in a row result in the correct offset
2052// and period.
2053TEST_P(AbstractEventLoopTest, PhasedLoopTest) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07002054 // Force a slower rate so we are guaranteed to have reports for our phased
Austin Schuh39788ff2019-12-01 18:22:57 -08002055 // loop.
2056 FLAGS_timing_report_ms = 2000;
2057
Austin Schuh52d325c2019-06-23 18:59:06 -07002058 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2059 const int kCount = 5;
2060
2061 auto loop1 = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08002062 auto loop2 = Make();
2063
2064 Fetcher<timing::Report> report_fetcher =
2065 loop2->MakeFetcher<timing::Report>("/aos");
2066 EXPECT_FALSE(report_fetcher.Fetch());
Austin Schuh52d325c2019-06-23 18:59:06 -07002067
2068 // Collect up a couple of samples.
2069 ::std::vector<::aos::monotonic_clock::time_point> times;
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002070 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
Austin Schuh52d325c2019-06-23 18:59:06 -07002071
2072 // Run kCount iterations.
Austin Schuh39788ff2019-12-01 18:22:57 -08002073 loop1
2074 ->AddPhasedLoop(
2075 [&times, &expected_times, &loop1, this](int count) {
2076 EXPECT_EQ(count, 1);
2077 times.push_back(loop1->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08002078 expected_times.push_back(loop1->context().monotonic_event_time);
Austin Schuh39788ff2019-12-01 18:22:57 -08002079
Austin Schuhad154822019-12-27 15:45:13 -08002080 EXPECT_EQ(loop1->context().monotonic_remote_time,
2081 monotonic_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002082 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08002083 EXPECT_EQ(loop1->context().realtime_event_time,
2084 realtime_clock::min_time);
2085 EXPECT_EQ(loop1->context().realtime_remote_time,
Austin Schuh39788ff2019-12-01 18:22:57 -08002086 realtime_clock::min_time);
2087 EXPECT_EQ(loop1->context().queue_index, 0xffffffffu);
2088 EXPECT_EQ(loop1->context().size, 0u);
2089 EXPECT_EQ(loop1->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07002090 EXPECT_EQ(loop1->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08002091
2092 if (times.size() == kCount) {
2093 LOG(INFO) << "Exiting";
2094 this->Exit();
2095 }
2096 },
2097 chrono::seconds(1), kOffset)
2098 ->set_name("Test loop");
Austin Schuh52d325c2019-06-23 18:59:06 -07002099
2100 // Add a delay to make sure that delay during startup doesn't result in a
2101 // "missed cycle".
2102 SleepFor(chrono::seconds(2));
2103
2104 Run();
2105
2106 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07002107 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
2108 ASSERT_EQ(times.size(), expected_times.size());
2109 ASSERT_EQ((times.size() % 2), 1);
Austin Schuh52d325c2019-06-23 18:59:06 -07002110
2111 // Grab the middle sample.
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002112 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
Austin Schuh52d325c2019-06-23 18:59:06 -07002113
2114 // Add up all the delays of all the times.
2115 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
2116 for (const ::aos::monotonic_clock::time_point time : times) {
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002117 sum += time - average_time;
Austin Schuh52d325c2019-06-23 18:59:06 -07002118 }
2119
2120 // Average and add to the middle to find the average time.
2121 sum /= times.size();
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002122 average_time += sum;
Austin Schuh52d325c2019-06-23 18:59:06 -07002123
2124 // Compute the offset from the start of the second of the average time. This
2125 // should be pretty close to the offset.
2126 const ::aos::monotonic_clock::duration remainder =
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002127 average_time.time_since_epoch() -
2128 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
Austin Schuh52d325c2019-06-23 18:59:06 -07002129
2130 const chrono::milliseconds kEpsilon(100);
2131 EXPECT_LT(remainder, kOffset + kEpsilon);
2132 EXPECT_GT(remainder, kOffset - kEpsilon);
2133
2134 // Make sure that the average duration is close to 1 second.
2135 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
2136 times.front())
2137 .count() /
2138 static_cast<double>(times.size() - 1),
2139 1.0, 0.1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002140
2141 // Confirm that the ideal wakeup times increment correctly.
2142 for (size_t i = 1; i < expected_times.size(); ++i) {
2143 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
2144 }
2145
2146 for (size_t i = 0; i < expected_times.size(); ++i) {
2147 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
2148 kOffset);
2149 }
2150
2151 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
2152 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08002153
Austin Schuh6bae8252021-02-07 22:01:49 -08002154 if (do_timing_reports() == DoTimingReports::kYes) {
2155 // And, since we are here, check that the timing report makes sense.
2156 // Start by looking for our event loop's timing.
2157 FlatbufferDetachedBuffer<timing::Report> report =
2158 FlatbufferDetachedBuffer<timing::Report>::Empty();
2159 while (report_fetcher.FetchNext()) {
2160 if (report_fetcher->name()->string_view() == "primary") {
2161 report = CopyFlatBuffer(report_fetcher.get());
2162 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002163 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002164
2165 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
2166
2167 EXPECT_EQ(report.message().name()->string_view(), "primary");
2168
2169 ASSERT_NE(report.message().senders(), nullptr);
2170 EXPECT_EQ(report.message().senders()->size(), 2);
2171
2172 ASSERT_NE(report.message().timers(), nullptr);
2173 EXPECT_EQ(report.message().timers()->size(), 1);
2174
2175 // Make sure there is a single phased loop report with our report in it.
2176 ASSERT_NE(report.message().phased_loops(), nullptr);
2177 ASSERT_EQ(report.message().phased_loops()->size(), 1);
2178 EXPECT_EQ(report.message().phased_loops()->Get(0)->name()->string_view(),
2179 "Test loop");
2180 EXPECT_GE(report.message().phased_loops()->Get(0)->count(), 1);
2181 } else {
2182 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002183 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002184}
2185
Milind Upadhyay42589bb2021-05-19 20:05:16 -07002186// Tests that a phased loop responds correctly to a changing offset.
2187TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetTest) {
2188 // Force a slower rate so we are guaranteed to have reports for our phased
2189 // loop.
2190 FLAGS_timing_report_ms = 2000;
2191
2192 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2193 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2194 const int kCount = 5;
2195
2196 auto loop1 = MakePrimary();
2197
2198 // Collect up a couple of samples.
2199 ::std::vector<::aos::monotonic_clock::time_point> times;
2200 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
2201
2202 PhasedLoopHandler *phased_loop;
2203
2204 // Run kCount iterations.
2205 phased_loop = loop1->AddPhasedLoop(
2206 [&phased_loop, &times, &expected_times, &loop1, this, kOffset,
2207 kInterval](int count) {
2208 EXPECT_EQ(count, 1);
2209 times.push_back(loop1->monotonic_now());
2210
2211 expected_times.push_back(loop1->context().monotonic_event_time);
2212
2213 phased_loop->set_interval_and_offset(
2214 kInterval, kOffset - chrono::milliseconds(times.size()));
2215 LOG(INFO) << "new offset: "
2216 << (kOffset - chrono::milliseconds(times.size())).count();
2217
2218 if (times.size() == kCount) {
2219 LOG(INFO) << "Exiting";
2220 this->Exit();
2221 }
2222 },
2223 kInterval, kOffset);
2224 phased_loop->set_name("Test loop");
2225
2226 // Add a delay to make sure that delay during startup doesn't result in a
2227 // "missed cycle".
2228 SleepFor(chrono::seconds(2));
2229
2230 Run();
2231 // Confirm that we got both the right number of samples, and it's odd.
2232 EXPECT_EQ(times.size(), static_cast<size_t>(kCount));
2233 EXPECT_EQ(times.size(), expected_times.size());
2234 EXPECT_EQ((times.size() % 2), 1);
2235
2236 // Grab the middle sample.
2237 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
2238
2239 // Add up all the delays of all the times.
2240 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
2241 for (const ::aos::monotonic_clock::time_point time : times) {
2242 sum += time - average_time;
2243 }
2244
2245 // Average and add to the middle to find the average time.
2246 sum /= times.size();
2247 average_time += sum;
2248
2249 // Compute the offset from the start of the second of the average time. This
2250 // should be pretty close to the offset.
2251 const ::aos::monotonic_clock::duration remainder =
2252 average_time.time_since_epoch() -
2253 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
2254
2255 const chrono::milliseconds kEpsilon(100);
2256 EXPECT_LT(remainder, kOffset + kEpsilon);
2257 EXPECT_GT(remainder, kOffset - kEpsilon);
2258
2259 // Make sure that the average duration is close to 1 second.
2260 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
2261 times.front())
2262 .count() /
2263 static_cast<double>(times.size() - 1),
2264 1.0, 0.1);
2265
2266 // Confirm that the ideal wakeup times increment correctly.
2267 for (size_t i = 1; i < expected_times.size(); ++i) {
2268 LOG(INFO) << i - 1 << ": " << expected_times[i - 1] << ", " << i << ": "
2269 << expected_times[i];
2270 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1) -
2271 chrono::milliseconds(1));
2272 }
2273
2274 for (size_t i = 0; i < expected_times.size(); ++i) {
2275 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
2276 kOffset - chrono::milliseconds(i));
2277 }
2278
2279 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
2280 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
2281}
2282
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002283// Tests that a phased loop responds correctly to a changing offset; sweep
2284// across a variety of potential offset changes, to ensure that we are
2285// exercising a variety of potential cases.
2286TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetSweep) {
2287 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2288 const int kCount = 5;
2289
2290 auto loop1 = MakePrimary();
2291
2292 std::vector<aos::monotonic_clock::duration> offset_options;
2293 for (int ii = 0; ii < kCount; ++ii) {
2294 offset_options.push_back(ii * kInterval / kCount);
2295 }
2296 std::vector<aos::monotonic_clock::duration> offset_sweep;
2297 // Run over all the pair-wise combinations of offsets.
2298 for (int ii = 0; ii < kCount; ++ii) {
2299 for (int jj = 0; jj < kCount; ++jj) {
2300 offset_sweep.push_back(offset_options.at(ii));
2301 offset_sweep.push_back(offset_options.at(jj));
2302 }
2303 }
2304
2305 std::vector<::aos::monotonic_clock::time_point> expected_times;
2306
2307 PhasedLoopHandler *phased_loop;
2308
2309 // Run kCount iterations.
2310 size_t counter = 0;
2311 phased_loop = loop1->AddPhasedLoop(
2312 [&phased_loop, &expected_times, &loop1, this, kInterval, &counter,
2313 offset_sweep](int count) {
2314 EXPECT_EQ(count, 1);
2315 expected_times.push_back(loop1->context().monotonic_event_time);
2316
2317 counter++;
2318
2319 if (counter == offset_sweep.size()) {
2320 LOG(INFO) << "Exiting";
2321 this->Exit();
2322 return;
2323 }
2324
2325 phased_loop->set_interval_and_offset(kInterval,
2326 offset_sweep.at(counter));
2327 },
2328 kInterval, offset_sweep.at(0));
2329
2330 Run();
2331 ASSERT_EQ(expected_times.size(), offset_sweep.size());
2332 for (size_t ii = 1; ii < expected_times.size(); ++ii) {
2333 EXPECT_LE(expected_times.at(ii) - expected_times.at(ii - 1), kInterval);
2334 }
2335}
2336
2337// Tests that a phased loop responds correctly to being rescheduled with now
2338// equal to a time in the past.
2339TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleInPast) {
2340 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2341 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2342
2343 auto loop1 = MakePrimary();
2344
2345 std::vector<::aos::monotonic_clock::time_point> expected_times;
2346
2347 PhasedLoopHandler *phased_loop;
2348
2349 int expected_count = 1;
2350
2351 // Set up a timer that will get run immediately after the phased loop and
2352 // which will attempt to reschedule the phased loop to just before now. This
2353 // should succeed, but will result in 0 cycles elapsing.
2354 TimerHandler *manager_timer =
2355 loop1->AddTimer([&phased_loop, &loop1, &expected_count, this]() {
2356 if (expected_count == 0) {
2357 LOG(INFO) << "Exiting";
2358 this->Exit();
2359 return;
2360 }
2361 phased_loop->Reschedule(loop1->context().monotonic_event_time -
2362 std::chrono::nanoseconds(1));
2363 expected_count = 0;
2364 });
2365
2366 phased_loop = loop1->AddPhasedLoop(
2367 [&expected_count, &expected_times, &loop1, manager_timer](int count) {
2368 EXPECT_EQ(count, expected_count);
2369 expected_times.push_back(loop1->context().monotonic_event_time);
2370
Philipp Schradera6712522023-07-05 20:25:11 -07002371 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002372 },
2373 kInterval, kOffset);
2374 phased_loop->set_name("Test loop");
2375 manager_timer->set_name("Manager timer");
2376
2377 Run();
2378
2379 ASSERT_EQ(2u, expected_times.size());
2380 ASSERT_EQ(expected_times[0], expected_times[1]);
2381}
2382
2383// Tests that a phased loop responds correctly to being rescheduled at the time
2384// when it should be triggering (it should kick the trigger to the next cycle).
2385TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleNow) {
2386 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2387 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2388
2389 auto loop1 = MakePrimary();
2390
2391 std::vector<::aos::monotonic_clock::time_point> expected_times;
2392
2393 PhasedLoopHandler *phased_loop;
2394
2395 bool should_exit = false;
2396 // Set up a timer that will get run immediately after the phased loop and
2397 // which will attempt to reschedule the phased loop to now. This should
2398 // succeed, but will result in no change to the expected behavior (since this
2399 // is the same thing that is actually done internally).
2400 TimerHandler *manager_timer =
2401 loop1->AddTimer([&phased_loop, &loop1, &should_exit, this]() {
2402 if (should_exit) {
2403 LOG(INFO) << "Exiting";
2404 this->Exit();
2405 return;
2406 }
2407 phased_loop->Reschedule(loop1->context().monotonic_event_time);
2408 should_exit = true;
2409 });
2410
2411 phased_loop = loop1->AddPhasedLoop(
2412 [&expected_times, &loop1, manager_timer](int count) {
2413 EXPECT_EQ(count, 1);
2414 expected_times.push_back(loop1->context().monotonic_event_time);
2415
Philipp Schradera6712522023-07-05 20:25:11 -07002416 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002417 },
2418 kInterval, kOffset);
2419 phased_loop->set_name("Test loop");
2420 manager_timer->set_name("Manager timer");
2421
2422 Run();
2423
2424 ASSERT_EQ(2u, expected_times.size());
2425 ASSERT_EQ(expected_times[0] + kInterval, expected_times[1]);
2426}
2427
2428// Tests that a phased loop responds correctly to being rescheduled at a time in
2429// the distant future.
2430TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleFuture) {
2431 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2432 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2433
2434 auto loop1 = MakePrimary();
2435
2436 std::vector<::aos::monotonic_clock::time_point> expected_times;
2437
2438 PhasedLoopHandler *phased_loop;
2439
2440 bool should_exit = false;
2441 int expected_count = 1;
2442 TimerHandler *manager_timer = loop1->AddTimer(
2443 [&expected_count, &phased_loop, &loop1, &should_exit, this, kInterval]() {
2444 if (should_exit) {
2445 LOG(INFO) << "Exiting";
2446 this->Exit();
2447 return;
2448 }
2449 expected_count = 10;
2450 // Knock off 1 ns, since the scheduler rounds up when it is
2451 // scheduled to exactly a loop time.
2452 phased_loop->Reschedule(loop1->context().monotonic_event_time +
2453 kInterval * expected_count -
2454 std::chrono::nanoseconds(1));
2455 should_exit = true;
2456 });
2457
2458 phased_loop = loop1->AddPhasedLoop(
2459 [&expected_times, &loop1, manager_timer, &expected_count](int count) {
2460 EXPECT_EQ(count, expected_count);
2461 expected_times.push_back(loop1->context().monotonic_event_time);
2462
Philipp Schradera6712522023-07-05 20:25:11 -07002463 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002464 },
2465 kInterval, kOffset);
2466 phased_loop->set_name("Test loop");
2467 manager_timer->set_name("Manager timer");
2468
2469 Run();
2470
2471 ASSERT_EQ(2u, expected_times.size());
2472 ASSERT_EQ(expected_times[0] + expected_count * kInterval, expected_times[1]);
2473}
2474
2475// Tests that a phased loop responds correctly to having its phase offset
2476// incremented and then being scheduled after a set time, exercising a pattern
2477// where a phased loop's offset is changed while trying to maintain the trigger
2478// at a consistent period.
2479TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleWithLaterOffset) {
2480 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2481 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2482
2483 auto loop1 = MakePrimary();
2484
2485 std::vector<::aos::monotonic_clock::time_point> expected_times;
2486
2487 PhasedLoopHandler *phased_loop;
2488
2489 bool should_exit = false;
2490 TimerHandler *manager_timer = loop1->AddTimer(
2491 [&phased_loop, &loop1, &should_exit, this, kInterval, kOffset]() {
2492 if (should_exit) {
2493 LOG(INFO) << "Exiting";
2494 this->Exit();
2495 return;
2496 }
2497 // Schedule the next callback to be strictly later than the current time
2498 // + interval / 2, to ensure a consistent frequency.
2499 monotonic_clock::time_point half_time =
2500 loop1->context().monotonic_event_time + kInterval / 2;
2501 phased_loop->set_interval_and_offset(
2502 kInterval, kOffset + std::chrono::nanoseconds(1), half_time);
2503 phased_loop->Reschedule(half_time);
2504 should_exit = true;
2505 });
2506
2507 phased_loop = loop1->AddPhasedLoop(
2508 [&expected_times, &loop1, manager_timer](int count) {
2509 EXPECT_EQ(1, count);
2510 expected_times.push_back(loop1->context().monotonic_event_time);
2511
Philipp Schradera6712522023-07-05 20:25:11 -07002512 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002513 },
2514 kInterval, kOffset);
2515 phased_loop->set_name("Test loop");
2516 manager_timer->set_name("Manager timer");
2517
2518 Run();
2519
2520 ASSERT_EQ(2u, expected_times.size());
2521 ASSERT_EQ(expected_times[0] + kInterval + std::chrono::nanoseconds(1),
2522 expected_times[1]);
2523}
2524
2525// Tests that a phased loop responds correctly to having its phase offset
2526// decremented and then being scheduled after a set time, exercising a pattern
2527// where a phased loop's offset is changed while trying to maintain the trigger
2528// at a consistent period.
2529TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleWithEarlierOffset) {
2530 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2531 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2532
2533 auto loop1 = MakePrimary();
2534
2535 std::vector<::aos::monotonic_clock::time_point> expected_times;
2536
2537 PhasedLoopHandler *phased_loop;
2538
2539 bool should_exit = false;
2540 TimerHandler *manager_timer = loop1->AddTimer(
2541 [&phased_loop, &loop1, &should_exit, this, kInterval, kOffset]() {
2542 if (should_exit) {
2543 LOG(INFO) << "Exiting";
2544 this->Exit();
2545 return;
2546 }
2547 // Schedule the next callback to be strictly later than the current time
2548 // + interval / 2, to ensure a consistent frequency.
2549 const aos::monotonic_clock::time_point half_time =
2550 loop1->context().monotonic_event_time + kInterval / 2;
2551 phased_loop->set_interval_and_offset(
2552 kInterval, kOffset - std::chrono::nanoseconds(1), half_time);
2553 phased_loop->Reschedule(half_time);
2554 should_exit = true;
2555 });
2556
2557 phased_loop = loop1->AddPhasedLoop(
2558 [&expected_times, &loop1, manager_timer](int count) {
2559 EXPECT_EQ(1, count);
2560 expected_times.push_back(loop1->context().monotonic_event_time);
2561
Philipp Schradera6712522023-07-05 20:25:11 -07002562 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002563 },
2564 kInterval, kOffset);
2565 phased_loop->set_name("Test loop");
2566 manager_timer->set_name("Manager timer");
2567
2568 Run();
2569
2570 ASSERT_EQ(2u, expected_times.size());
2571 ASSERT_EQ(expected_times[0] + kInterval - std::chrono::nanoseconds(1),
2572 expected_times[1]);
2573}
2574
Austin Schuh39788ff2019-12-01 18:22:57 -08002575// Tests that senders count correctly in the timing report.
2576TEST_P(AbstractEventLoopTest, SenderTimingReport) {
2577 FLAGS_timing_report_ms = 1000;
2578 auto loop1 = MakePrimary();
2579
2580 auto loop2 = Make("watcher_loop");
2581 loop2->MakeWatcher("/test", [](const TestMessage &) {});
2582
2583 auto loop3 = Make();
2584
2585 Fetcher<timing::Report> report_fetcher =
2586 loop3->MakeFetcher<timing::Report>("/aos");
2587 EXPECT_FALSE(report_fetcher.Fetch());
2588
2589 auto sender = loop1->MakeSender<TestMessage>("/test");
2590
James Kuszmaul78514332022-04-06 15:08:34 -07002591 // Sanity check channel frequencies to ensure that we've designed the test
2592 // correctly.
2593 ASSERT_EQ(800, sender.channel()->frequency());
Austin Schuhfff9c3a2023-06-16 18:48:23 -07002594 ASSERT_EQ(2000000000, configuration::ChannelStorageDuration(
2595 loop1->configuration(), sender.channel())
2596 .count());
James Kuszmaul78514332022-04-06 15:08:34 -07002597 constexpr int kMaxAllowedMessages = 800 * 2;
2598 constexpr int kSendMessages = kMaxAllowedMessages * 2;
2599 constexpr int kDroppedMessages = kSendMessages - kMaxAllowedMessages;
2600
Austin Schuh39788ff2019-12-01 18:22:57 -08002601 // Add a timer to actually quit.
2602 auto test_timer = loop1->AddTimer([&sender]() {
James Kuszmaul78514332022-04-06 15:08:34 -07002603 for (int i = 0; i < kSendMessages; ++i) {
Austin Schuh39788ff2019-12-01 18:22:57 -08002604 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2605 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2606 builder.add_value(200 + i);
James Kuszmaul78514332022-04-06 15:08:34 -07002607 if (i < kMaxAllowedMessages) {
2608 msg.CheckOk(msg.Send(builder.Finish()));
2609 } else {
2610 EXPECT_EQ(RawSender::Error::kMessagesSentTooFast,
2611 msg.Send(builder.Finish()));
2612 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002613 }
2614 });
2615
2616 // Quit after 1 timing report, mid way through the next cycle.
2617 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2618
2619 loop1->OnRun([&test_timer, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002620 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1500));
Austin Schuh39788ff2019-12-01 18:22:57 -08002621 });
2622
2623 Run();
2624
Austin Schuh6bae8252021-02-07 22:01:49 -08002625 if (do_timing_reports() == DoTimingReports::kYes) {
2626 // And, since we are here, check that the timing report makes sense.
2627 // Start by looking for our event loop's timing.
2628 FlatbufferDetachedBuffer<timing::Report> primary_report =
2629 FlatbufferDetachedBuffer<timing::Report>::Empty();
2630 while (report_fetcher.FetchNext()) {
Austin Schuh8902fa52021-03-14 22:39:24 -07002631 VLOG(1) << "Report " << FlatbufferToJson(report_fetcher.get());
Austin Schuh6bae8252021-02-07 22:01:49 -08002632 if (report_fetcher->name()->string_view() == "primary") {
2633 primary_report = CopyFlatBuffer(report_fetcher.get());
2634 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002635 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002636
Austin Schuh8902fa52021-03-14 22:39:24 -07002637 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
Austin Schuh6bae8252021-02-07 22:01:49 -08002638
2639 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2640
2641 ASSERT_NE(primary_report.message().senders(), nullptr);
2642 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2643
2644 // Confirm that the sender looks sane.
2645 EXPECT_EQ(
2646 loop1->configuration()
2647 ->channels()
2648 ->Get(primary_report.message().senders()->Get(0)->channel_index())
2649 ->name()
2650 ->string_view(),
2651 "/test");
James Kuszmaul78514332022-04-06 15:08:34 -07002652 EXPECT_EQ(primary_report.message().senders()->Get(0)->count(),
2653 kMaxAllowedMessages);
2654 ASSERT_TRUE(primary_report.message().senders()->Get(0)->has_error_counts());
2655 ASSERT_EQ(
2656 primary_report.message().senders()->Get(0)->error_counts()->size(), 2u);
2657 EXPECT_EQ(
2658 primary_report.message()
2659 .senders()
2660 ->Get(0)
2661 ->error_counts()
2662 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2663 ->count(),
2664 kDroppedMessages)
2665 << aos::FlatbufferToJson(primary_report);
2666 EXPECT_EQ(primary_report.message()
2667 .senders()
2668 ->Get(0)
2669 ->error_counts()
2670 ->Get(static_cast<size_t>(timing::SendError::INVALID_REDZONE))
2671 ->count(),
2672 0);
Austin Schuh6bae8252021-02-07 22:01:49 -08002673
2674 // Confirm that the timing primary_report sender looks sane.
2675 EXPECT_EQ(
2676 loop1->configuration()
2677 ->channels()
2678 ->Get(primary_report.message().senders()->Get(1)->channel_index())
2679 ->name()
2680 ->string_view(),
2681 "/aos");
2682 EXPECT_EQ(primary_report.message().senders()->Get(1)->count(), 1);
2683
2684 ASSERT_NE(primary_report.message().timers(), nullptr);
2685 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2686
2687 // Make sure there are no phased loops or watchers.
2688 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2689 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2690 } else {
2691 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002692 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002693}
2694
James Kuszmaul93abac12022-04-14 15:05:10 -07002695// Tests that the RawSender::Send(void*, size_t) overload tracks things properly
2696// in its timing report.
2697TEST_P(AbstractEventLoopTest, CopySenderTimingReport) {
2698 gflags::FlagSaver flag_saver;
2699 FLAGS_timing_report_ms = 1000;
2700 auto loop1 = Make();
2701 auto loop2 = MakePrimary();
2702
2703 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2704 JsonToFlatbuffer<TestMessage>("{}");
2705
2706 std::unique_ptr<aos::RawSender> sender =
2707 loop2->MakeRawSender(configuration::GetChannel(
2708 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
2709
2710 Fetcher<timing::Report> report_fetcher =
2711 loop1->MakeFetcher<timing::Report>("/aos");
2712 EXPECT_FALSE(report_fetcher.Fetch());
2713
2714 loop2->OnRun([&]() {
2715 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
2716 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2717 RawSender::Error::kOk);
2718 }
2719 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2720 RawSender::Error::kMessagesSentTooFast);
2721 });
2722 // Quit after 1 timing report, mid way through the next cycle.
2723 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
2724
2725 Run();
2726
2727 if (do_timing_reports() == DoTimingReports::kYes) {
2728 // Check that the sent too fast actually got recorded by the timing report.
2729 FlatbufferDetachedBuffer<timing::Report> primary_report =
2730 FlatbufferDetachedBuffer<timing::Report>::Empty();
2731 while (report_fetcher.FetchNext()) {
2732 if (report_fetcher->name()->string_view() == "primary") {
2733 primary_report = CopyFlatBuffer(report_fetcher.get());
2734 }
2735 }
2736
2737 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2738
2739 ASSERT_NE(primary_report.message().senders(), nullptr);
2740 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2741 EXPECT_EQ(
2742 primary_report.message()
2743 .senders()
2744 ->Get(0)
2745 ->error_counts()
2746 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2747 ->count(),
2748 1);
2749 }
2750}
2751
Austin Schuhe0ab4de2023-05-03 08:05:08 -07002752// Tests that the RawSender::Send(SharedSpan) overload works.
2753TEST_P(AbstractEventLoopTest, SharedSenderTimingReport) {
2754 gflags::FlagSaver flag_saver;
2755 FLAGS_timing_report_ms = 1000;
2756 auto loop1 = Make();
2757 auto loop2 = MakePrimary();
2758
2759 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2760 JsonToFlatbuffer<TestMessage>("{}");
2761
2762 std::unique_ptr<aos::RawSender> sender =
2763 loop2->MakeRawSender(configuration::GetChannel(
2764 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
2765
2766 Fetcher<timing::Report> report_fetcher =
2767 loop1->MakeFetcher<timing::Report>("/aos");
2768 EXPECT_FALSE(report_fetcher.Fetch());
2769
2770 loop2->OnRun([&]() {
2771 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
2772 auto shared_span = MakeSharedSpan(kMessage.span().size());
2773 memcpy(shared_span.second.data(), kMessage.span().data(),
2774 kMessage.span().size());
2775 EXPECT_EQ(sender->Send(std::move(shared_span.first)),
2776 RawSender::Error::kOk);
2777 }
2778 auto shared_span = MakeSharedSpan(kMessage.span().size());
2779 memcpy(shared_span.second.data(), kMessage.span().data(),
2780 kMessage.span().size());
2781 EXPECT_EQ(sender->Send(std::move(shared_span.first)),
2782 RawSender::Error::kMessagesSentTooFast);
2783 });
2784 // Quit after 1 timing report, mid way through the next cycle.
2785 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
2786
2787 Run();
2788
2789 if (do_timing_reports() == DoTimingReports::kYes) {
2790 // Check that the sent too fast actually got recorded by the timing report.
2791 FlatbufferDetachedBuffer<timing::Report> primary_report =
2792 FlatbufferDetachedBuffer<timing::Report>::Empty();
2793 while (report_fetcher.FetchNext()) {
2794 if (report_fetcher->name()->string_view() == "primary") {
2795 primary_report = CopyFlatBuffer(report_fetcher.get());
2796 }
2797 }
2798
2799 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2800
2801 ASSERT_NE(primary_report.message().senders(), nullptr);
2802 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2803 EXPECT_EQ(
2804 primary_report.message()
2805 .senders()
2806 ->Get(0)
2807 ->error_counts()
2808 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2809 ->count(),
2810 1);
2811 }
2812}
2813
Austin Schuh39788ff2019-12-01 18:22:57 -08002814// Tests that senders count correctly in the timing report.
2815TEST_P(AbstractEventLoopTest, WatcherTimingReport) {
2816 FLAGS_timing_report_ms = 1000;
2817 auto loop1 = MakePrimary();
2818 loop1->MakeWatcher("/test", [](const TestMessage &) {});
2819
2820 auto loop2 = Make("sender_loop");
2821
2822 auto loop3 = Make();
2823
2824 Fetcher<timing::Report> report_fetcher =
2825 loop3->MakeFetcher<timing::Report>("/aos");
2826 EXPECT_FALSE(report_fetcher.Fetch());
2827
2828 auto sender = loop2->MakeSender<TestMessage>("/test");
2829
2830 // Add a timer to actually quit.
2831 auto test_timer = loop1->AddTimer([&sender]() {
2832 for (int i = 0; i < 10; ++i) {
2833 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2834 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2835 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002836 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002837 }
2838 });
2839
2840 // Quit after 1 timing report, mid way through the next cycle.
2841 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2842
2843 loop1->OnRun([&test_timer, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002844 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1500));
Austin Schuh39788ff2019-12-01 18:22:57 -08002845 });
2846
2847 Run();
2848
Austin Schuh6bae8252021-02-07 22:01:49 -08002849 if (do_timing_reports() == DoTimingReports::kYes) {
2850 // And, since we are here, check that the timing report makes sense.
2851 // Start by looking for our event loop's timing.
2852 FlatbufferDetachedBuffer<timing::Report> primary_report =
2853 FlatbufferDetachedBuffer<timing::Report>::Empty();
2854 while (report_fetcher.FetchNext()) {
2855 LOG(INFO) << "Report " << FlatbufferToJson(report_fetcher.get());
2856 if (report_fetcher->name()->string_view() == "primary") {
2857 primary_report = CopyFlatBuffer(report_fetcher.get());
2858 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002859 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002860
2861 // Check the watcher report.
2862 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2863
2864 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2865
2866 // Just the timing report timer.
2867 ASSERT_NE(primary_report.message().timers(), nullptr);
2868 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2869
2870 // No phased loops
2871 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2872
2873 ASSERT_NE(primary_report.message().watchers(), nullptr);
2874 ASSERT_EQ(primary_report.message().watchers()->size(), 1);
2875 EXPECT_EQ(primary_report.message().watchers()->Get(0)->count(), 10);
2876 } else {
2877 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002878 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002879}
2880
2881// Tests that fetchers count correctly in the timing report.
2882TEST_P(AbstractEventLoopTest, FetcherTimingReport) {
2883 FLAGS_timing_report_ms = 1000;
2884 auto loop1 = MakePrimary();
2885 auto loop2 = Make("sender_loop");
2886
2887 auto loop3 = Make();
2888
2889 Fetcher<timing::Report> report_fetcher =
2890 loop3->MakeFetcher<timing::Report>("/aos");
2891 EXPECT_FALSE(report_fetcher.Fetch());
2892
2893 auto sender = loop2->MakeSender<TestMessage>("/test");
2894 auto fetcher1 = loop1->MakeFetcher<TestMessage>("/test");
2895 auto fetcher2 = loop1->MakeFetcher<TestMessage>("/test");
2896 fetcher1.Fetch();
2897 fetcher2.Fetch();
2898
2899 // Add a timer to actually quit.
2900 auto test_timer = loop1->AddTimer([&sender]() {
2901 for (int i = 0; i < 10; ++i) {
2902 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2903 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2904 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002905 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002906 }
2907 });
2908
2909 auto test_timer2 = loop1->AddTimer([&fetcher1, &fetcher2]() {
2910 fetcher1.Fetch();
2911 while (fetcher2.FetchNext()) {
2912 }
2913 });
2914
2915 // Quit after 1 timing report, mid way through the next cycle.
2916 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2917
2918 loop1->OnRun([test_timer, test_timer2, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002919 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1400));
2920 test_timer2->Schedule(loop1->monotonic_now() + chrono::milliseconds(1600));
Austin Schuh39788ff2019-12-01 18:22:57 -08002921 });
2922
2923 Run();
2924
Austin Schuh6bae8252021-02-07 22:01:49 -08002925 if (do_timing_reports() == DoTimingReports::kYes) {
2926 // And, since we are here, check that the timing report makes sense.
2927 // Start by looking for our event loop's timing.
2928 FlatbufferDetachedBuffer<timing::Report> primary_report =
2929 FlatbufferDetachedBuffer<timing::Report>::Empty();
2930 while (report_fetcher.FetchNext()) {
2931 if (report_fetcher->name()->string_view() == "primary") {
2932 primary_report = CopyFlatBuffer(report_fetcher.get());
2933 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002934 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002935
2936 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2937
2938 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2939
2940 ASSERT_NE(primary_report.message().senders(), nullptr);
2941 EXPECT_EQ(primary_report.message().senders()->size(), 2);
2942
2943 ASSERT_NE(primary_report.message().timers(), nullptr);
2944 EXPECT_EQ(primary_report.message().timers()->size(), 4);
2945
2946 // Make sure there are no phased loops or watchers.
2947 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2948 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2949
2950 // Now look at the fetchrs.
2951 ASSERT_NE(primary_report.message().fetchers(), nullptr);
2952 ASSERT_EQ(primary_report.message().fetchers()->size(), 2);
2953
2954 EXPECT_EQ(primary_report.message().fetchers()->Get(0)->count(), 1);
2955 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->average(),
2956 0.1);
2957 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->min(),
2958 0.1);
2959 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->max(),
2960 0.1);
2961 EXPECT_EQ(primary_report.message()
2962 .fetchers()
2963 ->Get(0)
2964 ->latency()
2965 ->standard_deviation(),
2966 0.0);
2967
2968 EXPECT_EQ(primary_report.message().fetchers()->Get(1)->count(), 10);
2969 } else {
2970 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002971 }
Austin Schuh52d325c2019-06-23 18:59:06 -07002972}
2973
Austin Schuh67420a42019-12-21 21:55:04 -08002974// Tests that a raw watcher and raw fetcher can receive messages from a raw
2975// sender without messing up offsets.
2976TEST_P(AbstractEventLoopTest, RawBasic) {
2977 auto loop1 = Make();
2978 auto loop2 = MakePrimary();
2979 auto loop3 = Make();
2980
Austin Schuha9df9ad2021-06-16 14:49:39 -07002981 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2982 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuh67420a42019-12-21 21:55:04 -08002983
2984 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002985 loop1->MakeRawSender(configuration::GetChannel(
2986 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08002987
2988 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002989 loop3->MakeRawFetcher(configuration::GetChannel(
2990 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08002991
Austin Schuha9df9ad2021-06-16 14:49:39 -07002992 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002993 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2994 RawSender::Error::kOk);
Austin Schuha9df9ad2021-06-16 14:49:39 -07002995 });
Austin Schuh67420a42019-12-21 21:55:04 -08002996
2997 bool happened = false;
2998 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08002999 configuration::GetChannel(loop2->configuration(), "/test",
3000 "aos.TestMessage", "", nullptr),
Austin Schuha9df9ad2021-06-16 14:49:39 -07003001 [this, &kMessage, &fetcher, &happened](const Context &context,
3002 const void *message) {
Austin Schuh67420a42019-12-21 21:55:04 -08003003 happened = true;
Austin Schuha9df9ad2021-06-16 14:49:39 -07003004 EXPECT_EQ(
3005 kMessage.span(),
3006 absl::Span<const uint8_t>(
3007 reinterpret_cast<const uint8_t *>(message), context.size));
3008 EXPECT_EQ(message, context.data);
Austin Schuh67420a42019-12-21 21:55:04 -08003009
3010 ASSERT_TRUE(fetcher->Fetch());
3011
Austin Schuha9df9ad2021-06-16 14:49:39 -07003012 EXPECT_EQ(kMessage.span(),
3013 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
3014 fetcher->context().data),
3015 fetcher->context().size));
Austin Schuh67420a42019-12-21 21:55:04 -08003016
3017 this->Exit();
3018 });
3019
3020 EXPECT_FALSE(happened);
3021 Run();
3022 EXPECT_TRUE(happened);
3023}
3024
Austin Schuhad154822019-12-27 15:45:13 -08003025// Tests that a raw watcher and raw fetcher can receive messages from a raw
Brian Silvermanbf889922021-11-10 12:41:57 -08003026// sender without messing up offsets, using the RawSpan overload.
3027TEST_P(AbstractEventLoopTest, RawBasicSharedSpan) {
3028 auto loop1 = Make();
3029 auto loop2 = MakePrimary();
3030 auto loop3 = Make();
3031
3032 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3033 JsonToFlatbuffer<TestMessage>("{}");
3034
3035 std::unique_ptr<aos::RawSender> sender =
3036 loop1->MakeRawSender(configuration::GetChannel(
3037 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
3038
3039 std::unique_ptr<aos::RawFetcher> fetcher =
3040 loop3->MakeRawFetcher(configuration::GetChannel(
3041 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
3042
3043 loop2->OnRun([&]() {
Austin Schuhe0ab4de2023-05-03 08:05:08 -07003044 auto shared_span = MakeSharedSpan(kMessage.span().size());
3045 memcpy(shared_span.second.data(), kMessage.span().data(),
3046 kMessage.span().size());
3047 sender->CheckOk(sender->Send(std::move(shared_span.first)));
Brian Silvermanbf889922021-11-10 12:41:57 -08003048 });
3049
3050 bool happened = false;
3051 loop2->MakeRawWatcher(
3052 configuration::GetChannel(loop2->configuration(), "/test",
3053 "aos.TestMessage", "", nullptr),
3054 [this, &kMessage, &fetcher, &happened](const Context &context,
3055 const void *message) {
3056 happened = true;
3057 EXPECT_EQ(
3058 kMessage.span(),
3059 absl::Span<const uint8_t>(
3060 reinterpret_cast<const uint8_t *>(message), context.size));
3061 EXPECT_EQ(message, context.data);
3062
3063 ASSERT_TRUE(fetcher->Fetch());
3064
3065 EXPECT_EQ(kMessage.span(),
3066 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
3067 fetcher->context().data),
3068 fetcher->context().size));
3069
3070 this->Exit();
3071 });
3072
3073 EXPECT_FALSE(happened);
3074 Run();
3075 EXPECT_TRUE(happened);
3076}
3077
3078// Tests that a raw watcher and raw fetcher can receive messages from a raw
Austin Schuhad154822019-12-27 15:45:13 -08003079// sender with remote times filled out.
3080TEST_P(AbstractEventLoopTest, RawRemoteTimes) {
3081 auto loop1 = Make();
3082 auto loop2 = MakePrimary();
3083 auto loop3 = Make();
3084
Austin Schuha9df9ad2021-06-16 14:49:39 -07003085 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3086 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08003087
3088 const aos::monotonic_clock::time_point monotonic_remote_time =
3089 aos::monotonic_clock::time_point(chrono::seconds(1501));
3090 const aos::realtime_clock::time_point realtime_remote_time =
3091 aos::realtime_clock::time_point(chrono::seconds(3132));
Austin Schuhb5c6f972021-03-14 21:53:07 -07003092 const uint32_t remote_queue_index = 0x254971;
Austin Schuha9012be2021-07-21 15:19:11 -07003093 const UUID source_boot_uuid = UUID::Random();
Austin Schuhad154822019-12-27 15:45:13 -08003094
3095 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003096 loop1->MakeRawSender(configuration::GetChannel(
3097 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08003098
3099 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003100 loop3->MakeRawFetcher(configuration::GetChannel(
3101 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08003102
3103 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07003104 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size(),
3105 monotonic_remote_time, realtime_remote_time,
3106 remote_queue_index, source_boot_uuid),
3107 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08003108 });
3109
3110 bool happened = false;
3111 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08003112 configuration::GetChannel(loop2->configuration(), "/test",
3113 "aos.TestMessage", "", nullptr),
Austin Schuha9012be2021-07-21 15:19:11 -07003114 [this, monotonic_remote_time, realtime_remote_time, source_boot_uuid,
Austin Schuhb5c6f972021-03-14 21:53:07 -07003115 remote_queue_index, &fetcher,
3116 &happened](const Context &context, const void * /*message*/) {
Austin Schuhad154822019-12-27 15:45:13 -08003117 happened = true;
3118 EXPECT_EQ(monotonic_remote_time, context.monotonic_remote_time);
3119 EXPECT_EQ(realtime_remote_time, context.realtime_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07003120 EXPECT_EQ(source_boot_uuid, context.source_boot_uuid);
Austin Schuhb5c6f972021-03-14 21:53:07 -07003121 EXPECT_EQ(remote_queue_index, context.remote_queue_index);
Austin Schuhad154822019-12-27 15:45:13 -08003122
3123 ASSERT_TRUE(fetcher->Fetch());
3124 EXPECT_EQ(monotonic_remote_time,
3125 fetcher->context().monotonic_remote_time);
3126 EXPECT_EQ(realtime_remote_time,
3127 fetcher->context().realtime_remote_time);
3128
3129 this->Exit();
3130 });
3131
3132 EXPECT_FALSE(happened);
3133 Run();
3134 EXPECT_TRUE(happened);
3135}
3136
3137// Tests that a raw sender fills out sent data.
3138TEST_P(AbstractEventLoopTest, RawSenderSentData) {
3139 auto loop1 = MakePrimary();
3140
Austin Schuha9df9ad2021-06-16 14:49:39 -07003141 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3142 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08003143
3144 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003145 loop1->MakeRawSender(configuration::GetChannel(
3146 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08003147
Tyler Chatow67ddb032020-01-12 14:30:04 -08003148 const aos::monotonic_clock::time_point monotonic_now = loop1->monotonic_now();
3149 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08003150
milind1f1dca32021-07-03 13:50:07 -07003151 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
3152 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08003153
3154 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
3155 EXPECT_LE(sender->monotonic_sent_time(),
3156 monotonic_now + chrono::milliseconds(100));
3157 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
3158 EXPECT_LE(sender->realtime_sent_time(),
3159 realtime_now + chrono::milliseconds(100));
3160 EXPECT_EQ(sender->sent_queue_index(), 0u);
3161
milind1f1dca32021-07-03 13:50:07 -07003162 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
3163 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08003164
3165 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
3166 EXPECT_LE(sender->monotonic_sent_time(),
3167 monotonic_now + chrono::milliseconds(100));
3168 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
3169 EXPECT_LE(sender->realtime_sent_time(),
3170 realtime_now + chrono::milliseconds(100));
3171 EXPECT_EQ(sender->sent_queue_index(), 1u);
3172}
3173
Austin Schuh217a9782019-12-21 23:02:50 -08003174// Tests that not setting up nodes results in no node.
3175TEST_P(AbstractEventLoopTest, NoNode) {
3176 auto loop1 = Make();
3177 auto loop2 = MakePrimary();
3178
3179 EXPECT_EQ(loop1->node(), nullptr);
3180 EXPECT_EQ(loop2->node(), nullptr);
3181}
3182
3183// Tests that setting up nodes results in node being set.
3184TEST_P(AbstractEventLoopTest, Node) {
3185 EnableNodes("me");
3186
3187 auto loop1 = Make();
3188 auto loop2 = MakePrimary();
3189
3190 EXPECT_NE(loop1->node(), nullptr);
3191 EXPECT_NE(loop2->node(), nullptr);
3192}
3193
3194// Tests that watchers work with a node setup.
3195TEST_P(AbstractEventLoopTest, NodeWatcher) {
3196 EnableNodes("me");
3197
3198 auto loop1 = Make();
3199 auto loop2 = Make();
3200 loop1->MakeWatcher("/test", [](const TestMessage &) {});
Tyler Chatow67ddb032020-01-12 14:30:04 -08003201 loop2->MakeRawWatcher(
3202 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
3203 nullptr),
3204 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08003205}
3206
Brian Silverman454bc112020-03-05 14:21:25 -08003207// Tests that no-arg watchers work with a node setup.
3208TEST_P(AbstractEventLoopTest, NodeNoArgWatcher) {
3209 EnableNodes("me");
3210
3211 auto loop1 = Make();
3212 auto loop2 = Make();
3213 loop1->MakeWatcher("/test", [](const TestMessage &) {});
3214 loop2->MakeRawNoArgWatcher(
3215 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
3216 nullptr),
3217 [](const Context &) {});
3218}
3219
Austin Schuh217a9782019-12-21 23:02:50 -08003220// Tests that fetcher work with a node setup.
3221TEST_P(AbstractEventLoopTest, NodeFetcher) {
3222 EnableNodes("me");
3223 auto loop1 = Make();
3224
3225 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
Tyler Chatow67ddb032020-01-12 14:30:04 -08003226 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
3227 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08003228}
3229
3230// Tests that sender work with a node setup.
3231TEST_P(AbstractEventLoopTest, NodeSender) {
3232 EnableNodes("me");
3233 auto loop1 = Make();
3234
3235 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
3236}
3237
Austin Schuhcc6070c2020-10-10 20:25:56 -07003238// Tests that a non-realtime event loop timer is marked non-realtime.
3239TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopTimer) {
3240 auto loop1 = MakePrimary();
3241
3242 // Add a timer to actually quit.
3243 auto test_timer = loop1->AddTimer([this]() {
3244 CheckNotRealtime();
3245 this->Exit();
3246 });
3247
3248 loop1->OnRun([&test_timer, &loop1]() {
3249 CheckNotRealtime();
Philipp Schradera6712522023-07-05 20:25:11 -07003250 test_timer->Schedule(loop1->monotonic_now(),
3251 ::std::chrono::milliseconds(100));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003252 });
3253
3254 Run();
3255}
3256
3257// Tests that a realtime event loop timer is marked realtime.
Austin Schuh9b1d6282022-06-10 17:03:21 -07003258TEST_P(AbstractEventLoopTest, RealtimeSend) {
3259 auto loop1 = MakePrimary();
3260
3261 loop1->SetRuntimeRealtimePriority(1);
3262
3263 auto sender = loop1->MakeSender<TestMessage>("/test2");
3264
3265 loop1->OnRun([&]() {
3266 CheckRealtime();
3267
3268 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3269 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
3270 builder.add_value(200);
3271 msg.CheckOk(msg.Send(builder.Finish()));
3272
3273 this->Exit();
3274 });
3275
3276 Run();
3277}
3278
3279// Tests that a realtime event loop timer is marked realtime.
Austin Schuhcc6070c2020-10-10 20:25:56 -07003280TEST_P(AbstractEventLoopTest, RealtimeEventLoopTimer) {
3281 auto loop1 = MakePrimary();
3282
3283 loop1->SetRuntimeRealtimePriority(1);
3284
3285 // Add a timer to actually quit.
3286 auto test_timer = loop1->AddTimer([this]() {
3287 CheckRealtime();
3288 this->Exit();
3289 });
3290
3291 loop1->OnRun([&test_timer, &loop1]() {
3292 CheckRealtime();
Philipp Schradera6712522023-07-05 20:25:11 -07003293 test_timer->Schedule(loop1->monotonic_now(),
3294 ::std::chrono::milliseconds(100));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003295 });
3296
3297 Run();
3298}
3299
3300// Tests that a non-realtime event loop phased loop is marked non-realtime.
3301TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopPhasedLoop) {
3302 auto loop1 = MakePrimary();
3303
3304 // Add a timer to actually quit.
3305 loop1->AddPhasedLoop(
3306 [this](int) {
3307 CheckNotRealtime();
3308 this->Exit();
3309 },
3310 chrono::seconds(1), chrono::seconds(0));
3311
3312 Run();
3313}
3314
3315// Tests that a realtime event loop phased loop is marked realtime.
3316TEST_P(AbstractEventLoopTest, RealtimeEventLoopPhasedLoop) {
3317 auto loop1 = MakePrimary();
3318
3319 loop1->SetRuntimeRealtimePriority(1);
3320
3321 // Add a timer to actually quit.
3322 loop1->AddPhasedLoop(
3323 [this](int) {
3324 CheckRealtime();
3325 this->Exit();
3326 },
3327 chrono::seconds(1), chrono::seconds(0));
3328
3329 Run();
3330}
3331
3332// Tests that a non-realtime event loop watcher is marked non-realtime.
3333TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopWatcher) {
3334 auto loop1 = MakePrimary();
3335 auto loop2 = Make();
3336
3337 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
3338
3339 loop1->OnRun([&]() {
3340 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3341 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07003342 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003343 });
3344
3345 loop1->MakeWatcher("/test", [&](const TestMessage &) {
3346 CheckNotRealtime();
3347 this->Exit();
3348 });
3349
3350 Run();
3351}
3352
3353// Tests that a realtime event loop watcher is marked realtime.
3354TEST_P(AbstractEventLoopTest, RealtimeEventLoopWatcher) {
3355 auto loop1 = MakePrimary();
3356 auto loop2 = Make();
3357
3358 loop1->SetRuntimeRealtimePriority(1);
3359
3360 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
3361
3362 loop1->OnRun([&]() {
3363 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3364 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07003365 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003366 });
3367
3368 loop1->MakeWatcher("/test", [&](const TestMessage &) {
3369 CheckRealtime();
3370 this->Exit();
3371 });
3372
3373 Run();
3374}
3375
Austin Schuha9012be2021-07-21 15:19:11 -07003376// Tests that event loop's context's monotonic time is set to a value on OnRun.
3377TEST_P(AbstractEventLoopTest, SetContextOnRun) {
3378 auto loop = MakePrimary();
3379
Austin Schuh0debde12022-08-17 16:25:17 -07003380 EXPECT_EQ(loop->context().monotonic_event_time, monotonic_clock::min_time);
3381 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3382 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3383 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3384 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3385 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
3386 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
3387 EXPECT_EQ(loop->context().size, 0u);
3388 EXPECT_EQ(loop->context().data, nullptr);
3389 EXPECT_EQ(loop->context().buffer_index, -1);
3390
Austin Schuha9012be2021-07-21 15:19:11 -07003391 // We want to check that monotonic event time is before monotonic now
3392 // called inside of callback, but after time point obtained callback.
3393 aos::monotonic_clock::time_point monotonic_event_time_on_run;
3394
3395 loop->OnRun([&]() {
3396 monotonic_event_time_on_run = loop->context().monotonic_event_time;
3397 EXPECT_LE(monotonic_event_time_on_run, loop->monotonic_now());
3398 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3399 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3400 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3401 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3402 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
Austin Schuh0debde12022-08-17 16:25:17 -07003403 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
Austin Schuha9012be2021-07-21 15:19:11 -07003404 EXPECT_EQ(loop->context().size, 0u);
3405 EXPECT_EQ(loop->context().data, nullptr);
3406 EXPECT_EQ(loop->context().buffer_index, -1);
3407 });
3408
3409 EndEventLoop(loop.get(), ::std::chrono::milliseconds(200));
3410
3411 const aos::monotonic_clock::time_point before_run_time =
3412 loop->monotonic_now();
3413 Run();
3414 EXPECT_GE(monotonic_event_time_on_run, before_run_time);
Austin Schuh0debde12022-08-17 16:25:17 -07003415
3416 EXPECT_EQ(loop->context().monotonic_event_time, monotonic_clock::min_time);
3417 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3418 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3419 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3420 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3421 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
3422 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
3423 EXPECT_EQ(loop->context().size, 0u);
3424 EXPECT_EQ(loop->context().data, nullptr);
3425 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuha9012be2021-07-21 15:19:11 -07003426}
3427
Austin Schuh217a9782019-12-21 23:02:50 -08003428// Tests that watchers fail when created on the wrong node.
3429TEST_P(AbstractEventLoopDeathTest, NodeWatcher) {
3430 EnableNodes("them");
3431
3432 auto loop1 = Make();
3433 auto loop2 = Make();
3434 EXPECT_DEATH({ loop1->MakeWatcher("/test", [](const TestMessage &) {}); },
3435 "node");
3436 EXPECT_DEATH(
3437 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08003438 loop2->MakeRawWatcher(
3439 configuration::GetChannel(configuration(), "/test",
3440 "aos.TestMessage", "", nullptr),
3441 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08003442 },
3443 "node");
Brian Silverman454bc112020-03-05 14:21:25 -08003444 EXPECT_DEATH({ loop1->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
3445 "node");
3446 EXPECT_DEATH(
3447 {
3448 loop2->MakeRawNoArgWatcher(
3449 configuration::GetChannel(configuration(), "/test",
3450 "aos.TestMessage", "", nullptr),
3451 [](const Context &) {});
3452 },
3453 "node");
Austin Schuh217a9782019-12-21 23:02:50 -08003454}
3455
3456// Tests that fetchers fail when created on the wrong node.
3457TEST_P(AbstractEventLoopDeathTest, NodeFetcher) {
3458 EnableNodes("them");
3459 auto loop1 = Make();
3460
3461 EXPECT_DEATH({ auto fetcher = loop1->MakeFetcher<TestMessage>("/test"); },
3462 "node");
3463 EXPECT_DEATH(
3464 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08003465 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
3466 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08003467 },
3468 "node");
3469}
3470
3471// Tests that senders fail when created on the wrong node.
3472TEST_P(AbstractEventLoopDeathTest, NodeSender) {
3473 EnableNodes("them");
3474 auto loop1 = Make();
3475
3476 EXPECT_DEATH(
3477 {
3478 aos::Sender<TestMessage> sender =
3479 loop1->MakeSender<TestMessage>("/test");
3480 },
3481 "node");
3482
3483 // Note: Creating raw senders is always supported. Right now, this lets us
3484 // use them to create message_gateway.
3485}
3486
Brian Silverman341b57e2020-06-23 16:23:18 -07003487// Tests creating multiple Builders from a single Sender at the same time.
3488TEST_P(AbstractEventLoopDeathTest, MultipleBuilders) {
3489 auto loop1 = Make();
3490 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
3491
3492 { auto builder = sender.MakeBuilder(); }
3493 {
3494 auto builder = sender.MakeBuilder();
3495 builder.MakeBuilder<TestMessage>().Finish();
3496 }
3497 {
3498 // Creating this after the first one was destroyed should be fine.
3499 auto builder = sender.MakeBuilder();
3500 builder.MakeBuilder<TestMessage>().Finish();
3501 // But not a second one.
3502 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
James Kuszmaulb1c11052023-11-06 13:20:53 -08003503 "May not have multiple active allocators");
Brian Silverman341b57e2020-06-23 16:23:18 -07003504 }
3505
3506 FlatbufferDetachedBuffer<TestMessage> detached =
3507 flatbuffers::DetachedBuffer();
3508 {
3509 auto builder = sender.MakeBuilder();
3510 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
3511 }
3512 {
3513 // This is the second one, after the detached one, so it should fail.
3514 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
James Kuszmaulb1c11052023-11-06 13:20:53 -08003515 "May not have multiple active allocators");
Brian Silverman341b57e2020-06-23 16:23:18 -07003516 }
3517
3518 // Clear the detached one, and then we should be able to create another.
3519 detached = flatbuffers::DetachedBuffer();
3520 {
3521 auto builder = sender.MakeBuilder();
3522 builder.MakeBuilder<TestMessage>().Finish();
3523 }
3524
3525 // And then detach another one.
3526 {
3527 auto builder = sender.MakeBuilder();
3528 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
3529 }
3530}
3531
3532// Tests sending a buffer detached from a different builder.
3533TEST_P(AbstractEventLoopDeathTest, WrongDetachedBuffer) {
3534 auto loop1 = Make();
3535 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
3536 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
3537
3538 auto builder = sender1.MakeBuilder();
3539 FlatbufferDetachedBuffer<TestMessage> detached =
3540 builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
milind1f1dca32021-07-03 13:50:07 -07003541 EXPECT_DEATH(sender2.CheckOk(sender2.SendDetached(std::move(detached))),
Brian Silverman341b57e2020-06-23 16:23:18 -07003542 "May only send the buffer detached from this Sender");
3543}
3544
James Kuszmaul762e8692023-07-31 14:57:53 -07003545// Tests that senders fail when created on the wrong node.
3546TEST_P(AbstractEventLoopDeathTest, SetVersionWhileRunning) {
3547 auto loop1 = MakePrimary();
3548
3549 loop1->OnRun([&loop1, this]() {
3550 EXPECT_DEATH({ loop1->SetVersionString("abcdef"); },
3551 "timing report while running");
3552 Exit();
3553 });
3554
3555 Run();
3556}
3557
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003558int TestChannelFrequency(EventLoop *event_loop) {
3559 return event_loop->GetChannel<TestMessage>("/test")->frequency();
3560}
3561
3562int TestChannelQueueSize(EventLoop *event_loop) {
Austin Schuhfff9c3a2023-06-16 18:48:23 -07003563 return configuration::QueueSize(event_loop->configuration(),
3564 event_loop->GetChannel<TestMessage>("/test"));
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003565}
3566
3567RawSender::Error SendTestMessage(aos::Sender<TestMessage> &sender) {
3568 aos::Sender<TestMessage>::Builder builder = sender.MakeBuilder();
3569 TestMessage::Builder test_message_builder =
3570 builder.MakeBuilder<TestMessage>();
3571 test_message_builder.add_value(0);
3572 return builder.Send(test_message_builder.Finish());
3573}
3574
3575// Test that sending messages too fast returns
3576// RawSender::Error::kMessagesSentTooFast.
3577TEST_P(AbstractEventLoopTest, SendingMessagesTooFast) {
3578 auto event_loop = MakePrimary();
Austin Schuh63756be2024-02-05 19:51:20 -08003579 event_loop->SetRuntimeRealtimePriority(5);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003580
3581 auto sender = event_loop->MakeSender<TestMessage>("/test");
3582
3583 // Send one message in the beginning, then wait until the
3584 // channel_storage_duration is almost done and start sending messages rapidly,
3585 // having some come in the next chanel_storage_duration. The queue_size is
3586 // 1600, so the 1601st message will be the last valid one (the initial message
3587 // having being sent more than a channel_storage_duration ago), and trying to
3588 // send the 1602nd message should return
3589 // RawSender::Error::kMessagesSentTooFast.
3590 EXPECT_EQ(SendTestMessage(sender), RawSender::Error::kOk);
3591 int msgs_sent = 1;
3592 const int queue_size = TestChannelQueueSize(event_loop.get());
3593
Austin Schuh63756be2024-02-05 19:51:20 -08003594 const int messages_per_ms = 2;
3595 const auto kRepeatOffset = std::chrono::milliseconds(10);
3596 const auto base_offset =
3597 configuration::ChannelStorageDuration(event_loop->configuration(),
3598 sender.channel()) -
3599 (std::chrono::milliseconds(1) * (queue_size / 2) / messages_per_ms);
3600
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003601 const auto timer = event_loop->AddTimer([&]() {
Austin Schuh63756be2024-02-05 19:51:20 -08003602 // Send in bursts to reduce scheduler load to make the test more
3603 // reproducible.
3604 for (int i = 0; i < messages_per_ms * kRepeatOffset.count(); ++i) {
3605 const bool done = (msgs_sent == queue_size + 1);
3606 ASSERT_EQ(SendTestMessage(sender),
3607 done ? RawSender::Error::kMessagesSentTooFast
3608 : RawSender::Error::kOk);
3609 msgs_sent++;
3610 if (done) {
3611 Exit();
3612 return;
3613 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003614 }
3615 });
3616
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003617 event_loop->OnRun([&event_loop, &timer, &base_offset, &kRepeatOffset]() {
Philipp Schradera6712522023-07-05 20:25:11 -07003618 timer->Schedule(event_loop->monotonic_now() + base_offset, kRepeatOffset);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003619 });
3620
3621 Run();
3622}
3623
3624// Tests that we are able to send messages successfully after sending messages
3625// too fast and waiting while continuously attempting to send messages.
3626// Also tests that SendFailureCounter is working correctly in this
3627// situation
3628TEST_P(AbstractEventLoopTest, SendingAfterSendingTooFast) {
3629 auto event_loop = MakePrimary();
Austin Schuh63756be2024-02-05 19:51:20 -08003630 event_loop->SetRuntimeRealtimePriority(5);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003631
3632 auto sender = event_loop->MakeSender<TestMessage>("/test");
3633
Austin Schuh0e96d372023-05-08 10:10:21 -07003634 // We are sending bunches of messages at 100 Hz, so we will be sending too
3635 // fast after queue_size (800) ms. After this, keep sending messages, and
3636 // exactly a channel storage duration (2s) after we send the first message we
3637 // should be able to successfully send a message.
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003638
Austin Schuh0e96d372023-05-08 10:10:21 -07003639 const std::chrono::milliseconds kInterval = std::chrono::milliseconds(10);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003640 const monotonic_clock::duration channel_storage_duration =
Austin Schuhfff9c3a2023-06-16 18:48:23 -07003641 configuration::ChannelStorageDuration(event_loop->configuration(),
3642 sender.channel());
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003643 const int queue_size = TestChannelQueueSize(event_loop.get());
3644
3645 int msgs_sent = 0;
3646 SendFailureCounter counter;
3647 auto start = monotonic_clock::min_time;
3648
3649 event_loop->AddPhasedLoop(
Austin Schuh0e96d372023-05-08 10:10:21 -07003650 [&](int elapsed_cycles) {
3651 // The queue is setup for 800 messages/sec. We want to fill that up at
3652 // a rate of 2000 messages/sec so we make sure we fill it up.
3653 for (int i = 0; i < 2 * kInterval.count() * elapsed_cycles; ++i) {
3654 const auto actual_err = SendTestMessage(sender);
3655 const bool done_waiting = (start != monotonic_clock::min_time &&
3656 sender.monotonic_sent_time() >=
3657 (start + channel_storage_duration));
3658 const auto expected_err =
3659 (msgs_sent < queue_size || done_waiting
3660 ? RawSender::Error::kOk
3661 : RawSender::Error::kMessagesSentTooFast);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003662
Austin Schuh0e96d372023-05-08 10:10:21 -07003663 if (start == monotonic_clock::min_time) {
3664 start = sender.monotonic_sent_time();
3665 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003666
Austin Schuh0e96d372023-05-08 10:10:21 -07003667 ASSERT_EQ(actual_err, expected_err);
3668 counter.Count(actual_err);
3669 msgs_sent++;
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003670
Austin Schuh0e96d372023-05-08 10:10:21 -07003671 EXPECT_EQ(counter.failures(),
3672 msgs_sent <= queue_size
3673 ? 0
3674 : (msgs_sent - queue_size) -
3675 (actual_err == RawSender::Error::kOk ? 1 : 0));
3676 EXPECT_EQ(counter.just_failed(), actual_err != RawSender::Error::kOk);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003677
Austin Schuh0e96d372023-05-08 10:10:21 -07003678 if (done_waiting) {
3679 Exit();
3680 return;
3681 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003682 }
3683 },
3684 kInterval);
3685 Run();
3686}
3687
3688// Tests that RawSender::Error::kMessagesSentTooFast is returned
3689// when messages are sent too fast from senders in different loops
3690TEST_P(AbstractEventLoopTest, SendingTooFastWithMultipleLoops) {
3691 auto loop1 = MakePrimary();
3692 auto loop2 = Make();
3693
3694 auto sender1 = loop1->MakeSender<TestMessage>("/test");
3695 auto sender2 = loop2->MakeSender<TestMessage>("/test");
3696
3697 // Send queue_size messages split between the senders.
3698 const int queue_size = TestChannelQueueSize(loop1.get());
3699 for (int i = 0; i < queue_size / 2; i++) {
3700 ASSERT_EQ(SendTestMessage(sender1), RawSender::Error::kOk);
3701 ASSERT_EQ(SendTestMessage(sender2), RawSender::Error::kOk);
3702 }
3703
3704 // Since queue_size messages have been sent, this should return an error
3705 EXPECT_EQ(SendTestMessage(sender2), RawSender::Error::kMessagesSentTooFast);
3706}
3707
Austin Schuhdda6db72023-06-21 17:02:34 -07003708// Tests that a longer storage durations store more messages.
3709TEST_P(AbstractEventLoopTest, SendingTooFastWithLongDuration) {
3710 auto loop1 = MakePrimary();
3711
3712 auto sender1 = loop1->MakeSender<TestMessage>("/test3");
3713
3714 // Send queue_size messages split between the senders.
3715 const int queue_size =
3716 configuration::QueueSize(loop1->configuration(), sender1.channel());
3717 EXPECT_EQ(queue_size, 100 * 10);
3718 for (int i = 0; i < queue_size; i++) {
3719 ASSERT_EQ(SendTestMessage(sender1), RawSender::Error::kOk);
3720 }
3721
3722 // Since queue_size messages have been sent, and little time has elapsed,
3723 // this should return an error.
3724 EXPECT_EQ(SendTestMessage(sender1), RawSender::Error::kMessagesSentTooFast);
3725}
3726
Stephan Pleinesf63bde82024-01-13 15:59:33 -08003727} // namespace aos::testing