blob: ba2d42630877beec17e39f878c619aec422be158 [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"
Austin Schuh54cf95f2019-11-29 13:14:18 -080012#include "aos/flatbuffer_merge.h"
Austin Schuhad9e5eb2021-11-19 20:33:55 -080013#include "aos/logging/log_message_generated.h"
14#include "aos/logging/logging.h"
Austin Schuhcc6070c2020-10-10 20:25:56 -070015#include "aos/realtime.h"
Austin Schuh9fe68f72019-08-10 19:32:03 -070016
Parker Schuhe4a70d62017-12-27 20:10:20 -080017namespace aos {
18namespace 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
Brian Silverman341b57e2020-06-23 16:23:18 -0700104// Tests that watcher can receive messages from a sender, sent via SendDetached.
105TEST_P(AbstractEventLoopTest, BasicSendDetached) {
106 auto loop1 = Make();
107 auto loop2 = MakePrimary();
108
109 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
110
111 FlatbufferDetachedBuffer<TestMessage> detached =
112 flatbuffers::DetachedBuffer();
113 {
114 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
115 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
116 builder.add_value(100);
117 detached = msg.Detach(builder.Finish());
118 }
119 detached = flatbuffers::DetachedBuffer();
120 {
121 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
122 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
123 builder.add_value(200);
124 detached = msg.Detach(builder.Finish());
125 }
milind1f1dca32021-07-03 13:50:07 -0700126 sender.CheckOk(sender.SendDetached(std::move(detached)));
Brian Silverman341b57e2020-06-23 16:23:18 -0700127
128 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
129 ASSERT_TRUE(fetcher.Fetch());
130 EXPECT_EQ(fetcher->value(), 200);
131}
132
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800133// Verifies that a no-arg watcher will not have a data pointer.
134TEST_P(AbstractEventLoopTest, NoArgNoData) {
135 auto loop1 = Make();
136 auto loop2 = MakePrimary();
137
138 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
139
140 bool happened = false;
141
142 loop2->OnRun([&]() {
143 happened = true;
144
145 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
146 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -0700147 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800148 });
149
150 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
151 EXPECT_GT(loop2->context().size, 0u);
152 EXPECT_EQ(nullptr, loop2->context().data);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700153 EXPECT_EQ(-1, loop2->context().buffer_index);
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800154 this->Exit();
155 });
156
157 EXPECT_FALSE(happened);
158 Run();
159 EXPECT_TRUE(happened);
160}
161
Brian Silverman454bc112020-03-05 14:21:25 -0800162// Tests that no-arg watcher can receive messages from a sender.
163// Also tests that OnRun() works.
164TEST_P(AbstractEventLoopTest, BasicNoArg) {
165 auto loop1 = Make();
166 auto loop2 = MakePrimary();
167
168 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
169
170 bool happened = false;
171
172 loop2->OnRun([&]() {
173 happened = true;
174
175 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
176 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
177 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700178 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -0800179 });
180
181 aos::Fetcher<TestMessage> fetcher = loop2->MakeFetcher<TestMessage>("/test");
182 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
183 ASSERT_TRUE(fetcher.Fetch());
184 EXPECT_EQ(fetcher->value(), 200);
185 this->Exit();
186 });
187
188 EXPECT_FALSE(happened);
189 Run();
190 EXPECT_TRUE(happened);
191}
192
193// Tests that a watcher can be created with an std::function.
194TEST_P(AbstractEventLoopTest, BasicFunction) {
195 auto loop1 = Make();
196 auto loop2 = MakePrimary();
197
198 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
199
200 bool happened = false;
201
202 loop2->OnRun([&]() {
203 happened = true;
204
205 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
206 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
207 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700208 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -0800209 });
210
211 loop2->MakeWatcher("/test", std::function<void(const TestMessage &)>(
212 [&](const TestMessage &message) {
213 EXPECT_EQ(message.value(), 200);
214 this->Exit();
215 }));
216
217 EXPECT_FALSE(happened);
218 Run();
219 EXPECT_TRUE(happened);
220}
221
Brian Silverman0fc69932020-01-24 21:54:02 -0800222// Tests that watcher can receive messages from two senders.
223// Also tests that OnRun() works.
224TEST_P(AbstractEventLoopTest, BasicTwoSenders) {
225 auto loop1 = Make();
226 auto loop2 = MakePrimary();
227
228 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
229 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
230
231 bool happened = false;
232
233 loop2->OnRun([&]() {
234 happened = true;
235
236 {
237 aos::Sender<TestMessage>::Builder msg = sender1.MakeBuilder();
238 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
239 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700240 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman0fc69932020-01-24 21:54:02 -0800241 }
242 {
243 aos::Sender<TestMessage>::Builder msg = sender2.MakeBuilder();
244 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
245 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700246 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman0fc69932020-01-24 21:54:02 -0800247 }
248 });
249
250 int messages_received = 0;
251 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
252 EXPECT_EQ(message.value(), 200);
253 this->Exit();
254 ++messages_received;
255 });
256
257 EXPECT_FALSE(happened);
258 Run();
259 EXPECT_TRUE(happened);
260 EXPECT_EQ(messages_received, 2);
261}
262
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700263// Tests that a fetcher can fetch from a sender.
264// Also tests that OnRun() works.
265TEST_P(AbstractEventLoopTest, FetchWithoutRun) {
266 auto loop1 = Make();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800267 auto loop2 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -0700268 auto loop3 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800269
270 auto sender = loop1->MakeSender<TestMessage>("/test");
271
272 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
273
Austin Schuhbbce72d2019-05-26 15:11:46 -0700274 EXPECT_FALSE(fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -0800275 EXPECT_EQ(fetcher.get(), nullptr);
276
Austin Schuhad154822019-12-27 15:45:13 -0800277 EXPECT_EQ(fetcher.context().monotonic_event_time, monotonic_clock::min_time);
278 EXPECT_EQ(fetcher.context().monotonic_remote_time, monotonic_clock::min_time);
279 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
280 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -0700281 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
Austin Schuh39788ff2019-12-01 18:22:57 -0800282 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
283 EXPECT_EQ(fetcher.context().size, 0u);
284 EXPECT_EQ(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700285 EXPECT_EQ(fetcher.context().buffer_index, -1);
Austin Schuhbbce72d2019-05-26 15:11:46 -0700286
Alex Perrycb7da4b2019-08-28 19:35:56 -0700287 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
288 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
289 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700290 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700291
292 EXPECT_TRUE(fetcher.Fetch());
293 ASSERT_FALSE(fetcher.get() == nullptr);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700294 EXPECT_EQ(fetcher.get()->value(), 200);
Austin Schuh39788ff2019-12-01 18:22:57 -0800295
296 const chrono::milliseconds kEpsilon(100);
297
Austin Schuhad154822019-12-27 15:45:13 -0800298 const aos::monotonic_clock::time_point monotonic_now = loop2->monotonic_now();
299 const aos::realtime_clock::time_point realtime_now = loop2->realtime_now();
300 EXPECT_EQ(fetcher.context().monotonic_event_time,
301 fetcher.context().monotonic_remote_time);
302 EXPECT_EQ(fetcher.context().realtime_event_time,
303 fetcher.context().realtime_remote_time);
304
305 EXPECT_GE(fetcher.context().monotonic_event_time, monotonic_now - kEpsilon);
306 EXPECT_LE(fetcher.context().monotonic_event_time, monotonic_now + kEpsilon);
307 EXPECT_GE(fetcher.context().realtime_event_time, realtime_now - kEpsilon);
308 EXPECT_LE(fetcher.context().realtime_event_time, realtime_now + kEpsilon);
Austin Schuha9012be2021-07-21 15:19:11 -0700309 EXPECT_EQ(fetcher.context().source_boot_uuid, loop2->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -0800310 EXPECT_EQ(fetcher.context().queue_index, 0x0u);
311 EXPECT_EQ(fetcher.context().size, 20u);
312 EXPECT_NE(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700313 if (read_method() == ReadMethod::PIN) {
314 EXPECT_GE(fetcher.context().buffer_index, 0);
315 EXPECT_LT(fetcher.context().buffer_index,
316 loop2->NumberBuffers(fetcher.channel()));
317 } else {
318 EXPECT_EQ(fetcher.context().buffer_index, -1);
319 }
Parker Schuhe4a70d62017-12-27 20:10:20 -0800320}
321
Austin Schuh98ed26f2023-07-19 14:12:28 -0700322std::function<bool(const Context &)> MakeShouldFetch(
323 bool should_fetch, size_t *called_count = nullptr) {
324 return [should_fetch, called_count](const Context &) {
325 if (called_count != nullptr) {
326 (*called_count)++;
327 }
328 return should_fetch;
329 };
330}
331
332// Tests that a fetcher using FetchIf can fetch from a sender.
333TEST_P(AbstractEventLoopTest, FetchIfWithoutRun) {
334 auto loop1 = Make();
335 auto loop2 = Make();
336 auto loop3 = MakePrimary();
337
338 auto sender = loop1->MakeSender<TestMessage>("/test");
339
340 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
341
342 for (const bool should_fetch : {true, false}) {
343 EXPECT_FALSE(fetcher.FetchIf(MakeShouldFetch(should_fetch)));
344 EXPECT_EQ(fetcher.get(), nullptr);
345
346 EXPECT_EQ(fetcher.context().monotonic_event_time,
347 monotonic_clock::min_time);
348 EXPECT_EQ(fetcher.context().monotonic_remote_time,
349 monotonic_clock::min_time);
350 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
351 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
352 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
353 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
354 EXPECT_EQ(fetcher.context().size, 0u);
355 EXPECT_EQ(fetcher.context().data, nullptr);
356 EXPECT_EQ(fetcher.context().buffer_index, -1);
357 }
358
359 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
360 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
361 builder.add_value(200);
362 msg.CheckOk(msg.Send(builder.Finish()));
363
364 // Make sure failing to fetch won't affect anything.
365 EXPECT_FALSE(fetcher.FetchIf(MakeShouldFetch(false)));
366 EXPECT_EQ(fetcher.get(), nullptr);
367
368 EXPECT_EQ(fetcher.context().monotonic_event_time, monotonic_clock::min_time);
369 EXPECT_EQ(fetcher.context().monotonic_remote_time, monotonic_clock::min_time);
370 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
371 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
372 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
373 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
374 EXPECT_EQ(fetcher.context().size, 0u);
375 EXPECT_EQ(fetcher.context().data, nullptr);
376 EXPECT_EQ(fetcher.context().buffer_index, -1);
377
378 // And now confirm we succeed and everything gets set right.
379 EXPECT_TRUE(fetcher.FetchIf(MakeShouldFetch(true)));
380 ASSERT_FALSE(fetcher.get() == nullptr);
381 EXPECT_EQ(fetcher.get()->value(), 200);
382
383 const chrono::milliseconds kEpsilon(100);
384
385 const aos::monotonic_clock::time_point monotonic_now = loop2->monotonic_now();
386 const aos::realtime_clock::time_point realtime_now = loop2->realtime_now();
387 EXPECT_EQ(fetcher.context().monotonic_event_time,
388 fetcher.context().monotonic_remote_time);
389 EXPECT_EQ(fetcher.context().realtime_event_time,
390 fetcher.context().realtime_remote_time);
391
392 EXPECT_GE(fetcher.context().monotonic_event_time, monotonic_now - kEpsilon);
393 EXPECT_LE(fetcher.context().monotonic_event_time, monotonic_now + kEpsilon);
394 EXPECT_GE(fetcher.context().realtime_event_time, realtime_now - kEpsilon);
395 EXPECT_LE(fetcher.context().realtime_event_time, realtime_now + kEpsilon);
396 EXPECT_EQ(fetcher.context().source_boot_uuid, loop2->boot_uuid());
397 EXPECT_EQ(fetcher.context().queue_index, 0x0u);
398 EXPECT_EQ(fetcher.context().size, 20u);
399 EXPECT_NE(fetcher.context().data, nullptr);
400 if (read_method() == ReadMethod::PIN) {
401 EXPECT_GE(fetcher.context().buffer_index, 0);
402 EXPECT_LT(fetcher.context().buffer_index,
403 loop2->NumberBuffers(fetcher.channel()));
404 } else {
405 EXPECT_EQ(fetcher.context().buffer_index, -1);
406 }
407}
408
Austin Schuh3578a2e2019-05-25 18:17:59 -0700409// Tests that watcher will receive all messages sent if they are sent after
410// initialization and before running.
411TEST_P(AbstractEventLoopTest, DoubleSendAtStartup) {
412 auto loop1 = Make();
413 auto loop2 = MakePrimary();
414
415 auto sender = loop1->MakeSender<TestMessage>("/test");
416
417 ::std::vector<int> values;
418
419 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700420 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700421 if (values.size() == 2) {
Austin Schuh9fe68f72019-08-10 19:32:03 -0700422 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -0700423 }
424 });
425
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700426 // Before Run, should be ignored.
Austin Schuh3578a2e2019-05-25 18:17:59 -0700427 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700428 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
429 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
430 builder.add_value(199);
milind1f1dca32021-07-03 13:50:07 -0700431 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700432 }
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700433
434 loop2->OnRun([&]() {
Austin Schuh98ed26f2023-07-19 14:12:28 -0700435 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700436 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
437 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700438 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700439 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700440 }
441 });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700442
443 Run();
444
445 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
446}
447
448// Tests that watcher will not receive messages sent before the watcher is
449// created.
450TEST_P(AbstractEventLoopTest, DoubleSendAfterStartup) {
451 auto loop1 = Make();
452 auto loop2 = MakePrimary();
453
454 auto sender = loop1->MakeSender<TestMessage>("/test");
455
456 ::std::vector<int> values;
457
Austin Schuh98ed26f2023-07-19 14:12:28 -0700458 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700459 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
460 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700461 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700462 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700463 }
464
465 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700466 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700467 });
468
469 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700470 auto test_timer = loop2->AddTimer([this]() { this->Exit(); });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700471 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700472 test_timer->Schedule(loop2->monotonic_now(),
473 ::std::chrono::milliseconds(100));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700474 });
475
476 Run();
477 EXPECT_EQ(0, values.size());
478}
479
Austin Schuhbbce72d2019-05-26 15:11:46 -0700480// Tests that FetchNext gets all the messages sent after it is constructed.
481TEST_P(AbstractEventLoopTest, FetchNext) {
482 auto loop1 = Make();
483 auto loop2 = MakePrimary();
484
485 auto sender = loop1->MakeSender<TestMessage>("/test");
486 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
487
488 ::std::vector<int> values;
489
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 Schuhbbce72d2019-05-26 15:11:46 -0700495 }
496
497 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700498 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700499 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700500 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700501 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700502 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700503 });
504
505 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700506 test_timer->Schedule(loop2->monotonic_now(),
507 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700508 });
509
510 Run();
511 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
512}
513
514// Tests that FetchNext gets no messages sent before it is constructed.
515TEST_P(AbstractEventLoopTest, FetchNextAfterSend) {
516 auto loop1 = Make();
517 auto loop2 = MakePrimary();
518
519 auto sender = loop1->MakeSender<TestMessage>("/test");
520
521 ::std::vector<int> values;
522
Austin Schuh98ed26f2023-07-19 14:12:28 -0700523 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700524 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
525 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700526 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700527 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700528 }
529
530 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
531
532 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700533 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700534 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700535 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700536 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700537 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700538 });
539
540 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700541 test_timer->Schedule(loop2->monotonic_now(),
542 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700543 });
544
545 Run();
546 EXPECT_THAT(0, values.size());
547}
548
Austin Schuh98ed26f2023-07-19 14:12:28 -0700549// Tests that FetchNextIf gets no messages sent before it is constructed.
550TEST_P(AbstractEventLoopTest, FetchNextIfAfterSend) {
551 auto loop1 = Make();
552 auto loop2 = MakePrimary();
553
554 auto sender = loop1->MakeSender<TestMessage>("/test");
555
556 ::std::vector<int> values;
557
558 for (int i = 200; i < 202; ++i) {
559 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
560 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
561 builder.add_value(i);
562 msg.CheckOk(msg.Send(builder.Finish()));
563 }
564
565 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
566
567 // Add a timer to actually quit.
568 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
569 while (fetcher.FetchNextIf(MakeShouldFetch(true))) {
570 values.push_back(fetcher.get()->value());
571 }
572 this->Exit();
573 });
574
575 loop2->OnRun([&test_timer, &loop2]() {
576 test_timer->Schedule(loop2->monotonic_now(),
577 ::std::chrono::milliseconds(100));
578 });
579
580 Run();
581 EXPECT_EQ(0, values.size());
582}
583
Austin Schuhbbce72d2019-05-26 15:11:46 -0700584// Tests that Fetch returns the last message created before the loop was
585// started.
586TEST_P(AbstractEventLoopTest, FetchDataFromBeforeCreation) {
587 auto loop1 = Make();
588 auto loop2 = MakePrimary();
589
590 auto sender = loop1->MakeSender<TestMessage>("/test");
591
592 ::std::vector<int> values;
593
Austin Schuh98ed26f2023-07-19 14:12:28 -0700594 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700595 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
596 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700597 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700598 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700599 }
600
601 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
602
603 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700604 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700605 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700606 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700607 }
608 // Do it again to make sure we don't double fetch.
609 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700610 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700611 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700612 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700613 });
614
615 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700616 test_timer->Schedule(loop2->monotonic_now(),
617 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700618 });
619
620 Run();
621 EXPECT_THAT(values, ::testing::ElementsAreArray({201}));
622}
623
Austin Schuh98ed26f2023-07-19 14:12:28 -0700624// Tests that FetchIf returns the last message created before the loop was
625// started.
626TEST_P(AbstractEventLoopTest, FetchIfDataFromBeforeCreation) {
627 auto loop1 = Make();
628 auto loop2 = MakePrimary();
629
630 auto sender = loop1->MakeSender<TestMessage>("/test");
631
632 ::std::vector<int> values;
633
634 for (int i = 200; i < 202; ++i) {
635 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
636 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
637 builder.add_value(i);
638 msg.CheckOk(msg.Send(builder.Finish()));
639 }
640
641 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
642
643 // Add a timer to actually quit.
644 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
645 if (fetcher.FetchIf(MakeShouldFetch(true))) {
646 values.push_back(fetcher.get()->value());
647 }
648
649 if (fetcher.FetchIf(MakeShouldFetch(false))) {
650 values.push_back(fetcher.get()->value());
651 }
652 // Do it again to make sure we don't double fetch.
653 if (fetcher.FetchIf(MakeShouldFetch(true))) {
654 values.push_back(fetcher.get()->value());
655 }
656 this->Exit();
657 });
658
659 loop2->OnRun([&test_timer, &loop2]() {
660 test_timer->Schedule(loop2->monotonic_now(),
661 ::std::chrono::milliseconds(100));
662 });
663
664 Run();
665 EXPECT_THAT(values, ::testing::ElementsAreArray({201}));
666}
667
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700668// Tests that timer handler is enabled after setup (even if it is in the past)
669// and is disabled after running
670TEST_P(AbstractEventLoopTest, CheckTimerDisabled) {
671 auto loop = MakePrimary("primary");
672
673 auto timer = loop->AddTimer([this]() {
674 LOG(INFO) << "timer called";
675 Exit();
676 });
677
678 loop->OnRun([&loop, timer]() {
679 EXPECT_TRUE(timer->IsDisabled());
Philipp Schradera6712522023-07-05 20:25:11 -0700680 timer->Schedule(loop->monotonic_now() + chrono::milliseconds(100));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700681 EXPECT_FALSE(timer->IsDisabled());
682 });
683
684 Run();
685 EXPECT_TRUE(timer->IsDisabled());
686}
687
688// Tests that timer handler is enabled after setup (even if it is in the past)
689// and is disabled after running
690TEST_P(AbstractEventLoopTest, CheckTimerRunInPastDisabled) {
691 auto loop = MakePrimary("primary");
692
693 auto timer2 = loop->AddTimer([this]() {
694 LOG(INFO) << "timer called";
695 Exit();
696 });
697
698 auto timer = loop->AddTimer([&loop, timer2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700699 timer2->Schedule(loop->monotonic_now() - chrono::nanoseconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700700 });
701
702 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700703 timer->Schedule(loop->monotonic_now() + chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700704 EXPECT_FALSE(timer->IsDisabled());
705 });
706
707 Run();
708 EXPECT_TRUE(timer2->IsDisabled());
709}
710
711// Tests that timer handler is not disabled even after calling Exit on the event
712// loop within the timer
713TEST_P(AbstractEventLoopTest, CheckTimerRepeatOnCountDisabled) {
714 auto loop = MakePrimary("primary");
715 int counter = 0;
716
717 auto timer = loop->AddTimer([&counter, this]() {
718 LOG(INFO) << "timer called";
719 counter++;
720 if (counter >= 5) {
721 Exit();
722 }
723 });
724
725 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700726 timer->Schedule(loop->monotonic_now() + chrono::seconds(1),
727 chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700728 EXPECT_FALSE(timer->IsDisabled());
729 });
730 Run();
731
732 // Sanity check
733 EXPECT_EQ(counter, 5);
734
735 // if you run the loop again, the timer will start running again
736 EXPECT_FALSE(timer->IsDisabled());
737
738 counter = 0;
739 Run();
740 timer->Disable();
741
742 EXPECT_TRUE(timer->IsDisabled());
743}
744
745// Tests that timer handler is not disabled even after calling Exit on the event
746// loop using an external timer
747TEST_P(AbstractEventLoopTest, CheckTimerRepeatTillEndTimerDisabled) {
748 auto loop = MakePrimary("primary");
749
750 auto timer = loop->AddTimer([]() { LOG(INFO) << "timer called"; });
751
752 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700753 timer->Schedule(loop->monotonic_now() + chrono::seconds(1),
754 chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700755 EXPECT_FALSE(timer->IsDisabled());
756 });
757
758 EndEventLoop(loop.get(), chrono::seconds(5));
759 Run();
760 EXPECT_FALSE(timer->IsDisabled());
761
762 timer->Disable();
763 EXPECT_TRUE(timer->IsDisabled());
764}
765
Austin Schuhbbce72d2019-05-26 15:11:46 -0700766// Tests that Fetch and FetchNext interleave as expected.
767TEST_P(AbstractEventLoopTest, FetchAndFetchNextTogether) {
768 auto loop1 = Make();
769 auto loop2 = MakePrimary();
770
771 auto sender = loop1->MakeSender<TestMessage>("/test");
772
773 ::std::vector<int> values;
774
Austin Schuh98ed26f2023-07-19 14:12:28 -0700775 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700776 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
777 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700778 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700779 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700780 }
781
782 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
783
784 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700785 auto test_timer = loop2->AddTimer([&fetcher, &values, &sender, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700786 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700787 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700788 }
789
Austin Schuh98ed26f2023-07-19 14:12:28 -0700790 for (int i = 202; i < 205; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700791 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
792 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700793 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700794 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700795 }
796
797 if (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700798 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700799 }
800
801 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700802 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700803 }
804
Austin Schuh9fe68f72019-08-10 19:32:03 -0700805 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700806 });
807
808 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700809 test_timer->Schedule(loop2->monotonic_now(),
810 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700811 });
812
813 Run();
814 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
815}
816
Austin Schuh98ed26f2023-07-19 14:12:28 -0700817// Tests that Fetch{If,} and FetchNext{If,} interleave as expected.
818TEST_P(AbstractEventLoopTest, FetchAndFetchNextIfTogether) {
819 auto loop1 = Make();
820 auto loop2 = MakePrimary();
821
822 auto sender = loop1->MakeSender<TestMessage>("/test");
823
824 ::std::vector<int> values;
825
826 for (int i = 200; i < 202; ++i) {
827 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
828 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
829 builder.add_value(i);
830 msg.CheckOk(msg.Send(builder.Finish()));
831 }
832
833 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
834
835 // Add a timer to actually quit.
836 auto test_timer = loop2->AddTimer([&fetcher, &values, &sender, this]() {
837 if (fetcher.Fetch()) {
838 values.push_back(fetcher.get()->value());
839 }
840
841 for (int i = 202; i < 205; ++i) {
842 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
843 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
844 builder.add_value(i);
845 msg.CheckOk(msg.Send(builder.Finish()));
846 }
847
848 EXPECT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false)));
849
850 if (fetcher.FetchNext()) {
851 values.push_back(fetcher.get()->value());
852 }
853
854 EXPECT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false)));
855 EXPECT_FALSE(fetcher.FetchIf(MakeShouldFetch(false)));
856
857 if (fetcher.FetchIf(MakeShouldFetch(true))) {
858 values.push_back(fetcher.get()->value());
859 }
860
861 this->Exit();
862 });
863
864 loop2->OnRun([&test_timer, &loop2]() {
865 test_timer->Schedule(loop2->monotonic_now(),
866 ::std::chrono::milliseconds(100));
867 });
868
869 Run();
870 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
871}
872
Austin Schuh3115a202019-05-27 21:02:14 -0700873// Tests that FetchNext behaves correctly when we get two messages in the queue
874// but don't consume the first until after the second has been sent.
875TEST_P(AbstractEventLoopTest, FetchNextTest) {
Austin Schuh3115a202019-05-27 21:02:14 -0700876 auto send_loop = Make();
877 auto fetch_loop = Make();
878 auto sender = send_loop->MakeSender<TestMessage>("/test");
879 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
880
881 {
Tyler Chatow67ddb032020-01-12 14:30:04 -0800882 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
883 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
884 builder.add_value(100);
milind1f1dca32021-07-03 13:50:07 -0700885 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700886 }
887
888 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700889 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
890 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
891 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700892 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700893 }
894
895 ASSERT_TRUE(fetcher.FetchNext());
896 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700897 EXPECT_EQ(100, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700898
899 ASSERT_TRUE(fetcher.FetchNext());
900 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700901 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700902
903 // When we run off the end of the queue, expect to still have the old message:
904 ASSERT_FALSE(fetcher.FetchNext());
905 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700906 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700907}
908
Austin Schuh98ed26f2023-07-19 14:12:28 -0700909// Tests that FetchNext behaves correctly when we get two messages in the queue
910// but don't consume the first until after the second has been sent.
911TEST_P(AbstractEventLoopTest, FetchNextIfTest) {
912 auto send_loop = Make();
913 auto fetch_loop = Make();
914 auto sender = send_loop->MakeSender<TestMessage>("/test");
915 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
916
917 {
918 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
919 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
920 builder.add_value(100);
921 msg.CheckOk(msg.Send(builder.Finish()));
922 }
923
924 {
925 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
926 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
927 builder.add_value(200);
928 msg.CheckOk(msg.Send(builder.Finish()));
929 }
930
931 size_t called_count = 0;
932 ASSERT_TRUE(fetcher.FetchNextIf(MakeShouldFetch(true, &called_count)));
933 ASSERT_NE(nullptr, fetcher.get());
934 EXPECT_EQ(100, fetcher.get()->value());
935 EXPECT_EQ(called_count, 1u);
936
937 ASSERT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false, &called_count)));
938 EXPECT_EQ(called_count, 2u);
939
940 ASSERT_TRUE(fetcher.FetchNextIf(MakeShouldFetch(true, &called_count)));
941 ASSERT_NE(nullptr, fetcher.get());
942 EXPECT_EQ(200, fetcher.get()->value());
943 EXPECT_EQ(called_count, 3u);
944
945 // When we run off the end of the queue, expect to still have the old message:
946 ASSERT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false, &called_count)));
947 EXPECT_EQ(called_count, 3u);
948 ASSERT_NE(nullptr, fetcher.get());
949 EXPECT_EQ(200, fetcher.get()->value());
950}
951
Brian Silverman77162972020-08-12 19:52:40 -0700952// Verify that a fetcher still holds its data, even after falling behind.
953TEST_P(AbstractEventLoopTest, FetcherBehindData) {
954 auto send_loop = Make();
955 auto fetch_loop = Make();
956 auto sender = send_loop->MakeSender<TestMessage>("/test");
957 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
958 {
959 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
960 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
961 builder.add_value(1);
milind1f1dca32021-07-03 13:50:07 -0700962 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -0700963 }
964 ASSERT_TRUE(fetcher.Fetch());
965 EXPECT_EQ(1, fetcher.get()->value());
966 for (int i = 0; i < 300; ++i) {
967 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
968 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
969 builder.add_value(i + 2);
milind1f1dca32021-07-03 13:50:07 -0700970 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -0700971 }
972 EXPECT_EQ(1, fetcher.get()->value());
973}
974
975// Try a bunch of orderings of operations with fetchers and senders. Verify that
976// all the fetchers have the correct data at each step.
977TEST_P(AbstractEventLoopTest, FetcherPermutations) {
978 for (int max_save = 0; max_save < 5; ++max_save) {
979 SCOPED_TRACE("max_save=" + std::to_string(max_save));
980
981 auto send_loop = Make();
982 auto fetch_loop = Make();
983 auto sender = send_loop->MakeSender<TestMessage>("/test");
984 const auto send_message = [&sender](int i) {
985 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
986 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
987 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700988 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -0700989 };
990 std::vector<Fetcher<TestMessage>> fetchers;
991 for (int i = 0; i < 10; ++i) {
992 fetchers.emplace_back(fetch_loop->MakeFetcher<TestMessage>("/test"));
993 }
994 send_message(1);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700995 const auto verify_buffers = [&]() {
996 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>>
997 fetchers_copy;
998 for (const auto &fetcher : fetchers) {
999 fetchers_copy.emplace_back(fetcher);
1000 }
1001 std::vector<std::reference_wrapper<const Sender<TestMessage>>>
1002 senders_copy;
1003 senders_copy.emplace_back(sender);
1004 VerifyBuffers(send_loop->NumberBuffers(sender.channel()), fetchers_copy,
1005 senders_copy);
1006 };
Brian Silverman77162972020-08-12 19:52:40 -07001007 for (auto &fetcher : fetchers) {
1008 ASSERT_TRUE(fetcher.Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -07001009 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001010 EXPECT_EQ(1, fetcher.get()->value());
1011 }
1012
1013 for (int save = 1; save <= max_save; ++save) {
1014 SCOPED_TRACE("save=" + std::to_string(save));
1015 send_message(100 + save);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001016 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001017 for (size_t i = 0; i < fetchers.size() - save; ++i) {
1018 SCOPED_TRACE("fetcher=" + std::to_string(i));
1019 ASSERT_TRUE(fetchers[i].Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -07001020 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001021 EXPECT_EQ(100 + save, fetchers[i].get()->value());
1022 }
1023 for (size_t i = fetchers.size() - save; i < fetchers.size() - 1; ++i) {
1024 SCOPED_TRACE("fetcher=" + std::to_string(i));
1025 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
1026 }
1027 EXPECT_EQ(1, fetchers.back().get()->value());
1028 }
1029
1030 for (int i = 0; i < 300; ++i) {
1031 send_message(200 + i);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001032 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001033 }
1034
1035 for (size_t i = 0; i < fetchers.size() - max_save; ++i) {
1036 SCOPED_TRACE("fetcher=" + std::to_string(i));
1037 if (max_save > 0) {
1038 EXPECT_EQ(100 + max_save, fetchers[i].get()->value());
1039 } else {
1040 EXPECT_EQ(1, fetchers[i].get()->value());
1041 }
1042 }
1043 for (size_t i = fetchers.size() - max_save; i < fetchers.size() - 1; ++i) {
1044 SCOPED_TRACE("fetcher=" + std::to_string(i));
1045 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
1046 }
1047 EXPECT_EQ(1, fetchers.back().get()->value());
1048 }
1049}
1050
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001051// Verify that making a fetcher and watcher for "/test" succeeds.
1052TEST_P(AbstractEventLoopTest, FetcherAndWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -08001053 auto loop = Make();
1054 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001055 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Parker Schuhe4a70d62017-12-27 20:10:20 -08001056}
1057
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001058// Verify that making 2 fetchers for "/test" succeeds.
Parker Schuhe4a70d62017-12-27 20:10:20 -08001059TEST_P(AbstractEventLoopTest, TwoFetcher) {
1060 auto loop = Make();
1061 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001062 auto fetcher2 = loop->MakeFetcher<TestMessage>("/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -08001063}
1064
Alex Perrycb7da4b2019-08-28 19:35:56 -07001065// Verify that registering a watcher for an invalid channel name dies.
1066TEST_P(AbstractEventLoopDeathTest, InvalidChannelName) {
1067 auto loop = Make();
1068 EXPECT_DEATH(
1069 { loop->MakeWatcher("/test/invalid", [&](const TestMessage &) {}); },
1070 "/test/invalid");
Brian Silverman454bc112020-03-05 14:21:25 -08001071 EXPECT_DEATH(
1072 { loop->MakeNoArgWatcher<TestMessage>("/test/invalid", [&]() {}); },
1073 "/test/invalid");
Alex Perrycb7da4b2019-08-28 19:35:56 -07001074}
1075
James Kuszmaul8866e642022-06-10 16:00:36 -07001076// Verify that setting up a timer before monotonic_clock::epoch() fails.
James Kuszmaul86e86c32022-07-21 17:39:47 -07001077TEST_P(AbstractEventLoopDeathTest, NegativeTimeTimer) {
James Kuszmaul8866e642022-06-10 16:00:36 -07001078 auto loop = Make();
1079 TimerHandler *time = loop->AddTimer([]() {});
Philipp Schradera6712522023-07-05 20:25:11 -07001080 EXPECT_DEATH(
1081 time->Schedule(monotonic_clock::epoch() - std::chrono::seconds(1)),
1082 "-1.000");
James Kuszmaul8866e642022-06-10 16:00:36 -07001083}
1084
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001085// Verify that registering a watcher twice for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001086TEST_P(AbstractEventLoopDeathTest, TwoWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -08001087 auto loop = Make();
1088 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001089 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
1090 "/test");
Brian Silverman454bc112020-03-05 14:21:25 -08001091 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
1092}
1093
1094// Verify that registering a no-arg watcher twice for "/test" fails.
1095TEST_P(AbstractEventLoopDeathTest, TwoNoArgWatcher) {
1096 auto loop = Make();
1097 loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {});
1098 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
1099 "/test");
1100 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001101}
1102
Austin Schuh3115a202019-05-27 21:02:14 -07001103// Verify that SetRuntimeRealtimePriority fails while running.
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001104TEST_P(AbstractEventLoopDeathTest, SetRuntimeRealtimePriority) {
Austin Schuh3115a202019-05-27 21:02:14 -07001105 auto loop = MakePrimary();
Austin Schuh65493d62022-08-17 15:10:37 -07001106 EXPECT_EQ(0, loop->runtime_realtime_priority());
Austin Schuh3115a202019-05-27 21:02:14 -07001107 // Confirm that runtime priority calls work when not realtime.
1108 loop->SetRuntimeRealtimePriority(5);
Austin Schuh65493d62022-08-17 15:10:37 -07001109 EXPECT_EQ(5, loop->runtime_realtime_priority());
Austin Schuh3115a202019-05-27 21:02:14 -07001110
1111 loop->OnRun([&]() { loop->SetRuntimeRealtimePriority(5); });
1112
1113 EXPECT_DEATH(Run(), "realtime");
1114}
1115
Austin Schuh65493d62022-08-17 15:10:37 -07001116namespace {
1117
1118bool CpuSetEqual(const cpu_set_t &a, const cpu_set_t &b) {
1119 return CPU_EQUAL(&a, &b);
1120}
1121
1122} // namespace
1123
Brian Silverman6a54ff32020-04-28 16:41:39 -07001124// Verify that SetRuntimeAffinity fails while running.
1125TEST_P(AbstractEventLoopDeathTest, SetRuntimeAffinity) {
Austin Schuhde973292021-10-12 18:09:49 -07001126 const cpu_set_t available = GetCurrentThreadAffinity();
1127 int first_cpu = -1;
1128 for (int i = 0; i < CPU_SETSIZE; ++i) {
1129 if (CPU_ISSET(i, &available)) {
1130 first_cpu = i;
1131 break;
1132 continue;
1133 }
1134 }
1135 CHECK_NE(first_cpu, -1) << ": Default affinity has no CPUs?";
1136
Brian Silverman6a54ff32020-04-28 16:41:39 -07001137 auto loop = MakePrimary();
Austin Schuh65493d62022-08-17 15:10:37 -07001138 EXPECT_TRUE(
1139 CpuSetEqual(EventLoop::DefaultAffinity(), loop->runtime_affinity()));
1140 const cpu_set_t new_affinity = MakeCpusetFromCpus({first_cpu});
Brian Silverman6a54ff32020-04-28 16:41:39 -07001141 // Confirm that runtime priority calls work when not running.
Austin Schuh65493d62022-08-17 15:10:37 -07001142 loop->SetRuntimeAffinity(new_affinity);
1143 EXPECT_TRUE(CpuSetEqual(new_affinity, loop->runtime_affinity()));
Brian Silverman6a54ff32020-04-28 16:41:39 -07001144
Austin Schuhde973292021-10-12 18:09:49 -07001145 loop->OnRun(
1146 [&]() { loop->SetRuntimeAffinity(MakeCpusetFromCpus({first_cpu})); });
Brian Silverman6a54ff32020-04-28 16:41:39 -07001147
1148 EXPECT_DEATH(Run(), "Cannot set affinity while running");
1149}
1150
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001151// Verify that registering a watcher and a sender for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001152TEST_P(AbstractEventLoopDeathTest, WatcherAndSender) {
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001153 auto loop = Make();
1154 auto sender = loop->MakeSender<TestMessage>("/test");
1155 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
1156 "/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -08001157}
1158
Austin Schuhe516ab02020-05-06 21:37:04 -07001159// Verify that creating too many senders fails.
1160TEST_P(AbstractEventLoopDeathTest, TooManySenders) {
1161 auto loop = Make();
1162 std::vector<aos::Sender<TestMessage>> senders;
1163 for (int i = 0; i < 10; ++i) {
1164 senders.emplace_back(loop->MakeSender<TestMessage>("/test"));
1165 }
1166 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); },
1167 "Failed to create sender on \\{ \"name\": \"/test\", \"type\": "
Brian Silverman77162972020-08-12 19:52:40 -07001168 "\"aos.TestMessage\"[^}]*\\ }, too many senders.");
1169}
1170
1171// Verify that creating too many fetchers fails.
1172TEST_P(AbstractEventLoopDeathTest, TooManyFetchers) {
1173 if (read_method() != ReadMethod::PIN) {
1174 // Other read methods don't limit the number of readers, so just skip this.
1175 return;
1176 }
1177
1178 auto loop = Make();
1179 std::vector<aos::Fetcher<TestMessage>> fetchers;
1180 for (int i = 0; i < 10; ++i) {
1181 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1182 }
1183 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1184 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1185 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
1186}
1187
1188// Verify that creating too many fetchers, split between two event loops, fails.
1189TEST_P(AbstractEventLoopDeathTest, TooManyFetchersTwoLoops) {
1190 if (read_method() != ReadMethod::PIN) {
1191 // Other read methods don't limit the number of readers, so just skip this.
1192 return;
1193 }
1194
1195 auto loop = Make();
1196 auto loop2 = Make();
1197 std::vector<aos::Fetcher<TestMessage>> fetchers;
1198 for (int i = 0; i < 5; ++i) {
1199 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1200 fetchers.emplace_back(loop2->MakeFetcher<TestMessage>("/test"));
1201 }
1202 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1203 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1204 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
1205}
1206
1207// Verify that creating too many watchers fails.
1208TEST_P(AbstractEventLoopDeathTest, TooManyWatchers) {
1209 if (read_method() != ReadMethod::PIN) {
1210 // Other read methods don't limit the number of readers, so just skip this.
1211 return;
1212 }
1213
1214 std::vector<std::unique_ptr<EventLoop>> loops;
1215 for (int i = 0; i < 10; ++i) {
1216 loops.emplace_back(Make());
1217 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
1218 }
1219 EXPECT_DEATH({ Make()->MakeWatcher("/test", [](const TestMessage &) {}); },
1220 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1221 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
1222}
1223
1224// Verify that creating too many watchers and fetchers combined fails.
1225TEST_P(AbstractEventLoopDeathTest, TooManyWatchersAndFetchers) {
1226 if (read_method() != ReadMethod::PIN) {
1227 // Other read methods don't limit the number of readers, so just skip this.
1228 return;
1229 }
1230
1231 auto loop = Make();
1232 std::vector<aos::Fetcher<TestMessage>> fetchers;
1233 std::vector<std::unique_ptr<EventLoop>> loops;
1234 for (int i = 0; i < 5; ++i) {
1235 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1236 loops.emplace_back(Make());
1237 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
1238 }
1239 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1240 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1241 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
Austin Schuhe516ab02020-05-06 21:37:04 -07001242}
1243
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001244// Verify that we can't create a sender inside OnRun.
1245TEST_P(AbstractEventLoopDeathTest, SenderInOnRun) {
1246 auto loop1 = MakePrimary();
1247
1248 loop1->OnRun(
1249 [&]() { auto sender = loop1->MakeSender<TestMessage>("/test2"); });
1250
1251 EXPECT_DEATH(Run(), "running");
1252}
1253
1254// Verify that we can't create a watcher inside OnRun.
1255TEST_P(AbstractEventLoopDeathTest, WatcherInOnRun) {
1256 auto loop1 = MakePrimary();
1257
1258 loop1->OnRun(
1259 [&]() { loop1->MakeWatcher("/test", [&](const TestMessage &) {}); });
1260
1261 EXPECT_DEATH(Run(), "running");
1262}
1263
Brian Silverman454bc112020-03-05 14:21:25 -08001264// Verify that we can't create a no-arg watcher inside OnRun.
1265TEST_P(AbstractEventLoopDeathTest, NoArgWatcherInOnRun) {
1266 auto loop1 = MakePrimary();
1267
1268 loop1->OnRun(
1269 [&]() { loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {}); });
1270
1271 EXPECT_DEATH(Run(), "running");
1272}
1273
Parker Schuhe4a70d62017-12-27 20:10:20 -08001274// Verify that Quit() works when there are multiple watchers.
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001275TEST_P(AbstractEventLoopTest, MultipleWatcherQuit) {
1276 auto loop1 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -07001277 auto loop2 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -08001278
Austin Schuh3578a2e2019-05-25 18:17:59 -07001279 loop2->MakeWatcher("/test1", [&](const TestMessage &) {});
1280 loop2->MakeWatcher("/test2", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001281 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -07001282 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -07001283 });
1284
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001285 auto sender = loop1->MakeSender<TestMessage>("/test2");
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001286
1287 loop2->OnRun([&]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001288 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1289 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1290 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001291 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001292 });
Parker Schuhe4a70d62017-12-27 20:10:20 -08001293
Austin Schuh44019f92019-05-19 19:58:27 -07001294 Run();
Parker Schuhe4a70d62017-12-27 20:10:20 -08001295}
1296
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001297// Verify that AOS_LOG has the right name.
1298TEST_P(AbstractEventLoopTest, AOSLog) {
1299 auto loop2 = MakePrimary("loop1");
1300 auto loop1 = Make("loop0");
1301
1302 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1303
1304 EXPECT_FALSE(fetcher.Fetch());
1305
1306 loop2->OnRun([&]() {
1307 AOS_LOG(INFO, "Testing123");
1308 this->Exit();
1309 });
1310
1311 Run();
1312 EXPECT_TRUE(fetcher.Fetch());
1313 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1314}
1315
1316// Verify that AOS_LOG has the right name in a watcher.
1317TEST_P(AbstractEventLoopTest, AOSLogWatcher) {
1318 auto loop2 = MakePrimary("loop1");
1319 auto loop1 = Make("loop0");
1320
1321 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1322
1323 EXPECT_FALSE(fetcher.Fetch());
1324
1325 auto sender = loop1->MakeSender<TestMessage>("/test2");
1326
1327 loop2->MakeWatcher("/test2", [&](const TestMessage & /*message*/) {
1328 AOS_LOG(INFO, "Testing123");
1329 this->Exit();
1330 });
1331
1332 loop2->OnRun([&]() {
1333 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1334 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1335 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001336 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001337 });
1338
1339 Run();
1340 EXPECT_TRUE(fetcher.Fetch());
1341 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1342}
1343
1344// Verify that AOS_LOG has the right name in a timer.
1345TEST_P(AbstractEventLoopTest, AOSLogTimer) {
1346 auto loop2 = MakePrimary("loop1");
1347 auto loop1 = Make("loop0");
1348
1349 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1350
1351 EXPECT_FALSE(fetcher.Fetch());
1352
1353 auto test_timer = loop2->AddTimer([&]() {
1354 AOS_LOG(INFO, "Testing123");
1355 this->Exit();
1356 });
1357
Philipp Schradera6712522023-07-05 20:25:11 -07001358 loop2->OnRun([&]() { test_timer->Schedule(loop2->monotonic_now()); });
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001359
1360 Run();
1361 EXPECT_TRUE(fetcher.Fetch());
1362 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1363}
1364
Neil Balch229001a2018-01-07 18:22:52 -08001365// Verify that timer intervals and duration function properly.
1366TEST_P(AbstractEventLoopTest, TimerIntervalAndDuration) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001367 // Force a slower rate so we are guaranteed to have reports for our timer.
Austin Schuh39788ff2019-12-01 18:22:57 -08001368 FLAGS_timing_report_ms = 2000;
1369
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001370 const int kCount = 5;
Neil Balch229001a2018-01-07 18:22:52 -08001371
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001372 auto loop = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001373 auto loop2 = Make();
1374
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001375 ::std::vector<::aos::monotonic_clock::time_point> times;
1376 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
1377
Austin Schuh39788ff2019-12-01 18:22:57 -08001378 Fetcher<timing::Report> report_fetcher =
1379 loop2->MakeFetcher<timing::Report>("/aos");
1380 EXPECT_FALSE(report_fetcher.Fetch());
1381
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001382 auto test_timer = loop->AddTimer([this, &times, &expected_times, &loop]() {
1383 times.push_back(loop->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001384 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
1385 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
1386 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001387 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -08001388 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
1389 EXPECT_EQ(loop->context().size, 0u);
1390 EXPECT_EQ(loop->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001391 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001392
Austin Schuhad154822019-12-27 15:45:13 -08001393 expected_times.push_back(loop->context().monotonic_event_time);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001394 if (times.size() == kCount) {
1395 this->Exit();
1396 }
Neil Balch229001a2018-01-07 18:22:52 -08001397 });
Austin Schuh39788ff2019-12-01 18:22:57 -08001398 test_timer->set_name("Test loop");
Neil Balch229001a2018-01-07 18:22:52 -08001399
Austin Schuh39788ff2019-12-01 18:22:57 -08001400 const monotonic_clock::time_point start_time = loop->monotonic_now();
Austin Schuh52d325c2019-06-23 18:59:06 -07001401 // TODO(austin): This should be an error... Should be done in OnRun only.
Philipp Schradera6712522023-07-05 20:25:11 -07001402 test_timer->Schedule(start_time + chrono::seconds(1), chrono::seconds(1));
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001403
Austin Schuh44019f92019-05-19 19:58:27 -07001404 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001405
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001406 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001407 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
1408 ASSERT_EQ(times.size(), expected_times.size());
1409 ASSERT_EQ((times.size() % 2), 1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001410
1411 // Grab the middle sample.
1412 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
1413
1414 // Add up all the delays of all the times.
1415 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1416 for (const ::aos::monotonic_clock::time_point time : times) {
1417 sum += time - average_time;
1418 }
1419
1420 // Average and add to the middle to find the average time.
1421 sum /= times.size();
1422 average_time += sum;
1423
1424 // Compute the offset from the average and the expected average. It
1425 // should be pretty close to 0.
1426 const ::aos::monotonic_clock::duration remainder =
1427 average_time - start_time - chrono::seconds(times.size() / 2 + 1);
1428
1429 const chrono::milliseconds kEpsilon(100);
1430 EXPECT_LT(remainder, +kEpsilon);
1431 EXPECT_GT(remainder, -kEpsilon);
1432
1433 // Make sure that the average duration is close to 1 second.
1434 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1435 times.front())
1436 .count() /
1437 static_cast<double>(times.size() - 1),
1438 1.0, 0.1);
1439
1440 // Confirm that the ideal wakeup times increment correctly.
1441 for (size_t i = 1; i < expected_times.size(); ++i) {
1442 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1443 }
1444
1445 for (size_t i = 0; i < expected_times.size(); ++i) {
1446 EXPECT_EQ((expected_times[i] - start_time) % chrono::seconds(1),
1447 chrono::seconds(0));
1448 }
1449
1450 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1451 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001452
Austin Schuh6bae8252021-02-07 22:01:49 -08001453 if (do_timing_reports() == DoTimingReports::kYes) {
1454 // And, since we are here, check that the timing report makes sense.
1455 // Start by looking for our event loop's timing.
1456 FlatbufferDetachedBuffer<timing::Report> report =
1457 FlatbufferDetachedBuffer<timing::Report>::Empty();
1458 while (report_fetcher.FetchNext()) {
1459 if (report_fetcher->name()->string_view() == "primary") {
1460 report = CopyFlatBuffer(report_fetcher.get());
1461 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001462 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001463
1464 // Confirm that we have the right number of reports, and the contents are
1465 // sane.
1466 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
1467
1468 EXPECT_EQ(report.message().name()->string_view(), "primary");
1469
1470 ASSERT_NE(report.message().senders(), nullptr);
1471 EXPECT_EQ(report.message().senders()->size(), 2);
1472
1473 ASSERT_NE(report.message().timers(), nullptr);
1474 EXPECT_EQ(report.message().timers()->size(), 2);
1475
1476 EXPECT_EQ(report.message().timers()->Get(0)->name()->string_view(),
1477 "Test loop");
1478 EXPECT_GE(report.message().timers()->Get(0)->count(), 1);
1479
1480 EXPECT_EQ(report.message().timers()->Get(1)->name()->string_view(),
1481 "timing_reports");
1482 EXPECT_EQ(report.message().timers()->Get(1)->count(), 1);
1483
1484 // Make sure there is a single phased loop report with our report in it.
1485 ASSERT_EQ(report.message().phased_loops(), nullptr);
1486 } else {
1487 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001488 }
Neil Balch229001a2018-01-07 18:22:52 -08001489}
1490
1491// Verify that we can change a timer's parameters during execution.
1492TEST_P(AbstractEventLoopTest, TimerChangeParameters) {
Austin Schuh44019f92019-05-19 19:58:27 -07001493 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001494 loop->SetRuntimeRealtimePriority(1);
Austin Schuh7f20f512021-01-31 17:56:16 -08001495 std::vector<monotonic_clock::time_point> iteration_list;
Neil Balch229001a2018-01-07 18:22:52 -08001496
1497 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001498 ScopedNotRealtime nrt;
Austin Schuh7f20f512021-01-31 17:56:16 -08001499 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001500 });
1501
Austin Schuh7f20f512021-01-31 17:56:16 -08001502 monotonic_clock::time_point s;
1503 auto modifier_timer = loop->AddTimer([&test_timer, &s]() {
Philipp Schradera6712522023-07-05 20:25:11 -07001504 test_timer->Schedule(s + chrono::milliseconds(1750),
1505 chrono::milliseconds(600));
Neil Balch229001a2018-01-07 18:22:52 -08001506 });
1507
Austin Schuh7f20f512021-01-31 17:56:16 -08001508 s = loop->monotonic_now();
Philipp Schradera6712522023-07-05 20:25:11 -07001509 test_timer->Schedule(s, chrono::milliseconds(500));
1510 modifier_timer->Schedule(s + chrono::milliseconds(1250));
Austin Schuhd892f102021-10-12 18:01:46 -07001511 EndEventLoop(loop.get(), chrono::milliseconds(3950));
Austin Schuh44019f92019-05-19 19:58:27 -07001512 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001513
Austin Schuhd892f102021-10-12 18:01:46 -07001514 EXPECT_THAT(
1515 iteration_list,
1516 ::testing::ElementsAre(
1517 s, s + chrono::milliseconds(500), s + chrono::milliseconds(1000),
1518 s + chrono::milliseconds(1750), s + chrono::milliseconds(2350),
1519 s + chrono::milliseconds(2950), s + chrono::milliseconds(3550)));
Neil Balch229001a2018-01-07 18:22:52 -08001520}
1521
1522// Verify that we can disable a timer during execution.
1523TEST_P(AbstractEventLoopTest, TimerDisable) {
Austin Schuh44019f92019-05-19 19:58:27 -07001524 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001525 loop->SetRuntimeRealtimePriority(1);
Neil Balch229001a2018-01-07 18:22:52 -08001526 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
1527
1528 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001529 ScopedNotRealtime nrt;
Austin Schuhd892f102021-10-12 18:01:46 -07001530 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001531 });
1532
Tyler Chatow67ddb032020-01-12 14:30:04 -08001533 auto ender_timer = loop->AddTimer([&test_timer]() { test_timer->Disable(); });
Neil Balch229001a2018-01-07 18:22:52 -08001534
Austin Schuhd892f102021-10-12 18:01:46 -07001535 monotonic_clock::time_point s = loop->monotonic_now();
Philipp Schradera6712522023-07-05 20:25:11 -07001536 test_timer->Schedule(s, ::std::chrono::milliseconds(500));
1537 ender_timer->Schedule(s + ::std::chrono::milliseconds(1250));
Austin Schuh73d99502021-12-08 12:05:39 -08001538 EndEventLoop(loop.get(), ::std::chrono::milliseconds(2000));
Austin Schuh44019f92019-05-19 19:58:27 -07001539 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001540
Austin Schuhd892f102021-10-12 18:01:46 -07001541 EXPECT_THAT(iteration_list,
Austin Schuh73d99502021-12-08 12:05:39 -08001542 ::testing::ElementsAre(s, s + chrono::milliseconds(500),
1543 s + chrono::milliseconds(1000)));
Neil Balch229001a2018-01-07 18:22:52 -08001544}
Austin Schuh7267c532019-05-19 19:55:53 -07001545
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001546// Verify that a timer can disable itself.
1547//
1548// TODO(Brian): Do something similar with phased loops, both with a quick
1549// handler and a handler that would miss a cycle except it got deferred. Current
1550// behavior doing that is a mess.
1551TEST_P(AbstractEventLoopTest, TimerDisableSelf) {
1552 auto loop = MakePrimary();
1553
1554 int count = 0;
1555 aos::TimerHandler *test_timer;
1556 test_timer = loop->AddTimer([&count, &test_timer]() {
1557 ++count;
1558 test_timer->Disable();
1559 });
1560
Philipp Schradera6712522023-07-05 20:25:11 -07001561 test_timer->Schedule(loop->monotonic_now(), ::std::chrono::milliseconds(20));
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001562 EndEventLoop(loop.get(), ::std::chrono::milliseconds(80));
1563 Run();
1564
1565 EXPECT_EQ(count, 1);
1566}
1567
Brian Silvermanbd405c02020-06-23 16:25:23 -07001568// Verify that we can disable a timer during execution of another timer
1569// scheduled for the same time, with one ordering of creation for the timers.
1570//
1571// Also schedule some more events to reshuffle the heap in EventLoop used for
1572// tracking events to change up the order. This used to segfault
1573// SimulatedEventLoop.
1574TEST_P(AbstractEventLoopTest, TimerDisableOther) {
1575 for (bool creation_order : {true, false}) {
1576 for (bool setup_order : {true, false}) {
1577 for (int shuffle_events = 0; shuffle_events < 5; ++shuffle_events) {
1578 auto loop = MakePrimary();
1579 aos::TimerHandler *test_timer, *ender_timer;
1580 if (creation_order) {
1581 test_timer = loop->AddTimer([]() {});
1582 ender_timer =
1583 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1584 } else {
1585 ender_timer =
1586 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1587 test_timer = loop->AddTimer([]() {});
1588 }
1589
1590 const auto start = loop->monotonic_now();
1591
1592 for (int i = 0; i < shuffle_events; ++i) {
Philipp Schradera6712522023-07-05 20:25:11 -07001593 loop->AddTimer([]() {})->Schedule(start +
1594 std::chrono::milliseconds(10));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001595 }
1596
1597 if (setup_order) {
Philipp Schradera6712522023-07-05 20:25:11 -07001598 test_timer->Schedule(start + ::std::chrono::milliseconds(20));
1599 ender_timer->Schedule(start + ::std::chrono::milliseconds(20));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001600 } else {
Philipp Schradera6712522023-07-05 20:25:11 -07001601 ender_timer->Schedule(start + ::std::chrono::milliseconds(20));
1602 test_timer->Schedule(start + ::std::chrono::milliseconds(20));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001603 }
1604 EndEventLoop(loop.get(), ::std::chrono::milliseconds(40));
1605 Run();
1606 }
1607 }
1608 }
1609}
1610
Austin Schuh54cf95f2019-11-29 13:14:18 -08001611// Verifies that the event loop implementations detect when Channel is not a
Brian Silverman631b6262021-11-10 12:25:08 -08001612// pointer into configuration(), or a name doesn't map to a channel in
1613// configuration().
Austin Schuh54cf95f2019-11-29 13:14:18 -08001614TEST_P(AbstractEventLoopDeathTest, InvalidChannel) {
1615 auto loop = MakePrimary();
1616
Tyler Chatow67ddb032020-01-12 14:30:04 -08001617 const Channel *channel = configuration::GetChannel(
1618 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
Austin Schuh54cf95f2019-11-29 13:14:18 -08001619
1620 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1621
1622 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001623 loop->MakeRawSender(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001624 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1625
1626 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001627 loop->MakeSender<TestMessage>("/testbad"),
1628 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1629 " not found in config");
1630
1631 EXPECT_FALSE(loop->TryMakeSender<TestMessage>("/testbad"));
1632
1633 EXPECT_DEATH(
1634 loop->MakeRawFetcher(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001635 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1636
1637 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001638 loop->MakeFetcher<TestMessage>("/testbad"),
1639 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1640 " not found in config");
1641
1642 EXPECT_FALSE(loop->TryMakeFetcher<TestMessage>("/testbad").valid());
1643
1644 EXPECT_DEATH(
Austin Schuh54cf95f2019-11-29 13:14:18 -08001645 {
1646 loop->MakeRawWatcher(&channel_copy.message(),
1647 [](const Context, const void *) {});
1648 },
1649 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
Brian Silverman631b6262021-11-10 12:25:08 -08001650
1651 EXPECT_DEATH(
1652 { loop->MakeWatcher("/testbad", [](const TestMessage &) {}); },
1653 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1654 " not found in config");
1655}
1656
1657// Verifies that the event loop handles a channel which is not readable or
1658// writable on the current node nicely.
1659TEST_P(AbstractEventLoopDeathTest, InaccessibleChannel) {
1660 EnableNodes("me");
1661 auto loop = MakePrimary("me");
1662 auto loop2 = Make("them");
1663
1664 const Channel *channel = configuration::GetChannel(
1665 loop->configuration(), "/test_noforward", "aos.TestMessage", "", nullptr);
1666
1667 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1668
1669 EXPECT_DEATH(
1670 loop2->MakeSender<TestMessage>("/test_forward"),
1671 "Channel"
1672 " \\{ \"name\": \"/test_forward\", \"type\": \"aos.TestMessage\" \\}"
1673 " is not able to be sent on this node");
1674
1675 EXPECT_FALSE(loop2->TryMakeSender<TestMessage>("/test_forward"));
1676
1677 EXPECT_DEATH(
1678 loop2->MakeRawFetcher(channel),
1679 "Channel"
1680 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1681 " is not able to be fetched on this node");
1682
1683 EXPECT_DEATH(
1684 loop2->MakeFetcher<TestMessage>("/test_noforward"),
1685 "Channel"
1686 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1687 " is not able to be fetched on this node");
1688
1689 EXPECT_FALSE(loop2->TryMakeFetcher<TestMessage>("/test_noforward").valid());
1690
1691 EXPECT_DEATH(
1692 { loop2->MakeRawWatcher(channel, [](const Context, const void *) {}); },
1693 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1694 "\"source_node\": \"them\" \\}"
1695 " is not able to be watched on this node");
1696
1697 EXPECT_DEATH(
1698 { loop2->MakeWatcher("/test_noforward", [](const TestMessage &) {}); },
1699 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1700 "\"source_node\": \"them\" \\}"
1701 " is not able to be watched on this node");
Austin Schuh54cf95f2019-11-29 13:14:18 -08001702}
1703
Austin Schuhd54780b2020-10-03 16:26:02 -07001704// Verifies that the event loop implementations detect when Channel has an
1705// invalid alignment.
1706TEST_P(AbstractEventLoopDeathTest, InvalidChannelAlignment) {
1707 const char *const kError = "multiple of alignment";
1708 InvalidChannelAlignment();
1709
1710 auto loop = MakePrimary();
1711
1712 const Channel *channel = configuration::GetChannel(
1713 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
1714
1715 EXPECT_DEATH({ loop->MakeRawSender(channel); }, kError);
1716 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); }, kError);
1717
1718 EXPECT_DEATH({ loop->MakeRawFetcher(channel); }, kError);
1719 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); }, kError);
1720
1721 EXPECT_DEATH(
1722 { loop->MakeRawWatcher(channel, [](const Context &, const void *) {}); },
1723 kError);
1724 EXPECT_DEATH({ loop->MakeRawNoArgWatcher(channel, [](const Context &) {}); },
1725 kError);
1726
1727 EXPECT_DEATH({ loop->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
1728 kError);
1729 EXPECT_DEATH({ loop->MakeWatcher("/test", [](const TestMessage &) {}); },
1730 kError);
1731}
1732
Brian Silverman454bc112020-03-05 14:21:25 -08001733// Verify that the send time on a message is roughly right when using a watcher.
Austin Schuh7267c532019-05-19 19:55:53 -07001734TEST_P(AbstractEventLoopTest, MessageSendTime) {
Austin Schuh44019f92019-05-19 19:58:27 -07001735 auto loop1 = MakePrimary();
Austin Schuh7267c532019-05-19 19:55:53 -07001736 auto loop2 = Make();
Austin Schuhad154822019-12-27 15:45:13 -08001737 auto sender = loop2->MakeSender<TestMessage>("/test");
Austin Schuh7267c532019-05-19 19:55:53 -07001738 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
1739
1740 auto test_timer = loop1->AddTimer([&sender]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001741 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1742 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1743 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001744 msg.CheckOk(msg.Send(builder.Finish()));
Alex Perrycb7da4b2019-08-28 19:35:56 -07001745 });
1746
Austin Schuhad154822019-12-27 15:45:13 -08001747 bool triggered = false;
Brian Silverman454bc112020-03-05 14:21:25 -08001748 loop1->MakeWatcher("/test", [&](const TestMessage &msg) {
Austin Schuhad154822019-12-27 15:45:13 -08001749 // Confirm that the data pointer makes sense from a watcher, and all the
1750 // timestamps look right.
1751 EXPECT_GT(&msg, loop1->context().data);
1752 EXPECT_EQ(loop1->context().monotonic_remote_time,
1753 loop1->context().monotonic_event_time);
1754 EXPECT_EQ(loop1->context().realtime_remote_time,
1755 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001756 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001757
1758 const aos::monotonic_clock::time_point monotonic_now =
1759 loop1->monotonic_now();
Tyler Chatow67ddb032020-01-12 14:30:04 -08001760 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08001761
1762 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1763 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1764 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1765 monotonic_now);
1766 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1767 realtime_now);
1768
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001769 EXPECT_LT(&msg, reinterpret_cast<const void *>(
1770 reinterpret_cast<const char *>(loop1->context().data) +
Austin Schuhad154822019-12-27 15:45:13 -08001771 loop1->context().size));
Brian Silverman4f4e0612020-08-12 19:54:41 -07001772 if (read_method() == ReadMethod::PIN) {
1773 EXPECT_GE(loop1->context().buffer_index, 0);
1774 EXPECT_LT(loop1->context().buffer_index,
1775 loop1->NumberBuffers(
1776 configuration::GetChannel(loop1->configuration(), "/test",
1777 "aos.TestMessage", "", nullptr)));
1778 } else {
1779 EXPECT_EQ(-1, loop1->context().buffer_index);
1780 }
Austin Schuhad154822019-12-27 15:45:13 -08001781 triggered = true;
Austin Schuh7267c532019-05-19 19:55:53 -07001782 });
1783
Philipp Schradera6712522023-07-05 20:25:11 -07001784 test_timer->Schedule(loop1->monotonic_now() + ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07001785
1786 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
Austin Schuh44019f92019-05-19 19:58:27 -07001787 Run();
Austin Schuh7267c532019-05-19 19:55:53 -07001788
Austin Schuhad154822019-12-27 15:45:13 -08001789 EXPECT_TRUE(triggered);
1790
Brian Silverman454bc112020-03-05 14:21:25 -08001791 ASSERT_TRUE(fetcher.Fetch());
1792
1793 monotonic_clock::duration monotonic_time_offset =
1794 fetcher.context().monotonic_event_time -
1795 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1796 realtime_clock::duration realtime_time_offset =
1797 fetcher.context().realtime_event_time -
1798 (loop1->realtime_now() - ::std::chrono::seconds(1));
1799
1800 EXPECT_EQ(fetcher.context().realtime_event_time,
1801 fetcher.context().realtime_remote_time);
1802 EXPECT_EQ(fetcher.context().monotonic_event_time,
1803 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001804 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001805
1806 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1807 << ": Got "
1808 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1809 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1810 // Confirm that the data pointer makes sense.
1811 EXPECT_GT(fetcher.get(), fetcher.context().data);
1812 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001813 reinterpret_cast<const void *>(
1814 reinterpret_cast<const char *>(fetcher.context().data) +
Brian Silverman454bc112020-03-05 14:21:25 -08001815 fetcher.context().size));
1816 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1817 << ": Got "
1818 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1819 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1820
1821 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1822 << ": Got "
1823 << fetcher.context().realtime_event_time.time_since_epoch().count()
1824 << " expected " << loop1->realtime_now().time_since_epoch().count();
1825 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1826 << ": Got "
1827 << fetcher.context().realtime_event_time.time_since_epoch().count()
1828 << " expected " << loop1->realtime_now().time_since_epoch().count();
1829}
1830
1831// Verify that the send time on a message is roughly right when using a no-arg
1832// watcher. To get a message, we need to use a fetcher to actually access the
1833// message. This is also the main use case for no-arg fetchers.
1834TEST_P(AbstractEventLoopTest, MessageSendTimeNoArg) {
1835 auto loop1 = MakePrimary();
1836 auto loop2 = Make();
1837 auto sender = loop2->MakeSender<TestMessage>("/test");
1838 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
1839
1840 auto test_timer = loop1->AddTimer([&sender]() {
1841 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1842 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1843 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001844 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -08001845 });
1846
1847 bool triggered = false;
1848 loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {
1849 // Confirm that we can indeed use a fetcher on this channel from this
1850 // context, and it results in a sane data pointer and timestamps.
1851 ASSERT_TRUE(fetcher.Fetch());
1852
1853 EXPECT_EQ(loop1->context().monotonic_remote_time,
1854 loop1->context().monotonic_event_time);
1855 EXPECT_EQ(loop1->context().realtime_remote_time,
1856 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001857 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001858
1859 const aos::monotonic_clock::time_point monotonic_now =
1860 loop1->monotonic_now();
1861 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
1862
1863 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1864 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1865 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1866 monotonic_now);
1867 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1868 realtime_now);
1869
1870 triggered = true;
1871 });
1872
Philipp Schradera6712522023-07-05 20:25:11 -07001873 test_timer->Schedule(loop1->monotonic_now() + ::std::chrono::seconds(1));
Brian Silverman454bc112020-03-05 14:21:25 -08001874
1875 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
1876 Run();
1877
1878 ASSERT_TRUE(triggered);
Austin Schuh7267c532019-05-19 19:55:53 -07001879
Alex Perrycb7da4b2019-08-28 19:35:56 -07001880 monotonic_clock::duration monotonic_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001881 fetcher.context().monotonic_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001882 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1883 realtime_clock::duration realtime_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001884 fetcher.context().realtime_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001885 (loop1->realtime_now() - ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07001886
Austin Schuhad154822019-12-27 15:45:13 -08001887 EXPECT_EQ(fetcher.context().realtime_event_time,
1888 fetcher.context().realtime_remote_time);
1889 EXPECT_EQ(fetcher.context().monotonic_event_time,
1890 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001891 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001892
Alex Perrycb7da4b2019-08-28 19:35:56 -07001893 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1894 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001895 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh52d325c2019-06-23 18:59:06 -07001896 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07001897 // Confirm that the data pointer makes sense.
1898 EXPECT_GT(fetcher.get(), fetcher.context().data);
1899 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001900 reinterpret_cast<const void *>(
1901 reinterpret_cast<const char *>(fetcher.context().data) +
Alex Perrycb7da4b2019-08-28 19:35:56 -07001902 fetcher.context().size));
1903 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1904 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001905 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh7267c532019-05-19 19:55:53 -07001906 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07001907
1908 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1909 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001910 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07001911 << " expected " << loop1->realtime_now().time_since_epoch().count();
1912 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1913 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001914 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07001915 << " expected " << loop1->realtime_now().time_since_epoch().count();
Austin Schuh7267c532019-05-19 19:55:53 -07001916}
1917
Austin Schuh52d325c2019-06-23 18:59:06 -07001918// Tests that a couple phased loops run in a row result in the correct offset
1919// and period.
1920TEST_P(AbstractEventLoopTest, PhasedLoopTest) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001921 // Force a slower rate so we are guaranteed to have reports for our phased
Austin Schuh39788ff2019-12-01 18:22:57 -08001922 // loop.
1923 FLAGS_timing_report_ms = 2000;
1924
Austin Schuh52d325c2019-06-23 18:59:06 -07001925 const chrono::milliseconds kOffset = chrono::milliseconds(400);
1926 const int kCount = 5;
1927
1928 auto loop1 = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001929 auto loop2 = Make();
1930
1931 Fetcher<timing::Report> report_fetcher =
1932 loop2->MakeFetcher<timing::Report>("/aos");
1933 EXPECT_FALSE(report_fetcher.Fetch());
Austin Schuh52d325c2019-06-23 18:59:06 -07001934
1935 // Collect up a couple of samples.
1936 ::std::vector<::aos::monotonic_clock::time_point> times;
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001937 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
Austin Schuh52d325c2019-06-23 18:59:06 -07001938
1939 // Run kCount iterations.
Austin Schuh39788ff2019-12-01 18:22:57 -08001940 loop1
1941 ->AddPhasedLoop(
1942 [&times, &expected_times, &loop1, this](int count) {
1943 EXPECT_EQ(count, 1);
1944 times.push_back(loop1->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001945 expected_times.push_back(loop1->context().monotonic_event_time);
Austin Schuh39788ff2019-12-01 18:22:57 -08001946
Austin Schuhad154822019-12-27 15:45:13 -08001947 EXPECT_EQ(loop1->context().monotonic_remote_time,
1948 monotonic_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001949 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001950 EXPECT_EQ(loop1->context().realtime_event_time,
1951 realtime_clock::min_time);
1952 EXPECT_EQ(loop1->context().realtime_remote_time,
Austin Schuh39788ff2019-12-01 18:22:57 -08001953 realtime_clock::min_time);
1954 EXPECT_EQ(loop1->context().queue_index, 0xffffffffu);
1955 EXPECT_EQ(loop1->context().size, 0u);
1956 EXPECT_EQ(loop1->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001957 EXPECT_EQ(loop1->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001958
1959 if (times.size() == kCount) {
1960 LOG(INFO) << "Exiting";
1961 this->Exit();
1962 }
1963 },
1964 chrono::seconds(1), kOffset)
1965 ->set_name("Test loop");
Austin Schuh52d325c2019-06-23 18:59:06 -07001966
1967 // Add a delay to make sure that delay during startup doesn't result in a
1968 // "missed cycle".
1969 SleepFor(chrono::seconds(2));
1970
1971 Run();
1972
1973 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001974 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
1975 ASSERT_EQ(times.size(), expected_times.size());
1976 ASSERT_EQ((times.size() % 2), 1);
Austin Schuh52d325c2019-06-23 18:59:06 -07001977
1978 // Grab the middle sample.
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001979 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
Austin Schuh52d325c2019-06-23 18:59:06 -07001980
1981 // Add up all the delays of all the times.
1982 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1983 for (const ::aos::monotonic_clock::time_point time : times) {
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001984 sum += time - average_time;
Austin Schuh52d325c2019-06-23 18:59:06 -07001985 }
1986
1987 // Average and add to the middle to find the average time.
1988 sum /= times.size();
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001989 average_time += sum;
Austin Schuh52d325c2019-06-23 18:59:06 -07001990
1991 // Compute the offset from the start of the second of the average time. This
1992 // should be pretty close to the offset.
1993 const ::aos::monotonic_clock::duration remainder =
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001994 average_time.time_since_epoch() -
1995 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
Austin Schuh52d325c2019-06-23 18:59:06 -07001996
1997 const chrono::milliseconds kEpsilon(100);
1998 EXPECT_LT(remainder, kOffset + kEpsilon);
1999 EXPECT_GT(remainder, kOffset - kEpsilon);
2000
2001 // Make sure that the average duration is close to 1 second.
2002 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
2003 times.front())
2004 .count() /
2005 static_cast<double>(times.size() - 1),
2006 1.0, 0.1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002007
2008 // Confirm that the ideal wakeup times increment correctly.
2009 for (size_t i = 1; i < expected_times.size(); ++i) {
2010 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
2011 }
2012
2013 for (size_t i = 0; i < expected_times.size(); ++i) {
2014 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
2015 kOffset);
2016 }
2017
2018 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
2019 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08002020
Austin Schuh6bae8252021-02-07 22:01:49 -08002021 if (do_timing_reports() == DoTimingReports::kYes) {
2022 // And, since we are here, check that the timing report makes sense.
2023 // Start by looking for our event loop's timing.
2024 FlatbufferDetachedBuffer<timing::Report> report =
2025 FlatbufferDetachedBuffer<timing::Report>::Empty();
2026 while (report_fetcher.FetchNext()) {
2027 if (report_fetcher->name()->string_view() == "primary") {
2028 report = CopyFlatBuffer(report_fetcher.get());
2029 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002030 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002031
2032 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
2033
2034 EXPECT_EQ(report.message().name()->string_view(), "primary");
2035
2036 ASSERT_NE(report.message().senders(), nullptr);
2037 EXPECT_EQ(report.message().senders()->size(), 2);
2038
2039 ASSERT_NE(report.message().timers(), nullptr);
2040 EXPECT_EQ(report.message().timers()->size(), 1);
2041
2042 // Make sure there is a single phased loop report with our report in it.
2043 ASSERT_NE(report.message().phased_loops(), nullptr);
2044 ASSERT_EQ(report.message().phased_loops()->size(), 1);
2045 EXPECT_EQ(report.message().phased_loops()->Get(0)->name()->string_view(),
2046 "Test loop");
2047 EXPECT_GE(report.message().phased_loops()->Get(0)->count(), 1);
2048 } else {
2049 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002050 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002051}
2052
Milind Upadhyay42589bb2021-05-19 20:05:16 -07002053// Tests that a phased loop responds correctly to a changing offset.
2054TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetTest) {
2055 // Force a slower rate so we are guaranteed to have reports for our phased
2056 // loop.
2057 FLAGS_timing_report_ms = 2000;
2058
2059 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2060 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2061 const int kCount = 5;
2062
2063 auto loop1 = MakePrimary();
2064
2065 // Collect up a couple of samples.
2066 ::std::vector<::aos::monotonic_clock::time_point> times;
2067 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
2068
2069 PhasedLoopHandler *phased_loop;
2070
2071 // Run kCount iterations.
2072 phased_loop = loop1->AddPhasedLoop(
2073 [&phased_loop, &times, &expected_times, &loop1, this, kOffset,
2074 kInterval](int count) {
2075 EXPECT_EQ(count, 1);
2076 times.push_back(loop1->monotonic_now());
2077
2078 expected_times.push_back(loop1->context().monotonic_event_time);
2079
2080 phased_loop->set_interval_and_offset(
2081 kInterval, kOffset - chrono::milliseconds(times.size()));
2082 LOG(INFO) << "new offset: "
2083 << (kOffset - chrono::milliseconds(times.size())).count();
2084
2085 if (times.size() == kCount) {
2086 LOG(INFO) << "Exiting";
2087 this->Exit();
2088 }
2089 },
2090 kInterval, kOffset);
2091 phased_loop->set_name("Test loop");
2092
2093 // Add a delay to make sure that delay during startup doesn't result in a
2094 // "missed cycle".
2095 SleepFor(chrono::seconds(2));
2096
2097 Run();
2098 // Confirm that we got both the right number of samples, and it's odd.
2099 EXPECT_EQ(times.size(), static_cast<size_t>(kCount));
2100 EXPECT_EQ(times.size(), expected_times.size());
2101 EXPECT_EQ((times.size() % 2), 1);
2102
2103 // Grab the middle sample.
2104 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
2105
2106 // Add up all the delays of all the times.
2107 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
2108 for (const ::aos::monotonic_clock::time_point time : times) {
2109 sum += time - average_time;
2110 }
2111
2112 // Average and add to the middle to find the average time.
2113 sum /= times.size();
2114 average_time += sum;
2115
2116 // Compute the offset from the start of the second of the average time. This
2117 // should be pretty close to the offset.
2118 const ::aos::monotonic_clock::duration remainder =
2119 average_time.time_since_epoch() -
2120 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
2121
2122 const chrono::milliseconds kEpsilon(100);
2123 EXPECT_LT(remainder, kOffset + kEpsilon);
2124 EXPECT_GT(remainder, kOffset - kEpsilon);
2125
2126 // Make sure that the average duration is close to 1 second.
2127 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
2128 times.front())
2129 .count() /
2130 static_cast<double>(times.size() - 1),
2131 1.0, 0.1);
2132
2133 // Confirm that the ideal wakeup times increment correctly.
2134 for (size_t i = 1; i < expected_times.size(); ++i) {
2135 LOG(INFO) << i - 1 << ": " << expected_times[i - 1] << ", " << i << ": "
2136 << expected_times[i];
2137 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1) -
2138 chrono::milliseconds(1));
2139 }
2140
2141 for (size_t i = 0; i < expected_times.size(); ++i) {
2142 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
2143 kOffset - chrono::milliseconds(i));
2144 }
2145
2146 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
2147 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
2148}
2149
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002150// Tests that a phased loop responds correctly to a changing offset; sweep
2151// across a variety of potential offset changes, to ensure that we are
2152// exercising a variety of potential cases.
2153TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetSweep) {
2154 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2155 const int kCount = 5;
2156
2157 auto loop1 = MakePrimary();
2158
2159 std::vector<aos::monotonic_clock::duration> offset_options;
2160 for (int ii = 0; ii < kCount; ++ii) {
2161 offset_options.push_back(ii * kInterval / kCount);
2162 }
2163 std::vector<aos::monotonic_clock::duration> offset_sweep;
2164 // Run over all the pair-wise combinations of offsets.
2165 for (int ii = 0; ii < kCount; ++ii) {
2166 for (int jj = 0; jj < kCount; ++jj) {
2167 offset_sweep.push_back(offset_options.at(ii));
2168 offset_sweep.push_back(offset_options.at(jj));
2169 }
2170 }
2171
2172 std::vector<::aos::monotonic_clock::time_point> expected_times;
2173
2174 PhasedLoopHandler *phased_loop;
2175
2176 // Run kCount iterations.
2177 size_t counter = 0;
2178 phased_loop = loop1->AddPhasedLoop(
2179 [&phased_loop, &expected_times, &loop1, this, kInterval, &counter,
2180 offset_sweep](int count) {
2181 EXPECT_EQ(count, 1);
2182 expected_times.push_back(loop1->context().monotonic_event_time);
2183
2184 counter++;
2185
2186 if (counter == offset_sweep.size()) {
2187 LOG(INFO) << "Exiting";
2188 this->Exit();
2189 return;
2190 }
2191
2192 phased_loop->set_interval_and_offset(kInterval,
2193 offset_sweep.at(counter));
2194 },
2195 kInterval, offset_sweep.at(0));
2196
2197 Run();
2198 ASSERT_EQ(expected_times.size(), offset_sweep.size());
2199 for (size_t ii = 1; ii < expected_times.size(); ++ii) {
2200 EXPECT_LE(expected_times.at(ii) - expected_times.at(ii - 1), kInterval);
2201 }
2202}
2203
2204// Tests that a phased loop responds correctly to being rescheduled with now
2205// equal to a time in the past.
2206TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleInPast) {
2207 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2208 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2209
2210 auto loop1 = MakePrimary();
2211
2212 std::vector<::aos::monotonic_clock::time_point> expected_times;
2213
2214 PhasedLoopHandler *phased_loop;
2215
2216 int expected_count = 1;
2217
2218 // Set up a timer that will get run immediately after the phased loop and
2219 // which will attempt to reschedule the phased loop to just before now. This
2220 // should succeed, but will result in 0 cycles elapsing.
2221 TimerHandler *manager_timer =
2222 loop1->AddTimer([&phased_loop, &loop1, &expected_count, this]() {
2223 if (expected_count == 0) {
2224 LOG(INFO) << "Exiting";
2225 this->Exit();
2226 return;
2227 }
2228 phased_loop->Reschedule(loop1->context().monotonic_event_time -
2229 std::chrono::nanoseconds(1));
2230 expected_count = 0;
2231 });
2232
2233 phased_loop = loop1->AddPhasedLoop(
2234 [&expected_count, &expected_times, &loop1, manager_timer](int count) {
2235 EXPECT_EQ(count, expected_count);
2236 expected_times.push_back(loop1->context().monotonic_event_time);
2237
Philipp Schradera6712522023-07-05 20:25:11 -07002238 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002239 },
2240 kInterval, kOffset);
2241 phased_loop->set_name("Test loop");
2242 manager_timer->set_name("Manager timer");
2243
2244 Run();
2245
2246 ASSERT_EQ(2u, expected_times.size());
2247 ASSERT_EQ(expected_times[0], expected_times[1]);
2248}
2249
2250// Tests that a phased loop responds correctly to being rescheduled at the time
2251// when it should be triggering (it should kick the trigger to the next cycle).
2252TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleNow) {
2253 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2254 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2255
2256 auto loop1 = MakePrimary();
2257
2258 std::vector<::aos::monotonic_clock::time_point> expected_times;
2259
2260 PhasedLoopHandler *phased_loop;
2261
2262 bool should_exit = false;
2263 // Set up a timer that will get run immediately after the phased loop and
2264 // which will attempt to reschedule the phased loop to now. This should
2265 // succeed, but will result in no change to the expected behavior (since this
2266 // is the same thing that is actually done internally).
2267 TimerHandler *manager_timer =
2268 loop1->AddTimer([&phased_loop, &loop1, &should_exit, this]() {
2269 if (should_exit) {
2270 LOG(INFO) << "Exiting";
2271 this->Exit();
2272 return;
2273 }
2274 phased_loop->Reschedule(loop1->context().monotonic_event_time);
2275 should_exit = true;
2276 });
2277
2278 phased_loop = loop1->AddPhasedLoop(
2279 [&expected_times, &loop1, manager_timer](int count) {
2280 EXPECT_EQ(count, 1);
2281 expected_times.push_back(loop1->context().monotonic_event_time);
2282
Philipp Schradera6712522023-07-05 20:25:11 -07002283 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002284 },
2285 kInterval, kOffset);
2286 phased_loop->set_name("Test loop");
2287 manager_timer->set_name("Manager timer");
2288
2289 Run();
2290
2291 ASSERT_EQ(2u, expected_times.size());
2292 ASSERT_EQ(expected_times[0] + kInterval, expected_times[1]);
2293}
2294
2295// Tests that a phased loop responds correctly to being rescheduled at a time in
2296// the distant future.
2297TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleFuture) {
2298 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2299 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2300
2301 auto loop1 = MakePrimary();
2302
2303 std::vector<::aos::monotonic_clock::time_point> expected_times;
2304
2305 PhasedLoopHandler *phased_loop;
2306
2307 bool should_exit = false;
2308 int expected_count = 1;
2309 TimerHandler *manager_timer = loop1->AddTimer(
2310 [&expected_count, &phased_loop, &loop1, &should_exit, this, kInterval]() {
2311 if (should_exit) {
2312 LOG(INFO) << "Exiting";
2313 this->Exit();
2314 return;
2315 }
2316 expected_count = 10;
2317 // Knock off 1 ns, since the scheduler rounds up when it is
2318 // scheduled to exactly a loop time.
2319 phased_loop->Reschedule(loop1->context().monotonic_event_time +
2320 kInterval * expected_count -
2321 std::chrono::nanoseconds(1));
2322 should_exit = true;
2323 });
2324
2325 phased_loop = loop1->AddPhasedLoop(
2326 [&expected_times, &loop1, manager_timer, &expected_count](int count) {
2327 EXPECT_EQ(count, expected_count);
2328 expected_times.push_back(loop1->context().monotonic_event_time);
2329
Philipp Schradera6712522023-07-05 20:25:11 -07002330 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002331 },
2332 kInterval, kOffset);
2333 phased_loop->set_name("Test loop");
2334 manager_timer->set_name("Manager timer");
2335
2336 Run();
2337
2338 ASSERT_EQ(2u, expected_times.size());
2339 ASSERT_EQ(expected_times[0] + expected_count * kInterval, expected_times[1]);
2340}
2341
2342// Tests that a phased loop responds correctly to having its phase offset
2343// incremented and then being scheduled after a set time, exercising a pattern
2344// where a phased loop's offset is changed while trying to maintain the trigger
2345// at a consistent period.
2346TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleWithLaterOffset) {
2347 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2348 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2349
2350 auto loop1 = MakePrimary();
2351
2352 std::vector<::aos::monotonic_clock::time_point> expected_times;
2353
2354 PhasedLoopHandler *phased_loop;
2355
2356 bool should_exit = false;
2357 TimerHandler *manager_timer = loop1->AddTimer(
2358 [&phased_loop, &loop1, &should_exit, this, kInterval, kOffset]() {
2359 if (should_exit) {
2360 LOG(INFO) << "Exiting";
2361 this->Exit();
2362 return;
2363 }
2364 // Schedule the next callback to be strictly later than the current time
2365 // + interval / 2, to ensure a consistent frequency.
2366 monotonic_clock::time_point half_time =
2367 loop1->context().monotonic_event_time + kInterval / 2;
2368 phased_loop->set_interval_and_offset(
2369 kInterval, kOffset + std::chrono::nanoseconds(1), half_time);
2370 phased_loop->Reschedule(half_time);
2371 should_exit = true;
2372 });
2373
2374 phased_loop = loop1->AddPhasedLoop(
2375 [&expected_times, &loop1, manager_timer](int count) {
2376 EXPECT_EQ(1, count);
2377 expected_times.push_back(loop1->context().monotonic_event_time);
2378
Philipp Schradera6712522023-07-05 20:25:11 -07002379 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002380 },
2381 kInterval, kOffset);
2382 phased_loop->set_name("Test loop");
2383 manager_timer->set_name("Manager timer");
2384
2385 Run();
2386
2387 ASSERT_EQ(2u, expected_times.size());
2388 ASSERT_EQ(expected_times[0] + kInterval + std::chrono::nanoseconds(1),
2389 expected_times[1]);
2390}
2391
2392// Tests that a phased loop responds correctly to having its phase offset
2393// decremented and then being scheduled after a set time, exercising a pattern
2394// where a phased loop's offset is changed while trying to maintain the trigger
2395// at a consistent period.
2396TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleWithEarlierOffset) {
2397 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2398 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2399
2400 auto loop1 = MakePrimary();
2401
2402 std::vector<::aos::monotonic_clock::time_point> expected_times;
2403
2404 PhasedLoopHandler *phased_loop;
2405
2406 bool should_exit = false;
2407 TimerHandler *manager_timer = loop1->AddTimer(
2408 [&phased_loop, &loop1, &should_exit, this, kInterval, kOffset]() {
2409 if (should_exit) {
2410 LOG(INFO) << "Exiting";
2411 this->Exit();
2412 return;
2413 }
2414 // Schedule the next callback to be strictly later than the current time
2415 // + interval / 2, to ensure a consistent frequency.
2416 const aos::monotonic_clock::time_point half_time =
2417 loop1->context().monotonic_event_time + kInterval / 2;
2418 phased_loop->set_interval_and_offset(
2419 kInterval, kOffset - std::chrono::nanoseconds(1), half_time);
2420 phased_loop->Reschedule(half_time);
2421 should_exit = true;
2422 });
2423
2424 phased_loop = loop1->AddPhasedLoop(
2425 [&expected_times, &loop1, manager_timer](int count) {
2426 EXPECT_EQ(1, count);
2427 expected_times.push_back(loop1->context().monotonic_event_time);
2428
Philipp Schradera6712522023-07-05 20:25:11 -07002429 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002430 },
2431 kInterval, kOffset);
2432 phased_loop->set_name("Test loop");
2433 manager_timer->set_name("Manager timer");
2434
2435 Run();
2436
2437 ASSERT_EQ(2u, expected_times.size());
2438 ASSERT_EQ(expected_times[0] + kInterval - std::chrono::nanoseconds(1),
2439 expected_times[1]);
2440}
2441
Austin Schuh39788ff2019-12-01 18:22:57 -08002442// Tests that senders count correctly in the timing report.
2443TEST_P(AbstractEventLoopTest, SenderTimingReport) {
2444 FLAGS_timing_report_ms = 1000;
2445 auto loop1 = MakePrimary();
2446
2447 auto loop2 = Make("watcher_loop");
2448 loop2->MakeWatcher("/test", [](const TestMessage &) {});
2449
2450 auto loop3 = Make();
2451
2452 Fetcher<timing::Report> report_fetcher =
2453 loop3->MakeFetcher<timing::Report>("/aos");
2454 EXPECT_FALSE(report_fetcher.Fetch());
2455
2456 auto sender = loop1->MakeSender<TestMessage>("/test");
2457
James Kuszmaul78514332022-04-06 15:08:34 -07002458 // Sanity check channel frequencies to ensure that we've designed the test
2459 // correctly.
2460 ASSERT_EQ(800, sender.channel()->frequency());
Austin Schuhfff9c3a2023-06-16 18:48:23 -07002461 ASSERT_EQ(2000000000, configuration::ChannelStorageDuration(
2462 loop1->configuration(), sender.channel())
2463 .count());
James Kuszmaul78514332022-04-06 15:08:34 -07002464 constexpr int kMaxAllowedMessages = 800 * 2;
2465 constexpr int kSendMessages = kMaxAllowedMessages * 2;
2466 constexpr int kDroppedMessages = kSendMessages - kMaxAllowedMessages;
2467
Austin Schuh39788ff2019-12-01 18:22:57 -08002468 // Add a timer to actually quit.
2469 auto test_timer = loop1->AddTimer([&sender]() {
James Kuszmaul78514332022-04-06 15:08:34 -07002470 for (int i = 0; i < kSendMessages; ++i) {
Austin Schuh39788ff2019-12-01 18:22:57 -08002471 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2472 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2473 builder.add_value(200 + i);
James Kuszmaul78514332022-04-06 15:08:34 -07002474 if (i < kMaxAllowedMessages) {
2475 msg.CheckOk(msg.Send(builder.Finish()));
2476 } else {
2477 EXPECT_EQ(RawSender::Error::kMessagesSentTooFast,
2478 msg.Send(builder.Finish()));
2479 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002480 }
2481 });
2482
2483 // Quit after 1 timing report, mid way through the next cycle.
2484 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2485
2486 loop1->OnRun([&test_timer, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002487 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1500));
Austin Schuh39788ff2019-12-01 18:22:57 -08002488 });
2489
2490 Run();
2491
Austin Schuh6bae8252021-02-07 22:01:49 -08002492 if (do_timing_reports() == DoTimingReports::kYes) {
2493 // And, since we are here, check that the timing report makes sense.
2494 // Start by looking for our event loop's timing.
2495 FlatbufferDetachedBuffer<timing::Report> primary_report =
2496 FlatbufferDetachedBuffer<timing::Report>::Empty();
2497 while (report_fetcher.FetchNext()) {
Austin Schuh8902fa52021-03-14 22:39:24 -07002498 VLOG(1) << "Report " << FlatbufferToJson(report_fetcher.get());
Austin Schuh6bae8252021-02-07 22:01:49 -08002499 if (report_fetcher->name()->string_view() == "primary") {
2500 primary_report = CopyFlatBuffer(report_fetcher.get());
2501 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002502 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002503
Austin Schuh8902fa52021-03-14 22:39:24 -07002504 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
Austin Schuh6bae8252021-02-07 22:01:49 -08002505
2506 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2507
2508 ASSERT_NE(primary_report.message().senders(), nullptr);
2509 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2510
2511 // Confirm that the sender looks sane.
2512 EXPECT_EQ(
2513 loop1->configuration()
2514 ->channels()
2515 ->Get(primary_report.message().senders()->Get(0)->channel_index())
2516 ->name()
2517 ->string_view(),
2518 "/test");
James Kuszmaul78514332022-04-06 15:08:34 -07002519 EXPECT_EQ(primary_report.message().senders()->Get(0)->count(),
2520 kMaxAllowedMessages);
2521 ASSERT_TRUE(primary_report.message().senders()->Get(0)->has_error_counts());
2522 ASSERT_EQ(
2523 primary_report.message().senders()->Get(0)->error_counts()->size(), 2u);
2524 EXPECT_EQ(
2525 primary_report.message()
2526 .senders()
2527 ->Get(0)
2528 ->error_counts()
2529 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2530 ->count(),
2531 kDroppedMessages)
2532 << aos::FlatbufferToJson(primary_report);
2533 EXPECT_EQ(primary_report.message()
2534 .senders()
2535 ->Get(0)
2536 ->error_counts()
2537 ->Get(static_cast<size_t>(timing::SendError::INVALID_REDZONE))
2538 ->count(),
2539 0);
Austin Schuh6bae8252021-02-07 22:01:49 -08002540
2541 // Confirm that the timing primary_report sender looks sane.
2542 EXPECT_EQ(
2543 loop1->configuration()
2544 ->channels()
2545 ->Get(primary_report.message().senders()->Get(1)->channel_index())
2546 ->name()
2547 ->string_view(),
2548 "/aos");
2549 EXPECT_EQ(primary_report.message().senders()->Get(1)->count(), 1);
2550
2551 ASSERT_NE(primary_report.message().timers(), nullptr);
2552 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2553
2554 // Make sure there are no phased loops or watchers.
2555 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2556 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2557 } else {
2558 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002559 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002560}
2561
James Kuszmaul93abac12022-04-14 15:05:10 -07002562// Tests that the RawSender::Send(void*, size_t) overload tracks things properly
2563// in its timing report.
2564TEST_P(AbstractEventLoopTest, CopySenderTimingReport) {
2565 gflags::FlagSaver flag_saver;
2566 FLAGS_timing_report_ms = 1000;
2567 auto loop1 = Make();
2568 auto loop2 = MakePrimary();
2569
2570 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2571 JsonToFlatbuffer<TestMessage>("{}");
2572
2573 std::unique_ptr<aos::RawSender> sender =
2574 loop2->MakeRawSender(configuration::GetChannel(
2575 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
2576
2577 Fetcher<timing::Report> report_fetcher =
2578 loop1->MakeFetcher<timing::Report>("/aos");
2579 EXPECT_FALSE(report_fetcher.Fetch());
2580
2581 loop2->OnRun([&]() {
2582 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
2583 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2584 RawSender::Error::kOk);
2585 }
2586 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2587 RawSender::Error::kMessagesSentTooFast);
2588 });
2589 // Quit after 1 timing report, mid way through the next cycle.
2590 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
2591
2592 Run();
2593
2594 if (do_timing_reports() == DoTimingReports::kYes) {
2595 // Check that the sent too fast actually got recorded by the timing report.
2596 FlatbufferDetachedBuffer<timing::Report> primary_report =
2597 FlatbufferDetachedBuffer<timing::Report>::Empty();
2598 while (report_fetcher.FetchNext()) {
2599 if (report_fetcher->name()->string_view() == "primary") {
2600 primary_report = CopyFlatBuffer(report_fetcher.get());
2601 }
2602 }
2603
2604 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2605
2606 ASSERT_NE(primary_report.message().senders(), nullptr);
2607 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2608 EXPECT_EQ(
2609 primary_report.message()
2610 .senders()
2611 ->Get(0)
2612 ->error_counts()
2613 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2614 ->count(),
2615 1);
2616 }
2617}
2618
Austin Schuhe0ab4de2023-05-03 08:05:08 -07002619// Tests that the RawSender::Send(SharedSpan) overload works.
2620TEST_P(AbstractEventLoopTest, SharedSenderTimingReport) {
2621 gflags::FlagSaver flag_saver;
2622 FLAGS_timing_report_ms = 1000;
2623 auto loop1 = Make();
2624 auto loop2 = MakePrimary();
2625
2626 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2627 JsonToFlatbuffer<TestMessage>("{}");
2628
2629 std::unique_ptr<aos::RawSender> sender =
2630 loop2->MakeRawSender(configuration::GetChannel(
2631 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
2632
2633 Fetcher<timing::Report> report_fetcher =
2634 loop1->MakeFetcher<timing::Report>("/aos");
2635 EXPECT_FALSE(report_fetcher.Fetch());
2636
2637 loop2->OnRun([&]() {
2638 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
2639 auto shared_span = MakeSharedSpan(kMessage.span().size());
2640 memcpy(shared_span.second.data(), kMessage.span().data(),
2641 kMessage.span().size());
2642 EXPECT_EQ(sender->Send(std::move(shared_span.first)),
2643 RawSender::Error::kOk);
2644 }
2645 auto shared_span = MakeSharedSpan(kMessage.span().size());
2646 memcpy(shared_span.second.data(), kMessage.span().data(),
2647 kMessage.span().size());
2648 EXPECT_EQ(sender->Send(std::move(shared_span.first)),
2649 RawSender::Error::kMessagesSentTooFast);
2650 });
2651 // Quit after 1 timing report, mid way through the next cycle.
2652 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
2653
2654 Run();
2655
2656 if (do_timing_reports() == DoTimingReports::kYes) {
2657 // Check that the sent too fast actually got recorded by the timing report.
2658 FlatbufferDetachedBuffer<timing::Report> primary_report =
2659 FlatbufferDetachedBuffer<timing::Report>::Empty();
2660 while (report_fetcher.FetchNext()) {
2661 if (report_fetcher->name()->string_view() == "primary") {
2662 primary_report = CopyFlatBuffer(report_fetcher.get());
2663 }
2664 }
2665
2666 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2667
2668 ASSERT_NE(primary_report.message().senders(), nullptr);
2669 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2670 EXPECT_EQ(
2671 primary_report.message()
2672 .senders()
2673 ->Get(0)
2674 ->error_counts()
2675 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2676 ->count(),
2677 1);
2678 }
2679}
2680
Austin Schuh39788ff2019-12-01 18:22:57 -08002681// Tests that senders count correctly in the timing report.
2682TEST_P(AbstractEventLoopTest, WatcherTimingReport) {
2683 FLAGS_timing_report_ms = 1000;
2684 auto loop1 = MakePrimary();
2685 loop1->MakeWatcher("/test", [](const TestMessage &) {});
2686
2687 auto loop2 = Make("sender_loop");
2688
2689 auto loop3 = Make();
2690
2691 Fetcher<timing::Report> report_fetcher =
2692 loop3->MakeFetcher<timing::Report>("/aos");
2693 EXPECT_FALSE(report_fetcher.Fetch());
2694
2695 auto sender = loop2->MakeSender<TestMessage>("/test");
2696
2697 // Add a timer to actually quit.
2698 auto test_timer = loop1->AddTimer([&sender]() {
2699 for (int i = 0; i < 10; ++i) {
2700 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2701 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2702 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002703 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002704 }
2705 });
2706
2707 // Quit after 1 timing report, mid way through the next cycle.
2708 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2709
2710 loop1->OnRun([&test_timer, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002711 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1500));
Austin Schuh39788ff2019-12-01 18:22:57 -08002712 });
2713
2714 Run();
2715
Austin Schuh6bae8252021-02-07 22:01:49 -08002716 if (do_timing_reports() == DoTimingReports::kYes) {
2717 // And, since we are here, check that the timing report makes sense.
2718 // Start by looking for our event loop's timing.
2719 FlatbufferDetachedBuffer<timing::Report> primary_report =
2720 FlatbufferDetachedBuffer<timing::Report>::Empty();
2721 while (report_fetcher.FetchNext()) {
2722 LOG(INFO) << "Report " << FlatbufferToJson(report_fetcher.get());
2723 if (report_fetcher->name()->string_view() == "primary") {
2724 primary_report = CopyFlatBuffer(report_fetcher.get());
2725 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002726 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002727
2728 // Check the watcher report.
2729 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2730
2731 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2732
2733 // Just the timing report timer.
2734 ASSERT_NE(primary_report.message().timers(), nullptr);
2735 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2736
2737 // No phased loops
2738 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2739
2740 ASSERT_NE(primary_report.message().watchers(), nullptr);
2741 ASSERT_EQ(primary_report.message().watchers()->size(), 1);
2742 EXPECT_EQ(primary_report.message().watchers()->Get(0)->count(), 10);
2743 } else {
2744 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002745 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002746}
2747
2748// Tests that fetchers count correctly in the timing report.
2749TEST_P(AbstractEventLoopTest, FetcherTimingReport) {
2750 FLAGS_timing_report_ms = 1000;
2751 auto loop1 = MakePrimary();
2752 auto loop2 = Make("sender_loop");
2753
2754 auto loop3 = Make();
2755
2756 Fetcher<timing::Report> report_fetcher =
2757 loop3->MakeFetcher<timing::Report>("/aos");
2758 EXPECT_FALSE(report_fetcher.Fetch());
2759
2760 auto sender = loop2->MakeSender<TestMessage>("/test");
2761 auto fetcher1 = loop1->MakeFetcher<TestMessage>("/test");
2762 auto fetcher2 = loop1->MakeFetcher<TestMessage>("/test");
2763 fetcher1.Fetch();
2764 fetcher2.Fetch();
2765
2766 // Add a timer to actually quit.
2767 auto test_timer = loop1->AddTimer([&sender]() {
2768 for (int i = 0; i < 10; ++i) {
2769 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2770 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2771 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002772 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002773 }
2774 });
2775
2776 auto test_timer2 = loop1->AddTimer([&fetcher1, &fetcher2]() {
2777 fetcher1.Fetch();
2778 while (fetcher2.FetchNext()) {
2779 }
2780 });
2781
2782 // Quit after 1 timing report, mid way through the next cycle.
2783 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2784
2785 loop1->OnRun([test_timer, test_timer2, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002786 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1400));
2787 test_timer2->Schedule(loop1->monotonic_now() + chrono::milliseconds(1600));
Austin Schuh39788ff2019-12-01 18:22:57 -08002788 });
2789
2790 Run();
2791
Austin Schuh6bae8252021-02-07 22:01:49 -08002792 if (do_timing_reports() == DoTimingReports::kYes) {
2793 // And, since we are here, check that the timing report makes sense.
2794 // Start by looking for our event loop's timing.
2795 FlatbufferDetachedBuffer<timing::Report> primary_report =
2796 FlatbufferDetachedBuffer<timing::Report>::Empty();
2797 while (report_fetcher.FetchNext()) {
2798 if (report_fetcher->name()->string_view() == "primary") {
2799 primary_report = CopyFlatBuffer(report_fetcher.get());
2800 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002801 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002802
2803 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2804
2805 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2806
2807 ASSERT_NE(primary_report.message().senders(), nullptr);
2808 EXPECT_EQ(primary_report.message().senders()->size(), 2);
2809
2810 ASSERT_NE(primary_report.message().timers(), nullptr);
2811 EXPECT_EQ(primary_report.message().timers()->size(), 4);
2812
2813 // Make sure there are no phased loops or watchers.
2814 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2815 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2816
2817 // Now look at the fetchrs.
2818 ASSERT_NE(primary_report.message().fetchers(), nullptr);
2819 ASSERT_EQ(primary_report.message().fetchers()->size(), 2);
2820
2821 EXPECT_EQ(primary_report.message().fetchers()->Get(0)->count(), 1);
2822 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->average(),
2823 0.1);
2824 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->min(),
2825 0.1);
2826 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->max(),
2827 0.1);
2828 EXPECT_EQ(primary_report.message()
2829 .fetchers()
2830 ->Get(0)
2831 ->latency()
2832 ->standard_deviation(),
2833 0.0);
2834
2835 EXPECT_EQ(primary_report.message().fetchers()->Get(1)->count(), 10);
2836 } else {
2837 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002838 }
Austin Schuh52d325c2019-06-23 18:59:06 -07002839}
2840
Austin Schuh67420a42019-12-21 21:55:04 -08002841// Tests that a raw watcher and raw fetcher can receive messages from a raw
2842// sender without messing up offsets.
2843TEST_P(AbstractEventLoopTest, RawBasic) {
2844 auto loop1 = Make();
2845 auto loop2 = MakePrimary();
2846 auto loop3 = Make();
2847
Austin Schuha9df9ad2021-06-16 14:49:39 -07002848 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2849 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuh67420a42019-12-21 21:55:04 -08002850
2851 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002852 loop1->MakeRawSender(configuration::GetChannel(
2853 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08002854
2855 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002856 loop3->MakeRawFetcher(configuration::GetChannel(
2857 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08002858
Austin Schuha9df9ad2021-06-16 14:49:39 -07002859 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002860 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2861 RawSender::Error::kOk);
Austin Schuha9df9ad2021-06-16 14:49:39 -07002862 });
Austin Schuh67420a42019-12-21 21:55:04 -08002863
2864 bool happened = false;
2865 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08002866 configuration::GetChannel(loop2->configuration(), "/test",
2867 "aos.TestMessage", "", nullptr),
Austin Schuha9df9ad2021-06-16 14:49:39 -07002868 [this, &kMessage, &fetcher, &happened](const Context &context,
2869 const void *message) {
Austin Schuh67420a42019-12-21 21:55:04 -08002870 happened = true;
Austin Schuha9df9ad2021-06-16 14:49:39 -07002871 EXPECT_EQ(
2872 kMessage.span(),
2873 absl::Span<const uint8_t>(
2874 reinterpret_cast<const uint8_t *>(message), context.size));
2875 EXPECT_EQ(message, context.data);
Austin Schuh67420a42019-12-21 21:55:04 -08002876
2877 ASSERT_TRUE(fetcher->Fetch());
2878
Austin Schuha9df9ad2021-06-16 14:49:39 -07002879 EXPECT_EQ(kMessage.span(),
2880 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
2881 fetcher->context().data),
2882 fetcher->context().size));
Austin Schuh67420a42019-12-21 21:55:04 -08002883
2884 this->Exit();
2885 });
2886
2887 EXPECT_FALSE(happened);
2888 Run();
2889 EXPECT_TRUE(happened);
2890}
2891
Austin Schuhad154822019-12-27 15:45:13 -08002892// Tests that a raw watcher and raw fetcher can receive messages from a raw
Brian Silvermanbf889922021-11-10 12:41:57 -08002893// sender without messing up offsets, using the RawSpan overload.
2894TEST_P(AbstractEventLoopTest, RawBasicSharedSpan) {
2895 auto loop1 = Make();
2896 auto loop2 = MakePrimary();
2897 auto loop3 = Make();
2898
2899 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2900 JsonToFlatbuffer<TestMessage>("{}");
2901
2902 std::unique_ptr<aos::RawSender> sender =
2903 loop1->MakeRawSender(configuration::GetChannel(
2904 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
2905
2906 std::unique_ptr<aos::RawFetcher> fetcher =
2907 loop3->MakeRawFetcher(configuration::GetChannel(
2908 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
2909
2910 loop2->OnRun([&]() {
Austin Schuhe0ab4de2023-05-03 08:05:08 -07002911 auto shared_span = MakeSharedSpan(kMessage.span().size());
2912 memcpy(shared_span.second.data(), kMessage.span().data(),
2913 kMessage.span().size());
2914 sender->CheckOk(sender->Send(std::move(shared_span.first)));
Brian Silvermanbf889922021-11-10 12:41:57 -08002915 });
2916
2917 bool happened = false;
2918 loop2->MakeRawWatcher(
2919 configuration::GetChannel(loop2->configuration(), "/test",
2920 "aos.TestMessage", "", nullptr),
2921 [this, &kMessage, &fetcher, &happened](const Context &context,
2922 const void *message) {
2923 happened = true;
2924 EXPECT_EQ(
2925 kMessage.span(),
2926 absl::Span<const uint8_t>(
2927 reinterpret_cast<const uint8_t *>(message), context.size));
2928 EXPECT_EQ(message, context.data);
2929
2930 ASSERT_TRUE(fetcher->Fetch());
2931
2932 EXPECT_EQ(kMessage.span(),
2933 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
2934 fetcher->context().data),
2935 fetcher->context().size));
2936
2937 this->Exit();
2938 });
2939
2940 EXPECT_FALSE(happened);
2941 Run();
2942 EXPECT_TRUE(happened);
2943}
2944
2945// Tests that a raw watcher and raw fetcher can receive messages from a raw
Austin Schuhad154822019-12-27 15:45:13 -08002946// sender with remote times filled out.
2947TEST_P(AbstractEventLoopTest, RawRemoteTimes) {
2948 auto loop1 = Make();
2949 auto loop2 = MakePrimary();
2950 auto loop3 = Make();
2951
Austin Schuha9df9ad2021-06-16 14:49:39 -07002952 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2953 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08002954
2955 const aos::monotonic_clock::time_point monotonic_remote_time =
2956 aos::monotonic_clock::time_point(chrono::seconds(1501));
2957 const aos::realtime_clock::time_point realtime_remote_time =
2958 aos::realtime_clock::time_point(chrono::seconds(3132));
Austin Schuhb5c6f972021-03-14 21:53:07 -07002959 const uint32_t remote_queue_index = 0x254971;
Austin Schuha9012be2021-07-21 15:19:11 -07002960 const UUID source_boot_uuid = UUID::Random();
Austin Schuhad154822019-12-27 15:45:13 -08002961
2962 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002963 loop1->MakeRawSender(configuration::GetChannel(
2964 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08002965
2966 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002967 loop3->MakeRawFetcher(configuration::GetChannel(
2968 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08002969
2970 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002971 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size(),
2972 monotonic_remote_time, realtime_remote_time,
2973 remote_queue_index, source_boot_uuid),
2974 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08002975 });
2976
2977 bool happened = false;
2978 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08002979 configuration::GetChannel(loop2->configuration(), "/test",
2980 "aos.TestMessage", "", nullptr),
Austin Schuha9012be2021-07-21 15:19:11 -07002981 [this, monotonic_remote_time, realtime_remote_time, source_boot_uuid,
Austin Schuhb5c6f972021-03-14 21:53:07 -07002982 remote_queue_index, &fetcher,
2983 &happened](const Context &context, const void * /*message*/) {
Austin Schuhad154822019-12-27 15:45:13 -08002984 happened = true;
2985 EXPECT_EQ(monotonic_remote_time, context.monotonic_remote_time);
2986 EXPECT_EQ(realtime_remote_time, context.realtime_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002987 EXPECT_EQ(source_boot_uuid, context.source_boot_uuid);
Austin Schuhb5c6f972021-03-14 21:53:07 -07002988 EXPECT_EQ(remote_queue_index, context.remote_queue_index);
Austin Schuhad154822019-12-27 15:45:13 -08002989
2990 ASSERT_TRUE(fetcher->Fetch());
2991 EXPECT_EQ(monotonic_remote_time,
2992 fetcher->context().monotonic_remote_time);
2993 EXPECT_EQ(realtime_remote_time,
2994 fetcher->context().realtime_remote_time);
2995
2996 this->Exit();
2997 });
2998
2999 EXPECT_FALSE(happened);
3000 Run();
3001 EXPECT_TRUE(happened);
3002}
3003
3004// Tests that a raw sender fills out sent data.
3005TEST_P(AbstractEventLoopTest, RawSenderSentData) {
3006 auto loop1 = MakePrimary();
3007
Austin Schuha9df9ad2021-06-16 14:49:39 -07003008 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3009 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08003010
3011 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003012 loop1->MakeRawSender(configuration::GetChannel(
3013 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08003014
Tyler Chatow67ddb032020-01-12 14:30:04 -08003015 const aos::monotonic_clock::time_point monotonic_now = loop1->monotonic_now();
3016 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08003017
milind1f1dca32021-07-03 13:50:07 -07003018 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
3019 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08003020
3021 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
3022 EXPECT_LE(sender->monotonic_sent_time(),
3023 monotonic_now + chrono::milliseconds(100));
3024 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
3025 EXPECT_LE(sender->realtime_sent_time(),
3026 realtime_now + chrono::milliseconds(100));
3027 EXPECT_EQ(sender->sent_queue_index(), 0u);
3028
milind1f1dca32021-07-03 13:50:07 -07003029 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
3030 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08003031
3032 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
3033 EXPECT_LE(sender->monotonic_sent_time(),
3034 monotonic_now + chrono::milliseconds(100));
3035 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
3036 EXPECT_LE(sender->realtime_sent_time(),
3037 realtime_now + chrono::milliseconds(100));
3038 EXPECT_EQ(sender->sent_queue_index(), 1u);
3039}
3040
Austin Schuh217a9782019-12-21 23:02:50 -08003041// Tests that not setting up nodes results in no node.
3042TEST_P(AbstractEventLoopTest, NoNode) {
3043 auto loop1 = Make();
3044 auto loop2 = MakePrimary();
3045
3046 EXPECT_EQ(loop1->node(), nullptr);
3047 EXPECT_EQ(loop2->node(), nullptr);
3048}
3049
3050// Tests that setting up nodes results in node being set.
3051TEST_P(AbstractEventLoopTest, Node) {
3052 EnableNodes("me");
3053
3054 auto loop1 = Make();
3055 auto loop2 = MakePrimary();
3056
3057 EXPECT_NE(loop1->node(), nullptr);
3058 EXPECT_NE(loop2->node(), nullptr);
3059}
3060
3061// Tests that watchers work with a node setup.
3062TEST_P(AbstractEventLoopTest, NodeWatcher) {
3063 EnableNodes("me");
3064
3065 auto loop1 = Make();
3066 auto loop2 = Make();
3067 loop1->MakeWatcher("/test", [](const TestMessage &) {});
Tyler Chatow67ddb032020-01-12 14:30:04 -08003068 loop2->MakeRawWatcher(
3069 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
3070 nullptr),
3071 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08003072}
3073
Brian Silverman454bc112020-03-05 14:21:25 -08003074// Tests that no-arg watchers work with a node setup.
3075TEST_P(AbstractEventLoopTest, NodeNoArgWatcher) {
3076 EnableNodes("me");
3077
3078 auto loop1 = Make();
3079 auto loop2 = Make();
3080 loop1->MakeWatcher("/test", [](const TestMessage &) {});
3081 loop2->MakeRawNoArgWatcher(
3082 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
3083 nullptr),
3084 [](const Context &) {});
3085}
3086
Austin Schuh217a9782019-12-21 23:02:50 -08003087// Tests that fetcher work with a node setup.
3088TEST_P(AbstractEventLoopTest, NodeFetcher) {
3089 EnableNodes("me");
3090 auto loop1 = Make();
3091
3092 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
Tyler Chatow67ddb032020-01-12 14:30:04 -08003093 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
3094 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08003095}
3096
3097// Tests that sender work with a node setup.
3098TEST_P(AbstractEventLoopTest, NodeSender) {
3099 EnableNodes("me");
3100 auto loop1 = Make();
3101
3102 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
3103}
3104
Austin Schuhcc6070c2020-10-10 20:25:56 -07003105// Tests that a non-realtime event loop timer is marked non-realtime.
3106TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopTimer) {
3107 auto loop1 = MakePrimary();
3108
3109 // Add a timer to actually quit.
3110 auto test_timer = loop1->AddTimer([this]() {
3111 CheckNotRealtime();
3112 this->Exit();
3113 });
3114
3115 loop1->OnRun([&test_timer, &loop1]() {
3116 CheckNotRealtime();
Philipp Schradera6712522023-07-05 20:25:11 -07003117 test_timer->Schedule(loop1->monotonic_now(),
3118 ::std::chrono::milliseconds(100));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003119 });
3120
3121 Run();
3122}
3123
3124// Tests that a realtime event loop timer is marked realtime.
Austin Schuh9b1d6282022-06-10 17:03:21 -07003125TEST_P(AbstractEventLoopTest, RealtimeSend) {
3126 auto loop1 = MakePrimary();
3127
3128 loop1->SetRuntimeRealtimePriority(1);
3129
3130 auto sender = loop1->MakeSender<TestMessage>("/test2");
3131
3132 loop1->OnRun([&]() {
3133 CheckRealtime();
3134
3135 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3136 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
3137 builder.add_value(200);
3138 msg.CheckOk(msg.Send(builder.Finish()));
3139
3140 this->Exit();
3141 });
3142
3143 Run();
3144}
3145
3146// Tests that a realtime event loop timer is marked realtime.
Austin Schuhcc6070c2020-10-10 20:25:56 -07003147TEST_P(AbstractEventLoopTest, RealtimeEventLoopTimer) {
3148 auto loop1 = MakePrimary();
3149
3150 loop1->SetRuntimeRealtimePriority(1);
3151
3152 // Add a timer to actually quit.
3153 auto test_timer = loop1->AddTimer([this]() {
3154 CheckRealtime();
3155 this->Exit();
3156 });
3157
3158 loop1->OnRun([&test_timer, &loop1]() {
3159 CheckRealtime();
Philipp Schradera6712522023-07-05 20:25:11 -07003160 test_timer->Schedule(loop1->monotonic_now(),
3161 ::std::chrono::milliseconds(100));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003162 });
3163
3164 Run();
3165}
3166
3167// Tests that a non-realtime event loop phased loop is marked non-realtime.
3168TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopPhasedLoop) {
3169 auto loop1 = MakePrimary();
3170
3171 // Add a timer to actually quit.
3172 loop1->AddPhasedLoop(
3173 [this](int) {
3174 CheckNotRealtime();
3175 this->Exit();
3176 },
3177 chrono::seconds(1), chrono::seconds(0));
3178
3179 Run();
3180}
3181
3182// Tests that a realtime event loop phased loop is marked realtime.
3183TEST_P(AbstractEventLoopTest, RealtimeEventLoopPhasedLoop) {
3184 auto loop1 = MakePrimary();
3185
3186 loop1->SetRuntimeRealtimePriority(1);
3187
3188 // Add a timer to actually quit.
3189 loop1->AddPhasedLoop(
3190 [this](int) {
3191 CheckRealtime();
3192 this->Exit();
3193 },
3194 chrono::seconds(1), chrono::seconds(0));
3195
3196 Run();
3197}
3198
3199// Tests that a non-realtime event loop watcher is marked non-realtime.
3200TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopWatcher) {
3201 auto loop1 = MakePrimary();
3202 auto loop2 = Make();
3203
3204 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
3205
3206 loop1->OnRun([&]() {
3207 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3208 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07003209 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003210 });
3211
3212 loop1->MakeWatcher("/test", [&](const TestMessage &) {
3213 CheckNotRealtime();
3214 this->Exit();
3215 });
3216
3217 Run();
3218}
3219
3220// Tests that a realtime event loop watcher is marked realtime.
3221TEST_P(AbstractEventLoopTest, RealtimeEventLoopWatcher) {
3222 auto loop1 = MakePrimary();
3223 auto loop2 = Make();
3224
3225 loop1->SetRuntimeRealtimePriority(1);
3226
3227 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
3228
3229 loop1->OnRun([&]() {
3230 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3231 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07003232 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003233 });
3234
3235 loop1->MakeWatcher("/test", [&](const TestMessage &) {
3236 CheckRealtime();
3237 this->Exit();
3238 });
3239
3240 Run();
3241}
3242
Austin Schuha9012be2021-07-21 15:19:11 -07003243// Tests that event loop's context's monotonic time is set to a value on OnRun.
3244TEST_P(AbstractEventLoopTest, SetContextOnRun) {
3245 auto loop = MakePrimary();
3246
Austin Schuh0debde12022-08-17 16:25:17 -07003247 EXPECT_EQ(loop->context().monotonic_event_time, monotonic_clock::min_time);
3248 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3249 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3250 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3251 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3252 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
3253 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
3254 EXPECT_EQ(loop->context().size, 0u);
3255 EXPECT_EQ(loop->context().data, nullptr);
3256 EXPECT_EQ(loop->context().buffer_index, -1);
3257
Austin Schuha9012be2021-07-21 15:19:11 -07003258 // We want to check that monotonic event time is before monotonic now
3259 // called inside of callback, but after time point obtained callback.
3260 aos::monotonic_clock::time_point monotonic_event_time_on_run;
3261
3262 loop->OnRun([&]() {
3263 monotonic_event_time_on_run = loop->context().monotonic_event_time;
3264 EXPECT_LE(monotonic_event_time_on_run, loop->monotonic_now());
3265 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3266 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3267 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3268 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3269 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
Austin Schuh0debde12022-08-17 16:25:17 -07003270 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
Austin Schuha9012be2021-07-21 15:19:11 -07003271 EXPECT_EQ(loop->context().size, 0u);
3272 EXPECT_EQ(loop->context().data, nullptr);
3273 EXPECT_EQ(loop->context().buffer_index, -1);
3274 });
3275
3276 EndEventLoop(loop.get(), ::std::chrono::milliseconds(200));
3277
3278 const aos::monotonic_clock::time_point before_run_time =
3279 loop->monotonic_now();
3280 Run();
3281 EXPECT_GE(monotonic_event_time_on_run, before_run_time);
Austin Schuh0debde12022-08-17 16:25:17 -07003282
3283 EXPECT_EQ(loop->context().monotonic_event_time, monotonic_clock::min_time);
3284 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3285 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3286 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3287 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3288 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
3289 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
3290 EXPECT_EQ(loop->context().size, 0u);
3291 EXPECT_EQ(loop->context().data, nullptr);
3292 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuha9012be2021-07-21 15:19:11 -07003293}
3294
Austin Schuh217a9782019-12-21 23:02:50 -08003295// Tests that watchers fail when created on the wrong node.
3296TEST_P(AbstractEventLoopDeathTest, NodeWatcher) {
3297 EnableNodes("them");
3298
3299 auto loop1 = Make();
3300 auto loop2 = Make();
3301 EXPECT_DEATH({ loop1->MakeWatcher("/test", [](const TestMessage &) {}); },
3302 "node");
3303 EXPECT_DEATH(
3304 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08003305 loop2->MakeRawWatcher(
3306 configuration::GetChannel(configuration(), "/test",
3307 "aos.TestMessage", "", nullptr),
3308 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08003309 },
3310 "node");
Brian Silverman454bc112020-03-05 14:21:25 -08003311 EXPECT_DEATH({ loop1->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
3312 "node");
3313 EXPECT_DEATH(
3314 {
3315 loop2->MakeRawNoArgWatcher(
3316 configuration::GetChannel(configuration(), "/test",
3317 "aos.TestMessage", "", nullptr),
3318 [](const Context &) {});
3319 },
3320 "node");
Austin Schuh217a9782019-12-21 23:02:50 -08003321}
3322
3323// Tests that fetchers fail when created on the wrong node.
3324TEST_P(AbstractEventLoopDeathTest, NodeFetcher) {
3325 EnableNodes("them");
3326 auto loop1 = Make();
3327
3328 EXPECT_DEATH({ auto fetcher = loop1->MakeFetcher<TestMessage>("/test"); },
3329 "node");
3330 EXPECT_DEATH(
3331 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08003332 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
3333 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08003334 },
3335 "node");
3336}
3337
3338// Tests that senders fail when created on the wrong node.
3339TEST_P(AbstractEventLoopDeathTest, NodeSender) {
3340 EnableNodes("them");
3341 auto loop1 = Make();
3342
3343 EXPECT_DEATH(
3344 {
3345 aos::Sender<TestMessage> sender =
3346 loop1->MakeSender<TestMessage>("/test");
3347 },
3348 "node");
3349
3350 // Note: Creating raw senders is always supported. Right now, this lets us
3351 // use them to create message_gateway.
3352}
3353
Brian Silverman341b57e2020-06-23 16:23:18 -07003354// Tests creating multiple Builders from a single Sender at the same time.
3355TEST_P(AbstractEventLoopDeathTest, MultipleBuilders) {
3356 auto loop1 = Make();
3357 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
3358
3359 { auto builder = sender.MakeBuilder(); }
3360 {
3361 auto builder = sender.MakeBuilder();
3362 builder.MakeBuilder<TestMessage>().Finish();
3363 }
3364 {
3365 // Creating this after the first one was destroyed should be fine.
3366 auto builder = sender.MakeBuilder();
3367 builder.MakeBuilder<TestMessage>().Finish();
3368 // But not a second one.
3369 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
3370 "May not overwrite in-use allocator");
3371 }
3372
3373 FlatbufferDetachedBuffer<TestMessage> detached =
3374 flatbuffers::DetachedBuffer();
3375 {
3376 auto builder = sender.MakeBuilder();
3377 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
3378 }
3379 {
3380 // This is the second one, after the detached one, so it should fail.
3381 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
3382 "May not overwrite in-use allocator");
3383 }
3384
3385 // Clear the detached one, and then we should be able to create another.
3386 detached = flatbuffers::DetachedBuffer();
3387 {
3388 auto builder = sender.MakeBuilder();
3389 builder.MakeBuilder<TestMessage>().Finish();
3390 }
3391
3392 // And then detach another one.
3393 {
3394 auto builder = sender.MakeBuilder();
3395 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
3396 }
3397}
3398
3399// Tests sending a buffer detached from a different builder.
3400TEST_P(AbstractEventLoopDeathTest, WrongDetachedBuffer) {
3401 auto loop1 = Make();
3402 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
3403 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
3404
3405 auto builder = sender1.MakeBuilder();
3406 FlatbufferDetachedBuffer<TestMessage> detached =
3407 builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
milind1f1dca32021-07-03 13:50:07 -07003408 EXPECT_DEATH(sender2.CheckOk(sender2.SendDetached(std::move(detached))),
Brian Silverman341b57e2020-06-23 16:23:18 -07003409 "May only send the buffer detached from this Sender");
3410}
3411
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003412int TestChannelFrequency(EventLoop *event_loop) {
3413 return event_loop->GetChannel<TestMessage>("/test")->frequency();
3414}
3415
3416int TestChannelQueueSize(EventLoop *event_loop) {
Austin Schuhfff9c3a2023-06-16 18:48:23 -07003417 return configuration::QueueSize(event_loop->configuration(),
3418 event_loop->GetChannel<TestMessage>("/test"));
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003419}
3420
3421RawSender::Error SendTestMessage(aos::Sender<TestMessage> &sender) {
3422 aos::Sender<TestMessage>::Builder builder = sender.MakeBuilder();
3423 TestMessage::Builder test_message_builder =
3424 builder.MakeBuilder<TestMessage>();
3425 test_message_builder.add_value(0);
3426 return builder.Send(test_message_builder.Finish());
3427}
3428
3429// Test that sending messages too fast returns
3430// RawSender::Error::kMessagesSentTooFast.
3431TEST_P(AbstractEventLoopTest, SendingMessagesTooFast) {
3432 auto event_loop = MakePrimary();
3433
3434 auto sender = event_loop->MakeSender<TestMessage>("/test");
3435
3436 // Send one message in the beginning, then wait until the
3437 // channel_storage_duration is almost done and start sending messages rapidly,
3438 // having some come in the next chanel_storage_duration. The queue_size is
3439 // 1600, so the 1601st message will be the last valid one (the initial message
3440 // having being sent more than a channel_storage_duration ago), and trying to
3441 // send the 1602nd message should return
3442 // RawSender::Error::kMessagesSentTooFast.
3443 EXPECT_EQ(SendTestMessage(sender), RawSender::Error::kOk);
3444 int msgs_sent = 1;
3445 const int queue_size = TestChannelQueueSize(event_loop.get());
3446
3447 const auto timer = event_loop->AddTimer([&]() {
3448 const bool done = (msgs_sent == queue_size + 1);
3449 ASSERT_EQ(
3450 SendTestMessage(sender),
3451 done ? RawSender::Error::kMessagesSentTooFast : RawSender::Error::kOk);
3452 msgs_sent++;
3453 if (done) {
3454 Exit();
3455 }
3456 });
3457
3458 const auto kRepeatOffset = std::chrono::milliseconds(1);
Austin Schuhfff9c3a2023-06-16 18:48:23 -07003459 const auto base_offset = configuration::ChannelStorageDuration(
3460 event_loop->configuration(), sender.channel()) -
3461 (kRepeatOffset * (queue_size / 2));
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003462 event_loop->OnRun([&event_loop, &timer, &base_offset, &kRepeatOffset]() {
Philipp Schradera6712522023-07-05 20:25:11 -07003463 timer->Schedule(event_loop->monotonic_now() + base_offset, kRepeatOffset);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003464 });
3465
3466 Run();
3467}
3468
3469// Tests that we are able to send messages successfully after sending messages
3470// too fast and waiting while continuously attempting to send messages.
3471// Also tests that SendFailureCounter is working correctly in this
3472// situation
3473TEST_P(AbstractEventLoopTest, SendingAfterSendingTooFast) {
3474 auto event_loop = MakePrimary();
3475
3476 auto sender = event_loop->MakeSender<TestMessage>("/test");
3477
Austin Schuh0e96d372023-05-08 10:10:21 -07003478 // We are sending bunches of messages at 100 Hz, so we will be sending too
3479 // fast after queue_size (800) ms. After this, keep sending messages, and
3480 // exactly a channel storage duration (2s) after we send the first message we
3481 // should be able to successfully send a message.
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003482
Austin Schuh0e96d372023-05-08 10:10:21 -07003483 const std::chrono::milliseconds kInterval = std::chrono::milliseconds(10);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003484 const monotonic_clock::duration channel_storage_duration =
Austin Schuhfff9c3a2023-06-16 18:48:23 -07003485 configuration::ChannelStorageDuration(event_loop->configuration(),
3486 sender.channel());
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003487 const int queue_size = TestChannelQueueSize(event_loop.get());
3488
3489 int msgs_sent = 0;
3490 SendFailureCounter counter;
3491 auto start = monotonic_clock::min_time;
3492
3493 event_loop->AddPhasedLoop(
Austin Schuh0e96d372023-05-08 10:10:21 -07003494 [&](int elapsed_cycles) {
3495 // The queue is setup for 800 messages/sec. We want to fill that up at
3496 // a rate of 2000 messages/sec so we make sure we fill it up.
3497 for (int i = 0; i < 2 * kInterval.count() * elapsed_cycles; ++i) {
3498 const auto actual_err = SendTestMessage(sender);
3499 const bool done_waiting = (start != monotonic_clock::min_time &&
3500 sender.monotonic_sent_time() >=
3501 (start + channel_storage_duration));
3502 const auto expected_err =
3503 (msgs_sent < queue_size || done_waiting
3504 ? RawSender::Error::kOk
3505 : RawSender::Error::kMessagesSentTooFast);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003506
Austin Schuh0e96d372023-05-08 10:10:21 -07003507 if (start == monotonic_clock::min_time) {
3508 start = sender.monotonic_sent_time();
3509 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003510
Austin Schuh0e96d372023-05-08 10:10:21 -07003511 ASSERT_EQ(actual_err, expected_err);
3512 counter.Count(actual_err);
3513 msgs_sent++;
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003514
Austin Schuh0e96d372023-05-08 10:10:21 -07003515 EXPECT_EQ(counter.failures(),
3516 msgs_sent <= queue_size
3517 ? 0
3518 : (msgs_sent - queue_size) -
3519 (actual_err == RawSender::Error::kOk ? 1 : 0));
3520 EXPECT_EQ(counter.just_failed(), actual_err != RawSender::Error::kOk);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003521
Austin Schuh0e96d372023-05-08 10:10:21 -07003522 if (done_waiting) {
3523 Exit();
3524 return;
3525 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003526 }
3527 },
3528 kInterval);
3529 Run();
3530}
3531
3532// Tests that RawSender::Error::kMessagesSentTooFast is returned
3533// when messages are sent too fast from senders in different loops
3534TEST_P(AbstractEventLoopTest, SendingTooFastWithMultipleLoops) {
3535 auto loop1 = MakePrimary();
3536 auto loop2 = Make();
3537
3538 auto sender1 = loop1->MakeSender<TestMessage>("/test");
3539 auto sender2 = loop2->MakeSender<TestMessage>("/test");
3540
3541 // Send queue_size messages split between the senders.
3542 const int queue_size = TestChannelQueueSize(loop1.get());
3543 for (int i = 0; i < queue_size / 2; i++) {
3544 ASSERT_EQ(SendTestMessage(sender1), RawSender::Error::kOk);
3545 ASSERT_EQ(SendTestMessage(sender2), RawSender::Error::kOk);
3546 }
3547
3548 // Since queue_size messages have been sent, this should return an error
3549 EXPECT_EQ(SendTestMessage(sender2), RawSender::Error::kMessagesSentTooFast);
3550}
3551
Austin Schuhdda6db72023-06-21 17:02:34 -07003552// Tests that a longer storage durations store more messages.
3553TEST_P(AbstractEventLoopTest, SendingTooFastWithLongDuration) {
3554 auto loop1 = MakePrimary();
3555
3556 auto sender1 = loop1->MakeSender<TestMessage>("/test3");
3557
3558 // Send queue_size messages split between the senders.
3559 const int queue_size =
3560 configuration::QueueSize(loop1->configuration(), sender1.channel());
3561 EXPECT_EQ(queue_size, 100 * 10);
3562 for (int i = 0; i < queue_size; i++) {
3563 ASSERT_EQ(SendTestMessage(sender1), RawSender::Error::kOk);
3564 }
3565
3566 // Since queue_size messages have been sent, and little time has elapsed,
3567 // this should return an error.
3568 EXPECT_EQ(SendTestMessage(sender1), RawSender::Error::kMessagesSentTooFast);
3569}
3570
Parker Schuhe4a70d62017-12-27 20:10:20 -08003571} // namespace testing
3572} // namespace aos