blob: 3fb9e9ab1ee954964e08d883407dfed66463b298 [file] [log] [blame]
Alex Perrycb7da4b2019-08-28 19:35:56 -07001#include "aos/events/event_loop_param_test.h"
Parker Schuhe4a70d62017-12-27 20:10:20 -08002
Austin Schuh52d325c2019-06-23 18:59:06 -07003#include <chrono>
Brian Silverman4f4e0612020-08-12 19:54:41 -07004#include <unordered_map>
5#include <unordered_set>
Austin Schuh52d325c2019-06-23 18:59:06 -07006
Philipp Schrader790cb542023-07-05 21:06:52 -07007#include "glog/logging.h"
8#include "gmock/gmock.h"
9#include "gtest/gtest.h"
10
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -070011#include "aos/events/test_message_generated.h"
James Kuszmaulb1c11052023-11-06 13:20:53 -080012#include "aos/events/test_message_static.h"
Austin Schuh54cf95f2019-11-29 13:14:18 -080013#include "aos/flatbuffer_merge.h"
Austin Schuhad9e5eb2021-11-19 20:33:55 -080014#include "aos/logging/log_message_generated.h"
15#include "aos/logging/logging.h"
Austin Schuhcc6070c2020-10-10 20:25:56 -070016#include "aos/realtime.h"
Austin Schuh9fe68f72019-08-10 19:32:03 -070017
Stephan Pleinesf63bde82024-01-13 15:59:33 -080018namespace aos::testing {
Austin Schuh52d325c2019-06-23 18:59:06 -070019namespace {
20namespace chrono = ::std::chrono;
21} // namespace
Parker Schuhe4a70d62017-12-27 20:10:20 -080022
Brian Silverman4f4e0612020-08-12 19:54:41 -070023::std::unique_ptr<EventLoop> AbstractEventLoopTest::Make(
24 std::string_view name) {
25 std::string name_copy(name);
26 if (name == "") {
27 name_copy = "loop";
28 name_copy += std::to_string(event_loop_count_);
29 }
30 ++event_loop_count_;
Austin Schuh6bae8252021-02-07 22:01:49 -080031 auto result = factory_->Make(name_copy);
32 if (do_timing_reports() == DoTimingReports::kNo) {
33 result->SkipTimingReport();
34 }
35 return result;
Brian Silverman4f4e0612020-08-12 19:54:41 -070036}
37
38void AbstractEventLoopTest::VerifyBuffers(
39 int number_buffers,
40 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>> fetchers,
41 std::vector<std::reference_wrapper<const Sender<TestMessage>>> senders) {
42 // The buffers which are in a sender.
43 std::unordered_set<int> in_sender;
44 for (const Sender<TestMessage> &sender : senders) {
45 const int this_buffer = sender.buffer_index();
46 CHECK_GE(this_buffer, 0);
47 CHECK_LT(this_buffer, number_buffers);
48 CHECK(in_sender.insert(this_buffer).second) << ": " << this_buffer;
49 }
50
51 if (read_method() != ReadMethod::PIN) {
52 // If we're not using PIN, we can't really verify anything about what
53 // buffers the fetchers have.
54 return;
55 }
56
57 // Mapping from TestMessage::value to buffer index.
58 std::unordered_map<int, int> fetcher_values;
59 for (const Fetcher<TestMessage> &fetcher : fetchers) {
60 if (!fetcher.get()) {
61 continue;
62 }
63 const int this_buffer = fetcher.context().buffer_index;
64 CHECK_GE(this_buffer, 0);
65 CHECK_LT(this_buffer, number_buffers);
66 CHECK(in_sender.count(this_buffer) == 0) << ": " << this_buffer;
67 const auto insert_result = fetcher_values.insert(
68 std::make_pair(fetcher.get()->value(), this_buffer));
69 if (!insert_result.second) {
70 CHECK_EQ(this_buffer, insert_result.first->second);
71 }
72 }
73}
74
Austin Schuh6b6dfa52019-06-12 20:16:20 -070075// Tests that watcher can receive messages from a sender.
Parker Schuhe4a70d62017-12-27 20:10:20 -080076// Also tests that OnRun() works.
77TEST_P(AbstractEventLoopTest, Basic) {
78 auto loop1 = Make();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070079 auto loop2 = MakePrimary();
80
Alex Perrycb7da4b2019-08-28 19:35:56 -070081 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
Austin Schuh6b6dfa52019-06-12 20:16:20 -070082
83 bool happened = false;
84
85 loop2->OnRun([&]() {
86 happened = true;
87
Alex Perrycb7da4b2019-08-28 19:35:56 -070088 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
89 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
90 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -070091 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -070092 });
93
94 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070095 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -070096 this->Exit();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070097 });
98
99 EXPECT_FALSE(happened);
100 Run();
101 EXPECT_TRUE(happened);
102}
103
James Kuszmaulb1c11052023-11-06 13:20:53 -0800104// Tests that watcher can receive messages from a static sender.
105// This confirms that the "static" flatbuffer API works with the EventLoop
106// senders.
107TEST_P(AbstractEventLoopTest, BasicStatic) {
108 auto loop1 = Make();
109 auto loop2 = MakePrimary();
110
111 aos::Sender<TestMessageStatic> sender =
112 loop1->MakeSender<TestMessageStatic>("/test");
113
114 bool happened = false;
115
116 loop2->OnRun([&]() {
117 happened = true;
118
119 aos::Sender<TestMessageStatic>::StaticBuilder msg =
120 sender.MakeStaticBuilder();
James Kuszmauldde65632023-12-07 16:12:26 -0800121 msg->set_value(200);
James Kuszmaulb1c11052023-11-06 13:20:53 -0800122 CHECK(msg.builder()->Verify());
123 msg.CheckOk(msg.Send());
124 });
125
126 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
127 EXPECT_EQ(message.value(), 200);
128 this->Exit();
129 });
130
131 EXPECT_FALSE(happened);
132 Run();
133 EXPECT_TRUE(happened);
134}
135
Brian Silverman341b57e2020-06-23 16:23:18 -0700136// Tests that watcher can receive messages from a sender, sent via SendDetached.
137TEST_P(AbstractEventLoopTest, BasicSendDetached) {
138 auto loop1 = Make();
139 auto loop2 = MakePrimary();
140
141 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
142
143 FlatbufferDetachedBuffer<TestMessage> detached =
144 flatbuffers::DetachedBuffer();
145 {
146 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
147 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
148 builder.add_value(100);
149 detached = msg.Detach(builder.Finish());
150 }
151 detached = flatbuffers::DetachedBuffer();
152 {
153 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
154 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
155 builder.add_value(200);
156 detached = msg.Detach(builder.Finish());
157 }
milind1f1dca32021-07-03 13:50:07 -0700158 sender.CheckOk(sender.SendDetached(std::move(detached)));
Brian Silverman341b57e2020-06-23 16:23:18 -0700159
160 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
161 ASSERT_TRUE(fetcher.Fetch());
162 EXPECT_EQ(fetcher->value(), 200);
163}
164
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800165// Verifies that a no-arg watcher will not have a data pointer.
166TEST_P(AbstractEventLoopTest, NoArgNoData) {
167 auto loop1 = Make();
168 auto loop2 = MakePrimary();
169
170 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
171
172 bool happened = false;
173
174 loop2->OnRun([&]() {
175 happened = true;
176
177 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
178 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -0700179 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800180 });
181
182 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
183 EXPECT_GT(loop2->context().size, 0u);
184 EXPECT_EQ(nullptr, loop2->context().data);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700185 EXPECT_EQ(-1, loop2->context().buffer_index);
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800186 this->Exit();
187 });
188
189 EXPECT_FALSE(happened);
190 Run();
191 EXPECT_TRUE(happened);
192}
193
Brian Silverman454bc112020-03-05 14:21:25 -0800194// Tests that no-arg watcher can receive messages from a sender.
195// Also tests that OnRun() works.
196TEST_P(AbstractEventLoopTest, BasicNoArg) {
197 auto loop1 = Make();
198 auto loop2 = MakePrimary();
199
200 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
201
202 bool happened = false;
203
204 loop2->OnRun([&]() {
205 happened = true;
206
207 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
208 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
209 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700210 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -0800211 });
212
213 aos::Fetcher<TestMessage> fetcher = loop2->MakeFetcher<TestMessage>("/test");
214 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
215 ASSERT_TRUE(fetcher.Fetch());
216 EXPECT_EQ(fetcher->value(), 200);
217 this->Exit();
218 });
219
220 EXPECT_FALSE(happened);
221 Run();
222 EXPECT_TRUE(happened);
223}
224
225// Tests that a watcher can be created with an std::function.
226TEST_P(AbstractEventLoopTest, BasicFunction) {
227 auto loop1 = Make();
228 auto loop2 = MakePrimary();
229
230 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
231
232 bool happened = false;
233
234 loop2->OnRun([&]() {
235 happened = true;
236
237 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
238 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
239 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700240 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -0800241 });
242
243 loop2->MakeWatcher("/test", std::function<void(const TestMessage &)>(
244 [&](const TestMessage &message) {
245 EXPECT_EQ(message.value(), 200);
246 this->Exit();
247 }));
248
249 EXPECT_FALSE(happened);
250 Run();
251 EXPECT_TRUE(happened);
252}
253
Brian Silverman0fc69932020-01-24 21:54:02 -0800254// Tests that watcher can receive messages from two senders.
255// Also tests that OnRun() works.
256TEST_P(AbstractEventLoopTest, BasicTwoSenders) {
257 auto loop1 = Make();
258 auto loop2 = MakePrimary();
259
260 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
261 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
262
263 bool happened = false;
264
265 loop2->OnRun([&]() {
266 happened = true;
267
268 {
269 aos::Sender<TestMessage>::Builder msg = sender1.MakeBuilder();
270 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
271 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700272 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman0fc69932020-01-24 21:54:02 -0800273 }
274 {
275 aos::Sender<TestMessage>::Builder msg = sender2.MakeBuilder();
276 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
277 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700278 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman0fc69932020-01-24 21:54:02 -0800279 }
280 });
281
282 int messages_received = 0;
283 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
284 EXPECT_EQ(message.value(), 200);
285 this->Exit();
286 ++messages_received;
287 });
288
289 EXPECT_FALSE(happened);
290 Run();
291 EXPECT_TRUE(happened);
292 EXPECT_EQ(messages_received, 2);
293}
294
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700295// Tests that a fetcher can fetch from a sender.
296// Also tests that OnRun() works.
297TEST_P(AbstractEventLoopTest, FetchWithoutRun) {
298 auto loop1 = Make();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800299 auto loop2 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -0700300 auto loop3 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800301
302 auto sender = loop1->MakeSender<TestMessage>("/test");
303
304 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
305
Austin Schuhbbce72d2019-05-26 15:11:46 -0700306 EXPECT_FALSE(fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -0800307 EXPECT_EQ(fetcher.get(), nullptr);
308
Austin Schuhad154822019-12-27 15:45:13 -0800309 EXPECT_EQ(fetcher.context().monotonic_event_time, monotonic_clock::min_time);
310 EXPECT_EQ(fetcher.context().monotonic_remote_time, monotonic_clock::min_time);
311 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
312 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -0700313 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
Austin Schuh39788ff2019-12-01 18:22:57 -0800314 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
315 EXPECT_EQ(fetcher.context().size, 0u);
316 EXPECT_EQ(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700317 EXPECT_EQ(fetcher.context().buffer_index, -1);
Austin Schuhbbce72d2019-05-26 15:11:46 -0700318
Alex Perrycb7da4b2019-08-28 19:35:56 -0700319 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
320 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
321 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700322 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700323
324 EXPECT_TRUE(fetcher.Fetch());
325 ASSERT_FALSE(fetcher.get() == nullptr);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700326 EXPECT_EQ(fetcher.get()->value(), 200);
Austin Schuh39788ff2019-12-01 18:22:57 -0800327
328 const chrono::milliseconds kEpsilon(100);
329
Austin Schuhad154822019-12-27 15:45:13 -0800330 const aos::monotonic_clock::time_point monotonic_now = loop2->monotonic_now();
331 const aos::realtime_clock::time_point realtime_now = loop2->realtime_now();
332 EXPECT_EQ(fetcher.context().monotonic_event_time,
333 fetcher.context().monotonic_remote_time);
334 EXPECT_EQ(fetcher.context().realtime_event_time,
335 fetcher.context().realtime_remote_time);
336
337 EXPECT_GE(fetcher.context().monotonic_event_time, monotonic_now - kEpsilon);
338 EXPECT_LE(fetcher.context().monotonic_event_time, monotonic_now + kEpsilon);
339 EXPECT_GE(fetcher.context().realtime_event_time, realtime_now - kEpsilon);
340 EXPECT_LE(fetcher.context().realtime_event_time, realtime_now + kEpsilon);
Austin Schuha9012be2021-07-21 15:19:11 -0700341 EXPECT_EQ(fetcher.context().source_boot_uuid, loop2->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -0800342 EXPECT_EQ(fetcher.context().queue_index, 0x0u);
343 EXPECT_EQ(fetcher.context().size, 20u);
344 EXPECT_NE(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700345 if (read_method() == ReadMethod::PIN) {
346 EXPECT_GE(fetcher.context().buffer_index, 0);
347 EXPECT_LT(fetcher.context().buffer_index,
348 loop2->NumberBuffers(fetcher.channel()));
349 } else {
350 EXPECT_EQ(fetcher.context().buffer_index, -1);
351 }
Parker Schuhe4a70d62017-12-27 20:10:20 -0800352}
353
Austin Schuh98ed26f2023-07-19 14:12:28 -0700354std::function<bool(const Context &)> MakeShouldFetch(
355 bool should_fetch, size_t *called_count = nullptr) {
356 return [should_fetch, called_count](const Context &) {
357 if (called_count != nullptr) {
358 (*called_count)++;
359 }
360 return should_fetch;
361 };
362}
363
364// Tests that a fetcher using FetchIf can fetch from a sender.
365TEST_P(AbstractEventLoopTest, FetchIfWithoutRun) {
366 auto loop1 = Make();
367 auto loop2 = Make();
368 auto loop3 = MakePrimary();
369
370 auto sender = loop1->MakeSender<TestMessage>("/test");
371
372 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
373
374 for (const bool should_fetch : {true, false}) {
375 EXPECT_FALSE(fetcher.FetchIf(MakeShouldFetch(should_fetch)));
376 EXPECT_EQ(fetcher.get(), nullptr);
377
378 EXPECT_EQ(fetcher.context().monotonic_event_time,
379 monotonic_clock::min_time);
380 EXPECT_EQ(fetcher.context().monotonic_remote_time,
381 monotonic_clock::min_time);
382 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
383 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
384 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
385 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
386 EXPECT_EQ(fetcher.context().size, 0u);
387 EXPECT_EQ(fetcher.context().data, nullptr);
388 EXPECT_EQ(fetcher.context().buffer_index, -1);
389 }
390
391 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
392 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
393 builder.add_value(200);
394 msg.CheckOk(msg.Send(builder.Finish()));
395
396 // Make sure failing to fetch won't affect anything.
397 EXPECT_FALSE(fetcher.FetchIf(MakeShouldFetch(false)));
398 EXPECT_EQ(fetcher.get(), nullptr);
399
400 EXPECT_EQ(fetcher.context().monotonic_event_time, monotonic_clock::min_time);
401 EXPECT_EQ(fetcher.context().monotonic_remote_time, monotonic_clock::min_time);
402 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
403 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
404 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
405 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
406 EXPECT_EQ(fetcher.context().size, 0u);
407 EXPECT_EQ(fetcher.context().data, nullptr);
408 EXPECT_EQ(fetcher.context().buffer_index, -1);
409
410 // And now confirm we succeed and everything gets set right.
411 EXPECT_TRUE(fetcher.FetchIf(MakeShouldFetch(true)));
412 ASSERT_FALSE(fetcher.get() == nullptr);
413 EXPECT_EQ(fetcher.get()->value(), 200);
414
415 const chrono::milliseconds kEpsilon(100);
416
417 const aos::monotonic_clock::time_point monotonic_now = loop2->monotonic_now();
418 const aos::realtime_clock::time_point realtime_now = loop2->realtime_now();
419 EXPECT_EQ(fetcher.context().monotonic_event_time,
420 fetcher.context().monotonic_remote_time);
421 EXPECT_EQ(fetcher.context().realtime_event_time,
422 fetcher.context().realtime_remote_time);
423
424 EXPECT_GE(fetcher.context().monotonic_event_time, monotonic_now - kEpsilon);
425 EXPECT_LE(fetcher.context().monotonic_event_time, monotonic_now + kEpsilon);
426 EXPECT_GE(fetcher.context().realtime_event_time, realtime_now - kEpsilon);
427 EXPECT_LE(fetcher.context().realtime_event_time, realtime_now + kEpsilon);
428 EXPECT_EQ(fetcher.context().source_boot_uuid, loop2->boot_uuid());
429 EXPECT_EQ(fetcher.context().queue_index, 0x0u);
430 EXPECT_EQ(fetcher.context().size, 20u);
431 EXPECT_NE(fetcher.context().data, nullptr);
432 if (read_method() == ReadMethod::PIN) {
433 EXPECT_GE(fetcher.context().buffer_index, 0);
434 EXPECT_LT(fetcher.context().buffer_index,
435 loop2->NumberBuffers(fetcher.channel()));
436 } else {
437 EXPECT_EQ(fetcher.context().buffer_index, -1);
438 }
439}
440
Austin Schuh3578a2e2019-05-25 18:17:59 -0700441// Tests that watcher will receive all messages sent if they are sent after
442// initialization and before running.
443TEST_P(AbstractEventLoopTest, DoubleSendAtStartup) {
444 auto loop1 = Make();
445 auto loop2 = MakePrimary();
446
447 auto sender = loop1->MakeSender<TestMessage>("/test");
448
449 ::std::vector<int> values;
450
451 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700452 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700453 if (values.size() == 2) {
Austin Schuh9fe68f72019-08-10 19:32:03 -0700454 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -0700455 }
456 });
457
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700458 // Before Run, should be ignored.
Austin Schuh3578a2e2019-05-25 18:17:59 -0700459 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700460 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
461 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
462 builder.add_value(199);
milind1f1dca32021-07-03 13:50:07 -0700463 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700464 }
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700465
466 loop2->OnRun([&]() {
Austin Schuh98ed26f2023-07-19 14:12:28 -0700467 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700468 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
469 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700470 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700471 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700472 }
473 });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700474
475 Run();
476
477 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
478}
479
480// Tests that watcher will not receive messages sent before the watcher is
481// created.
482TEST_P(AbstractEventLoopTest, DoubleSendAfterStartup) {
483 auto loop1 = Make();
484 auto loop2 = MakePrimary();
485
486 auto sender = loop1->MakeSender<TestMessage>("/test");
487
488 ::std::vector<int> values;
489
Austin Schuh98ed26f2023-07-19 14:12:28 -0700490 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700491 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
492 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700493 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700494 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700495 }
496
497 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700498 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700499 });
500
501 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700502 auto test_timer = loop2->AddTimer([this]() { this->Exit(); });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700503 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700504 test_timer->Schedule(loop2->monotonic_now(),
505 ::std::chrono::milliseconds(100));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700506 });
507
508 Run();
509 EXPECT_EQ(0, values.size());
510}
511
Austin Schuhbbce72d2019-05-26 15:11:46 -0700512// Tests that FetchNext gets all the messages sent after it is constructed.
513TEST_P(AbstractEventLoopTest, FetchNext) {
514 auto loop1 = Make();
515 auto loop2 = MakePrimary();
516
517 auto sender = loop1->MakeSender<TestMessage>("/test");
518 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
519
520 ::std::vector<int> values;
521
Austin Schuh98ed26f2023-07-19 14:12:28 -0700522 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700523 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
524 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700525 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700526 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700527 }
528
529 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700530 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700531 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700532 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700533 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700534 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700535 });
536
537 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700538 test_timer->Schedule(loop2->monotonic_now(),
539 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700540 });
541
542 Run();
543 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
544}
545
546// Tests that FetchNext gets no messages sent before it is constructed.
547TEST_P(AbstractEventLoopTest, FetchNextAfterSend) {
548 auto loop1 = Make();
549 auto loop2 = MakePrimary();
550
551 auto sender = loop1->MakeSender<TestMessage>("/test");
552
553 ::std::vector<int> values;
554
Austin Schuh98ed26f2023-07-19 14:12:28 -0700555 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700556 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
557 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700558 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700559 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700560 }
561
562 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
563
564 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700565 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700566 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700567 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700568 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700569 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700570 });
571
572 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700573 test_timer->Schedule(loop2->monotonic_now(),
574 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700575 });
576
577 Run();
578 EXPECT_THAT(0, values.size());
579}
580
Austin Schuh98ed26f2023-07-19 14:12:28 -0700581// Tests that FetchNextIf gets no messages sent before it is constructed.
582TEST_P(AbstractEventLoopTest, FetchNextIfAfterSend) {
583 auto loop1 = Make();
584 auto loop2 = MakePrimary();
585
586 auto sender = loop1->MakeSender<TestMessage>("/test");
587
588 ::std::vector<int> values;
589
590 for (int i = 200; i < 202; ++i) {
591 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
592 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
593 builder.add_value(i);
594 msg.CheckOk(msg.Send(builder.Finish()));
595 }
596
597 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
598
599 // Add a timer to actually quit.
600 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
601 while (fetcher.FetchNextIf(MakeShouldFetch(true))) {
602 values.push_back(fetcher.get()->value());
603 }
604 this->Exit();
605 });
606
607 loop2->OnRun([&test_timer, &loop2]() {
608 test_timer->Schedule(loop2->monotonic_now(),
609 ::std::chrono::milliseconds(100));
610 });
611
612 Run();
613 EXPECT_EQ(0, values.size());
614}
615
Austin Schuhbbce72d2019-05-26 15:11:46 -0700616// Tests that Fetch returns the last message created before the loop was
617// started.
618TEST_P(AbstractEventLoopTest, FetchDataFromBeforeCreation) {
619 auto loop1 = Make();
620 auto loop2 = MakePrimary();
621
622 auto sender = loop1->MakeSender<TestMessage>("/test");
623
624 ::std::vector<int> values;
625
Austin Schuh98ed26f2023-07-19 14:12:28 -0700626 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700627 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
628 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700629 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700630 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700631 }
632
633 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
634
635 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700636 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700637 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700638 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700639 }
640 // Do it again to make sure we don't double fetch.
641 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700642 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700643 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700644 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700645 });
646
647 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700648 test_timer->Schedule(loop2->monotonic_now(),
649 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700650 });
651
652 Run();
653 EXPECT_THAT(values, ::testing::ElementsAreArray({201}));
654}
655
Austin Schuh98ed26f2023-07-19 14:12:28 -0700656// Tests that FetchIf returns the last message created before the loop was
657// started.
658TEST_P(AbstractEventLoopTest, FetchIfDataFromBeforeCreation) {
659 auto loop1 = Make();
660 auto loop2 = MakePrimary();
661
662 auto sender = loop1->MakeSender<TestMessage>("/test");
663
664 ::std::vector<int> values;
665
666 for (int i = 200; i < 202; ++i) {
667 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
668 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
669 builder.add_value(i);
670 msg.CheckOk(msg.Send(builder.Finish()));
671 }
672
673 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
674
675 // Add a timer to actually quit.
676 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
677 if (fetcher.FetchIf(MakeShouldFetch(true))) {
678 values.push_back(fetcher.get()->value());
679 }
680
681 if (fetcher.FetchIf(MakeShouldFetch(false))) {
682 values.push_back(fetcher.get()->value());
683 }
684 // Do it again to make sure we don't double fetch.
685 if (fetcher.FetchIf(MakeShouldFetch(true))) {
686 values.push_back(fetcher.get()->value());
687 }
688 this->Exit();
689 });
690
691 loop2->OnRun([&test_timer, &loop2]() {
692 test_timer->Schedule(loop2->monotonic_now(),
693 ::std::chrono::milliseconds(100));
694 });
695
696 Run();
697 EXPECT_THAT(values, ::testing::ElementsAreArray({201}));
698}
699
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700700// Tests that timer handler is enabled after setup (even if it is in the past)
701// and is disabled after running
702TEST_P(AbstractEventLoopTest, CheckTimerDisabled) {
703 auto loop = MakePrimary("primary");
704
705 auto timer = loop->AddTimer([this]() {
706 LOG(INFO) << "timer called";
707 Exit();
708 });
709
710 loop->OnRun([&loop, timer]() {
711 EXPECT_TRUE(timer->IsDisabled());
Philipp Schradera6712522023-07-05 20:25:11 -0700712 timer->Schedule(loop->monotonic_now() + chrono::milliseconds(100));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700713 EXPECT_FALSE(timer->IsDisabled());
714 });
715
716 Run();
717 EXPECT_TRUE(timer->IsDisabled());
718}
719
720// Tests that timer handler is enabled after setup (even if it is in the past)
721// and is disabled after running
722TEST_P(AbstractEventLoopTest, CheckTimerRunInPastDisabled) {
723 auto loop = MakePrimary("primary");
724
725 auto timer2 = loop->AddTimer([this]() {
726 LOG(INFO) << "timer called";
727 Exit();
728 });
729
730 auto timer = loop->AddTimer([&loop, timer2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700731 timer2->Schedule(loop->monotonic_now() - chrono::nanoseconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700732 });
733
734 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700735 timer->Schedule(loop->monotonic_now() + chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700736 EXPECT_FALSE(timer->IsDisabled());
737 });
738
739 Run();
740 EXPECT_TRUE(timer2->IsDisabled());
741}
742
743// Tests that timer handler is not disabled even after calling Exit on the event
744// loop within the timer
745TEST_P(AbstractEventLoopTest, CheckTimerRepeatOnCountDisabled) {
746 auto loop = MakePrimary("primary");
747 int counter = 0;
748
749 auto timer = loop->AddTimer([&counter, this]() {
750 LOG(INFO) << "timer called";
751 counter++;
752 if (counter >= 5) {
753 Exit();
754 }
755 });
756
757 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700758 timer->Schedule(loop->monotonic_now() + chrono::seconds(1),
759 chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700760 EXPECT_FALSE(timer->IsDisabled());
761 });
762 Run();
763
764 // Sanity check
765 EXPECT_EQ(counter, 5);
766
767 // if you run the loop again, the timer will start running again
768 EXPECT_FALSE(timer->IsDisabled());
769
770 counter = 0;
771 Run();
772 timer->Disable();
773
774 EXPECT_TRUE(timer->IsDisabled());
775}
776
777// Tests that timer handler is not disabled even after calling Exit on the event
778// loop using an external timer
779TEST_P(AbstractEventLoopTest, CheckTimerRepeatTillEndTimerDisabled) {
780 auto loop = MakePrimary("primary");
781
782 auto timer = loop->AddTimer([]() { LOG(INFO) << "timer called"; });
783
784 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700785 timer->Schedule(loop->monotonic_now() + chrono::seconds(1),
786 chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700787 EXPECT_FALSE(timer->IsDisabled());
788 });
789
790 EndEventLoop(loop.get(), chrono::seconds(5));
791 Run();
792 EXPECT_FALSE(timer->IsDisabled());
793
794 timer->Disable();
795 EXPECT_TRUE(timer->IsDisabled());
796}
797
Austin Schuhbbce72d2019-05-26 15:11:46 -0700798// Tests that Fetch and FetchNext interleave as expected.
799TEST_P(AbstractEventLoopTest, FetchAndFetchNextTogether) {
800 auto loop1 = Make();
801 auto loop2 = MakePrimary();
802
803 auto sender = loop1->MakeSender<TestMessage>("/test");
804
805 ::std::vector<int> values;
806
Austin Schuh98ed26f2023-07-19 14:12:28 -0700807 for (int i = 200; i < 202; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700808 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
809 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700810 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700811 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700812 }
813
814 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
815
816 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700817 auto test_timer = loop2->AddTimer([&fetcher, &values, &sender, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700818 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700819 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700820 }
821
Austin Schuh98ed26f2023-07-19 14:12:28 -0700822 for (int i = 202; i < 205; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700823 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
824 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
Austin Schuh98ed26f2023-07-19 14:12:28 -0700825 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700826 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700827 }
828
829 if (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700830 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700831 }
832
833 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700834 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700835 }
836
Austin Schuh9fe68f72019-08-10 19:32:03 -0700837 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700838 });
839
840 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700841 test_timer->Schedule(loop2->monotonic_now(),
842 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700843 });
844
845 Run();
846 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
847}
848
Austin Schuh98ed26f2023-07-19 14:12:28 -0700849// Tests that Fetch{If,} and FetchNext{If,} interleave as expected.
850TEST_P(AbstractEventLoopTest, FetchAndFetchNextIfTogether) {
851 auto loop1 = Make();
852 auto loop2 = MakePrimary();
853
854 auto sender = loop1->MakeSender<TestMessage>("/test");
855
856 ::std::vector<int> values;
857
858 for (int i = 200; i < 202; ++i) {
859 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
860 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
861 builder.add_value(i);
862 msg.CheckOk(msg.Send(builder.Finish()));
863 }
864
865 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
866
867 // Add a timer to actually quit.
868 auto test_timer = loop2->AddTimer([&fetcher, &values, &sender, this]() {
869 if (fetcher.Fetch()) {
870 values.push_back(fetcher.get()->value());
871 }
872
873 for (int i = 202; i < 205; ++i) {
874 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
875 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
876 builder.add_value(i);
877 msg.CheckOk(msg.Send(builder.Finish()));
878 }
879
880 EXPECT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false)));
881
882 if (fetcher.FetchNext()) {
883 values.push_back(fetcher.get()->value());
884 }
885
886 EXPECT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false)));
887 EXPECT_FALSE(fetcher.FetchIf(MakeShouldFetch(false)));
888
889 if (fetcher.FetchIf(MakeShouldFetch(true))) {
890 values.push_back(fetcher.get()->value());
891 }
892
893 this->Exit();
894 });
895
896 loop2->OnRun([&test_timer, &loop2]() {
897 test_timer->Schedule(loop2->monotonic_now(),
898 ::std::chrono::milliseconds(100));
899 });
900
901 Run();
902 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
903}
904
Austin Schuh3115a202019-05-27 21:02:14 -0700905// Tests that FetchNext behaves correctly when we get two messages in the queue
906// but don't consume the first until after the second has been sent.
907TEST_P(AbstractEventLoopTest, FetchNextTest) {
Austin Schuh3115a202019-05-27 21:02:14 -0700908 auto send_loop = Make();
909 auto fetch_loop = Make();
910 auto sender = send_loop->MakeSender<TestMessage>("/test");
911 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
912
913 {
Tyler Chatow67ddb032020-01-12 14:30:04 -0800914 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
915 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
916 builder.add_value(100);
milind1f1dca32021-07-03 13:50:07 -0700917 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700918 }
919
920 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700921 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
922 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
923 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700924 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700925 }
926
927 ASSERT_TRUE(fetcher.FetchNext());
928 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700929 EXPECT_EQ(100, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700930
931 ASSERT_TRUE(fetcher.FetchNext());
932 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700933 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700934
935 // When we run off the end of the queue, expect to still have the old message:
936 ASSERT_FALSE(fetcher.FetchNext());
937 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700938 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700939}
940
Austin Schuh98ed26f2023-07-19 14:12:28 -0700941// Tests that FetchNext behaves correctly when we get two messages in the queue
942// but don't consume the first until after the second has been sent.
943TEST_P(AbstractEventLoopTest, FetchNextIfTest) {
944 auto send_loop = Make();
945 auto fetch_loop = Make();
946 auto sender = send_loop->MakeSender<TestMessage>("/test");
947 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
948
949 {
950 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
951 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
952 builder.add_value(100);
953 msg.CheckOk(msg.Send(builder.Finish()));
954 }
955
956 {
957 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
958 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
959 builder.add_value(200);
960 msg.CheckOk(msg.Send(builder.Finish()));
961 }
962
963 size_t called_count = 0;
964 ASSERT_TRUE(fetcher.FetchNextIf(MakeShouldFetch(true, &called_count)));
965 ASSERT_NE(nullptr, fetcher.get());
966 EXPECT_EQ(100, fetcher.get()->value());
967 EXPECT_EQ(called_count, 1u);
968
969 ASSERT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false, &called_count)));
970 EXPECT_EQ(called_count, 2u);
971
972 ASSERT_TRUE(fetcher.FetchNextIf(MakeShouldFetch(true, &called_count)));
973 ASSERT_NE(nullptr, fetcher.get());
974 EXPECT_EQ(200, fetcher.get()->value());
975 EXPECT_EQ(called_count, 3u);
976
977 // When we run off the end of the queue, expect to still have the old message:
978 ASSERT_FALSE(fetcher.FetchNextIf(MakeShouldFetch(false, &called_count)));
979 EXPECT_EQ(called_count, 3u);
980 ASSERT_NE(nullptr, fetcher.get());
981 EXPECT_EQ(200, fetcher.get()->value());
982}
983
Brian Silverman77162972020-08-12 19:52:40 -0700984// Verify that a fetcher still holds its data, even after falling behind.
985TEST_P(AbstractEventLoopTest, FetcherBehindData) {
986 auto send_loop = Make();
987 auto fetch_loop = Make();
988 auto sender = send_loop->MakeSender<TestMessage>("/test");
989 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
990 {
991 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
992 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
993 builder.add_value(1);
milind1f1dca32021-07-03 13:50:07 -0700994 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -0700995 }
996 ASSERT_TRUE(fetcher.Fetch());
997 EXPECT_EQ(1, fetcher.get()->value());
998 for (int i = 0; i < 300; ++i) {
999 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1000 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1001 builder.add_value(i + 2);
milind1f1dca32021-07-03 13:50:07 -07001002 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -07001003 }
1004 EXPECT_EQ(1, fetcher.get()->value());
1005}
1006
1007// Try a bunch of orderings of operations with fetchers and senders. Verify that
1008// all the fetchers have the correct data at each step.
1009TEST_P(AbstractEventLoopTest, FetcherPermutations) {
1010 for (int max_save = 0; max_save < 5; ++max_save) {
1011 SCOPED_TRACE("max_save=" + std::to_string(max_save));
1012
1013 auto send_loop = Make();
1014 auto fetch_loop = Make();
1015 auto sender = send_loop->MakeSender<TestMessage>("/test");
1016 const auto send_message = [&sender](int i) {
1017 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1018 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1019 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -07001020 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -07001021 };
1022 std::vector<Fetcher<TestMessage>> fetchers;
1023 for (int i = 0; i < 10; ++i) {
1024 fetchers.emplace_back(fetch_loop->MakeFetcher<TestMessage>("/test"));
1025 }
1026 send_message(1);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001027 const auto verify_buffers = [&]() {
1028 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>>
1029 fetchers_copy;
1030 for (const auto &fetcher : fetchers) {
1031 fetchers_copy.emplace_back(fetcher);
1032 }
1033 std::vector<std::reference_wrapper<const Sender<TestMessage>>>
1034 senders_copy;
1035 senders_copy.emplace_back(sender);
1036 VerifyBuffers(send_loop->NumberBuffers(sender.channel()), fetchers_copy,
1037 senders_copy);
1038 };
Brian Silverman77162972020-08-12 19:52:40 -07001039 for (auto &fetcher : fetchers) {
1040 ASSERT_TRUE(fetcher.Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -07001041 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001042 EXPECT_EQ(1, fetcher.get()->value());
1043 }
1044
1045 for (int save = 1; save <= max_save; ++save) {
1046 SCOPED_TRACE("save=" + std::to_string(save));
1047 send_message(100 + save);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001048 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001049 for (size_t i = 0; i < fetchers.size() - save; ++i) {
1050 SCOPED_TRACE("fetcher=" + std::to_string(i));
1051 ASSERT_TRUE(fetchers[i].Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -07001052 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001053 EXPECT_EQ(100 + save, fetchers[i].get()->value());
1054 }
1055 for (size_t i = fetchers.size() - save; i < fetchers.size() - 1; ++i) {
1056 SCOPED_TRACE("fetcher=" + std::to_string(i));
1057 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
1058 }
1059 EXPECT_EQ(1, fetchers.back().get()->value());
1060 }
1061
1062 for (int i = 0; i < 300; ++i) {
1063 send_message(200 + i);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001064 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -07001065 }
1066
1067 for (size_t i = 0; i < fetchers.size() - max_save; ++i) {
1068 SCOPED_TRACE("fetcher=" + std::to_string(i));
1069 if (max_save > 0) {
1070 EXPECT_EQ(100 + max_save, fetchers[i].get()->value());
1071 } else {
1072 EXPECT_EQ(1, fetchers[i].get()->value());
1073 }
1074 }
1075 for (size_t i = fetchers.size() - max_save; i < fetchers.size() - 1; ++i) {
1076 SCOPED_TRACE("fetcher=" + std::to_string(i));
1077 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
1078 }
1079 EXPECT_EQ(1, fetchers.back().get()->value());
1080 }
1081}
1082
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001083// Verify that making a fetcher and watcher for "/test" succeeds.
1084TEST_P(AbstractEventLoopTest, FetcherAndWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -08001085 auto loop = Make();
1086 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001087 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Parker Schuhe4a70d62017-12-27 20:10:20 -08001088}
1089
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001090// Verify that making 2 fetchers for "/test" succeeds.
Parker Schuhe4a70d62017-12-27 20:10:20 -08001091TEST_P(AbstractEventLoopTest, TwoFetcher) {
1092 auto loop = Make();
1093 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001094 auto fetcher2 = loop->MakeFetcher<TestMessage>("/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -08001095}
1096
Alex Perrycb7da4b2019-08-28 19:35:56 -07001097// Verify that registering a watcher for an invalid channel name dies.
1098TEST_P(AbstractEventLoopDeathTest, InvalidChannelName) {
1099 auto loop = Make();
1100 EXPECT_DEATH(
1101 { loop->MakeWatcher("/test/invalid", [&](const TestMessage &) {}); },
1102 "/test/invalid");
Brian Silverman454bc112020-03-05 14:21:25 -08001103 EXPECT_DEATH(
1104 { loop->MakeNoArgWatcher<TestMessage>("/test/invalid", [&]() {}); },
1105 "/test/invalid");
Alex Perrycb7da4b2019-08-28 19:35:56 -07001106}
1107
James Kuszmaul8866e642022-06-10 16:00:36 -07001108// Verify that setting up a timer before monotonic_clock::epoch() fails.
James Kuszmaul86e86c32022-07-21 17:39:47 -07001109TEST_P(AbstractEventLoopDeathTest, NegativeTimeTimer) {
James Kuszmaul8866e642022-06-10 16:00:36 -07001110 auto loop = Make();
1111 TimerHandler *time = loop->AddTimer([]() {});
Philipp Schradera6712522023-07-05 20:25:11 -07001112 EXPECT_DEATH(
1113 time->Schedule(monotonic_clock::epoch() - std::chrono::seconds(1)),
1114 "-1.000");
James Kuszmaul8866e642022-06-10 16:00:36 -07001115}
1116
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001117// Verify that registering a watcher twice for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001118TEST_P(AbstractEventLoopDeathTest, TwoWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -08001119 auto loop = Make();
1120 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001121 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
1122 "/test");
Brian Silverman454bc112020-03-05 14:21:25 -08001123 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
1124}
1125
1126// Verify that registering a no-arg watcher twice for "/test" fails.
1127TEST_P(AbstractEventLoopDeathTest, TwoNoArgWatcher) {
1128 auto loop = Make();
1129 loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {});
1130 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
1131 "/test");
1132 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001133}
1134
Austin Schuh3115a202019-05-27 21:02:14 -07001135// Verify that SetRuntimeRealtimePriority fails while running.
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001136TEST_P(AbstractEventLoopDeathTest, SetRuntimeRealtimePriority) {
Austin Schuh3115a202019-05-27 21:02:14 -07001137 auto loop = MakePrimary();
Austin Schuh65493d62022-08-17 15:10:37 -07001138 EXPECT_EQ(0, loop->runtime_realtime_priority());
Austin Schuh3115a202019-05-27 21:02:14 -07001139 // Confirm that runtime priority calls work when not realtime.
1140 loop->SetRuntimeRealtimePriority(5);
Austin Schuh65493d62022-08-17 15:10:37 -07001141 EXPECT_EQ(5, loop->runtime_realtime_priority());
Austin Schuh3115a202019-05-27 21:02:14 -07001142
1143 loop->OnRun([&]() { loop->SetRuntimeRealtimePriority(5); });
1144
1145 EXPECT_DEATH(Run(), "realtime");
1146}
1147
Austin Schuh65493d62022-08-17 15:10:37 -07001148namespace {
1149
1150bool CpuSetEqual(const cpu_set_t &a, const cpu_set_t &b) {
1151 return CPU_EQUAL(&a, &b);
1152}
1153
1154} // namespace
1155
Brian Silverman6a54ff32020-04-28 16:41:39 -07001156// Verify that SetRuntimeAffinity fails while running.
1157TEST_P(AbstractEventLoopDeathTest, SetRuntimeAffinity) {
Austin Schuhde973292021-10-12 18:09:49 -07001158 const cpu_set_t available = GetCurrentThreadAffinity();
1159 int first_cpu = -1;
1160 for (int i = 0; i < CPU_SETSIZE; ++i) {
1161 if (CPU_ISSET(i, &available)) {
1162 first_cpu = i;
1163 break;
1164 continue;
1165 }
1166 }
1167 CHECK_NE(first_cpu, -1) << ": Default affinity has no CPUs?";
1168
Brian Silverman6a54ff32020-04-28 16:41:39 -07001169 auto loop = MakePrimary();
Austin Schuh65493d62022-08-17 15:10:37 -07001170 EXPECT_TRUE(
1171 CpuSetEqual(EventLoop::DefaultAffinity(), loop->runtime_affinity()));
1172 const cpu_set_t new_affinity = MakeCpusetFromCpus({first_cpu});
Brian Silverman6a54ff32020-04-28 16:41:39 -07001173 // Confirm that runtime priority calls work when not running.
Austin Schuh65493d62022-08-17 15:10:37 -07001174 loop->SetRuntimeAffinity(new_affinity);
1175 EXPECT_TRUE(CpuSetEqual(new_affinity, loop->runtime_affinity()));
Brian Silverman6a54ff32020-04-28 16:41:39 -07001176
Austin Schuhde973292021-10-12 18:09:49 -07001177 loop->OnRun(
1178 [&]() { loop->SetRuntimeAffinity(MakeCpusetFromCpus({first_cpu})); });
Brian Silverman6a54ff32020-04-28 16:41:39 -07001179
1180 EXPECT_DEATH(Run(), "Cannot set affinity while running");
1181}
1182
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001183// Verify that registering a watcher and a sender for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001184TEST_P(AbstractEventLoopDeathTest, WatcherAndSender) {
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001185 auto loop = Make();
1186 auto sender = loop->MakeSender<TestMessage>("/test");
1187 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
1188 "/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -08001189}
1190
Austin Schuhe516ab02020-05-06 21:37:04 -07001191// Verify that creating too many senders fails.
1192TEST_P(AbstractEventLoopDeathTest, TooManySenders) {
1193 auto loop = Make();
1194 std::vector<aos::Sender<TestMessage>> senders;
1195 for (int i = 0; i < 10; ++i) {
1196 senders.emplace_back(loop->MakeSender<TestMessage>("/test"));
1197 }
1198 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); },
1199 "Failed to create sender on \\{ \"name\": \"/test\", \"type\": "
Brian Silverman77162972020-08-12 19:52:40 -07001200 "\"aos.TestMessage\"[^}]*\\ }, too many senders.");
1201}
1202
1203// Verify that creating too many fetchers fails.
1204TEST_P(AbstractEventLoopDeathTest, TooManyFetchers) {
1205 if (read_method() != ReadMethod::PIN) {
1206 // Other read methods don't limit the number of readers, so just skip this.
1207 return;
1208 }
1209
1210 auto loop = Make();
1211 std::vector<aos::Fetcher<TestMessage>> fetchers;
1212 for (int i = 0; i < 10; ++i) {
1213 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1214 }
1215 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1216 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1217 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
1218}
1219
1220// Verify that creating too many fetchers, split between two event loops, fails.
1221TEST_P(AbstractEventLoopDeathTest, TooManyFetchersTwoLoops) {
1222 if (read_method() != ReadMethod::PIN) {
1223 // Other read methods don't limit the number of readers, so just skip this.
1224 return;
1225 }
1226
1227 auto loop = Make();
1228 auto loop2 = Make();
1229 std::vector<aos::Fetcher<TestMessage>> fetchers;
1230 for (int i = 0; i < 5; ++i) {
1231 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1232 fetchers.emplace_back(loop2->MakeFetcher<TestMessage>("/test"));
1233 }
1234 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1235 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1236 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
1237}
1238
1239// Verify that creating too many watchers fails.
1240TEST_P(AbstractEventLoopDeathTest, TooManyWatchers) {
1241 if (read_method() != ReadMethod::PIN) {
1242 // Other read methods don't limit the number of readers, so just skip this.
1243 return;
1244 }
1245
1246 std::vector<std::unique_ptr<EventLoop>> loops;
1247 for (int i = 0; i < 10; ++i) {
1248 loops.emplace_back(Make());
1249 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
1250 }
1251 EXPECT_DEATH({ Make()->MakeWatcher("/test", [](const TestMessage &) {}); },
1252 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1253 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
1254}
1255
1256// Verify that creating too many watchers and fetchers combined fails.
1257TEST_P(AbstractEventLoopDeathTest, TooManyWatchersAndFetchers) {
1258 if (read_method() != ReadMethod::PIN) {
1259 // Other read methods don't limit the number of readers, so just skip this.
1260 return;
1261 }
1262
1263 auto loop = Make();
1264 std::vector<aos::Fetcher<TestMessage>> fetchers;
1265 std::vector<std::unique_ptr<EventLoop>> loops;
1266 for (int i = 0; i < 5; ++i) {
1267 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1268 loops.emplace_back(Make());
1269 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
1270 }
1271 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1272 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1273 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
Austin Schuhe516ab02020-05-06 21:37:04 -07001274}
1275
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001276// Verify that we can't create a sender inside OnRun.
1277TEST_P(AbstractEventLoopDeathTest, SenderInOnRun) {
1278 auto loop1 = MakePrimary();
1279
1280 loop1->OnRun(
1281 [&]() { auto sender = loop1->MakeSender<TestMessage>("/test2"); });
1282
1283 EXPECT_DEATH(Run(), "running");
1284}
1285
1286// Verify that we can't create a watcher inside OnRun.
1287TEST_P(AbstractEventLoopDeathTest, WatcherInOnRun) {
1288 auto loop1 = MakePrimary();
1289
1290 loop1->OnRun(
1291 [&]() { loop1->MakeWatcher("/test", [&](const TestMessage &) {}); });
1292
1293 EXPECT_DEATH(Run(), "running");
1294}
1295
Brian Silverman454bc112020-03-05 14:21:25 -08001296// Verify that we can't create a no-arg watcher inside OnRun.
1297TEST_P(AbstractEventLoopDeathTest, NoArgWatcherInOnRun) {
1298 auto loop1 = MakePrimary();
1299
1300 loop1->OnRun(
1301 [&]() { loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {}); });
1302
1303 EXPECT_DEATH(Run(), "running");
1304}
1305
Parker Schuhe4a70d62017-12-27 20:10:20 -08001306// Verify that Quit() works when there are multiple watchers.
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001307TEST_P(AbstractEventLoopTest, MultipleWatcherQuit) {
1308 auto loop1 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -07001309 auto loop2 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -08001310
Austin Schuh3578a2e2019-05-25 18:17:59 -07001311 loop2->MakeWatcher("/test1", [&](const TestMessage &) {});
1312 loop2->MakeWatcher("/test2", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001313 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -07001314 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -07001315 });
1316
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001317 auto sender = loop1->MakeSender<TestMessage>("/test2");
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001318
1319 loop2->OnRun([&]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001320 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1321 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1322 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001323 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001324 });
Parker Schuhe4a70d62017-12-27 20:10:20 -08001325
Austin Schuh44019f92019-05-19 19:58:27 -07001326 Run();
Parker Schuhe4a70d62017-12-27 20:10:20 -08001327}
1328
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001329// Verify that AOS_LOG has the right name.
1330TEST_P(AbstractEventLoopTest, AOSLog) {
1331 auto loop2 = MakePrimary("loop1");
1332 auto loop1 = Make("loop0");
1333
1334 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1335
1336 EXPECT_FALSE(fetcher.Fetch());
1337
1338 loop2->OnRun([&]() {
1339 AOS_LOG(INFO, "Testing123");
1340 this->Exit();
1341 });
1342
1343 Run();
1344 EXPECT_TRUE(fetcher.Fetch());
1345 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1346}
1347
1348// Verify that AOS_LOG has the right name in a watcher.
1349TEST_P(AbstractEventLoopTest, AOSLogWatcher) {
1350 auto loop2 = MakePrimary("loop1");
1351 auto loop1 = Make("loop0");
1352
1353 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1354
1355 EXPECT_FALSE(fetcher.Fetch());
1356
1357 auto sender = loop1->MakeSender<TestMessage>("/test2");
1358
1359 loop2->MakeWatcher("/test2", [&](const TestMessage & /*message*/) {
1360 AOS_LOG(INFO, "Testing123");
1361 this->Exit();
1362 });
1363
1364 loop2->OnRun([&]() {
1365 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1366 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1367 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001368 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001369 });
1370
1371 Run();
1372 EXPECT_TRUE(fetcher.Fetch());
1373 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1374}
1375
1376// Verify that AOS_LOG has the right name in a timer.
1377TEST_P(AbstractEventLoopTest, AOSLogTimer) {
1378 auto loop2 = MakePrimary("loop1");
1379 auto loop1 = Make("loop0");
1380
1381 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1382
1383 EXPECT_FALSE(fetcher.Fetch());
1384
1385 auto test_timer = loop2->AddTimer([&]() {
1386 AOS_LOG(INFO, "Testing123");
1387 this->Exit();
1388 });
1389
Philipp Schradera6712522023-07-05 20:25:11 -07001390 loop2->OnRun([&]() { test_timer->Schedule(loop2->monotonic_now()); });
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001391
1392 Run();
1393 EXPECT_TRUE(fetcher.Fetch());
1394 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1395}
1396
Neil Balch229001a2018-01-07 18:22:52 -08001397// Verify that timer intervals and duration function properly.
1398TEST_P(AbstractEventLoopTest, TimerIntervalAndDuration) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001399 // Force a slower rate so we are guaranteed to have reports for our timer.
Austin Schuh39788ff2019-12-01 18:22:57 -08001400 FLAGS_timing_report_ms = 2000;
1401
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001402 const int kCount = 5;
Neil Balch229001a2018-01-07 18:22:52 -08001403
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001404 auto loop = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001405 auto loop2 = Make();
1406
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001407 ::std::vector<::aos::monotonic_clock::time_point> times;
1408 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
1409
Austin Schuh39788ff2019-12-01 18:22:57 -08001410 Fetcher<timing::Report> report_fetcher =
1411 loop2->MakeFetcher<timing::Report>("/aos");
1412 EXPECT_FALSE(report_fetcher.Fetch());
1413
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001414 auto test_timer = loop->AddTimer([this, &times, &expected_times, &loop]() {
1415 times.push_back(loop->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001416 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
1417 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
1418 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001419 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -08001420 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
1421 EXPECT_EQ(loop->context().size, 0u);
1422 EXPECT_EQ(loop->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001423 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001424
Austin Schuhad154822019-12-27 15:45:13 -08001425 expected_times.push_back(loop->context().monotonic_event_time);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001426 if (times.size() == kCount) {
1427 this->Exit();
1428 }
Neil Balch229001a2018-01-07 18:22:52 -08001429 });
Austin Schuh39788ff2019-12-01 18:22:57 -08001430 test_timer->set_name("Test loop");
Neil Balch229001a2018-01-07 18:22:52 -08001431
Austin Schuh39788ff2019-12-01 18:22:57 -08001432 const monotonic_clock::time_point start_time = loop->monotonic_now();
Austin Schuh52d325c2019-06-23 18:59:06 -07001433 // TODO(austin): This should be an error... Should be done in OnRun only.
Philipp Schradera6712522023-07-05 20:25:11 -07001434 test_timer->Schedule(start_time + chrono::seconds(1), chrono::seconds(1));
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001435
Austin Schuh44019f92019-05-19 19:58:27 -07001436 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001437
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001438 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001439 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
1440 ASSERT_EQ(times.size(), expected_times.size());
1441 ASSERT_EQ((times.size() % 2), 1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001442
1443 // Grab the middle sample.
1444 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
1445
1446 // Add up all the delays of all the times.
1447 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1448 for (const ::aos::monotonic_clock::time_point time : times) {
1449 sum += time - average_time;
1450 }
1451
1452 // Average and add to the middle to find the average time.
1453 sum /= times.size();
1454 average_time += sum;
1455
1456 // Compute the offset from the average and the expected average. It
1457 // should be pretty close to 0.
1458 const ::aos::monotonic_clock::duration remainder =
1459 average_time - start_time - chrono::seconds(times.size() / 2 + 1);
1460
1461 const chrono::milliseconds kEpsilon(100);
1462 EXPECT_LT(remainder, +kEpsilon);
1463 EXPECT_GT(remainder, -kEpsilon);
1464
1465 // Make sure that the average duration is close to 1 second.
1466 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1467 times.front())
1468 .count() /
1469 static_cast<double>(times.size() - 1),
1470 1.0, 0.1);
1471
1472 // Confirm that the ideal wakeup times increment correctly.
1473 for (size_t i = 1; i < expected_times.size(); ++i) {
1474 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1475 }
1476
1477 for (size_t i = 0; i < expected_times.size(); ++i) {
1478 EXPECT_EQ((expected_times[i] - start_time) % chrono::seconds(1),
1479 chrono::seconds(0));
1480 }
1481
1482 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1483 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001484
Austin Schuh6bae8252021-02-07 22:01:49 -08001485 if (do_timing_reports() == DoTimingReports::kYes) {
1486 // And, since we are here, check that the timing report makes sense.
1487 // Start by looking for our event loop's timing.
1488 FlatbufferDetachedBuffer<timing::Report> report =
1489 FlatbufferDetachedBuffer<timing::Report>::Empty();
1490 while (report_fetcher.FetchNext()) {
1491 if (report_fetcher->name()->string_view() == "primary") {
1492 report = CopyFlatBuffer(report_fetcher.get());
1493 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001494 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001495
1496 // Confirm that we have the right number of reports, and the contents are
1497 // sane.
1498 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
1499
1500 EXPECT_EQ(report.message().name()->string_view(), "primary");
1501
1502 ASSERT_NE(report.message().senders(), nullptr);
1503 EXPECT_EQ(report.message().senders()->size(), 2);
1504
1505 ASSERT_NE(report.message().timers(), nullptr);
1506 EXPECT_EQ(report.message().timers()->size(), 2);
1507
1508 EXPECT_EQ(report.message().timers()->Get(0)->name()->string_view(),
1509 "Test loop");
1510 EXPECT_GE(report.message().timers()->Get(0)->count(), 1);
1511
1512 EXPECT_EQ(report.message().timers()->Get(1)->name()->string_view(),
1513 "timing_reports");
1514 EXPECT_EQ(report.message().timers()->Get(1)->count(), 1);
1515
1516 // Make sure there is a single phased loop report with our report in it.
1517 ASSERT_EQ(report.message().phased_loops(), nullptr);
1518 } else {
1519 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001520 }
Neil Balch229001a2018-01-07 18:22:52 -08001521}
1522
James Kuszmaul762e8692023-07-31 14:57:53 -07001523// Test that setting a default version string results in it getting populated
1524// correctly.
1525TEST_P(AbstractEventLoopTest, DefaultVersionStringInTimingReport) {
1526 gflags::FlagSaver flag_saver;
1527 FLAGS_timing_report_ms = 1000;
1528
1529 EventLoop::SetDefaultVersionString("default_version_string");
1530
1531 auto loop = MakePrimary();
1532
1533 Fetcher<timing::Report> report_fetcher =
1534 loop->MakeFetcher<timing::Report>("/aos");
1535
1536 TimerHandler *exit_timer = loop->AddTimer([this]() { Exit(); });
1537 loop->OnRun([exit_timer, &loop, &report_fetcher]() {
1538 report_fetcher.Fetch();
1539 exit_timer->Schedule(loop->monotonic_now() + std::chrono::seconds(2));
1540 });
1541
1542 Run();
1543
1544 bool found_primary_report = false;
1545 while (report_fetcher.FetchNext()) {
1546 if (report_fetcher->name()->string_view() == "primary") {
1547 found_primary_report = true;
1548 EXPECT_EQ("default_version_string",
1549 report_fetcher->version()->string_view());
1550 } else {
1551 FAIL() << report_fetcher->name()->string_view();
1552 }
1553 }
1554
1555 if (do_timing_reports() == DoTimingReports::kYes) {
1556 EXPECT_TRUE(found_primary_report);
1557 } else {
1558 EXPECT_FALSE(found_primary_report);
1559 }
1560}
1561
1562// Test that overriding the default version string results in it getting
1563// populated correctly.
1564TEST_P(AbstractEventLoopTest, OverrideDersionStringInTimingReport) {
1565 gflags::FlagSaver flag_saver;
1566 FLAGS_timing_report_ms = 1000;
1567
1568 EventLoop::SetDefaultVersionString("default_version_string");
1569
1570 auto loop = MakePrimary();
1571 loop->SetVersionString("override_version");
1572
1573 Fetcher<timing::Report> report_fetcher =
1574 loop->MakeFetcher<timing::Report>("/aos");
1575
1576 TimerHandler *exit_timer = loop->AddTimer([this]() { Exit(); });
1577 loop->OnRun([exit_timer, &loop, &report_fetcher]() {
1578 report_fetcher.Fetch();
1579 exit_timer->Schedule(loop->monotonic_now() + std::chrono::seconds(2));
1580 });
1581
1582 Run();
1583
1584 bool found_primary_report = false;
1585 while (report_fetcher.FetchNext()) {
1586 if (report_fetcher->name()->string_view() == "primary") {
1587 found_primary_report = true;
1588 EXPECT_EQ("override_version", report_fetcher->version()->string_view());
1589 } else {
1590 FAIL() << report_fetcher->name()->string_view();
1591 }
1592 }
1593
1594 if (do_timing_reports() == DoTimingReports::kYes) {
1595 EXPECT_TRUE(found_primary_report);
1596 } else {
1597 EXPECT_FALSE(found_primary_report);
1598 }
1599}
1600
Neil Balch229001a2018-01-07 18:22:52 -08001601// Verify that we can change a timer's parameters during execution.
1602TEST_P(AbstractEventLoopTest, TimerChangeParameters) {
Austin Schuh44019f92019-05-19 19:58:27 -07001603 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001604 loop->SetRuntimeRealtimePriority(1);
Austin Schuh7f20f512021-01-31 17:56:16 -08001605 std::vector<monotonic_clock::time_point> iteration_list;
Neil Balch229001a2018-01-07 18:22:52 -08001606
1607 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001608 ScopedNotRealtime nrt;
Austin Schuh7f20f512021-01-31 17:56:16 -08001609 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001610 });
1611
Austin Schuh7f20f512021-01-31 17:56:16 -08001612 monotonic_clock::time_point s;
1613 auto modifier_timer = loop->AddTimer([&test_timer, &s]() {
Philipp Schradera6712522023-07-05 20:25:11 -07001614 test_timer->Schedule(s + chrono::milliseconds(1750),
1615 chrono::milliseconds(600));
Neil Balch229001a2018-01-07 18:22:52 -08001616 });
1617
Austin Schuh7f20f512021-01-31 17:56:16 -08001618 s = loop->monotonic_now();
Philipp Schradera6712522023-07-05 20:25:11 -07001619 test_timer->Schedule(s, chrono::milliseconds(500));
1620 modifier_timer->Schedule(s + chrono::milliseconds(1250));
Austin Schuhd892f102021-10-12 18:01:46 -07001621 EndEventLoop(loop.get(), chrono::milliseconds(3950));
Austin Schuh44019f92019-05-19 19:58:27 -07001622 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001623
Austin Schuhd892f102021-10-12 18:01:46 -07001624 EXPECT_THAT(
1625 iteration_list,
1626 ::testing::ElementsAre(
1627 s, s + chrono::milliseconds(500), s + chrono::milliseconds(1000),
1628 s + chrono::milliseconds(1750), s + chrono::milliseconds(2350),
1629 s + chrono::milliseconds(2950), s + chrono::milliseconds(3550)));
Neil Balch229001a2018-01-07 18:22:52 -08001630}
1631
1632// Verify that we can disable a timer during execution.
1633TEST_P(AbstractEventLoopTest, TimerDisable) {
Austin Schuh44019f92019-05-19 19:58:27 -07001634 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001635 loop->SetRuntimeRealtimePriority(1);
Neil Balch229001a2018-01-07 18:22:52 -08001636 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
1637
1638 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001639 ScopedNotRealtime nrt;
Austin Schuhd892f102021-10-12 18:01:46 -07001640 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001641 });
1642
Tyler Chatow67ddb032020-01-12 14:30:04 -08001643 auto ender_timer = loop->AddTimer([&test_timer]() { test_timer->Disable(); });
Neil Balch229001a2018-01-07 18:22:52 -08001644
Austin Schuhd892f102021-10-12 18:01:46 -07001645 monotonic_clock::time_point s = loop->monotonic_now();
Philipp Schradera6712522023-07-05 20:25:11 -07001646 test_timer->Schedule(s, ::std::chrono::milliseconds(500));
1647 ender_timer->Schedule(s + ::std::chrono::milliseconds(1250));
Austin Schuh73d99502021-12-08 12:05:39 -08001648 EndEventLoop(loop.get(), ::std::chrono::milliseconds(2000));
Austin Schuh44019f92019-05-19 19:58:27 -07001649 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001650
Austin Schuhd892f102021-10-12 18:01:46 -07001651 EXPECT_THAT(iteration_list,
Austin Schuh73d99502021-12-08 12:05:39 -08001652 ::testing::ElementsAre(s, s + chrono::milliseconds(500),
1653 s + chrono::milliseconds(1000)));
Neil Balch229001a2018-01-07 18:22:52 -08001654}
Austin Schuh7267c532019-05-19 19:55:53 -07001655
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001656// Verify that a timer can disable itself.
1657//
1658// TODO(Brian): Do something similar with phased loops, both with a quick
1659// handler and a handler that would miss a cycle except it got deferred. Current
1660// behavior doing that is a mess.
1661TEST_P(AbstractEventLoopTest, TimerDisableSelf) {
1662 auto loop = MakePrimary();
1663
1664 int count = 0;
1665 aos::TimerHandler *test_timer;
1666 test_timer = loop->AddTimer([&count, &test_timer]() {
1667 ++count;
1668 test_timer->Disable();
1669 });
1670
Philipp Schradera6712522023-07-05 20:25:11 -07001671 test_timer->Schedule(loop->monotonic_now(), ::std::chrono::milliseconds(20));
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001672 EndEventLoop(loop.get(), ::std::chrono::milliseconds(80));
1673 Run();
1674
1675 EXPECT_EQ(count, 1);
1676}
1677
Brian Silvermanbd405c02020-06-23 16:25:23 -07001678// Verify that we can disable a timer during execution of another timer
1679// scheduled for the same time, with one ordering of creation for the timers.
1680//
1681// Also schedule some more events to reshuffle the heap in EventLoop used for
1682// tracking events to change up the order. This used to segfault
1683// SimulatedEventLoop.
1684TEST_P(AbstractEventLoopTest, TimerDisableOther) {
1685 for (bool creation_order : {true, false}) {
1686 for (bool setup_order : {true, false}) {
1687 for (int shuffle_events = 0; shuffle_events < 5; ++shuffle_events) {
1688 auto loop = MakePrimary();
1689 aos::TimerHandler *test_timer, *ender_timer;
1690 if (creation_order) {
1691 test_timer = loop->AddTimer([]() {});
1692 ender_timer =
1693 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1694 } else {
1695 ender_timer =
1696 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1697 test_timer = loop->AddTimer([]() {});
1698 }
1699
1700 const auto start = loop->monotonic_now();
1701
1702 for (int i = 0; i < shuffle_events; ++i) {
Philipp Schradera6712522023-07-05 20:25:11 -07001703 loop->AddTimer([]() {})->Schedule(start +
1704 std::chrono::milliseconds(10));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001705 }
1706
1707 if (setup_order) {
Philipp Schradera6712522023-07-05 20:25:11 -07001708 test_timer->Schedule(start + ::std::chrono::milliseconds(20));
1709 ender_timer->Schedule(start + ::std::chrono::milliseconds(20));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001710 } else {
Philipp Schradera6712522023-07-05 20:25:11 -07001711 ender_timer->Schedule(start + ::std::chrono::milliseconds(20));
1712 test_timer->Schedule(start + ::std::chrono::milliseconds(20));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001713 }
1714 EndEventLoop(loop.get(), ::std::chrono::milliseconds(40));
1715 Run();
1716 }
1717 }
1718 }
1719}
1720
Austin Schuh54cf95f2019-11-29 13:14:18 -08001721// Verifies that the event loop implementations detect when Channel is not a
Brian Silverman631b6262021-11-10 12:25:08 -08001722// pointer into configuration(), or a name doesn't map to a channel in
1723// configuration().
Austin Schuh54cf95f2019-11-29 13:14:18 -08001724TEST_P(AbstractEventLoopDeathTest, InvalidChannel) {
1725 auto loop = MakePrimary();
1726
Tyler Chatow67ddb032020-01-12 14:30:04 -08001727 const Channel *channel = configuration::GetChannel(
1728 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
Austin Schuh54cf95f2019-11-29 13:14:18 -08001729
1730 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1731
1732 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001733 loop->MakeRawSender(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001734 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1735
1736 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001737 loop->MakeSender<TestMessage>("/testbad"),
1738 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1739 " not found in config");
1740
1741 EXPECT_FALSE(loop->TryMakeSender<TestMessage>("/testbad"));
1742
1743 EXPECT_DEATH(
1744 loop->MakeRawFetcher(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001745 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1746
1747 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001748 loop->MakeFetcher<TestMessage>("/testbad"),
1749 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1750 " not found in config");
1751
1752 EXPECT_FALSE(loop->TryMakeFetcher<TestMessage>("/testbad").valid());
1753
1754 EXPECT_DEATH(
Austin Schuh54cf95f2019-11-29 13:14:18 -08001755 {
1756 loop->MakeRawWatcher(&channel_copy.message(),
1757 [](const Context, const void *) {});
1758 },
1759 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
Brian Silverman631b6262021-11-10 12:25:08 -08001760
1761 EXPECT_DEATH(
1762 { loop->MakeWatcher("/testbad", [](const TestMessage &) {}); },
1763 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1764 " not found in config");
1765}
1766
1767// Verifies that the event loop handles a channel which is not readable or
1768// writable on the current node nicely.
1769TEST_P(AbstractEventLoopDeathTest, InaccessibleChannel) {
1770 EnableNodes("me");
1771 auto loop = MakePrimary("me");
1772 auto loop2 = Make("them");
1773
1774 const Channel *channel = configuration::GetChannel(
1775 loop->configuration(), "/test_noforward", "aos.TestMessage", "", nullptr);
1776
1777 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1778
1779 EXPECT_DEATH(
1780 loop2->MakeSender<TestMessage>("/test_forward"),
1781 "Channel"
1782 " \\{ \"name\": \"/test_forward\", \"type\": \"aos.TestMessage\" \\}"
1783 " is not able to be sent on this node");
1784
1785 EXPECT_FALSE(loop2->TryMakeSender<TestMessage>("/test_forward"));
1786
1787 EXPECT_DEATH(
1788 loop2->MakeRawFetcher(channel),
1789 "Channel"
1790 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1791 " is not able to be fetched on this node");
1792
1793 EXPECT_DEATH(
1794 loop2->MakeFetcher<TestMessage>("/test_noforward"),
1795 "Channel"
1796 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1797 " is not able to be fetched on this node");
1798
1799 EXPECT_FALSE(loop2->TryMakeFetcher<TestMessage>("/test_noforward").valid());
1800
1801 EXPECT_DEATH(
1802 { loop2->MakeRawWatcher(channel, [](const Context, const void *) {}); },
1803 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1804 "\"source_node\": \"them\" \\}"
1805 " is not able to be watched on this node");
1806
1807 EXPECT_DEATH(
1808 { loop2->MakeWatcher("/test_noforward", [](const TestMessage &) {}); },
1809 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1810 "\"source_node\": \"them\" \\}"
1811 " is not able to be watched on this node");
Austin Schuh54cf95f2019-11-29 13:14:18 -08001812}
1813
Austin Schuhd54780b2020-10-03 16:26:02 -07001814// Verifies that the event loop implementations detect when Channel has an
1815// invalid alignment.
1816TEST_P(AbstractEventLoopDeathTest, InvalidChannelAlignment) {
1817 const char *const kError = "multiple of alignment";
1818 InvalidChannelAlignment();
1819
1820 auto loop = MakePrimary();
1821
1822 const Channel *channel = configuration::GetChannel(
1823 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
1824
1825 EXPECT_DEATH({ loop->MakeRawSender(channel); }, kError);
1826 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); }, kError);
1827
1828 EXPECT_DEATH({ loop->MakeRawFetcher(channel); }, kError);
1829 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); }, kError);
1830
1831 EXPECT_DEATH(
1832 { loop->MakeRawWatcher(channel, [](const Context &, const void *) {}); },
1833 kError);
1834 EXPECT_DEATH({ loop->MakeRawNoArgWatcher(channel, [](const Context &) {}); },
1835 kError);
1836
1837 EXPECT_DEATH({ loop->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
1838 kError);
1839 EXPECT_DEATH({ loop->MakeWatcher("/test", [](const TestMessage &) {}); },
1840 kError);
1841}
1842
Brian Silverman454bc112020-03-05 14:21:25 -08001843// Verify that the send time on a message is roughly right when using a watcher.
Austin Schuh7267c532019-05-19 19:55:53 -07001844TEST_P(AbstractEventLoopTest, MessageSendTime) {
Austin Schuh44019f92019-05-19 19:58:27 -07001845 auto loop1 = MakePrimary();
Austin Schuh7267c532019-05-19 19:55:53 -07001846 auto loop2 = Make();
Austin Schuhad154822019-12-27 15:45:13 -08001847 auto sender = loop2->MakeSender<TestMessage>("/test");
Austin Schuh7267c532019-05-19 19:55:53 -07001848 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
1849
1850 auto test_timer = loop1->AddTimer([&sender]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001851 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1852 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1853 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001854 msg.CheckOk(msg.Send(builder.Finish()));
Alex Perrycb7da4b2019-08-28 19:35:56 -07001855 });
1856
Austin Schuhad154822019-12-27 15:45:13 -08001857 bool triggered = false;
Brian Silverman454bc112020-03-05 14:21:25 -08001858 loop1->MakeWatcher("/test", [&](const TestMessage &msg) {
Austin Schuhad154822019-12-27 15:45:13 -08001859 // Confirm that the data pointer makes sense from a watcher, and all the
1860 // timestamps look right.
1861 EXPECT_GT(&msg, loop1->context().data);
1862 EXPECT_EQ(loop1->context().monotonic_remote_time,
1863 loop1->context().monotonic_event_time);
1864 EXPECT_EQ(loop1->context().realtime_remote_time,
1865 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001866 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001867
1868 const aos::monotonic_clock::time_point monotonic_now =
1869 loop1->monotonic_now();
Tyler Chatow67ddb032020-01-12 14:30:04 -08001870 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08001871
1872 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1873 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1874 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1875 monotonic_now);
1876 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1877 realtime_now);
1878
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001879 EXPECT_LT(&msg, reinterpret_cast<const void *>(
1880 reinterpret_cast<const char *>(loop1->context().data) +
Austin Schuhad154822019-12-27 15:45:13 -08001881 loop1->context().size));
Brian Silverman4f4e0612020-08-12 19:54:41 -07001882 if (read_method() == ReadMethod::PIN) {
1883 EXPECT_GE(loop1->context().buffer_index, 0);
1884 EXPECT_LT(loop1->context().buffer_index,
1885 loop1->NumberBuffers(
1886 configuration::GetChannel(loop1->configuration(), "/test",
1887 "aos.TestMessage", "", nullptr)));
1888 } else {
1889 EXPECT_EQ(-1, loop1->context().buffer_index);
1890 }
Austin Schuhad154822019-12-27 15:45:13 -08001891 triggered = true;
Austin Schuh7267c532019-05-19 19:55:53 -07001892 });
1893
Philipp Schradera6712522023-07-05 20:25:11 -07001894 test_timer->Schedule(loop1->monotonic_now() + ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07001895
1896 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
Austin Schuh44019f92019-05-19 19:58:27 -07001897 Run();
Austin Schuh7267c532019-05-19 19:55:53 -07001898
Austin Schuhad154822019-12-27 15:45:13 -08001899 EXPECT_TRUE(triggered);
1900
Brian Silverman454bc112020-03-05 14:21:25 -08001901 ASSERT_TRUE(fetcher.Fetch());
1902
1903 monotonic_clock::duration monotonic_time_offset =
1904 fetcher.context().monotonic_event_time -
1905 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1906 realtime_clock::duration realtime_time_offset =
1907 fetcher.context().realtime_event_time -
1908 (loop1->realtime_now() - ::std::chrono::seconds(1));
1909
1910 EXPECT_EQ(fetcher.context().realtime_event_time,
1911 fetcher.context().realtime_remote_time);
1912 EXPECT_EQ(fetcher.context().monotonic_event_time,
1913 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001914 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001915
1916 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1917 << ": Got "
1918 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1919 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1920 // Confirm that the data pointer makes sense.
1921 EXPECT_GT(fetcher.get(), fetcher.context().data);
1922 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001923 reinterpret_cast<const void *>(
1924 reinterpret_cast<const char *>(fetcher.context().data) +
Brian Silverman454bc112020-03-05 14:21:25 -08001925 fetcher.context().size));
1926 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1927 << ": Got "
1928 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1929 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1930
1931 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1932 << ": Got "
1933 << fetcher.context().realtime_event_time.time_since_epoch().count()
1934 << " expected " << loop1->realtime_now().time_since_epoch().count();
1935 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1936 << ": Got "
1937 << fetcher.context().realtime_event_time.time_since_epoch().count()
1938 << " expected " << loop1->realtime_now().time_since_epoch().count();
1939}
1940
1941// Verify that the send time on a message is roughly right when using a no-arg
1942// watcher. To get a message, we need to use a fetcher to actually access the
1943// message. This is also the main use case for no-arg fetchers.
1944TEST_P(AbstractEventLoopTest, MessageSendTimeNoArg) {
1945 auto loop1 = MakePrimary();
1946 auto loop2 = Make();
1947 auto sender = loop2->MakeSender<TestMessage>("/test");
1948 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
1949
1950 auto test_timer = loop1->AddTimer([&sender]() {
1951 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1952 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1953 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001954 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -08001955 });
1956
1957 bool triggered = false;
1958 loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {
1959 // Confirm that we can indeed use a fetcher on this channel from this
1960 // context, and it results in a sane data pointer and timestamps.
1961 ASSERT_TRUE(fetcher.Fetch());
1962
1963 EXPECT_EQ(loop1->context().monotonic_remote_time,
1964 loop1->context().monotonic_event_time);
1965 EXPECT_EQ(loop1->context().realtime_remote_time,
1966 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001967 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001968
1969 const aos::monotonic_clock::time_point monotonic_now =
1970 loop1->monotonic_now();
1971 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
1972
1973 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1974 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1975 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1976 monotonic_now);
1977 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1978 realtime_now);
1979
1980 triggered = true;
1981 });
1982
Philipp Schradera6712522023-07-05 20:25:11 -07001983 test_timer->Schedule(loop1->monotonic_now() + ::std::chrono::seconds(1));
Brian Silverman454bc112020-03-05 14:21:25 -08001984
1985 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
1986 Run();
1987
1988 ASSERT_TRUE(triggered);
Austin Schuh7267c532019-05-19 19:55:53 -07001989
Alex Perrycb7da4b2019-08-28 19:35:56 -07001990 monotonic_clock::duration monotonic_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001991 fetcher.context().monotonic_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001992 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1993 realtime_clock::duration realtime_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001994 fetcher.context().realtime_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001995 (loop1->realtime_now() - ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07001996
Austin Schuhad154822019-12-27 15:45:13 -08001997 EXPECT_EQ(fetcher.context().realtime_event_time,
1998 fetcher.context().realtime_remote_time);
1999 EXPECT_EQ(fetcher.context().monotonic_event_time,
2000 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002001 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08002002
Alex Perrycb7da4b2019-08-28 19:35:56 -07002003 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
2004 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002005 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh52d325c2019-06-23 18:59:06 -07002006 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07002007 // Confirm that the data pointer makes sense.
2008 EXPECT_GT(fetcher.get(), fetcher.context().data);
2009 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07002010 reinterpret_cast<const void *>(
2011 reinterpret_cast<const char *>(fetcher.context().data) +
Alex Perrycb7da4b2019-08-28 19:35:56 -07002012 fetcher.context().size));
2013 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
2014 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002015 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh7267c532019-05-19 19:55:53 -07002016 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07002017
2018 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
2019 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002020 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07002021 << " expected " << loop1->realtime_now().time_since_epoch().count();
2022 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
2023 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08002024 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07002025 << " expected " << loop1->realtime_now().time_since_epoch().count();
Austin Schuh7267c532019-05-19 19:55:53 -07002026}
2027
Austin Schuh52d325c2019-06-23 18:59:06 -07002028// Tests that a couple phased loops run in a row result in the correct offset
2029// and period.
2030TEST_P(AbstractEventLoopTest, PhasedLoopTest) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07002031 // Force a slower rate so we are guaranteed to have reports for our phased
Austin Schuh39788ff2019-12-01 18:22:57 -08002032 // loop.
2033 FLAGS_timing_report_ms = 2000;
2034
Austin Schuh52d325c2019-06-23 18:59:06 -07002035 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2036 const int kCount = 5;
2037
2038 auto loop1 = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08002039 auto loop2 = Make();
2040
2041 Fetcher<timing::Report> report_fetcher =
2042 loop2->MakeFetcher<timing::Report>("/aos");
2043 EXPECT_FALSE(report_fetcher.Fetch());
Austin Schuh52d325c2019-06-23 18:59:06 -07002044
2045 // Collect up a couple of samples.
2046 ::std::vector<::aos::monotonic_clock::time_point> times;
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002047 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
Austin Schuh52d325c2019-06-23 18:59:06 -07002048
2049 // Run kCount iterations.
Austin Schuh39788ff2019-12-01 18:22:57 -08002050 loop1
2051 ->AddPhasedLoop(
2052 [&times, &expected_times, &loop1, this](int count) {
2053 EXPECT_EQ(count, 1);
2054 times.push_back(loop1->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08002055 expected_times.push_back(loop1->context().monotonic_event_time);
Austin Schuh39788ff2019-12-01 18:22:57 -08002056
Austin Schuhad154822019-12-27 15:45:13 -08002057 EXPECT_EQ(loop1->context().monotonic_remote_time,
2058 monotonic_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002059 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08002060 EXPECT_EQ(loop1->context().realtime_event_time,
2061 realtime_clock::min_time);
2062 EXPECT_EQ(loop1->context().realtime_remote_time,
Austin Schuh39788ff2019-12-01 18:22:57 -08002063 realtime_clock::min_time);
2064 EXPECT_EQ(loop1->context().queue_index, 0xffffffffu);
2065 EXPECT_EQ(loop1->context().size, 0u);
2066 EXPECT_EQ(loop1->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07002067 EXPECT_EQ(loop1->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08002068
2069 if (times.size() == kCount) {
2070 LOG(INFO) << "Exiting";
2071 this->Exit();
2072 }
2073 },
2074 chrono::seconds(1), kOffset)
2075 ->set_name("Test loop");
Austin Schuh52d325c2019-06-23 18:59:06 -07002076
2077 // Add a delay to make sure that delay during startup doesn't result in a
2078 // "missed cycle".
2079 SleepFor(chrono::seconds(2));
2080
2081 Run();
2082
2083 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07002084 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
2085 ASSERT_EQ(times.size(), expected_times.size());
2086 ASSERT_EQ((times.size() % 2), 1);
Austin Schuh52d325c2019-06-23 18:59:06 -07002087
2088 // Grab the middle sample.
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002089 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
Austin Schuh52d325c2019-06-23 18:59:06 -07002090
2091 // Add up all the delays of all the times.
2092 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
2093 for (const ::aos::monotonic_clock::time_point time : times) {
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002094 sum += time - average_time;
Austin Schuh52d325c2019-06-23 18:59:06 -07002095 }
2096
2097 // Average and add to the middle to find the average time.
2098 sum /= times.size();
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002099 average_time += sum;
Austin Schuh52d325c2019-06-23 18:59:06 -07002100
2101 // Compute the offset from the start of the second of the average time. This
2102 // should be pretty close to the offset.
2103 const ::aos::monotonic_clock::duration remainder =
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002104 average_time.time_since_epoch() -
2105 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
Austin Schuh52d325c2019-06-23 18:59:06 -07002106
2107 const chrono::milliseconds kEpsilon(100);
2108 EXPECT_LT(remainder, kOffset + kEpsilon);
2109 EXPECT_GT(remainder, kOffset - kEpsilon);
2110
2111 // Make sure that the average duration is close to 1 second.
2112 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
2113 times.front())
2114 .count() /
2115 static_cast<double>(times.size() - 1),
2116 1.0, 0.1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08002117
2118 // Confirm that the ideal wakeup times increment correctly.
2119 for (size_t i = 1; i < expected_times.size(); ++i) {
2120 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
2121 }
2122
2123 for (size_t i = 0; i < expected_times.size(); ++i) {
2124 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
2125 kOffset);
2126 }
2127
2128 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
2129 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08002130
Austin Schuh6bae8252021-02-07 22:01:49 -08002131 if (do_timing_reports() == DoTimingReports::kYes) {
2132 // And, since we are here, check that the timing report makes sense.
2133 // Start by looking for our event loop's timing.
2134 FlatbufferDetachedBuffer<timing::Report> report =
2135 FlatbufferDetachedBuffer<timing::Report>::Empty();
2136 while (report_fetcher.FetchNext()) {
2137 if (report_fetcher->name()->string_view() == "primary") {
2138 report = CopyFlatBuffer(report_fetcher.get());
2139 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002140 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002141
2142 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
2143
2144 EXPECT_EQ(report.message().name()->string_view(), "primary");
2145
2146 ASSERT_NE(report.message().senders(), nullptr);
2147 EXPECT_EQ(report.message().senders()->size(), 2);
2148
2149 ASSERT_NE(report.message().timers(), nullptr);
2150 EXPECT_EQ(report.message().timers()->size(), 1);
2151
2152 // Make sure there is a single phased loop report with our report in it.
2153 ASSERT_NE(report.message().phased_loops(), nullptr);
2154 ASSERT_EQ(report.message().phased_loops()->size(), 1);
2155 EXPECT_EQ(report.message().phased_loops()->Get(0)->name()->string_view(),
2156 "Test loop");
2157 EXPECT_GE(report.message().phased_loops()->Get(0)->count(), 1);
2158 } else {
2159 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002160 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002161}
2162
Milind Upadhyay42589bb2021-05-19 20:05:16 -07002163// Tests that a phased loop responds correctly to a changing offset.
2164TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetTest) {
2165 // Force a slower rate so we are guaranteed to have reports for our phased
2166 // loop.
2167 FLAGS_timing_report_ms = 2000;
2168
2169 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2170 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2171 const int kCount = 5;
2172
2173 auto loop1 = MakePrimary();
2174
2175 // Collect up a couple of samples.
2176 ::std::vector<::aos::monotonic_clock::time_point> times;
2177 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
2178
2179 PhasedLoopHandler *phased_loop;
2180
2181 // Run kCount iterations.
2182 phased_loop = loop1->AddPhasedLoop(
2183 [&phased_loop, &times, &expected_times, &loop1, this, kOffset,
2184 kInterval](int count) {
2185 EXPECT_EQ(count, 1);
2186 times.push_back(loop1->monotonic_now());
2187
2188 expected_times.push_back(loop1->context().monotonic_event_time);
2189
2190 phased_loop->set_interval_and_offset(
2191 kInterval, kOffset - chrono::milliseconds(times.size()));
2192 LOG(INFO) << "new offset: "
2193 << (kOffset - chrono::milliseconds(times.size())).count();
2194
2195 if (times.size() == kCount) {
2196 LOG(INFO) << "Exiting";
2197 this->Exit();
2198 }
2199 },
2200 kInterval, kOffset);
2201 phased_loop->set_name("Test loop");
2202
2203 // Add a delay to make sure that delay during startup doesn't result in a
2204 // "missed cycle".
2205 SleepFor(chrono::seconds(2));
2206
2207 Run();
2208 // Confirm that we got both the right number of samples, and it's odd.
2209 EXPECT_EQ(times.size(), static_cast<size_t>(kCount));
2210 EXPECT_EQ(times.size(), expected_times.size());
2211 EXPECT_EQ((times.size() % 2), 1);
2212
2213 // Grab the middle sample.
2214 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
2215
2216 // Add up all the delays of all the times.
2217 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
2218 for (const ::aos::monotonic_clock::time_point time : times) {
2219 sum += time - average_time;
2220 }
2221
2222 // Average and add to the middle to find the average time.
2223 sum /= times.size();
2224 average_time += sum;
2225
2226 // Compute the offset from the start of the second of the average time. This
2227 // should be pretty close to the offset.
2228 const ::aos::monotonic_clock::duration remainder =
2229 average_time.time_since_epoch() -
2230 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
2231
2232 const chrono::milliseconds kEpsilon(100);
2233 EXPECT_LT(remainder, kOffset + kEpsilon);
2234 EXPECT_GT(remainder, kOffset - kEpsilon);
2235
2236 // Make sure that the average duration is close to 1 second.
2237 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
2238 times.front())
2239 .count() /
2240 static_cast<double>(times.size() - 1),
2241 1.0, 0.1);
2242
2243 // Confirm that the ideal wakeup times increment correctly.
2244 for (size_t i = 1; i < expected_times.size(); ++i) {
2245 LOG(INFO) << i - 1 << ": " << expected_times[i - 1] << ", " << i << ": "
2246 << expected_times[i];
2247 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1) -
2248 chrono::milliseconds(1));
2249 }
2250
2251 for (size_t i = 0; i < expected_times.size(); ++i) {
2252 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
2253 kOffset - chrono::milliseconds(i));
2254 }
2255
2256 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
2257 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
2258}
2259
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002260// Tests that a phased loop responds correctly to a changing offset; sweep
2261// across a variety of potential offset changes, to ensure that we are
2262// exercising a variety of potential cases.
2263TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetSweep) {
2264 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2265 const int kCount = 5;
2266
2267 auto loop1 = MakePrimary();
2268
2269 std::vector<aos::monotonic_clock::duration> offset_options;
2270 for (int ii = 0; ii < kCount; ++ii) {
2271 offset_options.push_back(ii * kInterval / kCount);
2272 }
2273 std::vector<aos::monotonic_clock::duration> offset_sweep;
2274 // Run over all the pair-wise combinations of offsets.
2275 for (int ii = 0; ii < kCount; ++ii) {
2276 for (int jj = 0; jj < kCount; ++jj) {
2277 offset_sweep.push_back(offset_options.at(ii));
2278 offset_sweep.push_back(offset_options.at(jj));
2279 }
2280 }
2281
2282 std::vector<::aos::monotonic_clock::time_point> expected_times;
2283
2284 PhasedLoopHandler *phased_loop;
2285
2286 // Run kCount iterations.
2287 size_t counter = 0;
2288 phased_loop = loop1->AddPhasedLoop(
2289 [&phased_loop, &expected_times, &loop1, this, kInterval, &counter,
2290 offset_sweep](int count) {
2291 EXPECT_EQ(count, 1);
2292 expected_times.push_back(loop1->context().monotonic_event_time);
2293
2294 counter++;
2295
2296 if (counter == offset_sweep.size()) {
2297 LOG(INFO) << "Exiting";
2298 this->Exit();
2299 return;
2300 }
2301
2302 phased_loop->set_interval_and_offset(kInterval,
2303 offset_sweep.at(counter));
2304 },
2305 kInterval, offset_sweep.at(0));
2306
2307 Run();
2308 ASSERT_EQ(expected_times.size(), offset_sweep.size());
2309 for (size_t ii = 1; ii < expected_times.size(); ++ii) {
2310 EXPECT_LE(expected_times.at(ii) - expected_times.at(ii - 1), kInterval);
2311 }
2312}
2313
2314// Tests that a phased loop responds correctly to being rescheduled with now
2315// equal to a time in the past.
2316TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleInPast) {
2317 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2318 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2319
2320 auto loop1 = MakePrimary();
2321
2322 std::vector<::aos::monotonic_clock::time_point> expected_times;
2323
2324 PhasedLoopHandler *phased_loop;
2325
2326 int expected_count = 1;
2327
2328 // Set up a timer that will get run immediately after the phased loop and
2329 // which will attempt to reschedule the phased loop to just before now. This
2330 // should succeed, but will result in 0 cycles elapsing.
2331 TimerHandler *manager_timer =
2332 loop1->AddTimer([&phased_loop, &loop1, &expected_count, this]() {
2333 if (expected_count == 0) {
2334 LOG(INFO) << "Exiting";
2335 this->Exit();
2336 return;
2337 }
2338 phased_loop->Reschedule(loop1->context().monotonic_event_time -
2339 std::chrono::nanoseconds(1));
2340 expected_count = 0;
2341 });
2342
2343 phased_loop = loop1->AddPhasedLoop(
2344 [&expected_count, &expected_times, &loop1, manager_timer](int count) {
2345 EXPECT_EQ(count, expected_count);
2346 expected_times.push_back(loop1->context().monotonic_event_time);
2347
Philipp Schradera6712522023-07-05 20:25:11 -07002348 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002349 },
2350 kInterval, kOffset);
2351 phased_loop->set_name("Test loop");
2352 manager_timer->set_name("Manager timer");
2353
2354 Run();
2355
2356 ASSERT_EQ(2u, expected_times.size());
2357 ASSERT_EQ(expected_times[0], expected_times[1]);
2358}
2359
2360// Tests that a phased loop responds correctly to being rescheduled at the time
2361// when it should be triggering (it should kick the trigger to the next cycle).
2362TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleNow) {
2363 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2364 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2365
2366 auto loop1 = MakePrimary();
2367
2368 std::vector<::aos::monotonic_clock::time_point> expected_times;
2369
2370 PhasedLoopHandler *phased_loop;
2371
2372 bool should_exit = false;
2373 // Set up a timer that will get run immediately after the phased loop and
2374 // which will attempt to reschedule the phased loop to now. This should
2375 // succeed, but will result in no change to the expected behavior (since this
2376 // is the same thing that is actually done internally).
2377 TimerHandler *manager_timer =
2378 loop1->AddTimer([&phased_loop, &loop1, &should_exit, this]() {
2379 if (should_exit) {
2380 LOG(INFO) << "Exiting";
2381 this->Exit();
2382 return;
2383 }
2384 phased_loop->Reschedule(loop1->context().monotonic_event_time);
2385 should_exit = true;
2386 });
2387
2388 phased_loop = loop1->AddPhasedLoop(
2389 [&expected_times, &loop1, manager_timer](int count) {
2390 EXPECT_EQ(count, 1);
2391 expected_times.push_back(loop1->context().monotonic_event_time);
2392
Philipp Schradera6712522023-07-05 20:25:11 -07002393 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002394 },
2395 kInterval, kOffset);
2396 phased_loop->set_name("Test loop");
2397 manager_timer->set_name("Manager timer");
2398
2399 Run();
2400
2401 ASSERT_EQ(2u, expected_times.size());
2402 ASSERT_EQ(expected_times[0] + kInterval, expected_times[1]);
2403}
2404
2405// Tests that a phased loop responds correctly to being rescheduled at a time in
2406// the distant future.
2407TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleFuture) {
2408 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2409 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2410
2411 auto loop1 = MakePrimary();
2412
2413 std::vector<::aos::monotonic_clock::time_point> expected_times;
2414
2415 PhasedLoopHandler *phased_loop;
2416
2417 bool should_exit = false;
2418 int expected_count = 1;
2419 TimerHandler *manager_timer = loop1->AddTimer(
2420 [&expected_count, &phased_loop, &loop1, &should_exit, this, kInterval]() {
2421 if (should_exit) {
2422 LOG(INFO) << "Exiting";
2423 this->Exit();
2424 return;
2425 }
2426 expected_count = 10;
2427 // Knock off 1 ns, since the scheduler rounds up when it is
2428 // scheduled to exactly a loop time.
2429 phased_loop->Reschedule(loop1->context().monotonic_event_time +
2430 kInterval * expected_count -
2431 std::chrono::nanoseconds(1));
2432 should_exit = true;
2433 });
2434
2435 phased_loop = loop1->AddPhasedLoop(
2436 [&expected_times, &loop1, manager_timer, &expected_count](int count) {
2437 EXPECT_EQ(count, expected_count);
2438 expected_times.push_back(loop1->context().monotonic_event_time);
2439
Philipp Schradera6712522023-07-05 20:25:11 -07002440 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002441 },
2442 kInterval, kOffset);
2443 phased_loop->set_name("Test loop");
2444 manager_timer->set_name("Manager timer");
2445
2446 Run();
2447
2448 ASSERT_EQ(2u, expected_times.size());
2449 ASSERT_EQ(expected_times[0] + expected_count * kInterval, expected_times[1]);
2450}
2451
2452// Tests that a phased loop responds correctly to having its phase offset
2453// incremented and then being scheduled after a set time, exercising a pattern
2454// where a phased loop's offset is changed while trying to maintain the trigger
2455// at a consistent period.
2456TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleWithLaterOffset) {
2457 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2458 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2459
2460 auto loop1 = MakePrimary();
2461
2462 std::vector<::aos::monotonic_clock::time_point> expected_times;
2463
2464 PhasedLoopHandler *phased_loop;
2465
2466 bool should_exit = false;
2467 TimerHandler *manager_timer = loop1->AddTimer(
2468 [&phased_loop, &loop1, &should_exit, this, kInterval, kOffset]() {
2469 if (should_exit) {
2470 LOG(INFO) << "Exiting";
2471 this->Exit();
2472 return;
2473 }
2474 // Schedule the next callback to be strictly later than the current time
2475 // + interval / 2, to ensure a consistent frequency.
2476 monotonic_clock::time_point half_time =
2477 loop1->context().monotonic_event_time + kInterval / 2;
2478 phased_loop->set_interval_and_offset(
2479 kInterval, kOffset + std::chrono::nanoseconds(1), half_time);
2480 phased_loop->Reschedule(half_time);
2481 should_exit = true;
2482 });
2483
2484 phased_loop = loop1->AddPhasedLoop(
2485 [&expected_times, &loop1, manager_timer](int count) {
2486 EXPECT_EQ(1, count);
2487 expected_times.push_back(loop1->context().monotonic_event_time);
2488
Philipp Schradera6712522023-07-05 20:25:11 -07002489 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002490 },
2491 kInterval, kOffset);
2492 phased_loop->set_name("Test loop");
2493 manager_timer->set_name("Manager timer");
2494
2495 Run();
2496
2497 ASSERT_EQ(2u, expected_times.size());
2498 ASSERT_EQ(expected_times[0] + kInterval + std::chrono::nanoseconds(1),
2499 expected_times[1]);
2500}
2501
2502// Tests that a phased loop responds correctly to having its phase offset
2503// decremented and then being scheduled after a set time, exercising a pattern
2504// where a phased loop's offset is changed while trying to maintain the trigger
2505// at a consistent period.
2506TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleWithEarlierOffset) {
2507 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2508 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2509
2510 auto loop1 = MakePrimary();
2511
2512 std::vector<::aos::monotonic_clock::time_point> expected_times;
2513
2514 PhasedLoopHandler *phased_loop;
2515
2516 bool should_exit = false;
2517 TimerHandler *manager_timer = loop1->AddTimer(
2518 [&phased_loop, &loop1, &should_exit, this, kInterval, kOffset]() {
2519 if (should_exit) {
2520 LOG(INFO) << "Exiting";
2521 this->Exit();
2522 return;
2523 }
2524 // Schedule the next callback to be strictly later than the current time
2525 // + interval / 2, to ensure a consistent frequency.
2526 const aos::monotonic_clock::time_point half_time =
2527 loop1->context().monotonic_event_time + kInterval / 2;
2528 phased_loop->set_interval_and_offset(
2529 kInterval, kOffset - std::chrono::nanoseconds(1), half_time);
2530 phased_loop->Reschedule(half_time);
2531 should_exit = true;
2532 });
2533
2534 phased_loop = loop1->AddPhasedLoop(
2535 [&expected_times, &loop1, manager_timer](int count) {
2536 EXPECT_EQ(1, count);
2537 expected_times.push_back(loop1->context().monotonic_event_time);
2538
Philipp Schradera6712522023-07-05 20:25:11 -07002539 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002540 },
2541 kInterval, kOffset);
2542 phased_loop->set_name("Test loop");
2543 manager_timer->set_name("Manager timer");
2544
2545 Run();
2546
2547 ASSERT_EQ(2u, expected_times.size());
2548 ASSERT_EQ(expected_times[0] + kInterval - std::chrono::nanoseconds(1),
2549 expected_times[1]);
2550}
2551
Austin Schuh39788ff2019-12-01 18:22:57 -08002552// Tests that senders count correctly in the timing report.
2553TEST_P(AbstractEventLoopTest, SenderTimingReport) {
2554 FLAGS_timing_report_ms = 1000;
2555 auto loop1 = MakePrimary();
2556
2557 auto loop2 = Make("watcher_loop");
2558 loop2->MakeWatcher("/test", [](const TestMessage &) {});
2559
2560 auto loop3 = Make();
2561
2562 Fetcher<timing::Report> report_fetcher =
2563 loop3->MakeFetcher<timing::Report>("/aos");
2564 EXPECT_FALSE(report_fetcher.Fetch());
2565
2566 auto sender = loop1->MakeSender<TestMessage>("/test");
2567
James Kuszmaul78514332022-04-06 15:08:34 -07002568 // Sanity check channel frequencies to ensure that we've designed the test
2569 // correctly.
2570 ASSERT_EQ(800, sender.channel()->frequency());
Austin Schuhfff9c3a2023-06-16 18:48:23 -07002571 ASSERT_EQ(2000000000, configuration::ChannelStorageDuration(
2572 loop1->configuration(), sender.channel())
2573 .count());
James Kuszmaul78514332022-04-06 15:08:34 -07002574 constexpr int kMaxAllowedMessages = 800 * 2;
2575 constexpr int kSendMessages = kMaxAllowedMessages * 2;
2576 constexpr int kDroppedMessages = kSendMessages - kMaxAllowedMessages;
2577
Austin Schuh39788ff2019-12-01 18:22:57 -08002578 // Add a timer to actually quit.
2579 auto test_timer = loop1->AddTimer([&sender]() {
James Kuszmaul78514332022-04-06 15:08:34 -07002580 for (int i = 0; i < kSendMessages; ++i) {
Austin Schuh39788ff2019-12-01 18:22:57 -08002581 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2582 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2583 builder.add_value(200 + i);
James Kuszmaul78514332022-04-06 15:08:34 -07002584 if (i < kMaxAllowedMessages) {
2585 msg.CheckOk(msg.Send(builder.Finish()));
2586 } else {
2587 EXPECT_EQ(RawSender::Error::kMessagesSentTooFast,
2588 msg.Send(builder.Finish()));
2589 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002590 }
2591 });
2592
2593 // Quit after 1 timing report, mid way through the next cycle.
2594 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2595
2596 loop1->OnRun([&test_timer, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002597 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1500));
Austin Schuh39788ff2019-12-01 18:22:57 -08002598 });
2599
2600 Run();
2601
Austin Schuh6bae8252021-02-07 22:01:49 -08002602 if (do_timing_reports() == DoTimingReports::kYes) {
2603 // And, since we are here, check that the timing report makes sense.
2604 // Start by looking for our event loop's timing.
2605 FlatbufferDetachedBuffer<timing::Report> primary_report =
2606 FlatbufferDetachedBuffer<timing::Report>::Empty();
2607 while (report_fetcher.FetchNext()) {
Austin Schuh8902fa52021-03-14 22:39:24 -07002608 VLOG(1) << "Report " << FlatbufferToJson(report_fetcher.get());
Austin Schuh6bae8252021-02-07 22:01:49 -08002609 if (report_fetcher->name()->string_view() == "primary") {
2610 primary_report = CopyFlatBuffer(report_fetcher.get());
2611 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002612 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002613
Austin Schuh8902fa52021-03-14 22:39:24 -07002614 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
Austin Schuh6bae8252021-02-07 22:01:49 -08002615
2616 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2617
2618 ASSERT_NE(primary_report.message().senders(), nullptr);
2619 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2620
2621 // Confirm that the sender looks sane.
2622 EXPECT_EQ(
2623 loop1->configuration()
2624 ->channels()
2625 ->Get(primary_report.message().senders()->Get(0)->channel_index())
2626 ->name()
2627 ->string_view(),
2628 "/test");
James Kuszmaul78514332022-04-06 15:08:34 -07002629 EXPECT_EQ(primary_report.message().senders()->Get(0)->count(),
2630 kMaxAllowedMessages);
2631 ASSERT_TRUE(primary_report.message().senders()->Get(0)->has_error_counts());
2632 ASSERT_EQ(
2633 primary_report.message().senders()->Get(0)->error_counts()->size(), 2u);
2634 EXPECT_EQ(
2635 primary_report.message()
2636 .senders()
2637 ->Get(0)
2638 ->error_counts()
2639 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2640 ->count(),
2641 kDroppedMessages)
2642 << aos::FlatbufferToJson(primary_report);
2643 EXPECT_EQ(primary_report.message()
2644 .senders()
2645 ->Get(0)
2646 ->error_counts()
2647 ->Get(static_cast<size_t>(timing::SendError::INVALID_REDZONE))
2648 ->count(),
2649 0);
Austin Schuh6bae8252021-02-07 22:01:49 -08002650
2651 // Confirm that the timing primary_report sender looks sane.
2652 EXPECT_EQ(
2653 loop1->configuration()
2654 ->channels()
2655 ->Get(primary_report.message().senders()->Get(1)->channel_index())
2656 ->name()
2657 ->string_view(),
2658 "/aos");
2659 EXPECT_EQ(primary_report.message().senders()->Get(1)->count(), 1);
2660
2661 ASSERT_NE(primary_report.message().timers(), nullptr);
2662 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2663
2664 // Make sure there are no phased loops or watchers.
2665 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2666 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2667 } else {
2668 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002669 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002670}
2671
James Kuszmaul93abac12022-04-14 15:05:10 -07002672// Tests that the RawSender::Send(void*, size_t) overload tracks things properly
2673// in its timing report.
2674TEST_P(AbstractEventLoopTest, CopySenderTimingReport) {
2675 gflags::FlagSaver flag_saver;
2676 FLAGS_timing_report_ms = 1000;
2677 auto loop1 = Make();
2678 auto loop2 = MakePrimary();
2679
2680 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2681 JsonToFlatbuffer<TestMessage>("{}");
2682
2683 std::unique_ptr<aos::RawSender> sender =
2684 loop2->MakeRawSender(configuration::GetChannel(
2685 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
2686
2687 Fetcher<timing::Report> report_fetcher =
2688 loop1->MakeFetcher<timing::Report>("/aos");
2689 EXPECT_FALSE(report_fetcher.Fetch());
2690
2691 loop2->OnRun([&]() {
2692 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
2693 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2694 RawSender::Error::kOk);
2695 }
2696 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2697 RawSender::Error::kMessagesSentTooFast);
2698 });
2699 // Quit after 1 timing report, mid way through the next cycle.
2700 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
2701
2702 Run();
2703
2704 if (do_timing_reports() == DoTimingReports::kYes) {
2705 // Check that the sent too fast actually got recorded by the timing report.
2706 FlatbufferDetachedBuffer<timing::Report> primary_report =
2707 FlatbufferDetachedBuffer<timing::Report>::Empty();
2708 while (report_fetcher.FetchNext()) {
2709 if (report_fetcher->name()->string_view() == "primary") {
2710 primary_report = CopyFlatBuffer(report_fetcher.get());
2711 }
2712 }
2713
2714 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2715
2716 ASSERT_NE(primary_report.message().senders(), nullptr);
2717 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2718 EXPECT_EQ(
2719 primary_report.message()
2720 .senders()
2721 ->Get(0)
2722 ->error_counts()
2723 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2724 ->count(),
2725 1);
2726 }
2727}
2728
Austin Schuhe0ab4de2023-05-03 08:05:08 -07002729// Tests that the RawSender::Send(SharedSpan) overload works.
2730TEST_P(AbstractEventLoopTest, SharedSenderTimingReport) {
2731 gflags::FlagSaver flag_saver;
2732 FLAGS_timing_report_ms = 1000;
2733 auto loop1 = Make();
2734 auto loop2 = MakePrimary();
2735
2736 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2737 JsonToFlatbuffer<TestMessage>("{}");
2738
2739 std::unique_ptr<aos::RawSender> sender =
2740 loop2->MakeRawSender(configuration::GetChannel(
2741 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
2742
2743 Fetcher<timing::Report> report_fetcher =
2744 loop1->MakeFetcher<timing::Report>("/aos");
2745 EXPECT_FALSE(report_fetcher.Fetch());
2746
2747 loop2->OnRun([&]() {
2748 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
2749 auto shared_span = MakeSharedSpan(kMessage.span().size());
2750 memcpy(shared_span.second.data(), kMessage.span().data(),
2751 kMessage.span().size());
2752 EXPECT_EQ(sender->Send(std::move(shared_span.first)),
2753 RawSender::Error::kOk);
2754 }
2755 auto shared_span = MakeSharedSpan(kMessage.span().size());
2756 memcpy(shared_span.second.data(), kMessage.span().data(),
2757 kMessage.span().size());
2758 EXPECT_EQ(sender->Send(std::move(shared_span.first)),
2759 RawSender::Error::kMessagesSentTooFast);
2760 });
2761 // Quit after 1 timing report, mid way through the next cycle.
2762 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
2763
2764 Run();
2765
2766 if (do_timing_reports() == DoTimingReports::kYes) {
2767 // Check that the sent too fast actually got recorded by the timing report.
2768 FlatbufferDetachedBuffer<timing::Report> primary_report =
2769 FlatbufferDetachedBuffer<timing::Report>::Empty();
2770 while (report_fetcher.FetchNext()) {
2771 if (report_fetcher->name()->string_view() == "primary") {
2772 primary_report = CopyFlatBuffer(report_fetcher.get());
2773 }
2774 }
2775
2776 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2777
2778 ASSERT_NE(primary_report.message().senders(), nullptr);
2779 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2780 EXPECT_EQ(
2781 primary_report.message()
2782 .senders()
2783 ->Get(0)
2784 ->error_counts()
2785 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2786 ->count(),
2787 1);
2788 }
2789}
2790
Austin Schuh39788ff2019-12-01 18:22:57 -08002791// Tests that senders count correctly in the timing report.
2792TEST_P(AbstractEventLoopTest, WatcherTimingReport) {
2793 FLAGS_timing_report_ms = 1000;
2794 auto loop1 = MakePrimary();
2795 loop1->MakeWatcher("/test", [](const TestMessage &) {});
2796
2797 auto loop2 = Make("sender_loop");
2798
2799 auto loop3 = Make();
2800
2801 Fetcher<timing::Report> report_fetcher =
2802 loop3->MakeFetcher<timing::Report>("/aos");
2803 EXPECT_FALSE(report_fetcher.Fetch());
2804
2805 auto sender = loop2->MakeSender<TestMessage>("/test");
2806
2807 // Add a timer to actually quit.
2808 auto test_timer = loop1->AddTimer([&sender]() {
2809 for (int i = 0; i < 10; ++i) {
2810 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2811 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2812 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002813 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002814 }
2815 });
2816
2817 // Quit after 1 timing report, mid way through the next cycle.
2818 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2819
2820 loop1->OnRun([&test_timer, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002821 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1500));
Austin Schuh39788ff2019-12-01 18:22:57 -08002822 });
2823
2824 Run();
2825
Austin Schuh6bae8252021-02-07 22:01:49 -08002826 if (do_timing_reports() == DoTimingReports::kYes) {
2827 // And, since we are here, check that the timing report makes sense.
2828 // Start by looking for our event loop's timing.
2829 FlatbufferDetachedBuffer<timing::Report> primary_report =
2830 FlatbufferDetachedBuffer<timing::Report>::Empty();
2831 while (report_fetcher.FetchNext()) {
2832 LOG(INFO) << "Report " << FlatbufferToJson(report_fetcher.get());
2833 if (report_fetcher->name()->string_view() == "primary") {
2834 primary_report = CopyFlatBuffer(report_fetcher.get());
2835 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002836 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002837
2838 // Check the watcher report.
2839 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2840
2841 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2842
2843 // Just the timing report timer.
2844 ASSERT_NE(primary_report.message().timers(), nullptr);
2845 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2846
2847 // No phased loops
2848 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2849
2850 ASSERT_NE(primary_report.message().watchers(), nullptr);
2851 ASSERT_EQ(primary_report.message().watchers()->size(), 1);
2852 EXPECT_EQ(primary_report.message().watchers()->Get(0)->count(), 10);
2853 } else {
2854 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002855 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002856}
2857
2858// Tests that fetchers count correctly in the timing report.
2859TEST_P(AbstractEventLoopTest, FetcherTimingReport) {
2860 FLAGS_timing_report_ms = 1000;
2861 auto loop1 = MakePrimary();
2862 auto loop2 = Make("sender_loop");
2863
2864 auto loop3 = Make();
2865
2866 Fetcher<timing::Report> report_fetcher =
2867 loop3->MakeFetcher<timing::Report>("/aos");
2868 EXPECT_FALSE(report_fetcher.Fetch());
2869
2870 auto sender = loop2->MakeSender<TestMessage>("/test");
2871 auto fetcher1 = loop1->MakeFetcher<TestMessage>("/test");
2872 auto fetcher2 = loop1->MakeFetcher<TestMessage>("/test");
2873 fetcher1.Fetch();
2874 fetcher2.Fetch();
2875
2876 // Add a timer to actually quit.
2877 auto test_timer = loop1->AddTimer([&sender]() {
2878 for (int i = 0; i < 10; ++i) {
2879 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2880 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2881 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002882 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002883 }
2884 });
2885
2886 auto test_timer2 = loop1->AddTimer([&fetcher1, &fetcher2]() {
2887 fetcher1.Fetch();
2888 while (fetcher2.FetchNext()) {
2889 }
2890 });
2891
2892 // Quit after 1 timing report, mid way through the next cycle.
2893 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2894
2895 loop1->OnRun([test_timer, test_timer2, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002896 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1400));
2897 test_timer2->Schedule(loop1->monotonic_now() + chrono::milliseconds(1600));
Austin Schuh39788ff2019-12-01 18:22:57 -08002898 });
2899
2900 Run();
2901
Austin Schuh6bae8252021-02-07 22:01:49 -08002902 if (do_timing_reports() == DoTimingReports::kYes) {
2903 // And, since we are here, check that the timing report makes sense.
2904 // Start by looking for our event loop's timing.
2905 FlatbufferDetachedBuffer<timing::Report> primary_report =
2906 FlatbufferDetachedBuffer<timing::Report>::Empty();
2907 while (report_fetcher.FetchNext()) {
2908 if (report_fetcher->name()->string_view() == "primary") {
2909 primary_report = CopyFlatBuffer(report_fetcher.get());
2910 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002911 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002912
2913 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2914
2915 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2916
2917 ASSERT_NE(primary_report.message().senders(), nullptr);
2918 EXPECT_EQ(primary_report.message().senders()->size(), 2);
2919
2920 ASSERT_NE(primary_report.message().timers(), nullptr);
2921 EXPECT_EQ(primary_report.message().timers()->size(), 4);
2922
2923 // Make sure there are no phased loops or watchers.
2924 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2925 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2926
2927 // Now look at the fetchrs.
2928 ASSERT_NE(primary_report.message().fetchers(), nullptr);
2929 ASSERT_EQ(primary_report.message().fetchers()->size(), 2);
2930
2931 EXPECT_EQ(primary_report.message().fetchers()->Get(0)->count(), 1);
2932 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->average(),
2933 0.1);
2934 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->min(),
2935 0.1);
2936 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->max(),
2937 0.1);
2938 EXPECT_EQ(primary_report.message()
2939 .fetchers()
2940 ->Get(0)
2941 ->latency()
2942 ->standard_deviation(),
2943 0.0);
2944
2945 EXPECT_EQ(primary_report.message().fetchers()->Get(1)->count(), 10);
2946 } else {
2947 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002948 }
Austin Schuh52d325c2019-06-23 18:59:06 -07002949}
2950
Austin Schuh67420a42019-12-21 21:55:04 -08002951// Tests that a raw watcher and raw fetcher can receive messages from a raw
2952// sender without messing up offsets.
2953TEST_P(AbstractEventLoopTest, RawBasic) {
2954 auto loop1 = Make();
2955 auto loop2 = MakePrimary();
2956 auto loop3 = Make();
2957
Austin Schuha9df9ad2021-06-16 14:49:39 -07002958 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2959 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuh67420a42019-12-21 21:55:04 -08002960
2961 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002962 loop1->MakeRawSender(configuration::GetChannel(
2963 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08002964
2965 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002966 loop3->MakeRawFetcher(configuration::GetChannel(
2967 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08002968
Austin Schuha9df9ad2021-06-16 14:49:39 -07002969 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002970 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2971 RawSender::Error::kOk);
Austin Schuha9df9ad2021-06-16 14:49:39 -07002972 });
Austin Schuh67420a42019-12-21 21:55:04 -08002973
2974 bool happened = false;
2975 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08002976 configuration::GetChannel(loop2->configuration(), "/test",
2977 "aos.TestMessage", "", nullptr),
Austin Schuha9df9ad2021-06-16 14:49:39 -07002978 [this, &kMessage, &fetcher, &happened](const Context &context,
2979 const void *message) {
Austin Schuh67420a42019-12-21 21:55:04 -08002980 happened = true;
Austin Schuha9df9ad2021-06-16 14:49:39 -07002981 EXPECT_EQ(
2982 kMessage.span(),
2983 absl::Span<const uint8_t>(
2984 reinterpret_cast<const uint8_t *>(message), context.size));
2985 EXPECT_EQ(message, context.data);
Austin Schuh67420a42019-12-21 21:55:04 -08002986
2987 ASSERT_TRUE(fetcher->Fetch());
2988
Austin Schuha9df9ad2021-06-16 14:49:39 -07002989 EXPECT_EQ(kMessage.span(),
2990 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
2991 fetcher->context().data),
2992 fetcher->context().size));
Austin Schuh67420a42019-12-21 21:55:04 -08002993
2994 this->Exit();
2995 });
2996
2997 EXPECT_FALSE(happened);
2998 Run();
2999 EXPECT_TRUE(happened);
3000}
3001
Austin Schuhad154822019-12-27 15:45:13 -08003002// Tests that a raw watcher and raw fetcher can receive messages from a raw
Brian Silvermanbf889922021-11-10 12:41:57 -08003003// sender without messing up offsets, using the RawSpan overload.
3004TEST_P(AbstractEventLoopTest, RawBasicSharedSpan) {
3005 auto loop1 = Make();
3006 auto loop2 = MakePrimary();
3007 auto loop3 = Make();
3008
3009 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3010 JsonToFlatbuffer<TestMessage>("{}");
3011
3012 std::unique_ptr<aos::RawSender> sender =
3013 loop1->MakeRawSender(configuration::GetChannel(
3014 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
3015
3016 std::unique_ptr<aos::RawFetcher> fetcher =
3017 loop3->MakeRawFetcher(configuration::GetChannel(
3018 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
3019
3020 loop2->OnRun([&]() {
Austin Schuhe0ab4de2023-05-03 08:05:08 -07003021 auto shared_span = MakeSharedSpan(kMessage.span().size());
3022 memcpy(shared_span.second.data(), kMessage.span().data(),
3023 kMessage.span().size());
3024 sender->CheckOk(sender->Send(std::move(shared_span.first)));
Brian Silvermanbf889922021-11-10 12:41:57 -08003025 });
3026
3027 bool happened = false;
3028 loop2->MakeRawWatcher(
3029 configuration::GetChannel(loop2->configuration(), "/test",
3030 "aos.TestMessage", "", nullptr),
3031 [this, &kMessage, &fetcher, &happened](const Context &context,
3032 const void *message) {
3033 happened = true;
3034 EXPECT_EQ(
3035 kMessage.span(),
3036 absl::Span<const uint8_t>(
3037 reinterpret_cast<const uint8_t *>(message), context.size));
3038 EXPECT_EQ(message, context.data);
3039
3040 ASSERT_TRUE(fetcher->Fetch());
3041
3042 EXPECT_EQ(kMessage.span(),
3043 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
3044 fetcher->context().data),
3045 fetcher->context().size));
3046
3047 this->Exit();
3048 });
3049
3050 EXPECT_FALSE(happened);
3051 Run();
3052 EXPECT_TRUE(happened);
3053}
3054
3055// Tests that a raw watcher and raw fetcher can receive messages from a raw
Austin Schuhad154822019-12-27 15:45:13 -08003056// sender with remote times filled out.
3057TEST_P(AbstractEventLoopTest, RawRemoteTimes) {
3058 auto loop1 = Make();
3059 auto loop2 = MakePrimary();
3060 auto loop3 = Make();
3061
Austin Schuha9df9ad2021-06-16 14:49:39 -07003062 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3063 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08003064
3065 const aos::monotonic_clock::time_point monotonic_remote_time =
3066 aos::monotonic_clock::time_point(chrono::seconds(1501));
3067 const aos::realtime_clock::time_point realtime_remote_time =
3068 aos::realtime_clock::time_point(chrono::seconds(3132));
Austin Schuhb5c6f972021-03-14 21:53:07 -07003069 const uint32_t remote_queue_index = 0x254971;
Austin Schuha9012be2021-07-21 15:19:11 -07003070 const UUID source_boot_uuid = UUID::Random();
Austin Schuhad154822019-12-27 15:45:13 -08003071
3072 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003073 loop1->MakeRawSender(configuration::GetChannel(
3074 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08003075
3076 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003077 loop3->MakeRawFetcher(configuration::GetChannel(
3078 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08003079
3080 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07003081 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size(),
3082 monotonic_remote_time, realtime_remote_time,
3083 remote_queue_index, source_boot_uuid),
3084 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08003085 });
3086
3087 bool happened = false;
3088 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08003089 configuration::GetChannel(loop2->configuration(), "/test",
3090 "aos.TestMessage", "", nullptr),
Austin Schuha9012be2021-07-21 15:19:11 -07003091 [this, monotonic_remote_time, realtime_remote_time, source_boot_uuid,
Austin Schuhb5c6f972021-03-14 21:53:07 -07003092 remote_queue_index, &fetcher,
3093 &happened](const Context &context, const void * /*message*/) {
Austin Schuhad154822019-12-27 15:45:13 -08003094 happened = true;
3095 EXPECT_EQ(monotonic_remote_time, context.monotonic_remote_time);
3096 EXPECT_EQ(realtime_remote_time, context.realtime_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07003097 EXPECT_EQ(source_boot_uuid, context.source_boot_uuid);
Austin Schuhb5c6f972021-03-14 21:53:07 -07003098 EXPECT_EQ(remote_queue_index, context.remote_queue_index);
Austin Schuhad154822019-12-27 15:45:13 -08003099
3100 ASSERT_TRUE(fetcher->Fetch());
3101 EXPECT_EQ(monotonic_remote_time,
3102 fetcher->context().monotonic_remote_time);
3103 EXPECT_EQ(realtime_remote_time,
3104 fetcher->context().realtime_remote_time);
3105
3106 this->Exit();
3107 });
3108
3109 EXPECT_FALSE(happened);
3110 Run();
3111 EXPECT_TRUE(happened);
3112}
3113
3114// Tests that a raw sender fills out sent data.
3115TEST_P(AbstractEventLoopTest, RawSenderSentData) {
3116 auto loop1 = MakePrimary();
3117
Austin Schuha9df9ad2021-06-16 14:49:39 -07003118 const FlatbufferDetachedBuffer<TestMessage> kMessage =
3119 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08003120
3121 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08003122 loop1->MakeRawSender(configuration::GetChannel(
3123 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08003124
Tyler Chatow67ddb032020-01-12 14:30:04 -08003125 const aos::monotonic_clock::time_point monotonic_now = loop1->monotonic_now();
3126 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08003127
milind1f1dca32021-07-03 13:50:07 -07003128 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
3129 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08003130
3131 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
3132 EXPECT_LE(sender->monotonic_sent_time(),
3133 monotonic_now + chrono::milliseconds(100));
3134 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
3135 EXPECT_LE(sender->realtime_sent_time(),
3136 realtime_now + chrono::milliseconds(100));
3137 EXPECT_EQ(sender->sent_queue_index(), 0u);
3138
milind1f1dca32021-07-03 13:50:07 -07003139 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
3140 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08003141
3142 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
3143 EXPECT_LE(sender->monotonic_sent_time(),
3144 monotonic_now + chrono::milliseconds(100));
3145 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
3146 EXPECT_LE(sender->realtime_sent_time(),
3147 realtime_now + chrono::milliseconds(100));
3148 EXPECT_EQ(sender->sent_queue_index(), 1u);
3149}
3150
Austin Schuh217a9782019-12-21 23:02:50 -08003151// Tests that not setting up nodes results in no node.
3152TEST_P(AbstractEventLoopTest, NoNode) {
3153 auto loop1 = Make();
3154 auto loop2 = MakePrimary();
3155
3156 EXPECT_EQ(loop1->node(), nullptr);
3157 EXPECT_EQ(loop2->node(), nullptr);
3158}
3159
3160// Tests that setting up nodes results in node being set.
3161TEST_P(AbstractEventLoopTest, Node) {
3162 EnableNodes("me");
3163
3164 auto loop1 = Make();
3165 auto loop2 = MakePrimary();
3166
3167 EXPECT_NE(loop1->node(), nullptr);
3168 EXPECT_NE(loop2->node(), nullptr);
3169}
3170
3171// Tests that watchers work with a node setup.
3172TEST_P(AbstractEventLoopTest, NodeWatcher) {
3173 EnableNodes("me");
3174
3175 auto loop1 = Make();
3176 auto loop2 = Make();
3177 loop1->MakeWatcher("/test", [](const TestMessage &) {});
Tyler Chatow67ddb032020-01-12 14:30:04 -08003178 loop2->MakeRawWatcher(
3179 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
3180 nullptr),
3181 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08003182}
3183
Brian Silverman454bc112020-03-05 14:21:25 -08003184// Tests that no-arg watchers work with a node setup.
3185TEST_P(AbstractEventLoopTest, NodeNoArgWatcher) {
3186 EnableNodes("me");
3187
3188 auto loop1 = Make();
3189 auto loop2 = Make();
3190 loop1->MakeWatcher("/test", [](const TestMessage &) {});
3191 loop2->MakeRawNoArgWatcher(
3192 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
3193 nullptr),
3194 [](const Context &) {});
3195}
3196
Austin Schuh217a9782019-12-21 23:02:50 -08003197// Tests that fetcher work with a node setup.
3198TEST_P(AbstractEventLoopTest, NodeFetcher) {
3199 EnableNodes("me");
3200 auto loop1 = Make();
3201
3202 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
Tyler Chatow67ddb032020-01-12 14:30:04 -08003203 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
3204 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08003205}
3206
3207// Tests that sender work with a node setup.
3208TEST_P(AbstractEventLoopTest, NodeSender) {
3209 EnableNodes("me");
3210 auto loop1 = Make();
3211
3212 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
3213}
3214
Austin Schuhcc6070c2020-10-10 20:25:56 -07003215// Tests that a non-realtime event loop timer is marked non-realtime.
3216TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopTimer) {
3217 auto loop1 = MakePrimary();
3218
3219 // Add a timer to actually quit.
3220 auto test_timer = loop1->AddTimer([this]() {
3221 CheckNotRealtime();
3222 this->Exit();
3223 });
3224
3225 loop1->OnRun([&test_timer, &loop1]() {
3226 CheckNotRealtime();
Philipp Schradera6712522023-07-05 20:25:11 -07003227 test_timer->Schedule(loop1->monotonic_now(),
3228 ::std::chrono::milliseconds(100));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003229 });
3230
3231 Run();
3232}
3233
3234// Tests that a realtime event loop timer is marked realtime.
Austin Schuh9b1d6282022-06-10 17:03:21 -07003235TEST_P(AbstractEventLoopTest, RealtimeSend) {
3236 auto loop1 = MakePrimary();
3237
3238 loop1->SetRuntimeRealtimePriority(1);
3239
3240 auto sender = loop1->MakeSender<TestMessage>("/test2");
3241
3242 loop1->OnRun([&]() {
3243 CheckRealtime();
3244
3245 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3246 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
3247 builder.add_value(200);
3248 msg.CheckOk(msg.Send(builder.Finish()));
3249
3250 this->Exit();
3251 });
3252
3253 Run();
3254}
3255
3256// Tests that a realtime event loop timer is marked realtime.
Austin Schuhcc6070c2020-10-10 20:25:56 -07003257TEST_P(AbstractEventLoopTest, RealtimeEventLoopTimer) {
3258 auto loop1 = MakePrimary();
3259
3260 loop1->SetRuntimeRealtimePriority(1);
3261
3262 // Add a timer to actually quit.
3263 auto test_timer = loop1->AddTimer([this]() {
3264 CheckRealtime();
3265 this->Exit();
3266 });
3267
3268 loop1->OnRun([&test_timer, &loop1]() {
3269 CheckRealtime();
Philipp Schradera6712522023-07-05 20:25:11 -07003270 test_timer->Schedule(loop1->monotonic_now(),
3271 ::std::chrono::milliseconds(100));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003272 });
3273
3274 Run();
3275}
3276
3277// Tests that a non-realtime event loop phased loop is marked non-realtime.
3278TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopPhasedLoop) {
3279 auto loop1 = MakePrimary();
3280
3281 // Add a timer to actually quit.
3282 loop1->AddPhasedLoop(
3283 [this](int) {
3284 CheckNotRealtime();
3285 this->Exit();
3286 },
3287 chrono::seconds(1), chrono::seconds(0));
3288
3289 Run();
3290}
3291
3292// Tests that a realtime event loop phased loop is marked realtime.
3293TEST_P(AbstractEventLoopTest, RealtimeEventLoopPhasedLoop) {
3294 auto loop1 = MakePrimary();
3295
3296 loop1->SetRuntimeRealtimePriority(1);
3297
3298 // Add a timer to actually quit.
3299 loop1->AddPhasedLoop(
3300 [this](int) {
3301 CheckRealtime();
3302 this->Exit();
3303 },
3304 chrono::seconds(1), chrono::seconds(0));
3305
3306 Run();
3307}
3308
3309// Tests that a non-realtime event loop watcher is marked non-realtime.
3310TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopWatcher) {
3311 auto loop1 = MakePrimary();
3312 auto loop2 = Make();
3313
3314 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
3315
3316 loop1->OnRun([&]() {
3317 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3318 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07003319 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003320 });
3321
3322 loop1->MakeWatcher("/test", [&](const TestMessage &) {
3323 CheckNotRealtime();
3324 this->Exit();
3325 });
3326
3327 Run();
3328}
3329
3330// Tests that a realtime event loop watcher is marked realtime.
3331TEST_P(AbstractEventLoopTest, RealtimeEventLoopWatcher) {
3332 auto loop1 = MakePrimary();
3333 auto loop2 = Make();
3334
3335 loop1->SetRuntimeRealtimePriority(1);
3336
3337 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
3338
3339 loop1->OnRun([&]() {
3340 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3341 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07003342 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003343 });
3344
3345 loop1->MakeWatcher("/test", [&](const TestMessage &) {
3346 CheckRealtime();
3347 this->Exit();
3348 });
3349
3350 Run();
3351}
3352
Austin Schuha9012be2021-07-21 15:19:11 -07003353// Tests that event loop's context's monotonic time is set to a value on OnRun.
3354TEST_P(AbstractEventLoopTest, SetContextOnRun) {
3355 auto loop = MakePrimary();
3356
Austin Schuh0debde12022-08-17 16:25:17 -07003357 EXPECT_EQ(loop->context().monotonic_event_time, monotonic_clock::min_time);
3358 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3359 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3360 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3361 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3362 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
3363 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
3364 EXPECT_EQ(loop->context().size, 0u);
3365 EXPECT_EQ(loop->context().data, nullptr);
3366 EXPECT_EQ(loop->context().buffer_index, -1);
3367
Austin Schuha9012be2021-07-21 15:19:11 -07003368 // We want to check that monotonic event time is before monotonic now
3369 // called inside of callback, but after time point obtained callback.
3370 aos::monotonic_clock::time_point monotonic_event_time_on_run;
3371
3372 loop->OnRun([&]() {
3373 monotonic_event_time_on_run = loop->context().monotonic_event_time;
3374 EXPECT_LE(monotonic_event_time_on_run, loop->monotonic_now());
3375 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3376 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3377 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3378 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3379 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
Austin Schuh0debde12022-08-17 16:25:17 -07003380 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
Austin Schuha9012be2021-07-21 15:19:11 -07003381 EXPECT_EQ(loop->context().size, 0u);
3382 EXPECT_EQ(loop->context().data, nullptr);
3383 EXPECT_EQ(loop->context().buffer_index, -1);
3384 });
3385
3386 EndEventLoop(loop.get(), ::std::chrono::milliseconds(200));
3387
3388 const aos::monotonic_clock::time_point before_run_time =
3389 loop->monotonic_now();
3390 Run();
3391 EXPECT_GE(monotonic_event_time_on_run, before_run_time);
Austin Schuh0debde12022-08-17 16:25:17 -07003392
3393 EXPECT_EQ(loop->context().monotonic_event_time, monotonic_clock::min_time);
3394 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3395 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3396 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3397 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3398 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
3399 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
3400 EXPECT_EQ(loop->context().size, 0u);
3401 EXPECT_EQ(loop->context().data, nullptr);
3402 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuha9012be2021-07-21 15:19:11 -07003403}
3404
Austin Schuh217a9782019-12-21 23:02:50 -08003405// Tests that watchers fail when created on the wrong node.
3406TEST_P(AbstractEventLoopDeathTest, NodeWatcher) {
3407 EnableNodes("them");
3408
3409 auto loop1 = Make();
3410 auto loop2 = Make();
3411 EXPECT_DEATH({ loop1->MakeWatcher("/test", [](const TestMessage &) {}); },
3412 "node");
3413 EXPECT_DEATH(
3414 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08003415 loop2->MakeRawWatcher(
3416 configuration::GetChannel(configuration(), "/test",
3417 "aos.TestMessage", "", nullptr),
3418 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08003419 },
3420 "node");
Brian Silverman454bc112020-03-05 14:21:25 -08003421 EXPECT_DEATH({ loop1->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
3422 "node");
3423 EXPECT_DEATH(
3424 {
3425 loop2->MakeRawNoArgWatcher(
3426 configuration::GetChannel(configuration(), "/test",
3427 "aos.TestMessage", "", nullptr),
3428 [](const Context &) {});
3429 },
3430 "node");
Austin Schuh217a9782019-12-21 23:02:50 -08003431}
3432
3433// Tests that fetchers fail when created on the wrong node.
3434TEST_P(AbstractEventLoopDeathTest, NodeFetcher) {
3435 EnableNodes("them");
3436 auto loop1 = Make();
3437
3438 EXPECT_DEATH({ auto fetcher = loop1->MakeFetcher<TestMessage>("/test"); },
3439 "node");
3440 EXPECT_DEATH(
3441 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08003442 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
3443 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08003444 },
3445 "node");
3446}
3447
3448// Tests that senders fail when created on the wrong node.
3449TEST_P(AbstractEventLoopDeathTest, NodeSender) {
3450 EnableNodes("them");
3451 auto loop1 = Make();
3452
3453 EXPECT_DEATH(
3454 {
3455 aos::Sender<TestMessage> sender =
3456 loop1->MakeSender<TestMessage>("/test");
3457 },
3458 "node");
3459
3460 // Note: Creating raw senders is always supported. Right now, this lets us
3461 // use them to create message_gateway.
3462}
3463
Brian Silverman341b57e2020-06-23 16:23:18 -07003464// Tests creating multiple Builders from a single Sender at the same time.
3465TEST_P(AbstractEventLoopDeathTest, MultipleBuilders) {
3466 auto loop1 = Make();
3467 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
3468
3469 { auto builder = sender.MakeBuilder(); }
3470 {
3471 auto builder = sender.MakeBuilder();
3472 builder.MakeBuilder<TestMessage>().Finish();
3473 }
3474 {
3475 // Creating this after the first one was destroyed should be fine.
3476 auto builder = sender.MakeBuilder();
3477 builder.MakeBuilder<TestMessage>().Finish();
3478 // But not a second one.
3479 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
James Kuszmaulb1c11052023-11-06 13:20:53 -08003480 "May not have multiple active allocators");
Brian Silverman341b57e2020-06-23 16:23:18 -07003481 }
3482
3483 FlatbufferDetachedBuffer<TestMessage> detached =
3484 flatbuffers::DetachedBuffer();
3485 {
3486 auto builder = sender.MakeBuilder();
3487 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
3488 }
3489 {
3490 // This is the second one, after the detached one, so it should fail.
3491 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
James Kuszmaulb1c11052023-11-06 13:20:53 -08003492 "May not have multiple active allocators");
Brian Silverman341b57e2020-06-23 16:23:18 -07003493 }
3494
3495 // Clear the detached one, and then we should be able to create another.
3496 detached = flatbuffers::DetachedBuffer();
3497 {
3498 auto builder = sender.MakeBuilder();
3499 builder.MakeBuilder<TestMessage>().Finish();
3500 }
3501
3502 // And then detach another one.
3503 {
3504 auto builder = sender.MakeBuilder();
3505 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
3506 }
3507}
3508
3509// Tests sending a buffer detached from a different builder.
3510TEST_P(AbstractEventLoopDeathTest, WrongDetachedBuffer) {
3511 auto loop1 = Make();
3512 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
3513 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
3514
3515 auto builder = sender1.MakeBuilder();
3516 FlatbufferDetachedBuffer<TestMessage> detached =
3517 builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
milind1f1dca32021-07-03 13:50:07 -07003518 EXPECT_DEATH(sender2.CheckOk(sender2.SendDetached(std::move(detached))),
Brian Silverman341b57e2020-06-23 16:23:18 -07003519 "May only send the buffer detached from this Sender");
3520}
3521
James Kuszmaul762e8692023-07-31 14:57:53 -07003522// Tests that senders fail when created on the wrong node.
3523TEST_P(AbstractEventLoopDeathTest, SetVersionWhileRunning) {
3524 auto loop1 = MakePrimary();
3525
3526 loop1->OnRun([&loop1, this]() {
3527 EXPECT_DEATH({ loop1->SetVersionString("abcdef"); },
3528 "timing report while running");
3529 Exit();
3530 });
3531
3532 Run();
3533}
3534
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003535int TestChannelFrequency(EventLoop *event_loop) {
3536 return event_loop->GetChannel<TestMessage>("/test")->frequency();
3537}
3538
3539int TestChannelQueueSize(EventLoop *event_loop) {
Austin Schuhfff9c3a2023-06-16 18:48:23 -07003540 return configuration::QueueSize(event_loop->configuration(),
3541 event_loop->GetChannel<TestMessage>("/test"));
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003542}
3543
3544RawSender::Error SendTestMessage(aos::Sender<TestMessage> &sender) {
3545 aos::Sender<TestMessage>::Builder builder = sender.MakeBuilder();
3546 TestMessage::Builder test_message_builder =
3547 builder.MakeBuilder<TestMessage>();
3548 test_message_builder.add_value(0);
3549 return builder.Send(test_message_builder.Finish());
3550}
3551
3552// Test that sending messages too fast returns
3553// RawSender::Error::kMessagesSentTooFast.
3554TEST_P(AbstractEventLoopTest, SendingMessagesTooFast) {
3555 auto event_loop = MakePrimary();
Austin Schuh63756be2024-02-05 19:51:20 -08003556 event_loop->SetRuntimeRealtimePriority(5);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003557
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
Austin Schuh63756be2024-02-05 19:51:20 -08003571 const int messages_per_ms = 2;
3572 const auto kRepeatOffset = std::chrono::milliseconds(10);
3573 const auto base_offset =
3574 configuration::ChannelStorageDuration(event_loop->configuration(),
3575 sender.channel()) -
3576 (std::chrono::milliseconds(1) * (queue_size / 2) / messages_per_ms);
3577
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003578 const auto timer = event_loop->AddTimer([&]() {
Austin Schuh63756be2024-02-05 19:51:20 -08003579 // Send in bursts to reduce scheduler load to make the test more
3580 // reproducible.
3581 for (int i = 0; i < messages_per_ms * kRepeatOffset.count(); ++i) {
3582 const bool done = (msgs_sent == queue_size + 1);
3583 ASSERT_EQ(SendTestMessage(sender),
3584 done ? RawSender::Error::kMessagesSentTooFast
3585 : RawSender::Error::kOk);
3586 msgs_sent++;
3587 if (done) {
3588 Exit();
3589 return;
3590 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003591 }
3592 });
3593
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003594 event_loop->OnRun([&event_loop, &timer, &base_offset, &kRepeatOffset]() {
Philipp Schradera6712522023-07-05 20:25:11 -07003595 timer->Schedule(event_loop->monotonic_now() + base_offset, kRepeatOffset);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003596 });
3597
3598 Run();
3599}
3600
3601// Tests that we are able to send messages successfully after sending messages
3602// too fast and waiting while continuously attempting to send messages.
3603// Also tests that SendFailureCounter is working correctly in this
3604// situation
3605TEST_P(AbstractEventLoopTest, SendingAfterSendingTooFast) {
3606 auto event_loop = MakePrimary();
Austin Schuh63756be2024-02-05 19:51:20 -08003607 event_loop->SetRuntimeRealtimePriority(5);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003608
3609 auto sender = event_loop->MakeSender<TestMessage>("/test");
3610
Austin Schuh0e96d372023-05-08 10:10:21 -07003611 // We are sending bunches of messages at 100 Hz, so we will be sending too
3612 // fast after queue_size (800) ms. After this, keep sending messages, and
3613 // exactly a channel storage duration (2s) after we send the first message we
3614 // should be able to successfully send a message.
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003615
Austin Schuh0e96d372023-05-08 10:10:21 -07003616 const std::chrono::milliseconds kInterval = std::chrono::milliseconds(10);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003617 const monotonic_clock::duration channel_storage_duration =
Austin Schuhfff9c3a2023-06-16 18:48:23 -07003618 configuration::ChannelStorageDuration(event_loop->configuration(),
3619 sender.channel());
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003620 const int queue_size = TestChannelQueueSize(event_loop.get());
3621
3622 int msgs_sent = 0;
3623 SendFailureCounter counter;
3624 auto start = monotonic_clock::min_time;
3625
3626 event_loop->AddPhasedLoop(
Austin Schuh0e96d372023-05-08 10:10:21 -07003627 [&](int elapsed_cycles) {
3628 // The queue is setup for 800 messages/sec. We want to fill that up at
3629 // a rate of 2000 messages/sec so we make sure we fill it up.
3630 for (int i = 0; i < 2 * kInterval.count() * elapsed_cycles; ++i) {
3631 const auto actual_err = SendTestMessage(sender);
3632 const bool done_waiting = (start != monotonic_clock::min_time &&
3633 sender.monotonic_sent_time() >=
3634 (start + channel_storage_duration));
3635 const auto expected_err =
3636 (msgs_sent < queue_size || done_waiting
3637 ? RawSender::Error::kOk
3638 : RawSender::Error::kMessagesSentTooFast);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003639
Austin Schuh0e96d372023-05-08 10:10:21 -07003640 if (start == monotonic_clock::min_time) {
3641 start = sender.monotonic_sent_time();
3642 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003643
Austin Schuh0e96d372023-05-08 10:10:21 -07003644 ASSERT_EQ(actual_err, expected_err);
3645 counter.Count(actual_err);
3646 msgs_sent++;
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003647
Austin Schuh0e96d372023-05-08 10:10:21 -07003648 EXPECT_EQ(counter.failures(),
3649 msgs_sent <= queue_size
3650 ? 0
3651 : (msgs_sent - queue_size) -
3652 (actual_err == RawSender::Error::kOk ? 1 : 0));
3653 EXPECT_EQ(counter.just_failed(), actual_err != RawSender::Error::kOk);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003654
Austin Schuh0e96d372023-05-08 10:10:21 -07003655 if (done_waiting) {
3656 Exit();
3657 return;
3658 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003659 }
3660 },
3661 kInterval);
3662 Run();
3663}
3664
3665// Tests that RawSender::Error::kMessagesSentTooFast is returned
3666// when messages are sent too fast from senders in different loops
3667TEST_P(AbstractEventLoopTest, SendingTooFastWithMultipleLoops) {
3668 auto loop1 = MakePrimary();
3669 auto loop2 = Make();
3670
3671 auto sender1 = loop1->MakeSender<TestMessage>("/test");
3672 auto sender2 = loop2->MakeSender<TestMessage>("/test");
3673
3674 // Send queue_size messages split between the senders.
3675 const int queue_size = TestChannelQueueSize(loop1.get());
3676 for (int i = 0; i < queue_size / 2; i++) {
3677 ASSERT_EQ(SendTestMessage(sender1), RawSender::Error::kOk);
3678 ASSERT_EQ(SendTestMessage(sender2), RawSender::Error::kOk);
3679 }
3680
3681 // Since queue_size messages have been sent, this should return an error
3682 EXPECT_EQ(SendTestMessage(sender2), RawSender::Error::kMessagesSentTooFast);
3683}
3684
Austin Schuhdda6db72023-06-21 17:02:34 -07003685// Tests that a longer storage durations store more messages.
3686TEST_P(AbstractEventLoopTest, SendingTooFastWithLongDuration) {
3687 auto loop1 = MakePrimary();
3688
3689 auto sender1 = loop1->MakeSender<TestMessage>("/test3");
3690
3691 // Send queue_size messages split between the senders.
3692 const int queue_size =
3693 configuration::QueueSize(loop1->configuration(), sender1.channel());
3694 EXPECT_EQ(queue_size, 100 * 10);
3695 for (int i = 0; i < queue_size; i++) {
3696 ASSERT_EQ(SendTestMessage(sender1), RawSender::Error::kOk);
3697 }
3698
3699 // Since queue_size messages have been sent, and little time has elapsed,
3700 // this should return an error.
3701 EXPECT_EQ(SendTestMessage(sender1), RawSender::Error::kMessagesSentTooFast);
3702}
3703
Stephan Pleinesf63bde82024-01-13 15:59:33 -08003704} // namespace aos::testing