blob: c8612843d17b447da760a3d08f6ad5c80afbee1e [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
James Kuszmaul762e8692023-07-31 14:57:53 -07001491// Test that setting a default version string results in it getting populated
1492// correctly.
1493TEST_P(AbstractEventLoopTest, DefaultVersionStringInTimingReport) {
1494 gflags::FlagSaver flag_saver;
1495 FLAGS_timing_report_ms = 1000;
1496
1497 EventLoop::SetDefaultVersionString("default_version_string");
1498
1499 auto loop = MakePrimary();
1500
1501 Fetcher<timing::Report> report_fetcher =
1502 loop->MakeFetcher<timing::Report>("/aos");
1503
1504 TimerHandler *exit_timer = loop->AddTimer([this]() { Exit(); });
1505 loop->OnRun([exit_timer, &loop, &report_fetcher]() {
1506 report_fetcher.Fetch();
1507 exit_timer->Schedule(loop->monotonic_now() + std::chrono::seconds(2));
1508 });
1509
1510 Run();
1511
1512 bool found_primary_report = false;
1513 while (report_fetcher.FetchNext()) {
1514 if (report_fetcher->name()->string_view() == "primary") {
1515 found_primary_report = true;
1516 EXPECT_EQ("default_version_string",
1517 report_fetcher->version()->string_view());
1518 } else {
1519 FAIL() << report_fetcher->name()->string_view();
1520 }
1521 }
1522
1523 if (do_timing_reports() == DoTimingReports::kYes) {
1524 EXPECT_TRUE(found_primary_report);
1525 } else {
1526 EXPECT_FALSE(found_primary_report);
1527 }
1528}
1529
1530// Test that overriding the default version string results in it getting
1531// populated correctly.
1532TEST_P(AbstractEventLoopTest, OverrideDersionStringInTimingReport) {
1533 gflags::FlagSaver flag_saver;
1534 FLAGS_timing_report_ms = 1000;
1535
1536 EventLoop::SetDefaultVersionString("default_version_string");
1537
1538 auto loop = MakePrimary();
1539 loop->SetVersionString("override_version");
1540
1541 Fetcher<timing::Report> report_fetcher =
1542 loop->MakeFetcher<timing::Report>("/aos");
1543
1544 TimerHandler *exit_timer = loop->AddTimer([this]() { Exit(); });
1545 loop->OnRun([exit_timer, &loop, &report_fetcher]() {
1546 report_fetcher.Fetch();
1547 exit_timer->Schedule(loop->monotonic_now() + std::chrono::seconds(2));
1548 });
1549
1550 Run();
1551
1552 bool found_primary_report = false;
1553 while (report_fetcher.FetchNext()) {
1554 if (report_fetcher->name()->string_view() == "primary") {
1555 found_primary_report = true;
1556 EXPECT_EQ("override_version", report_fetcher->version()->string_view());
1557 } else {
1558 FAIL() << report_fetcher->name()->string_view();
1559 }
1560 }
1561
1562 if (do_timing_reports() == DoTimingReports::kYes) {
1563 EXPECT_TRUE(found_primary_report);
1564 } else {
1565 EXPECT_FALSE(found_primary_report);
1566 }
1567}
1568
Neil Balch229001a2018-01-07 18:22:52 -08001569// Verify that we can change a timer's parameters during execution.
1570TEST_P(AbstractEventLoopTest, TimerChangeParameters) {
Austin Schuh44019f92019-05-19 19:58:27 -07001571 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001572 loop->SetRuntimeRealtimePriority(1);
Austin Schuh7f20f512021-01-31 17:56:16 -08001573 std::vector<monotonic_clock::time_point> iteration_list;
Neil Balch229001a2018-01-07 18:22:52 -08001574
1575 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001576 ScopedNotRealtime nrt;
Austin Schuh7f20f512021-01-31 17:56:16 -08001577 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001578 });
1579
Austin Schuh7f20f512021-01-31 17:56:16 -08001580 monotonic_clock::time_point s;
1581 auto modifier_timer = loop->AddTimer([&test_timer, &s]() {
Philipp Schradera6712522023-07-05 20:25:11 -07001582 test_timer->Schedule(s + chrono::milliseconds(1750),
1583 chrono::milliseconds(600));
Neil Balch229001a2018-01-07 18:22:52 -08001584 });
1585
Austin Schuh7f20f512021-01-31 17:56:16 -08001586 s = loop->monotonic_now();
Philipp Schradera6712522023-07-05 20:25:11 -07001587 test_timer->Schedule(s, chrono::milliseconds(500));
1588 modifier_timer->Schedule(s + chrono::milliseconds(1250));
Austin Schuhd892f102021-10-12 18:01:46 -07001589 EndEventLoop(loop.get(), chrono::milliseconds(3950));
Austin Schuh44019f92019-05-19 19:58:27 -07001590 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001591
Austin Schuhd892f102021-10-12 18:01:46 -07001592 EXPECT_THAT(
1593 iteration_list,
1594 ::testing::ElementsAre(
1595 s, s + chrono::milliseconds(500), s + chrono::milliseconds(1000),
1596 s + chrono::milliseconds(1750), s + chrono::milliseconds(2350),
1597 s + chrono::milliseconds(2950), s + chrono::milliseconds(3550)));
Neil Balch229001a2018-01-07 18:22:52 -08001598}
1599
1600// Verify that we can disable a timer during execution.
1601TEST_P(AbstractEventLoopTest, TimerDisable) {
Austin Schuh44019f92019-05-19 19:58:27 -07001602 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001603 loop->SetRuntimeRealtimePriority(1);
Neil Balch229001a2018-01-07 18:22:52 -08001604 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
1605
1606 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001607 ScopedNotRealtime nrt;
Austin Schuhd892f102021-10-12 18:01:46 -07001608 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001609 });
1610
Tyler Chatow67ddb032020-01-12 14:30:04 -08001611 auto ender_timer = loop->AddTimer([&test_timer]() { test_timer->Disable(); });
Neil Balch229001a2018-01-07 18:22:52 -08001612
Austin Schuhd892f102021-10-12 18:01:46 -07001613 monotonic_clock::time_point s = loop->monotonic_now();
Philipp Schradera6712522023-07-05 20:25:11 -07001614 test_timer->Schedule(s, ::std::chrono::milliseconds(500));
1615 ender_timer->Schedule(s + ::std::chrono::milliseconds(1250));
Austin Schuh73d99502021-12-08 12:05:39 -08001616 EndEventLoop(loop.get(), ::std::chrono::milliseconds(2000));
Austin Schuh44019f92019-05-19 19:58:27 -07001617 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001618
Austin Schuhd892f102021-10-12 18:01:46 -07001619 EXPECT_THAT(iteration_list,
Austin Schuh73d99502021-12-08 12:05:39 -08001620 ::testing::ElementsAre(s, s + chrono::milliseconds(500),
1621 s + chrono::milliseconds(1000)));
Neil Balch229001a2018-01-07 18:22:52 -08001622}
Austin Schuh7267c532019-05-19 19:55:53 -07001623
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001624// Verify that a timer can disable itself.
1625//
1626// TODO(Brian): Do something similar with phased loops, both with a quick
1627// handler and a handler that would miss a cycle except it got deferred. Current
1628// behavior doing that is a mess.
1629TEST_P(AbstractEventLoopTest, TimerDisableSelf) {
1630 auto loop = MakePrimary();
1631
1632 int count = 0;
1633 aos::TimerHandler *test_timer;
1634 test_timer = loop->AddTimer([&count, &test_timer]() {
1635 ++count;
1636 test_timer->Disable();
1637 });
1638
Philipp Schradera6712522023-07-05 20:25:11 -07001639 test_timer->Schedule(loop->monotonic_now(), ::std::chrono::milliseconds(20));
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001640 EndEventLoop(loop.get(), ::std::chrono::milliseconds(80));
1641 Run();
1642
1643 EXPECT_EQ(count, 1);
1644}
1645
Brian Silvermanbd405c02020-06-23 16:25:23 -07001646// Verify that we can disable a timer during execution of another timer
1647// scheduled for the same time, with one ordering of creation for the timers.
1648//
1649// Also schedule some more events to reshuffle the heap in EventLoop used for
1650// tracking events to change up the order. This used to segfault
1651// SimulatedEventLoop.
1652TEST_P(AbstractEventLoopTest, TimerDisableOther) {
1653 for (bool creation_order : {true, false}) {
1654 for (bool setup_order : {true, false}) {
1655 for (int shuffle_events = 0; shuffle_events < 5; ++shuffle_events) {
1656 auto loop = MakePrimary();
1657 aos::TimerHandler *test_timer, *ender_timer;
1658 if (creation_order) {
1659 test_timer = loop->AddTimer([]() {});
1660 ender_timer =
1661 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1662 } else {
1663 ender_timer =
1664 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1665 test_timer = loop->AddTimer([]() {});
1666 }
1667
1668 const auto start = loop->monotonic_now();
1669
1670 for (int i = 0; i < shuffle_events; ++i) {
Philipp Schradera6712522023-07-05 20:25:11 -07001671 loop->AddTimer([]() {})->Schedule(start +
1672 std::chrono::milliseconds(10));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001673 }
1674
1675 if (setup_order) {
Philipp Schradera6712522023-07-05 20:25:11 -07001676 test_timer->Schedule(start + ::std::chrono::milliseconds(20));
1677 ender_timer->Schedule(start + ::std::chrono::milliseconds(20));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001678 } else {
Philipp Schradera6712522023-07-05 20:25:11 -07001679 ender_timer->Schedule(start + ::std::chrono::milliseconds(20));
1680 test_timer->Schedule(start + ::std::chrono::milliseconds(20));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001681 }
1682 EndEventLoop(loop.get(), ::std::chrono::milliseconds(40));
1683 Run();
1684 }
1685 }
1686 }
1687}
1688
Austin Schuh54cf95f2019-11-29 13:14:18 -08001689// Verifies that the event loop implementations detect when Channel is not a
Brian Silverman631b6262021-11-10 12:25:08 -08001690// pointer into configuration(), or a name doesn't map to a channel in
1691// configuration().
Austin Schuh54cf95f2019-11-29 13:14:18 -08001692TEST_P(AbstractEventLoopDeathTest, InvalidChannel) {
1693 auto loop = MakePrimary();
1694
Tyler Chatow67ddb032020-01-12 14:30:04 -08001695 const Channel *channel = configuration::GetChannel(
1696 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
Austin Schuh54cf95f2019-11-29 13:14:18 -08001697
1698 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1699
1700 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001701 loop->MakeRawSender(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001702 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1703
1704 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001705 loop->MakeSender<TestMessage>("/testbad"),
1706 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1707 " not found in config");
1708
1709 EXPECT_FALSE(loop->TryMakeSender<TestMessage>("/testbad"));
1710
1711 EXPECT_DEATH(
1712 loop->MakeRawFetcher(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001713 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1714
1715 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001716 loop->MakeFetcher<TestMessage>("/testbad"),
1717 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1718 " not found in config");
1719
1720 EXPECT_FALSE(loop->TryMakeFetcher<TestMessage>("/testbad").valid());
1721
1722 EXPECT_DEATH(
Austin Schuh54cf95f2019-11-29 13:14:18 -08001723 {
1724 loop->MakeRawWatcher(&channel_copy.message(),
1725 [](const Context, const void *) {});
1726 },
1727 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
Brian Silverman631b6262021-11-10 12:25:08 -08001728
1729 EXPECT_DEATH(
1730 { loop->MakeWatcher("/testbad", [](const TestMessage &) {}); },
1731 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1732 " not found in config");
1733}
1734
1735// Verifies that the event loop handles a channel which is not readable or
1736// writable on the current node nicely.
1737TEST_P(AbstractEventLoopDeathTest, InaccessibleChannel) {
1738 EnableNodes("me");
1739 auto loop = MakePrimary("me");
1740 auto loop2 = Make("them");
1741
1742 const Channel *channel = configuration::GetChannel(
1743 loop->configuration(), "/test_noforward", "aos.TestMessage", "", nullptr);
1744
1745 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1746
1747 EXPECT_DEATH(
1748 loop2->MakeSender<TestMessage>("/test_forward"),
1749 "Channel"
1750 " \\{ \"name\": \"/test_forward\", \"type\": \"aos.TestMessage\" \\}"
1751 " is not able to be sent on this node");
1752
1753 EXPECT_FALSE(loop2->TryMakeSender<TestMessage>("/test_forward"));
1754
1755 EXPECT_DEATH(
1756 loop2->MakeRawFetcher(channel),
1757 "Channel"
1758 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1759 " is not able to be fetched on this node");
1760
1761 EXPECT_DEATH(
1762 loop2->MakeFetcher<TestMessage>("/test_noforward"),
1763 "Channel"
1764 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1765 " is not able to be fetched on this node");
1766
1767 EXPECT_FALSE(loop2->TryMakeFetcher<TestMessage>("/test_noforward").valid());
1768
1769 EXPECT_DEATH(
1770 { loop2->MakeRawWatcher(channel, [](const Context, const void *) {}); },
1771 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1772 "\"source_node\": \"them\" \\}"
1773 " is not able to be watched on this node");
1774
1775 EXPECT_DEATH(
1776 { loop2->MakeWatcher("/test_noforward", [](const TestMessage &) {}); },
1777 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1778 "\"source_node\": \"them\" \\}"
1779 " is not able to be watched on this node");
Austin Schuh54cf95f2019-11-29 13:14:18 -08001780}
1781
Austin Schuhd54780b2020-10-03 16:26:02 -07001782// Verifies that the event loop implementations detect when Channel has an
1783// invalid alignment.
1784TEST_P(AbstractEventLoopDeathTest, InvalidChannelAlignment) {
1785 const char *const kError = "multiple of alignment";
1786 InvalidChannelAlignment();
1787
1788 auto loop = MakePrimary();
1789
1790 const Channel *channel = configuration::GetChannel(
1791 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
1792
1793 EXPECT_DEATH({ loop->MakeRawSender(channel); }, kError);
1794 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); }, kError);
1795
1796 EXPECT_DEATH({ loop->MakeRawFetcher(channel); }, kError);
1797 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); }, kError);
1798
1799 EXPECT_DEATH(
1800 { loop->MakeRawWatcher(channel, [](const Context &, const void *) {}); },
1801 kError);
1802 EXPECT_DEATH({ loop->MakeRawNoArgWatcher(channel, [](const Context &) {}); },
1803 kError);
1804
1805 EXPECT_DEATH({ loop->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
1806 kError);
1807 EXPECT_DEATH({ loop->MakeWatcher("/test", [](const TestMessage &) {}); },
1808 kError);
1809}
1810
Brian Silverman454bc112020-03-05 14:21:25 -08001811// Verify that the send time on a message is roughly right when using a watcher.
Austin Schuh7267c532019-05-19 19:55:53 -07001812TEST_P(AbstractEventLoopTest, MessageSendTime) {
Austin Schuh44019f92019-05-19 19:58:27 -07001813 auto loop1 = MakePrimary();
Austin Schuh7267c532019-05-19 19:55:53 -07001814 auto loop2 = Make();
Austin Schuhad154822019-12-27 15:45:13 -08001815 auto sender = loop2->MakeSender<TestMessage>("/test");
Austin Schuh7267c532019-05-19 19:55:53 -07001816 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
1817
1818 auto test_timer = loop1->AddTimer([&sender]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001819 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1820 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1821 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001822 msg.CheckOk(msg.Send(builder.Finish()));
Alex Perrycb7da4b2019-08-28 19:35:56 -07001823 });
1824
Austin Schuhad154822019-12-27 15:45:13 -08001825 bool triggered = false;
Brian Silverman454bc112020-03-05 14:21:25 -08001826 loop1->MakeWatcher("/test", [&](const TestMessage &msg) {
Austin Schuhad154822019-12-27 15:45:13 -08001827 // Confirm that the data pointer makes sense from a watcher, and all the
1828 // timestamps look right.
1829 EXPECT_GT(&msg, loop1->context().data);
1830 EXPECT_EQ(loop1->context().monotonic_remote_time,
1831 loop1->context().monotonic_event_time);
1832 EXPECT_EQ(loop1->context().realtime_remote_time,
1833 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001834 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001835
1836 const aos::monotonic_clock::time_point monotonic_now =
1837 loop1->monotonic_now();
Tyler Chatow67ddb032020-01-12 14:30:04 -08001838 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08001839
1840 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1841 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1842 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1843 monotonic_now);
1844 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1845 realtime_now);
1846
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001847 EXPECT_LT(&msg, reinterpret_cast<const void *>(
1848 reinterpret_cast<const char *>(loop1->context().data) +
Austin Schuhad154822019-12-27 15:45:13 -08001849 loop1->context().size));
Brian Silverman4f4e0612020-08-12 19:54:41 -07001850 if (read_method() == ReadMethod::PIN) {
1851 EXPECT_GE(loop1->context().buffer_index, 0);
1852 EXPECT_LT(loop1->context().buffer_index,
1853 loop1->NumberBuffers(
1854 configuration::GetChannel(loop1->configuration(), "/test",
1855 "aos.TestMessage", "", nullptr)));
1856 } else {
1857 EXPECT_EQ(-1, loop1->context().buffer_index);
1858 }
Austin Schuhad154822019-12-27 15:45:13 -08001859 triggered = true;
Austin Schuh7267c532019-05-19 19:55:53 -07001860 });
1861
Philipp Schradera6712522023-07-05 20:25:11 -07001862 test_timer->Schedule(loop1->monotonic_now() + ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07001863
1864 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
Austin Schuh44019f92019-05-19 19:58:27 -07001865 Run();
Austin Schuh7267c532019-05-19 19:55:53 -07001866
Austin Schuhad154822019-12-27 15:45:13 -08001867 EXPECT_TRUE(triggered);
1868
Brian Silverman454bc112020-03-05 14:21:25 -08001869 ASSERT_TRUE(fetcher.Fetch());
1870
1871 monotonic_clock::duration monotonic_time_offset =
1872 fetcher.context().monotonic_event_time -
1873 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1874 realtime_clock::duration realtime_time_offset =
1875 fetcher.context().realtime_event_time -
1876 (loop1->realtime_now() - ::std::chrono::seconds(1));
1877
1878 EXPECT_EQ(fetcher.context().realtime_event_time,
1879 fetcher.context().realtime_remote_time);
1880 EXPECT_EQ(fetcher.context().monotonic_event_time,
1881 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001882 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001883
1884 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1885 << ": Got "
1886 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1887 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1888 // Confirm that the data pointer makes sense.
1889 EXPECT_GT(fetcher.get(), fetcher.context().data);
1890 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001891 reinterpret_cast<const void *>(
1892 reinterpret_cast<const char *>(fetcher.context().data) +
Brian Silverman454bc112020-03-05 14:21:25 -08001893 fetcher.context().size));
1894 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1895 << ": Got "
1896 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1897 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1898
1899 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1900 << ": Got "
1901 << fetcher.context().realtime_event_time.time_since_epoch().count()
1902 << " expected " << loop1->realtime_now().time_since_epoch().count();
1903 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1904 << ": Got "
1905 << fetcher.context().realtime_event_time.time_since_epoch().count()
1906 << " expected " << loop1->realtime_now().time_since_epoch().count();
1907}
1908
1909// Verify that the send time on a message is roughly right when using a no-arg
1910// watcher. To get a message, we need to use a fetcher to actually access the
1911// message. This is also the main use case for no-arg fetchers.
1912TEST_P(AbstractEventLoopTest, MessageSendTimeNoArg) {
1913 auto loop1 = MakePrimary();
1914 auto loop2 = Make();
1915 auto sender = loop2->MakeSender<TestMessage>("/test");
1916 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
1917
1918 auto test_timer = loop1->AddTimer([&sender]() {
1919 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1920 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1921 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001922 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -08001923 });
1924
1925 bool triggered = false;
1926 loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {
1927 // Confirm that we can indeed use a fetcher on this channel from this
1928 // context, and it results in a sane data pointer and timestamps.
1929 ASSERT_TRUE(fetcher.Fetch());
1930
1931 EXPECT_EQ(loop1->context().monotonic_remote_time,
1932 loop1->context().monotonic_event_time);
1933 EXPECT_EQ(loop1->context().realtime_remote_time,
1934 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001935 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001936
1937 const aos::monotonic_clock::time_point monotonic_now =
1938 loop1->monotonic_now();
1939 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
1940
1941 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1942 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1943 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1944 monotonic_now);
1945 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1946 realtime_now);
1947
1948 triggered = true;
1949 });
1950
Philipp Schradera6712522023-07-05 20:25:11 -07001951 test_timer->Schedule(loop1->monotonic_now() + ::std::chrono::seconds(1));
Brian Silverman454bc112020-03-05 14:21:25 -08001952
1953 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
1954 Run();
1955
1956 ASSERT_TRUE(triggered);
Austin Schuh7267c532019-05-19 19:55:53 -07001957
Alex Perrycb7da4b2019-08-28 19:35:56 -07001958 monotonic_clock::duration monotonic_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001959 fetcher.context().monotonic_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001960 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1961 realtime_clock::duration realtime_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001962 fetcher.context().realtime_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001963 (loop1->realtime_now() - ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07001964
Austin Schuhad154822019-12-27 15:45:13 -08001965 EXPECT_EQ(fetcher.context().realtime_event_time,
1966 fetcher.context().realtime_remote_time);
1967 EXPECT_EQ(fetcher.context().monotonic_event_time,
1968 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001969 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001970
Alex Perrycb7da4b2019-08-28 19:35:56 -07001971 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1972 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001973 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh52d325c2019-06-23 18:59:06 -07001974 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07001975 // Confirm that the data pointer makes sense.
1976 EXPECT_GT(fetcher.get(), fetcher.context().data);
1977 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001978 reinterpret_cast<const void *>(
1979 reinterpret_cast<const char *>(fetcher.context().data) +
Alex Perrycb7da4b2019-08-28 19:35:56 -07001980 fetcher.context().size));
1981 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1982 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001983 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh7267c532019-05-19 19:55:53 -07001984 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07001985
1986 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1987 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001988 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07001989 << " expected " << loop1->realtime_now().time_since_epoch().count();
1990 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1991 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001992 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07001993 << " expected " << loop1->realtime_now().time_since_epoch().count();
Austin Schuh7267c532019-05-19 19:55:53 -07001994}
1995
Austin Schuh52d325c2019-06-23 18:59:06 -07001996// Tests that a couple phased loops run in a row result in the correct offset
1997// and period.
1998TEST_P(AbstractEventLoopTest, PhasedLoopTest) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001999 // Force a slower rate so we are guaranteed to have reports for our phased
Austin Schuh39788ff2019-12-01 18:22:57 -08002000 // loop.
2001 FLAGS_timing_report_ms = 2000;
2002
Austin Schuh52d325c2019-06-23 18:59:06 -07002003 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2004 const int kCount = 5;
2005
2006 auto loop1 = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08002007 auto loop2 = Make();
2008
2009 Fetcher<timing::Report> report_fetcher =
2010 loop2->MakeFetcher<timing::Report>("/aos");
2011 EXPECT_FALSE(report_fetcher.Fetch());
Austin Schuh52d325c2019-06-23 18:59:06 -07002012
2013 // Collect up a couple of samples.
2014 ::std::vector<::aos::monotonic_clock::time_point> times;
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002015 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
Austin Schuh52d325c2019-06-23 18:59:06 -07002016
2017 // Run kCount iterations.
Austin Schuh39788ff2019-12-01 18:22:57 -08002018 loop1
2019 ->AddPhasedLoop(
2020 [&times, &expected_times, &loop1, this](int count) {
2021 EXPECT_EQ(count, 1);
2022 times.push_back(loop1->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08002023 expected_times.push_back(loop1->context().monotonic_event_time);
Austin Schuh39788ff2019-12-01 18:22:57 -08002024
Austin Schuhad154822019-12-27 15:45:13 -08002025 EXPECT_EQ(loop1->context().monotonic_remote_time,
2026 monotonic_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002027 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08002028 EXPECT_EQ(loop1->context().realtime_event_time,
2029 realtime_clock::min_time);
2030 EXPECT_EQ(loop1->context().realtime_remote_time,
Austin Schuh39788ff2019-12-01 18:22:57 -08002031 realtime_clock::min_time);
2032 EXPECT_EQ(loop1->context().queue_index, 0xffffffffu);
2033 EXPECT_EQ(loop1->context().size, 0u);
2034 EXPECT_EQ(loop1->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07002035 EXPECT_EQ(loop1->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08002036
2037 if (times.size() == kCount) {
2038 LOG(INFO) << "Exiting";
2039 this->Exit();
2040 }
2041 },
2042 chrono::seconds(1), kOffset)
2043 ->set_name("Test loop");
Austin Schuh52d325c2019-06-23 18:59:06 -07002044
2045 // Add a delay to make sure that delay during startup doesn't result in a
2046 // "missed cycle".
2047 SleepFor(chrono::seconds(2));
2048
2049 Run();
2050
2051 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07002052 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
2053 ASSERT_EQ(times.size(), expected_times.size());
2054 ASSERT_EQ((times.size() % 2), 1);
Austin Schuh52d325c2019-06-23 18:59:06 -07002055
2056 // Grab the middle sample.
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002057 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
Austin Schuh52d325c2019-06-23 18:59:06 -07002058
2059 // Add up all the delays of all the times.
2060 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
2061 for (const ::aos::monotonic_clock::time_point time : times) {
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002062 sum += time - average_time;
Austin Schuh52d325c2019-06-23 18:59:06 -07002063 }
2064
2065 // Average and add to the middle to find the average time.
2066 sum /= times.size();
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002067 average_time += sum;
Austin Schuh52d325c2019-06-23 18:59:06 -07002068
2069 // Compute the offset from the start of the second of the average time. This
2070 // should be pretty close to the offset.
2071 const ::aos::monotonic_clock::duration remainder =
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002072 average_time.time_since_epoch() -
2073 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
Austin Schuh52d325c2019-06-23 18:59:06 -07002074
2075 const chrono::milliseconds kEpsilon(100);
2076 EXPECT_LT(remainder, kOffset + kEpsilon);
2077 EXPECT_GT(remainder, kOffset - kEpsilon);
2078
2079 // Make sure that the average duration is close to 1 second.
2080 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
2081 times.front())
2082 .count() /
2083 static_cast<double>(times.size() - 1),
2084 1.0, 0.1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002085
2086 // Confirm that the ideal wakeup times increment correctly.
2087 for (size_t i = 1; i < expected_times.size(); ++i) {
2088 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
2089 }
2090
2091 for (size_t i = 0; i < expected_times.size(); ++i) {
2092 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
2093 kOffset);
2094 }
2095
2096 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
2097 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08002098
Austin Schuh6bae8252021-02-07 22:01:49 -08002099 if (do_timing_reports() == DoTimingReports::kYes) {
2100 // And, since we are here, check that the timing report makes sense.
2101 // Start by looking for our event loop's timing.
2102 FlatbufferDetachedBuffer<timing::Report> report =
2103 FlatbufferDetachedBuffer<timing::Report>::Empty();
2104 while (report_fetcher.FetchNext()) {
2105 if (report_fetcher->name()->string_view() == "primary") {
2106 report = CopyFlatBuffer(report_fetcher.get());
2107 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002108 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002109
2110 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
2111
2112 EXPECT_EQ(report.message().name()->string_view(), "primary");
2113
2114 ASSERT_NE(report.message().senders(), nullptr);
2115 EXPECT_EQ(report.message().senders()->size(), 2);
2116
2117 ASSERT_NE(report.message().timers(), nullptr);
2118 EXPECT_EQ(report.message().timers()->size(), 1);
2119
2120 // Make sure there is a single phased loop report with our report in it.
2121 ASSERT_NE(report.message().phased_loops(), nullptr);
2122 ASSERT_EQ(report.message().phased_loops()->size(), 1);
2123 EXPECT_EQ(report.message().phased_loops()->Get(0)->name()->string_view(),
2124 "Test loop");
2125 EXPECT_GE(report.message().phased_loops()->Get(0)->count(), 1);
2126 } else {
2127 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002128 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002129}
2130
Milind Upadhyay42589bb2021-05-19 20:05:16 -07002131// Tests that a phased loop responds correctly to a changing offset.
2132TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetTest) {
2133 // Force a slower rate so we are guaranteed to have reports for our phased
2134 // loop.
2135 FLAGS_timing_report_ms = 2000;
2136
2137 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2138 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2139 const int kCount = 5;
2140
2141 auto loop1 = MakePrimary();
2142
2143 // Collect up a couple of samples.
2144 ::std::vector<::aos::monotonic_clock::time_point> times;
2145 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
2146
2147 PhasedLoopHandler *phased_loop;
2148
2149 // Run kCount iterations.
2150 phased_loop = loop1->AddPhasedLoop(
2151 [&phased_loop, &times, &expected_times, &loop1, this, kOffset,
2152 kInterval](int count) {
2153 EXPECT_EQ(count, 1);
2154 times.push_back(loop1->monotonic_now());
2155
2156 expected_times.push_back(loop1->context().monotonic_event_time);
2157
2158 phased_loop->set_interval_and_offset(
2159 kInterval, kOffset - chrono::milliseconds(times.size()));
2160 LOG(INFO) << "new offset: "
2161 << (kOffset - chrono::milliseconds(times.size())).count();
2162
2163 if (times.size() == kCount) {
2164 LOG(INFO) << "Exiting";
2165 this->Exit();
2166 }
2167 },
2168 kInterval, kOffset);
2169 phased_loop->set_name("Test loop");
2170
2171 // Add a delay to make sure that delay during startup doesn't result in a
2172 // "missed cycle".
2173 SleepFor(chrono::seconds(2));
2174
2175 Run();
2176 // Confirm that we got both the right number of samples, and it's odd.
2177 EXPECT_EQ(times.size(), static_cast<size_t>(kCount));
2178 EXPECT_EQ(times.size(), expected_times.size());
2179 EXPECT_EQ((times.size() % 2), 1);
2180
2181 // Grab the middle sample.
2182 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
2183
2184 // Add up all the delays of all the times.
2185 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
2186 for (const ::aos::monotonic_clock::time_point time : times) {
2187 sum += time - average_time;
2188 }
2189
2190 // Average and add to the middle to find the average time.
2191 sum /= times.size();
2192 average_time += sum;
2193
2194 // Compute the offset from the start of the second of the average time. This
2195 // should be pretty close to the offset.
2196 const ::aos::monotonic_clock::duration remainder =
2197 average_time.time_since_epoch() -
2198 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
2199
2200 const chrono::milliseconds kEpsilon(100);
2201 EXPECT_LT(remainder, kOffset + kEpsilon);
2202 EXPECT_GT(remainder, kOffset - kEpsilon);
2203
2204 // Make sure that the average duration is close to 1 second.
2205 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
2206 times.front())
2207 .count() /
2208 static_cast<double>(times.size() - 1),
2209 1.0, 0.1);
2210
2211 // Confirm that the ideal wakeup times increment correctly.
2212 for (size_t i = 1; i < expected_times.size(); ++i) {
2213 LOG(INFO) << i - 1 << ": " << expected_times[i - 1] << ", " << i << ": "
2214 << expected_times[i];
2215 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1) -
2216 chrono::milliseconds(1));
2217 }
2218
2219 for (size_t i = 0; i < expected_times.size(); ++i) {
2220 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
2221 kOffset - chrono::milliseconds(i));
2222 }
2223
2224 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
2225 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
2226}
2227
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002228// Tests that a phased loop responds correctly to a changing offset; sweep
2229// across a variety of potential offset changes, to ensure that we are
2230// exercising a variety of potential cases.
2231TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetSweep) {
2232 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2233 const int kCount = 5;
2234
2235 auto loop1 = MakePrimary();
2236
2237 std::vector<aos::monotonic_clock::duration> offset_options;
2238 for (int ii = 0; ii < kCount; ++ii) {
2239 offset_options.push_back(ii * kInterval / kCount);
2240 }
2241 std::vector<aos::monotonic_clock::duration> offset_sweep;
2242 // Run over all the pair-wise combinations of offsets.
2243 for (int ii = 0; ii < kCount; ++ii) {
2244 for (int jj = 0; jj < kCount; ++jj) {
2245 offset_sweep.push_back(offset_options.at(ii));
2246 offset_sweep.push_back(offset_options.at(jj));
2247 }
2248 }
2249
2250 std::vector<::aos::monotonic_clock::time_point> expected_times;
2251
2252 PhasedLoopHandler *phased_loop;
2253
2254 // Run kCount iterations.
2255 size_t counter = 0;
2256 phased_loop = loop1->AddPhasedLoop(
2257 [&phased_loop, &expected_times, &loop1, this, kInterval, &counter,
2258 offset_sweep](int count) {
2259 EXPECT_EQ(count, 1);
2260 expected_times.push_back(loop1->context().monotonic_event_time);
2261
2262 counter++;
2263
2264 if (counter == offset_sweep.size()) {
2265 LOG(INFO) << "Exiting";
2266 this->Exit();
2267 return;
2268 }
2269
2270 phased_loop->set_interval_and_offset(kInterval,
2271 offset_sweep.at(counter));
2272 },
2273 kInterval, offset_sweep.at(0));
2274
2275 Run();
2276 ASSERT_EQ(expected_times.size(), offset_sweep.size());
2277 for (size_t ii = 1; ii < expected_times.size(); ++ii) {
2278 EXPECT_LE(expected_times.at(ii) - expected_times.at(ii - 1), kInterval);
2279 }
2280}
2281
2282// Tests that a phased loop responds correctly to being rescheduled with now
2283// equal to a time in the past.
2284TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleInPast) {
2285 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2286 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2287
2288 auto loop1 = MakePrimary();
2289
2290 std::vector<::aos::monotonic_clock::time_point> expected_times;
2291
2292 PhasedLoopHandler *phased_loop;
2293
2294 int expected_count = 1;
2295
2296 // Set up a timer that will get run immediately after the phased loop and
2297 // which will attempt to reschedule the phased loop to just before now. This
2298 // should succeed, but will result in 0 cycles elapsing.
2299 TimerHandler *manager_timer =
2300 loop1->AddTimer([&phased_loop, &loop1, &expected_count, this]() {
2301 if (expected_count == 0) {
2302 LOG(INFO) << "Exiting";
2303 this->Exit();
2304 return;
2305 }
2306 phased_loop->Reschedule(loop1->context().monotonic_event_time -
2307 std::chrono::nanoseconds(1));
2308 expected_count = 0;
2309 });
2310
2311 phased_loop = loop1->AddPhasedLoop(
2312 [&expected_count, &expected_times, &loop1, manager_timer](int count) {
2313 EXPECT_EQ(count, expected_count);
2314 expected_times.push_back(loop1->context().monotonic_event_time);
2315
Philipp Schradera6712522023-07-05 20:25:11 -07002316 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002317 },
2318 kInterval, kOffset);
2319 phased_loop->set_name("Test loop");
2320 manager_timer->set_name("Manager timer");
2321
2322 Run();
2323
2324 ASSERT_EQ(2u, expected_times.size());
2325 ASSERT_EQ(expected_times[0], expected_times[1]);
2326}
2327
2328// Tests that a phased loop responds correctly to being rescheduled at the time
2329// when it should be triggering (it should kick the trigger to the next cycle).
2330TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleNow) {
2331 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2332 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2333
2334 auto loop1 = MakePrimary();
2335
2336 std::vector<::aos::monotonic_clock::time_point> expected_times;
2337
2338 PhasedLoopHandler *phased_loop;
2339
2340 bool should_exit = false;
2341 // Set up a timer that will get run immediately after the phased loop and
2342 // which will attempt to reschedule the phased loop to now. This should
2343 // succeed, but will result in no change to the expected behavior (since this
2344 // is the same thing that is actually done internally).
2345 TimerHandler *manager_timer =
2346 loop1->AddTimer([&phased_loop, &loop1, &should_exit, this]() {
2347 if (should_exit) {
2348 LOG(INFO) << "Exiting";
2349 this->Exit();
2350 return;
2351 }
2352 phased_loop->Reschedule(loop1->context().monotonic_event_time);
2353 should_exit = true;
2354 });
2355
2356 phased_loop = loop1->AddPhasedLoop(
2357 [&expected_times, &loop1, manager_timer](int count) {
2358 EXPECT_EQ(count, 1);
2359 expected_times.push_back(loop1->context().monotonic_event_time);
2360
Philipp Schradera6712522023-07-05 20:25:11 -07002361 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002362 },
2363 kInterval, kOffset);
2364 phased_loop->set_name("Test loop");
2365 manager_timer->set_name("Manager timer");
2366
2367 Run();
2368
2369 ASSERT_EQ(2u, expected_times.size());
2370 ASSERT_EQ(expected_times[0] + kInterval, expected_times[1]);
2371}
2372
2373// Tests that a phased loop responds correctly to being rescheduled at a time in
2374// the distant future.
2375TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleFuture) {
2376 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2377 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2378
2379 auto loop1 = MakePrimary();
2380
2381 std::vector<::aos::monotonic_clock::time_point> expected_times;
2382
2383 PhasedLoopHandler *phased_loop;
2384
2385 bool should_exit = false;
2386 int expected_count = 1;
2387 TimerHandler *manager_timer = loop1->AddTimer(
2388 [&expected_count, &phased_loop, &loop1, &should_exit, this, kInterval]() {
2389 if (should_exit) {
2390 LOG(INFO) << "Exiting";
2391 this->Exit();
2392 return;
2393 }
2394 expected_count = 10;
2395 // Knock off 1 ns, since the scheduler rounds up when it is
2396 // scheduled to exactly a loop time.
2397 phased_loop->Reschedule(loop1->context().monotonic_event_time +
2398 kInterval * expected_count -
2399 std::chrono::nanoseconds(1));
2400 should_exit = true;
2401 });
2402
2403 phased_loop = loop1->AddPhasedLoop(
2404 [&expected_times, &loop1, manager_timer, &expected_count](int count) {
2405 EXPECT_EQ(count, expected_count);
2406 expected_times.push_back(loop1->context().monotonic_event_time);
2407
Philipp Schradera6712522023-07-05 20:25:11 -07002408 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002409 },
2410 kInterval, kOffset);
2411 phased_loop->set_name("Test loop");
2412 manager_timer->set_name("Manager timer");
2413
2414 Run();
2415
2416 ASSERT_EQ(2u, expected_times.size());
2417 ASSERT_EQ(expected_times[0] + expected_count * kInterval, expected_times[1]);
2418}
2419
2420// Tests that a phased loop responds correctly to having its phase offset
2421// incremented and then being scheduled after a set time, exercising a pattern
2422// where a phased loop's offset is changed while trying to maintain the trigger
2423// at a consistent period.
2424TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleWithLaterOffset) {
2425 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2426 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2427
2428 auto loop1 = MakePrimary();
2429
2430 std::vector<::aos::monotonic_clock::time_point> expected_times;
2431
2432 PhasedLoopHandler *phased_loop;
2433
2434 bool should_exit = false;
2435 TimerHandler *manager_timer = loop1->AddTimer(
2436 [&phased_loop, &loop1, &should_exit, this, kInterval, kOffset]() {
2437 if (should_exit) {
2438 LOG(INFO) << "Exiting";
2439 this->Exit();
2440 return;
2441 }
2442 // Schedule the next callback to be strictly later than the current time
2443 // + interval / 2, to ensure a consistent frequency.
2444 monotonic_clock::time_point half_time =
2445 loop1->context().monotonic_event_time + kInterval / 2;
2446 phased_loop->set_interval_and_offset(
2447 kInterval, kOffset + std::chrono::nanoseconds(1), half_time);
2448 phased_loop->Reschedule(half_time);
2449 should_exit = true;
2450 });
2451
2452 phased_loop = loop1->AddPhasedLoop(
2453 [&expected_times, &loop1, manager_timer](int count) {
2454 EXPECT_EQ(1, count);
2455 expected_times.push_back(loop1->context().monotonic_event_time);
2456
Philipp Schradera6712522023-07-05 20:25:11 -07002457 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002458 },
2459 kInterval, kOffset);
2460 phased_loop->set_name("Test loop");
2461 manager_timer->set_name("Manager timer");
2462
2463 Run();
2464
2465 ASSERT_EQ(2u, expected_times.size());
2466 ASSERT_EQ(expected_times[0] + kInterval + std::chrono::nanoseconds(1),
2467 expected_times[1]);
2468}
2469
2470// Tests that a phased loop responds correctly to having its phase offset
2471// decremented and then being scheduled after a set time, exercising a pattern
2472// where a phased loop's offset is changed while trying to maintain the trigger
2473// at a consistent period.
2474TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleWithEarlierOffset) {
2475 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2476 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2477
2478 auto loop1 = MakePrimary();
2479
2480 std::vector<::aos::monotonic_clock::time_point> expected_times;
2481
2482 PhasedLoopHandler *phased_loop;
2483
2484 bool should_exit = false;
2485 TimerHandler *manager_timer = loop1->AddTimer(
2486 [&phased_loop, &loop1, &should_exit, this, kInterval, kOffset]() {
2487 if (should_exit) {
2488 LOG(INFO) << "Exiting";
2489 this->Exit();
2490 return;
2491 }
2492 // Schedule the next callback to be strictly later than the current time
2493 // + interval / 2, to ensure a consistent frequency.
2494 const aos::monotonic_clock::time_point half_time =
2495 loop1->context().monotonic_event_time + kInterval / 2;
2496 phased_loop->set_interval_and_offset(
2497 kInterval, kOffset - std::chrono::nanoseconds(1), half_time);
2498 phased_loop->Reschedule(half_time);
2499 should_exit = true;
2500 });
2501
2502 phased_loop = loop1->AddPhasedLoop(
2503 [&expected_times, &loop1, manager_timer](int count) {
2504 EXPECT_EQ(1, count);
2505 expected_times.push_back(loop1->context().monotonic_event_time);
2506
Philipp Schradera6712522023-07-05 20:25:11 -07002507 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002508 },
2509 kInterval, kOffset);
2510 phased_loop->set_name("Test loop");
2511 manager_timer->set_name("Manager timer");
2512
2513 Run();
2514
2515 ASSERT_EQ(2u, expected_times.size());
2516 ASSERT_EQ(expected_times[0] + kInterval - std::chrono::nanoseconds(1),
2517 expected_times[1]);
2518}
2519
Austin Schuh39788ff2019-12-01 18:22:57 -08002520// Tests that senders count correctly in the timing report.
2521TEST_P(AbstractEventLoopTest, SenderTimingReport) {
2522 FLAGS_timing_report_ms = 1000;
2523 auto loop1 = MakePrimary();
2524
2525 auto loop2 = Make("watcher_loop");
2526 loop2->MakeWatcher("/test", [](const TestMessage &) {});
2527
2528 auto loop3 = Make();
2529
2530 Fetcher<timing::Report> report_fetcher =
2531 loop3->MakeFetcher<timing::Report>("/aos");
2532 EXPECT_FALSE(report_fetcher.Fetch());
2533
2534 auto sender = loop1->MakeSender<TestMessage>("/test");
2535
James Kuszmaul78514332022-04-06 15:08:34 -07002536 // Sanity check channel frequencies to ensure that we've designed the test
2537 // correctly.
2538 ASSERT_EQ(800, sender.channel()->frequency());
Austin Schuhfff9c3a2023-06-16 18:48:23 -07002539 ASSERT_EQ(2000000000, configuration::ChannelStorageDuration(
2540 loop1->configuration(), sender.channel())
2541 .count());
James Kuszmaul78514332022-04-06 15:08:34 -07002542 constexpr int kMaxAllowedMessages = 800 * 2;
2543 constexpr int kSendMessages = kMaxAllowedMessages * 2;
2544 constexpr int kDroppedMessages = kSendMessages - kMaxAllowedMessages;
2545
Austin Schuh39788ff2019-12-01 18:22:57 -08002546 // Add a timer to actually quit.
2547 auto test_timer = loop1->AddTimer([&sender]() {
James Kuszmaul78514332022-04-06 15:08:34 -07002548 for (int i = 0; i < kSendMessages; ++i) {
Austin Schuh39788ff2019-12-01 18:22:57 -08002549 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2550 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2551 builder.add_value(200 + i);
James Kuszmaul78514332022-04-06 15:08:34 -07002552 if (i < kMaxAllowedMessages) {
2553 msg.CheckOk(msg.Send(builder.Finish()));
2554 } else {
2555 EXPECT_EQ(RawSender::Error::kMessagesSentTooFast,
2556 msg.Send(builder.Finish()));
2557 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002558 }
2559 });
2560
2561 // Quit after 1 timing report, mid way through the next cycle.
2562 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2563
2564 loop1->OnRun([&test_timer, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002565 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1500));
Austin Schuh39788ff2019-12-01 18:22:57 -08002566 });
2567
2568 Run();
2569
Austin Schuh6bae8252021-02-07 22:01:49 -08002570 if (do_timing_reports() == DoTimingReports::kYes) {
2571 // And, since we are here, check that the timing report makes sense.
2572 // Start by looking for our event loop's timing.
2573 FlatbufferDetachedBuffer<timing::Report> primary_report =
2574 FlatbufferDetachedBuffer<timing::Report>::Empty();
2575 while (report_fetcher.FetchNext()) {
Austin Schuh8902fa52021-03-14 22:39:24 -07002576 VLOG(1) << "Report " << FlatbufferToJson(report_fetcher.get());
Austin Schuh6bae8252021-02-07 22:01:49 -08002577 if (report_fetcher->name()->string_view() == "primary") {
2578 primary_report = CopyFlatBuffer(report_fetcher.get());
2579 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002580 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002581
Austin Schuh8902fa52021-03-14 22:39:24 -07002582 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
Austin Schuh6bae8252021-02-07 22:01:49 -08002583
2584 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2585
2586 ASSERT_NE(primary_report.message().senders(), nullptr);
2587 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2588
2589 // Confirm that the sender looks sane.
2590 EXPECT_EQ(
2591 loop1->configuration()
2592 ->channels()
2593 ->Get(primary_report.message().senders()->Get(0)->channel_index())
2594 ->name()
2595 ->string_view(),
2596 "/test");
James Kuszmaul78514332022-04-06 15:08:34 -07002597 EXPECT_EQ(primary_report.message().senders()->Get(0)->count(),
2598 kMaxAllowedMessages);
2599 ASSERT_TRUE(primary_report.message().senders()->Get(0)->has_error_counts());
2600 ASSERT_EQ(
2601 primary_report.message().senders()->Get(0)->error_counts()->size(), 2u);
2602 EXPECT_EQ(
2603 primary_report.message()
2604 .senders()
2605 ->Get(0)
2606 ->error_counts()
2607 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2608 ->count(),
2609 kDroppedMessages)
2610 << aos::FlatbufferToJson(primary_report);
2611 EXPECT_EQ(primary_report.message()
2612 .senders()
2613 ->Get(0)
2614 ->error_counts()
2615 ->Get(static_cast<size_t>(timing::SendError::INVALID_REDZONE))
2616 ->count(),
2617 0);
Austin Schuh6bae8252021-02-07 22:01:49 -08002618
2619 // Confirm that the timing primary_report sender looks sane.
2620 EXPECT_EQ(
2621 loop1->configuration()
2622 ->channels()
2623 ->Get(primary_report.message().senders()->Get(1)->channel_index())
2624 ->name()
2625 ->string_view(),
2626 "/aos");
2627 EXPECT_EQ(primary_report.message().senders()->Get(1)->count(), 1);
2628
2629 ASSERT_NE(primary_report.message().timers(), nullptr);
2630 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2631
2632 // Make sure there are no phased loops or watchers.
2633 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2634 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2635 } else {
2636 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002637 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002638}
2639
James Kuszmaul93abac12022-04-14 15:05:10 -07002640// Tests that the RawSender::Send(void*, size_t) overload tracks things properly
2641// in its timing report.
2642TEST_P(AbstractEventLoopTest, CopySenderTimingReport) {
2643 gflags::FlagSaver flag_saver;
2644 FLAGS_timing_report_ms = 1000;
2645 auto loop1 = Make();
2646 auto loop2 = MakePrimary();
2647
2648 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2649 JsonToFlatbuffer<TestMessage>("{}");
2650
2651 std::unique_ptr<aos::RawSender> sender =
2652 loop2->MakeRawSender(configuration::GetChannel(
2653 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
2654
2655 Fetcher<timing::Report> report_fetcher =
2656 loop1->MakeFetcher<timing::Report>("/aos");
2657 EXPECT_FALSE(report_fetcher.Fetch());
2658
2659 loop2->OnRun([&]() {
2660 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
2661 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2662 RawSender::Error::kOk);
2663 }
2664 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2665 RawSender::Error::kMessagesSentTooFast);
2666 });
2667 // Quit after 1 timing report, mid way through the next cycle.
2668 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
2669
2670 Run();
2671
2672 if (do_timing_reports() == DoTimingReports::kYes) {
2673 // Check that the sent too fast actually got recorded by the timing report.
2674 FlatbufferDetachedBuffer<timing::Report> primary_report =
2675 FlatbufferDetachedBuffer<timing::Report>::Empty();
2676 while (report_fetcher.FetchNext()) {
2677 if (report_fetcher->name()->string_view() == "primary") {
2678 primary_report = CopyFlatBuffer(report_fetcher.get());
2679 }
2680 }
2681
2682 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2683
2684 ASSERT_NE(primary_report.message().senders(), nullptr);
2685 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2686 EXPECT_EQ(
2687 primary_report.message()
2688 .senders()
2689 ->Get(0)
2690 ->error_counts()
2691 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2692 ->count(),
2693 1);
2694 }
2695}
2696
Austin Schuhe0ab4de2023-05-03 08:05:08 -07002697// Tests that the RawSender::Send(SharedSpan) overload works.
2698TEST_P(AbstractEventLoopTest, SharedSenderTimingReport) {
2699 gflags::FlagSaver flag_saver;
2700 FLAGS_timing_report_ms = 1000;
2701 auto loop1 = Make();
2702 auto loop2 = MakePrimary();
2703
2704 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2705 JsonToFlatbuffer<TestMessage>("{}");
2706
2707 std::unique_ptr<aos::RawSender> sender =
2708 loop2->MakeRawSender(configuration::GetChannel(
2709 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
2710
2711 Fetcher<timing::Report> report_fetcher =
2712 loop1->MakeFetcher<timing::Report>("/aos");
2713 EXPECT_FALSE(report_fetcher.Fetch());
2714
2715 loop2->OnRun([&]() {
2716 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
2717 auto shared_span = MakeSharedSpan(kMessage.span().size());
2718 memcpy(shared_span.second.data(), kMessage.span().data(),
2719 kMessage.span().size());
2720 EXPECT_EQ(sender->Send(std::move(shared_span.first)),
2721 RawSender::Error::kOk);
2722 }
2723 auto shared_span = MakeSharedSpan(kMessage.span().size());
2724 memcpy(shared_span.second.data(), kMessage.span().data(),
2725 kMessage.span().size());
2726 EXPECT_EQ(sender->Send(std::move(shared_span.first)),
2727 RawSender::Error::kMessagesSentTooFast);
2728 });
2729 // Quit after 1 timing report, mid way through the next cycle.
2730 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
2731
2732 Run();
2733
2734 if (do_timing_reports() == DoTimingReports::kYes) {
2735 // Check that the sent too fast actually got recorded by the timing report.
2736 FlatbufferDetachedBuffer<timing::Report> primary_report =
2737 FlatbufferDetachedBuffer<timing::Report>::Empty();
2738 while (report_fetcher.FetchNext()) {
2739 if (report_fetcher->name()->string_view() == "primary") {
2740 primary_report = CopyFlatBuffer(report_fetcher.get());
2741 }
2742 }
2743
2744 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2745
2746 ASSERT_NE(primary_report.message().senders(), nullptr);
2747 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2748 EXPECT_EQ(
2749 primary_report.message()
2750 .senders()
2751 ->Get(0)
2752 ->error_counts()
2753 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2754 ->count(),
2755 1);
2756 }
2757}
2758
Austin Schuh39788ff2019-12-01 18:22:57 -08002759// Tests that senders count correctly in the timing report.
2760TEST_P(AbstractEventLoopTest, WatcherTimingReport) {
2761 FLAGS_timing_report_ms = 1000;
2762 auto loop1 = MakePrimary();
2763 loop1->MakeWatcher("/test", [](const TestMessage &) {});
2764
2765 auto loop2 = Make("sender_loop");
2766
2767 auto loop3 = Make();
2768
2769 Fetcher<timing::Report> report_fetcher =
2770 loop3->MakeFetcher<timing::Report>("/aos");
2771 EXPECT_FALSE(report_fetcher.Fetch());
2772
2773 auto sender = loop2->MakeSender<TestMessage>("/test");
2774
2775 // Add a timer to actually quit.
2776 auto test_timer = loop1->AddTimer([&sender]() {
2777 for (int i = 0; i < 10; ++i) {
2778 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2779 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2780 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002781 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002782 }
2783 });
2784
2785 // Quit after 1 timing report, mid way through the next cycle.
2786 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2787
2788 loop1->OnRun([&test_timer, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002789 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1500));
Austin Schuh39788ff2019-12-01 18:22:57 -08002790 });
2791
2792 Run();
2793
Austin Schuh6bae8252021-02-07 22:01:49 -08002794 if (do_timing_reports() == DoTimingReports::kYes) {
2795 // And, since we are here, check that the timing report makes sense.
2796 // Start by looking for our event loop's timing.
2797 FlatbufferDetachedBuffer<timing::Report> primary_report =
2798 FlatbufferDetachedBuffer<timing::Report>::Empty();
2799 while (report_fetcher.FetchNext()) {
2800 LOG(INFO) << "Report " << FlatbufferToJson(report_fetcher.get());
2801 if (report_fetcher->name()->string_view() == "primary") {
2802 primary_report = CopyFlatBuffer(report_fetcher.get());
2803 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002804 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002805
2806 // Check the watcher report.
2807 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2808
2809 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2810
2811 // Just the timing report timer.
2812 ASSERT_NE(primary_report.message().timers(), nullptr);
2813 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2814
2815 // No phased loops
2816 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2817
2818 ASSERT_NE(primary_report.message().watchers(), nullptr);
2819 ASSERT_EQ(primary_report.message().watchers()->size(), 1);
2820 EXPECT_EQ(primary_report.message().watchers()->Get(0)->count(), 10);
2821 } else {
2822 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002823 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002824}
2825
2826// Tests that fetchers count correctly in the timing report.
2827TEST_P(AbstractEventLoopTest, FetcherTimingReport) {
2828 FLAGS_timing_report_ms = 1000;
2829 auto loop1 = MakePrimary();
2830 auto loop2 = Make("sender_loop");
2831
2832 auto loop3 = Make();
2833
2834 Fetcher<timing::Report> report_fetcher =
2835 loop3->MakeFetcher<timing::Report>("/aos");
2836 EXPECT_FALSE(report_fetcher.Fetch());
2837
2838 auto sender = loop2->MakeSender<TestMessage>("/test");
2839 auto fetcher1 = loop1->MakeFetcher<TestMessage>("/test");
2840 auto fetcher2 = loop1->MakeFetcher<TestMessage>("/test");
2841 fetcher1.Fetch();
2842 fetcher2.Fetch();
2843
2844 // Add a timer to actually quit.
2845 auto test_timer = loop1->AddTimer([&sender]() {
2846 for (int i = 0; i < 10; ++i) {
2847 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2848 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2849 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002850 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002851 }
2852 });
2853
2854 auto test_timer2 = loop1->AddTimer([&fetcher1, &fetcher2]() {
2855 fetcher1.Fetch();
2856 while (fetcher2.FetchNext()) {
2857 }
2858 });
2859
2860 // Quit after 1 timing report, mid way through the next cycle.
2861 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2862
2863 loop1->OnRun([test_timer, test_timer2, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002864 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1400));
2865 test_timer2->Schedule(loop1->monotonic_now() + chrono::milliseconds(1600));
Austin Schuh39788ff2019-12-01 18:22:57 -08002866 });
2867
2868 Run();
2869
Austin Schuh6bae8252021-02-07 22:01:49 -08002870 if (do_timing_reports() == DoTimingReports::kYes) {
2871 // And, since we are here, check that the timing report makes sense.
2872 // Start by looking for our event loop's timing.
2873 FlatbufferDetachedBuffer<timing::Report> primary_report =
2874 FlatbufferDetachedBuffer<timing::Report>::Empty();
2875 while (report_fetcher.FetchNext()) {
2876 if (report_fetcher->name()->string_view() == "primary") {
2877 primary_report = CopyFlatBuffer(report_fetcher.get());
2878 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002879 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002880
2881 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2882
2883 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2884
2885 ASSERT_NE(primary_report.message().senders(), nullptr);
2886 EXPECT_EQ(primary_report.message().senders()->size(), 2);
2887
2888 ASSERT_NE(primary_report.message().timers(), nullptr);
2889 EXPECT_EQ(primary_report.message().timers()->size(), 4);
2890
2891 // Make sure there are no phased loops or watchers.
2892 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2893 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2894
2895 // Now look at the fetchrs.
2896 ASSERT_NE(primary_report.message().fetchers(), nullptr);
2897 ASSERT_EQ(primary_report.message().fetchers()->size(), 2);
2898
2899 EXPECT_EQ(primary_report.message().fetchers()->Get(0)->count(), 1);
2900 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->average(),
2901 0.1);
2902 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->min(),
2903 0.1);
2904 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->max(),
2905 0.1);
2906 EXPECT_EQ(primary_report.message()
2907 .fetchers()
2908 ->Get(0)
2909 ->latency()
2910 ->standard_deviation(),
2911 0.0);
2912
2913 EXPECT_EQ(primary_report.message().fetchers()->Get(1)->count(), 10);
2914 } else {
2915 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002916 }
Austin Schuh52d325c2019-06-23 18:59:06 -07002917}
2918
Austin Schuh67420a42019-12-21 21:55:04 -08002919// Tests that a raw watcher and raw fetcher can receive messages from a raw
2920// sender without messing up offsets.
2921TEST_P(AbstractEventLoopTest, RawBasic) {
2922 auto loop1 = Make();
2923 auto loop2 = MakePrimary();
2924 auto loop3 = Make();
2925
Austin Schuha9df9ad2021-06-16 14:49:39 -07002926 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2927 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuh67420a42019-12-21 21:55:04 -08002928
2929 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002930 loop1->MakeRawSender(configuration::GetChannel(
2931 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08002932
2933 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002934 loop3->MakeRawFetcher(configuration::GetChannel(
2935 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08002936
Austin Schuha9df9ad2021-06-16 14:49:39 -07002937 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002938 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2939 RawSender::Error::kOk);
Austin Schuha9df9ad2021-06-16 14:49:39 -07002940 });
Austin Schuh67420a42019-12-21 21:55:04 -08002941
2942 bool happened = false;
2943 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08002944 configuration::GetChannel(loop2->configuration(), "/test",
2945 "aos.TestMessage", "", nullptr),
Austin Schuha9df9ad2021-06-16 14:49:39 -07002946 [this, &kMessage, &fetcher, &happened](const Context &context,
2947 const void *message) {
Austin Schuh67420a42019-12-21 21:55:04 -08002948 happened = true;
Austin Schuha9df9ad2021-06-16 14:49:39 -07002949 EXPECT_EQ(
2950 kMessage.span(),
2951 absl::Span<const uint8_t>(
2952 reinterpret_cast<const uint8_t *>(message), context.size));
2953 EXPECT_EQ(message, context.data);
Austin Schuh67420a42019-12-21 21:55:04 -08002954
2955 ASSERT_TRUE(fetcher->Fetch());
2956
Austin Schuha9df9ad2021-06-16 14:49:39 -07002957 EXPECT_EQ(kMessage.span(),
2958 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
2959 fetcher->context().data),
2960 fetcher->context().size));
Austin Schuh67420a42019-12-21 21:55:04 -08002961
2962 this->Exit();
2963 });
2964
2965 EXPECT_FALSE(happened);
2966 Run();
2967 EXPECT_TRUE(happened);
2968}
2969
Austin Schuhad154822019-12-27 15:45:13 -08002970// Tests that a raw watcher and raw fetcher can receive messages from a raw
Brian Silvermanbf889922021-11-10 12:41:57 -08002971// sender without messing up offsets, using the RawSpan overload.
2972TEST_P(AbstractEventLoopTest, RawBasicSharedSpan) {
2973 auto loop1 = Make();
2974 auto loop2 = MakePrimary();
2975 auto loop3 = Make();
2976
2977 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2978 JsonToFlatbuffer<TestMessage>("{}");
2979
2980 std::unique_ptr<aos::RawSender> sender =
2981 loop1->MakeRawSender(configuration::GetChannel(
2982 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
2983
2984 std::unique_ptr<aos::RawFetcher> fetcher =
2985 loop3->MakeRawFetcher(configuration::GetChannel(
2986 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
2987
2988 loop2->OnRun([&]() {
Austin Schuhe0ab4de2023-05-03 08:05:08 -07002989 auto shared_span = MakeSharedSpan(kMessage.span().size());
2990 memcpy(shared_span.second.data(), kMessage.span().data(),
2991 kMessage.span().size());
2992 sender->CheckOk(sender->Send(std::move(shared_span.first)));
Brian Silvermanbf889922021-11-10 12:41:57 -08002993 });
2994
2995 bool happened = false;
2996 loop2->MakeRawWatcher(
2997 configuration::GetChannel(loop2->configuration(), "/test",
2998 "aos.TestMessage", "", nullptr),
2999 [this, &kMessage, &fetcher, &happened](const Context &context,
3000 const void *message) {
3001 happened = true;
3002 EXPECT_EQ(
3003 kMessage.span(),
3004 absl::Span<const uint8_t>(
3005 reinterpret_cast<const uint8_t *>(message), context.size));
3006 EXPECT_EQ(message, context.data);
3007
3008 ASSERT_TRUE(fetcher->Fetch());
3009
3010 EXPECT_EQ(kMessage.span(),
3011 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
3012 fetcher->context().data),
3013 fetcher->context().size));
3014
3015 this->Exit();
3016 });
3017
3018 EXPECT_FALSE(happened);
3019 Run();
3020 EXPECT_TRUE(happened);
3021}
3022
3023// Tests that a raw watcher and raw fetcher can receive messages from a raw
Austin Schuhad154822019-12-27 15:45:13 -08003024// sender with remote times filled out.
3025TEST_P(AbstractEventLoopTest, RawRemoteTimes) {
3026 auto loop1 = Make();
3027 auto loop2 = MakePrimary();
3028 auto loop3 = Make();
3029
Austin Schuha9df9ad2021-06-16 14:49:39 -07003030 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3031 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08003032
3033 const aos::monotonic_clock::time_point monotonic_remote_time =
3034 aos::monotonic_clock::time_point(chrono::seconds(1501));
3035 const aos::realtime_clock::time_point realtime_remote_time =
3036 aos::realtime_clock::time_point(chrono::seconds(3132));
Austin Schuhb5c6f972021-03-14 21:53:07 -07003037 const uint32_t remote_queue_index = 0x254971;
Austin Schuha9012be2021-07-21 15:19:11 -07003038 const UUID source_boot_uuid = UUID::Random();
Austin Schuhad154822019-12-27 15:45:13 -08003039
3040 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003041 loop1->MakeRawSender(configuration::GetChannel(
3042 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08003043
3044 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003045 loop3->MakeRawFetcher(configuration::GetChannel(
3046 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08003047
3048 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07003049 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size(),
3050 monotonic_remote_time, realtime_remote_time,
3051 remote_queue_index, source_boot_uuid),
3052 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08003053 });
3054
3055 bool happened = false;
3056 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08003057 configuration::GetChannel(loop2->configuration(), "/test",
3058 "aos.TestMessage", "", nullptr),
Austin Schuha9012be2021-07-21 15:19:11 -07003059 [this, monotonic_remote_time, realtime_remote_time, source_boot_uuid,
Austin Schuhb5c6f972021-03-14 21:53:07 -07003060 remote_queue_index, &fetcher,
3061 &happened](const Context &context, const void * /*message*/) {
Austin Schuhad154822019-12-27 15:45:13 -08003062 happened = true;
3063 EXPECT_EQ(monotonic_remote_time, context.monotonic_remote_time);
3064 EXPECT_EQ(realtime_remote_time, context.realtime_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07003065 EXPECT_EQ(source_boot_uuid, context.source_boot_uuid);
Austin Schuhb5c6f972021-03-14 21:53:07 -07003066 EXPECT_EQ(remote_queue_index, context.remote_queue_index);
Austin Schuhad154822019-12-27 15:45:13 -08003067
3068 ASSERT_TRUE(fetcher->Fetch());
3069 EXPECT_EQ(monotonic_remote_time,
3070 fetcher->context().monotonic_remote_time);
3071 EXPECT_EQ(realtime_remote_time,
3072 fetcher->context().realtime_remote_time);
3073
3074 this->Exit();
3075 });
3076
3077 EXPECT_FALSE(happened);
3078 Run();
3079 EXPECT_TRUE(happened);
3080}
3081
3082// Tests that a raw sender fills out sent data.
3083TEST_P(AbstractEventLoopTest, RawSenderSentData) {
3084 auto loop1 = MakePrimary();
3085
Austin Schuha9df9ad2021-06-16 14:49:39 -07003086 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3087 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08003088
3089 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003090 loop1->MakeRawSender(configuration::GetChannel(
3091 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08003092
Tyler Chatow67ddb032020-01-12 14:30:04 -08003093 const aos::monotonic_clock::time_point monotonic_now = loop1->monotonic_now();
3094 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08003095
milind1f1dca32021-07-03 13:50:07 -07003096 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
3097 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08003098
3099 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
3100 EXPECT_LE(sender->monotonic_sent_time(),
3101 monotonic_now + chrono::milliseconds(100));
3102 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
3103 EXPECT_LE(sender->realtime_sent_time(),
3104 realtime_now + chrono::milliseconds(100));
3105 EXPECT_EQ(sender->sent_queue_index(), 0u);
3106
milind1f1dca32021-07-03 13:50:07 -07003107 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
3108 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08003109
3110 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
3111 EXPECT_LE(sender->monotonic_sent_time(),
3112 monotonic_now + chrono::milliseconds(100));
3113 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
3114 EXPECT_LE(sender->realtime_sent_time(),
3115 realtime_now + chrono::milliseconds(100));
3116 EXPECT_EQ(sender->sent_queue_index(), 1u);
3117}
3118
Austin Schuh217a9782019-12-21 23:02:50 -08003119// Tests that not setting up nodes results in no node.
3120TEST_P(AbstractEventLoopTest, NoNode) {
3121 auto loop1 = Make();
3122 auto loop2 = MakePrimary();
3123
3124 EXPECT_EQ(loop1->node(), nullptr);
3125 EXPECT_EQ(loop2->node(), nullptr);
3126}
3127
3128// Tests that setting up nodes results in node being set.
3129TEST_P(AbstractEventLoopTest, Node) {
3130 EnableNodes("me");
3131
3132 auto loop1 = Make();
3133 auto loop2 = MakePrimary();
3134
3135 EXPECT_NE(loop1->node(), nullptr);
3136 EXPECT_NE(loop2->node(), nullptr);
3137}
3138
3139// Tests that watchers work with a node setup.
3140TEST_P(AbstractEventLoopTest, NodeWatcher) {
3141 EnableNodes("me");
3142
3143 auto loop1 = Make();
3144 auto loop2 = Make();
3145 loop1->MakeWatcher("/test", [](const TestMessage &) {});
Tyler Chatow67ddb032020-01-12 14:30:04 -08003146 loop2->MakeRawWatcher(
3147 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
3148 nullptr),
3149 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08003150}
3151
Brian Silverman454bc112020-03-05 14:21:25 -08003152// Tests that no-arg watchers work with a node setup.
3153TEST_P(AbstractEventLoopTest, NodeNoArgWatcher) {
3154 EnableNodes("me");
3155
3156 auto loop1 = Make();
3157 auto loop2 = Make();
3158 loop1->MakeWatcher("/test", [](const TestMessage &) {});
3159 loop2->MakeRawNoArgWatcher(
3160 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
3161 nullptr),
3162 [](const Context &) {});
3163}
3164
Austin Schuh217a9782019-12-21 23:02:50 -08003165// Tests that fetcher work with a node setup.
3166TEST_P(AbstractEventLoopTest, NodeFetcher) {
3167 EnableNodes("me");
3168 auto loop1 = Make();
3169
3170 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
Tyler Chatow67ddb032020-01-12 14:30:04 -08003171 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
3172 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08003173}
3174
3175// Tests that sender work with a node setup.
3176TEST_P(AbstractEventLoopTest, NodeSender) {
3177 EnableNodes("me");
3178 auto loop1 = Make();
3179
3180 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
3181}
3182
Austin Schuhcc6070c2020-10-10 20:25:56 -07003183// Tests that a non-realtime event loop timer is marked non-realtime.
3184TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopTimer) {
3185 auto loop1 = MakePrimary();
3186
3187 // Add a timer to actually quit.
3188 auto test_timer = loop1->AddTimer([this]() {
3189 CheckNotRealtime();
3190 this->Exit();
3191 });
3192
3193 loop1->OnRun([&test_timer, &loop1]() {
3194 CheckNotRealtime();
Philipp Schradera6712522023-07-05 20:25:11 -07003195 test_timer->Schedule(loop1->monotonic_now(),
3196 ::std::chrono::milliseconds(100));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003197 });
3198
3199 Run();
3200}
3201
3202// Tests that a realtime event loop timer is marked realtime.
Austin Schuh9b1d6282022-06-10 17:03:21 -07003203TEST_P(AbstractEventLoopTest, RealtimeSend) {
3204 auto loop1 = MakePrimary();
3205
3206 loop1->SetRuntimeRealtimePriority(1);
3207
3208 auto sender = loop1->MakeSender<TestMessage>("/test2");
3209
3210 loop1->OnRun([&]() {
3211 CheckRealtime();
3212
3213 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3214 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
3215 builder.add_value(200);
3216 msg.CheckOk(msg.Send(builder.Finish()));
3217
3218 this->Exit();
3219 });
3220
3221 Run();
3222}
3223
3224// Tests that a realtime event loop timer is marked realtime.
Austin Schuhcc6070c2020-10-10 20:25:56 -07003225TEST_P(AbstractEventLoopTest, RealtimeEventLoopTimer) {
3226 auto loop1 = MakePrimary();
3227
3228 loop1->SetRuntimeRealtimePriority(1);
3229
3230 // Add a timer to actually quit.
3231 auto test_timer = loop1->AddTimer([this]() {
3232 CheckRealtime();
3233 this->Exit();
3234 });
3235
3236 loop1->OnRun([&test_timer, &loop1]() {
3237 CheckRealtime();
Philipp Schradera6712522023-07-05 20:25:11 -07003238 test_timer->Schedule(loop1->monotonic_now(),
3239 ::std::chrono::milliseconds(100));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003240 });
3241
3242 Run();
3243}
3244
3245// Tests that a non-realtime event loop phased loop is marked non-realtime.
3246TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopPhasedLoop) {
3247 auto loop1 = MakePrimary();
3248
3249 // Add a timer to actually quit.
3250 loop1->AddPhasedLoop(
3251 [this](int) {
3252 CheckNotRealtime();
3253 this->Exit();
3254 },
3255 chrono::seconds(1), chrono::seconds(0));
3256
3257 Run();
3258}
3259
3260// Tests that a realtime event loop phased loop is marked realtime.
3261TEST_P(AbstractEventLoopTest, RealtimeEventLoopPhasedLoop) {
3262 auto loop1 = MakePrimary();
3263
3264 loop1->SetRuntimeRealtimePriority(1);
3265
3266 // Add a timer to actually quit.
3267 loop1->AddPhasedLoop(
3268 [this](int) {
3269 CheckRealtime();
3270 this->Exit();
3271 },
3272 chrono::seconds(1), chrono::seconds(0));
3273
3274 Run();
3275}
3276
3277// Tests that a non-realtime event loop watcher is marked non-realtime.
3278TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopWatcher) {
3279 auto loop1 = MakePrimary();
3280 auto loop2 = Make();
3281
3282 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
3283
3284 loop1->OnRun([&]() {
3285 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3286 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07003287 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003288 });
3289
3290 loop1->MakeWatcher("/test", [&](const TestMessage &) {
3291 CheckNotRealtime();
3292 this->Exit();
3293 });
3294
3295 Run();
3296}
3297
3298// Tests that a realtime event loop watcher is marked realtime.
3299TEST_P(AbstractEventLoopTest, RealtimeEventLoopWatcher) {
3300 auto loop1 = MakePrimary();
3301 auto loop2 = Make();
3302
3303 loop1->SetRuntimeRealtimePriority(1);
3304
3305 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
3306
3307 loop1->OnRun([&]() {
3308 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3309 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07003310 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003311 });
3312
3313 loop1->MakeWatcher("/test", [&](const TestMessage &) {
3314 CheckRealtime();
3315 this->Exit();
3316 });
3317
3318 Run();
3319}
3320
Austin Schuha9012be2021-07-21 15:19:11 -07003321// Tests that event loop's context's monotonic time is set to a value on OnRun.
3322TEST_P(AbstractEventLoopTest, SetContextOnRun) {
3323 auto loop = MakePrimary();
3324
Austin Schuh0debde12022-08-17 16:25:17 -07003325 EXPECT_EQ(loop->context().monotonic_event_time, monotonic_clock::min_time);
3326 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3327 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3328 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3329 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3330 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
3331 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
3332 EXPECT_EQ(loop->context().size, 0u);
3333 EXPECT_EQ(loop->context().data, nullptr);
3334 EXPECT_EQ(loop->context().buffer_index, -1);
3335
Austin Schuha9012be2021-07-21 15:19:11 -07003336 // We want to check that monotonic event time is before monotonic now
3337 // called inside of callback, but after time point obtained callback.
3338 aos::monotonic_clock::time_point monotonic_event_time_on_run;
3339
3340 loop->OnRun([&]() {
3341 monotonic_event_time_on_run = loop->context().monotonic_event_time;
3342 EXPECT_LE(monotonic_event_time_on_run, loop->monotonic_now());
3343 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3344 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3345 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3346 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3347 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
Austin Schuh0debde12022-08-17 16:25:17 -07003348 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
Austin Schuha9012be2021-07-21 15:19:11 -07003349 EXPECT_EQ(loop->context().size, 0u);
3350 EXPECT_EQ(loop->context().data, nullptr);
3351 EXPECT_EQ(loop->context().buffer_index, -1);
3352 });
3353
3354 EndEventLoop(loop.get(), ::std::chrono::milliseconds(200));
3355
3356 const aos::monotonic_clock::time_point before_run_time =
3357 loop->monotonic_now();
3358 Run();
3359 EXPECT_GE(monotonic_event_time_on_run, before_run_time);
Austin Schuh0debde12022-08-17 16:25:17 -07003360
3361 EXPECT_EQ(loop->context().monotonic_event_time, monotonic_clock::min_time);
3362 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3363 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3364 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3365 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3366 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
3367 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
3368 EXPECT_EQ(loop->context().size, 0u);
3369 EXPECT_EQ(loop->context().data, nullptr);
3370 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuha9012be2021-07-21 15:19:11 -07003371}
3372
Austin Schuh217a9782019-12-21 23:02:50 -08003373// Tests that watchers fail when created on the wrong node.
3374TEST_P(AbstractEventLoopDeathTest, NodeWatcher) {
3375 EnableNodes("them");
3376
3377 auto loop1 = Make();
3378 auto loop2 = Make();
3379 EXPECT_DEATH({ loop1->MakeWatcher("/test", [](const TestMessage &) {}); },
3380 "node");
3381 EXPECT_DEATH(
3382 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08003383 loop2->MakeRawWatcher(
3384 configuration::GetChannel(configuration(), "/test",
3385 "aos.TestMessage", "", nullptr),
3386 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08003387 },
3388 "node");
Brian Silverman454bc112020-03-05 14:21:25 -08003389 EXPECT_DEATH({ loop1->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
3390 "node");
3391 EXPECT_DEATH(
3392 {
3393 loop2->MakeRawNoArgWatcher(
3394 configuration::GetChannel(configuration(), "/test",
3395 "aos.TestMessage", "", nullptr),
3396 [](const Context &) {});
3397 },
3398 "node");
Austin Schuh217a9782019-12-21 23:02:50 -08003399}
3400
3401// Tests that fetchers fail when created on the wrong node.
3402TEST_P(AbstractEventLoopDeathTest, NodeFetcher) {
3403 EnableNodes("them");
3404 auto loop1 = Make();
3405
3406 EXPECT_DEATH({ auto fetcher = loop1->MakeFetcher<TestMessage>("/test"); },
3407 "node");
3408 EXPECT_DEATH(
3409 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08003410 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
3411 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08003412 },
3413 "node");
3414}
3415
3416// Tests that senders fail when created on the wrong node.
3417TEST_P(AbstractEventLoopDeathTest, NodeSender) {
3418 EnableNodes("them");
3419 auto loop1 = Make();
3420
3421 EXPECT_DEATH(
3422 {
3423 aos::Sender<TestMessage> sender =
3424 loop1->MakeSender<TestMessage>("/test");
3425 },
3426 "node");
3427
3428 // Note: Creating raw senders is always supported. Right now, this lets us
3429 // use them to create message_gateway.
3430}
3431
Brian Silverman341b57e2020-06-23 16:23:18 -07003432// Tests creating multiple Builders from a single Sender at the same time.
3433TEST_P(AbstractEventLoopDeathTest, MultipleBuilders) {
3434 auto loop1 = Make();
3435 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
3436
3437 { auto builder = sender.MakeBuilder(); }
3438 {
3439 auto builder = sender.MakeBuilder();
3440 builder.MakeBuilder<TestMessage>().Finish();
3441 }
3442 {
3443 // Creating this after the first one was destroyed should be fine.
3444 auto builder = sender.MakeBuilder();
3445 builder.MakeBuilder<TestMessage>().Finish();
3446 // But not a second one.
3447 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
3448 "May not overwrite in-use allocator");
3449 }
3450
3451 FlatbufferDetachedBuffer<TestMessage> detached =
3452 flatbuffers::DetachedBuffer();
3453 {
3454 auto builder = sender.MakeBuilder();
3455 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
3456 }
3457 {
3458 // This is the second one, after the detached one, so it should fail.
3459 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
3460 "May not overwrite in-use allocator");
3461 }
3462
3463 // Clear the detached one, and then we should be able to create another.
3464 detached = flatbuffers::DetachedBuffer();
3465 {
3466 auto builder = sender.MakeBuilder();
3467 builder.MakeBuilder<TestMessage>().Finish();
3468 }
3469
3470 // And then detach another one.
3471 {
3472 auto builder = sender.MakeBuilder();
3473 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
3474 }
3475}
3476
3477// Tests sending a buffer detached from a different builder.
3478TEST_P(AbstractEventLoopDeathTest, WrongDetachedBuffer) {
3479 auto loop1 = Make();
3480 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
3481 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
3482
3483 auto builder = sender1.MakeBuilder();
3484 FlatbufferDetachedBuffer<TestMessage> detached =
3485 builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
milind1f1dca32021-07-03 13:50:07 -07003486 EXPECT_DEATH(sender2.CheckOk(sender2.SendDetached(std::move(detached))),
Brian Silverman341b57e2020-06-23 16:23:18 -07003487 "May only send the buffer detached from this Sender");
3488}
3489
James Kuszmaul762e8692023-07-31 14:57:53 -07003490// Tests that senders fail when created on the wrong node.
3491TEST_P(AbstractEventLoopDeathTest, SetVersionWhileRunning) {
3492 auto loop1 = MakePrimary();
3493
3494 loop1->OnRun([&loop1, this]() {
3495 EXPECT_DEATH({ loop1->SetVersionString("abcdef"); },
3496 "timing report while running");
3497 Exit();
3498 });
3499
3500 Run();
3501}
3502
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003503int TestChannelFrequency(EventLoop *event_loop) {
3504 return event_loop->GetChannel<TestMessage>("/test")->frequency();
3505}
3506
3507int TestChannelQueueSize(EventLoop *event_loop) {
Austin Schuhfff9c3a2023-06-16 18:48:23 -07003508 return configuration::QueueSize(event_loop->configuration(),
3509 event_loop->GetChannel<TestMessage>("/test"));
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003510}
3511
3512RawSender::Error SendTestMessage(aos::Sender<TestMessage> &sender) {
3513 aos::Sender<TestMessage>::Builder builder = sender.MakeBuilder();
3514 TestMessage::Builder test_message_builder =
3515 builder.MakeBuilder<TestMessage>();
3516 test_message_builder.add_value(0);
3517 return builder.Send(test_message_builder.Finish());
3518}
3519
3520// Test that sending messages too fast returns
3521// RawSender::Error::kMessagesSentTooFast.
3522TEST_P(AbstractEventLoopTest, SendingMessagesTooFast) {
3523 auto event_loop = MakePrimary();
3524
3525 auto sender = event_loop->MakeSender<TestMessage>("/test");
3526
3527 // Send one message in the beginning, then wait until the
3528 // channel_storage_duration is almost done and start sending messages rapidly,
3529 // having some come in the next chanel_storage_duration. The queue_size is
3530 // 1600, so the 1601st message will be the last valid one (the initial message
3531 // having being sent more than a channel_storage_duration ago), and trying to
3532 // send the 1602nd message should return
3533 // RawSender::Error::kMessagesSentTooFast.
3534 EXPECT_EQ(SendTestMessage(sender), RawSender::Error::kOk);
3535 int msgs_sent = 1;
3536 const int queue_size = TestChannelQueueSize(event_loop.get());
3537
3538 const auto timer = event_loop->AddTimer([&]() {
3539 const bool done = (msgs_sent == queue_size + 1);
3540 ASSERT_EQ(
3541 SendTestMessage(sender),
3542 done ? RawSender::Error::kMessagesSentTooFast : RawSender::Error::kOk);
3543 msgs_sent++;
3544 if (done) {
3545 Exit();
3546 }
3547 });
3548
3549 const auto kRepeatOffset = std::chrono::milliseconds(1);
Austin Schuhfff9c3a2023-06-16 18:48:23 -07003550 const auto base_offset = configuration::ChannelStorageDuration(
3551 event_loop->configuration(), sender.channel()) -
3552 (kRepeatOffset * (queue_size / 2));
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003553 event_loop->OnRun([&event_loop, &timer, &base_offset, &kRepeatOffset]() {
Philipp Schradera6712522023-07-05 20:25:11 -07003554 timer->Schedule(event_loop->monotonic_now() + base_offset, kRepeatOffset);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003555 });
3556
3557 Run();
3558}
3559
3560// Tests that we are able to send messages successfully after sending messages
3561// too fast and waiting while continuously attempting to send messages.
3562// Also tests that SendFailureCounter is working correctly in this
3563// situation
3564TEST_P(AbstractEventLoopTest, SendingAfterSendingTooFast) {
3565 auto event_loop = MakePrimary();
3566
3567 auto sender = event_loop->MakeSender<TestMessage>("/test");
3568
Austin Schuh0e96d372023-05-08 10:10:21 -07003569 // We are sending bunches of messages at 100 Hz, so we will be sending too
3570 // fast after queue_size (800) ms. After this, keep sending messages, and
3571 // exactly a channel storage duration (2s) after we send the first message we
3572 // should be able to successfully send a message.
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003573
Austin Schuh0e96d372023-05-08 10:10:21 -07003574 const std::chrono::milliseconds kInterval = std::chrono::milliseconds(10);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003575 const monotonic_clock::duration channel_storage_duration =
Austin Schuhfff9c3a2023-06-16 18:48:23 -07003576 configuration::ChannelStorageDuration(event_loop->configuration(),
3577 sender.channel());
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003578 const int queue_size = TestChannelQueueSize(event_loop.get());
3579
3580 int msgs_sent = 0;
3581 SendFailureCounter counter;
3582 auto start = monotonic_clock::min_time;
3583
3584 event_loop->AddPhasedLoop(
Austin Schuh0e96d372023-05-08 10:10:21 -07003585 [&](int elapsed_cycles) {
3586 // The queue is setup for 800 messages/sec. We want to fill that up at
3587 // a rate of 2000 messages/sec so we make sure we fill it up.
3588 for (int i = 0; i < 2 * kInterval.count() * elapsed_cycles; ++i) {
3589 const auto actual_err = SendTestMessage(sender);
3590 const bool done_waiting = (start != monotonic_clock::min_time &&
3591 sender.monotonic_sent_time() >=
3592 (start + channel_storage_duration));
3593 const auto expected_err =
3594 (msgs_sent < queue_size || done_waiting
3595 ? RawSender::Error::kOk
3596 : RawSender::Error::kMessagesSentTooFast);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003597
Austin Schuh0e96d372023-05-08 10:10:21 -07003598 if (start == monotonic_clock::min_time) {
3599 start = sender.monotonic_sent_time();
3600 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003601
Austin Schuh0e96d372023-05-08 10:10:21 -07003602 ASSERT_EQ(actual_err, expected_err);
3603 counter.Count(actual_err);
3604 msgs_sent++;
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003605
Austin Schuh0e96d372023-05-08 10:10:21 -07003606 EXPECT_EQ(counter.failures(),
3607 msgs_sent <= queue_size
3608 ? 0
3609 : (msgs_sent - queue_size) -
3610 (actual_err == RawSender::Error::kOk ? 1 : 0));
3611 EXPECT_EQ(counter.just_failed(), actual_err != RawSender::Error::kOk);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003612
Austin Schuh0e96d372023-05-08 10:10:21 -07003613 if (done_waiting) {
3614 Exit();
3615 return;
3616 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003617 }
3618 },
3619 kInterval);
3620 Run();
3621}
3622
3623// Tests that RawSender::Error::kMessagesSentTooFast is returned
3624// when messages are sent too fast from senders in different loops
3625TEST_P(AbstractEventLoopTest, SendingTooFastWithMultipleLoops) {
3626 auto loop1 = MakePrimary();
3627 auto loop2 = Make();
3628
3629 auto sender1 = loop1->MakeSender<TestMessage>("/test");
3630 auto sender2 = loop2->MakeSender<TestMessage>("/test");
3631
3632 // Send queue_size messages split between the senders.
3633 const int queue_size = TestChannelQueueSize(loop1.get());
3634 for (int i = 0; i < queue_size / 2; i++) {
3635 ASSERT_EQ(SendTestMessage(sender1), RawSender::Error::kOk);
3636 ASSERT_EQ(SendTestMessage(sender2), RawSender::Error::kOk);
3637 }
3638
3639 // Since queue_size messages have been sent, this should return an error
3640 EXPECT_EQ(SendTestMessage(sender2), RawSender::Error::kMessagesSentTooFast);
3641}
3642
Austin Schuhdda6db72023-06-21 17:02:34 -07003643// Tests that a longer storage durations store more messages.
3644TEST_P(AbstractEventLoopTest, SendingTooFastWithLongDuration) {
3645 auto loop1 = MakePrimary();
3646
3647 auto sender1 = loop1->MakeSender<TestMessage>("/test3");
3648
3649 // Send queue_size messages split between the senders.
3650 const int queue_size =
3651 configuration::QueueSize(loop1->configuration(), sender1.channel());
3652 EXPECT_EQ(queue_size, 100 * 10);
3653 for (int i = 0; i < queue_size; i++) {
3654 ASSERT_EQ(SendTestMessage(sender1), RawSender::Error::kOk);
3655 }
3656
3657 // Since queue_size messages have been sent, and little time has elapsed,
3658 // this should return an error.
3659 EXPECT_EQ(SendTestMessage(sender1), RawSender::Error::kMessagesSentTooFast);
3660}
3661
Parker Schuhe4a70d62017-12-27 20:10:20 -08003662} // namespace testing
3663} // namespace aos