blob: 5ec494f71cb023e56ef985925244474b2c045e6a [file] [log] [blame]
Alex Perrycb7da4b2019-08-28 19:35:56 -07001#include "aos/events/event_loop_param_test.h"
Parker Schuhe4a70d62017-12-27 20:10:20 -08002
Austin Schuh52d325c2019-06-23 18:59:06 -07003#include <chrono>
Brian Silverman4f4e0612020-08-12 19:54:41 -07004#include <unordered_map>
5#include <unordered_set>
Austin Schuh52d325c2019-06-23 18:59:06 -07006
Philipp Schrader790cb542023-07-05 21:06:52 -07007#include "glog/logging.h"
8#include "gmock/gmock.h"
9#include "gtest/gtest.h"
10
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -070011#include "aos/events/test_message_generated.h"
James Kuszmaulb1c11052023-11-06 13:20:53 -080012#include "aos/events/test_message_static.h"
Austin Schuh54cf95f2019-11-29 13:14:18 -080013#include "aos/flatbuffer_merge.h"
Austin Schuhad9e5eb2021-11-19 20:33:55 -080014#include "aos/logging/log_message_generated.h"
15#include "aos/logging/logging.h"
Austin Schuhcc6070c2020-10-10 20:25:56 -070016#include "aos/realtime.h"
Austin Schuh9fe68f72019-08-10 19:32:03 -070017
Parker Schuhe4a70d62017-12-27 20:10:20 -080018namespace aos {
19namespace testing {
Austin Schuh52d325c2019-06-23 18:59:06 -070020namespace {
21namespace chrono = ::std::chrono;
22} // namespace
Parker Schuhe4a70d62017-12-27 20:10:20 -080023
Brian Silverman4f4e0612020-08-12 19:54:41 -070024::std::unique_ptr<EventLoop> AbstractEventLoopTest::Make(
25 std::string_view name) {
26 std::string name_copy(name);
27 if (name == "") {
28 name_copy = "loop";
29 name_copy += std::to_string(event_loop_count_);
30 }
31 ++event_loop_count_;
Austin Schuh6bae8252021-02-07 22:01:49 -080032 auto result = factory_->Make(name_copy);
33 if (do_timing_reports() == DoTimingReports::kNo) {
34 result->SkipTimingReport();
35 }
36 return result;
Brian Silverman4f4e0612020-08-12 19:54:41 -070037}
38
39void AbstractEventLoopTest::VerifyBuffers(
40 int number_buffers,
41 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>> fetchers,
42 std::vector<std::reference_wrapper<const Sender<TestMessage>>> senders) {
43 // The buffers which are in a sender.
44 std::unordered_set<int> in_sender;
45 for (const Sender<TestMessage> &sender : senders) {
46 const int this_buffer = sender.buffer_index();
47 CHECK_GE(this_buffer, 0);
48 CHECK_LT(this_buffer, number_buffers);
49 CHECK(in_sender.insert(this_buffer).second) << ": " << this_buffer;
50 }
51
52 if (read_method() != ReadMethod::PIN) {
53 // If we're not using PIN, we can't really verify anything about what
54 // buffers the fetchers have.
55 return;
56 }
57
58 // Mapping from TestMessage::value to buffer index.
59 std::unordered_map<int, int> fetcher_values;
60 for (const Fetcher<TestMessage> &fetcher : fetchers) {
61 if (!fetcher.get()) {
62 continue;
63 }
64 const int this_buffer = fetcher.context().buffer_index;
65 CHECK_GE(this_buffer, 0);
66 CHECK_LT(this_buffer, number_buffers);
67 CHECK(in_sender.count(this_buffer) == 0) << ": " << this_buffer;
68 const auto insert_result = fetcher_values.insert(
69 std::make_pair(fetcher.get()->value(), this_buffer));
70 if (!insert_result.second) {
71 CHECK_EQ(this_buffer, insert_result.first->second);
72 }
73 }
74}
75
Austin Schuh6b6dfa52019-06-12 20:16:20 -070076// Tests that watcher can receive messages from a sender.
Parker Schuhe4a70d62017-12-27 20:10:20 -080077// Also tests that OnRun() works.
78TEST_P(AbstractEventLoopTest, Basic) {
79 auto loop1 = Make();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070080 auto loop2 = MakePrimary();
81
Alex Perrycb7da4b2019-08-28 19:35:56 -070082 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
Austin Schuh6b6dfa52019-06-12 20:16:20 -070083
84 bool happened = false;
85
86 loop2->OnRun([&]() {
87 happened = true;
88
Alex Perrycb7da4b2019-08-28 19:35:56 -070089 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
90 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
91 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -070092 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -070093 });
94
95 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070096 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -070097 this->Exit();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070098 });
99
100 EXPECT_FALSE(happened);
101 Run();
102 EXPECT_TRUE(happened);
103}
104
James Kuszmaulb1c11052023-11-06 13:20:53 -0800105// Tests that watcher can receive messages from a static sender.
106// This confirms that the "static" flatbuffer API works with the EventLoop
107// senders.
108TEST_P(AbstractEventLoopTest, BasicStatic) {
109 auto loop1 = Make();
110 auto loop2 = MakePrimary();
111
112 aos::Sender<TestMessageStatic> sender =
113 loop1->MakeSender<TestMessageStatic>("/test");
114
115 bool happened = false;
116
117 loop2->OnRun([&]() {
118 happened = true;
119
120 aos::Sender<TestMessageStatic>::StaticBuilder msg =
121 sender.MakeStaticBuilder();
James Kuszmauldde65632023-12-07 16:12:26 -0800122 msg->set_value(200);
James Kuszmaulb1c11052023-11-06 13:20:53 -0800123 CHECK(msg.builder()->Verify());
124 msg.CheckOk(msg.Send());
125 });
126
127 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
128 EXPECT_EQ(message.value(), 200);
129 this->Exit();
130 });
131
132 EXPECT_FALSE(happened);
133 Run();
134 EXPECT_TRUE(happened);
135}
136
Brian Silverman341b57e2020-06-23 16:23:18 -0700137// Tests that watcher can receive messages from a sender, sent via SendDetached.
138TEST_P(AbstractEventLoopTest, BasicSendDetached) {
139 auto loop1 = Make();
140 auto loop2 = MakePrimary();
141
142 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
143
144 FlatbufferDetachedBuffer<TestMessage> detached =
145 flatbuffers::DetachedBuffer();
146 {
147 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
148 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
149 builder.add_value(100);
150 detached = msg.Detach(builder.Finish());
151 }
152 detached = flatbuffers::DetachedBuffer();
153 {
154 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
155 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
156 builder.add_value(200);
157 detached = msg.Detach(builder.Finish());
158 }
milind1f1dca32021-07-03 13:50:07 -0700159 sender.CheckOk(sender.SendDetached(std::move(detached)));
Brian Silverman341b57e2020-06-23 16:23:18 -0700160
161 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
162 ASSERT_TRUE(fetcher.Fetch());
163 EXPECT_EQ(fetcher->value(), 200);
164}
165
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800166// Verifies that a no-arg watcher will not have a data pointer.
167TEST_P(AbstractEventLoopTest, NoArgNoData) {
168 auto loop1 = Make();
169 auto loop2 = MakePrimary();
170
171 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
172
173 bool happened = false;
174
175 loop2->OnRun([&]() {
176 happened = true;
177
178 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
179 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -0700180 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800181 });
182
183 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
184 EXPECT_GT(loop2->context().size, 0u);
185 EXPECT_EQ(nullptr, loop2->context().data);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700186 EXPECT_EQ(-1, loop2->context().buffer_index);
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800187 this->Exit();
188 });
189
190 EXPECT_FALSE(happened);
191 Run();
192 EXPECT_TRUE(happened);
193}
194
Brian Silverman454bc112020-03-05 14:21:25 -0800195// Tests that no-arg watcher can receive messages from a sender.
196// Also tests that OnRun() works.
197TEST_P(AbstractEventLoopTest, BasicNoArg) {
198 auto loop1 = Make();
199 auto loop2 = MakePrimary();
200
201 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
202
203 bool happened = false;
204
205 loop2->OnRun([&]() {
206 happened = true;
207
208 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
209 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
210 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700211 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -0800212 });
213
214 aos::Fetcher<TestMessage> fetcher = loop2->MakeFetcher<TestMessage>("/test");
215 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
216 ASSERT_TRUE(fetcher.Fetch());
217 EXPECT_EQ(fetcher->value(), 200);
218 this->Exit();
219 });
220
221 EXPECT_FALSE(happened);
222 Run();
223 EXPECT_TRUE(happened);
224}
225
226// Tests that a watcher can be created with an std::function.
227TEST_P(AbstractEventLoopTest, BasicFunction) {
228 auto loop1 = Make();
229 auto loop2 = MakePrimary();
230
231 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
232
233 bool happened = false;
234
235 loop2->OnRun([&]() {
236 happened = true;
237
238 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
239 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
240 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700241 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -0800242 });
243
244 loop2->MakeWatcher("/test", std::function<void(const TestMessage &)>(
245 [&](const TestMessage &message) {
246 EXPECT_EQ(message.value(), 200);
247 this->Exit();
248 }));
249
250 EXPECT_FALSE(happened);
251 Run();
252 EXPECT_TRUE(happened);
253}
254
Brian Silverman0fc69932020-01-24 21:54:02 -0800255// Tests that watcher can receive messages from two senders.
256// Also tests that OnRun() works.
257TEST_P(AbstractEventLoopTest, BasicTwoSenders) {
258 auto loop1 = Make();
259 auto loop2 = MakePrimary();
260
261 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
262 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
263
264 bool happened = false;
265
266 loop2->OnRun([&]() {
267 happened = true;
268
269 {
270 aos::Sender<TestMessage>::Builder msg = sender1.MakeBuilder();
271 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
272 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700273 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman0fc69932020-01-24 21:54:02 -0800274 }
275 {
276 aos::Sender<TestMessage>::Builder msg = sender2.MakeBuilder();
277 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
278 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700279 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman0fc69932020-01-24 21:54:02 -0800280 }
281 });
282
283 int messages_received = 0;
284 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
285 EXPECT_EQ(message.value(), 200);
286 this->Exit();
287 ++messages_received;
288 });
289
290 EXPECT_FALSE(happened);
291 Run();
292 EXPECT_TRUE(happened);
293 EXPECT_EQ(messages_received, 2);
294}
295
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700296// Tests that a fetcher can fetch from a sender.
297// Also tests that OnRun() works.
298TEST_P(AbstractEventLoopTest, FetchWithoutRun) {
299 auto loop1 = Make();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800300 auto loop2 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -0700301 auto loop3 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800302
303 auto sender = loop1->MakeSender<TestMessage>("/test");
304
305 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
306
Austin Schuhbbce72d2019-05-26 15:11:46 -0700307 EXPECT_FALSE(fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -0800308 EXPECT_EQ(fetcher.get(), nullptr);
309
Austin Schuhad154822019-12-27 15:45:13 -0800310 EXPECT_EQ(fetcher.context().monotonic_event_time, monotonic_clock::min_time);
311 EXPECT_EQ(fetcher.context().monotonic_remote_time, monotonic_clock::min_time);
312 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
313 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -0700314 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
Austin Schuh39788ff2019-12-01 18:22:57 -0800315 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
316 EXPECT_EQ(fetcher.context().size, 0u);
317 EXPECT_EQ(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700318 EXPECT_EQ(fetcher.context().buffer_index, -1);
Austin Schuhbbce72d2019-05-26 15:11:46 -0700319
Alex Perrycb7da4b2019-08-28 19:35:56 -0700320 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
321 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
322 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700323 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700324
325 EXPECT_TRUE(fetcher.Fetch());
326 ASSERT_FALSE(fetcher.get() == nullptr);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700327 EXPECT_EQ(fetcher.get()->value(), 200);
Austin Schuh39788ff2019-12-01 18:22:57 -0800328
329 const chrono::milliseconds kEpsilon(100);
330
Austin Schuhad154822019-12-27 15:45:13 -0800331 const aos::monotonic_clock::time_point monotonic_now = loop2->monotonic_now();
332 const aos::realtime_clock::time_point realtime_now = loop2->realtime_now();
333 EXPECT_EQ(fetcher.context().monotonic_event_time,
334 fetcher.context().monotonic_remote_time);
335 EXPECT_EQ(fetcher.context().realtime_event_time,
336 fetcher.context().realtime_remote_time);
337
338 EXPECT_GE(fetcher.context().monotonic_event_time, monotonic_now - kEpsilon);
339 EXPECT_LE(fetcher.context().monotonic_event_time, monotonic_now + kEpsilon);
340 EXPECT_GE(fetcher.context().realtime_event_time, realtime_now - kEpsilon);
341 EXPECT_LE(fetcher.context().realtime_event_time, realtime_now + kEpsilon);
Austin Schuha9012be2021-07-21 15:19:11 -0700342 EXPECT_EQ(fetcher.context().source_boot_uuid, loop2->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -0800343 EXPECT_EQ(fetcher.context().queue_index, 0x0u);
344 EXPECT_EQ(fetcher.context().size, 20u);
345 EXPECT_NE(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700346 if (read_method() == ReadMethod::PIN) {
347 EXPECT_GE(fetcher.context().buffer_index, 0);
348 EXPECT_LT(fetcher.context().buffer_index,
349 loop2->NumberBuffers(fetcher.channel()));
350 } else {
351 EXPECT_EQ(fetcher.context().buffer_index, -1);
352 }
Parker Schuhe4a70d62017-12-27 20:10:20 -0800353}
354
Austin Schuh98ed26f2023-07-19 14:12:28 -0700355std::function<bool(const Context &)> MakeShouldFetch(
356 bool should_fetch, size_t *called_count = nullptr) {
357 return [should_fetch, called_count](const Context &) {
358 if (called_count != nullptr) {
359 (*called_count)++;
360 }
361 return should_fetch;
362 };
363}
364
365// Tests that a fetcher using FetchIf can fetch from a sender.
366TEST_P(AbstractEventLoopTest, FetchIfWithoutRun) {
367 auto loop1 = Make();
368 auto loop2 = Make();
369 auto loop3 = MakePrimary();
370
371 auto sender = loop1->MakeSender<TestMessage>("/test");
372
373 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
374
375 for (const bool should_fetch : {true, false}) {
376 EXPECT_FALSE(fetcher.FetchIf(MakeShouldFetch(should_fetch)));
377 EXPECT_EQ(fetcher.get(), nullptr);
378
379 EXPECT_EQ(fetcher.context().monotonic_event_time,
380 monotonic_clock::min_time);
381 EXPECT_EQ(fetcher.context().monotonic_remote_time,
382 monotonic_clock::min_time);
383 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
384 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
385 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
386 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
387 EXPECT_EQ(fetcher.context().size, 0u);
388 EXPECT_EQ(fetcher.context().data, nullptr);
389 EXPECT_EQ(fetcher.context().buffer_index, -1);
390 }
391
392 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
393 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
394 builder.add_value(200);
395 msg.CheckOk(msg.Send(builder.Finish()));
396
397 // Make sure failing to fetch won't affect anything.
398 EXPECT_FALSE(fetcher.FetchIf(MakeShouldFetch(false)));
399 EXPECT_EQ(fetcher.get(), nullptr);
400
401 EXPECT_EQ(fetcher.context().monotonic_event_time, monotonic_clock::min_time);
402 EXPECT_EQ(fetcher.context().monotonic_remote_time, monotonic_clock::min_time);
403 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
404 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
405 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
406 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
407 EXPECT_EQ(fetcher.context().size, 0u);
408 EXPECT_EQ(fetcher.context().data, nullptr);
409 EXPECT_EQ(fetcher.context().buffer_index, -1);
410
411 // And now confirm we succeed and everything gets set right.
412 EXPECT_TRUE(fetcher.FetchIf(MakeShouldFetch(true)));
413 ASSERT_FALSE(fetcher.get() == nullptr);
414 EXPECT_EQ(fetcher.get()->value(), 200);
415
416 const chrono::milliseconds kEpsilon(100);
417
418 const aos::monotonic_clock::time_point monotonic_now = loop2->monotonic_now();
419 const aos::realtime_clock::time_point realtime_now = loop2->realtime_now();
420 EXPECT_EQ(fetcher.context().monotonic_event_time,
421 fetcher.context().monotonic_remote_time);
422 EXPECT_EQ(fetcher.context().realtime_event_time,
423 fetcher.context().realtime_remote_time);
424
425 EXPECT_GE(fetcher.context().monotonic_event_time, monotonic_now - kEpsilon);
426 EXPECT_LE(fetcher.context().monotonic_event_time, monotonic_now + kEpsilon);
427 EXPECT_GE(fetcher.context().realtime_event_time, realtime_now - kEpsilon);
428 EXPECT_LE(fetcher.context().realtime_event_time, realtime_now + kEpsilon);
429 EXPECT_EQ(fetcher.context().source_boot_uuid, loop2->boot_uuid());
430 EXPECT_EQ(fetcher.context().queue_index, 0x0u);
431 EXPECT_EQ(fetcher.context().size, 20u);
432 EXPECT_NE(fetcher.context().data, nullptr);
433 if (read_method() == ReadMethod::PIN) {
434 EXPECT_GE(fetcher.context().buffer_index, 0);
435 EXPECT_LT(fetcher.context().buffer_index,
436 loop2->NumberBuffers(fetcher.channel()));
437 } else {
438 EXPECT_EQ(fetcher.context().buffer_index, -1);
439 }
440}
441
Austin Schuh3578a2e2019-05-25 18:17:59 -0700442// Tests that watcher will receive all messages sent if they are sent after
443// initialization and before running.
444TEST_P(AbstractEventLoopTest, DoubleSendAtStartup) {
445 auto loop1 = Make();
446 auto loop2 = MakePrimary();
447
448 auto sender = loop1->MakeSender<TestMessage>("/test");
449
450 ::std::vector<int> values;
451
452 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700453 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700454 if (values.size() == 2) {
Austin Schuh9fe68f72019-08-10 19:32:03 -0700455 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -0700456 }
457 });
458
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700459 // Before Run, should be ignored.
Austin Schuh3578a2e2019-05-25 18:17:59 -0700460 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700461 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
462 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
463 builder.add_value(199);
milind1f1dca32021-07-03 13:50:07 -0700464 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700465 }
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700466
467 loop2->OnRun([&]() {
Austin Schuh98ed26f2023-07-19 14:12:28 -0700468 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700469 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
470 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700471 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700472 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700473 }
474 });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700475
476 Run();
477
478 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
479}
480
481// Tests that watcher will not receive messages sent before the watcher is
482// created.
483TEST_P(AbstractEventLoopTest, DoubleSendAfterStartup) {
484 auto loop1 = Make();
485 auto loop2 = MakePrimary();
486
487 auto sender = loop1->MakeSender<TestMessage>("/test");
488
489 ::std::vector<int> values;
490
Austin Schuh98ed26f2023-07-19 14:12:28 -0700491 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700492 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
493 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700494 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700495 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700496 }
497
498 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700499 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700500 });
501
502 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700503 auto test_timer = loop2->AddTimer([this]() { this->Exit(); });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700504 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700505 test_timer->Schedule(loop2->monotonic_now(),
506 ::std::chrono::milliseconds(100));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700507 });
508
509 Run();
510 EXPECT_EQ(0, values.size());
511}
512
Austin Schuhbbce72d2019-05-26 15:11:46 -0700513// Tests that FetchNext gets all the messages sent after it is constructed.
514TEST_P(AbstractEventLoopTest, FetchNext) {
515 auto loop1 = Make();
516 auto loop2 = MakePrimary();
517
518 auto sender = loop1->MakeSender<TestMessage>("/test");
519 auto fetcher = loop2->MakeFetcher<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 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700531 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700532 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700533 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700534 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700535 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700536 });
537
538 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700539 test_timer->Schedule(loop2->monotonic_now(),
540 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700541 });
542
543 Run();
544 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
545}
546
547// Tests that FetchNext gets no messages sent before it is constructed.
548TEST_P(AbstractEventLoopTest, FetchNextAfterSend) {
549 auto loop1 = Make();
550 auto loop2 = MakePrimary();
551
552 auto sender = loop1->MakeSender<TestMessage>("/test");
553
554 ::std::vector<int> values;
555
Austin Schuh98ed26f2023-07-19 14:12:28 -0700556 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700557 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
558 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700559 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700560 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700561 }
562
563 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
564
565 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700566 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700567 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700568 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700569 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700570 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700571 });
572
573 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700574 test_timer->Schedule(loop2->monotonic_now(),
575 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700576 });
577
578 Run();
579 EXPECT_THAT(0, values.size());
580}
581
Austin Schuh98ed26f2023-07-19 14:12:28 -0700582// Tests that FetchNextIf gets no messages sent before it is constructed.
583TEST_P(AbstractEventLoopTest, FetchNextIfAfterSend) {
584 auto loop1 = Make();
585 auto loop2 = MakePrimary();
586
587 auto sender = loop1->MakeSender<TestMessage>("/test");
588
589 ::std::vector<int> values;
590
591 for (int i = 200; i < 202; ++i) {
592 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
593 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
594 builder.add_value(i);
595 msg.CheckOk(msg.Send(builder.Finish()));
596 }
597
598 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
599
600 // Add a timer to actually quit.
601 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
602 while (fetcher.FetchNextIf(MakeShouldFetch(true))) {
603 values.push_back(fetcher.get()->value());
604 }
605 this->Exit();
606 });
607
608 loop2->OnRun([&test_timer, &loop2]() {
609 test_timer->Schedule(loop2->monotonic_now(),
610 ::std::chrono::milliseconds(100));
611 });
612
613 Run();
614 EXPECT_EQ(0, values.size());
615}
616
Austin Schuhbbce72d2019-05-26 15:11:46 -0700617// Tests that Fetch returns the last message created before the loop was
618// started.
619TEST_P(AbstractEventLoopTest, FetchDataFromBeforeCreation) {
620 auto loop1 = Make();
621 auto loop2 = MakePrimary();
622
623 auto sender = loop1->MakeSender<TestMessage>("/test");
624
625 ::std::vector<int> values;
626
Austin Schuh98ed26f2023-07-19 14:12:28 -0700627 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700628 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
629 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700630 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700631 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700632 }
633
634 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
635
636 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700637 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700638 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700639 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700640 }
641 // Do it again to make sure we don't double fetch.
642 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700643 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700644 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700645 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700646 });
647
648 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700649 test_timer->Schedule(loop2->monotonic_now(),
650 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700651 });
652
653 Run();
654 EXPECT_THAT(values, ::testing::ElementsAreArray({201}));
655}
656
Austin Schuh98ed26f2023-07-19 14:12:28 -0700657// Tests that FetchIf returns the last message created before the loop was
658// started.
659TEST_P(AbstractEventLoopTest, FetchIfDataFromBeforeCreation) {
660 auto loop1 = Make();
661 auto loop2 = MakePrimary();
662
663 auto sender = loop1->MakeSender<TestMessage>("/test");
664
665 ::std::vector<int> values;
666
667 for (int i = 200; i < 202; ++i) {
668 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
669 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
670 builder.add_value(i);
671 msg.CheckOk(msg.Send(builder.Finish()));
672 }
673
674 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
675
676 // Add a timer to actually quit.
677 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
678 if (fetcher.FetchIf(MakeShouldFetch(true))) {
679 values.push_back(fetcher.get()->value());
680 }
681
682 if (fetcher.FetchIf(MakeShouldFetch(false))) {
683 values.push_back(fetcher.get()->value());
684 }
685 // Do it again to make sure we don't double fetch.
686 if (fetcher.FetchIf(MakeShouldFetch(true))) {
687 values.push_back(fetcher.get()->value());
688 }
689 this->Exit();
690 });
691
692 loop2->OnRun([&test_timer, &loop2]() {
693 test_timer->Schedule(loop2->monotonic_now(),
694 ::std::chrono::milliseconds(100));
695 });
696
697 Run();
698 EXPECT_THAT(values, ::testing::ElementsAreArray({201}));
699}
700
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700701// Tests that timer handler is enabled after setup (even if it is in the past)
702// and is disabled after running
703TEST_P(AbstractEventLoopTest, CheckTimerDisabled) {
704 auto loop = MakePrimary("primary");
705
706 auto timer = loop->AddTimer([this]() {
707 LOG(INFO) << "timer called";
708 Exit();
709 });
710
711 loop->OnRun([&loop, timer]() {
712 EXPECT_TRUE(timer->IsDisabled());
Philipp Schradera6712522023-07-05 20:25:11 -0700713 timer->Schedule(loop->monotonic_now() + chrono::milliseconds(100));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700714 EXPECT_FALSE(timer->IsDisabled());
715 });
716
717 Run();
718 EXPECT_TRUE(timer->IsDisabled());
719}
720
721// Tests that timer handler is enabled after setup (even if it is in the past)
722// and is disabled after running
723TEST_P(AbstractEventLoopTest, CheckTimerRunInPastDisabled) {
724 auto loop = MakePrimary("primary");
725
726 auto timer2 = loop->AddTimer([this]() {
727 LOG(INFO) << "timer called";
728 Exit();
729 });
730
731 auto timer = loop->AddTimer([&loop, timer2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700732 timer2->Schedule(loop->monotonic_now() - chrono::nanoseconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700733 });
734
735 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700736 timer->Schedule(loop->monotonic_now() + chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700737 EXPECT_FALSE(timer->IsDisabled());
738 });
739
740 Run();
741 EXPECT_TRUE(timer2->IsDisabled());
742}
743
744// Tests that timer handler is not disabled even after calling Exit on the event
745// loop within the timer
746TEST_P(AbstractEventLoopTest, CheckTimerRepeatOnCountDisabled) {
747 auto loop = MakePrimary("primary");
748 int counter = 0;
749
750 auto timer = loop->AddTimer([&counter, this]() {
751 LOG(INFO) << "timer called";
752 counter++;
753 if (counter >= 5) {
754 Exit();
755 }
756 });
757
758 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700759 timer->Schedule(loop->monotonic_now() + chrono::seconds(1),
760 chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700761 EXPECT_FALSE(timer->IsDisabled());
762 });
763 Run();
764
765 // Sanity check
766 EXPECT_EQ(counter, 5);
767
768 // if you run the loop again, the timer will start running again
769 EXPECT_FALSE(timer->IsDisabled());
770
771 counter = 0;
772 Run();
773 timer->Disable();
774
775 EXPECT_TRUE(timer->IsDisabled());
776}
777
778// Tests that timer handler is not disabled even after calling Exit on the event
779// loop using an external timer
780TEST_P(AbstractEventLoopTest, CheckTimerRepeatTillEndTimerDisabled) {
781 auto loop = MakePrimary("primary");
782
783 auto timer = loop->AddTimer([]() { LOG(INFO) << "timer called"; });
784
785 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700786 timer->Schedule(loop->monotonic_now() + chrono::seconds(1),
787 chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700788 EXPECT_FALSE(timer->IsDisabled());
789 });
790
791 EndEventLoop(loop.get(), chrono::seconds(5));
792 Run();
793 EXPECT_FALSE(timer->IsDisabled());
794
795 timer->Disable();
796 EXPECT_TRUE(timer->IsDisabled());
797}
798
Austin Schuhbbce72d2019-05-26 15:11:46 -0700799// Tests that Fetch and FetchNext interleave as expected.
800TEST_P(AbstractEventLoopTest, FetchAndFetchNextTogether) {
801 auto loop1 = Make();
802 auto loop2 = MakePrimary();
803
804 auto sender = loop1->MakeSender<TestMessage>("/test");
805
806 ::std::vector<int> values;
807
Austin Schuh98ed26f2023-07-19 14:12:28 -0700808 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700809 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
810 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700811 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700812 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700813 }
814
815 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
816
817 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700818 auto test_timer = loop2->AddTimer([&fetcher, &values, &sender, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700819 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700820 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700821 }
822
Austin Schuh98ed26f2023-07-19 14:12:28 -0700823 for (int i = 202; i < 205; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700824 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
825 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700826 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700827 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700828 }
829
830 if (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700831 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700832 }
833
834 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700835 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700836 }
837
Austin Schuh9fe68f72019-08-10 19:32:03 -0700838 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700839 });
840
841 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700842 test_timer->Schedule(loop2->monotonic_now(),
843 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700844 });
845
846 Run();
847 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
848}
849
Austin Schuh98ed26f2023-07-19 14:12:28 -0700850// Tests that Fetch{If,} and FetchNext{If,} interleave as expected.
851TEST_P(AbstractEventLoopTest, FetchAndFetchNextIfTogether) {
852 auto loop1 = Make();
853 auto loop2 = MakePrimary();
854
855 auto sender = loop1->MakeSender<TestMessage>("/test");
856
857 ::std::vector<int> values;
858
859 for (int i = 200; i < 202; ++i) {
860 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
861 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
862 builder.add_value(i);
863 msg.CheckOk(msg.Send(builder.Finish()));
864 }
865
866 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
867
868 // Add a timer to actually quit.
869 auto test_timer = loop2->AddTimer([&fetcher, &values, &sender, this]() {
870 if (fetcher.Fetch()) {
871 values.push_back(fetcher.get()->value());
872 }
873
874 for (int i = 202; i < 205; ++i) {
875 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
876 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
877 builder.add_value(i);
878 msg.CheckOk(msg.Send(builder.Finish()));
879 }
880
881 EXPECT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false)));
882
883 if (fetcher.FetchNext()) {
884 values.push_back(fetcher.get()->value());
885 }
886
887 EXPECT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false)));
888 EXPECT_FALSE(fetcher.FetchIf(MakeShouldFetch(false)));
889
890 if (fetcher.FetchIf(MakeShouldFetch(true))) {
891 values.push_back(fetcher.get()->value());
892 }
893
894 this->Exit();
895 });
896
897 loop2->OnRun([&test_timer, &loop2]() {
898 test_timer->Schedule(loop2->monotonic_now(),
899 ::std::chrono::milliseconds(100));
900 });
901
902 Run();
903 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
904}
905
Austin Schuh3115a202019-05-27 21:02:14 -0700906// Tests that FetchNext behaves correctly when we get two messages in the queue
907// but don't consume the first until after the second has been sent.
908TEST_P(AbstractEventLoopTest, FetchNextTest) {
Austin Schuh3115a202019-05-27 21:02:14 -0700909 auto send_loop = Make();
910 auto fetch_loop = Make();
911 auto sender = send_loop->MakeSender<TestMessage>("/test");
912 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
913
914 {
Tyler Chatow67ddb032020-01-12 14:30:04 -0800915 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
916 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
917 builder.add_value(100);
milind1f1dca32021-07-03 13:50:07 -0700918 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700919 }
920
921 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700922 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
923 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
924 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700925 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700926 }
927
928 ASSERT_TRUE(fetcher.FetchNext());
929 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700930 EXPECT_EQ(100, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700931
932 ASSERT_TRUE(fetcher.FetchNext());
933 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700934 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700935
936 // When we run off the end of the queue, expect to still have the old message:
937 ASSERT_FALSE(fetcher.FetchNext());
938 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700939 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700940}
941
Austin Schuh98ed26f2023-07-19 14:12:28 -0700942// Tests that FetchNext behaves correctly when we get two messages in the queue
943// but don't consume the first until after the second has been sent.
944TEST_P(AbstractEventLoopTest, FetchNextIfTest) {
945 auto send_loop = Make();
946 auto fetch_loop = Make();
947 auto sender = send_loop->MakeSender<TestMessage>("/test");
948 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
949
950 {
951 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
952 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
953 builder.add_value(100);
954 msg.CheckOk(msg.Send(builder.Finish()));
955 }
956
957 {
958 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
959 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
960 builder.add_value(200);
961 msg.CheckOk(msg.Send(builder.Finish()));
962 }
963
964 size_t called_count = 0;
965 ASSERT_TRUE(fetcher.FetchNextIf(MakeShouldFetch(true, &called_count)));
966 ASSERT_NE(nullptr, fetcher.get());
967 EXPECT_EQ(100, fetcher.get()->value());
968 EXPECT_EQ(called_count, 1u);
969
970 ASSERT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false, &called_count)));
971 EXPECT_EQ(called_count, 2u);
972
973 ASSERT_TRUE(fetcher.FetchNextIf(MakeShouldFetch(true, &called_count)));
974 ASSERT_NE(nullptr, fetcher.get());
975 EXPECT_EQ(200, fetcher.get()->value());
976 EXPECT_EQ(called_count, 3u);
977
978 // When we run off the end of the queue, expect to still have the old message:
979 ASSERT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false, &called_count)));
980 EXPECT_EQ(called_count, 3u);
981 ASSERT_NE(nullptr, fetcher.get());
982 EXPECT_EQ(200, fetcher.get()->value());
983}
984
Brian Silverman77162972020-08-12 19:52:40 -0700985// Verify that a fetcher still holds its data, even after falling behind.
986TEST_P(AbstractEventLoopTest, FetcherBehindData) {
987 auto send_loop = Make();
988 auto fetch_loop = Make();
989 auto sender = send_loop->MakeSender<TestMessage>("/test");
990 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
991 {
992 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
993 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
994 builder.add_value(1);
milind1f1dca32021-07-03 13:50:07 -0700995 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -0700996 }
997 ASSERT_TRUE(fetcher.Fetch());
998 EXPECT_EQ(1, fetcher.get()->value());
999 for (int i = 0; i < 300; ++i) {
1000 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1001 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1002 builder.add_value(i + 2);
milind1f1dca32021-07-03 13:50:07 -07001003 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -07001004 }
1005 EXPECT_EQ(1, fetcher.get()->value());
1006}
1007
1008// Try a bunch of orderings of operations with fetchers and senders. Verify that
1009// all the fetchers have the correct data at each step.
1010TEST_P(AbstractEventLoopTest, FetcherPermutations) {
1011 for (int max_save = 0; max_save < 5; ++max_save) {
1012 SCOPED_TRACE("max_save=" + std::to_string(max_save));
1013
1014 auto send_loop = Make();
1015 auto fetch_loop = Make();
1016 auto sender = send_loop->MakeSender<TestMessage>("/test");
1017 const auto send_message = [&sender](int i) {
1018 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1019 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1020 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -07001021 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -07001022 };
1023 std::vector<Fetcher<TestMessage>> fetchers;
1024 for (int i = 0; i < 10; ++i) {
1025 fetchers.emplace_back(fetch_loop->MakeFetcher<TestMessage>("/test"));
1026 }
1027 send_message(1);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001028 const auto verify_buffers = [&]() {
1029 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>>
1030 fetchers_copy;
1031 for (const auto &fetcher : fetchers) {
1032 fetchers_copy.emplace_back(fetcher);
1033 }
1034 std::vector<std::reference_wrapper<const Sender<TestMessage>>>
1035 senders_copy;
1036 senders_copy.emplace_back(sender);
1037 VerifyBuffers(send_loop->NumberBuffers(sender.channel()), fetchers_copy,
1038 senders_copy);
1039 };
Brian Silverman77162972020-08-12 19:52:40 -07001040 for (auto &fetcher : fetchers) {
1041 ASSERT_TRUE(fetcher.Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -07001042 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001043 EXPECT_EQ(1, fetcher.get()->value());
1044 }
1045
1046 for (int save = 1; save <= max_save; ++save) {
1047 SCOPED_TRACE("save=" + std::to_string(save));
1048 send_message(100 + save);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001049 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001050 for (size_t i = 0; i < fetchers.size() - save; ++i) {
1051 SCOPED_TRACE("fetcher=" + std::to_string(i));
1052 ASSERT_TRUE(fetchers[i].Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -07001053 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001054 EXPECT_EQ(100 + save, fetchers[i].get()->value());
1055 }
1056 for (size_t i = fetchers.size() - save; i < fetchers.size() - 1; ++i) {
1057 SCOPED_TRACE("fetcher=" + std::to_string(i));
1058 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
1059 }
1060 EXPECT_EQ(1, fetchers.back().get()->value());
1061 }
1062
1063 for (int i = 0; i < 300; ++i) {
1064 send_message(200 + i);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001065 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001066 }
1067
1068 for (size_t i = 0; i < fetchers.size() - max_save; ++i) {
1069 SCOPED_TRACE("fetcher=" + std::to_string(i));
1070 if (max_save > 0) {
1071 EXPECT_EQ(100 + max_save, fetchers[i].get()->value());
1072 } else {
1073 EXPECT_EQ(1, fetchers[i].get()->value());
1074 }
1075 }
1076 for (size_t i = fetchers.size() - max_save; i < fetchers.size() - 1; ++i) {
1077 SCOPED_TRACE("fetcher=" + std::to_string(i));
1078 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
1079 }
1080 EXPECT_EQ(1, fetchers.back().get()->value());
1081 }
1082}
1083
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001084// Verify that making a fetcher and watcher for "/test" succeeds.
1085TEST_P(AbstractEventLoopTest, FetcherAndWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -08001086 auto loop = Make();
1087 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001088 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Parker Schuhe4a70d62017-12-27 20:10:20 -08001089}
1090
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001091// Verify that making 2 fetchers for "/test" succeeds.
Parker Schuhe4a70d62017-12-27 20:10:20 -08001092TEST_P(AbstractEventLoopTest, TwoFetcher) {
1093 auto loop = Make();
1094 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001095 auto fetcher2 = loop->MakeFetcher<TestMessage>("/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -08001096}
1097
Alex Perrycb7da4b2019-08-28 19:35:56 -07001098// Verify that registering a watcher for an invalid channel name dies.
1099TEST_P(AbstractEventLoopDeathTest, InvalidChannelName) {
1100 auto loop = Make();
1101 EXPECT_DEATH(
1102 { loop->MakeWatcher("/test/invalid", [&](const TestMessage &) {}); },
1103 "/test/invalid");
Brian Silverman454bc112020-03-05 14:21:25 -08001104 EXPECT_DEATH(
1105 { loop->MakeNoArgWatcher<TestMessage>("/test/invalid", [&]() {}); },
1106 "/test/invalid");
Alex Perrycb7da4b2019-08-28 19:35:56 -07001107}
1108
James Kuszmaul8866e642022-06-10 16:00:36 -07001109// Verify that setting up a timer before monotonic_clock::epoch() fails.
James Kuszmaul86e86c32022-07-21 17:39:47 -07001110TEST_P(AbstractEventLoopDeathTest, NegativeTimeTimer) {
James Kuszmaul8866e642022-06-10 16:00:36 -07001111 auto loop = Make();
1112 TimerHandler *time = loop->AddTimer([]() {});
Philipp Schradera6712522023-07-05 20:25:11 -07001113 EXPECT_DEATH(
1114 time->Schedule(monotonic_clock::epoch() - std::chrono::seconds(1)),
1115 "-1.000");
James Kuszmaul8866e642022-06-10 16:00:36 -07001116}
1117
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001118// Verify that registering a watcher twice for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001119TEST_P(AbstractEventLoopDeathTest, TwoWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -08001120 auto loop = Make();
1121 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001122 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
1123 "/test");
Brian Silverman454bc112020-03-05 14:21:25 -08001124 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
1125}
1126
1127// Verify that registering a no-arg watcher twice for "/test" fails.
1128TEST_P(AbstractEventLoopDeathTest, TwoNoArgWatcher) {
1129 auto loop = Make();
1130 loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {});
1131 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
1132 "/test");
1133 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001134}
1135
Austin Schuh3115a202019-05-27 21:02:14 -07001136// Verify that SetRuntimeRealtimePriority fails while running.
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001137TEST_P(AbstractEventLoopDeathTest, SetRuntimeRealtimePriority) {
Austin Schuh3115a202019-05-27 21:02:14 -07001138 auto loop = MakePrimary();
Austin Schuh65493d62022-08-17 15:10:37 -07001139 EXPECT_EQ(0, loop->runtime_realtime_priority());
Austin Schuh3115a202019-05-27 21:02:14 -07001140 // Confirm that runtime priority calls work when not realtime.
1141 loop->SetRuntimeRealtimePriority(5);
Austin Schuh65493d62022-08-17 15:10:37 -07001142 EXPECT_EQ(5, loop->runtime_realtime_priority());
Austin Schuh3115a202019-05-27 21:02:14 -07001143
1144 loop->OnRun([&]() { loop->SetRuntimeRealtimePriority(5); });
1145
1146 EXPECT_DEATH(Run(), "realtime");
1147}
1148
Austin Schuh65493d62022-08-17 15:10:37 -07001149namespace {
1150
1151bool CpuSetEqual(const cpu_set_t &a, const cpu_set_t &b) {
1152 return CPU_EQUAL(&a, &b);
1153}
1154
1155} // namespace
1156
Brian Silverman6a54ff32020-04-28 16:41:39 -07001157// Verify that SetRuntimeAffinity fails while running.
1158TEST_P(AbstractEventLoopDeathTest, SetRuntimeAffinity) {
Austin Schuhde973292021-10-12 18:09:49 -07001159 const cpu_set_t available = GetCurrentThreadAffinity();
1160 int first_cpu = -1;
1161 for (int i = 0; i < CPU_SETSIZE; ++i) {
1162 if (CPU_ISSET(i, &available)) {
1163 first_cpu = i;
1164 break;
1165 continue;
1166 }
1167 }
1168 CHECK_NE(first_cpu, -1) << ": Default affinity has no CPUs?";
1169
Brian Silverman6a54ff32020-04-28 16:41:39 -07001170 auto loop = MakePrimary();
Austin Schuh65493d62022-08-17 15:10:37 -07001171 EXPECT_TRUE(
1172 CpuSetEqual(EventLoop::DefaultAffinity(), loop->runtime_affinity()));
1173 const cpu_set_t new_affinity = MakeCpusetFromCpus({first_cpu});
Brian Silverman6a54ff32020-04-28 16:41:39 -07001174 // Confirm that runtime priority calls work when not running.
Austin Schuh65493d62022-08-17 15:10:37 -07001175 loop->SetRuntimeAffinity(new_affinity);
1176 EXPECT_TRUE(CpuSetEqual(new_affinity, loop->runtime_affinity()));
Brian Silverman6a54ff32020-04-28 16:41:39 -07001177
Austin Schuhde973292021-10-12 18:09:49 -07001178 loop->OnRun(
1179 [&]() { loop->SetRuntimeAffinity(MakeCpusetFromCpus({first_cpu})); });
Brian Silverman6a54ff32020-04-28 16:41:39 -07001180
1181 EXPECT_DEATH(Run(), "Cannot set affinity while running");
1182}
1183
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001184// Verify that registering a watcher and a sender for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001185TEST_P(AbstractEventLoopDeathTest, WatcherAndSender) {
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001186 auto loop = Make();
1187 auto sender = loop->MakeSender<TestMessage>("/test");
1188 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
1189 "/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -08001190}
1191
Austin Schuhe516ab02020-05-06 21:37:04 -07001192// Verify that creating too many senders fails.
1193TEST_P(AbstractEventLoopDeathTest, TooManySenders) {
1194 auto loop = Make();
1195 std::vector<aos::Sender<TestMessage>> senders;
1196 for (int i = 0; i < 10; ++i) {
1197 senders.emplace_back(loop->MakeSender<TestMessage>("/test"));
1198 }
1199 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); },
1200 "Failed to create sender on \\{ \"name\": \"/test\", \"type\": "
Brian Silverman77162972020-08-12 19:52:40 -07001201 "\"aos.TestMessage\"[^}]*\\ }, too many senders.");
1202}
1203
1204// Verify that creating too many fetchers fails.
1205TEST_P(AbstractEventLoopDeathTest, TooManyFetchers) {
1206 if (read_method() != ReadMethod::PIN) {
1207 // Other read methods don't limit the number of readers, so just skip this.
1208 return;
1209 }
1210
1211 auto loop = Make();
1212 std::vector<aos::Fetcher<TestMessage>> fetchers;
1213 for (int i = 0; i < 10; ++i) {
1214 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1215 }
1216 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1217 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1218 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
1219}
1220
1221// Verify that creating too many fetchers, split between two event loops, fails.
1222TEST_P(AbstractEventLoopDeathTest, TooManyFetchersTwoLoops) {
1223 if (read_method() != ReadMethod::PIN) {
1224 // Other read methods don't limit the number of readers, so just skip this.
1225 return;
1226 }
1227
1228 auto loop = Make();
1229 auto loop2 = Make();
1230 std::vector<aos::Fetcher<TestMessage>> fetchers;
1231 for (int i = 0; i < 5; ++i) {
1232 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1233 fetchers.emplace_back(loop2->MakeFetcher<TestMessage>("/test"));
1234 }
1235 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1236 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1237 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
1238}
1239
1240// Verify that creating too many watchers fails.
1241TEST_P(AbstractEventLoopDeathTest, TooManyWatchers) {
1242 if (read_method() != ReadMethod::PIN) {
1243 // Other read methods don't limit the number of readers, so just skip this.
1244 return;
1245 }
1246
1247 std::vector<std::unique_ptr<EventLoop>> loops;
1248 for (int i = 0; i < 10; ++i) {
1249 loops.emplace_back(Make());
1250 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
1251 }
1252 EXPECT_DEATH({ Make()->MakeWatcher("/test", [](const TestMessage &) {}); },
1253 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1254 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
1255}
1256
1257// Verify that creating too many watchers and fetchers combined fails.
1258TEST_P(AbstractEventLoopDeathTest, TooManyWatchersAndFetchers) {
1259 if (read_method() != ReadMethod::PIN) {
1260 // Other read methods don't limit the number of readers, so just skip this.
1261 return;
1262 }
1263
1264 auto loop = Make();
1265 std::vector<aos::Fetcher<TestMessage>> fetchers;
1266 std::vector<std::unique_ptr<EventLoop>> loops;
1267 for (int i = 0; i < 5; ++i) {
1268 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1269 loops.emplace_back(Make());
1270 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
1271 }
1272 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1273 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1274 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
Austin Schuhe516ab02020-05-06 21:37:04 -07001275}
1276
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001277// Verify that we can't create a sender inside OnRun.
1278TEST_P(AbstractEventLoopDeathTest, SenderInOnRun) {
1279 auto loop1 = MakePrimary();
1280
1281 loop1->OnRun(
1282 [&]() { auto sender = loop1->MakeSender<TestMessage>("/test2"); });
1283
1284 EXPECT_DEATH(Run(), "running");
1285}
1286
1287// Verify that we can't create a watcher inside OnRun.
1288TEST_P(AbstractEventLoopDeathTest, WatcherInOnRun) {
1289 auto loop1 = MakePrimary();
1290
1291 loop1->OnRun(
1292 [&]() { loop1->MakeWatcher("/test", [&](const TestMessage &) {}); });
1293
1294 EXPECT_DEATH(Run(), "running");
1295}
1296
Brian Silverman454bc112020-03-05 14:21:25 -08001297// Verify that we can't create a no-arg watcher inside OnRun.
1298TEST_P(AbstractEventLoopDeathTest, NoArgWatcherInOnRun) {
1299 auto loop1 = MakePrimary();
1300
1301 loop1->OnRun(
1302 [&]() { loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {}); });
1303
1304 EXPECT_DEATH(Run(), "running");
1305}
1306
Parker Schuhe4a70d62017-12-27 20:10:20 -08001307// Verify that Quit() works when there are multiple watchers.
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001308TEST_P(AbstractEventLoopTest, MultipleWatcherQuit) {
1309 auto loop1 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -07001310 auto loop2 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -08001311
Austin Schuh3578a2e2019-05-25 18:17:59 -07001312 loop2->MakeWatcher("/test1", [&](const TestMessage &) {});
1313 loop2->MakeWatcher("/test2", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001314 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -07001315 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -07001316 });
1317
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001318 auto sender = loop1->MakeSender<TestMessage>("/test2");
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001319
1320 loop2->OnRun([&]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001321 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1322 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1323 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001324 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001325 });
Parker Schuhe4a70d62017-12-27 20:10:20 -08001326
Austin Schuh44019f92019-05-19 19:58:27 -07001327 Run();
Parker Schuhe4a70d62017-12-27 20:10:20 -08001328}
1329
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001330// Verify that AOS_LOG has the right name.
1331TEST_P(AbstractEventLoopTest, AOSLog) {
1332 auto loop2 = MakePrimary("loop1");
1333 auto loop1 = Make("loop0");
1334
1335 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1336
1337 EXPECT_FALSE(fetcher.Fetch());
1338
1339 loop2->OnRun([&]() {
1340 AOS_LOG(INFO, "Testing123");
1341 this->Exit();
1342 });
1343
1344 Run();
1345 EXPECT_TRUE(fetcher.Fetch());
1346 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1347}
1348
1349// Verify that AOS_LOG has the right name in a watcher.
1350TEST_P(AbstractEventLoopTest, AOSLogWatcher) {
1351 auto loop2 = MakePrimary("loop1");
1352 auto loop1 = Make("loop0");
1353
1354 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1355
1356 EXPECT_FALSE(fetcher.Fetch());
1357
1358 auto sender = loop1->MakeSender<TestMessage>("/test2");
1359
1360 loop2->MakeWatcher("/test2", [&](const TestMessage & /*message*/) {
1361 AOS_LOG(INFO, "Testing123");
1362 this->Exit();
1363 });
1364
1365 loop2->OnRun([&]() {
1366 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1367 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1368 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001369 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001370 });
1371
1372 Run();
1373 EXPECT_TRUE(fetcher.Fetch());
1374 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1375}
1376
1377// Verify that AOS_LOG has the right name in a timer.
1378TEST_P(AbstractEventLoopTest, AOSLogTimer) {
1379 auto loop2 = MakePrimary("loop1");
1380 auto loop1 = Make("loop0");
1381
1382 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1383
1384 EXPECT_FALSE(fetcher.Fetch());
1385
1386 auto test_timer = loop2->AddTimer([&]() {
1387 AOS_LOG(INFO, "Testing123");
1388 this->Exit();
1389 });
1390
Philipp Schradera6712522023-07-05 20:25:11 -07001391 loop2->OnRun([&]() { test_timer->Schedule(loop2->monotonic_now()); });
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001392
1393 Run();
1394 EXPECT_TRUE(fetcher.Fetch());
1395 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1396}
1397
Neil Balch229001a2018-01-07 18:22:52 -08001398// Verify that timer intervals and duration function properly.
1399TEST_P(AbstractEventLoopTest, TimerIntervalAndDuration) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001400 // Force a slower rate so we are guaranteed to have reports for our timer.
Austin Schuh39788ff2019-12-01 18:22:57 -08001401 FLAGS_timing_report_ms = 2000;
1402
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001403 const int kCount = 5;
Neil Balch229001a2018-01-07 18:22:52 -08001404
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001405 auto loop = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001406 auto loop2 = Make();
1407
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001408 ::std::vector<::aos::monotonic_clock::time_point> times;
1409 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
1410
Austin Schuh39788ff2019-12-01 18:22:57 -08001411 Fetcher<timing::Report> report_fetcher =
1412 loop2->MakeFetcher<timing::Report>("/aos");
1413 EXPECT_FALSE(report_fetcher.Fetch());
1414
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001415 auto test_timer = loop->AddTimer([this, &times, &expected_times, &loop]() {
1416 times.push_back(loop->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001417 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
1418 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
1419 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001420 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -08001421 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
1422 EXPECT_EQ(loop->context().size, 0u);
1423 EXPECT_EQ(loop->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001424 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001425
Austin Schuhad154822019-12-27 15:45:13 -08001426 expected_times.push_back(loop->context().monotonic_event_time);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001427 if (times.size() == kCount) {
1428 this->Exit();
1429 }
Neil Balch229001a2018-01-07 18:22:52 -08001430 });
Austin Schuh39788ff2019-12-01 18:22:57 -08001431 test_timer->set_name("Test loop");
Neil Balch229001a2018-01-07 18:22:52 -08001432
Austin Schuh39788ff2019-12-01 18:22:57 -08001433 const monotonic_clock::time_point start_time = loop->monotonic_now();
Austin Schuh52d325c2019-06-23 18:59:06 -07001434 // TODO(austin): This should be an error... Should be done in OnRun only.
Philipp Schradera6712522023-07-05 20:25:11 -07001435 test_timer->Schedule(start_time + chrono::seconds(1), chrono::seconds(1));
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001436
Austin Schuh44019f92019-05-19 19:58:27 -07001437 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001438
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001439 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001440 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
1441 ASSERT_EQ(times.size(), expected_times.size());
1442 ASSERT_EQ((times.size() % 2), 1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001443
1444 // Grab the middle sample.
1445 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
1446
1447 // Add up all the delays of all the times.
1448 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1449 for (const ::aos::monotonic_clock::time_point time : times) {
1450 sum += time - average_time;
1451 }
1452
1453 // Average and add to the middle to find the average time.
1454 sum /= times.size();
1455 average_time += sum;
1456
1457 // Compute the offset from the average and the expected average. It
1458 // should be pretty close to 0.
1459 const ::aos::monotonic_clock::duration remainder =
1460 average_time - start_time - chrono::seconds(times.size() / 2 + 1);
1461
1462 const chrono::milliseconds kEpsilon(100);
1463 EXPECT_LT(remainder, +kEpsilon);
1464 EXPECT_GT(remainder, -kEpsilon);
1465
1466 // Make sure that the average duration is close to 1 second.
1467 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1468 times.front())
1469 .count() /
1470 static_cast<double>(times.size() - 1),
1471 1.0, 0.1);
1472
1473 // Confirm that the ideal wakeup times increment correctly.
1474 for (size_t i = 1; i < expected_times.size(); ++i) {
1475 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1476 }
1477
1478 for (size_t i = 0; i < expected_times.size(); ++i) {
1479 EXPECT_EQ((expected_times[i] - start_time) % chrono::seconds(1),
1480 chrono::seconds(0));
1481 }
1482
1483 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1484 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001485
Austin Schuh6bae8252021-02-07 22:01:49 -08001486 if (do_timing_reports() == DoTimingReports::kYes) {
1487 // And, since we are here, check that the timing report makes sense.
1488 // Start by looking for our event loop's timing.
1489 FlatbufferDetachedBuffer<timing::Report> report =
1490 FlatbufferDetachedBuffer<timing::Report>::Empty();
1491 while (report_fetcher.FetchNext()) {
1492 if (report_fetcher->name()->string_view() == "primary") {
1493 report = CopyFlatBuffer(report_fetcher.get());
1494 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001495 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001496
1497 // Confirm that we have the right number of reports, and the contents are
1498 // sane.
1499 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
1500
1501 EXPECT_EQ(report.message().name()->string_view(), "primary");
1502
1503 ASSERT_NE(report.message().senders(), nullptr);
1504 EXPECT_EQ(report.message().senders()->size(), 2);
1505
1506 ASSERT_NE(report.message().timers(), nullptr);
1507 EXPECT_EQ(report.message().timers()->size(), 2);
1508
1509 EXPECT_EQ(report.message().timers()->Get(0)->name()->string_view(),
1510 "Test loop");
1511 EXPECT_GE(report.message().timers()->Get(0)->count(), 1);
1512
1513 EXPECT_EQ(report.message().timers()->Get(1)->name()->string_view(),
1514 "timing_reports");
1515 EXPECT_EQ(report.message().timers()->Get(1)->count(), 1);
1516
1517 // Make sure there is a single phased loop report with our report in it.
1518 ASSERT_EQ(report.message().phased_loops(), nullptr);
1519 } else {
1520 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001521 }
Neil Balch229001a2018-01-07 18:22:52 -08001522}
1523
James Kuszmaul762e8692023-07-31 14:57:53 -07001524// Test that setting a default version string results in it getting populated
1525// correctly.
1526TEST_P(AbstractEventLoopTest, DefaultVersionStringInTimingReport) {
1527 gflags::FlagSaver flag_saver;
1528 FLAGS_timing_report_ms = 1000;
1529
1530 EventLoop::SetDefaultVersionString("default_version_string");
1531
1532 auto loop = MakePrimary();
1533
1534 Fetcher<timing::Report> report_fetcher =
1535 loop->MakeFetcher<timing::Report>("/aos");
1536
1537 TimerHandler *exit_timer = loop->AddTimer([this]() { Exit(); });
1538 loop->OnRun([exit_timer, &loop, &report_fetcher]() {
1539 report_fetcher.Fetch();
1540 exit_timer->Schedule(loop->monotonic_now() + std::chrono::seconds(2));
1541 });
1542
1543 Run();
1544
1545 bool found_primary_report = false;
1546 while (report_fetcher.FetchNext()) {
1547 if (report_fetcher->name()->string_view() == "primary") {
1548 found_primary_report = true;
1549 EXPECT_EQ("default_version_string",
1550 report_fetcher->version()->string_view());
1551 } else {
1552 FAIL() << report_fetcher->name()->string_view();
1553 }
1554 }
1555
1556 if (do_timing_reports() == DoTimingReports::kYes) {
1557 EXPECT_TRUE(found_primary_report);
1558 } else {
1559 EXPECT_FALSE(found_primary_report);
1560 }
1561}
1562
1563// Test that overriding the default version string results in it getting
1564// populated correctly.
1565TEST_P(AbstractEventLoopTest, OverrideDersionStringInTimingReport) {
1566 gflags::FlagSaver flag_saver;
1567 FLAGS_timing_report_ms = 1000;
1568
1569 EventLoop::SetDefaultVersionString("default_version_string");
1570
1571 auto loop = MakePrimary();
1572 loop->SetVersionString("override_version");
1573
1574 Fetcher<timing::Report> report_fetcher =
1575 loop->MakeFetcher<timing::Report>("/aos");
1576
1577 TimerHandler *exit_timer = loop->AddTimer([this]() { Exit(); });
1578 loop->OnRun([exit_timer, &loop, &report_fetcher]() {
1579 report_fetcher.Fetch();
1580 exit_timer->Schedule(loop->monotonic_now() + std::chrono::seconds(2));
1581 });
1582
1583 Run();
1584
1585 bool found_primary_report = false;
1586 while (report_fetcher.FetchNext()) {
1587 if (report_fetcher->name()->string_view() == "primary") {
1588 found_primary_report = true;
1589 EXPECT_EQ("override_version", report_fetcher->version()->string_view());
1590 } else {
1591 FAIL() << report_fetcher->name()->string_view();
1592 }
1593 }
1594
1595 if (do_timing_reports() == DoTimingReports::kYes) {
1596 EXPECT_TRUE(found_primary_report);
1597 } else {
1598 EXPECT_FALSE(found_primary_report);
1599 }
1600}
1601
Neil Balch229001a2018-01-07 18:22:52 -08001602// Verify that we can change a timer's parameters during execution.
1603TEST_P(AbstractEventLoopTest, TimerChangeParameters) {
Austin Schuh44019f92019-05-19 19:58:27 -07001604 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001605 loop->SetRuntimeRealtimePriority(1);
Austin Schuh7f20f512021-01-31 17:56:16 -08001606 std::vector<monotonic_clock::time_point> iteration_list;
Neil Balch229001a2018-01-07 18:22:52 -08001607
1608 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001609 ScopedNotRealtime nrt;
Austin Schuh7f20f512021-01-31 17:56:16 -08001610 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001611 });
1612
Austin Schuh7f20f512021-01-31 17:56:16 -08001613 monotonic_clock::time_point s;
1614 auto modifier_timer = loop->AddTimer([&test_timer, &s]() {
Philipp Schradera6712522023-07-05 20:25:11 -07001615 test_timer->Schedule(s + chrono::milliseconds(1750),
1616 chrono::milliseconds(600));
Neil Balch229001a2018-01-07 18:22:52 -08001617 });
1618
Austin Schuh7f20f512021-01-31 17:56:16 -08001619 s = loop->monotonic_now();
Philipp Schradera6712522023-07-05 20:25:11 -07001620 test_timer->Schedule(s, chrono::milliseconds(500));
1621 modifier_timer->Schedule(s + chrono::milliseconds(1250));
Austin Schuhd892f102021-10-12 18:01:46 -07001622 EndEventLoop(loop.get(), chrono::milliseconds(3950));
Austin Schuh44019f92019-05-19 19:58:27 -07001623 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001624
Austin Schuhd892f102021-10-12 18:01:46 -07001625 EXPECT_THAT(
1626 iteration_list,
1627 ::testing::ElementsAre(
1628 s, s + chrono::milliseconds(500), s + chrono::milliseconds(1000),
1629 s + chrono::milliseconds(1750), s + chrono::milliseconds(2350),
1630 s + chrono::milliseconds(2950), s + chrono::milliseconds(3550)));
Neil Balch229001a2018-01-07 18:22:52 -08001631}
1632
1633// Verify that we can disable a timer during execution.
1634TEST_P(AbstractEventLoopTest, TimerDisable) {
Austin Schuh44019f92019-05-19 19:58:27 -07001635 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001636 loop->SetRuntimeRealtimePriority(1);
Neil Balch229001a2018-01-07 18:22:52 -08001637 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
1638
1639 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001640 ScopedNotRealtime nrt;
Austin Schuhd892f102021-10-12 18:01:46 -07001641 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001642 });
1643
Tyler Chatow67ddb032020-01-12 14:30:04 -08001644 auto ender_timer = loop->AddTimer([&test_timer]() { test_timer->Disable(); });
Neil Balch229001a2018-01-07 18:22:52 -08001645
Austin Schuhd892f102021-10-12 18:01:46 -07001646 monotonic_clock::time_point s = loop->monotonic_now();
Philipp Schradera6712522023-07-05 20:25:11 -07001647 test_timer->Schedule(s, ::std::chrono::milliseconds(500));
1648 ender_timer->Schedule(s + ::std::chrono::milliseconds(1250));
Austin Schuh73d99502021-12-08 12:05:39 -08001649 EndEventLoop(loop.get(), ::std::chrono::milliseconds(2000));
Austin Schuh44019f92019-05-19 19:58:27 -07001650 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001651
Austin Schuhd892f102021-10-12 18:01:46 -07001652 EXPECT_THAT(iteration_list,
Austin Schuh73d99502021-12-08 12:05:39 -08001653 ::testing::ElementsAre(s, s + chrono::milliseconds(500),
1654 s + chrono::milliseconds(1000)));
Neil Balch229001a2018-01-07 18:22:52 -08001655}
Austin Schuh7267c532019-05-19 19:55:53 -07001656
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001657// Verify that a timer can disable itself.
1658//
1659// TODO(Brian): Do something similar with phased loops, both with a quick
1660// handler and a handler that would miss a cycle except it got deferred. Current
1661// behavior doing that is a mess.
1662TEST_P(AbstractEventLoopTest, TimerDisableSelf) {
1663 auto loop = MakePrimary();
1664
1665 int count = 0;
1666 aos::TimerHandler *test_timer;
1667 test_timer = loop->AddTimer([&count, &test_timer]() {
1668 ++count;
1669 test_timer->Disable();
1670 });
1671
Philipp Schradera6712522023-07-05 20:25:11 -07001672 test_timer->Schedule(loop->monotonic_now(), ::std::chrono::milliseconds(20));
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001673 EndEventLoop(loop.get(), ::std::chrono::milliseconds(80));
1674 Run();
1675
1676 EXPECT_EQ(count, 1);
1677}
1678
Brian Silvermanbd405c02020-06-23 16:25:23 -07001679// Verify that we can disable a timer during execution of another timer
1680// scheduled for the same time, with one ordering of creation for the timers.
1681//
1682// Also schedule some more events to reshuffle the heap in EventLoop used for
1683// tracking events to change up the order. This used to segfault
1684// SimulatedEventLoop.
1685TEST_P(AbstractEventLoopTest, TimerDisableOther) {
1686 for (bool creation_order : {true, false}) {
1687 for (bool setup_order : {true, false}) {
1688 for (int shuffle_events = 0; shuffle_events < 5; ++shuffle_events) {
1689 auto loop = MakePrimary();
1690 aos::TimerHandler *test_timer, *ender_timer;
1691 if (creation_order) {
1692 test_timer = loop->AddTimer([]() {});
1693 ender_timer =
1694 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1695 } else {
1696 ender_timer =
1697 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1698 test_timer = loop->AddTimer([]() {});
1699 }
1700
1701 const auto start = loop->monotonic_now();
1702
1703 for (int i = 0; i < shuffle_events; ++i) {
Philipp Schradera6712522023-07-05 20:25:11 -07001704 loop->AddTimer([]() {})->Schedule(start +
1705 std::chrono::milliseconds(10));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001706 }
1707
1708 if (setup_order) {
Philipp Schradera6712522023-07-05 20:25:11 -07001709 test_timer->Schedule(start + ::std::chrono::milliseconds(20));
1710 ender_timer->Schedule(start + ::std::chrono::milliseconds(20));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001711 } else {
Philipp Schradera6712522023-07-05 20:25:11 -07001712 ender_timer->Schedule(start + ::std::chrono::milliseconds(20));
1713 test_timer->Schedule(start + ::std::chrono::milliseconds(20));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001714 }
1715 EndEventLoop(loop.get(), ::std::chrono::milliseconds(40));
1716 Run();
1717 }
1718 }
1719 }
1720}
1721
Austin Schuh54cf95f2019-11-29 13:14:18 -08001722// Verifies that the event loop implementations detect when Channel is not a
Brian Silverman631b6262021-11-10 12:25:08 -08001723// pointer into configuration(), or a name doesn't map to a channel in
1724// configuration().
Austin Schuh54cf95f2019-11-29 13:14:18 -08001725TEST_P(AbstractEventLoopDeathTest, InvalidChannel) {
1726 auto loop = MakePrimary();
1727
Tyler Chatow67ddb032020-01-12 14:30:04 -08001728 const Channel *channel = configuration::GetChannel(
1729 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
Austin Schuh54cf95f2019-11-29 13:14:18 -08001730
1731 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1732
1733 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001734 loop->MakeRawSender(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001735 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1736
1737 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001738 loop->MakeSender<TestMessage>("/testbad"),
1739 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1740 " not found in config");
1741
1742 EXPECT_FALSE(loop->TryMakeSender<TestMessage>("/testbad"));
1743
1744 EXPECT_DEATH(
1745 loop->MakeRawFetcher(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001746 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1747
1748 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001749 loop->MakeFetcher<TestMessage>("/testbad"),
1750 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1751 " not found in config");
1752
1753 EXPECT_FALSE(loop->TryMakeFetcher<TestMessage>("/testbad").valid());
1754
1755 EXPECT_DEATH(
Austin Schuh54cf95f2019-11-29 13:14:18 -08001756 {
1757 loop->MakeRawWatcher(&channel_copy.message(),
1758 [](const Context, const void *) {});
1759 },
1760 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
Brian Silverman631b6262021-11-10 12:25:08 -08001761
1762 EXPECT_DEATH(
1763 { loop->MakeWatcher("/testbad", [](const TestMessage &) {}); },
1764 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1765 " not found in config");
1766}
1767
1768// Verifies that the event loop handles a channel which is not readable or
1769// writable on the current node nicely.
1770TEST_P(AbstractEventLoopDeathTest, InaccessibleChannel) {
1771 EnableNodes("me");
1772 auto loop = MakePrimary("me");
1773 auto loop2 = Make("them");
1774
1775 const Channel *channel = configuration::GetChannel(
1776 loop->configuration(), "/test_noforward", "aos.TestMessage", "", nullptr);
1777
1778 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1779
1780 EXPECT_DEATH(
1781 loop2->MakeSender<TestMessage>("/test_forward"),
1782 "Channel"
1783 " \\{ \"name\": \"/test_forward\", \"type\": \"aos.TestMessage\" \\}"
1784 " is not able to be sent on this node");
1785
1786 EXPECT_FALSE(loop2->TryMakeSender<TestMessage>("/test_forward"));
1787
1788 EXPECT_DEATH(
1789 loop2->MakeRawFetcher(channel),
1790 "Channel"
1791 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1792 " is not able to be fetched on this node");
1793
1794 EXPECT_DEATH(
1795 loop2->MakeFetcher<TestMessage>("/test_noforward"),
1796 "Channel"
1797 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1798 " is not able to be fetched on this node");
1799
1800 EXPECT_FALSE(loop2->TryMakeFetcher<TestMessage>("/test_noforward").valid());
1801
1802 EXPECT_DEATH(
1803 { loop2->MakeRawWatcher(channel, [](const Context, const void *) {}); },
1804 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1805 "\"source_node\": \"them\" \\}"
1806 " is not able to be watched on this node");
1807
1808 EXPECT_DEATH(
1809 { loop2->MakeWatcher("/test_noforward", [](const TestMessage &) {}); },
1810 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1811 "\"source_node\": \"them\" \\}"
1812 " is not able to be watched on this node");
Austin Schuh54cf95f2019-11-29 13:14:18 -08001813}
1814
Austin Schuhd54780b2020-10-03 16:26:02 -07001815// Verifies that the event loop implementations detect when Channel has an
1816// invalid alignment.
1817TEST_P(AbstractEventLoopDeathTest, InvalidChannelAlignment) {
1818 const char *const kError = "multiple of alignment";
1819 InvalidChannelAlignment();
1820
1821 auto loop = MakePrimary();
1822
1823 const Channel *channel = configuration::GetChannel(
1824 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
1825
1826 EXPECT_DEATH({ loop->MakeRawSender(channel); }, kError);
1827 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); }, kError);
1828
1829 EXPECT_DEATH({ loop->MakeRawFetcher(channel); }, kError);
1830 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); }, kError);
1831
1832 EXPECT_DEATH(
1833 { loop->MakeRawWatcher(channel, [](const Context &, const void *) {}); },
1834 kError);
1835 EXPECT_DEATH({ loop->MakeRawNoArgWatcher(channel, [](const Context &) {}); },
1836 kError);
1837
1838 EXPECT_DEATH({ loop->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
1839 kError);
1840 EXPECT_DEATH({ loop->MakeWatcher("/test", [](const TestMessage &) {}); },
1841 kError);
1842}
1843
Brian Silverman454bc112020-03-05 14:21:25 -08001844// Verify that the send time on a message is roughly right when using a watcher.
Austin Schuh7267c532019-05-19 19:55:53 -07001845TEST_P(AbstractEventLoopTest, MessageSendTime) {
Austin Schuh44019f92019-05-19 19:58:27 -07001846 auto loop1 = MakePrimary();
Austin Schuh7267c532019-05-19 19:55:53 -07001847 auto loop2 = Make();
Austin Schuhad154822019-12-27 15:45:13 -08001848 auto sender = loop2->MakeSender<TestMessage>("/test");
Austin Schuh7267c532019-05-19 19:55:53 -07001849 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
1850
1851 auto test_timer = loop1->AddTimer([&sender]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001852 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1853 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1854 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001855 msg.CheckOk(msg.Send(builder.Finish()));
Alex Perrycb7da4b2019-08-28 19:35:56 -07001856 });
1857
Austin Schuhad154822019-12-27 15:45:13 -08001858 bool triggered = false;
Brian Silverman454bc112020-03-05 14:21:25 -08001859 loop1->MakeWatcher("/test", [&](const TestMessage &msg) {
Austin Schuhad154822019-12-27 15:45:13 -08001860 // Confirm that the data pointer makes sense from a watcher, and all the
1861 // timestamps look right.
1862 EXPECT_GT(&msg, loop1->context().data);
1863 EXPECT_EQ(loop1->context().monotonic_remote_time,
1864 loop1->context().monotonic_event_time);
1865 EXPECT_EQ(loop1->context().realtime_remote_time,
1866 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001867 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001868
1869 const aos::monotonic_clock::time_point monotonic_now =
1870 loop1->monotonic_now();
Tyler Chatow67ddb032020-01-12 14:30:04 -08001871 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08001872
1873 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1874 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1875 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1876 monotonic_now);
1877 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1878 realtime_now);
1879
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001880 EXPECT_LT(&msg, reinterpret_cast<const void *>(
1881 reinterpret_cast<const char *>(loop1->context().data) +
Austin Schuhad154822019-12-27 15:45:13 -08001882 loop1->context().size));
Brian Silverman4f4e0612020-08-12 19:54:41 -07001883 if (read_method() == ReadMethod::PIN) {
1884 EXPECT_GE(loop1->context().buffer_index, 0);
1885 EXPECT_LT(loop1->context().buffer_index,
1886 loop1->NumberBuffers(
1887 configuration::GetChannel(loop1->configuration(), "/test",
1888 "aos.TestMessage", "", nullptr)));
1889 } else {
1890 EXPECT_EQ(-1, loop1->context().buffer_index);
1891 }
Austin Schuhad154822019-12-27 15:45:13 -08001892 triggered = true;
Austin Schuh7267c532019-05-19 19:55:53 -07001893 });
1894
Philipp Schradera6712522023-07-05 20:25:11 -07001895 test_timer->Schedule(loop1->monotonic_now() + ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07001896
1897 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
Austin Schuh44019f92019-05-19 19:58:27 -07001898 Run();
Austin Schuh7267c532019-05-19 19:55:53 -07001899
Austin Schuhad154822019-12-27 15:45:13 -08001900 EXPECT_TRUE(triggered);
1901
Brian Silverman454bc112020-03-05 14:21:25 -08001902 ASSERT_TRUE(fetcher.Fetch());
1903
1904 monotonic_clock::duration monotonic_time_offset =
1905 fetcher.context().monotonic_event_time -
1906 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1907 realtime_clock::duration realtime_time_offset =
1908 fetcher.context().realtime_event_time -
1909 (loop1->realtime_now() - ::std::chrono::seconds(1));
1910
1911 EXPECT_EQ(fetcher.context().realtime_event_time,
1912 fetcher.context().realtime_remote_time);
1913 EXPECT_EQ(fetcher.context().monotonic_event_time,
1914 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001915 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001916
1917 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1918 << ": Got "
1919 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1920 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1921 // Confirm that the data pointer makes sense.
1922 EXPECT_GT(fetcher.get(), fetcher.context().data);
1923 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001924 reinterpret_cast<const void *>(
1925 reinterpret_cast<const char *>(fetcher.context().data) +
Brian Silverman454bc112020-03-05 14:21:25 -08001926 fetcher.context().size));
1927 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1928 << ": Got "
1929 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1930 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1931
1932 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1933 << ": Got "
1934 << fetcher.context().realtime_event_time.time_since_epoch().count()
1935 << " expected " << loop1->realtime_now().time_since_epoch().count();
1936 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1937 << ": Got "
1938 << fetcher.context().realtime_event_time.time_since_epoch().count()
1939 << " expected " << loop1->realtime_now().time_since_epoch().count();
1940}
1941
1942// Verify that the send time on a message is roughly right when using a no-arg
1943// watcher. To get a message, we need to use a fetcher to actually access the
1944// message. This is also the main use case for no-arg fetchers.
1945TEST_P(AbstractEventLoopTest, MessageSendTimeNoArg) {
1946 auto loop1 = MakePrimary();
1947 auto loop2 = Make();
1948 auto sender = loop2->MakeSender<TestMessage>("/test");
1949 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
1950
1951 auto test_timer = loop1->AddTimer([&sender]() {
1952 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1953 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1954 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001955 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -08001956 });
1957
1958 bool triggered = false;
1959 loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {
1960 // Confirm that we can indeed use a fetcher on this channel from this
1961 // context, and it results in a sane data pointer and timestamps.
1962 ASSERT_TRUE(fetcher.Fetch());
1963
1964 EXPECT_EQ(loop1->context().monotonic_remote_time,
1965 loop1->context().monotonic_event_time);
1966 EXPECT_EQ(loop1->context().realtime_remote_time,
1967 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001968 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001969
1970 const aos::monotonic_clock::time_point monotonic_now =
1971 loop1->monotonic_now();
1972 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
1973
1974 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1975 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1976 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1977 monotonic_now);
1978 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1979 realtime_now);
1980
1981 triggered = true;
1982 });
1983
Philipp Schradera6712522023-07-05 20:25:11 -07001984 test_timer->Schedule(loop1->monotonic_now() + ::std::chrono::seconds(1));
Brian Silverman454bc112020-03-05 14:21:25 -08001985
1986 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
1987 Run();
1988
1989 ASSERT_TRUE(triggered);
Austin Schuh7267c532019-05-19 19:55:53 -07001990
Alex Perrycb7da4b2019-08-28 19:35:56 -07001991 monotonic_clock::duration monotonic_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001992 fetcher.context().monotonic_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001993 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1994 realtime_clock::duration realtime_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001995 fetcher.context().realtime_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001996 (loop1->realtime_now() - ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07001997
Austin Schuhad154822019-12-27 15:45:13 -08001998 EXPECT_EQ(fetcher.context().realtime_event_time,
1999 fetcher.context().realtime_remote_time);
2000 EXPECT_EQ(fetcher.context().monotonic_event_time,
2001 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002002 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08002003
Alex Perrycb7da4b2019-08-28 19:35:56 -07002004 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
2005 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002006 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh52d325c2019-06-23 18:59:06 -07002007 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07002008 // Confirm that the data pointer makes sense.
2009 EXPECT_GT(fetcher.get(), fetcher.context().data);
2010 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07002011 reinterpret_cast<const void *>(
2012 reinterpret_cast<const char *>(fetcher.context().data) +
Alex Perrycb7da4b2019-08-28 19:35:56 -07002013 fetcher.context().size));
2014 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
2015 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002016 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh7267c532019-05-19 19:55:53 -07002017 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07002018
2019 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
2020 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002021 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07002022 << " expected " << loop1->realtime_now().time_since_epoch().count();
2023 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
2024 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002025 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07002026 << " expected " << loop1->realtime_now().time_since_epoch().count();
Austin Schuh7267c532019-05-19 19:55:53 -07002027}
2028
Austin Schuh52d325c2019-06-23 18:59:06 -07002029// Tests that a couple phased loops run in a row result in the correct offset
2030// and period.
2031TEST_P(AbstractEventLoopTest, PhasedLoopTest) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07002032 // Force a slower rate so we are guaranteed to have reports for our phased
Austin Schuh39788ff2019-12-01 18:22:57 -08002033 // loop.
2034 FLAGS_timing_report_ms = 2000;
2035
Austin Schuh52d325c2019-06-23 18:59:06 -07002036 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2037 const int kCount = 5;
2038
2039 auto loop1 = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08002040 auto loop2 = Make();
2041
2042 Fetcher<timing::Report> report_fetcher =
2043 loop2->MakeFetcher<timing::Report>("/aos");
2044 EXPECT_FALSE(report_fetcher.Fetch());
Austin Schuh52d325c2019-06-23 18:59:06 -07002045
2046 // Collect up a couple of samples.
2047 ::std::vector<::aos::monotonic_clock::time_point> times;
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002048 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
Austin Schuh52d325c2019-06-23 18:59:06 -07002049
2050 // Run kCount iterations.
Austin Schuh39788ff2019-12-01 18:22:57 -08002051 loop1
2052 ->AddPhasedLoop(
2053 [&times, &expected_times, &loop1, this](int count) {
2054 EXPECT_EQ(count, 1);
2055 times.push_back(loop1->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08002056 expected_times.push_back(loop1->context().monotonic_event_time);
Austin Schuh39788ff2019-12-01 18:22:57 -08002057
Austin Schuhad154822019-12-27 15:45:13 -08002058 EXPECT_EQ(loop1->context().monotonic_remote_time,
2059 monotonic_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002060 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08002061 EXPECT_EQ(loop1->context().realtime_event_time,
2062 realtime_clock::min_time);
2063 EXPECT_EQ(loop1->context().realtime_remote_time,
Austin Schuh39788ff2019-12-01 18:22:57 -08002064 realtime_clock::min_time);
2065 EXPECT_EQ(loop1->context().queue_index, 0xffffffffu);
2066 EXPECT_EQ(loop1->context().size, 0u);
2067 EXPECT_EQ(loop1->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07002068 EXPECT_EQ(loop1->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08002069
2070 if (times.size() == kCount) {
2071 LOG(INFO) << "Exiting";
2072 this->Exit();
2073 }
2074 },
2075 chrono::seconds(1), kOffset)
2076 ->set_name("Test loop");
Austin Schuh52d325c2019-06-23 18:59:06 -07002077
2078 // Add a delay to make sure that delay during startup doesn't result in a
2079 // "missed cycle".
2080 SleepFor(chrono::seconds(2));
2081
2082 Run();
2083
2084 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07002085 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
2086 ASSERT_EQ(times.size(), expected_times.size());
2087 ASSERT_EQ((times.size() % 2), 1);
Austin Schuh52d325c2019-06-23 18:59:06 -07002088
2089 // Grab the middle sample.
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002090 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
Austin Schuh52d325c2019-06-23 18:59:06 -07002091
2092 // Add up all the delays of all the times.
2093 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
2094 for (const ::aos::monotonic_clock::time_point time : times) {
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002095 sum += time - average_time;
Austin Schuh52d325c2019-06-23 18:59:06 -07002096 }
2097
2098 // Average and add to the middle to find the average time.
2099 sum /= times.size();
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002100 average_time += sum;
Austin Schuh52d325c2019-06-23 18:59:06 -07002101
2102 // Compute the offset from the start of the second of the average time. This
2103 // should be pretty close to the offset.
2104 const ::aos::monotonic_clock::duration remainder =
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002105 average_time.time_since_epoch() -
2106 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
Austin Schuh52d325c2019-06-23 18:59:06 -07002107
2108 const chrono::milliseconds kEpsilon(100);
2109 EXPECT_LT(remainder, kOffset + kEpsilon);
2110 EXPECT_GT(remainder, kOffset - kEpsilon);
2111
2112 // Make sure that the average duration is close to 1 second.
2113 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
2114 times.front())
2115 .count() /
2116 static_cast<double>(times.size() - 1),
2117 1.0, 0.1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002118
2119 // Confirm that the ideal wakeup times increment correctly.
2120 for (size_t i = 1; i < expected_times.size(); ++i) {
2121 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
2122 }
2123
2124 for (size_t i = 0; i < expected_times.size(); ++i) {
2125 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
2126 kOffset);
2127 }
2128
2129 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
2130 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08002131
Austin Schuh6bae8252021-02-07 22:01:49 -08002132 if (do_timing_reports() == DoTimingReports::kYes) {
2133 // And, since we are here, check that the timing report makes sense.
2134 // Start by looking for our event loop's timing.
2135 FlatbufferDetachedBuffer<timing::Report> report =
2136 FlatbufferDetachedBuffer<timing::Report>::Empty();
2137 while (report_fetcher.FetchNext()) {
2138 if (report_fetcher->name()->string_view() == "primary") {
2139 report = CopyFlatBuffer(report_fetcher.get());
2140 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002141 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002142
2143 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
2144
2145 EXPECT_EQ(report.message().name()->string_view(), "primary");
2146
2147 ASSERT_NE(report.message().senders(), nullptr);
2148 EXPECT_EQ(report.message().senders()->size(), 2);
2149
2150 ASSERT_NE(report.message().timers(), nullptr);
2151 EXPECT_EQ(report.message().timers()->size(), 1);
2152
2153 // Make sure there is a single phased loop report with our report in it.
2154 ASSERT_NE(report.message().phased_loops(), nullptr);
2155 ASSERT_EQ(report.message().phased_loops()->size(), 1);
2156 EXPECT_EQ(report.message().phased_loops()->Get(0)->name()->string_view(),
2157 "Test loop");
2158 EXPECT_GE(report.message().phased_loops()->Get(0)->count(), 1);
2159 } else {
2160 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002161 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002162}
2163
Milind Upadhyay42589bb2021-05-19 20:05:16 -07002164// Tests that a phased loop responds correctly to a changing offset.
2165TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetTest) {
2166 // Force a slower rate so we are guaranteed to have reports for our phased
2167 // loop.
2168 FLAGS_timing_report_ms = 2000;
2169
2170 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2171 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2172 const int kCount = 5;
2173
2174 auto loop1 = MakePrimary();
2175
2176 // Collect up a couple of samples.
2177 ::std::vector<::aos::monotonic_clock::time_point> times;
2178 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
2179
2180 PhasedLoopHandler *phased_loop;
2181
2182 // Run kCount iterations.
2183 phased_loop = loop1->AddPhasedLoop(
2184 [&phased_loop, &times, &expected_times, &loop1, this, kOffset,
2185 kInterval](int count) {
2186 EXPECT_EQ(count, 1);
2187 times.push_back(loop1->monotonic_now());
2188
2189 expected_times.push_back(loop1->context().monotonic_event_time);
2190
2191 phased_loop->set_interval_and_offset(
2192 kInterval, kOffset - chrono::milliseconds(times.size()));
2193 LOG(INFO) << "new offset: "
2194 << (kOffset - chrono::milliseconds(times.size())).count();
2195
2196 if (times.size() == kCount) {
2197 LOG(INFO) << "Exiting";
2198 this->Exit();
2199 }
2200 },
2201 kInterval, kOffset);
2202 phased_loop->set_name("Test loop");
2203
2204 // Add a delay to make sure that delay during startup doesn't result in a
2205 // "missed cycle".
2206 SleepFor(chrono::seconds(2));
2207
2208 Run();
2209 // Confirm that we got both the right number of samples, and it's odd.
2210 EXPECT_EQ(times.size(), static_cast<size_t>(kCount));
2211 EXPECT_EQ(times.size(), expected_times.size());
2212 EXPECT_EQ((times.size() % 2), 1);
2213
2214 // Grab the middle sample.
2215 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
2216
2217 // Add up all the delays of all the times.
2218 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
2219 for (const ::aos::monotonic_clock::time_point time : times) {
2220 sum += time - average_time;
2221 }
2222
2223 // Average and add to the middle to find the average time.
2224 sum /= times.size();
2225 average_time += sum;
2226
2227 // Compute the offset from the start of the second of the average time. This
2228 // should be pretty close to the offset.
2229 const ::aos::monotonic_clock::duration remainder =
2230 average_time.time_since_epoch() -
2231 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
2232
2233 const chrono::milliseconds kEpsilon(100);
2234 EXPECT_LT(remainder, kOffset + kEpsilon);
2235 EXPECT_GT(remainder, kOffset - kEpsilon);
2236
2237 // Make sure that the average duration is close to 1 second.
2238 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
2239 times.front())
2240 .count() /
2241 static_cast<double>(times.size() - 1),
2242 1.0, 0.1);
2243
2244 // Confirm that the ideal wakeup times increment correctly.
2245 for (size_t i = 1; i < expected_times.size(); ++i) {
2246 LOG(INFO) << i - 1 << ": " << expected_times[i - 1] << ", " << i << ": "
2247 << expected_times[i];
2248 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1) -
2249 chrono::milliseconds(1));
2250 }
2251
2252 for (size_t i = 0; i < expected_times.size(); ++i) {
2253 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
2254 kOffset - chrono::milliseconds(i));
2255 }
2256
2257 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
2258 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
2259}
2260
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002261// Tests that a phased loop responds correctly to a changing offset; sweep
2262// across a variety of potential offset changes, to ensure that we are
2263// exercising a variety of potential cases.
2264TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetSweep) {
2265 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2266 const int kCount = 5;
2267
2268 auto loop1 = MakePrimary();
2269
2270 std::vector<aos::monotonic_clock::duration> offset_options;
2271 for (int ii = 0; ii < kCount; ++ii) {
2272 offset_options.push_back(ii * kInterval / kCount);
2273 }
2274 std::vector<aos::monotonic_clock::duration> offset_sweep;
2275 // Run over all the pair-wise combinations of offsets.
2276 for (int ii = 0; ii < kCount; ++ii) {
2277 for (int jj = 0; jj < kCount; ++jj) {
2278 offset_sweep.push_back(offset_options.at(ii));
2279 offset_sweep.push_back(offset_options.at(jj));
2280 }
2281 }
2282
2283 std::vector<::aos::monotonic_clock::time_point> expected_times;
2284
2285 PhasedLoopHandler *phased_loop;
2286
2287 // Run kCount iterations.
2288 size_t counter = 0;
2289 phased_loop = loop1->AddPhasedLoop(
2290 [&phased_loop, &expected_times, &loop1, this, kInterval, &counter,
2291 offset_sweep](int count) {
2292 EXPECT_EQ(count, 1);
2293 expected_times.push_back(loop1->context().monotonic_event_time);
2294
2295 counter++;
2296
2297 if (counter == offset_sweep.size()) {
2298 LOG(INFO) << "Exiting";
2299 this->Exit();
2300 return;
2301 }
2302
2303 phased_loop->set_interval_and_offset(kInterval,
2304 offset_sweep.at(counter));
2305 },
2306 kInterval, offset_sweep.at(0));
2307
2308 Run();
2309 ASSERT_EQ(expected_times.size(), offset_sweep.size());
2310 for (size_t ii = 1; ii < expected_times.size(); ++ii) {
2311 EXPECT_LE(expected_times.at(ii) - expected_times.at(ii - 1), kInterval);
2312 }
2313}
2314
2315// Tests that a phased loop responds correctly to being rescheduled with now
2316// equal to a time in the past.
2317TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleInPast) {
2318 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2319 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2320
2321 auto loop1 = MakePrimary();
2322
2323 std::vector<::aos::monotonic_clock::time_point> expected_times;
2324
2325 PhasedLoopHandler *phased_loop;
2326
2327 int expected_count = 1;
2328
2329 // Set up a timer that will get run immediately after the phased loop and
2330 // which will attempt to reschedule the phased loop to just before now. This
2331 // should succeed, but will result in 0 cycles elapsing.
2332 TimerHandler *manager_timer =
2333 loop1->AddTimer([&phased_loop, &loop1, &expected_count, this]() {
2334 if (expected_count == 0) {
2335 LOG(INFO) << "Exiting";
2336 this->Exit();
2337 return;
2338 }
2339 phased_loop->Reschedule(loop1->context().monotonic_event_time -
2340 std::chrono::nanoseconds(1));
2341 expected_count = 0;
2342 });
2343
2344 phased_loop = loop1->AddPhasedLoop(
2345 [&expected_count, &expected_times, &loop1, manager_timer](int count) {
2346 EXPECT_EQ(count, expected_count);
2347 expected_times.push_back(loop1->context().monotonic_event_time);
2348
Philipp Schradera6712522023-07-05 20:25:11 -07002349 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002350 },
2351 kInterval, kOffset);
2352 phased_loop->set_name("Test loop");
2353 manager_timer->set_name("Manager timer");
2354
2355 Run();
2356
2357 ASSERT_EQ(2u, expected_times.size());
2358 ASSERT_EQ(expected_times[0], expected_times[1]);
2359}
2360
2361// Tests that a phased loop responds correctly to being rescheduled at the time
2362// when it should be triggering (it should kick the trigger to the next cycle).
2363TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleNow) {
2364 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2365 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2366
2367 auto loop1 = MakePrimary();
2368
2369 std::vector<::aos::monotonic_clock::time_point> expected_times;
2370
2371 PhasedLoopHandler *phased_loop;
2372
2373 bool should_exit = false;
2374 // Set up a timer that will get run immediately after the phased loop and
2375 // which will attempt to reschedule the phased loop to now. This should
2376 // succeed, but will result in no change to the expected behavior (since this
2377 // is the same thing that is actually done internally).
2378 TimerHandler *manager_timer =
2379 loop1->AddTimer([&phased_loop, &loop1, &should_exit, this]() {
2380 if (should_exit) {
2381 LOG(INFO) << "Exiting";
2382 this->Exit();
2383 return;
2384 }
2385 phased_loop->Reschedule(loop1->context().monotonic_event_time);
2386 should_exit = true;
2387 });
2388
2389 phased_loop = loop1->AddPhasedLoop(
2390 [&expected_times, &loop1, manager_timer](int count) {
2391 EXPECT_EQ(count, 1);
2392 expected_times.push_back(loop1->context().monotonic_event_time);
2393
Philipp Schradera6712522023-07-05 20:25:11 -07002394 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002395 },
2396 kInterval, kOffset);
2397 phased_loop->set_name("Test loop");
2398 manager_timer->set_name("Manager timer");
2399
2400 Run();
2401
2402 ASSERT_EQ(2u, expected_times.size());
2403 ASSERT_EQ(expected_times[0] + kInterval, expected_times[1]);
2404}
2405
2406// Tests that a phased loop responds correctly to being rescheduled at a time in
2407// the distant future.
2408TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleFuture) {
2409 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2410 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2411
2412 auto loop1 = MakePrimary();
2413
2414 std::vector<::aos::monotonic_clock::time_point> expected_times;
2415
2416 PhasedLoopHandler *phased_loop;
2417
2418 bool should_exit = false;
2419 int expected_count = 1;
2420 TimerHandler *manager_timer = loop1->AddTimer(
2421 [&expected_count, &phased_loop, &loop1, &should_exit, this, kInterval]() {
2422 if (should_exit) {
2423 LOG(INFO) << "Exiting";
2424 this->Exit();
2425 return;
2426 }
2427 expected_count = 10;
2428 // Knock off 1 ns, since the scheduler rounds up when it is
2429 // scheduled to exactly a loop time.
2430 phased_loop->Reschedule(loop1->context().monotonic_event_time +
2431 kInterval * expected_count -
2432 std::chrono::nanoseconds(1));
2433 should_exit = true;
2434 });
2435
2436 phased_loop = loop1->AddPhasedLoop(
2437 [&expected_times, &loop1, manager_timer, &expected_count](int count) {
2438 EXPECT_EQ(count, expected_count);
2439 expected_times.push_back(loop1->context().monotonic_event_time);
2440
Philipp Schradera6712522023-07-05 20:25:11 -07002441 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002442 },
2443 kInterval, kOffset);
2444 phased_loop->set_name("Test loop");
2445 manager_timer->set_name("Manager timer");
2446
2447 Run();
2448
2449 ASSERT_EQ(2u, expected_times.size());
2450 ASSERT_EQ(expected_times[0] + expected_count * kInterval, expected_times[1]);
2451}
2452
2453// Tests that a phased loop responds correctly to having its phase offset
2454// incremented and then being scheduled after a set time, exercising a pattern
2455// where a phased loop's offset is changed while trying to maintain the trigger
2456// at a consistent period.
2457TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleWithLaterOffset) {
2458 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2459 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2460
2461 auto loop1 = MakePrimary();
2462
2463 std::vector<::aos::monotonic_clock::time_point> expected_times;
2464
2465 PhasedLoopHandler *phased_loop;
2466
2467 bool should_exit = false;
2468 TimerHandler *manager_timer = loop1->AddTimer(
2469 [&phased_loop, &loop1, &should_exit, this, kInterval, kOffset]() {
2470 if (should_exit) {
2471 LOG(INFO) << "Exiting";
2472 this->Exit();
2473 return;
2474 }
2475 // Schedule the next callback to be strictly later than the current time
2476 // + interval / 2, to ensure a consistent frequency.
2477 monotonic_clock::time_point half_time =
2478 loop1->context().monotonic_event_time + kInterval / 2;
2479 phased_loop->set_interval_and_offset(
2480 kInterval, kOffset + std::chrono::nanoseconds(1), half_time);
2481 phased_loop->Reschedule(half_time);
2482 should_exit = true;
2483 });
2484
2485 phased_loop = loop1->AddPhasedLoop(
2486 [&expected_times, &loop1, manager_timer](int count) {
2487 EXPECT_EQ(1, count);
2488 expected_times.push_back(loop1->context().monotonic_event_time);
2489
Philipp Schradera6712522023-07-05 20:25:11 -07002490 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002491 },
2492 kInterval, kOffset);
2493 phased_loop->set_name("Test loop");
2494 manager_timer->set_name("Manager timer");
2495
2496 Run();
2497
2498 ASSERT_EQ(2u, expected_times.size());
2499 ASSERT_EQ(expected_times[0] + kInterval + std::chrono::nanoseconds(1),
2500 expected_times[1]);
2501}
2502
2503// Tests that a phased loop responds correctly to having its phase offset
2504// decremented and then being scheduled after a set time, exercising a pattern
2505// where a phased loop's offset is changed while trying to maintain the trigger
2506// at a consistent period.
2507TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleWithEarlierOffset) {
2508 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2509 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2510
2511 auto loop1 = MakePrimary();
2512
2513 std::vector<::aos::monotonic_clock::time_point> expected_times;
2514
2515 PhasedLoopHandler *phased_loop;
2516
2517 bool should_exit = false;
2518 TimerHandler *manager_timer = loop1->AddTimer(
2519 [&phased_loop, &loop1, &should_exit, this, kInterval, kOffset]() {
2520 if (should_exit) {
2521 LOG(INFO) << "Exiting";
2522 this->Exit();
2523 return;
2524 }
2525 // Schedule the next callback to be strictly later than the current time
2526 // + interval / 2, to ensure a consistent frequency.
2527 const aos::monotonic_clock::time_point half_time =
2528 loop1->context().monotonic_event_time + kInterval / 2;
2529 phased_loop->set_interval_and_offset(
2530 kInterval, kOffset - std::chrono::nanoseconds(1), half_time);
2531 phased_loop->Reschedule(half_time);
2532 should_exit = true;
2533 });
2534
2535 phased_loop = loop1->AddPhasedLoop(
2536 [&expected_times, &loop1, manager_timer](int count) {
2537 EXPECT_EQ(1, count);
2538 expected_times.push_back(loop1->context().monotonic_event_time);
2539
Philipp Schradera6712522023-07-05 20:25:11 -07002540 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002541 },
2542 kInterval, kOffset);
2543 phased_loop->set_name("Test loop");
2544 manager_timer->set_name("Manager timer");
2545
2546 Run();
2547
2548 ASSERT_EQ(2u, expected_times.size());
2549 ASSERT_EQ(expected_times[0] + kInterval - std::chrono::nanoseconds(1),
2550 expected_times[1]);
2551}
2552
Austin Schuh39788ff2019-12-01 18:22:57 -08002553// Tests that senders count correctly in the timing report.
2554TEST_P(AbstractEventLoopTest, SenderTimingReport) {
2555 FLAGS_timing_report_ms = 1000;
2556 auto loop1 = MakePrimary();
2557
2558 auto loop2 = Make("watcher_loop");
2559 loop2->MakeWatcher("/test", [](const TestMessage &) {});
2560
2561 auto loop3 = Make();
2562
2563 Fetcher<timing::Report> report_fetcher =
2564 loop3->MakeFetcher<timing::Report>("/aos");
2565 EXPECT_FALSE(report_fetcher.Fetch());
2566
2567 auto sender = loop1->MakeSender<TestMessage>("/test");
2568
James Kuszmaul78514332022-04-06 15:08:34 -07002569 // Sanity check channel frequencies to ensure that we've designed the test
2570 // correctly.
2571 ASSERT_EQ(800, sender.channel()->frequency());
Austin Schuhfff9c3a2023-06-16 18:48:23 -07002572 ASSERT_EQ(2000000000, configuration::ChannelStorageDuration(
2573 loop1->configuration(), sender.channel())
2574 .count());
James Kuszmaul78514332022-04-06 15:08:34 -07002575 constexpr int kMaxAllowedMessages = 800 * 2;
2576 constexpr int kSendMessages = kMaxAllowedMessages * 2;
2577 constexpr int kDroppedMessages = kSendMessages - kMaxAllowedMessages;
2578
Austin Schuh39788ff2019-12-01 18:22:57 -08002579 // Add a timer to actually quit.
2580 auto test_timer = loop1->AddTimer([&sender]() {
James Kuszmaul78514332022-04-06 15:08:34 -07002581 for (int i = 0; i < kSendMessages; ++i) {
Austin Schuh39788ff2019-12-01 18:22:57 -08002582 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2583 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2584 builder.add_value(200 + i);
James Kuszmaul78514332022-04-06 15:08:34 -07002585 if (i < kMaxAllowedMessages) {
2586 msg.CheckOk(msg.Send(builder.Finish()));
2587 } else {
2588 EXPECT_EQ(RawSender::Error::kMessagesSentTooFast,
2589 msg.Send(builder.Finish()));
2590 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002591 }
2592 });
2593
2594 // Quit after 1 timing report, mid way through the next cycle.
2595 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2596
2597 loop1->OnRun([&test_timer, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002598 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1500));
Austin Schuh39788ff2019-12-01 18:22:57 -08002599 });
2600
2601 Run();
2602
Austin Schuh6bae8252021-02-07 22:01:49 -08002603 if (do_timing_reports() == DoTimingReports::kYes) {
2604 // And, since we are here, check that the timing report makes sense.
2605 // Start by looking for our event loop's timing.
2606 FlatbufferDetachedBuffer<timing::Report> primary_report =
2607 FlatbufferDetachedBuffer<timing::Report>::Empty();
2608 while (report_fetcher.FetchNext()) {
Austin Schuh8902fa52021-03-14 22:39:24 -07002609 VLOG(1) << "Report " << FlatbufferToJson(report_fetcher.get());
Austin Schuh6bae8252021-02-07 22:01:49 -08002610 if (report_fetcher->name()->string_view() == "primary") {
2611 primary_report = CopyFlatBuffer(report_fetcher.get());
2612 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002613 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002614
Austin Schuh8902fa52021-03-14 22:39:24 -07002615 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
Austin Schuh6bae8252021-02-07 22:01:49 -08002616
2617 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2618
2619 ASSERT_NE(primary_report.message().senders(), nullptr);
2620 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2621
2622 // Confirm that the sender looks sane.
2623 EXPECT_EQ(
2624 loop1->configuration()
2625 ->channels()
2626 ->Get(primary_report.message().senders()->Get(0)->channel_index())
2627 ->name()
2628 ->string_view(),
2629 "/test");
James Kuszmaul78514332022-04-06 15:08:34 -07002630 EXPECT_EQ(primary_report.message().senders()->Get(0)->count(),
2631 kMaxAllowedMessages);
2632 ASSERT_TRUE(primary_report.message().senders()->Get(0)->has_error_counts());
2633 ASSERT_EQ(
2634 primary_report.message().senders()->Get(0)->error_counts()->size(), 2u);
2635 EXPECT_EQ(
2636 primary_report.message()
2637 .senders()
2638 ->Get(0)
2639 ->error_counts()
2640 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2641 ->count(),
2642 kDroppedMessages)
2643 << aos::FlatbufferToJson(primary_report);
2644 EXPECT_EQ(primary_report.message()
2645 .senders()
2646 ->Get(0)
2647 ->error_counts()
2648 ->Get(static_cast<size_t>(timing::SendError::INVALID_REDZONE))
2649 ->count(),
2650 0);
Austin Schuh6bae8252021-02-07 22:01:49 -08002651
2652 // Confirm that the timing primary_report sender looks sane.
2653 EXPECT_EQ(
2654 loop1->configuration()
2655 ->channels()
2656 ->Get(primary_report.message().senders()->Get(1)->channel_index())
2657 ->name()
2658 ->string_view(),
2659 "/aos");
2660 EXPECT_EQ(primary_report.message().senders()->Get(1)->count(), 1);
2661
2662 ASSERT_NE(primary_report.message().timers(), nullptr);
2663 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2664
2665 // Make sure there are no phased loops or watchers.
2666 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2667 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2668 } else {
2669 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002670 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002671}
2672
James Kuszmaul93abac12022-04-14 15:05:10 -07002673// Tests that the RawSender::Send(void*, size_t) overload tracks things properly
2674// in its timing report.
2675TEST_P(AbstractEventLoopTest, CopySenderTimingReport) {
2676 gflags::FlagSaver flag_saver;
2677 FLAGS_timing_report_ms = 1000;
2678 auto loop1 = Make();
2679 auto loop2 = MakePrimary();
2680
2681 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2682 JsonToFlatbuffer<TestMessage>("{}");
2683
2684 std::unique_ptr<aos::RawSender> sender =
2685 loop2->MakeRawSender(configuration::GetChannel(
2686 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
2687
2688 Fetcher<timing::Report> report_fetcher =
2689 loop1->MakeFetcher<timing::Report>("/aos");
2690 EXPECT_FALSE(report_fetcher.Fetch());
2691
2692 loop2->OnRun([&]() {
2693 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
2694 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2695 RawSender::Error::kOk);
2696 }
2697 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2698 RawSender::Error::kMessagesSentTooFast);
2699 });
2700 // Quit after 1 timing report, mid way through the next cycle.
2701 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
2702
2703 Run();
2704
2705 if (do_timing_reports() == DoTimingReports::kYes) {
2706 // Check that the sent too fast actually got recorded by the timing report.
2707 FlatbufferDetachedBuffer<timing::Report> primary_report =
2708 FlatbufferDetachedBuffer<timing::Report>::Empty();
2709 while (report_fetcher.FetchNext()) {
2710 if (report_fetcher->name()->string_view() == "primary") {
2711 primary_report = CopyFlatBuffer(report_fetcher.get());
2712 }
2713 }
2714
2715 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2716
2717 ASSERT_NE(primary_report.message().senders(), nullptr);
2718 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2719 EXPECT_EQ(
2720 primary_report.message()
2721 .senders()
2722 ->Get(0)
2723 ->error_counts()
2724 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2725 ->count(),
2726 1);
2727 }
2728}
2729
Austin Schuhe0ab4de2023-05-03 08:05:08 -07002730// Tests that the RawSender::Send(SharedSpan) overload works.
2731TEST_P(AbstractEventLoopTest, SharedSenderTimingReport) {
2732 gflags::FlagSaver flag_saver;
2733 FLAGS_timing_report_ms = 1000;
2734 auto loop1 = Make();
2735 auto loop2 = MakePrimary();
2736
2737 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2738 JsonToFlatbuffer<TestMessage>("{}");
2739
2740 std::unique_ptr<aos::RawSender> sender =
2741 loop2->MakeRawSender(configuration::GetChannel(
2742 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
2743
2744 Fetcher<timing::Report> report_fetcher =
2745 loop1->MakeFetcher<timing::Report>("/aos");
2746 EXPECT_FALSE(report_fetcher.Fetch());
2747
2748 loop2->OnRun([&]() {
2749 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
2750 auto shared_span = MakeSharedSpan(kMessage.span().size());
2751 memcpy(shared_span.second.data(), kMessage.span().data(),
2752 kMessage.span().size());
2753 EXPECT_EQ(sender->Send(std::move(shared_span.first)),
2754 RawSender::Error::kOk);
2755 }
2756 auto shared_span = MakeSharedSpan(kMessage.span().size());
2757 memcpy(shared_span.second.data(), kMessage.span().data(),
2758 kMessage.span().size());
2759 EXPECT_EQ(sender->Send(std::move(shared_span.first)),
2760 RawSender::Error::kMessagesSentTooFast);
2761 });
2762 // Quit after 1 timing report, mid way through the next cycle.
2763 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
2764
2765 Run();
2766
2767 if (do_timing_reports() == DoTimingReports::kYes) {
2768 // Check that the sent too fast actually got recorded by the timing report.
2769 FlatbufferDetachedBuffer<timing::Report> primary_report =
2770 FlatbufferDetachedBuffer<timing::Report>::Empty();
2771 while (report_fetcher.FetchNext()) {
2772 if (report_fetcher->name()->string_view() == "primary") {
2773 primary_report = CopyFlatBuffer(report_fetcher.get());
2774 }
2775 }
2776
2777 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2778
2779 ASSERT_NE(primary_report.message().senders(), nullptr);
2780 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2781 EXPECT_EQ(
2782 primary_report.message()
2783 .senders()
2784 ->Get(0)
2785 ->error_counts()
2786 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2787 ->count(),
2788 1);
2789 }
2790}
2791
Austin Schuh39788ff2019-12-01 18:22:57 -08002792// Tests that senders count correctly in the timing report.
2793TEST_P(AbstractEventLoopTest, WatcherTimingReport) {
2794 FLAGS_timing_report_ms = 1000;
2795 auto loop1 = MakePrimary();
2796 loop1->MakeWatcher("/test", [](const TestMessage &) {});
2797
2798 auto loop2 = Make("sender_loop");
2799
2800 auto loop3 = Make();
2801
2802 Fetcher<timing::Report> report_fetcher =
2803 loop3->MakeFetcher<timing::Report>("/aos");
2804 EXPECT_FALSE(report_fetcher.Fetch());
2805
2806 auto sender = loop2->MakeSender<TestMessage>("/test");
2807
2808 // Add a timer to actually quit.
2809 auto test_timer = loop1->AddTimer([&sender]() {
2810 for (int i = 0; i < 10; ++i) {
2811 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2812 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2813 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002814 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002815 }
2816 });
2817
2818 // Quit after 1 timing report, mid way through the next cycle.
2819 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2820
2821 loop1->OnRun([&test_timer, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002822 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1500));
Austin Schuh39788ff2019-12-01 18:22:57 -08002823 });
2824
2825 Run();
2826
Austin Schuh6bae8252021-02-07 22:01:49 -08002827 if (do_timing_reports() == DoTimingReports::kYes) {
2828 // And, since we are here, check that the timing report makes sense.
2829 // Start by looking for our event loop's timing.
2830 FlatbufferDetachedBuffer<timing::Report> primary_report =
2831 FlatbufferDetachedBuffer<timing::Report>::Empty();
2832 while (report_fetcher.FetchNext()) {
2833 LOG(INFO) << "Report " << FlatbufferToJson(report_fetcher.get());
2834 if (report_fetcher->name()->string_view() == "primary") {
2835 primary_report = CopyFlatBuffer(report_fetcher.get());
2836 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002837 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002838
2839 // Check the watcher report.
2840 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2841
2842 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2843
2844 // Just the timing report timer.
2845 ASSERT_NE(primary_report.message().timers(), nullptr);
2846 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2847
2848 // No phased loops
2849 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2850
2851 ASSERT_NE(primary_report.message().watchers(), nullptr);
2852 ASSERT_EQ(primary_report.message().watchers()->size(), 1);
2853 EXPECT_EQ(primary_report.message().watchers()->Get(0)->count(), 10);
2854 } else {
2855 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002856 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002857}
2858
2859// Tests that fetchers count correctly in the timing report.
2860TEST_P(AbstractEventLoopTest, FetcherTimingReport) {
2861 FLAGS_timing_report_ms = 1000;
2862 auto loop1 = MakePrimary();
2863 auto loop2 = Make("sender_loop");
2864
2865 auto loop3 = Make();
2866
2867 Fetcher<timing::Report> report_fetcher =
2868 loop3->MakeFetcher<timing::Report>("/aos");
2869 EXPECT_FALSE(report_fetcher.Fetch());
2870
2871 auto sender = loop2->MakeSender<TestMessage>("/test");
2872 auto fetcher1 = loop1->MakeFetcher<TestMessage>("/test");
2873 auto fetcher2 = loop1->MakeFetcher<TestMessage>("/test");
2874 fetcher1.Fetch();
2875 fetcher2.Fetch();
2876
2877 // Add a timer to actually quit.
2878 auto test_timer = loop1->AddTimer([&sender]() {
2879 for (int i = 0; i < 10; ++i) {
2880 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2881 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2882 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002883 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002884 }
2885 });
2886
2887 auto test_timer2 = loop1->AddTimer([&fetcher1, &fetcher2]() {
2888 fetcher1.Fetch();
2889 while (fetcher2.FetchNext()) {
2890 }
2891 });
2892
2893 // Quit after 1 timing report, mid way through the next cycle.
2894 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2895
2896 loop1->OnRun([test_timer, test_timer2, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002897 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1400));
2898 test_timer2->Schedule(loop1->monotonic_now() + chrono::milliseconds(1600));
Austin Schuh39788ff2019-12-01 18:22:57 -08002899 });
2900
2901 Run();
2902
Austin Schuh6bae8252021-02-07 22:01:49 -08002903 if (do_timing_reports() == DoTimingReports::kYes) {
2904 // And, since we are here, check that the timing report makes sense.
2905 // Start by looking for our event loop's timing.
2906 FlatbufferDetachedBuffer<timing::Report> primary_report =
2907 FlatbufferDetachedBuffer<timing::Report>::Empty();
2908 while (report_fetcher.FetchNext()) {
2909 if (report_fetcher->name()->string_view() == "primary") {
2910 primary_report = CopyFlatBuffer(report_fetcher.get());
2911 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002912 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002913
2914 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2915
2916 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2917
2918 ASSERT_NE(primary_report.message().senders(), nullptr);
2919 EXPECT_EQ(primary_report.message().senders()->size(), 2);
2920
2921 ASSERT_NE(primary_report.message().timers(), nullptr);
2922 EXPECT_EQ(primary_report.message().timers()->size(), 4);
2923
2924 // Make sure there are no phased loops or watchers.
2925 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2926 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2927
2928 // Now look at the fetchrs.
2929 ASSERT_NE(primary_report.message().fetchers(), nullptr);
2930 ASSERT_EQ(primary_report.message().fetchers()->size(), 2);
2931
2932 EXPECT_EQ(primary_report.message().fetchers()->Get(0)->count(), 1);
2933 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->average(),
2934 0.1);
2935 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->min(),
2936 0.1);
2937 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->max(),
2938 0.1);
2939 EXPECT_EQ(primary_report.message()
2940 .fetchers()
2941 ->Get(0)
2942 ->latency()
2943 ->standard_deviation(),
2944 0.0);
2945
2946 EXPECT_EQ(primary_report.message().fetchers()->Get(1)->count(), 10);
2947 } else {
2948 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002949 }
Austin Schuh52d325c2019-06-23 18:59:06 -07002950}
2951
Austin Schuh67420a42019-12-21 21:55:04 -08002952// Tests that a raw watcher and raw fetcher can receive messages from a raw
2953// sender without messing up offsets.
2954TEST_P(AbstractEventLoopTest, RawBasic) {
2955 auto loop1 = Make();
2956 auto loop2 = MakePrimary();
2957 auto loop3 = Make();
2958
Austin Schuha9df9ad2021-06-16 14:49:39 -07002959 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2960 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuh67420a42019-12-21 21:55:04 -08002961
2962 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002963 loop1->MakeRawSender(configuration::GetChannel(
2964 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08002965
2966 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002967 loop3->MakeRawFetcher(configuration::GetChannel(
2968 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08002969
Austin Schuha9df9ad2021-06-16 14:49:39 -07002970 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002971 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2972 RawSender::Error::kOk);
Austin Schuha9df9ad2021-06-16 14:49:39 -07002973 });
Austin Schuh67420a42019-12-21 21:55:04 -08002974
2975 bool happened = false;
2976 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08002977 configuration::GetChannel(loop2->configuration(), "/test",
2978 "aos.TestMessage", "", nullptr),
Austin Schuha9df9ad2021-06-16 14:49:39 -07002979 [this, &kMessage, &fetcher, &happened](const Context &context,
2980 const void *message) {
Austin Schuh67420a42019-12-21 21:55:04 -08002981 happened = true;
Austin Schuha9df9ad2021-06-16 14:49:39 -07002982 EXPECT_EQ(
2983 kMessage.span(),
2984 absl::Span<const uint8_t>(
2985 reinterpret_cast<const uint8_t *>(message), context.size));
2986 EXPECT_EQ(message, context.data);
Austin Schuh67420a42019-12-21 21:55:04 -08002987
2988 ASSERT_TRUE(fetcher->Fetch());
2989
Austin Schuha9df9ad2021-06-16 14:49:39 -07002990 EXPECT_EQ(kMessage.span(),
2991 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
2992 fetcher->context().data),
2993 fetcher->context().size));
Austin Schuh67420a42019-12-21 21:55:04 -08002994
2995 this->Exit();
2996 });
2997
2998 EXPECT_FALSE(happened);
2999 Run();
3000 EXPECT_TRUE(happened);
3001}
3002
Austin Schuhad154822019-12-27 15:45:13 -08003003// Tests that a raw watcher and raw fetcher can receive messages from a raw
Brian Silvermanbf889922021-11-10 12:41:57 -08003004// sender without messing up offsets, using the RawSpan overload.
3005TEST_P(AbstractEventLoopTest, RawBasicSharedSpan) {
3006 auto loop1 = Make();
3007 auto loop2 = MakePrimary();
3008 auto loop3 = Make();
3009
3010 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3011 JsonToFlatbuffer<TestMessage>("{}");
3012
3013 std::unique_ptr<aos::RawSender> sender =
3014 loop1->MakeRawSender(configuration::GetChannel(
3015 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
3016
3017 std::unique_ptr<aos::RawFetcher> fetcher =
3018 loop3->MakeRawFetcher(configuration::GetChannel(
3019 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
3020
3021 loop2->OnRun([&]() {
Austin Schuhe0ab4de2023-05-03 08:05:08 -07003022 auto shared_span = MakeSharedSpan(kMessage.span().size());
3023 memcpy(shared_span.second.data(), kMessage.span().data(),
3024 kMessage.span().size());
3025 sender->CheckOk(sender->Send(std::move(shared_span.first)));
Brian Silvermanbf889922021-11-10 12:41:57 -08003026 });
3027
3028 bool happened = false;
3029 loop2->MakeRawWatcher(
3030 configuration::GetChannel(loop2->configuration(), "/test",
3031 "aos.TestMessage", "", nullptr),
3032 [this, &kMessage, &fetcher, &happened](const Context &context,
3033 const void *message) {
3034 happened = true;
3035 EXPECT_EQ(
3036 kMessage.span(),
3037 absl::Span<const uint8_t>(
3038 reinterpret_cast<const uint8_t *>(message), context.size));
3039 EXPECT_EQ(message, context.data);
3040
3041 ASSERT_TRUE(fetcher->Fetch());
3042
3043 EXPECT_EQ(kMessage.span(),
3044 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
3045 fetcher->context().data),
3046 fetcher->context().size));
3047
3048 this->Exit();
3049 });
3050
3051 EXPECT_FALSE(happened);
3052 Run();
3053 EXPECT_TRUE(happened);
3054}
3055
3056// Tests that a raw watcher and raw fetcher can receive messages from a raw
Austin Schuhad154822019-12-27 15:45:13 -08003057// sender with remote times filled out.
3058TEST_P(AbstractEventLoopTest, RawRemoteTimes) {
3059 auto loop1 = Make();
3060 auto loop2 = MakePrimary();
3061 auto loop3 = Make();
3062
Austin Schuha9df9ad2021-06-16 14:49:39 -07003063 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3064 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08003065
3066 const aos::monotonic_clock::time_point monotonic_remote_time =
3067 aos::monotonic_clock::time_point(chrono::seconds(1501));
3068 const aos::realtime_clock::time_point realtime_remote_time =
3069 aos::realtime_clock::time_point(chrono::seconds(3132));
Austin Schuhb5c6f972021-03-14 21:53:07 -07003070 const uint32_t remote_queue_index = 0x254971;
Austin Schuha9012be2021-07-21 15:19:11 -07003071 const UUID source_boot_uuid = UUID::Random();
Austin Schuhad154822019-12-27 15:45:13 -08003072
3073 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003074 loop1->MakeRawSender(configuration::GetChannel(
3075 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08003076
3077 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003078 loop3->MakeRawFetcher(configuration::GetChannel(
3079 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08003080
3081 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07003082 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size(),
3083 monotonic_remote_time, realtime_remote_time,
3084 remote_queue_index, source_boot_uuid),
3085 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08003086 });
3087
3088 bool happened = false;
3089 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08003090 configuration::GetChannel(loop2->configuration(), "/test",
3091 "aos.TestMessage", "", nullptr),
Austin Schuha9012be2021-07-21 15:19:11 -07003092 [this, monotonic_remote_time, realtime_remote_time, source_boot_uuid,
Austin Schuhb5c6f972021-03-14 21:53:07 -07003093 remote_queue_index, &fetcher,
3094 &happened](const Context &context, const void * /*message*/) {
Austin Schuhad154822019-12-27 15:45:13 -08003095 happened = true;
3096 EXPECT_EQ(monotonic_remote_time, context.monotonic_remote_time);
3097 EXPECT_EQ(realtime_remote_time, context.realtime_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07003098 EXPECT_EQ(source_boot_uuid, context.source_boot_uuid);
Austin Schuhb5c6f972021-03-14 21:53:07 -07003099 EXPECT_EQ(remote_queue_index, context.remote_queue_index);
Austin Schuhad154822019-12-27 15:45:13 -08003100
3101 ASSERT_TRUE(fetcher->Fetch());
3102 EXPECT_EQ(monotonic_remote_time,
3103 fetcher->context().monotonic_remote_time);
3104 EXPECT_EQ(realtime_remote_time,
3105 fetcher->context().realtime_remote_time);
3106
3107 this->Exit();
3108 });
3109
3110 EXPECT_FALSE(happened);
3111 Run();
3112 EXPECT_TRUE(happened);
3113}
3114
3115// Tests that a raw sender fills out sent data.
3116TEST_P(AbstractEventLoopTest, RawSenderSentData) {
3117 auto loop1 = MakePrimary();
3118
Austin Schuha9df9ad2021-06-16 14:49:39 -07003119 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3120 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08003121
3122 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003123 loop1->MakeRawSender(configuration::GetChannel(
3124 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08003125
Tyler Chatow67ddb032020-01-12 14:30:04 -08003126 const aos::monotonic_clock::time_point monotonic_now = loop1->monotonic_now();
3127 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08003128
milind1f1dca32021-07-03 13:50:07 -07003129 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
3130 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08003131
3132 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
3133 EXPECT_LE(sender->monotonic_sent_time(),
3134 monotonic_now + chrono::milliseconds(100));
3135 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
3136 EXPECT_LE(sender->realtime_sent_time(),
3137 realtime_now + chrono::milliseconds(100));
3138 EXPECT_EQ(sender->sent_queue_index(), 0u);
3139
milind1f1dca32021-07-03 13:50:07 -07003140 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
3141 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08003142
3143 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
3144 EXPECT_LE(sender->monotonic_sent_time(),
3145 monotonic_now + chrono::milliseconds(100));
3146 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
3147 EXPECT_LE(sender->realtime_sent_time(),
3148 realtime_now + chrono::milliseconds(100));
3149 EXPECT_EQ(sender->sent_queue_index(), 1u);
3150}
3151
Austin Schuh217a9782019-12-21 23:02:50 -08003152// Tests that not setting up nodes results in no node.
3153TEST_P(AbstractEventLoopTest, NoNode) {
3154 auto loop1 = Make();
3155 auto loop2 = MakePrimary();
3156
3157 EXPECT_EQ(loop1->node(), nullptr);
3158 EXPECT_EQ(loop2->node(), nullptr);
3159}
3160
3161// Tests that setting up nodes results in node being set.
3162TEST_P(AbstractEventLoopTest, Node) {
3163 EnableNodes("me");
3164
3165 auto loop1 = Make();
3166 auto loop2 = MakePrimary();
3167
3168 EXPECT_NE(loop1->node(), nullptr);
3169 EXPECT_NE(loop2->node(), nullptr);
3170}
3171
3172// Tests that watchers work with a node setup.
3173TEST_P(AbstractEventLoopTest, NodeWatcher) {
3174 EnableNodes("me");
3175
3176 auto loop1 = Make();
3177 auto loop2 = Make();
3178 loop1->MakeWatcher("/test", [](const TestMessage &) {});
Tyler Chatow67ddb032020-01-12 14:30:04 -08003179 loop2->MakeRawWatcher(
3180 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
3181 nullptr),
3182 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08003183}
3184
Brian Silverman454bc112020-03-05 14:21:25 -08003185// Tests that no-arg watchers work with a node setup.
3186TEST_P(AbstractEventLoopTest, NodeNoArgWatcher) {
3187 EnableNodes("me");
3188
3189 auto loop1 = Make();
3190 auto loop2 = Make();
3191 loop1->MakeWatcher("/test", [](const TestMessage &) {});
3192 loop2->MakeRawNoArgWatcher(
3193 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
3194 nullptr),
3195 [](const Context &) {});
3196}
3197
Austin Schuh217a9782019-12-21 23:02:50 -08003198// Tests that fetcher work with a node setup.
3199TEST_P(AbstractEventLoopTest, NodeFetcher) {
3200 EnableNodes("me");
3201 auto loop1 = Make();
3202
3203 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
Tyler Chatow67ddb032020-01-12 14:30:04 -08003204 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
3205 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08003206}
3207
3208// Tests that sender work with a node setup.
3209TEST_P(AbstractEventLoopTest, NodeSender) {
3210 EnableNodes("me");
3211 auto loop1 = Make();
3212
3213 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
3214}
3215
Austin Schuhcc6070c2020-10-10 20:25:56 -07003216// Tests that a non-realtime event loop timer is marked non-realtime.
3217TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopTimer) {
3218 auto loop1 = MakePrimary();
3219
3220 // Add a timer to actually quit.
3221 auto test_timer = loop1->AddTimer([this]() {
3222 CheckNotRealtime();
3223 this->Exit();
3224 });
3225
3226 loop1->OnRun([&test_timer, &loop1]() {
3227 CheckNotRealtime();
Philipp Schradera6712522023-07-05 20:25:11 -07003228 test_timer->Schedule(loop1->monotonic_now(),
3229 ::std::chrono::milliseconds(100));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003230 });
3231
3232 Run();
3233}
3234
3235// Tests that a realtime event loop timer is marked realtime.
Austin Schuh9b1d6282022-06-10 17:03:21 -07003236TEST_P(AbstractEventLoopTest, RealtimeSend) {
3237 auto loop1 = MakePrimary();
3238
3239 loop1->SetRuntimeRealtimePriority(1);
3240
3241 auto sender = loop1->MakeSender<TestMessage>("/test2");
3242
3243 loop1->OnRun([&]() {
3244 CheckRealtime();
3245
3246 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3247 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
3248 builder.add_value(200);
3249 msg.CheckOk(msg.Send(builder.Finish()));
3250
3251 this->Exit();
3252 });
3253
3254 Run();
3255}
3256
3257// Tests that a realtime event loop timer is marked realtime.
Austin Schuhcc6070c2020-10-10 20:25:56 -07003258TEST_P(AbstractEventLoopTest, RealtimeEventLoopTimer) {
3259 auto loop1 = MakePrimary();
3260
3261 loop1->SetRuntimeRealtimePriority(1);
3262
3263 // Add a timer to actually quit.
3264 auto test_timer = loop1->AddTimer([this]() {
3265 CheckRealtime();
3266 this->Exit();
3267 });
3268
3269 loop1->OnRun([&test_timer, &loop1]() {
3270 CheckRealtime();
Philipp Schradera6712522023-07-05 20:25:11 -07003271 test_timer->Schedule(loop1->monotonic_now(),
3272 ::std::chrono::milliseconds(100));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003273 });
3274
3275 Run();
3276}
3277
3278// Tests that a non-realtime event loop phased loop is marked non-realtime.
3279TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopPhasedLoop) {
3280 auto loop1 = MakePrimary();
3281
3282 // Add a timer to actually quit.
3283 loop1->AddPhasedLoop(
3284 [this](int) {
3285 CheckNotRealtime();
3286 this->Exit();
3287 },
3288 chrono::seconds(1), chrono::seconds(0));
3289
3290 Run();
3291}
3292
3293// Tests that a realtime event loop phased loop is marked realtime.
3294TEST_P(AbstractEventLoopTest, RealtimeEventLoopPhasedLoop) {
3295 auto loop1 = MakePrimary();
3296
3297 loop1->SetRuntimeRealtimePriority(1);
3298
3299 // Add a timer to actually quit.
3300 loop1->AddPhasedLoop(
3301 [this](int) {
3302 CheckRealtime();
3303 this->Exit();
3304 },
3305 chrono::seconds(1), chrono::seconds(0));
3306
3307 Run();
3308}
3309
3310// Tests that a non-realtime event loop watcher is marked non-realtime.
3311TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopWatcher) {
3312 auto loop1 = MakePrimary();
3313 auto loop2 = Make();
3314
3315 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
3316
3317 loop1->OnRun([&]() {
3318 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3319 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07003320 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003321 });
3322
3323 loop1->MakeWatcher("/test", [&](const TestMessage &) {
3324 CheckNotRealtime();
3325 this->Exit();
3326 });
3327
3328 Run();
3329}
3330
3331// Tests that a realtime event loop watcher is marked realtime.
3332TEST_P(AbstractEventLoopTest, RealtimeEventLoopWatcher) {
3333 auto loop1 = MakePrimary();
3334 auto loop2 = Make();
3335
3336 loop1->SetRuntimeRealtimePriority(1);
3337
3338 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
3339
3340 loop1->OnRun([&]() {
3341 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3342 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07003343 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003344 });
3345
3346 loop1->MakeWatcher("/test", [&](const TestMessage &) {
3347 CheckRealtime();
3348 this->Exit();
3349 });
3350
3351 Run();
3352}
3353
Austin Schuha9012be2021-07-21 15:19:11 -07003354// Tests that event loop's context's monotonic time is set to a value on OnRun.
3355TEST_P(AbstractEventLoopTest, SetContextOnRun) {
3356 auto loop = MakePrimary();
3357
Austin Schuh0debde12022-08-17 16:25:17 -07003358 EXPECT_EQ(loop->context().monotonic_event_time, monotonic_clock::min_time);
3359 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3360 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3361 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3362 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3363 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
3364 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
3365 EXPECT_EQ(loop->context().size, 0u);
3366 EXPECT_EQ(loop->context().data, nullptr);
3367 EXPECT_EQ(loop->context().buffer_index, -1);
3368
Austin Schuha9012be2021-07-21 15:19:11 -07003369 // We want to check that monotonic event time is before monotonic now
3370 // called inside of callback, but after time point obtained callback.
3371 aos::monotonic_clock::time_point monotonic_event_time_on_run;
3372
3373 loop->OnRun([&]() {
3374 monotonic_event_time_on_run = loop->context().monotonic_event_time;
3375 EXPECT_LE(monotonic_event_time_on_run, loop->monotonic_now());
3376 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3377 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3378 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3379 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3380 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
Austin Schuh0debde12022-08-17 16:25:17 -07003381 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
Austin Schuha9012be2021-07-21 15:19:11 -07003382 EXPECT_EQ(loop->context().size, 0u);
3383 EXPECT_EQ(loop->context().data, nullptr);
3384 EXPECT_EQ(loop->context().buffer_index, -1);
3385 });
3386
3387 EndEventLoop(loop.get(), ::std::chrono::milliseconds(200));
3388
3389 const aos::monotonic_clock::time_point before_run_time =
3390 loop->monotonic_now();
3391 Run();
3392 EXPECT_GE(monotonic_event_time_on_run, before_run_time);
Austin Schuh0debde12022-08-17 16:25:17 -07003393
3394 EXPECT_EQ(loop->context().monotonic_event_time, monotonic_clock::min_time);
3395 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3396 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3397 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3398 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3399 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
3400 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
3401 EXPECT_EQ(loop->context().size, 0u);
3402 EXPECT_EQ(loop->context().data, nullptr);
3403 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuha9012be2021-07-21 15:19:11 -07003404}
3405
Austin Schuh217a9782019-12-21 23:02:50 -08003406// Tests that watchers fail when created on the wrong node.
3407TEST_P(AbstractEventLoopDeathTest, NodeWatcher) {
3408 EnableNodes("them");
3409
3410 auto loop1 = Make();
3411 auto loop2 = Make();
3412 EXPECT_DEATH({ loop1->MakeWatcher("/test", [](const TestMessage &) {}); },
3413 "node");
3414 EXPECT_DEATH(
3415 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08003416 loop2->MakeRawWatcher(
3417 configuration::GetChannel(configuration(), "/test",
3418 "aos.TestMessage", "", nullptr),
3419 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08003420 },
3421 "node");
Brian Silverman454bc112020-03-05 14:21:25 -08003422 EXPECT_DEATH({ loop1->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
3423 "node");
3424 EXPECT_DEATH(
3425 {
3426 loop2->MakeRawNoArgWatcher(
3427 configuration::GetChannel(configuration(), "/test",
3428 "aos.TestMessage", "", nullptr),
3429 [](const Context &) {});
3430 },
3431 "node");
Austin Schuh217a9782019-12-21 23:02:50 -08003432}
3433
3434// Tests that fetchers fail when created on the wrong node.
3435TEST_P(AbstractEventLoopDeathTest, NodeFetcher) {
3436 EnableNodes("them");
3437 auto loop1 = Make();
3438
3439 EXPECT_DEATH({ auto fetcher = loop1->MakeFetcher<TestMessage>("/test"); },
3440 "node");
3441 EXPECT_DEATH(
3442 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08003443 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
3444 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08003445 },
3446 "node");
3447}
3448
3449// Tests that senders fail when created on the wrong node.
3450TEST_P(AbstractEventLoopDeathTest, NodeSender) {
3451 EnableNodes("them");
3452 auto loop1 = Make();
3453
3454 EXPECT_DEATH(
3455 {
3456 aos::Sender<TestMessage> sender =
3457 loop1->MakeSender<TestMessage>("/test");
3458 },
3459 "node");
3460
3461 // Note: Creating raw senders is always supported. Right now, this lets us
3462 // use them to create message_gateway.
3463}
3464
Brian Silverman341b57e2020-06-23 16:23:18 -07003465// Tests creating multiple Builders from a single Sender at the same time.
3466TEST_P(AbstractEventLoopDeathTest, MultipleBuilders) {
3467 auto loop1 = Make();
3468 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
3469
3470 { auto builder = sender.MakeBuilder(); }
3471 {
3472 auto builder = sender.MakeBuilder();
3473 builder.MakeBuilder<TestMessage>().Finish();
3474 }
3475 {
3476 // Creating this after the first one was destroyed should be fine.
3477 auto builder = sender.MakeBuilder();
3478 builder.MakeBuilder<TestMessage>().Finish();
3479 // But not a second one.
3480 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
James Kuszmaulb1c11052023-11-06 13:20:53 -08003481 "May not have multiple active allocators");
Brian Silverman341b57e2020-06-23 16:23:18 -07003482 }
3483
3484 FlatbufferDetachedBuffer<TestMessage> detached =
3485 flatbuffers::DetachedBuffer();
3486 {
3487 auto builder = sender.MakeBuilder();
3488 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
3489 }
3490 {
3491 // This is the second one, after the detached one, so it should fail.
3492 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
James Kuszmaulb1c11052023-11-06 13:20:53 -08003493 "May not have multiple active allocators");
Brian Silverman341b57e2020-06-23 16:23:18 -07003494 }
3495
3496 // Clear the detached one, and then we should be able to create another.
3497 detached = flatbuffers::DetachedBuffer();
3498 {
3499 auto builder = sender.MakeBuilder();
3500 builder.MakeBuilder<TestMessage>().Finish();
3501 }
3502
3503 // And then detach another one.
3504 {
3505 auto builder = sender.MakeBuilder();
3506 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
3507 }
3508}
3509
3510// Tests sending a buffer detached from a different builder.
3511TEST_P(AbstractEventLoopDeathTest, WrongDetachedBuffer) {
3512 auto loop1 = Make();
3513 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
3514 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
3515
3516 auto builder = sender1.MakeBuilder();
3517 FlatbufferDetachedBuffer<TestMessage> detached =
3518 builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
milind1f1dca32021-07-03 13:50:07 -07003519 EXPECT_DEATH(sender2.CheckOk(sender2.SendDetached(std::move(detached))),
Brian Silverman341b57e2020-06-23 16:23:18 -07003520 "May only send the buffer detached from this Sender");
3521}
3522
James Kuszmaul762e8692023-07-31 14:57:53 -07003523// Tests that senders fail when created on the wrong node.
3524TEST_P(AbstractEventLoopDeathTest, SetVersionWhileRunning) {
3525 auto loop1 = MakePrimary();
3526
3527 loop1->OnRun([&loop1, this]() {
3528 EXPECT_DEATH({ loop1->SetVersionString("abcdef"); },
3529 "timing report while running");
3530 Exit();
3531 });
3532
3533 Run();
3534}
3535
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003536int TestChannelFrequency(EventLoop *event_loop) {
3537 return event_loop->GetChannel<TestMessage>("/test")->frequency();
3538}
3539
3540int TestChannelQueueSize(EventLoop *event_loop) {
Austin Schuhfff9c3a2023-06-16 18:48:23 -07003541 return configuration::QueueSize(event_loop->configuration(),
3542 event_loop->GetChannel<TestMessage>("/test"));
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003543}
3544
3545RawSender::Error SendTestMessage(aos::Sender<TestMessage> &sender) {
3546 aos::Sender<TestMessage>::Builder builder = sender.MakeBuilder();
3547 TestMessage::Builder test_message_builder =
3548 builder.MakeBuilder<TestMessage>();
3549 test_message_builder.add_value(0);
3550 return builder.Send(test_message_builder.Finish());
3551}
3552
3553// Test that sending messages too fast returns
3554// RawSender::Error::kMessagesSentTooFast.
3555TEST_P(AbstractEventLoopTest, SendingMessagesTooFast) {
3556 auto event_loop = MakePrimary();
3557
3558 auto sender = event_loop->MakeSender<TestMessage>("/test");
3559
3560 // Send one message in the beginning, then wait until the
3561 // channel_storage_duration is almost done and start sending messages rapidly,
3562 // having some come in the next chanel_storage_duration. The queue_size is
3563 // 1600, so the 1601st message will be the last valid one (the initial message
3564 // having being sent more than a channel_storage_duration ago), and trying to
3565 // send the 1602nd message should return
3566 // RawSender::Error::kMessagesSentTooFast.
3567 EXPECT_EQ(SendTestMessage(sender), RawSender::Error::kOk);
3568 int msgs_sent = 1;
3569 const int queue_size = TestChannelQueueSize(event_loop.get());
3570
3571 const auto timer = event_loop->AddTimer([&]() {
3572 const bool done = (msgs_sent == queue_size + 1);
3573 ASSERT_EQ(
3574 SendTestMessage(sender),
3575 done ? RawSender::Error::kMessagesSentTooFast : RawSender::Error::kOk);
3576 msgs_sent++;
3577 if (done) {
3578 Exit();
3579 }
3580 });
3581
3582 const auto kRepeatOffset = std::chrono::milliseconds(1);
Austin Schuhfff9c3a2023-06-16 18:48:23 -07003583 const auto base_offset = configuration::ChannelStorageDuration(
3584 event_loop->configuration(), sender.channel()) -
3585 (kRepeatOffset * (queue_size / 2));
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003586 event_loop->OnRun([&event_loop, &timer, &base_offset, &kRepeatOffset]() {
Philipp Schradera6712522023-07-05 20:25:11 -07003587 timer->Schedule(event_loop->monotonic_now() + base_offset, kRepeatOffset);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003588 });
3589
3590 Run();
3591}
3592
3593// Tests that we are able to send messages successfully after sending messages
3594// too fast and waiting while continuously attempting to send messages.
3595// Also tests that SendFailureCounter is working correctly in this
3596// situation
3597TEST_P(AbstractEventLoopTest, SendingAfterSendingTooFast) {
3598 auto event_loop = MakePrimary();
3599
3600 auto sender = event_loop->MakeSender<TestMessage>("/test");
3601
Austin Schuh0e96d372023-05-08 10:10:21 -07003602 // We are sending bunches of messages at 100 Hz, so we will be sending too
3603 // fast after queue_size (800) ms. After this, keep sending messages, and
3604 // exactly a channel storage duration (2s) after we send the first message we
3605 // should be able to successfully send a message.
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003606
Austin Schuh0e96d372023-05-08 10:10:21 -07003607 const std::chrono::milliseconds kInterval = std::chrono::milliseconds(10);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003608 const monotonic_clock::duration channel_storage_duration =
Austin Schuhfff9c3a2023-06-16 18:48:23 -07003609 configuration::ChannelStorageDuration(event_loop->configuration(),
3610 sender.channel());
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003611 const int queue_size = TestChannelQueueSize(event_loop.get());
3612
3613 int msgs_sent = 0;
3614 SendFailureCounter counter;
3615 auto start = monotonic_clock::min_time;
3616
3617 event_loop->AddPhasedLoop(
Austin Schuh0e96d372023-05-08 10:10:21 -07003618 [&](int elapsed_cycles) {
3619 // The queue is setup for 800 messages/sec. We want to fill that up at
3620 // a rate of 2000 messages/sec so we make sure we fill it up.
3621 for (int i = 0; i < 2 * kInterval.count() * elapsed_cycles; ++i) {
3622 const auto actual_err = SendTestMessage(sender);
3623 const bool done_waiting = (start != monotonic_clock::min_time &&
3624 sender.monotonic_sent_time() >=
3625 (start + channel_storage_duration));
3626 const auto expected_err =
3627 (msgs_sent < queue_size || done_waiting
3628 ? RawSender::Error::kOk
3629 : RawSender::Error::kMessagesSentTooFast);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003630
Austin Schuh0e96d372023-05-08 10:10:21 -07003631 if (start == monotonic_clock::min_time) {
3632 start = sender.monotonic_sent_time();
3633 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003634
Austin Schuh0e96d372023-05-08 10:10:21 -07003635 ASSERT_EQ(actual_err, expected_err);
3636 counter.Count(actual_err);
3637 msgs_sent++;
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003638
Austin Schuh0e96d372023-05-08 10:10:21 -07003639 EXPECT_EQ(counter.failures(),
3640 msgs_sent <= queue_size
3641 ? 0
3642 : (msgs_sent - queue_size) -
3643 (actual_err == RawSender::Error::kOk ? 1 : 0));
3644 EXPECT_EQ(counter.just_failed(), actual_err != RawSender::Error::kOk);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003645
Austin Schuh0e96d372023-05-08 10:10:21 -07003646 if (done_waiting) {
3647 Exit();
3648 return;
3649 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003650 }
3651 },
3652 kInterval);
3653 Run();
3654}
3655
3656// Tests that RawSender::Error::kMessagesSentTooFast is returned
3657// when messages are sent too fast from senders in different loops
3658TEST_P(AbstractEventLoopTest, SendingTooFastWithMultipleLoops) {
3659 auto loop1 = MakePrimary();
3660 auto loop2 = Make();
3661
3662 auto sender1 = loop1->MakeSender<TestMessage>("/test");
3663 auto sender2 = loop2->MakeSender<TestMessage>("/test");
3664
3665 // Send queue_size messages split between the senders.
3666 const int queue_size = TestChannelQueueSize(loop1.get());
3667 for (int i = 0; i < queue_size / 2; i++) {
3668 ASSERT_EQ(SendTestMessage(sender1), RawSender::Error::kOk);
3669 ASSERT_EQ(SendTestMessage(sender2), RawSender::Error::kOk);
3670 }
3671
3672 // Since queue_size messages have been sent, this should return an error
3673 EXPECT_EQ(SendTestMessage(sender2), RawSender::Error::kMessagesSentTooFast);
3674}
3675
Austin Schuhdda6db72023-06-21 17:02:34 -07003676// Tests that a longer storage durations store more messages.
3677TEST_P(AbstractEventLoopTest, SendingTooFastWithLongDuration) {
3678 auto loop1 = MakePrimary();
3679
3680 auto sender1 = loop1->MakeSender<TestMessage>("/test3");
3681
3682 // Send queue_size messages split between the senders.
3683 const int queue_size =
3684 configuration::QueueSize(loop1->configuration(), sender1.channel());
3685 EXPECT_EQ(queue_size, 100 * 10);
3686 for (int i = 0; i < queue_size; i++) {
3687 ASSERT_EQ(SendTestMessage(sender1), RawSender::Error::kOk);
3688 }
3689
3690 // Since queue_size messages have been sent, and little time has elapsed,
3691 // this should return an error.
3692 EXPECT_EQ(SendTestMessage(sender1), RawSender::Error::kMessagesSentTooFast);
3693}
3694
Parker Schuhe4a70d62017-12-27 20:10:20 -08003695} // namespace testing
3696} // namespace aos