blob: 0d7794ebfb8add60b0852c080f7e8175c69cc5a1 [file] [log] [blame]
Alex Perrycb7da4b2019-08-28 19:35:56 -07001#include "aos/events/event_loop_param_test.h"
Parker Schuhe4a70d62017-12-27 20:10:20 -08002
Austin Schuh52d325c2019-06-23 18:59:06 -07003#include <chrono>
Brian Silverman4f4e0612020-08-12 19:54:41 -07004#include <unordered_map>
5#include <unordered_set>
Austin Schuh52d325c2019-06-23 18:59:06 -07006
Philipp Schrader790cb542023-07-05 21:06:52 -07007#include "glog/logging.h"
8#include "gmock/gmock.h"
9#include "gtest/gtest.h"
10
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -070011#include "aos/events/test_message_generated.h"
Austin Schuh54cf95f2019-11-29 13:14:18 -080012#include "aos/flatbuffer_merge.h"
Austin Schuhad9e5eb2021-11-19 20:33:55 -080013#include "aos/logging/log_message_generated.h"
14#include "aos/logging/logging.h"
Austin Schuhcc6070c2020-10-10 20:25:56 -070015#include "aos/realtime.h"
Austin Schuh9fe68f72019-08-10 19:32:03 -070016
Parker Schuhe4a70d62017-12-27 20:10:20 -080017namespace aos {
18namespace testing {
Austin Schuh52d325c2019-06-23 18:59:06 -070019namespace {
20namespace chrono = ::std::chrono;
21} // namespace
Parker Schuhe4a70d62017-12-27 20:10:20 -080022
Brian Silverman4f4e0612020-08-12 19:54:41 -070023::std::unique_ptr<EventLoop> AbstractEventLoopTest::Make(
24 std::string_view name) {
25 std::string name_copy(name);
26 if (name == "") {
27 name_copy = "loop";
28 name_copy += std::to_string(event_loop_count_);
29 }
30 ++event_loop_count_;
Austin Schuh6bae8252021-02-07 22:01:49 -080031 auto result = factory_->Make(name_copy);
32 if (do_timing_reports() == DoTimingReports::kNo) {
33 result->SkipTimingReport();
34 }
35 return result;
Brian Silverman4f4e0612020-08-12 19:54:41 -070036}
37
38void AbstractEventLoopTest::VerifyBuffers(
39 int number_buffers,
40 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>> fetchers,
41 std::vector<std::reference_wrapper<const Sender<TestMessage>>> senders) {
42 // The buffers which are in a sender.
43 std::unordered_set<int> in_sender;
44 for (const Sender<TestMessage> &sender : senders) {
45 const int this_buffer = sender.buffer_index();
46 CHECK_GE(this_buffer, 0);
47 CHECK_LT(this_buffer, number_buffers);
48 CHECK(in_sender.insert(this_buffer).second) << ": " << this_buffer;
49 }
50
51 if (read_method() != ReadMethod::PIN) {
52 // If we're not using PIN, we can't really verify anything about what
53 // buffers the fetchers have.
54 return;
55 }
56
57 // Mapping from TestMessage::value to buffer index.
58 std::unordered_map<int, int> fetcher_values;
59 for (const Fetcher<TestMessage> &fetcher : fetchers) {
60 if (!fetcher.get()) {
61 continue;
62 }
63 const int this_buffer = fetcher.context().buffer_index;
64 CHECK_GE(this_buffer, 0);
65 CHECK_LT(this_buffer, number_buffers);
66 CHECK(in_sender.count(this_buffer) == 0) << ": " << this_buffer;
67 const auto insert_result = fetcher_values.insert(
68 std::make_pair(fetcher.get()->value(), this_buffer));
69 if (!insert_result.second) {
70 CHECK_EQ(this_buffer, insert_result.first->second);
71 }
72 }
73}
74
Austin Schuh6b6dfa52019-06-12 20:16:20 -070075// Tests that watcher can receive messages from a sender.
Parker Schuhe4a70d62017-12-27 20:10:20 -080076// Also tests that OnRun() works.
77TEST_P(AbstractEventLoopTest, Basic) {
78 auto loop1 = Make();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070079 auto loop2 = MakePrimary();
80
Alex Perrycb7da4b2019-08-28 19:35:56 -070081 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
Austin Schuh6b6dfa52019-06-12 20:16:20 -070082
83 bool happened = false;
84
85 loop2->OnRun([&]() {
86 happened = true;
87
Alex Perrycb7da4b2019-08-28 19:35:56 -070088 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
89 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
90 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -070091 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -070092 });
93
94 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070095 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -070096 this->Exit();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070097 });
98
99 EXPECT_FALSE(happened);
100 Run();
101 EXPECT_TRUE(happened);
102}
103
Brian Silverman341b57e2020-06-23 16:23:18 -0700104// Tests that watcher can receive messages from a sender, sent via SendDetached.
105TEST_P(AbstractEventLoopTest, BasicSendDetached) {
106 auto loop1 = Make();
107 auto loop2 = MakePrimary();
108
109 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
110
111 FlatbufferDetachedBuffer<TestMessage> detached =
112 flatbuffers::DetachedBuffer();
113 {
114 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
115 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
116 builder.add_value(100);
117 detached = msg.Detach(builder.Finish());
118 }
119 detached = flatbuffers::DetachedBuffer();
120 {
121 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
122 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
123 builder.add_value(200);
124 detached = msg.Detach(builder.Finish());
125 }
milind1f1dca32021-07-03 13:50:07 -0700126 sender.CheckOk(sender.SendDetached(std::move(detached)));
Brian Silverman341b57e2020-06-23 16:23:18 -0700127
128 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
129 ASSERT_TRUE(fetcher.Fetch());
130 EXPECT_EQ(fetcher->value(), 200);
131}
132
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800133// Verifies that a no-arg watcher will not have a data pointer.
134TEST_P(AbstractEventLoopTest, NoArgNoData) {
135 auto loop1 = Make();
136 auto loop2 = MakePrimary();
137
138 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
139
140 bool happened = false;
141
142 loop2->OnRun([&]() {
143 happened = true;
144
145 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
146 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -0700147 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800148 });
149
150 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
151 EXPECT_GT(loop2->context().size, 0u);
152 EXPECT_EQ(nullptr, loop2->context().data);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700153 EXPECT_EQ(-1, loop2->context().buffer_index);
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800154 this->Exit();
155 });
156
157 EXPECT_FALSE(happened);
158 Run();
159 EXPECT_TRUE(happened);
160}
161
Brian Silverman454bc112020-03-05 14:21:25 -0800162// Tests that no-arg watcher can receive messages from a sender.
163// Also tests that OnRun() works.
164TEST_P(AbstractEventLoopTest, BasicNoArg) {
165 auto loop1 = Make();
166 auto loop2 = MakePrimary();
167
168 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
169
170 bool happened = false;
171
172 loop2->OnRun([&]() {
173 happened = true;
174
175 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
176 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
177 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700178 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -0800179 });
180
181 aos::Fetcher<TestMessage> fetcher = loop2->MakeFetcher<TestMessage>("/test");
182 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
183 ASSERT_TRUE(fetcher.Fetch());
184 EXPECT_EQ(fetcher->value(), 200);
185 this->Exit();
186 });
187
188 EXPECT_FALSE(happened);
189 Run();
190 EXPECT_TRUE(happened);
191}
192
193// Tests that a watcher can be created with an std::function.
194TEST_P(AbstractEventLoopTest, BasicFunction) {
195 auto loop1 = Make();
196 auto loop2 = MakePrimary();
197
198 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
199
200 bool happened = false;
201
202 loop2->OnRun([&]() {
203 happened = true;
204
205 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
206 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
207 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700208 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -0800209 });
210
211 loop2->MakeWatcher("/test", std::function<void(const TestMessage &)>(
212 [&](const TestMessage &message) {
213 EXPECT_EQ(message.value(), 200);
214 this->Exit();
215 }));
216
217 EXPECT_FALSE(happened);
218 Run();
219 EXPECT_TRUE(happened);
220}
221
Brian Silverman0fc69932020-01-24 21:54:02 -0800222// Tests that watcher can receive messages from two senders.
223// Also tests that OnRun() works.
224TEST_P(AbstractEventLoopTest, BasicTwoSenders) {
225 auto loop1 = Make();
226 auto loop2 = MakePrimary();
227
228 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
229 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
230
231 bool happened = false;
232
233 loop2->OnRun([&]() {
234 happened = true;
235
236 {
237 aos::Sender<TestMessage>::Builder msg = sender1.MakeBuilder();
238 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
239 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700240 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman0fc69932020-01-24 21:54:02 -0800241 }
242 {
243 aos::Sender<TestMessage>::Builder msg = sender2.MakeBuilder();
244 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
245 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700246 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman0fc69932020-01-24 21:54:02 -0800247 }
248 });
249
250 int messages_received = 0;
251 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
252 EXPECT_EQ(message.value(), 200);
253 this->Exit();
254 ++messages_received;
255 });
256
257 EXPECT_FALSE(happened);
258 Run();
259 EXPECT_TRUE(happened);
260 EXPECT_EQ(messages_received, 2);
261}
262
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700263// Tests that a fetcher can fetch from a sender.
264// Also tests that OnRun() works.
265TEST_P(AbstractEventLoopTest, FetchWithoutRun) {
266 auto loop1 = Make();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800267 auto loop2 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -0700268 auto loop3 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800269
270 auto sender = loop1->MakeSender<TestMessage>("/test");
271
272 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
273
Austin Schuhbbce72d2019-05-26 15:11:46 -0700274 EXPECT_FALSE(fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -0800275 EXPECT_EQ(fetcher.get(), nullptr);
276
Austin Schuhad154822019-12-27 15:45:13 -0800277 EXPECT_EQ(fetcher.context().monotonic_event_time, monotonic_clock::min_time);
278 EXPECT_EQ(fetcher.context().monotonic_remote_time, monotonic_clock::min_time);
279 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
280 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -0700281 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
Austin Schuh39788ff2019-12-01 18:22:57 -0800282 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
283 EXPECT_EQ(fetcher.context().size, 0u);
284 EXPECT_EQ(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700285 EXPECT_EQ(fetcher.context().buffer_index, -1);
Austin Schuhbbce72d2019-05-26 15:11:46 -0700286
Alex Perrycb7da4b2019-08-28 19:35:56 -0700287 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
288 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
289 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700290 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700291
292 EXPECT_TRUE(fetcher.Fetch());
293 ASSERT_FALSE(fetcher.get() == nullptr);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700294 EXPECT_EQ(fetcher.get()->value(), 200);
Austin Schuh39788ff2019-12-01 18:22:57 -0800295
296 const chrono::milliseconds kEpsilon(100);
297
Austin Schuhad154822019-12-27 15:45:13 -0800298 const aos::monotonic_clock::time_point monotonic_now = loop2->monotonic_now();
299 const aos::realtime_clock::time_point realtime_now = loop2->realtime_now();
300 EXPECT_EQ(fetcher.context().monotonic_event_time,
301 fetcher.context().monotonic_remote_time);
302 EXPECT_EQ(fetcher.context().realtime_event_time,
303 fetcher.context().realtime_remote_time);
304
305 EXPECT_GE(fetcher.context().monotonic_event_time, monotonic_now - kEpsilon);
306 EXPECT_LE(fetcher.context().monotonic_event_time, monotonic_now + kEpsilon);
307 EXPECT_GE(fetcher.context().realtime_event_time, realtime_now - kEpsilon);
308 EXPECT_LE(fetcher.context().realtime_event_time, realtime_now + kEpsilon);
Austin Schuha9012be2021-07-21 15:19:11 -0700309 EXPECT_EQ(fetcher.context().source_boot_uuid, loop2->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -0800310 EXPECT_EQ(fetcher.context().queue_index, 0x0u);
311 EXPECT_EQ(fetcher.context().size, 20u);
312 EXPECT_NE(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700313 if (read_method() == ReadMethod::PIN) {
314 EXPECT_GE(fetcher.context().buffer_index, 0);
315 EXPECT_LT(fetcher.context().buffer_index,
316 loop2->NumberBuffers(fetcher.channel()));
317 } else {
318 EXPECT_EQ(fetcher.context().buffer_index, -1);
319 }
Parker Schuhe4a70d62017-12-27 20:10:20 -0800320}
321
Austin Schuh3578a2e2019-05-25 18:17:59 -0700322// Tests that watcher will receive all messages sent if they are sent after
323// initialization and before running.
324TEST_P(AbstractEventLoopTest, DoubleSendAtStartup) {
325 auto loop1 = Make();
326 auto loop2 = MakePrimary();
327
328 auto sender = loop1->MakeSender<TestMessage>("/test");
329
330 ::std::vector<int> values;
331
332 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700333 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700334 if (values.size() == 2) {
Austin Schuh9fe68f72019-08-10 19:32:03 -0700335 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -0700336 }
337 });
338
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700339 // Before Run, should be ignored.
Austin Schuh3578a2e2019-05-25 18:17:59 -0700340 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700341 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
342 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
343 builder.add_value(199);
milind1f1dca32021-07-03 13:50:07 -0700344 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700345 }
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700346
347 loop2->OnRun([&]() {
348 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700349 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
350 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
351 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700352 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700353 }
354 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700355 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
356 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
357 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700358 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700359 }
360 });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700361
362 Run();
363
364 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
365}
366
367// Tests that watcher will not receive messages sent before the watcher is
368// created.
369TEST_P(AbstractEventLoopTest, DoubleSendAfterStartup) {
370 auto loop1 = Make();
371 auto loop2 = MakePrimary();
372
373 auto sender = loop1->MakeSender<TestMessage>("/test");
374
375 ::std::vector<int> values;
376
377 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700378 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
379 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
380 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700381 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700382 }
383 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700384 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
385 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
386 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700387 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700388 }
389
390 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700391 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700392 });
393
394 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700395 auto test_timer = loop2->AddTimer([this]() { this->Exit(); });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700396 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700397 test_timer->Schedule(loop2->monotonic_now(),
398 ::std::chrono::milliseconds(100));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700399 });
400
401 Run();
402 EXPECT_EQ(0, values.size());
403}
404
Austin Schuhbbce72d2019-05-26 15:11:46 -0700405// Tests that FetchNext gets all the messages sent after it is constructed.
406TEST_P(AbstractEventLoopTest, FetchNext) {
407 auto loop1 = Make();
408 auto loop2 = MakePrimary();
409
410 auto sender = loop1->MakeSender<TestMessage>("/test");
411 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
412
413 ::std::vector<int> values;
414
415 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700416 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
417 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
418 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700419 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700420 }
421 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700422 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
423 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
424 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700425 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700426 }
427
428 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700429 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700430 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700431 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700432 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700433 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700434 });
435
436 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700437 test_timer->Schedule(loop2->monotonic_now(),
438 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700439 });
440
441 Run();
442 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
443}
444
445// Tests that FetchNext gets no messages sent before it is constructed.
446TEST_P(AbstractEventLoopTest, FetchNextAfterSend) {
447 auto loop1 = Make();
448 auto loop2 = MakePrimary();
449
450 auto sender = loop1->MakeSender<TestMessage>("/test");
451
452 ::std::vector<int> values;
453
454 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700455 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
456 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
457 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700458 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700459 }
460 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700461 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
462 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
463 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700464 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700465 }
466
467 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
468
469 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700470 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700471 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700472 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700473 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700474 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700475 });
476
477 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700478 test_timer->Schedule(loop2->monotonic_now(),
479 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700480 });
481
482 Run();
483 EXPECT_THAT(0, values.size());
484}
485
486// Tests that Fetch returns the last message created before the loop was
487// started.
488TEST_P(AbstractEventLoopTest, FetchDataFromBeforeCreation) {
489 auto loop1 = Make();
490 auto loop2 = MakePrimary();
491
492 auto sender = loop1->MakeSender<TestMessage>("/test");
493
494 ::std::vector<int> values;
495
496 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700497 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
498 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
499 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700500 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700501 }
502 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700503 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
504 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
505 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700506 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700507 }
508
509 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
510
511 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700512 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700513 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700514 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700515 }
516 // Do it again to make sure we don't double fetch.
517 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700518 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700519 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700520 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700521 });
522
523 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700524 test_timer->Schedule(loop2->monotonic_now(),
525 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700526 });
527
528 Run();
529 EXPECT_THAT(values, ::testing::ElementsAreArray({201}));
530}
531
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700532// Tests that timer handler is enabled after setup (even if it is in the past)
533// and is disabled after running
534TEST_P(AbstractEventLoopTest, CheckTimerDisabled) {
535 auto loop = MakePrimary("primary");
536
537 auto timer = loop->AddTimer([this]() {
538 LOG(INFO) << "timer called";
539 Exit();
540 });
541
542 loop->OnRun([&loop, timer]() {
543 EXPECT_TRUE(timer->IsDisabled());
Philipp Schradera6712522023-07-05 20:25:11 -0700544 timer->Schedule(loop->monotonic_now() + chrono::milliseconds(100));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700545 EXPECT_FALSE(timer->IsDisabled());
546 });
547
548 Run();
549 EXPECT_TRUE(timer->IsDisabled());
550}
551
552// Tests that timer handler is enabled after setup (even if it is in the past)
553// and is disabled after running
554TEST_P(AbstractEventLoopTest, CheckTimerRunInPastDisabled) {
555 auto loop = MakePrimary("primary");
556
557 auto timer2 = loop->AddTimer([this]() {
558 LOG(INFO) << "timer called";
559 Exit();
560 });
561
562 auto timer = loop->AddTimer([&loop, timer2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700563 timer2->Schedule(loop->monotonic_now() - chrono::nanoseconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700564 });
565
566 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700567 timer->Schedule(loop->monotonic_now() + chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700568 EXPECT_FALSE(timer->IsDisabled());
569 });
570
571 Run();
572 EXPECT_TRUE(timer2->IsDisabled());
573}
574
575// Tests that timer handler is not disabled even after calling Exit on the event
576// loop within the timer
577TEST_P(AbstractEventLoopTest, CheckTimerRepeatOnCountDisabled) {
578 auto loop = MakePrimary("primary");
579 int counter = 0;
580
581 auto timer = loop->AddTimer([&counter, this]() {
582 LOG(INFO) << "timer called";
583 counter++;
584 if (counter >= 5) {
585 Exit();
586 }
587 });
588
589 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700590 timer->Schedule(loop->monotonic_now() + chrono::seconds(1),
591 chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700592 EXPECT_FALSE(timer->IsDisabled());
593 });
594 Run();
595
596 // Sanity check
597 EXPECT_EQ(counter, 5);
598
599 // if you run the loop again, the timer will start running again
600 EXPECT_FALSE(timer->IsDisabled());
601
602 counter = 0;
603 Run();
604 timer->Disable();
605
606 EXPECT_TRUE(timer->IsDisabled());
607}
608
609// Tests that timer handler is not disabled even after calling Exit on the event
610// loop using an external timer
611TEST_P(AbstractEventLoopTest, CheckTimerRepeatTillEndTimerDisabled) {
612 auto loop = MakePrimary("primary");
613
614 auto timer = loop->AddTimer([]() { LOG(INFO) << "timer called"; });
615
616 loop->OnRun([&loop, timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700617 timer->Schedule(loop->monotonic_now() + chrono::seconds(1),
618 chrono::seconds(1));
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700619 EXPECT_FALSE(timer->IsDisabled());
620 });
621
622 EndEventLoop(loop.get(), chrono::seconds(5));
623 Run();
624 EXPECT_FALSE(timer->IsDisabled());
625
626 timer->Disable();
627 EXPECT_TRUE(timer->IsDisabled());
628}
629
Austin Schuhbbce72d2019-05-26 15:11:46 -0700630// Tests that Fetch and FetchNext interleave as expected.
631TEST_P(AbstractEventLoopTest, FetchAndFetchNextTogether) {
632 auto loop1 = Make();
633 auto loop2 = MakePrimary();
634
635 auto sender = loop1->MakeSender<TestMessage>("/test");
636
637 ::std::vector<int> values;
638
639 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700640 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
641 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
642 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700643 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700644 }
645 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700646 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
647 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
648 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700649 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700650 }
651
652 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
653
654 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700655 auto test_timer = loop2->AddTimer([&fetcher, &values, &sender, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700656 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700657 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700658 }
659
660 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700661 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
662 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
663 builder.add_value(202);
milind1f1dca32021-07-03 13:50:07 -0700664 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700665 }
666 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700667 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
668 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
669 builder.add_value(203);
milind1f1dca32021-07-03 13:50:07 -0700670 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700671 }
672 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700673 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
674 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
675 builder.add_value(204);
milind1f1dca32021-07-03 13:50:07 -0700676 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700677 }
678
679 if (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700680 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700681 }
682
683 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700684 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700685 }
686
Austin Schuh9fe68f72019-08-10 19:32:03 -0700687 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700688 });
689
690 loop2->OnRun([&test_timer, &loop2]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700691 test_timer->Schedule(loop2->monotonic_now(),
692 ::std::chrono::milliseconds(100));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700693 });
694
695 Run();
696 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
697}
698
Austin Schuh3115a202019-05-27 21:02:14 -0700699// Tests that FetchNext behaves correctly when we get two messages in the queue
700// but don't consume the first until after the second has been sent.
701TEST_P(AbstractEventLoopTest, FetchNextTest) {
Austin Schuh3115a202019-05-27 21:02:14 -0700702 auto send_loop = Make();
703 auto fetch_loop = Make();
704 auto sender = send_loop->MakeSender<TestMessage>("/test");
705 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
706
707 {
Tyler Chatow67ddb032020-01-12 14:30:04 -0800708 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
709 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
710 builder.add_value(100);
milind1f1dca32021-07-03 13:50:07 -0700711 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700712 }
713
714 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700715 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
716 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
717 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700718 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700719 }
720
721 ASSERT_TRUE(fetcher.FetchNext());
722 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700723 EXPECT_EQ(100, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700724
725 ASSERT_TRUE(fetcher.FetchNext());
726 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700727 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700728
729 // When we run off the end of the queue, expect to still have the old message:
730 ASSERT_FALSE(fetcher.FetchNext());
731 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700732 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700733}
734
Brian Silverman77162972020-08-12 19:52:40 -0700735// Verify that a fetcher still holds its data, even after falling behind.
736TEST_P(AbstractEventLoopTest, FetcherBehindData) {
737 auto send_loop = Make();
738 auto fetch_loop = Make();
739 auto sender = send_loop->MakeSender<TestMessage>("/test");
740 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
741 {
742 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
743 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
744 builder.add_value(1);
milind1f1dca32021-07-03 13:50:07 -0700745 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -0700746 }
747 ASSERT_TRUE(fetcher.Fetch());
748 EXPECT_EQ(1, fetcher.get()->value());
749 for (int i = 0; i < 300; ++i) {
750 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
751 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
752 builder.add_value(i + 2);
milind1f1dca32021-07-03 13:50:07 -0700753 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -0700754 }
755 EXPECT_EQ(1, fetcher.get()->value());
756}
757
758// Try a bunch of orderings of operations with fetchers and senders. Verify that
759// all the fetchers have the correct data at each step.
760TEST_P(AbstractEventLoopTest, FetcherPermutations) {
761 for (int max_save = 0; max_save < 5; ++max_save) {
762 SCOPED_TRACE("max_save=" + std::to_string(max_save));
763
764 auto send_loop = Make();
765 auto fetch_loop = Make();
766 auto sender = send_loop->MakeSender<TestMessage>("/test");
767 const auto send_message = [&sender](int i) {
768 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
769 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
770 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700771 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -0700772 };
773 std::vector<Fetcher<TestMessage>> fetchers;
774 for (int i = 0; i < 10; ++i) {
775 fetchers.emplace_back(fetch_loop->MakeFetcher<TestMessage>("/test"));
776 }
777 send_message(1);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700778 const auto verify_buffers = [&]() {
779 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>>
780 fetchers_copy;
781 for (const auto &fetcher : fetchers) {
782 fetchers_copy.emplace_back(fetcher);
783 }
784 std::vector<std::reference_wrapper<const Sender<TestMessage>>>
785 senders_copy;
786 senders_copy.emplace_back(sender);
787 VerifyBuffers(send_loop->NumberBuffers(sender.channel()), fetchers_copy,
788 senders_copy);
789 };
Brian Silverman77162972020-08-12 19:52:40 -0700790 for (auto &fetcher : fetchers) {
791 ASSERT_TRUE(fetcher.Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -0700792 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700793 EXPECT_EQ(1, fetcher.get()->value());
794 }
795
796 for (int save = 1; save <= max_save; ++save) {
797 SCOPED_TRACE("save=" + std::to_string(save));
798 send_message(100 + save);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700799 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700800 for (size_t i = 0; i < fetchers.size() - save; ++i) {
801 SCOPED_TRACE("fetcher=" + std::to_string(i));
802 ASSERT_TRUE(fetchers[i].Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -0700803 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700804 EXPECT_EQ(100 + save, fetchers[i].get()->value());
805 }
806 for (size_t i = fetchers.size() - save; i < fetchers.size() - 1; ++i) {
807 SCOPED_TRACE("fetcher=" + std::to_string(i));
808 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
809 }
810 EXPECT_EQ(1, fetchers.back().get()->value());
811 }
812
813 for (int i = 0; i < 300; ++i) {
814 send_message(200 + i);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700815 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700816 }
817
818 for (size_t i = 0; i < fetchers.size() - max_save; ++i) {
819 SCOPED_TRACE("fetcher=" + std::to_string(i));
820 if (max_save > 0) {
821 EXPECT_EQ(100 + max_save, fetchers[i].get()->value());
822 } else {
823 EXPECT_EQ(1, fetchers[i].get()->value());
824 }
825 }
826 for (size_t i = fetchers.size() - max_save; i < fetchers.size() - 1; ++i) {
827 SCOPED_TRACE("fetcher=" + std::to_string(i));
828 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
829 }
830 EXPECT_EQ(1, fetchers.back().get()->value());
831 }
832}
833
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800834// Verify that making a fetcher and watcher for "/test" succeeds.
835TEST_P(AbstractEventLoopTest, FetcherAndWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800836 auto loop = Make();
837 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800838 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Parker Schuhe4a70d62017-12-27 20:10:20 -0800839}
840
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800841// Verify that making 2 fetchers for "/test" succeeds.
Parker Schuhe4a70d62017-12-27 20:10:20 -0800842TEST_P(AbstractEventLoopTest, TwoFetcher) {
843 auto loop = Make();
844 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800845 auto fetcher2 = loop->MakeFetcher<TestMessage>("/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -0800846}
847
Alex Perrycb7da4b2019-08-28 19:35:56 -0700848// Verify that registering a watcher for an invalid channel name dies.
849TEST_P(AbstractEventLoopDeathTest, InvalidChannelName) {
850 auto loop = Make();
851 EXPECT_DEATH(
852 { loop->MakeWatcher("/test/invalid", [&](const TestMessage &) {}); },
853 "/test/invalid");
Brian Silverman454bc112020-03-05 14:21:25 -0800854 EXPECT_DEATH(
855 { loop->MakeNoArgWatcher<TestMessage>("/test/invalid", [&]() {}); },
856 "/test/invalid");
Alex Perrycb7da4b2019-08-28 19:35:56 -0700857}
858
James Kuszmaul8866e642022-06-10 16:00:36 -0700859// Verify that setting up a timer before monotonic_clock::epoch() fails.
James Kuszmaul86e86c32022-07-21 17:39:47 -0700860TEST_P(AbstractEventLoopDeathTest, NegativeTimeTimer) {
James Kuszmaul8866e642022-06-10 16:00:36 -0700861 auto loop = Make();
862 TimerHandler *time = loop->AddTimer([]() {});
Philipp Schradera6712522023-07-05 20:25:11 -0700863 EXPECT_DEATH(
864 time->Schedule(monotonic_clock::epoch() - std::chrono::seconds(1)),
865 "-1.000");
James Kuszmaul8866e642022-06-10 16:00:36 -0700866}
867
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800868// Verify that registering a watcher twice for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700869TEST_P(AbstractEventLoopDeathTest, TwoWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800870 auto loop = Make();
871 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800872 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
873 "/test");
Brian Silverman454bc112020-03-05 14:21:25 -0800874 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
875}
876
877// Verify that registering a no-arg watcher twice for "/test" fails.
878TEST_P(AbstractEventLoopDeathTest, TwoNoArgWatcher) {
879 auto loop = Make();
880 loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {});
881 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
882 "/test");
883 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800884}
885
Austin Schuh3115a202019-05-27 21:02:14 -0700886// Verify that SetRuntimeRealtimePriority fails while running.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700887TEST_P(AbstractEventLoopDeathTest, SetRuntimeRealtimePriority) {
Austin Schuh3115a202019-05-27 21:02:14 -0700888 auto loop = MakePrimary();
Austin Schuh65493d62022-08-17 15:10:37 -0700889 EXPECT_EQ(0, loop->runtime_realtime_priority());
Austin Schuh3115a202019-05-27 21:02:14 -0700890 // Confirm that runtime priority calls work when not realtime.
891 loop->SetRuntimeRealtimePriority(5);
Austin Schuh65493d62022-08-17 15:10:37 -0700892 EXPECT_EQ(5, loop->runtime_realtime_priority());
Austin Schuh3115a202019-05-27 21:02:14 -0700893
894 loop->OnRun([&]() { loop->SetRuntimeRealtimePriority(5); });
895
896 EXPECT_DEATH(Run(), "realtime");
897}
898
Austin Schuh65493d62022-08-17 15:10:37 -0700899namespace {
900
901bool CpuSetEqual(const cpu_set_t &a, const cpu_set_t &b) {
902 return CPU_EQUAL(&a, &b);
903}
904
905} // namespace
906
Brian Silverman6a54ff32020-04-28 16:41:39 -0700907// Verify that SetRuntimeAffinity fails while running.
908TEST_P(AbstractEventLoopDeathTest, SetRuntimeAffinity) {
Austin Schuhde973292021-10-12 18:09:49 -0700909 const cpu_set_t available = GetCurrentThreadAffinity();
910 int first_cpu = -1;
911 for (int i = 0; i < CPU_SETSIZE; ++i) {
912 if (CPU_ISSET(i, &available)) {
913 first_cpu = i;
914 break;
915 continue;
916 }
917 }
918 CHECK_NE(first_cpu, -1) << ": Default affinity has no CPUs?";
919
Brian Silverman6a54ff32020-04-28 16:41:39 -0700920 auto loop = MakePrimary();
Austin Schuh65493d62022-08-17 15:10:37 -0700921 EXPECT_TRUE(
922 CpuSetEqual(EventLoop::DefaultAffinity(), loop->runtime_affinity()));
923 const cpu_set_t new_affinity = MakeCpusetFromCpus({first_cpu});
Brian Silverman6a54ff32020-04-28 16:41:39 -0700924 // Confirm that runtime priority calls work when not running.
Austin Schuh65493d62022-08-17 15:10:37 -0700925 loop->SetRuntimeAffinity(new_affinity);
926 EXPECT_TRUE(CpuSetEqual(new_affinity, loop->runtime_affinity()));
Brian Silverman6a54ff32020-04-28 16:41:39 -0700927
Austin Schuhde973292021-10-12 18:09:49 -0700928 loop->OnRun(
929 [&]() { loop->SetRuntimeAffinity(MakeCpusetFromCpus({first_cpu})); });
Brian Silverman6a54ff32020-04-28 16:41:39 -0700930
931 EXPECT_DEATH(Run(), "Cannot set affinity while running");
932}
933
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800934// Verify that registering a watcher and a sender for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700935TEST_P(AbstractEventLoopDeathTest, WatcherAndSender) {
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800936 auto loop = Make();
937 auto sender = loop->MakeSender<TestMessage>("/test");
938 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
939 "/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -0800940}
941
Austin Schuhe516ab02020-05-06 21:37:04 -0700942// Verify that creating too many senders fails.
943TEST_P(AbstractEventLoopDeathTest, TooManySenders) {
944 auto loop = Make();
945 std::vector<aos::Sender<TestMessage>> senders;
946 for (int i = 0; i < 10; ++i) {
947 senders.emplace_back(loop->MakeSender<TestMessage>("/test"));
948 }
949 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); },
950 "Failed to create sender on \\{ \"name\": \"/test\", \"type\": "
Brian Silverman77162972020-08-12 19:52:40 -0700951 "\"aos.TestMessage\"[^}]*\\ }, too many senders.");
952}
953
954// Verify that creating too many fetchers fails.
955TEST_P(AbstractEventLoopDeathTest, TooManyFetchers) {
956 if (read_method() != ReadMethod::PIN) {
957 // Other read methods don't limit the number of readers, so just skip this.
958 return;
959 }
960
961 auto loop = Make();
962 std::vector<aos::Fetcher<TestMessage>> fetchers;
963 for (int i = 0; i < 10; ++i) {
964 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
965 }
966 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
967 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
968 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
969}
970
971// Verify that creating too many fetchers, split between two event loops, fails.
972TEST_P(AbstractEventLoopDeathTest, TooManyFetchersTwoLoops) {
973 if (read_method() != ReadMethod::PIN) {
974 // Other read methods don't limit the number of readers, so just skip this.
975 return;
976 }
977
978 auto loop = Make();
979 auto loop2 = Make();
980 std::vector<aos::Fetcher<TestMessage>> fetchers;
981 for (int i = 0; i < 5; ++i) {
982 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
983 fetchers.emplace_back(loop2->MakeFetcher<TestMessage>("/test"));
984 }
985 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
986 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
987 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
988}
989
990// Verify that creating too many watchers fails.
991TEST_P(AbstractEventLoopDeathTest, TooManyWatchers) {
992 if (read_method() != ReadMethod::PIN) {
993 // Other read methods don't limit the number of readers, so just skip this.
994 return;
995 }
996
997 std::vector<std::unique_ptr<EventLoop>> loops;
998 for (int i = 0; i < 10; ++i) {
999 loops.emplace_back(Make());
1000 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
1001 }
1002 EXPECT_DEATH({ Make()->MakeWatcher("/test", [](const TestMessage &) {}); },
1003 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1004 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
1005}
1006
1007// Verify that creating too many watchers and fetchers combined fails.
1008TEST_P(AbstractEventLoopDeathTest, TooManyWatchersAndFetchers) {
1009 if (read_method() != ReadMethod::PIN) {
1010 // Other read methods don't limit the number of readers, so just skip this.
1011 return;
1012 }
1013
1014 auto loop = Make();
1015 std::vector<aos::Fetcher<TestMessage>> fetchers;
1016 std::vector<std::unique_ptr<EventLoop>> loops;
1017 for (int i = 0; i < 5; ++i) {
1018 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1019 loops.emplace_back(Make());
1020 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
1021 }
1022 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1023 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1024 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
Austin Schuhe516ab02020-05-06 21:37:04 -07001025}
1026
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001027// Verify that we can't create a sender inside OnRun.
1028TEST_P(AbstractEventLoopDeathTest, SenderInOnRun) {
1029 auto loop1 = MakePrimary();
1030
1031 loop1->OnRun(
1032 [&]() { auto sender = loop1->MakeSender<TestMessage>("/test2"); });
1033
1034 EXPECT_DEATH(Run(), "running");
1035}
1036
1037// Verify that we can't create a watcher inside OnRun.
1038TEST_P(AbstractEventLoopDeathTest, WatcherInOnRun) {
1039 auto loop1 = MakePrimary();
1040
1041 loop1->OnRun(
1042 [&]() { loop1->MakeWatcher("/test", [&](const TestMessage &) {}); });
1043
1044 EXPECT_DEATH(Run(), "running");
1045}
1046
Brian Silverman454bc112020-03-05 14:21:25 -08001047// Verify that we can't create a no-arg watcher inside OnRun.
1048TEST_P(AbstractEventLoopDeathTest, NoArgWatcherInOnRun) {
1049 auto loop1 = MakePrimary();
1050
1051 loop1->OnRun(
1052 [&]() { loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {}); });
1053
1054 EXPECT_DEATH(Run(), "running");
1055}
1056
Parker Schuhe4a70d62017-12-27 20:10:20 -08001057// Verify that Quit() works when there are multiple watchers.
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001058TEST_P(AbstractEventLoopTest, MultipleWatcherQuit) {
1059 auto loop1 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -07001060 auto loop2 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -08001061
Austin Schuh3578a2e2019-05-25 18:17:59 -07001062 loop2->MakeWatcher("/test1", [&](const TestMessage &) {});
1063 loop2->MakeWatcher("/test2", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001064 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -07001065 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -07001066 });
1067
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001068 auto sender = loop1->MakeSender<TestMessage>("/test2");
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001069
1070 loop2->OnRun([&]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001071 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1072 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1073 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001074 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001075 });
Parker Schuhe4a70d62017-12-27 20:10:20 -08001076
Austin Schuh44019f92019-05-19 19:58:27 -07001077 Run();
Parker Schuhe4a70d62017-12-27 20:10:20 -08001078}
1079
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001080// Verify that AOS_LOG has the right name.
1081TEST_P(AbstractEventLoopTest, AOSLog) {
1082 auto loop2 = MakePrimary("loop1");
1083 auto loop1 = Make("loop0");
1084
1085 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1086
1087 EXPECT_FALSE(fetcher.Fetch());
1088
1089 loop2->OnRun([&]() {
1090 AOS_LOG(INFO, "Testing123");
1091 this->Exit();
1092 });
1093
1094 Run();
1095 EXPECT_TRUE(fetcher.Fetch());
1096 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1097}
1098
1099// Verify that AOS_LOG has the right name in a watcher.
1100TEST_P(AbstractEventLoopTest, AOSLogWatcher) {
1101 auto loop2 = MakePrimary("loop1");
1102 auto loop1 = Make("loop0");
1103
1104 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1105
1106 EXPECT_FALSE(fetcher.Fetch());
1107
1108 auto sender = loop1->MakeSender<TestMessage>("/test2");
1109
1110 loop2->MakeWatcher("/test2", [&](const TestMessage & /*message*/) {
1111 AOS_LOG(INFO, "Testing123");
1112 this->Exit();
1113 });
1114
1115 loop2->OnRun([&]() {
1116 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1117 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1118 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001119 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001120 });
1121
1122 Run();
1123 EXPECT_TRUE(fetcher.Fetch());
1124 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1125}
1126
1127// Verify that AOS_LOG has the right name in a timer.
1128TEST_P(AbstractEventLoopTest, AOSLogTimer) {
1129 auto loop2 = MakePrimary("loop1");
1130 auto loop1 = Make("loop0");
1131
1132 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1133
1134 EXPECT_FALSE(fetcher.Fetch());
1135
1136 auto test_timer = loop2->AddTimer([&]() {
1137 AOS_LOG(INFO, "Testing123");
1138 this->Exit();
1139 });
1140
Philipp Schradera6712522023-07-05 20:25:11 -07001141 loop2->OnRun([&]() { test_timer->Schedule(loop2->monotonic_now()); });
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001142
1143 Run();
1144 EXPECT_TRUE(fetcher.Fetch());
1145 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1146}
1147
Neil Balch229001a2018-01-07 18:22:52 -08001148// Verify that timer intervals and duration function properly.
1149TEST_P(AbstractEventLoopTest, TimerIntervalAndDuration) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001150 // Force a slower rate so we are guaranteed to have reports for our timer.
Austin Schuh39788ff2019-12-01 18:22:57 -08001151 FLAGS_timing_report_ms = 2000;
1152
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001153 const int kCount = 5;
Neil Balch229001a2018-01-07 18:22:52 -08001154
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001155 auto loop = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001156 auto loop2 = Make();
1157
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001158 ::std::vector<::aos::monotonic_clock::time_point> times;
1159 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
1160
Austin Schuh39788ff2019-12-01 18:22:57 -08001161 Fetcher<timing::Report> report_fetcher =
1162 loop2->MakeFetcher<timing::Report>("/aos");
1163 EXPECT_FALSE(report_fetcher.Fetch());
1164
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001165 auto test_timer = loop->AddTimer([this, &times, &expected_times, &loop]() {
1166 times.push_back(loop->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001167 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
1168 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
1169 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001170 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -08001171 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
1172 EXPECT_EQ(loop->context().size, 0u);
1173 EXPECT_EQ(loop->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001174 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001175
Austin Schuhad154822019-12-27 15:45:13 -08001176 expected_times.push_back(loop->context().monotonic_event_time);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001177 if (times.size() == kCount) {
1178 this->Exit();
1179 }
Neil Balch229001a2018-01-07 18:22:52 -08001180 });
Austin Schuh39788ff2019-12-01 18:22:57 -08001181 test_timer->set_name("Test loop");
Neil Balch229001a2018-01-07 18:22:52 -08001182
Austin Schuh39788ff2019-12-01 18:22:57 -08001183 const monotonic_clock::time_point start_time = loop->monotonic_now();
Austin Schuh52d325c2019-06-23 18:59:06 -07001184 // TODO(austin): This should be an error... Should be done in OnRun only.
Philipp Schradera6712522023-07-05 20:25:11 -07001185 test_timer->Schedule(start_time + chrono::seconds(1), chrono::seconds(1));
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001186
Austin Schuh44019f92019-05-19 19:58:27 -07001187 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001188
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001189 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001190 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
1191 ASSERT_EQ(times.size(), expected_times.size());
1192 ASSERT_EQ((times.size() % 2), 1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001193
1194 // Grab the middle sample.
1195 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
1196
1197 // Add up all the delays of all the times.
1198 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1199 for (const ::aos::monotonic_clock::time_point time : times) {
1200 sum += time - average_time;
1201 }
1202
1203 // Average and add to the middle to find the average time.
1204 sum /= times.size();
1205 average_time += sum;
1206
1207 // Compute the offset from the average and the expected average. It
1208 // should be pretty close to 0.
1209 const ::aos::monotonic_clock::duration remainder =
1210 average_time - start_time - chrono::seconds(times.size() / 2 + 1);
1211
1212 const chrono::milliseconds kEpsilon(100);
1213 EXPECT_LT(remainder, +kEpsilon);
1214 EXPECT_GT(remainder, -kEpsilon);
1215
1216 // Make sure that the average duration is close to 1 second.
1217 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1218 times.front())
1219 .count() /
1220 static_cast<double>(times.size() - 1),
1221 1.0, 0.1);
1222
1223 // Confirm that the ideal wakeup times increment correctly.
1224 for (size_t i = 1; i < expected_times.size(); ++i) {
1225 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1226 }
1227
1228 for (size_t i = 0; i < expected_times.size(); ++i) {
1229 EXPECT_EQ((expected_times[i] - start_time) % chrono::seconds(1),
1230 chrono::seconds(0));
1231 }
1232
1233 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1234 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001235
Austin Schuh6bae8252021-02-07 22:01:49 -08001236 if (do_timing_reports() == DoTimingReports::kYes) {
1237 // And, since we are here, check that the timing report makes sense.
1238 // Start by looking for our event loop's timing.
1239 FlatbufferDetachedBuffer<timing::Report> report =
1240 FlatbufferDetachedBuffer<timing::Report>::Empty();
1241 while (report_fetcher.FetchNext()) {
1242 if (report_fetcher->name()->string_view() == "primary") {
1243 report = CopyFlatBuffer(report_fetcher.get());
1244 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001245 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001246
1247 // Confirm that we have the right number of reports, and the contents are
1248 // sane.
1249 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
1250
1251 EXPECT_EQ(report.message().name()->string_view(), "primary");
1252
1253 ASSERT_NE(report.message().senders(), nullptr);
1254 EXPECT_EQ(report.message().senders()->size(), 2);
1255
1256 ASSERT_NE(report.message().timers(), nullptr);
1257 EXPECT_EQ(report.message().timers()->size(), 2);
1258
1259 EXPECT_EQ(report.message().timers()->Get(0)->name()->string_view(),
1260 "Test loop");
1261 EXPECT_GE(report.message().timers()->Get(0)->count(), 1);
1262
1263 EXPECT_EQ(report.message().timers()->Get(1)->name()->string_view(),
1264 "timing_reports");
1265 EXPECT_EQ(report.message().timers()->Get(1)->count(), 1);
1266
1267 // Make sure there is a single phased loop report with our report in it.
1268 ASSERT_EQ(report.message().phased_loops(), nullptr);
1269 } else {
1270 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001271 }
Neil Balch229001a2018-01-07 18:22:52 -08001272}
1273
1274// Verify that we can change a timer's parameters during execution.
1275TEST_P(AbstractEventLoopTest, TimerChangeParameters) {
Austin Schuh44019f92019-05-19 19:58:27 -07001276 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001277 loop->SetRuntimeRealtimePriority(1);
Austin Schuh7f20f512021-01-31 17:56:16 -08001278 std::vector<monotonic_clock::time_point> iteration_list;
Neil Balch229001a2018-01-07 18:22:52 -08001279
1280 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001281 ScopedNotRealtime nrt;
Austin Schuh7f20f512021-01-31 17:56:16 -08001282 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001283 });
1284
Austin Schuh7f20f512021-01-31 17:56:16 -08001285 monotonic_clock::time_point s;
1286 auto modifier_timer = loop->AddTimer([&test_timer, &s]() {
Philipp Schradera6712522023-07-05 20:25:11 -07001287 test_timer->Schedule(s + chrono::milliseconds(1750),
1288 chrono::milliseconds(600));
Neil Balch229001a2018-01-07 18:22:52 -08001289 });
1290
Austin Schuh7f20f512021-01-31 17:56:16 -08001291 s = loop->monotonic_now();
Philipp Schradera6712522023-07-05 20:25:11 -07001292 test_timer->Schedule(s, chrono::milliseconds(500));
1293 modifier_timer->Schedule(s + chrono::milliseconds(1250));
Austin Schuhd892f102021-10-12 18:01:46 -07001294 EndEventLoop(loop.get(), chrono::milliseconds(3950));
Austin Schuh44019f92019-05-19 19:58:27 -07001295 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001296
Austin Schuhd892f102021-10-12 18:01:46 -07001297 EXPECT_THAT(
1298 iteration_list,
1299 ::testing::ElementsAre(
1300 s, s + chrono::milliseconds(500), s + chrono::milliseconds(1000),
1301 s + chrono::milliseconds(1750), s + chrono::milliseconds(2350),
1302 s + chrono::milliseconds(2950), s + chrono::milliseconds(3550)));
Neil Balch229001a2018-01-07 18:22:52 -08001303}
1304
1305// Verify that we can disable a timer during execution.
1306TEST_P(AbstractEventLoopTest, TimerDisable) {
Austin Schuh44019f92019-05-19 19:58:27 -07001307 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001308 loop->SetRuntimeRealtimePriority(1);
Neil Balch229001a2018-01-07 18:22:52 -08001309 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
1310
1311 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001312 ScopedNotRealtime nrt;
Austin Schuhd892f102021-10-12 18:01:46 -07001313 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001314 });
1315
Tyler Chatow67ddb032020-01-12 14:30:04 -08001316 auto ender_timer = loop->AddTimer([&test_timer]() { test_timer->Disable(); });
Neil Balch229001a2018-01-07 18:22:52 -08001317
Austin Schuhd892f102021-10-12 18:01:46 -07001318 monotonic_clock::time_point s = loop->monotonic_now();
Philipp Schradera6712522023-07-05 20:25:11 -07001319 test_timer->Schedule(s, ::std::chrono::milliseconds(500));
1320 ender_timer->Schedule(s + ::std::chrono::milliseconds(1250));
Austin Schuh73d99502021-12-08 12:05:39 -08001321 EndEventLoop(loop.get(), ::std::chrono::milliseconds(2000));
Austin Schuh44019f92019-05-19 19:58:27 -07001322 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001323
Austin Schuhd892f102021-10-12 18:01:46 -07001324 EXPECT_THAT(iteration_list,
Austin Schuh73d99502021-12-08 12:05:39 -08001325 ::testing::ElementsAre(s, s + chrono::milliseconds(500),
1326 s + chrono::milliseconds(1000)));
Neil Balch229001a2018-01-07 18:22:52 -08001327}
Austin Schuh7267c532019-05-19 19:55:53 -07001328
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001329// Verify that a timer can disable itself.
1330//
1331// TODO(Brian): Do something similar with phased loops, both with a quick
1332// handler and a handler that would miss a cycle except it got deferred. Current
1333// behavior doing that is a mess.
1334TEST_P(AbstractEventLoopTest, TimerDisableSelf) {
1335 auto loop = MakePrimary();
1336
1337 int count = 0;
1338 aos::TimerHandler *test_timer;
1339 test_timer = loop->AddTimer([&count, &test_timer]() {
1340 ++count;
1341 test_timer->Disable();
1342 });
1343
Philipp Schradera6712522023-07-05 20:25:11 -07001344 test_timer->Schedule(loop->monotonic_now(), ::std::chrono::milliseconds(20));
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001345 EndEventLoop(loop.get(), ::std::chrono::milliseconds(80));
1346 Run();
1347
1348 EXPECT_EQ(count, 1);
1349}
1350
Brian Silvermanbd405c02020-06-23 16:25:23 -07001351// Verify that we can disable a timer during execution of another timer
1352// scheduled for the same time, with one ordering of creation for the timers.
1353//
1354// Also schedule some more events to reshuffle the heap in EventLoop used for
1355// tracking events to change up the order. This used to segfault
1356// SimulatedEventLoop.
1357TEST_P(AbstractEventLoopTest, TimerDisableOther) {
1358 for (bool creation_order : {true, false}) {
1359 for (bool setup_order : {true, false}) {
1360 for (int shuffle_events = 0; shuffle_events < 5; ++shuffle_events) {
1361 auto loop = MakePrimary();
1362 aos::TimerHandler *test_timer, *ender_timer;
1363 if (creation_order) {
1364 test_timer = loop->AddTimer([]() {});
1365 ender_timer =
1366 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1367 } else {
1368 ender_timer =
1369 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1370 test_timer = loop->AddTimer([]() {});
1371 }
1372
1373 const auto start = loop->monotonic_now();
1374
1375 for (int i = 0; i < shuffle_events; ++i) {
Philipp Schradera6712522023-07-05 20:25:11 -07001376 loop->AddTimer([]() {})->Schedule(start +
1377 std::chrono::milliseconds(10));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001378 }
1379
1380 if (setup_order) {
Philipp Schradera6712522023-07-05 20:25:11 -07001381 test_timer->Schedule(start + ::std::chrono::milliseconds(20));
1382 ender_timer->Schedule(start + ::std::chrono::milliseconds(20));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001383 } else {
Philipp Schradera6712522023-07-05 20:25:11 -07001384 ender_timer->Schedule(start + ::std::chrono::milliseconds(20));
1385 test_timer->Schedule(start + ::std::chrono::milliseconds(20));
Brian Silvermanbd405c02020-06-23 16:25:23 -07001386 }
1387 EndEventLoop(loop.get(), ::std::chrono::milliseconds(40));
1388 Run();
1389 }
1390 }
1391 }
1392}
1393
Austin Schuh54cf95f2019-11-29 13:14:18 -08001394// Verifies that the event loop implementations detect when Channel is not a
Brian Silverman631b6262021-11-10 12:25:08 -08001395// pointer into configuration(), or a name doesn't map to a channel in
1396// configuration().
Austin Schuh54cf95f2019-11-29 13:14:18 -08001397TEST_P(AbstractEventLoopDeathTest, InvalidChannel) {
1398 auto loop = MakePrimary();
1399
Tyler Chatow67ddb032020-01-12 14:30:04 -08001400 const Channel *channel = configuration::GetChannel(
1401 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
Austin Schuh54cf95f2019-11-29 13:14:18 -08001402
1403 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1404
1405 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001406 loop->MakeRawSender(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001407 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1408
1409 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001410 loop->MakeSender<TestMessage>("/testbad"),
1411 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1412 " not found in config");
1413
1414 EXPECT_FALSE(loop->TryMakeSender<TestMessage>("/testbad"));
1415
1416 EXPECT_DEATH(
1417 loop->MakeRawFetcher(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001418 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1419
1420 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001421 loop->MakeFetcher<TestMessage>("/testbad"),
1422 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1423 " not found in config");
1424
1425 EXPECT_FALSE(loop->TryMakeFetcher<TestMessage>("/testbad").valid());
1426
1427 EXPECT_DEATH(
Austin Schuh54cf95f2019-11-29 13:14:18 -08001428 {
1429 loop->MakeRawWatcher(&channel_copy.message(),
1430 [](const Context, const void *) {});
1431 },
1432 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
Brian Silverman631b6262021-11-10 12:25:08 -08001433
1434 EXPECT_DEATH(
1435 { loop->MakeWatcher("/testbad", [](const TestMessage &) {}); },
1436 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1437 " not found in config");
1438}
1439
1440// Verifies that the event loop handles a channel which is not readable or
1441// writable on the current node nicely.
1442TEST_P(AbstractEventLoopDeathTest, InaccessibleChannel) {
1443 EnableNodes("me");
1444 auto loop = MakePrimary("me");
1445 auto loop2 = Make("them");
1446
1447 const Channel *channel = configuration::GetChannel(
1448 loop->configuration(), "/test_noforward", "aos.TestMessage", "", nullptr);
1449
1450 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1451
1452 EXPECT_DEATH(
1453 loop2->MakeSender<TestMessage>("/test_forward"),
1454 "Channel"
1455 " \\{ \"name\": \"/test_forward\", \"type\": \"aos.TestMessage\" \\}"
1456 " is not able to be sent on this node");
1457
1458 EXPECT_FALSE(loop2->TryMakeSender<TestMessage>("/test_forward"));
1459
1460 EXPECT_DEATH(
1461 loop2->MakeRawFetcher(channel),
1462 "Channel"
1463 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1464 " is not able to be fetched on this node");
1465
1466 EXPECT_DEATH(
1467 loop2->MakeFetcher<TestMessage>("/test_noforward"),
1468 "Channel"
1469 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1470 " is not able to be fetched on this node");
1471
1472 EXPECT_FALSE(loop2->TryMakeFetcher<TestMessage>("/test_noforward").valid());
1473
1474 EXPECT_DEATH(
1475 { loop2->MakeRawWatcher(channel, [](const Context, const void *) {}); },
1476 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1477 "\"source_node\": \"them\" \\}"
1478 " is not able to be watched on this node");
1479
1480 EXPECT_DEATH(
1481 { loop2->MakeWatcher("/test_noforward", [](const TestMessage &) {}); },
1482 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1483 "\"source_node\": \"them\" \\}"
1484 " is not able to be watched on this node");
Austin Schuh54cf95f2019-11-29 13:14:18 -08001485}
1486
Austin Schuhd54780b2020-10-03 16:26:02 -07001487// Verifies that the event loop implementations detect when Channel has an
1488// invalid alignment.
1489TEST_P(AbstractEventLoopDeathTest, InvalidChannelAlignment) {
1490 const char *const kError = "multiple of alignment";
1491 InvalidChannelAlignment();
1492
1493 auto loop = MakePrimary();
1494
1495 const Channel *channel = configuration::GetChannel(
1496 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
1497
1498 EXPECT_DEATH({ loop->MakeRawSender(channel); }, kError);
1499 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); }, kError);
1500
1501 EXPECT_DEATH({ loop->MakeRawFetcher(channel); }, kError);
1502 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); }, kError);
1503
1504 EXPECT_DEATH(
1505 { loop->MakeRawWatcher(channel, [](const Context &, const void *) {}); },
1506 kError);
1507 EXPECT_DEATH({ loop->MakeRawNoArgWatcher(channel, [](const Context &) {}); },
1508 kError);
1509
1510 EXPECT_DEATH({ loop->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
1511 kError);
1512 EXPECT_DEATH({ loop->MakeWatcher("/test", [](const TestMessage &) {}); },
1513 kError);
1514}
1515
Brian Silverman454bc112020-03-05 14:21:25 -08001516// Verify that the send time on a message is roughly right when using a watcher.
Austin Schuh7267c532019-05-19 19:55:53 -07001517TEST_P(AbstractEventLoopTest, MessageSendTime) {
Austin Schuh44019f92019-05-19 19:58:27 -07001518 auto loop1 = MakePrimary();
Austin Schuh7267c532019-05-19 19:55:53 -07001519 auto loop2 = Make();
Austin Schuhad154822019-12-27 15:45:13 -08001520 auto sender = loop2->MakeSender<TestMessage>("/test");
Austin Schuh7267c532019-05-19 19:55:53 -07001521 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
1522
1523 auto test_timer = loop1->AddTimer([&sender]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001524 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1525 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1526 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001527 msg.CheckOk(msg.Send(builder.Finish()));
Alex Perrycb7da4b2019-08-28 19:35:56 -07001528 });
1529
Austin Schuhad154822019-12-27 15:45:13 -08001530 bool triggered = false;
Brian Silverman454bc112020-03-05 14:21:25 -08001531 loop1->MakeWatcher("/test", [&](const TestMessage &msg) {
Austin Schuhad154822019-12-27 15:45:13 -08001532 // Confirm that the data pointer makes sense from a watcher, and all the
1533 // timestamps look right.
1534 EXPECT_GT(&msg, loop1->context().data);
1535 EXPECT_EQ(loop1->context().monotonic_remote_time,
1536 loop1->context().monotonic_event_time);
1537 EXPECT_EQ(loop1->context().realtime_remote_time,
1538 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001539 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001540
1541 const aos::monotonic_clock::time_point monotonic_now =
1542 loop1->monotonic_now();
Tyler Chatow67ddb032020-01-12 14:30:04 -08001543 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08001544
1545 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1546 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1547 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1548 monotonic_now);
1549 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1550 realtime_now);
1551
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001552 EXPECT_LT(&msg, reinterpret_cast<const void *>(
1553 reinterpret_cast<const char *>(loop1->context().data) +
Austin Schuhad154822019-12-27 15:45:13 -08001554 loop1->context().size));
Brian Silverman4f4e0612020-08-12 19:54:41 -07001555 if (read_method() == ReadMethod::PIN) {
1556 EXPECT_GE(loop1->context().buffer_index, 0);
1557 EXPECT_LT(loop1->context().buffer_index,
1558 loop1->NumberBuffers(
1559 configuration::GetChannel(loop1->configuration(), "/test",
1560 "aos.TestMessage", "", nullptr)));
1561 } else {
1562 EXPECT_EQ(-1, loop1->context().buffer_index);
1563 }
Austin Schuhad154822019-12-27 15:45:13 -08001564 triggered = true;
Austin Schuh7267c532019-05-19 19:55:53 -07001565 });
1566
Philipp Schradera6712522023-07-05 20:25:11 -07001567 test_timer->Schedule(loop1->monotonic_now() + ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07001568
1569 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
Austin Schuh44019f92019-05-19 19:58:27 -07001570 Run();
Austin Schuh7267c532019-05-19 19:55:53 -07001571
Austin Schuhad154822019-12-27 15:45:13 -08001572 EXPECT_TRUE(triggered);
1573
Brian Silverman454bc112020-03-05 14:21:25 -08001574 ASSERT_TRUE(fetcher.Fetch());
1575
1576 monotonic_clock::duration monotonic_time_offset =
1577 fetcher.context().monotonic_event_time -
1578 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1579 realtime_clock::duration realtime_time_offset =
1580 fetcher.context().realtime_event_time -
1581 (loop1->realtime_now() - ::std::chrono::seconds(1));
1582
1583 EXPECT_EQ(fetcher.context().realtime_event_time,
1584 fetcher.context().realtime_remote_time);
1585 EXPECT_EQ(fetcher.context().monotonic_event_time,
1586 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001587 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001588
1589 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1590 << ": Got "
1591 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1592 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1593 // Confirm that the data pointer makes sense.
1594 EXPECT_GT(fetcher.get(), fetcher.context().data);
1595 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001596 reinterpret_cast<const void *>(
1597 reinterpret_cast<const char *>(fetcher.context().data) +
Brian Silverman454bc112020-03-05 14:21:25 -08001598 fetcher.context().size));
1599 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1600 << ": Got "
1601 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1602 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1603
1604 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1605 << ": Got "
1606 << fetcher.context().realtime_event_time.time_since_epoch().count()
1607 << " expected " << loop1->realtime_now().time_since_epoch().count();
1608 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1609 << ": Got "
1610 << fetcher.context().realtime_event_time.time_since_epoch().count()
1611 << " expected " << loop1->realtime_now().time_since_epoch().count();
1612}
1613
1614// Verify that the send time on a message is roughly right when using a no-arg
1615// watcher. To get a message, we need to use a fetcher to actually access the
1616// message. This is also the main use case for no-arg fetchers.
1617TEST_P(AbstractEventLoopTest, MessageSendTimeNoArg) {
1618 auto loop1 = MakePrimary();
1619 auto loop2 = Make();
1620 auto sender = loop2->MakeSender<TestMessage>("/test");
1621 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
1622
1623 auto test_timer = loop1->AddTimer([&sender]() {
1624 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1625 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1626 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001627 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -08001628 });
1629
1630 bool triggered = false;
1631 loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {
1632 // Confirm that we can indeed use a fetcher on this channel from this
1633 // context, and it results in a sane data pointer and timestamps.
1634 ASSERT_TRUE(fetcher.Fetch());
1635
1636 EXPECT_EQ(loop1->context().monotonic_remote_time,
1637 loop1->context().monotonic_event_time);
1638 EXPECT_EQ(loop1->context().realtime_remote_time,
1639 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001640 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001641
1642 const aos::monotonic_clock::time_point monotonic_now =
1643 loop1->monotonic_now();
1644 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
1645
1646 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1647 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1648 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1649 monotonic_now);
1650 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1651 realtime_now);
1652
1653 triggered = true;
1654 });
1655
Philipp Schradera6712522023-07-05 20:25:11 -07001656 test_timer->Schedule(loop1->monotonic_now() + ::std::chrono::seconds(1));
Brian Silverman454bc112020-03-05 14:21:25 -08001657
1658 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
1659 Run();
1660
1661 ASSERT_TRUE(triggered);
Austin Schuh7267c532019-05-19 19:55:53 -07001662
Alex Perrycb7da4b2019-08-28 19:35:56 -07001663 monotonic_clock::duration monotonic_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001664 fetcher.context().monotonic_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001665 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1666 realtime_clock::duration realtime_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001667 fetcher.context().realtime_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001668 (loop1->realtime_now() - ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07001669
Austin Schuhad154822019-12-27 15:45:13 -08001670 EXPECT_EQ(fetcher.context().realtime_event_time,
1671 fetcher.context().realtime_remote_time);
1672 EXPECT_EQ(fetcher.context().monotonic_event_time,
1673 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001674 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001675
Alex Perrycb7da4b2019-08-28 19:35:56 -07001676 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1677 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001678 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh52d325c2019-06-23 18:59:06 -07001679 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07001680 // Confirm that the data pointer makes sense.
1681 EXPECT_GT(fetcher.get(), fetcher.context().data);
1682 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001683 reinterpret_cast<const void *>(
1684 reinterpret_cast<const char *>(fetcher.context().data) +
Alex Perrycb7da4b2019-08-28 19:35:56 -07001685 fetcher.context().size));
1686 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1687 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001688 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh7267c532019-05-19 19:55:53 -07001689 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07001690
1691 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1692 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001693 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07001694 << " expected " << loop1->realtime_now().time_since_epoch().count();
1695 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1696 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001697 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07001698 << " expected " << loop1->realtime_now().time_since_epoch().count();
Austin Schuh7267c532019-05-19 19:55:53 -07001699}
1700
Austin Schuh52d325c2019-06-23 18:59:06 -07001701// Tests that a couple phased loops run in a row result in the correct offset
1702// and period.
1703TEST_P(AbstractEventLoopTest, PhasedLoopTest) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001704 // Force a slower rate so we are guaranteed to have reports for our phased
Austin Schuh39788ff2019-12-01 18:22:57 -08001705 // loop.
1706 FLAGS_timing_report_ms = 2000;
1707
Austin Schuh52d325c2019-06-23 18:59:06 -07001708 const chrono::milliseconds kOffset = chrono::milliseconds(400);
1709 const int kCount = 5;
1710
1711 auto loop1 = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001712 auto loop2 = Make();
1713
1714 Fetcher<timing::Report> report_fetcher =
1715 loop2->MakeFetcher<timing::Report>("/aos");
1716 EXPECT_FALSE(report_fetcher.Fetch());
Austin Schuh52d325c2019-06-23 18:59:06 -07001717
1718 // Collect up a couple of samples.
1719 ::std::vector<::aos::monotonic_clock::time_point> times;
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001720 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
Austin Schuh52d325c2019-06-23 18:59:06 -07001721
1722 // Run kCount iterations.
Austin Schuh39788ff2019-12-01 18:22:57 -08001723 loop1
1724 ->AddPhasedLoop(
1725 [&times, &expected_times, &loop1, this](int count) {
1726 EXPECT_EQ(count, 1);
1727 times.push_back(loop1->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001728 expected_times.push_back(loop1->context().monotonic_event_time);
Austin Schuh39788ff2019-12-01 18:22:57 -08001729
Austin Schuhad154822019-12-27 15:45:13 -08001730 EXPECT_EQ(loop1->context().monotonic_remote_time,
1731 monotonic_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001732 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001733 EXPECT_EQ(loop1->context().realtime_event_time,
1734 realtime_clock::min_time);
1735 EXPECT_EQ(loop1->context().realtime_remote_time,
Austin Schuh39788ff2019-12-01 18:22:57 -08001736 realtime_clock::min_time);
1737 EXPECT_EQ(loop1->context().queue_index, 0xffffffffu);
1738 EXPECT_EQ(loop1->context().size, 0u);
1739 EXPECT_EQ(loop1->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001740 EXPECT_EQ(loop1->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001741
1742 if (times.size() == kCount) {
1743 LOG(INFO) << "Exiting";
1744 this->Exit();
1745 }
1746 },
1747 chrono::seconds(1), kOffset)
1748 ->set_name("Test loop");
Austin Schuh52d325c2019-06-23 18:59:06 -07001749
1750 // Add a delay to make sure that delay during startup doesn't result in a
1751 // "missed cycle".
1752 SleepFor(chrono::seconds(2));
1753
1754 Run();
1755
1756 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001757 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
1758 ASSERT_EQ(times.size(), expected_times.size());
1759 ASSERT_EQ((times.size() % 2), 1);
Austin Schuh52d325c2019-06-23 18:59:06 -07001760
1761 // Grab the middle sample.
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001762 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
Austin Schuh52d325c2019-06-23 18:59:06 -07001763
1764 // Add up all the delays of all the times.
1765 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1766 for (const ::aos::monotonic_clock::time_point time : times) {
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001767 sum += time - average_time;
Austin Schuh52d325c2019-06-23 18:59:06 -07001768 }
1769
1770 // Average and add to the middle to find the average time.
1771 sum /= times.size();
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001772 average_time += sum;
Austin Schuh52d325c2019-06-23 18:59:06 -07001773
1774 // Compute the offset from the start of the second of the average time. This
1775 // should be pretty close to the offset.
1776 const ::aos::monotonic_clock::duration remainder =
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001777 average_time.time_since_epoch() -
1778 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
Austin Schuh52d325c2019-06-23 18:59:06 -07001779
1780 const chrono::milliseconds kEpsilon(100);
1781 EXPECT_LT(remainder, kOffset + kEpsilon);
1782 EXPECT_GT(remainder, kOffset - kEpsilon);
1783
1784 // Make sure that the average duration is close to 1 second.
1785 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1786 times.front())
1787 .count() /
1788 static_cast<double>(times.size() - 1),
1789 1.0, 0.1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001790
1791 // Confirm that the ideal wakeup times increment correctly.
1792 for (size_t i = 1; i < expected_times.size(); ++i) {
1793 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1794 }
1795
1796 for (size_t i = 0; i < expected_times.size(); ++i) {
1797 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
1798 kOffset);
1799 }
1800
1801 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1802 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001803
Austin Schuh6bae8252021-02-07 22:01:49 -08001804 if (do_timing_reports() == DoTimingReports::kYes) {
1805 // And, since we are here, check that the timing report makes sense.
1806 // Start by looking for our event loop's timing.
1807 FlatbufferDetachedBuffer<timing::Report> report =
1808 FlatbufferDetachedBuffer<timing::Report>::Empty();
1809 while (report_fetcher.FetchNext()) {
1810 if (report_fetcher->name()->string_view() == "primary") {
1811 report = CopyFlatBuffer(report_fetcher.get());
1812 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001813 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001814
1815 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
1816
1817 EXPECT_EQ(report.message().name()->string_view(), "primary");
1818
1819 ASSERT_NE(report.message().senders(), nullptr);
1820 EXPECT_EQ(report.message().senders()->size(), 2);
1821
1822 ASSERT_NE(report.message().timers(), nullptr);
1823 EXPECT_EQ(report.message().timers()->size(), 1);
1824
1825 // Make sure there is a single phased loop report with our report in it.
1826 ASSERT_NE(report.message().phased_loops(), nullptr);
1827 ASSERT_EQ(report.message().phased_loops()->size(), 1);
1828 EXPECT_EQ(report.message().phased_loops()->Get(0)->name()->string_view(),
1829 "Test loop");
1830 EXPECT_GE(report.message().phased_loops()->Get(0)->count(), 1);
1831 } else {
1832 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001833 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001834}
1835
Milind Upadhyay42589bb2021-05-19 20:05:16 -07001836// Tests that a phased loop responds correctly to a changing offset.
1837TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetTest) {
1838 // Force a slower rate so we are guaranteed to have reports for our phased
1839 // loop.
1840 FLAGS_timing_report_ms = 2000;
1841
1842 const chrono::milliseconds kOffset = chrono::milliseconds(400);
1843 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
1844 const int kCount = 5;
1845
1846 auto loop1 = MakePrimary();
1847
1848 // Collect up a couple of samples.
1849 ::std::vector<::aos::monotonic_clock::time_point> times;
1850 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
1851
1852 PhasedLoopHandler *phased_loop;
1853
1854 // Run kCount iterations.
1855 phased_loop = loop1->AddPhasedLoop(
1856 [&phased_loop, &times, &expected_times, &loop1, this, kOffset,
1857 kInterval](int count) {
1858 EXPECT_EQ(count, 1);
1859 times.push_back(loop1->monotonic_now());
1860
1861 expected_times.push_back(loop1->context().monotonic_event_time);
1862
1863 phased_loop->set_interval_and_offset(
1864 kInterval, kOffset - chrono::milliseconds(times.size()));
1865 LOG(INFO) << "new offset: "
1866 << (kOffset - chrono::milliseconds(times.size())).count();
1867
1868 if (times.size() == kCount) {
1869 LOG(INFO) << "Exiting";
1870 this->Exit();
1871 }
1872 },
1873 kInterval, kOffset);
1874 phased_loop->set_name("Test loop");
1875
1876 // Add a delay to make sure that delay during startup doesn't result in a
1877 // "missed cycle".
1878 SleepFor(chrono::seconds(2));
1879
1880 Run();
1881 // Confirm that we got both the right number of samples, and it's odd.
1882 EXPECT_EQ(times.size(), static_cast<size_t>(kCount));
1883 EXPECT_EQ(times.size(), expected_times.size());
1884 EXPECT_EQ((times.size() % 2), 1);
1885
1886 // Grab the middle sample.
1887 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
1888
1889 // Add up all the delays of all the times.
1890 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1891 for (const ::aos::monotonic_clock::time_point time : times) {
1892 sum += time - average_time;
1893 }
1894
1895 // Average and add to the middle to find the average time.
1896 sum /= times.size();
1897 average_time += sum;
1898
1899 // Compute the offset from the start of the second of the average time. This
1900 // should be pretty close to the offset.
1901 const ::aos::monotonic_clock::duration remainder =
1902 average_time.time_since_epoch() -
1903 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
1904
1905 const chrono::milliseconds kEpsilon(100);
1906 EXPECT_LT(remainder, kOffset + kEpsilon);
1907 EXPECT_GT(remainder, kOffset - kEpsilon);
1908
1909 // Make sure that the average duration is close to 1 second.
1910 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1911 times.front())
1912 .count() /
1913 static_cast<double>(times.size() - 1),
1914 1.0, 0.1);
1915
1916 // Confirm that the ideal wakeup times increment correctly.
1917 for (size_t i = 1; i < expected_times.size(); ++i) {
1918 LOG(INFO) << i - 1 << ": " << expected_times[i - 1] << ", " << i << ": "
1919 << expected_times[i];
1920 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1) -
1921 chrono::milliseconds(1));
1922 }
1923
1924 for (size_t i = 0; i < expected_times.size(); ++i) {
1925 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
1926 kOffset - chrono::milliseconds(i));
1927 }
1928
1929 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1930 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
1931}
1932
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08001933// Tests that a phased loop responds correctly to a changing offset; sweep
1934// across a variety of potential offset changes, to ensure that we are
1935// exercising a variety of potential cases.
1936TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetSweep) {
1937 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
1938 const int kCount = 5;
1939
1940 auto loop1 = MakePrimary();
1941
1942 std::vector<aos::monotonic_clock::duration> offset_options;
1943 for (int ii = 0; ii < kCount; ++ii) {
1944 offset_options.push_back(ii * kInterval / kCount);
1945 }
1946 std::vector<aos::monotonic_clock::duration> offset_sweep;
1947 // Run over all the pair-wise combinations of offsets.
1948 for (int ii = 0; ii < kCount; ++ii) {
1949 for (int jj = 0; jj < kCount; ++jj) {
1950 offset_sweep.push_back(offset_options.at(ii));
1951 offset_sweep.push_back(offset_options.at(jj));
1952 }
1953 }
1954
1955 std::vector<::aos::monotonic_clock::time_point> expected_times;
1956
1957 PhasedLoopHandler *phased_loop;
1958
1959 // Run kCount iterations.
1960 size_t counter = 0;
1961 phased_loop = loop1->AddPhasedLoop(
1962 [&phased_loop, &expected_times, &loop1, this, kInterval, &counter,
1963 offset_sweep](int count) {
1964 EXPECT_EQ(count, 1);
1965 expected_times.push_back(loop1->context().monotonic_event_time);
1966
1967 counter++;
1968
1969 if (counter == offset_sweep.size()) {
1970 LOG(INFO) << "Exiting";
1971 this->Exit();
1972 return;
1973 }
1974
1975 phased_loop->set_interval_and_offset(kInterval,
1976 offset_sweep.at(counter));
1977 },
1978 kInterval, offset_sweep.at(0));
1979
1980 Run();
1981 ASSERT_EQ(expected_times.size(), offset_sweep.size());
1982 for (size_t ii = 1; ii < expected_times.size(); ++ii) {
1983 EXPECT_LE(expected_times.at(ii) - expected_times.at(ii - 1), kInterval);
1984 }
1985}
1986
1987// Tests that a phased loop responds correctly to being rescheduled with now
1988// equal to a time in the past.
1989TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleInPast) {
1990 const chrono::milliseconds kOffset = chrono::milliseconds(400);
1991 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
1992
1993 auto loop1 = MakePrimary();
1994
1995 std::vector<::aos::monotonic_clock::time_point> expected_times;
1996
1997 PhasedLoopHandler *phased_loop;
1998
1999 int expected_count = 1;
2000
2001 // Set up a timer that will get run immediately after the phased loop and
2002 // which will attempt to reschedule the phased loop to just before now. This
2003 // should succeed, but will result in 0 cycles elapsing.
2004 TimerHandler *manager_timer =
2005 loop1->AddTimer([&phased_loop, &loop1, &expected_count, this]() {
2006 if (expected_count == 0) {
2007 LOG(INFO) << "Exiting";
2008 this->Exit();
2009 return;
2010 }
2011 phased_loop->Reschedule(loop1->context().monotonic_event_time -
2012 std::chrono::nanoseconds(1));
2013 expected_count = 0;
2014 });
2015
2016 phased_loop = loop1->AddPhasedLoop(
2017 [&expected_count, &expected_times, &loop1, manager_timer](int count) {
2018 EXPECT_EQ(count, expected_count);
2019 expected_times.push_back(loop1->context().monotonic_event_time);
2020
Philipp Schradera6712522023-07-05 20:25:11 -07002021 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002022 },
2023 kInterval, kOffset);
2024 phased_loop->set_name("Test loop");
2025 manager_timer->set_name("Manager timer");
2026
2027 Run();
2028
2029 ASSERT_EQ(2u, expected_times.size());
2030 ASSERT_EQ(expected_times[0], expected_times[1]);
2031}
2032
2033// Tests that a phased loop responds correctly to being rescheduled at the time
2034// when it should be triggering (it should kick the trigger to the next cycle).
2035TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleNow) {
2036 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2037 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2038
2039 auto loop1 = MakePrimary();
2040
2041 std::vector<::aos::monotonic_clock::time_point> expected_times;
2042
2043 PhasedLoopHandler *phased_loop;
2044
2045 bool should_exit = false;
2046 // Set up a timer that will get run immediately after the phased loop and
2047 // which will attempt to reschedule the phased loop to now. This should
2048 // succeed, but will result in no change to the expected behavior (since this
2049 // is the same thing that is actually done internally).
2050 TimerHandler *manager_timer =
2051 loop1->AddTimer([&phased_loop, &loop1, &should_exit, this]() {
2052 if (should_exit) {
2053 LOG(INFO) << "Exiting";
2054 this->Exit();
2055 return;
2056 }
2057 phased_loop->Reschedule(loop1->context().monotonic_event_time);
2058 should_exit = true;
2059 });
2060
2061 phased_loop = loop1->AddPhasedLoop(
2062 [&expected_times, &loop1, manager_timer](int count) {
2063 EXPECT_EQ(count, 1);
2064 expected_times.push_back(loop1->context().monotonic_event_time);
2065
Philipp Schradera6712522023-07-05 20:25:11 -07002066 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002067 },
2068 kInterval, kOffset);
2069 phased_loop->set_name("Test loop");
2070 manager_timer->set_name("Manager timer");
2071
2072 Run();
2073
2074 ASSERT_EQ(2u, expected_times.size());
2075 ASSERT_EQ(expected_times[0] + kInterval, expected_times[1]);
2076}
2077
2078// Tests that a phased loop responds correctly to being rescheduled at a time in
2079// the distant future.
2080TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleFuture) {
2081 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2082 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2083
2084 auto loop1 = MakePrimary();
2085
2086 std::vector<::aos::monotonic_clock::time_point> expected_times;
2087
2088 PhasedLoopHandler *phased_loop;
2089
2090 bool should_exit = false;
2091 int expected_count = 1;
2092 TimerHandler *manager_timer = loop1->AddTimer(
2093 [&expected_count, &phased_loop, &loop1, &should_exit, this, kInterval]() {
2094 if (should_exit) {
2095 LOG(INFO) << "Exiting";
2096 this->Exit();
2097 return;
2098 }
2099 expected_count = 10;
2100 // Knock off 1 ns, since the scheduler rounds up when it is
2101 // scheduled to exactly a loop time.
2102 phased_loop->Reschedule(loop1->context().monotonic_event_time +
2103 kInterval * expected_count -
2104 std::chrono::nanoseconds(1));
2105 should_exit = true;
2106 });
2107
2108 phased_loop = loop1->AddPhasedLoop(
2109 [&expected_times, &loop1, manager_timer, &expected_count](int count) {
2110 EXPECT_EQ(count, expected_count);
2111 expected_times.push_back(loop1->context().monotonic_event_time);
2112
Philipp Schradera6712522023-07-05 20:25:11 -07002113 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002114 },
2115 kInterval, kOffset);
2116 phased_loop->set_name("Test loop");
2117 manager_timer->set_name("Manager timer");
2118
2119 Run();
2120
2121 ASSERT_EQ(2u, expected_times.size());
2122 ASSERT_EQ(expected_times[0] + expected_count * kInterval, expected_times[1]);
2123}
2124
2125// Tests that a phased loop responds correctly to having its phase offset
2126// incremented and then being scheduled after a set time, exercising a pattern
2127// where a phased loop's offset is changed while trying to maintain the trigger
2128// at a consistent period.
2129TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleWithLaterOffset) {
2130 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2131 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2132
2133 auto loop1 = MakePrimary();
2134
2135 std::vector<::aos::monotonic_clock::time_point> expected_times;
2136
2137 PhasedLoopHandler *phased_loop;
2138
2139 bool should_exit = false;
2140 TimerHandler *manager_timer = loop1->AddTimer(
2141 [&phased_loop, &loop1, &should_exit, this, kInterval, kOffset]() {
2142 if (should_exit) {
2143 LOG(INFO) << "Exiting";
2144 this->Exit();
2145 return;
2146 }
2147 // Schedule the next callback to be strictly later than the current time
2148 // + interval / 2, to ensure a consistent frequency.
2149 monotonic_clock::time_point half_time =
2150 loop1->context().monotonic_event_time + kInterval / 2;
2151 phased_loop->set_interval_and_offset(
2152 kInterval, kOffset + std::chrono::nanoseconds(1), half_time);
2153 phased_loop->Reschedule(half_time);
2154 should_exit = true;
2155 });
2156
2157 phased_loop = loop1->AddPhasedLoop(
2158 [&expected_times, &loop1, manager_timer](int count) {
2159 EXPECT_EQ(1, count);
2160 expected_times.push_back(loop1->context().monotonic_event_time);
2161
Philipp Schradera6712522023-07-05 20:25:11 -07002162 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002163 },
2164 kInterval, kOffset);
2165 phased_loop->set_name("Test loop");
2166 manager_timer->set_name("Manager timer");
2167
2168 Run();
2169
2170 ASSERT_EQ(2u, expected_times.size());
2171 ASSERT_EQ(expected_times[0] + kInterval + std::chrono::nanoseconds(1),
2172 expected_times[1]);
2173}
2174
2175// Tests that a phased loop responds correctly to having its phase offset
2176// decremented and then being scheduled after a set time, exercising a pattern
2177// where a phased loop's offset is changed while trying to maintain the trigger
2178// at a consistent period.
2179TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleWithEarlierOffset) {
2180 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2181 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2182
2183 auto loop1 = MakePrimary();
2184
2185 std::vector<::aos::monotonic_clock::time_point> expected_times;
2186
2187 PhasedLoopHandler *phased_loop;
2188
2189 bool should_exit = false;
2190 TimerHandler *manager_timer = loop1->AddTimer(
2191 [&phased_loop, &loop1, &should_exit, this, kInterval, kOffset]() {
2192 if (should_exit) {
2193 LOG(INFO) << "Exiting";
2194 this->Exit();
2195 return;
2196 }
2197 // Schedule the next callback to be strictly later than the current time
2198 // + interval / 2, to ensure a consistent frequency.
2199 const aos::monotonic_clock::time_point half_time =
2200 loop1->context().monotonic_event_time + kInterval / 2;
2201 phased_loop->set_interval_and_offset(
2202 kInterval, kOffset - std::chrono::nanoseconds(1), half_time);
2203 phased_loop->Reschedule(half_time);
2204 should_exit = true;
2205 });
2206
2207 phased_loop = loop1->AddPhasedLoop(
2208 [&expected_times, &loop1, manager_timer](int count) {
2209 EXPECT_EQ(1, count);
2210 expected_times.push_back(loop1->context().monotonic_event_time);
2211
Philipp Schradera6712522023-07-05 20:25:11 -07002212 manager_timer->Schedule(loop1->context().monotonic_event_time);
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08002213 },
2214 kInterval, kOffset);
2215 phased_loop->set_name("Test loop");
2216 manager_timer->set_name("Manager timer");
2217
2218 Run();
2219
2220 ASSERT_EQ(2u, expected_times.size());
2221 ASSERT_EQ(expected_times[0] + kInterval - std::chrono::nanoseconds(1),
2222 expected_times[1]);
2223}
2224
Austin Schuh39788ff2019-12-01 18:22:57 -08002225// Tests that senders count correctly in the timing report.
2226TEST_P(AbstractEventLoopTest, SenderTimingReport) {
2227 FLAGS_timing_report_ms = 1000;
2228 auto loop1 = MakePrimary();
2229
2230 auto loop2 = Make("watcher_loop");
2231 loop2->MakeWatcher("/test", [](const TestMessage &) {});
2232
2233 auto loop3 = Make();
2234
2235 Fetcher<timing::Report> report_fetcher =
2236 loop3->MakeFetcher<timing::Report>("/aos");
2237 EXPECT_FALSE(report_fetcher.Fetch());
2238
2239 auto sender = loop1->MakeSender<TestMessage>("/test");
2240
James Kuszmaul78514332022-04-06 15:08:34 -07002241 // Sanity check channel frequencies to ensure that we've designed the test
2242 // correctly.
2243 ASSERT_EQ(800, sender.channel()->frequency());
Austin Schuhfff9c3a2023-06-16 18:48:23 -07002244 ASSERT_EQ(2000000000, configuration::ChannelStorageDuration(
2245 loop1->configuration(), sender.channel())
2246 .count());
James Kuszmaul78514332022-04-06 15:08:34 -07002247 constexpr int kMaxAllowedMessages = 800 * 2;
2248 constexpr int kSendMessages = kMaxAllowedMessages * 2;
2249 constexpr int kDroppedMessages = kSendMessages - kMaxAllowedMessages;
2250
Austin Schuh39788ff2019-12-01 18:22:57 -08002251 // Add a timer to actually quit.
2252 auto test_timer = loop1->AddTimer([&sender]() {
James Kuszmaul78514332022-04-06 15:08:34 -07002253 for (int i = 0; i < kSendMessages; ++i) {
Austin Schuh39788ff2019-12-01 18:22:57 -08002254 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2255 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2256 builder.add_value(200 + i);
James Kuszmaul78514332022-04-06 15:08:34 -07002257 if (i < kMaxAllowedMessages) {
2258 msg.CheckOk(msg.Send(builder.Finish()));
2259 } else {
2260 EXPECT_EQ(RawSender::Error::kMessagesSentTooFast,
2261 msg.Send(builder.Finish()));
2262 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002263 }
2264 });
2265
2266 // Quit after 1 timing report, mid way through the next cycle.
2267 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2268
2269 loop1->OnRun([&test_timer, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002270 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1500));
Austin Schuh39788ff2019-12-01 18:22:57 -08002271 });
2272
2273 Run();
2274
Austin Schuh6bae8252021-02-07 22:01:49 -08002275 if (do_timing_reports() == DoTimingReports::kYes) {
2276 // And, since we are here, check that the timing report makes sense.
2277 // Start by looking for our event loop's timing.
2278 FlatbufferDetachedBuffer<timing::Report> primary_report =
2279 FlatbufferDetachedBuffer<timing::Report>::Empty();
2280 while (report_fetcher.FetchNext()) {
Austin Schuh8902fa52021-03-14 22:39:24 -07002281 VLOG(1) << "Report " << FlatbufferToJson(report_fetcher.get());
Austin Schuh6bae8252021-02-07 22:01:49 -08002282 if (report_fetcher->name()->string_view() == "primary") {
2283 primary_report = CopyFlatBuffer(report_fetcher.get());
2284 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002285 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002286
Austin Schuh8902fa52021-03-14 22:39:24 -07002287 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
Austin Schuh6bae8252021-02-07 22:01:49 -08002288
2289 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2290
2291 ASSERT_NE(primary_report.message().senders(), nullptr);
2292 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2293
2294 // Confirm that the sender looks sane.
2295 EXPECT_EQ(
2296 loop1->configuration()
2297 ->channels()
2298 ->Get(primary_report.message().senders()->Get(0)->channel_index())
2299 ->name()
2300 ->string_view(),
2301 "/test");
James Kuszmaul78514332022-04-06 15:08:34 -07002302 EXPECT_EQ(primary_report.message().senders()->Get(0)->count(),
2303 kMaxAllowedMessages);
2304 ASSERT_TRUE(primary_report.message().senders()->Get(0)->has_error_counts());
2305 ASSERT_EQ(
2306 primary_report.message().senders()->Get(0)->error_counts()->size(), 2u);
2307 EXPECT_EQ(
2308 primary_report.message()
2309 .senders()
2310 ->Get(0)
2311 ->error_counts()
2312 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2313 ->count(),
2314 kDroppedMessages)
2315 << aos::FlatbufferToJson(primary_report);
2316 EXPECT_EQ(primary_report.message()
2317 .senders()
2318 ->Get(0)
2319 ->error_counts()
2320 ->Get(static_cast<size_t>(timing::SendError::INVALID_REDZONE))
2321 ->count(),
2322 0);
Austin Schuh6bae8252021-02-07 22:01:49 -08002323
2324 // Confirm that the timing primary_report sender looks sane.
2325 EXPECT_EQ(
2326 loop1->configuration()
2327 ->channels()
2328 ->Get(primary_report.message().senders()->Get(1)->channel_index())
2329 ->name()
2330 ->string_view(),
2331 "/aos");
2332 EXPECT_EQ(primary_report.message().senders()->Get(1)->count(), 1);
2333
2334 ASSERT_NE(primary_report.message().timers(), nullptr);
2335 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2336
2337 // Make sure there are no phased loops or watchers.
2338 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2339 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2340 } else {
2341 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002342 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002343}
2344
James Kuszmaul93abac12022-04-14 15:05:10 -07002345// Tests that the RawSender::Send(void*, size_t) overload tracks things properly
2346// in its timing report.
2347TEST_P(AbstractEventLoopTest, CopySenderTimingReport) {
2348 gflags::FlagSaver flag_saver;
2349 FLAGS_timing_report_ms = 1000;
2350 auto loop1 = Make();
2351 auto loop2 = MakePrimary();
2352
2353 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2354 JsonToFlatbuffer<TestMessage>("{}");
2355
2356 std::unique_ptr<aos::RawSender> sender =
2357 loop2->MakeRawSender(configuration::GetChannel(
2358 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
2359
2360 Fetcher<timing::Report> report_fetcher =
2361 loop1->MakeFetcher<timing::Report>("/aos");
2362 EXPECT_FALSE(report_fetcher.Fetch());
2363
2364 loop2->OnRun([&]() {
2365 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
2366 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2367 RawSender::Error::kOk);
2368 }
2369 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2370 RawSender::Error::kMessagesSentTooFast);
2371 });
2372 // Quit after 1 timing report, mid way through the next cycle.
2373 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
2374
2375 Run();
2376
2377 if (do_timing_reports() == DoTimingReports::kYes) {
2378 // Check that the sent too fast actually got recorded by the timing report.
2379 FlatbufferDetachedBuffer<timing::Report> primary_report =
2380 FlatbufferDetachedBuffer<timing::Report>::Empty();
2381 while (report_fetcher.FetchNext()) {
2382 if (report_fetcher->name()->string_view() == "primary") {
2383 primary_report = CopyFlatBuffer(report_fetcher.get());
2384 }
2385 }
2386
2387 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2388
2389 ASSERT_NE(primary_report.message().senders(), nullptr);
2390 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2391 EXPECT_EQ(
2392 primary_report.message()
2393 .senders()
2394 ->Get(0)
2395 ->error_counts()
2396 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2397 ->count(),
2398 1);
2399 }
2400}
2401
Austin Schuhe0ab4de2023-05-03 08:05:08 -07002402// Tests that the RawSender::Send(SharedSpan) overload works.
2403TEST_P(AbstractEventLoopTest, SharedSenderTimingReport) {
2404 gflags::FlagSaver flag_saver;
2405 FLAGS_timing_report_ms = 1000;
2406 auto loop1 = Make();
2407 auto loop2 = MakePrimary();
2408
2409 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2410 JsonToFlatbuffer<TestMessage>("{}");
2411
2412 std::unique_ptr<aos::RawSender> sender =
2413 loop2->MakeRawSender(configuration::GetChannel(
2414 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
2415
2416 Fetcher<timing::Report> report_fetcher =
2417 loop1->MakeFetcher<timing::Report>("/aos");
2418 EXPECT_FALSE(report_fetcher.Fetch());
2419
2420 loop2->OnRun([&]() {
2421 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
2422 auto shared_span = MakeSharedSpan(kMessage.span().size());
2423 memcpy(shared_span.second.data(), kMessage.span().data(),
2424 kMessage.span().size());
2425 EXPECT_EQ(sender->Send(std::move(shared_span.first)),
2426 RawSender::Error::kOk);
2427 }
2428 auto shared_span = MakeSharedSpan(kMessage.span().size());
2429 memcpy(shared_span.second.data(), kMessage.span().data(),
2430 kMessage.span().size());
2431 EXPECT_EQ(sender->Send(std::move(shared_span.first)),
2432 RawSender::Error::kMessagesSentTooFast);
2433 });
2434 // Quit after 1 timing report, mid way through the next cycle.
2435 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
2436
2437 Run();
2438
2439 if (do_timing_reports() == DoTimingReports::kYes) {
2440 // Check that the sent too fast actually got recorded by the timing report.
2441 FlatbufferDetachedBuffer<timing::Report> primary_report =
2442 FlatbufferDetachedBuffer<timing::Report>::Empty();
2443 while (report_fetcher.FetchNext()) {
2444 if (report_fetcher->name()->string_view() == "primary") {
2445 primary_report = CopyFlatBuffer(report_fetcher.get());
2446 }
2447 }
2448
2449 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2450
2451 ASSERT_NE(primary_report.message().senders(), nullptr);
2452 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2453 EXPECT_EQ(
2454 primary_report.message()
2455 .senders()
2456 ->Get(0)
2457 ->error_counts()
2458 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2459 ->count(),
2460 1);
2461 }
2462}
2463
Austin Schuh39788ff2019-12-01 18:22:57 -08002464// Tests that senders count correctly in the timing report.
2465TEST_P(AbstractEventLoopTest, WatcherTimingReport) {
2466 FLAGS_timing_report_ms = 1000;
2467 auto loop1 = MakePrimary();
2468 loop1->MakeWatcher("/test", [](const TestMessage &) {});
2469
2470 auto loop2 = Make("sender_loop");
2471
2472 auto loop3 = Make();
2473
2474 Fetcher<timing::Report> report_fetcher =
2475 loop3->MakeFetcher<timing::Report>("/aos");
2476 EXPECT_FALSE(report_fetcher.Fetch());
2477
2478 auto sender = loop2->MakeSender<TestMessage>("/test");
2479
2480 // Add a timer to actually quit.
2481 auto test_timer = loop1->AddTimer([&sender]() {
2482 for (int i = 0; i < 10; ++i) {
2483 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2484 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2485 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002486 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002487 }
2488 });
2489
2490 // Quit after 1 timing report, mid way through the next cycle.
2491 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2492
2493 loop1->OnRun([&test_timer, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002494 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1500));
Austin Schuh39788ff2019-12-01 18:22:57 -08002495 });
2496
2497 Run();
2498
Austin Schuh6bae8252021-02-07 22:01:49 -08002499 if (do_timing_reports() == DoTimingReports::kYes) {
2500 // And, since we are here, check that the timing report makes sense.
2501 // Start by looking for our event loop's timing.
2502 FlatbufferDetachedBuffer<timing::Report> primary_report =
2503 FlatbufferDetachedBuffer<timing::Report>::Empty();
2504 while (report_fetcher.FetchNext()) {
2505 LOG(INFO) << "Report " << FlatbufferToJson(report_fetcher.get());
2506 if (report_fetcher->name()->string_view() == "primary") {
2507 primary_report = CopyFlatBuffer(report_fetcher.get());
2508 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002509 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002510
2511 // Check the watcher report.
2512 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2513
2514 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2515
2516 // Just the timing report timer.
2517 ASSERT_NE(primary_report.message().timers(), nullptr);
2518 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2519
2520 // No phased loops
2521 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2522
2523 ASSERT_NE(primary_report.message().watchers(), nullptr);
2524 ASSERT_EQ(primary_report.message().watchers()->size(), 1);
2525 EXPECT_EQ(primary_report.message().watchers()->Get(0)->count(), 10);
2526 } else {
2527 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002528 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002529}
2530
2531// Tests that fetchers count correctly in the timing report.
2532TEST_P(AbstractEventLoopTest, FetcherTimingReport) {
2533 FLAGS_timing_report_ms = 1000;
2534 auto loop1 = MakePrimary();
2535 auto loop2 = Make("sender_loop");
2536
2537 auto loop3 = Make();
2538
2539 Fetcher<timing::Report> report_fetcher =
2540 loop3->MakeFetcher<timing::Report>("/aos");
2541 EXPECT_FALSE(report_fetcher.Fetch());
2542
2543 auto sender = loop2->MakeSender<TestMessage>("/test");
2544 auto fetcher1 = loop1->MakeFetcher<TestMessage>("/test");
2545 auto fetcher2 = loop1->MakeFetcher<TestMessage>("/test");
2546 fetcher1.Fetch();
2547 fetcher2.Fetch();
2548
2549 // Add a timer to actually quit.
2550 auto test_timer = loop1->AddTimer([&sender]() {
2551 for (int i = 0; i < 10; ++i) {
2552 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2553 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2554 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002555 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002556 }
2557 });
2558
2559 auto test_timer2 = loop1->AddTimer([&fetcher1, &fetcher2]() {
2560 fetcher1.Fetch();
2561 while (fetcher2.FetchNext()) {
2562 }
2563 });
2564
2565 // Quit after 1 timing report, mid way through the next cycle.
2566 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2567
2568 loop1->OnRun([test_timer, test_timer2, &loop1]() {
Philipp Schradera6712522023-07-05 20:25:11 -07002569 test_timer->Schedule(loop1->monotonic_now() + chrono::milliseconds(1400));
2570 test_timer2->Schedule(loop1->monotonic_now() + chrono::milliseconds(1600));
Austin Schuh39788ff2019-12-01 18:22:57 -08002571 });
2572
2573 Run();
2574
Austin Schuh6bae8252021-02-07 22:01:49 -08002575 if (do_timing_reports() == DoTimingReports::kYes) {
2576 // And, since we are here, check that the timing report makes sense.
2577 // Start by looking for our event loop's timing.
2578 FlatbufferDetachedBuffer<timing::Report> primary_report =
2579 FlatbufferDetachedBuffer<timing::Report>::Empty();
2580 while (report_fetcher.FetchNext()) {
2581 if (report_fetcher->name()->string_view() == "primary") {
2582 primary_report = CopyFlatBuffer(report_fetcher.get());
2583 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002584 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002585
2586 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2587
2588 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2589
2590 ASSERT_NE(primary_report.message().senders(), nullptr);
2591 EXPECT_EQ(primary_report.message().senders()->size(), 2);
2592
2593 ASSERT_NE(primary_report.message().timers(), nullptr);
2594 EXPECT_EQ(primary_report.message().timers()->size(), 4);
2595
2596 // Make sure there are no phased loops or watchers.
2597 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2598 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2599
2600 // Now look at the fetchrs.
2601 ASSERT_NE(primary_report.message().fetchers(), nullptr);
2602 ASSERT_EQ(primary_report.message().fetchers()->size(), 2);
2603
2604 EXPECT_EQ(primary_report.message().fetchers()->Get(0)->count(), 1);
2605 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->average(),
2606 0.1);
2607 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->min(),
2608 0.1);
2609 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->max(),
2610 0.1);
2611 EXPECT_EQ(primary_report.message()
2612 .fetchers()
2613 ->Get(0)
2614 ->latency()
2615 ->standard_deviation(),
2616 0.0);
2617
2618 EXPECT_EQ(primary_report.message().fetchers()->Get(1)->count(), 10);
2619 } else {
2620 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002621 }
Austin Schuh52d325c2019-06-23 18:59:06 -07002622}
2623
Austin Schuh67420a42019-12-21 21:55:04 -08002624// Tests that a raw watcher and raw fetcher can receive messages from a raw
2625// sender without messing up offsets.
2626TEST_P(AbstractEventLoopTest, RawBasic) {
2627 auto loop1 = Make();
2628 auto loop2 = MakePrimary();
2629 auto loop3 = Make();
2630
Austin Schuha9df9ad2021-06-16 14:49:39 -07002631 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2632 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuh67420a42019-12-21 21:55:04 -08002633
2634 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002635 loop1->MakeRawSender(configuration::GetChannel(
2636 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08002637
2638 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002639 loop3->MakeRawFetcher(configuration::GetChannel(
2640 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08002641
Austin Schuha9df9ad2021-06-16 14:49:39 -07002642 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002643 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2644 RawSender::Error::kOk);
Austin Schuha9df9ad2021-06-16 14:49:39 -07002645 });
Austin Schuh67420a42019-12-21 21:55:04 -08002646
2647 bool happened = false;
2648 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08002649 configuration::GetChannel(loop2->configuration(), "/test",
2650 "aos.TestMessage", "", nullptr),
Austin Schuha9df9ad2021-06-16 14:49:39 -07002651 [this, &kMessage, &fetcher, &happened](const Context &context,
2652 const void *message) {
Austin Schuh67420a42019-12-21 21:55:04 -08002653 happened = true;
Austin Schuha9df9ad2021-06-16 14:49:39 -07002654 EXPECT_EQ(
2655 kMessage.span(),
2656 absl::Span<const uint8_t>(
2657 reinterpret_cast<const uint8_t *>(message), context.size));
2658 EXPECT_EQ(message, context.data);
Austin Schuh67420a42019-12-21 21:55:04 -08002659
2660 ASSERT_TRUE(fetcher->Fetch());
2661
Austin Schuha9df9ad2021-06-16 14:49:39 -07002662 EXPECT_EQ(kMessage.span(),
2663 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
2664 fetcher->context().data),
2665 fetcher->context().size));
Austin Schuh67420a42019-12-21 21:55:04 -08002666
2667 this->Exit();
2668 });
2669
2670 EXPECT_FALSE(happened);
2671 Run();
2672 EXPECT_TRUE(happened);
2673}
2674
Austin Schuhad154822019-12-27 15:45:13 -08002675// Tests that a raw watcher and raw fetcher can receive messages from a raw
Brian Silvermanbf889922021-11-10 12:41:57 -08002676// sender without messing up offsets, using the RawSpan overload.
2677TEST_P(AbstractEventLoopTest, RawBasicSharedSpan) {
2678 auto loop1 = Make();
2679 auto loop2 = MakePrimary();
2680 auto loop3 = Make();
2681
2682 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2683 JsonToFlatbuffer<TestMessage>("{}");
2684
2685 std::unique_ptr<aos::RawSender> sender =
2686 loop1->MakeRawSender(configuration::GetChannel(
2687 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
2688
2689 std::unique_ptr<aos::RawFetcher> fetcher =
2690 loop3->MakeRawFetcher(configuration::GetChannel(
2691 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
2692
2693 loop2->OnRun([&]() {
Austin Schuhe0ab4de2023-05-03 08:05:08 -07002694 auto shared_span = MakeSharedSpan(kMessage.span().size());
2695 memcpy(shared_span.second.data(), kMessage.span().data(),
2696 kMessage.span().size());
2697 sender->CheckOk(sender->Send(std::move(shared_span.first)));
Brian Silvermanbf889922021-11-10 12:41:57 -08002698 });
2699
2700 bool happened = false;
2701 loop2->MakeRawWatcher(
2702 configuration::GetChannel(loop2->configuration(), "/test",
2703 "aos.TestMessage", "", nullptr),
2704 [this, &kMessage, &fetcher, &happened](const Context &context,
2705 const void *message) {
2706 happened = true;
2707 EXPECT_EQ(
2708 kMessage.span(),
2709 absl::Span<const uint8_t>(
2710 reinterpret_cast<const uint8_t *>(message), context.size));
2711 EXPECT_EQ(message, context.data);
2712
2713 ASSERT_TRUE(fetcher->Fetch());
2714
2715 EXPECT_EQ(kMessage.span(),
2716 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
2717 fetcher->context().data),
2718 fetcher->context().size));
2719
2720 this->Exit();
2721 });
2722
2723 EXPECT_FALSE(happened);
2724 Run();
2725 EXPECT_TRUE(happened);
2726}
2727
2728// Tests that a raw watcher and raw fetcher can receive messages from a raw
Austin Schuhad154822019-12-27 15:45:13 -08002729// sender with remote times filled out.
2730TEST_P(AbstractEventLoopTest, RawRemoteTimes) {
2731 auto loop1 = Make();
2732 auto loop2 = MakePrimary();
2733 auto loop3 = Make();
2734
Austin Schuha9df9ad2021-06-16 14:49:39 -07002735 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2736 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08002737
2738 const aos::monotonic_clock::time_point monotonic_remote_time =
2739 aos::monotonic_clock::time_point(chrono::seconds(1501));
2740 const aos::realtime_clock::time_point realtime_remote_time =
2741 aos::realtime_clock::time_point(chrono::seconds(3132));
Austin Schuhb5c6f972021-03-14 21:53:07 -07002742 const uint32_t remote_queue_index = 0x254971;
Austin Schuha9012be2021-07-21 15:19:11 -07002743 const UUID source_boot_uuid = UUID::Random();
Austin Schuhad154822019-12-27 15:45:13 -08002744
2745 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002746 loop1->MakeRawSender(configuration::GetChannel(
2747 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08002748
2749 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002750 loop3->MakeRawFetcher(configuration::GetChannel(
2751 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08002752
2753 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002754 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size(),
2755 monotonic_remote_time, realtime_remote_time,
2756 remote_queue_index, source_boot_uuid),
2757 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08002758 });
2759
2760 bool happened = false;
2761 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08002762 configuration::GetChannel(loop2->configuration(), "/test",
2763 "aos.TestMessage", "", nullptr),
Austin Schuha9012be2021-07-21 15:19:11 -07002764 [this, monotonic_remote_time, realtime_remote_time, source_boot_uuid,
Austin Schuhb5c6f972021-03-14 21:53:07 -07002765 remote_queue_index, &fetcher,
2766 &happened](const Context &context, const void * /*message*/) {
Austin Schuhad154822019-12-27 15:45:13 -08002767 happened = true;
2768 EXPECT_EQ(monotonic_remote_time, context.monotonic_remote_time);
2769 EXPECT_EQ(realtime_remote_time, context.realtime_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002770 EXPECT_EQ(source_boot_uuid, context.source_boot_uuid);
Austin Schuhb5c6f972021-03-14 21:53:07 -07002771 EXPECT_EQ(remote_queue_index, context.remote_queue_index);
Austin Schuhad154822019-12-27 15:45:13 -08002772
2773 ASSERT_TRUE(fetcher->Fetch());
2774 EXPECT_EQ(monotonic_remote_time,
2775 fetcher->context().monotonic_remote_time);
2776 EXPECT_EQ(realtime_remote_time,
2777 fetcher->context().realtime_remote_time);
2778
2779 this->Exit();
2780 });
2781
2782 EXPECT_FALSE(happened);
2783 Run();
2784 EXPECT_TRUE(happened);
2785}
2786
2787// Tests that a raw sender fills out sent data.
2788TEST_P(AbstractEventLoopTest, RawSenderSentData) {
2789 auto loop1 = MakePrimary();
2790
Austin Schuha9df9ad2021-06-16 14:49:39 -07002791 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2792 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08002793
2794 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002795 loop1->MakeRawSender(configuration::GetChannel(
2796 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08002797
Tyler Chatow67ddb032020-01-12 14:30:04 -08002798 const aos::monotonic_clock::time_point monotonic_now = loop1->monotonic_now();
2799 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08002800
milind1f1dca32021-07-03 13:50:07 -07002801 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2802 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08002803
2804 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
2805 EXPECT_LE(sender->monotonic_sent_time(),
2806 monotonic_now + chrono::milliseconds(100));
2807 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
2808 EXPECT_LE(sender->realtime_sent_time(),
2809 realtime_now + chrono::milliseconds(100));
2810 EXPECT_EQ(sender->sent_queue_index(), 0u);
2811
milind1f1dca32021-07-03 13:50:07 -07002812 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2813 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08002814
2815 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
2816 EXPECT_LE(sender->monotonic_sent_time(),
2817 monotonic_now + chrono::milliseconds(100));
2818 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
2819 EXPECT_LE(sender->realtime_sent_time(),
2820 realtime_now + chrono::milliseconds(100));
2821 EXPECT_EQ(sender->sent_queue_index(), 1u);
2822}
2823
Austin Schuh217a9782019-12-21 23:02:50 -08002824// Tests that not setting up nodes results in no node.
2825TEST_P(AbstractEventLoopTest, NoNode) {
2826 auto loop1 = Make();
2827 auto loop2 = MakePrimary();
2828
2829 EXPECT_EQ(loop1->node(), nullptr);
2830 EXPECT_EQ(loop2->node(), nullptr);
2831}
2832
2833// Tests that setting up nodes results in node being set.
2834TEST_P(AbstractEventLoopTest, Node) {
2835 EnableNodes("me");
2836
2837 auto loop1 = Make();
2838 auto loop2 = MakePrimary();
2839
2840 EXPECT_NE(loop1->node(), nullptr);
2841 EXPECT_NE(loop2->node(), nullptr);
2842}
2843
2844// Tests that watchers work with a node setup.
2845TEST_P(AbstractEventLoopTest, NodeWatcher) {
2846 EnableNodes("me");
2847
2848 auto loop1 = Make();
2849 auto loop2 = Make();
2850 loop1->MakeWatcher("/test", [](const TestMessage &) {});
Tyler Chatow67ddb032020-01-12 14:30:04 -08002851 loop2->MakeRawWatcher(
2852 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
2853 nullptr),
2854 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08002855}
2856
Brian Silverman454bc112020-03-05 14:21:25 -08002857// Tests that no-arg watchers work with a node setup.
2858TEST_P(AbstractEventLoopTest, NodeNoArgWatcher) {
2859 EnableNodes("me");
2860
2861 auto loop1 = Make();
2862 auto loop2 = Make();
2863 loop1->MakeWatcher("/test", [](const TestMessage &) {});
2864 loop2->MakeRawNoArgWatcher(
2865 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
2866 nullptr),
2867 [](const Context &) {});
2868}
2869
Austin Schuh217a9782019-12-21 23:02:50 -08002870// Tests that fetcher work with a node setup.
2871TEST_P(AbstractEventLoopTest, NodeFetcher) {
2872 EnableNodes("me");
2873 auto loop1 = Make();
2874
2875 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
Tyler Chatow67ddb032020-01-12 14:30:04 -08002876 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
2877 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08002878}
2879
2880// Tests that sender work with a node setup.
2881TEST_P(AbstractEventLoopTest, NodeSender) {
2882 EnableNodes("me");
2883 auto loop1 = Make();
2884
2885 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
2886}
2887
Austin Schuhcc6070c2020-10-10 20:25:56 -07002888// Tests that a non-realtime event loop timer is marked non-realtime.
2889TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopTimer) {
2890 auto loop1 = MakePrimary();
2891
2892 // Add a timer to actually quit.
2893 auto test_timer = loop1->AddTimer([this]() {
2894 CheckNotRealtime();
2895 this->Exit();
2896 });
2897
2898 loop1->OnRun([&test_timer, &loop1]() {
2899 CheckNotRealtime();
Philipp Schradera6712522023-07-05 20:25:11 -07002900 test_timer->Schedule(loop1->monotonic_now(),
2901 ::std::chrono::milliseconds(100));
Austin Schuhcc6070c2020-10-10 20:25:56 -07002902 });
2903
2904 Run();
2905}
2906
2907// Tests that a realtime event loop timer is marked realtime.
Austin Schuh9b1d6282022-06-10 17:03:21 -07002908TEST_P(AbstractEventLoopTest, RealtimeSend) {
2909 auto loop1 = MakePrimary();
2910
2911 loop1->SetRuntimeRealtimePriority(1);
2912
2913 auto sender = loop1->MakeSender<TestMessage>("/test2");
2914
2915 loop1->OnRun([&]() {
2916 CheckRealtime();
2917
2918 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2919 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2920 builder.add_value(200);
2921 msg.CheckOk(msg.Send(builder.Finish()));
2922
2923 this->Exit();
2924 });
2925
2926 Run();
2927}
2928
2929// Tests that a realtime event loop timer is marked realtime.
Austin Schuhcc6070c2020-10-10 20:25:56 -07002930TEST_P(AbstractEventLoopTest, RealtimeEventLoopTimer) {
2931 auto loop1 = MakePrimary();
2932
2933 loop1->SetRuntimeRealtimePriority(1);
2934
2935 // Add a timer to actually quit.
2936 auto test_timer = loop1->AddTimer([this]() {
2937 CheckRealtime();
2938 this->Exit();
2939 });
2940
2941 loop1->OnRun([&test_timer, &loop1]() {
2942 CheckRealtime();
Philipp Schradera6712522023-07-05 20:25:11 -07002943 test_timer->Schedule(loop1->monotonic_now(),
2944 ::std::chrono::milliseconds(100));
Austin Schuhcc6070c2020-10-10 20:25:56 -07002945 });
2946
2947 Run();
2948}
2949
2950// Tests that a non-realtime event loop phased loop is marked non-realtime.
2951TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopPhasedLoop) {
2952 auto loop1 = MakePrimary();
2953
2954 // Add a timer to actually quit.
2955 loop1->AddPhasedLoop(
2956 [this](int) {
2957 CheckNotRealtime();
2958 this->Exit();
2959 },
2960 chrono::seconds(1), chrono::seconds(0));
2961
2962 Run();
2963}
2964
2965// Tests that a realtime event loop phased loop is marked realtime.
2966TEST_P(AbstractEventLoopTest, RealtimeEventLoopPhasedLoop) {
2967 auto loop1 = MakePrimary();
2968
2969 loop1->SetRuntimeRealtimePriority(1);
2970
2971 // Add a timer to actually quit.
2972 loop1->AddPhasedLoop(
2973 [this](int) {
2974 CheckRealtime();
2975 this->Exit();
2976 },
2977 chrono::seconds(1), chrono::seconds(0));
2978
2979 Run();
2980}
2981
2982// Tests that a non-realtime event loop watcher is marked non-realtime.
2983TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopWatcher) {
2984 auto loop1 = MakePrimary();
2985 auto loop2 = Make();
2986
2987 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
2988
2989 loop1->OnRun([&]() {
2990 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2991 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07002992 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07002993 });
2994
2995 loop1->MakeWatcher("/test", [&](const TestMessage &) {
2996 CheckNotRealtime();
2997 this->Exit();
2998 });
2999
3000 Run();
3001}
3002
3003// Tests that a realtime event loop watcher is marked realtime.
3004TEST_P(AbstractEventLoopTest, RealtimeEventLoopWatcher) {
3005 auto loop1 = MakePrimary();
3006 auto loop2 = Make();
3007
3008 loop1->SetRuntimeRealtimePriority(1);
3009
3010 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
3011
3012 loop1->OnRun([&]() {
3013 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3014 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07003015 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003016 });
3017
3018 loop1->MakeWatcher("/test", [&](const TestMessage &) {
3019 CheckRealtime();
3020 this->Exit();
3021 });
3022
3023 Run();
3024}
3025
Austin Schuha9012be2021-07-21 15:19:11 -07003026// Tests that event loop's context's monotonic time is set to a value on OnRun.
3027TEST_P(AbstractEventLoopTest, SetContextOnRun) {
3028 auto loop = MakePrimary();
3029
Austin Schuh0debde12022-08-17 16:25:17 -07003030 EXPECT_EQ(loop->context().monotonic_event_time, monotonic_clock::min_time);
3031 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3032 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3033 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3034 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3035 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
3036 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
3037 EXPECT_EQ(loop->context().size, 0u);
3038 EXPECT_EQ(loop->context().data, nullptr);
3039 EXPECT_EQ(loop->context().buffer_index, -1);
3040
Austin Schuha9012be2021-07-21 15:19:11 -07003041 // We want to check that monotonic event time is before monotonic now
3042 // called inside of callback, but after time point obtained callback.
3043 aos::monotonic_clock::time_point monotonic_event_time_on_run;
3044
3045 loop->OnRun([&]() {
3046 monotonic_event_time_on_run = loop->context().monotonic_event_time;
3047 EXPECT_LE(monotonic_event_time_on_run, loop->monotonic_now());
3048 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3049 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3050 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3051 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3052 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
Austin Schuh0debde12022-08-17 16:25:17 -07003053 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
Austin Schuha9012be2021-07-21 15:19:11 -07003054 EXPECT_EQ(loop->context().size, 0u);
3055 EXPECT_EQ(loop->context().data, nullptr);
3056 EXPECT_EQ(loop->context().buffer_index, -1);
3057 });
3058
3059 EndEventLoop(loop.get(), ::std::chrono::milliseconds(200));
3060
3061 const aos::monotonic_clock::time_point before_run_time =
3062 loop->monotonic_now();
3063 Run();
3064 EXPECT_GE(monotonic_event_time_on_run, before_run_time);
Austin Schuh0debde12022-08-17 16:25:17 -07003065
3066 EXPECT_EQ(loop->context().monotonic_event_time, monotonic_clock::min_time);
3067 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3068 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3069 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3070 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3071 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
3072 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
3073 EXPECT_EQ(loop->context().size, 0u);
3074 EXPECT_EQ(loop->context().data, nullptr);
3075 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuha9012be2021-07-21 15:19:11 -07003076}
3077
Austin Schuh217a9782019-12-21 23:02:50 -08003078// Tests that watchers fail when created on the wrong node.
3079TEST_P(AbstractEventLoopDeathTest, NodeWatcher) {
3080 EnableNodes("them");
3081
3082 auto loop1 = Make();
3083 auto loop2 = Make();
3084 EXPECT_DEATH({ loop1->MakeWatcher("/test", [](const TestMessage &) {}); },
3085 "node");
3086 EXPECT_DEATH(
3087 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08003088 loop2->MakeRawWatcher(
3089 configuration::GetChannel(configuration(), "/test",
3090 "aos.TestMessage", "", nullptr),
3091 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08003092 },
3093 "node");
Brian Silverman454bc112020-03-05 14:21:25 -08003094 EXPECT_DEATH({ loop1->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
3095 "node");
3096 EXPECT_DEATH(
3097 {
3098 loop2->MakeRawNoArgWatcher(
3099 configuration::GetChannel(configuration(), "/test",
3100 "aos.TestMessage", "", nullptr),
3101 [](const Context &) {});
3102 },
3103 "node");
Austin Schuh217a9782019-12-21 23:02:50 -08003104}
3105
3106// Tests that fetchers fail when created on the wrong node.
3107TEST_P(AbstractEventLoopDeathTest, NodeFetcher) {
3108 EnableNodes("them");
3109 auto loop1 = Make();
3110
3111 EXPECT_DEATH({ auto fetcher = loop1->MakeFetcher<TestMessage>("/test"); },
3112 "node");
3113 EXPECT_DEATH(
3114 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08003115 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
3116 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08003117 },
3118 "node");
3119}
3120
3121// Tests that senders fail when created on the wrong node.
3122TEST_P(AbstractEventLoopDeathTest, NodeSender) {
3123 EnableNodes("them");
3124 auto loop1 = Make();
3125
3126 EXPECT_DEATH(
3127 {
3128 aos::Sender<TestMessage> sender =
3129 loop1->MakeSender<TestMessage>("/test");
3130 },
3131 "node");
3132
3133 // Note: Creating raw senders is always supported. Right now, this lets us
3134 // use them to create message_gateway.
3135}
3136
Brian Silverman341b57e2020-06-23 16:23:18 -07003137// Tests creating multiple Builders from a single Sender at the same time.
3138TEST_P(AbstractEventLoopDeathTest, MultipleBuilders) {
3139 auto loop1 = Make();
3140 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
3141
3142 { auto builder = sender.MakeBuilder(); }
3143 {
3144 auto builder = sender.MakeBuilder();
3145 builder.MakeBuilder<TestMessage>().Finish();
3146 }
3147 {
3148 // Creating this after the first one was destroyed should be fine.
3149 auto builder = sender.MakeBuilder();
3150 builder.MakeBuilder<TestMessage>().Finish();
3151 // But not a second one.
3152 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
3153 "May not overwrite in-use allocator");
3154 }
3155
3156 FlatbufferDetachedBuffer<TestMessage> detached =
3157 flatbuffers::DetachedBuffer();
3158 {
3159 auto builder = sender.MakeBuilder();
3160 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
3161 }
3162 {
3163 // This is the second one, after the detached one, so it should fail.
3164 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
3165 "May not overwrite in-use allocator");
3166 }
3167
3168 // Clear the detached one, and then we should be able to create another.
3169 detached = flatbuffers::DetachedBuffer();
3170 {
3171 auto builder = sender.MakeBuilder();
3172 builder.MakeBuilder<TestMessage>().Finish();
3173 }
3174
3175 // And then detach another one.
3176 {
3177 auto builder = sender.MakeBuilder();
3178 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
3179 }
3180}
3181
3182// Tests sending a buffer detached from a different builder.
3183TEST_P(AbstractEventLoopDeathTest, WrongDetachedBuffer) {
3184 auto loop1 = Make();
3185 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
3186 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
3187
3188 auto builder = sender1.MakeBuilder();
3189 FlatbufferDetachedBuffer<TestMessage> detached =
3190 builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
milind1f1dca32021-07-03 13:50:07 -07003191 EXPECT_DEATH(sender2.CheckOk(sender2.SendDetached(std::move(detached))),
Brian Silverman341b57e2020-06-23 16:23:18 -07003192 "May only send the buffer detached from this Sender");
3193}
3194
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003195int TestChannelFrequency(EventLoop *event_loop) {
3196 return event_loop->GetChannel<TestMessage>("/test")->frequency();
3197}
3198
3199int TestChannelQueueSize(EventLoop *event_loop) {
Austin Schuhfff9c3a2023-06-16 18:48:23 -07003200 return configuration::QueueSize(event_loop->configuration(),
3201 event_loop->GetChannel<TestMessage>("/test"));
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003202}
3203
3204RawSender::Error SendTestMessage(aos::Sender<TestMessage> &sender) {
3205 aos::Sender<TestMessage>::Builder builder = sender.MakeBuilder();
3206 TestMessage::Builder test_message_builder =
3207 builder.MakeBuilder<TestMessage>();
3208 test_message_builder.add_value(0);
3209 return builder.Send(test_message_builder.Finish());
3210}
3211
3212// Test that sending messages too fast returns
3213// RawSender::Error::kMessagesSentTooFast.
3214TEST_P(AbstractEventLoopTest, SendingMessagesTooFast) {
3215 auto event_loop = MakePrimary();
3216
3217 auto sender = event_loop->MakeSender<TestMessage>("/test");
3218
3219 // Send one message in the beginning, then wait until the
3220 // channel_storage_duration is almost done and start sending messages rapidly,
3221 // having some come in the next chanel_storage_duration. The queue_size is
3222 // 1600, so the 1601st message will be the last valid one (the initial message
3223 // having being sent more than a channel_storage_duration ago), and trying to
3224 // send the 1602nd message should return
3225 // RawSender::Error::kMessagesSentTooFast.
3226 EXPECT_EQ(SendTestMessage(sender), RawSender::Error::kOk);
3227 int msgs_sent = 1;
3228 const int queue_size = TestChannelQueueSize(event_loop.get());
3229
3230 const auto timer = event_loop->AddTimer([&]() {
3231 const bool done = (msgs_sent == queue_size + 1);
3232 ASSERT_EQ(
3233 SendTestMessage(sender),
3234 done ? RawSender::Error::kMessagesSentTooFast : RawSender::Error::kOk);
3235 msgs_sent++;
3236 if (done) {
3237 Exit();
3238 }
3239 });
3240
3241 const auto kRepeatOffset = std::chrono::milliseconds(1);
Austin Schuhfff9c3a2023-06-16 18:48:23 -07003242 const auto base_offset = configuration::ChannelStorageDuration(
3243 event_loop->configuration(), sender.channel()) -
3244 (kRepeatOffset * (queue_size / 2));
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003245 event_loop->OnRun([&event_loop, &timer, &base_offset, &kRepeatOffset]() {
Philipp Schradera6712522023-07-05 20:25:11 -07003246 timer->Schedule(event_loop->monotonic_now() + base_offset, kRepeatOffset);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003247 });
3248
3249 Run();
3250}
3251
3252// Tests that we are able to send messages successfully after sending messages
3253// too fast and waiting while continuously attempting to send messages.
3254// Also tests that SendFailureCounter is working correctly in this
3255// situation
3256TEST_P(AbstractEventLoopTest, SendingAfterSendingTooFast) {
3257 auto event_loop = MakePrimary();
3258
3259 auto sender = event_loop->MakeSender<TestMessage>("/test");
3260
Austin Schuh0e96d372023-05-08 10:10:21 -07003261 // We are sending bunches of messages at 100 Hz, so we will be sending too
3262 // fast after queue_size (800) ms. After this, keep sending messages, and
3263 // exactly a channel storage duration (2s) after we send the first message we
3264 // should be able to successfully send a message.
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003265
Austin Schuh0e96d372023-05-08 10:10:21 -07003266 const std::chrono::milliseconds kInterval = std::chrono::milliseconds(10);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003267 const monotonic_clock::duration channel_storage_duration =
Austin Schuhfff9c3a2023-06-16 18:48:23 -07003268 configuration::ChannelStorageDuration(event_loop->configuration(),
3269 sender.channel());
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003270 const int queue_size = TestChannelQueueSize(event_loop.get());
3271
3272 int msgs_sent = 0;
3273 SendFailureCounter counter;
3274 auto start = monotonic_clock::min_time;
3275
3276 event_loop->AddPhasedLoop(
Austin Schuh0e96d372023-05-08 10:10:21 -07003277 [&](int elapsed_cycles) {
3278 // The queue is setup for 800 messages/sec. We want to fill that up at
3279 // a rate of 2000 messages/sec so we make sure we fill it up.
3280 for (int i = 0; i < 2 * kInterval.count() * elapsed_cycles; ++i) {
3281 const auto actual_err = SendTestMessage(sender);
3282 const bool done_waiting = (start != monotonic_clock::min_time &&
3283 sender.monotonic_sent_time() >=
3284 (start + channel_storage_duration));
3285 const auto expected_err =
3286 (msgs_sent < queue_size || done_waiting
3287 ? RawSender::Error::kOk
3288 : RawSender::Error::kMessagesSentTooFast);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003289
Austin Schuh0e96d372023-05-08 10:10:21 -07003290 if (start == monotonic_clock::min_time) {
3291 start = sender.monotonic_sent_time();
3292 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003293
Austin Schuh0e96d372023-05-08 10:10:21 -07003294 ASSERT_EQ(actual_err, expected_err);
3295 counter.Count(actual_err);
3296 msgs_sent++;
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003297
Austin Schuh0e96d372023-05-08 10:10:21 -07003298 EXPECT_EQ(counter.failures(),
3299 msgs_sent <= queue_size
3300 ? 0
3301 : (msgs_sent - queue_size) -
3302 (actual_err == RawSender::Error::kOk ? 1 : 0));
3303 EXPECT_EQ(counter.just_failed(), actual_err != RawSender::Error::kOk);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003304
Austin Schuh0e96d372023-05-08 10:10:21 -07003305 if (done_waiting) {
3306 Exit();
3307 return;
3308 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003309 }
3310 },
3311 kInterval);
3312 Run();
3313}
3314
3315// Tests that RawSender::Error::kMessagesSentTooFast is returned
3316// when messages are sent too fast from senders in different loops
3317TEST_P(AbstractEventLoopTest, SendingTooFastWithMultipleLoops) {
3318 auto loop1 = MakePrimary();
3319 auto loop2 = Make();
3320
3321 auto sender1 = loop1->MakeSender<TestMessage>("/test");
3322 auto sender2 = loop2->MakeSender<TestMessage>("/test");
3323
3324 // Send queue_size messages split between the senders.
3325 const int queue_size = TestChannelQueueSize(loop1.get());
3326 for (int i = 0; i < queue_size / 2; i++) {
3327 ASSERT_EQ(SendTestMessage(sender1), RawSender::Error::kOk);
3328 ASSERT_EQ(SendTestMessage(sender2), RawSender::Error::kOk);
3329 }
3330
3331 // Since queue_size messages have been sent, this should return an error
3332 EXPECT_EQ(SendTestMessage(sender2), RawSender::Error::kMessagesSentTooFast);
3333}
3334
Parker Schuhe4a70d62017-12-27 20:10:20 -08003335} // namespace testing
3336} // namespace aos