blob: beb5e7828b5e0c7a497580d90ab2b99e13258413 [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]() {
397 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
398 });
399
400 Run();
401 EXPECT_EQ(0, values.size());
402}
403
Austin Schuhbbce72d2019-05-26 15:11:46 -0700404// Tests that FetchNext gets all the messages sent after it is constructed.
405TEST_P(AbstractEventLoopTest, FetchNext) {
406 auto loop1 = Make();
407 auto loop2 = MakePrimary();
408
409 auto sender = loop1->MakeSender<TestMessage>("/test");
410 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
411
412 ::std::vector<int> values;
413
414 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700415 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
416 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
417 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700418 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700419 }
420 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700421 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
422 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
423 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700424 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700425 }
426
427 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700428 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700429 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700430 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700431 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700432 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700433 });
434
435 loop2->OnRun([&test_timer, &loop2]() {
436 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
437 });
438
439 Run();
440 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
441}
442
443// Tests that FetchNext gets no messages sent before it is constructed.
444TEST_P(AbstractEventLoopTest, FetchNextAfterSend) {
445 auto loop1 = Make();
446 auto loop2 = MakePrimary();
447
448 auto sender = loop1->MakeSender<TestMessage>("/test");
449
450 ::std::vector<int> values;
451
452 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700453 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
454 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
455 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700456 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700457 }
458 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700459 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
460 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
461 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700462 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700463 }
464
465 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
466
467 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700468 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700469 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700470 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700471 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700472 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700473 });
474
475 loop2->OnRun([&test_timer, &loop2]() {
476 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
477 });
478
479 Run();
480 EXPECT_THAT(0, values.size());
481}
482
483// Tests that Fetch returns the last message created before the loop was
484// started.
485TEST_P(AbstractEventLoopTest, FetchDataFromBeforeCreation) {
486 auto loop1 = Make();
487 auto loop2 = MakePrimary();
488
489 auto sender = loop1->MakeSender<TestMessage>("/test");
490
491 ::std::vector<int> values;
492
493 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700494 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
495 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
496 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700497 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700498 }
499 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700500 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
501 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
502 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700503 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700504 }
505
506 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
507
508 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700509 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700510 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700511 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700512 }
513 // Do it again to make sure we don't double fetch.
514 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700515 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700516 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700517 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700518 });
519
520 loop2->OnRun([&test_timer, &loop2]() {
521 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
522 });
523
524 Run();
525 EXPECT_THAT(values, ::testing::ElementsAreArray({201}));
526}
527
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700528// Tests that timer handler is enabled after setup (even if it is in the past)
529// and is disabled after running
530TEST_P(AbstractEventLoopTest, CheckTimerDisabled) {
531 auto loop = MakePrimary("primary");
532
533 auto timer = loop->AddTimer([this]() {
534 LOG(INFO) << "timer called";
535 Exit();
536 });
537
538 loop->OnRun([&loop, timer]() {
539 EXPECT_TRUE(timer->IsDisabled());
540 timer->Setup(loop->monotonic_now() + chrono::milliseconds(100));
541 EXPECT_FALSE(timer->IsDisabled());
542 });
543
544 Run();
545 EXPECT_TRUE(timer->IsDisabled());
546}
547
548// Tests that timer handler is enabled after setup (even if it is in the past)
549// and is disabled after running
550TEST_P(AbstractEventLoopTest, CheckTimerRunInPastDisabled) {
551 auto loop = MakePrimary("primary");
552
553 auto timer2 = loop->AddTimer([this]() {
554 LOG(INFO) << "timer called";
555 Exit();
556 });
557
558 auto timer = loop->AddTimer([&loop, timer2]() {
559 timer2->Setup(loop->monotonic_now() - chrono::nanoseconds(1));
560 });
561
562 loop->OnRun([&loop, timer]() {
563 timer->Setup(loop->monotonic_now() + chrono::seconds(1));
564 EXPECT_FALSE(timer->IsDisabled());
565 });
566
567 Run();
568 EXPECT_TRUE(timer2->IsDisabled());
569}
570
571// Tests that timer handler is not disabled even after calling Exit on the event
572// loop within the timer
573TEST_P(AbstractEventLoopTest, CheckTimerRepeatOnCountDisabled) {
574 auto loop = MakePrimary("primary");
575 int counter = 0;
576
577 auto timer = loop->AddTimer([&counter, this]() {
578 LOG(INFO) << "timer called";
579 counter++;
580 if (counter >= 5) {
581 Exit();
582 }
583 });
584
585 loop->OnRun([&loop, timer]() {
586 timer->Setup(loop->monotonic_now() + chrono::seconds(1),
587 chrono::seconds(1));
588 EXPECT_FALSE(timer->IsDisabled());
589 });
590 Run();
591
592 // Sanity check
593 EXPECT_EQ(counter, 5);
594
595 // if you run the loop again, the timer will start running again
596 EXPECT_FALSE(timer->IsDisabled());
597
598 counter = 0;
599 Run();
600 timer->Disable();
601
602 EXPECT_TRUE(timer->IsDisabled());
603}
604
605// Tests that timer handler is not disabled even after calling Exit on the event
606// loop using an external timer
607TEST_P(AbstractEventLoopTest, CheckTimerRepeatTillEndTimerDisabled) {
608 auto loop = MakePrimary("primary");
609
610 auto timer = loop->AddTimer([]() { LOG(INFO) << "timer called"; });
611
612 loop->OnRun([&loop, timer]() {
613 timer->Setup(loop->monotonic_now() + chrono::seconds(1),
614 chrono::seconds(1));
615 EXPECT_FALSE(timer->IsDisabled());
616 });
617
618 EndEventLoop(loop.get(), chrono::seconds(5));
619 Run();
620 EXPECT_FALSE(timer->IsDisabled());
621
622 timer->Disable();
623 EXPECT_TRUE(timer->IsDisabled());
624}
625
Austin Schuhbbce72d2019-05-26 15:11:46 -0700626// Tests that Fetch and FetchNext interleave as expected.
627TEST_P(AbstractEventLoopTest, FetchAndFetchNextTogether) {
628 auto loop1 = Make();
629 auto loop2 = MakePrimary();
630
631 auto sender = loop1->MakeSender<TestMessage>("/test");
632
633 ::std::vector<int> values;
634
635 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700636 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
637 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
638 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700639 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700640 }
641 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700642 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
643 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
644 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700645 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700646 }
647
648 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
649
650 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700651 auto test_timer = loop2->AddTimer([&fetcher, &values, &sender, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700652 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700653 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700654 }
655
656 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700657 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
658 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
659 builder.add_value(202);
milind1f1dca32021-07-03 13:50:07 -0700660 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700661 }
662 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700663 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
664 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
665 builder.add_value(203);
milind1f1dca32021-07-03 13:50:07 -0700666 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700667 }
668 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700669 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
670 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
671 builder.add_value(204);
milind1f1dca32021-07-03 13:50:07 -0700672 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700673 }
674
675 if (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700676 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700677 }
678
679 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700680 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700681 }
682
Austin Schuh9fe68f72019-08-10 19:32:03 -0700683 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700684 });
685
686 loop2->OnRun([&test_timer, &loop2]() {
687 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
688 });
689
690 Run();
691 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
692}
693
Austin Schuh3115a202019-05-27 21:02:14 -0700694// Tests that FetchNext behaves correctly when we get two messages in the queue
695// but don't consume the first until after the second has been sent.
696TEST_P(AbstractEventLoopTest, FetchNextTest) {
Austin Schuh3115a202019-05-27 21:02:14 -0700697 auto send_loop = Make();
698 auto fetch_loop = Make();
699 auto sender = send_loop->MakeSender<TestMessage>("/test");
700 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
701
702 {
Tyler Chatow67ddb032020-01-12 14:30:04 -0800703 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
704 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
705 builder.add_value(100);
milind1f1dca32021-07-03 13:50:07 -0700706 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700707 }
708
709 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700710 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
711 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
712 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700713 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700714 }
715
716 ASSERT_TRUE(fetcher.FetchNext());
717 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700718 EXPECT_EQ(100, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700719
720 ASSERT_TRUE(fetcher.FetchNext());
721 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700722 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700723
724 // When we run off the end of the queue, expect to still have the old message:
725 ASSERT_FALSE(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
Brian Silverman77162972020-08-12 19:52:40 -0700730// Verify that a fetcher still holds its data, even after falling behind.
731TEST_P(AbstractEventLoopTest, FetcherBehindData) {
732 auto send_loop = Make();
733 auto fetch_loop = Make();
734 auto sender = send_loop->MakeSender<TestMessage>("/test");
735 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
736 {
737 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
738 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
739 builder.add_value(1);
milind1f1dca32021-07-03 13:50:07 -0700740 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -0700741 }
742 ASSERT_TRUE(fetcher.Fetch());
743 EXPECT_EQ(1, fetcher.get()->value());
744 for (int i = 0; i < 300; ++i) {
745 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
746 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
747 builder.add_value(i + 2);
milind1f1dca32021-07-03 13:50:07 -0700748 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -0700749 }
750 EXPECT_EQ(1, fetcher.get()->value());
751}
752
753// Try a bunch of orderings of operations with fetchers and senders. Verify that
754// all the fetchers have the correct data at each step.
755TEST_P(AbstractEventLoopTest, FetcherPermutations) {
756 for (int max_save = 0; max_save < 5; ++max_save) {
757 SCOPED_TRACE("max_save=" + std::to_string(max_save));
758
759 auto send_loop = Make();
760 auto fetch_loop = Make();
761 auto sender = send_loop->MakeSender<TestMessage>("/test");
762 const auto send_message = [&sender](int i) {
763 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
764 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
765 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700766 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -0700767 };
768 std::vector<Fetcher<TestMessage>> fetchers;
769 for (int i = 0; i < 10; ++i) {
770 fetchers.emplace_back(fetch_loop->MakeFetcher<TestMessage>("/test"));
771 }
772 send_message(1);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700773 const auto verify_buffers = [&]() {
774 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>>
775 fetchers_copy;
776 for (const auto &fetcher : fetchers) {
777 fetchers_copy.emplace_back(fetcher);
778 }
779 std::vector<std::reference_wrapper<const Sender<TestMessage>>>
780 senders_copy;
781 senders_copy.emplace_back(sender);
782 VerifyBuffers(send_loop->NumberBuffers(sender.channel()), fetchers_copy,
783 senders_copy);
784 };
Brian Silverman77162972020-08-12 19:52:40 -0700785 for (auto &fetcher : fetchers) {
786 ASSERT_TRUE(fetcher.Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -0700787 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700788 EXPECT_EQ(1, fetcher.get()->value());
789 }
790
791 for (int save = 1; save <= max_save; ++save) {
792 SCOPED_TRACE("save=" + std::to_string(save));
793 send_message(100 + save);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700794 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700795 for (size_t i = 0; i < fetchers.size() - save; ++i) {
796 SCOPED_TRACE("fetcher=" + std::to_string(i));
797 ASSERT_TRUE(fetchers[i].Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -0700798 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700799 EXPECT_EQ(100 + save, fetchers[i].get()->value());
800 }
801 for (size_t i = fetchers.size() - save; i < fetchers.size() - 1; ++i) {
802 SCOPED_TRACE("fetcher=" + std::to_string(i));
803 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
804 }
805 EXPECT_EQ(1, fetchers.back().get()->value());
806 }
807
808 for (int i = 0; i < 300; ++i) {
809 send_message(200 + i);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700810 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700811 }
812
813 for (size_t i = 0; i < fetchers.size() - max_save; ++i) {
814 SCOPED_TRACE("fetcher=" + std::to_string(i));
815 if (max_save > 0) {
816 EXPECT_EQ(100 + max_save, fetchers[i].get()->value());
817 } else {
818 EXPECT_EQ(1, fetchers[i].get()->value());
819 }
820 }
821 for (size_t i = fetchers.size() - max_save; i < fetchers.size() - 1; ++i) {
822 SCOPED_TRACE("fetcher=" + std::to_string(i));
823 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
824 }
825 EXPECT_EQ(1, fetchers.back().get()->value());
826 }
827}
828
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800829// Verify that making a fetcher and watcher for "/test" succeeds.
830TEST_P(AbstractEventLoopTest, FetcherAndWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800831 auto loop = Make();
832 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800833 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Parker Schuhe4a70d62017-12-27 20:10:20 -0800834}
835
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800836// Verify that making 2 fetchers for "/test" succeeds.
Parker Schuhe4a70d62017-12-27 20:10:20 -0800837TEST_P(AbstractEventLoopTest, TwoFetcher) {
838 auto loop = Make();
839 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800840 auto fetcher2 = loop->MakeFetcher<TestMessage>("/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -0800841}
842
Alex Perrycb7da4b2019-08-28 19:35:56 -0700843// Verify that registering a watcher for an invalid channel name dies.
844TEST_P(AbstractEventLoopDeathTest, InvalidChannelName) {
845 auto loop = Make();
846 EXPECT_DEATH(
847 { loop->MakeWatcher("/test/invalid", [&](const TestMessage &) {}); },
848 "/test/invalid");
Brian Silverman454bc112020-03-05 14:21:25 -0800849 EXPECT_DEATH(
850 { loop->MakeNoArgWatcher<TestMessage>("/test/invalid", [&]() {}); },
851 "/test/invalid");
Alex Perrycb7da4b2019-08-28 19:35:56 -0700852}
853
James Kuszmaul8866e642022-06-10 16:00:36 -0700854// Verify that setting up a timer before monotonic_clock::epoch() fails.
James Kuszmaul86e86c32022-07-21 17:39:47 -0700855TEST_P(AbstractEventLoopDeathTest, NegativeTimeTimer) {
James Kuszmaul8866e642022-06-10 16:00:36 -0700856 auto loop = Make();
857 TimerHandler *time = loop->AddTimer([]() {});
858 EXPECT_DEATH(time->Setup(monotonic_clock::epoch() - std::chrono::seconds(1)),
859 "-1.000");
860}
861
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800862// Verify that registering a watcher twice for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700863TEST_P(AbstractEventLoopDeathTest, TwoWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800864 auto loop = Make();
865 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800866 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
867 "/test");
Brian Silverman454bc112020-03-05 14:21:25 -0800868 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
869}
870
871// Verify that registering a no-arg watcher twice for "/test" fails.
872TEST_P(AbstractEventLoopDeathTest, TwoNoArgWatcher) {
873 auto loop = Make();
874 loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {});
875 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
876 "/test");
877 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800878}
879
Austin Schuh3115a202019-05-27 21:02:14 -0700880// Verify that SetRuntimeRealtimePriority fails while running.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700881TEST_P(AbstractEventLoopDeathTest, SetRuntimeRealtimePriority) {
Austin Schuh3115a202019-05-27 21:02:14 -0700882 auto loop = MakePrimary();
Austin Schuh65493d62022-08-17 15:10:37 -0700883 EXPECT_EQ(0, loop->runtime_realtime_priority());
Austin Schuh3115a202019-05-27 21:02:14 -0700884 // Confirm that runtime priority calls work when not realtime.
885 loop->SetRuntimeRealtimePriority(5);
Austin Schuh65493d62022-08-17 15:10:37 -0700886 EXPECT_EQ(5, loop->runtime_realtime_priority());
Austin Schuh3115a202019-05-27 21:02:14 -0700887
888 loop->OnRun([&]() { loop->SetRuntimeRealtimePriority(5); });
889
890 EXPECT_DEATH(Run(), "realtime");
891}
892
Austin Schuh65493d62022-08-17 15:10:37 -0700893namespace {
894
895bool CpuSetEqual(const cpu_set_t &a, const cpu_set_t &b) {
896 return CPU_EQUAL(&a, &b);
897}
898
899} // namespace
900
Brian Silverman6a54ff32020-04-28 16:41:39 -0700901// Verify that SetRuntimeAffinity fails while running.
902TEST_P(AbstractEventLoopDeathTest, SetRuntimeAffinity) {
Austin Schuhde973292021-10-12 18:09:49 -0700903 const cpu_set_t available = GetCurrentThreadAffinity();
904 int first_cpu = -1;
905 for (int i = 0; i < CPU_SETSIZE; ++i) {
906 if (CPU_ISSET(i, &available)) {
907 first_cpu = i;
908 break;
909 continue;
910 }
911 }
912 CHECK_NE(first_cpu, -1) << ": Default affinity has no CPUs?";
913
Brian Silverman6a54ff32020-04-28 16:41:39 -0700914 auto loop = MakePrimary();
Austin Schuh65493d62022-08-17 15:10:37 -0700915 EXPECT_TRUE(
916 CpuSetEqual(EventLoop::DefaultAffinity(), loop->runtime_affinity()));
917 const cpu_set_t new_affinity = MakeCpusetFromCpus({first_cpu});
Brian Silverman6a54ff32020-04-28 16:41:39 -0700918 // Confirm that runtime priority calls work when not running.
Austin Schuh65493d62022-08-17 15:10:37 -0700919 loop->SetRuntimeAffinity(new_affinity);
920 EXPECT_TRUE(CpuSetEqual(new_affinity, loop->runtime_affinity()));
Brian Silverman6a54ff32020-04-28 16:41:39 -0700921
Austin Schuhde973292021-10-12 18:09:49 -0700922 loop->OnRun(
923 [&]() { loop->SetRuntimeAffinity(MakeCpusetFromCpus({first_cpu})); });
Brian Silverman6a54ff32020-04-28 16:41:39 -0700924
925 EXPECT_DEATH(Run(), "Cannot set affinity while running");
926}
927
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800928// Verify that registering a watcher and a sender for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700929TEST_P(AbstractEventLoopDeathTest, WatcherAndSender) {
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800930 auto loop = Make();
931 auto sender = loop->MakeSender<TestMessage>("/test");
932 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
933 "/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -0800934}
935
Austin Schuhe516ab02020-05-06 21:37:04 -0700936// Verify that creating too many senders fails.
937TEST_P(AbstractEventLoopDeathTest, TooManySenders) {
938 auto loop = Make();
939 std::vector<aos::Sender<TestMessage>> senders;
940 for (int i = 0; i < 10; ++i) {
941 senders.emplace_back(loop->MakeSender<TestMessage>("/test"));
942 }
943 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); },
944 "Failed to create sender on \\{ \"name\": \"/test\", \"type\": "
Brian Silverman77162972020-08-12 19:52:40 -0700945 "\"aos.TestMessage\"[^}]*\\ }, too many senders.");
946}
947
948// Verify that creating too many fetchers fails.
949TEST_P(AbstractEventLoopDeathTest, TooManyFetchers) {
950 if (read_method() != ReadMethod::PIN) {
951 // Other read methods don't limit the number of readers, so just skip this.
952 return;
953 }
954
955 auto loop = Make();
956 std::vector<aos::Fetcher<TestMessage>> fetchers;
957 for (int i = 0; i < 10; ++i) {
958 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
959 }
960 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
961 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
962 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
963}
964
965// Verify that creating too many fetchers, split between two event loops, fails.
966TEST_P(AbstractEventLoopDeathTest, TooManyFetchersTwoLoops) {
967 if (read_method() != ReadMethod::PIN) {
968 // Other read methods don't limit the number of readers, so just skip this.
969 return;
970 }
971
972 auto loop = Make();
973 auto loop2 = Make();
974 std::vector<aos::Fetcher<TestMessage>> fetchers;
975 for (int i = 0; i < 5; ++i) {
976 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
977 fetchers.emplace_back(loop2->MakeFetcher<TestMessage>("/test"));
978 }
979 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
980 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
981 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
982}
983
984// Verify that creating too many watchers fails.
985TEST_P(AbstractEventLoopDeathTest, TooManyWatchers) {
986 if (read_method() != ReadMethod::PIN) {
987 // Other read methods don't limit the number of readers, so just skip this.
988 return;
989 }
990
991 std::vector<std::unique_ptr<EventLoop>> loops;
992 for (int i = 0; i < 10; ++i) {
993 loops.emplace_back(Make());
994 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
995 }
996 EXPECT_DEATH({ Make()->MakeWatcher("/test", [](const TestMessage &) {}); },
997 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
998 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
999}
1000
1001// Verify that creating too many watchers and fetchers combined fails.
1002TEST_P(AbstractEventLoopDeathTest, TooManyWatchersAndFetchers) {
1003 if (read_method() != ReadMethod::PIN) {
1004 // Other read methods don't limit the number of readers, so just skip this.
1005 return;
1006 }
1007
1008 auto loop = Make();
1009 std::vector<aos::Fetcher<TestMessage>> fetchers;
1010 std::vector<std::unique_ptr<EventLoop>> loops;
1011 for (int i = 0; i < 5; ++i) {
1012 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1013 loops.emplace_back(Make());
1014 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
1015 }
1016 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1017 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1018 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
Austin Schuhe516ab02020-05-06 21:37:04 -07001019}
1020
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001021// Verify that we can't create a sender inside OnRun.
1022TEST_P(AbstractEventLoopDeathTest, SenderInOnRun) {
1023 auto loop1 = MakePrimary();
1024
1025 loop1->OnRun(
1026 [&]() { auto sender = loop1->MakeSender<TestMessage>("/test2"); });
1027
1028 EXPECT_DEATH(Run(), "running");
1029}
1030
1031// Verify that we can't create a watcher inside OnRun.
1032TEST_P(AbstractEventLoopDeathTest, WatcherInOnRun) {
1033 auto loop1 = MakePrimary();
1034
1035 loop1->OnRun(
1036 [&]() { loop1->MakeWatcher("/test", [&](const TestMessage &) {}); });
1037
1038 EXPECT_DEATH(Run(), "running");
1039}
1040
Brian Silverman454bc112020-03-05 14:21:25 -08001041// Verify that we can't create a no-arg watcher inside OnRun.
1042TEST_P(AbstractEventLoopDeathTest, NoArgWatcherInOnRun) {
1043 auto loop1 = MakePrimary();
1044
1045 loop1->OnRun(
1046 [&]() { loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {}); });
1047
1048 EXPECT_DEATH(Run(), "running");
1049}
1050
Parker Schuhe4a70d62017-12-27 20:10:20 -08001051// Verify that Quit() works when there are multiple watchers.
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001052TEST_P(AbstractEventLoopTest, MultipleWatcherQuit) {
1053 auto loop1 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -07001054 auto loop2 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -08001055
Austin Schuh3578a2e2019-05-25 18:17:59 -07001056 loop2->MakeWatcher("/test1", [&](const TestMessage &) {});
1057 loop2->MakeWatcher("/test2", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001058 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -07001059 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -07001060 });
1061
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001062 auto sender = loop1->MakeSender<TestMessage>("/test2");
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001063
1064 loop2->OnRun([&]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001065 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1066 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1067 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001068 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001069 });
Parker Schuhe4a70d62017-12-27 20:10:20 -08001070
Austin Schuh44019f92019-05-19 19:58:27 -07001071 Run();
Parker Schuhe4a70d62017-12-27 20:10:20 -08001072}
1073
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001074// Verify that AOS_LOG has the right name.
1075TEST_P(AbstractEventLoopTest, AOSLog) {
1076 auto loop2 = MakePrimary("loop1");
1077 auto loop1 = Make("loop0");
1078
1079 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1080
1081 EXPECT_FALSE(fetcher.Fetch());
1082
1083 loop2->OnRun([&]() {
1084 AOS_LOG(INFO, "Testing123");
1085 this->Exit();
1086 });
1087
1088 Run();
1089 EXPECT_TRUE(fetcher.Fetch());
1090 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1091}
1092
1093// Verify that AOS_LOG has the right name in a watcher.
1094TEST_P(AbstractEventLoopTest, AOSLogWatcher) {
1095 auto loop2 = MakePrimary("loop1");
1096 auto loop1 = Make("loop0");
1097
1098 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1099
1100 EXPECT_FALSE(fetcher.Fetch());
1101
1102 auto sender = loop1->MakeSender<TestMessage>("/test2");
1103
1104 loop2->MakeWatcher("/test2", [&](const TestMessage & /*message*/) {
1105 AOS_LOG(INFO, "Testing123");
1106 this->Exit();
1107 });
1108
1109 loop2->OnRun([&]() {
1110 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1111 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1112 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001113 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001114 });
1115
1116 Run();
1117 EXPECT_TRUE(fetcher.Fetch());
1118 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1119}
1120
1121// Verify that AOS_LOG has the right name in a timer.
1122TEST_P(AbstractEventLoopTest, AOSLogTimer) {
1123 auto loop2 = MakePrimary("loop1");
1124 auto loop1 = Make("loop0");
1125
1126 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1127
1128 EXPECT_FALSE(fetcher.Fetch());
1129
1130 auto test_timer = loop2->AddTimer([&]() {
1131 AOS_LOG(INFO, "Testing123");
1132 this->Exit();
1133 });
1134
1135 loop2->OnRun([&]() { test_timer->Setup(loop2->monotonic_now()); });
1136
1137 Run();
1138 EXPECT_TRUE(fetcher.Fetch());
1139 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1140}
1141
Neil Balch229001a2018-01-07 18:22:52 -08001142// Verify that timer intervals and duration function properly.
1143TEST_P(AbstractEventLoopTest, TimerIntervalAndDuration) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001144 // Force a slower rate so we are guaranteed to have reports for our timer.
Austin Schuh39788ff2019-12-01 18:22:57 -08001145 FLAGS_timing_report_ms = 2000;
1146
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001147 const int kCount = 5;
Neil Balch229001a2018-01-07 18:22:52 -08001148
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001149 auto loop = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001150 auto loop2 = Make();
1151
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001152 ::std::vector<::aos::monotonic_clock::time_point> times;
1153 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
1154
Austin Schuh39788ff2019-12-01 18:22:57 -08001155 Fetcher<timing::Report> report_fetcher =
1156 loop2->MakeFetcher<timing::Report>("/aos");
1157 EXPECT_FALSE(report_fetcher.Fetch());
1158
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001159 auto test_timer = loop->AddTimer([this, &times, &expected_times, &loop]() {
1160 times.push_back(loop->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001161 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
1162 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
1163 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001164 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -08001165 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
1166 EXPECT_EQ(loop->context().size, 0u);
1167 EXPECT_EQ(loop->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001168 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001169
Austin Schuhad154822019-12-27 15:45:13 -08001170 expected_times.push_back(loop->context().monotonic_event_time);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001171 if (times.size() == kCount) {
1172 this->Exit();
1173 }
Neil Balch229001a2018-01-07 18:22:52 -08001174 });
Austin Schuh39788ff2019-12-01 18:22:57 -08001175 test_timer->set_name("Test loop");
Neil Balch229001a2018-01-07 18:22:52 -08001176
Austin Schuh39788ff2019-12-01 18:22:57 -08001177 const monotonic_clock::time_point start_time = loop->monotonic_now();
Austin Schuh52d325c2019-06-23 18:59:06 -07001178 // TODO(austin): This should be an error... Should be done in OnRun only.
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001179 test_timer->Setup(start_time + chrono::seconds(1), chrono::seconds(1));
1180
Austin Schuh44019f92019-05-19 19:58:27 -07001181 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001182
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001183 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001184 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
1185 ASSERT_EQ(times.size(), expected_times.size());
1186 ASSERT_EQ((times.size() % 2), 1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001187
1188 // Grab the middle sample.
1189 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
1190
1191 // Add up all the delays of all the times.
1192 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1193 for (const ::aos::monotonic_clock::time_point time : times) {
1194 sum += time - average_time;
1195 }
1196
1197 // Average and add to the middle to find the average time.
1198 sum /= times.size();
1199 average_time += sum;
1200
1201 // Compute the offset from the average and the expected average. It
1202 // should be pretty close to 0.
1203 const ::aos::monotonic_clock::duration remainder =
1204 average_time - start_time - chrono::seconds(times.size() / 2 + 1);
1205
1206 const chrono::milliseconds kEpsilon(100);
1207 EXPECT_LT(remainder, +kEpsilon);
1208 EXPECT_GT(remainder, -kEpsilon);
1209
1210 // Make sure that the average duration is close to 1 second.
1211 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1212 times.front())
1213 .count() /
1214 static_cast<double>(times.size() - 1),
1215 1.0, 0.1);
1216
1217 // Confirm that the ideal wakeup times increment correctly.
1218 for (size_t i = 1; i < expected_times.size(); ++i) {
1219 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1220 }
1221
1222 for (size_t i = 0; i < expected_times.size(); ++i) {
1223 EXPECT_EQ((expected_times[i] - start_time) % chrono::seconds(1),
1224 chrono::seconds(0));
1225 }
1226
1227 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1228 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001229
Austin Schuh6bae8252021-02-07 22:01:49 -08001230 if (do_timing_reports() == DoTimingReports::kYes) {
1231 // And, since we are here, check that the timing report makes sense.
1232 // Start by looking for our event loop's timing.
1233 FlatbufferDetachedBuffer<timing::Report> report =
1234 FlatbufferDetachedBuffer<timing::Report>::Empty();
1235 while (report_fetcher.FetchNext()) {
1236 if (report_fetcher->name()->string_view() == "primary") {
1237 report = CopyFlatBuffer(report_fetcher.get());
1238 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001239 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001240
1241 // Confirm that we have the right number of reports, and the contents are
1242 // sane.
1243 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
1244
1245 EXPECT_EQ(report.message().name()->string_view(), "primary");
1246
1247 ASSERT_NE(report.message().senders(), nullptr);
1248 EXPECT_EQ(report.message().senders()->size(), 2);
1249
1250 ASSERT_NE(report.message().timers(), nullptr);
1251 EXPECT_EQ(report.message().timers()->size(), 2);
1252
1253 EXPECT_EQ(report.message().timers()->Get(0)->name()->string_view(),
1254 "Test loop");
1255 EXPECT_GE(report.message().timers()->Get(0)->count(), 1);
1256
1257 EXPECT_EQ(report.message().timers()->Get(1)->name()->string_view(),
1258 "timing_reports");
1259 EXPECT_EQ(report.message().timers()->Get(1)->count(), 1);
1260
1261 // Make sure there is a single phased loop report with our report in it.
1262 ASSERT_EQ(report.message().phased_loops(), nullptr);
1263 } else {
1264 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001265 }
Neil Balch229001a2018-01-07 18:22:52 -08001266}
1267
1268// Verify that we can change a timer's parameters during execution.
1269TEST_P(AbstractEventLoopTest, TimerChangeParameters) {
Austin Schuh44019f92019-05-19 19:58:27 -07001270 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001271 loop->SetRuntimeRealtimePriority(1);
Austin Schuh7f20f512021-01-31 17:56:16 -08001272 std::vector<monotonic_clock::time_point> iteration_list;
Neil Balch229001a2018-01-07 18:22:52 -08001273
1274 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001275 ScopedNotRealtime nrt;
Austin Schuh7f20f512021-01-31 17:56:16 -08001276 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001277 });
1278
Austin Schuh7f20f512021-01-31 17:56:16 -08001279 monotonic_clock::time_point s;
1280 auto modifier_timer = loop->AddTimer([&test_timer, &s]() {
Austin Schuhd892f102021-10-12 18:01:46 -07001281 test_timer->Setup(s + chrono::milliseconds(1750),
1282 chrono::milliseconds(600));
Neil Balch229001a2018-01-07 18:22:52 -08001283 });
1284
Austin Schuh7f20f512021-01-31 17:56:16 -08001285 s = loop->monotonic_now();
Austin Schuhd892f102021-10-12 18:01:46 -07001286 test_timer->Setup(s, chrono::milliseconds(500));
1287 modifier_timer->Setup(s + chrono::milliseconds(1250));
1288 EndEventLoop(loop.get(), chrono::milliseconds(3950));
Austin Schuh44019f92019-05-19 19:58:27 -07001289 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001290
Austin Schuhd892f102021-10-12 18:01:46 -07001291 EXPECT_THAT(
1292 iteration_list,
1293 ::testing::ElementsAre(
1294 s, s + chrono::milliseconds(500), s + chrono::milliseconds(1000),
1295 s + chrono::milliseconds(1750), s + chrono::milliseconds(2350),
1296 s + chrono::milliseconds(2950), s + chrono::milliseconds(3550)));
Neil Balch229001a2018-01-07 18:22:52 -08001297}
1298
1299// Verify that we can disable a timer during execution.
1300TEST_P(AbstractEventLoopTest, TimerDisable) {
Austin Schuh44019f92019-05-19 19:58:27 -07001301 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001302 loop->SetRuntimeRealtimePriority(1);
Neil Balch229001a2018-01-07 18:22:52 -08001303 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
1304
1305 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001306 ScopedNotRealtime nrt;
Austin Schuhd892f102021-10-12 18:01:46 -07001307 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001308 });
1309
Tyler Chatow67ddb032020-01-12 14:30:04 -08001310 auto ender_timer = loop->AddTimer([&test_timer]() { test_timer->Disable(); });
Neil Balch229001a2018-01-07 18:22:52 -08001311
Austin Schuhd892f102021-10-12 18:01:46 -07001312 monotonic_clock::time_point s = loop->monotonic_now();
Austin Schuh73d99502021-12-08 12:05:39 -08001313 test_timer->Setup(s, ::std::chrono::milliseconds(500));
1314 ender_timer->Setup(s + ::std::chrono::milliseconds(1250));
1315 EndEventLoop(loop.get(), ::std::chrono::milliseconds(2000));
Austin Schuh44019f92019-05-19 19:58:27 -07001316 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001317
Austin Schuhd892f102021-10-12 18:01:46 -07001318 EXPECT_THAT(iteration_list,
Austin Schuh73d99502021-12-08 12:05:39 -08001319 ::testing::ElementsAre(s, s + chrono::milliseconds(500),
1320 s + chrono::milliseconds(1000)));
Neil Balch229001a2018-01-07 18:22:52 -08001321}
Austin Schuh7267c532019-05-19 19:55:53 -07001322
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001323// Verify that a timer can disable itself.
1324//
1325// TODO(Brian): Do something similar with phased loops, both with a quick
1326// handler and a handler that would miss a cycle except it got deferred. Current
1327// behavior doing that is a mess.
1328TEST_P(AbstractEventLoopTest, TimerDisableSelf) {
1329 auto loop = MakePrimary();
1330
1331 int count = 0;
1332 aos::TimerHandler *test_timer;
1333 test_timer = loop->AddTimer([&count, &test_timer]() {
1334 ++count;
1335 test_timer->Disable();
1336 });
1337
1338 test_timer->Setup(loop->monotonic_now(), ::std::chrono::milliseconds(20));
1339 EndEventLoop(loop.get(), ::std::chrono::milliseconds(80));
1340 Run();
1341
1342 EXPECT_EQ(count, 1);
1343}
1344
Brian Silvermanbd405c02020-06-23 16:25:23 -07001345// Verify that we can disable a timer during execution of another timer
1346// scheduled for the same time, with one ordering of creation for the timers.
1347//
1348// Also schedule some more events to reshuffle the heap in EventLoop used for
1349// tracking events to change up the order. This used to segfault
1350// SimulatedEventLoop.
1351TEST_P(AbstractEventLoopTest, TimerDisableOther) {
1352 for (bool creation_order : {true, false}) {
1353 for (bool setup_order : {true, false}) {
1354 for (int shuffle_events = 0; shuffle_events < 5; ++shuffle_events) {
1355 auto loop = MakePrimary();
1356 aos::TimerHandler *test_timer, *ender_timer;
1357 if (creation_order) {
1358 test_timer = loop->AddTimer([]() {});
1359 ender_timer =
1360 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1361 } else {
1362 ender_timer =
1363 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1364 test_timer = loop->AddTimer([]() {});
1365 }
1366
1367 const auto start = loop->monotonic_now();
1368
1369 for (int i = 0; i < shuffle_events; ++i) {
1370 loop->AddTimer([]() {})->Setup(start + std::chrono::milliseconds(10));
1371 }
1372
1373 if (setup_order) {
1374 test_timer->Setup(start + ::std::chrono::milliseconds(20));
1375 ender_timer->Setup(start + ::std::chrono::milliseconds(20));
1376 } else {
1377 ender_timer->Setup(start + ::std::chrono::milliseconds(20));
1378 test_timer->Setup(start + ::std::chrono::milliseconds(20));
1379 }
1380 EndEventLoop(loop.get(), ::std::chrono::milliseconds(40));
1381 Run();
1382 }
1383 }
1384 }
1385}
1386
Austin Schuh54cf95f2019-11-29 13:14:18 -08001387// Verifies that the event loop implementations detect when Channel is not a
Brian Silverman631b6262021-11-10 12:25:08 -08001388// pointer into configuration(), or a name doesn't map to a channel in
1389// configuration().
Austin Schuh54cf95f2019-11-29 13:14:18 -08001390TEST_P(AbstractEventLoopDeathTest, InvalidChannel) {
1391 auto loop = MakePrimary();
1392
Tyler Chatow67ddb032020-01-12 14:30:04 -08001393 const Channel *channel = configuration::GetChannel(
1394 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
Austin Schuh54cf95f2019-11-29 13:14:18 -08001395
1396 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1397
1398 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001399 loop->MakeRawSender(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001400 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1401
1402 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001403 loop->MakeSender<TestMessage>("/testbad"),
1404 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1405 " not found in config");
1406
1407 EXPECT_FALSE(loop->TryMakeSender<TestMessage>("/testbad"));
1408
1409 EXPECT_DEATH(
1410 loop->MakeRawFetcher(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001411 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1412
1413 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001414 loop->MakeFetcher<TestMessage>("/testbad"),
1415 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1416 " not found in config");
1417
1418 EXPECT_FALSE(loop->TryMakeFetcher<TestMessage>("/testbad").valid());
1419
1420 EXPECT_DEATH(
Austin Schuh54cf95f2019-11-29 13:14:18 -08001421 {
1422 loop->MakeRawWatcher(&channel_copy.message(),
1423 [](const Context, const void *) {});
1424 },
1425 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
Brian Silverman631b6262021-11-10 12:25:08 -08001426
1427 EXPECT_DEATH(
1428 { loop->MakeWatcher("/testbad", [](const TestMessage &) {}); },
1429 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1430 " not found in config");
1431}
1432
1433// Verifies that the event loop handles a channel which is not readable or
1434// writable on the current node nicely.
1435TEST_P(AbstractEventLoopDeathTest, InaccessibleChannel) {
1436 EnableNodes("me");
1437 auto loop = MakePrimary("me");
1438 auto loop2 = Make("them");
1439
1440 const Channel *channel = configuration::GetChannel(
1441 loop->configuration(), "/test_noforward", "aos.TestMessage", "", nullptr);
1442
1443 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1444
1445 EXPECT_DEATH(
1446 loop2->MakeSender<TestMessage>("/test_forward"),
1447 "Channel"
1448 " \\{ \"name\": \"/test_forward\", \"type\": \"aos.TestMessage\" \\}"
1449 " is not able to be sent on this node");
1450
1451 EXPECT_FALSE(loop2->TryMakeSender<TestMessage>("/test_forward"));
1452
1453 EXPECT_DEATH(
1454 loop2->MakeRawFetcher(channel),
1455 "Channel"
1456 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1457 " is not able to be fetched on this node");
1458
1459 EXPECT_DEATH(
1460 loop2->MakeFetcher<TestMessage>("/test_noforward"),
1461 "Channel"
1462 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1463 " is not able to be fetched on this node");
1464
1465 EXPECT_FALSE(loop2->TryMakeFetcher<TestMessage>("/test_noforward").valid());
1466
1467 EXPECT_DEATH(
1468 { loop2->MakeRawWatcher(channel, [](const Context, const void *) {}); },
1469 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1470 "\"source_node\": \"them\" \\}"
1471 " is not able to be watched on this node");
1472
1473 EXPECT_DEATH(
1474 { loop2->MakeWatcher("/test_noforward", [](const TestMessage &) {}); },
1475 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1476 "\"source_node\": \"them\" \\}"
1477 " is not able to be watched on this node");
Austin Schuh54cf95f2019-11-29 13:14:18 -08001478}
1479
Austin Schuhd54780b2020-10-03 16:26:02 -07001480// Verifies that the event loop implementations detect when Channel has an
1481// invalid alignment.
1482TEST_P(AbstractEventLoopDeathTest, InvalidChannelAlignment) {
1483 const char *const kError = "multiple of alignment";
1484 InvalidChannelAlignment();
1485
1486 auto loop = MakePrimary();
1487
1488 const Channel *channel = configuration::GetChannel(
1489 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
1490
1491 EXPECT_DEATH({ loop->MakeRawSender(channel); }, kError);
1492 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); }, kError);
1493
1494 EXPECT_DEATH({ loop->MakeRawFetcher(channel); }, kError);
1495 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); }, kError);
1496
1497 EXPECT_DEATH(
1498 { loop->MakeRawWatcher(channel, [](const Context &, const void *) {}); },
1499 kError);
1500 EXPECT_DEATH({ loop->MakeRawNoArgWatcher(channel, [](const Context &) {}); },
1501 kError);
1502
1503 EXPECT_DEATH({ loop->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
1504 kError);
1505 EXPECT_DEATH({ loop->MakeWatcher("/test", [](const TestMessage &) {}); },
1506 kError);
1507}
1508
Brian Silverman454bc112020-03-05 14:21:25 -08001509// Verify that the send time on a message is roughly right when using a watcher.
Austin Schuh7267c532019-05-19 19:55:53 -07001510TEST_P(AbstractEventLoopTest, MessageSendTime) {
Austin Schuh44019f92019-05-19 19:58:27 -07001511 auto loop1 = MakePrimary();
Austin Schuh7267c532019-05-19 19:55:53 -07001512 auto loop2 = Make();
Austin Schuhad154822019-12-27 15:45:13 -08001513 auto sender = loop2->MakeSender<TestMessage>("/test");
Austin Schuh7267c532019-05-19 19:55:53 -07001514 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
1515
1516 auto test_timer = loop1->AddTimer([&sender]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001517 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1518 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1519 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001520 msg.CheckOk(msg.Send(builder.Finish()));
Alex Perrycb7da4b2019-08-28 19:35:56 -07001521 });
1522
Austin Schuhad154822019-12-27 15:45:13 -08001523 bool triggered = false;
Brian Silverman454bc112020-03-05 14:21:25 -08001524 loop1->MakeWatcher("/test", [&](const TestMessage &msg) {
Austin Schuhad154822019-12-27 15:45:13 -08001525 // Confirm that the data pointer makes sense from a watcher, and all the
1526 // timestamps look right.
1527 EXPECT_GT(&msg, loop1->context().data);
1528 EXPECT_EQ(loop1->context().monotonic_remote_time,
1529 loop1->context().monotonic_event_time);
1530 EXPECT_EQ(loop1->context().realtime_remote_time,
1531 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001532 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001533
1534 const aos::monotonic_clock::time_point monotonic_now =
1535 loop1->monotonic_now();
Tyler Chatow67ddb032020-01-12 14:30:04 -08001536 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08001537
1538 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1539 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1540 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1541 monotonic_now);
1542 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1543 realtime_now);
1544
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001545 EXPECT_LT(&msg, reinterpret_cast<const void *>(
1546 reinterpret_cast<const char *>(loop1->context().data) +
Austin Schuhad154822019-12-27 15:45:13 -08001547 loop1->context().size));
Brian Silverman4f4e0612020-08-12 19:54:41 -07001548 if (read_method() == ReadMethod::PIN) {
1549 EXPECT_GE(loop1->context().buffer_index, 0);
1550 EXPECT_LT(loop1->context().buffer_index,
1551 loop1->NumberBuffers(
1552 configuration::GetChannel(loop1->configuration(), "/test",
1553 "aos.TestMessage", "", nullptr)));
1554 } else {
1555 EXPECT_EQ(-1, loop1->context().buffer_index);
1556 }
Austin Schuhad154822019-12-27 15:45:13 -08001557 triggered = true;
Austin Schuh7267c532019-05-19 19:55:53 -07001558 });
1559
1560 test_timer->Setup(loop1->monotonic_now() + ::std::chrono::seconds(1));
1561
1562 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
Austin Schuh44019f92019-05-19 19:58:27 -07001563 Run();
Austin Schuh7267c532019-05-19 19:55:53 -07001564
Austin Schuhad154822019-12-27 15:45:13 -08001565 EXPECT_TRUE(triggered);
1566
Brian Silverman454bc112020-03-05 14:21:25 -08001567 ASSERT_TRUE(fetcher.Fetch());
1568
1569 monotonic_clock::duration monotonic_time_offset =
1570 fetcher.context().monotonic_event_time -
1571 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1572 realtime_clock::duration realtime_time_offset =
1573 fetcher.context().realtime_event_time -
1574 (loop1->realtime_now() - ::std::chrono::seconds(1));
1575
1576 EXPECT_EQ(fetcher.context().realtime_event_time,
1577 fetcher.context().realtime_remote_time);
1578 EXPECT_EQ(fetcher.context().monotonic_event_time,
1579 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001580 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001581
1582 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1583 << ": Got "
1584 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1585 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1586 // Confirm that the data pointer makes sense.
1587 EXPECT_GT(fetcher.get(), fetcher.context().data);
1588 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001589 reinterpret_cast<const void *>(
1590 reinterpret_cast<const char *>(fetcher.context().data) +
Brian Silverman454bc112020-03-05 14:21:25 -08001591 fetcher.context().size));
1592 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1593 << ": Got "
1594 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1595 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1596
1597 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1598 << ": Got "
1599 << fetcher.context().realtime_event_time.time_since_epoch().count()
1600 << " expected " << loop1->realtime_now().time_since_epoch().count();
1601 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1602 << ": Got "
1603 << fetcher.context().realtime_event_time.time_since_epoch().count()
1604 << " expected " << loop1->realtime_now().time_since_epoch().count();
1605}
1606
1607// Verify that the send time on a message is roughly right when using a no-arg
1608// watcher. To get a message, we need to use a fetcher to actually access the
1609// message. This is also the main use case for no-arg fetchers.
1610TEST_P(AbstractEventLoopTest, MessageSendTimeNoArg) {
1611 auto loop1 = MakePrimary();
1612 auto loop2 = Make();
1613 auto sender = loop2->MakeSender<TestMessage>("/test");
1614 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
1615
1616 auto test_timer = loop1->AddTimer([&sender]() {
1617 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1618 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1619 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001620 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -08001621 });
1622
1623 bool triggered = false;
1624 loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {
1625 // Confirm that we can indeed use a fetcher on this channel from this
1626 // context, and it results in a sane data pointer and timestamps.
1627 ASSERT_TRUE(fetcher.Fetch());
1628
1629 EXPECT_EQ(loop1->context().monotonic_remote_time,
1630 loop1->context().monotonic_event_time);
1631 EXPECT_EQ(loop1->context().realtime_remote_time,
1632 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001633 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001634
1635 const aos::monotonic_clock::time_point monotonic_now =
1636 loop1->monotonic_now();
1637 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
1638
1639 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1640 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1641 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1642 monotonic_now);
1643 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1644 realtime_now);
1645
1646 triggered = true;
1647 });
1648
1649 test_timer->Setup(loop1->monotonic_now() + ::std::chrono::seconds(1));
1650
1651 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
1652 Run();
1653
1654 ASSERT_TRUE(triggered);
Austin Schuh7267c532019-05-19 19:55:53 -07001655
Alex Perrycb7da4b2019-08-28 19:35:56 -07001656 monotonic_clock::duration monotonic_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001657 fetcher.context().monotonic_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001658 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1659 realtime_clock::duration realtime_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001660 fetcher.context().realtime_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001661 (loop1->realtime_now() - ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07001662
Austin Schuhad154822019-12-27 15:45:13 -08001663 EXPECT_EQ(fetcher.context().realtime_event_time,
1664 fetcher.context().realtime_remote_time);
1665 EXPECT_EQ(fetcher.context().monotonic_event_time,
1666 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001667 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001668
Alex Perrycb7da4b2019-08-28 19:35:56 -07001669 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1670 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001671 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh52d325c2019-06-23 18:59:06 -07001672 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07001673 // Confirm that the data pointer makes sense.
1674 EXPECT_GT(fetcher.get(), fetcher.context().data);
1675 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001676 reinterpret_cast<const void *>(
1677 reinterpret_cast<const char *>(fetcher.context().data) +
Alex Perrycb7da4b2019-08-28 19:35:56 -07001678 fetcher.context().size));
1679 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1680 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001681 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh7267c532019-05-19 19:55:53 -07001682 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07001683
1684 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1685 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001686 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07001687 << " expected " << loop1->realtime_now().time_since_epoch().count();
1688 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1689 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001690 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07001691 << " expected " << loop1->realtime_now().time_since_epoch().count();
Austin Schuh7267c532019-05-19 19:55:53 -07001692}
1693
Austin Schuh52d325c2019-06-23 18:59:06 -07001694// Tests that a couple phased loops run in a row result in the correct offset
1695// and period.
1696TEST_P(AbstractEventLoopTest, PhasedLoopTest) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001697 // Force a slower rate so we are guaranteed to have reports for our phased
Austin Schuh39788ff2019-12-01 18:22:57 -08001698 // loop.
1699 FLAGS_timing_report_ms = 2000;
1700
Austin Schuh52d325c2019-06-23 18:59:06 -07001701 const chrono::milliseconds kOffset = chrono::milliseconds(400);
1702 const int kCount = 5;
1703
1704 auto loop1 = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001705 auto loop2 = Make();
1706
1707 Fetcher<timing::Report> report_fetcher =
1708 loop2->MakeFetcher<timing::Report>("/aos");
1709 EXPECT_FALSE(report_fetcher.Fetch());
Austin Schuh52d325c2019-06-23 18:59:06 -07001710
1711 // Collect up a couple of samples.
1712 ::std::vector<::aos::monotonic_clock::time_point> times;
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001713 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
Austin Schuh52d325c2019-06-23 18:59:06 -07001714
1715 // Run kCount iterations.
Austin Schuh39788ff2019-12-01 18:22:57 -08001716 loop1
1717 ->AddPhasedLoop(
1718 [&times, &expected_times, &loop1, this](int count) {
1719 EXPECT_EQ(count, 1);
1720 times.push_back(loop1->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001721 expected_times.push_back(loop1->context().monotonic_event_time);
Austin Schuh39788ff2019-12-01 18:22:57 -08001722
Austin Schuhad154822019-12-27 15:45:13 -08001723 EXPECT_EQ(loop1->context().monotonic_remote_time,
1724 monotonic_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001725 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001726 EXPECT_EQ(loop1->context().realtime_event_time,
1727 realtime_clock::min_time);
1728 EXPECT_EQ(loop1->context().realtime_remote_time,
Austin Schuh39788ff2019-12-01 18:22:57 -08001729 realtime_clock::min_time);
1730 EXPECT_EQ(loop1->context().queue_index, 0xffffffffu);
1731 EXPECT_EQ(loop1->context().size, 0u);
1732 EXPECT_EQ(loop1->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001733 EXPECT_EQ(loop1->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001734
1735 if (times.size() == kCount) {
1736 LOG(INFO) << "Exiting";
1737 this->Exit();
1738 }
1739 },
1740 chrono::seconds(1), kOffset)
1741 ->set_name("Test loop");
Austin Schuh52d325c2019-06-23 18:59:06 -07001742
1743 // Add a delay to make sure that delay during startup doesn't result in a
1744 // "missed cycle".
1745 SleepFor(chrono::seconds(2));
1746
1747 Run();
1748
1749 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001750 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
1751 ASSERT_EQ(times.size(), expected_times.size());
1752 ASSERT_EQ((times.size() % 2), 1);
Austin Schuh52d325c2019-06-23 18:59:06 -07001753
1754 // Grab the middle sample.
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001755 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
Austin Schuh52d325c2019-06-23 18:59:06 -07001756
1757 // Add up all the delays of all the times.
1758 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1759 for (const ::aos::monotonic_clock::time_point time : times) {
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001760 sum += time - average_time;
Austin Schuh52d325c2019-06-23 18:59:06 -07001761 }
1762
1763 // Average and add to the middle to find the average time.
1764 sum /= times.size();
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001765 average_time += sum;
Austin Schuh52d325c2019-06-23 18:59:06 -07001766
1767 // Compute the offset from the start of the second of the average time. This
1768 // should be pretty close to the offset.
1769 const ::aos::monotonic_clock::duration remainder =
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001770 average_time.time_since_epoch() -
1771 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
Austin Schuh52d325c2019-06-23 18:59:06 -07001772
1773 const chrono::milliseconds kEpsilon(100);
1774 EXPECT_LT(remainder, kOffset + kEpsilon);
1775 EXPECT_GT(remainder, kOffset - kEpsilon);
1776
1777 // Make sure that the average duration is close to 1 second.
1778 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1779 times.front())
1780 .count() /
1781 static_cast<double>(times.size() - 1),
1782 1.0, 0.1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001783
1784 // Confirm that the ideal wakeup times increment correctly.
1785 for (size_t i = 1; i < expected_times.size(); ++i) {
1786 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1787 }
1788
1789 for (size_t i = 0; i < expected_times.size(); ++i) {
1790 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
1791 kOffset);
1792 }
1793
1794 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1795 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001796
Austin Schuh6bae8252021-02-07 22:01:49 -08001797 if (do_timing_reports() == DoTimingReports::kYes) {
1798 // And, since we are here, check that the timing report makes sense.
1799 // Start by looking for our event loop's timing.
1800 FlatbufferDetachedBuffer<timing::Report> report =
1801 FlatbufferDetachedBuffer<timing::Report>::Empty();
1802 while (report_fetcher.FetchNext()) {
1803 if (report_fetcher->name()->string_view() == "primary") {
1804 report = CopyFlatBuffer(report_fetcher.get());
1805 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001806 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001807
1808 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
1809
1810 EXPECT_EQ(report.message().name()->string_view(), "primary");
1811
1812 ASSERT_NE(report.message().senders(), nullptr);
1813 EXPECT_EQ(report.message().senders()->size(), 2);
1814
1815 ASSERT_NE(report.message().timers(), nullptr);
1816 EXPECT_EQ(report.message().timers()->size(), 1);
1817
1818 // Make sure there is a single phased loop report with our report in it.
1819 ASSERT_NE(report.message().phased_loops(), nullptr);
1820 ASSERT_EQ(report.message().phased_loops()->size(), 1);
1821 EXPECT_EQ(report.message().phased_loops()->Get(0)->name()->string_view(),
1822 "Test loop");
1823 EXPECT_GE(report.message().phased_loops()->Get(0)->count(), 1);
1824 } else {
1825 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001826 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001827}
1828
Milind Upadhyay42589bb2021-05-19 20:05:16 -07001829// Tests that a phased loop responds correctly to a changing offset.
1830TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetTest) {
1831 // Force a slower rate so we are guaranteed to have reports for our phased
1832 // loop.
1833 FLAGS_timing_report_ms = 2000;
1834
1835 const chrono::milliseconds kOffset = chrono::milliseconds(400);
1836 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
1837 const int kCount = 5;
1838
1839 auto loop1 = MakePrimary();
1840
1841 // Collect up a couple of samples.
1842 ::std::vector<::aos::monotonic_clock::time_point> times;
1843 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
1844
1845 PhasedLoopHandler *phased_loop;
1846
1847 // Run kCount iterations.
1848 phased_loop = loop1->AddPhasedLoop(
1849 [&phased_loop, &times, &expected_times, &loop1, this, kOffset,
1850 kInterval](int count) {
1851 EXPECT_EQ(count, 1);
1852 times.push_back(loop1->monotonic_now());
1853
1854 expected_times.push_back(loop1->context().monotonic_event_time);
1855
1856 phased_loop->set_interval_and_offset(
1857 kInterval, kOffset - chrono::milliseconds(times.size()));
1858 LOG(INFO) << "new offset: "
1859 << (kOffset - chrono::milliseconds(times.size())).count();
1860
1861 if (times.size() == kCount) {
1862 LOG(INFO) << "Exiting";
1863 this->Exit();
1864 }
1865 },
1866 kInterval, kOffset);
1867 phased_loop->set_name("Test loop");
1868
1869 // Add a delay to make sure that delay during startup doesn't result in a
1870 // "missed cycle".
1871 SleepFor(chrono::seconds(2));
1872
1873 Run();
1874 // Confirm that we got both the right number of samples, and it's odd.
1875 EXPECT_EQ(times.size(), static_cast<size_t>(kCount));
1876 EXPECT_EQ(times.size(), expected_times.size());
1877 EXPECT_EQ((times.size() % 2), 1);
1878
1879 // Grab the middle sample.
1880 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
1881
1882 // Add up all the delays of all the times.
1883 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1884 for (const ::aos::monotonic_clock::time_point time : times) {
1885 sum += time - average_time;
1886 }
1887
1888 // Average and add to the middle to find the average time.
1889 sum /= times.size();
1890 average_time += sum;
1891
1892 // Compute the offset from the start of the second of the average time. This
1893 // should be pretty close to the offset.
1894 const ::aos::monotonic_clock::duration remainder =
1895 average_time.time_since_epoch() -
1896 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
1897
1898 const chrono::milliseconds kEpsilon(100);
1899 EXPECT_LT(remainder, kOffset + kEpsilon);
1900 EXPECT_GT(remainder, kOffset - kEpsilon);
1901
1902 // Make sure that the average duration is close to 1 second.
1903 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1904 times.front())
1905 .count() /
1906 static_cast<double>(times.size() - 1),
1907 1.0, 0.1);
1908
1909 // Confirm that the ideal wakeup times increment correctly.
1910 for (size_t i = 1; i < expected_times.size(); ++i) {
1911 LOG(INFO) << i - 1 << ": " << expected_times[i - 1] << ", " << i << ": "
1912 << expected_times[i];
1913 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1) -
1914 chrono::milliseconds(1));
1915 }
1916
1917 for (size_t i = 0; i < expected_times.size(); ++i) {
1918 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
1919 kOffset - chrono::milliseconds(i));
1920 }
1921
1922 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1923 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
1924}
1925
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08001926// Tests that a phased loop responds correctly to a changing offset; sweep
1927// across a variety of potential offset changes, to ensure that we are
1928// exercising a variety of potential cases.
1929TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetSweep) {
1930 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
1931 const int kCount = 5;
1932
1933 auto loop1 = MakePrimary();
1934
1935 std::vector<aos::monotonic_clock::duration> offset_options;
1936 for (int ii = 0; ii < kCount; ++ii) {
1937 offset_options.push_back(ii * kInterval / kCount);
1938 }
1939 std::vector<aos::monotonic_clock::duration> offset_sweep;
1940 // Run over all the pair-wise combinations of offsets.
1941 for (int ii = 0; ii < kCount; ++ii) {
1942 for (int jj = 0; jj < kCount; ++jj) {
1943 offset_sweep.push_back(offset_options.at(ii));
1944 offset_sweep.push_back(offset_options.at(jj));
1945 }
1946 }
1947
1948 std::vector<::aos::monotonic_clock::time_point> expected_times;
1949
1950 PhasedLoopHandler *phased_loop;
1951
1952 // Run kCount iterations.
1953 size_t counter = 0;
1954 phased_loop = loop1->AddPhasedLoop(
1955 [&phased_loop, &expected_times, &loop1, this, kInterval, &counter,
1956 offset_sweep](int count) {
1957 EXPECT_EQ(count, 1);
1958 expected_times.push_back(loop1->context().monotonic_event_time);
1959
1960 counter++;
1961
1962 if (counter == offset_sweep.size()) {
1963 LOG(INFO) << "Exiting";
1964 this->Exit();
1965 return;
1966 }
1967
1968 phased_loop->set_interval_and_offset(kInterval,
1969 offset_sweep.at(counter));
1970 },
1971 kInterval, offset_sweep.at(0));
1972
1973 Run();
1974 ASSERT_EQ(expected_times.size(), offset_sweep.size());
1975 for (size_t ii = 1; ii < expected_times.size(); ++ii) {
1976 EXPECT_LE(expected_times.at(ii) - expected_times.at(ii - 1), kInterval);
1977 }
1978}
1979
1980// Tests that a phased loop responds correctly to being rescheduled with now
1981// equal to a time in the past.
1982TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleInPast) {
1983 const chrono::milliseconds kOffset = chrono::milliseconds(400);
1984 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
1985
1986 auto loop1 = MakePrimary();
1987
1988 std::vector<::aos::monotonic_clock::time_point> expected_times;
1989
1990 PhasedLoopHandler *phased_loop;
1991
1992 int expected_count = 1;
1993
1994 // Set up a timer that will get run immediately after the phased loop and
1995 // which will attempt to reschedule the phased loop to just before now. This
1996 // should succeed, but will result in 0 cycles elapsing.
1997 TimerHandler *manager_timer =
1998 loop1->AddTimer([&phased_loop, &loop1, &expected_count, this]() {
1999 if (expected_count == 0) {
2000 LOG(INFO) << "Exiting";
2001 this->Exit();
2002 return;
2003 }
2004 phased_loop->Reschedule(loop1->context().monotonic_event_time -
2005 std::chrono::nanoseconds(1));
2006 expected_count = 0;
2007 });
2008
2009 phased_loop = loop1->AddPhasedLoop(
2010 [&expected_count, &expected_times, &loop1, manager_timer](int count) {
2011 EXPECT_EQ(count, expected_count);
2012 expected_times.push_back(loop1->context().monotonic_event_time);
2013
2014 manager_timer->Setup(loop1->context().monotonic_event_time);
2015 },
2016 kInterval, kOffset);
2017 phased_loop->set_name("Test loop");
2018 manager_timer->set_name("Manager timer");
2019
2020 Run();
2021
2022 ASSERT_EQ(2u, expected_times.size());
2023 ASSERT_EQ(expected_times[0], expected_times[1]);
2024}
2025
2026// Tests that a phased loop responds correctly to being rescheduled at the time
2027// when it should be triggering (it should kick the trigger to the next cycle).
2028TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleNow) {
2029 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2030 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2031
2032 auto loop1 = MakePrimary();
2033
2034 std::vector<::aos::monotonic_clock::time_point> expected_times;
2035
2036 PhasedLoopHandler *phased_loop;
2037
2038 bool should_exit = false;
2039 // Set up a timer that will get run immediately after the phased loop and
2040 // which will attempt to reschedule the phased loop to now. This should
2041 // succeed, but will result in no change to the expected behavior (since this
2042 // is the same thing that is actually done internally).
2043 TimerHandler *manager_timer =
2044 loop1->AddTimer([&phased_loop, &loop1, &should_exit, this]() {
2045 if (should_exit) {
2046 LOG(INFO) << "Exiting";
2047 this->Exit();
2048 return;
2049 }
2050 phased_loop->Reschedule(loop1->context().monotonic_event_time);
2051 should_exit = true;
2052 });
2053
2054 phased_loop = loop1->AddPhasedLoop(
2055 [&expected_times, &loop1, manager_timer](int count) {
2056 EXPECT_EQ(count, 1);
2057 expected_times.push_back(loop1->context().monotonic_event_time);
2058
2059 manager_timer->Setup(loop1->context().monotonic_event_time);
2060 },
2061 kInterval, kOffset);
2062 phased_loop->set_name("Test loop");
2063 manager_timer->set_name("Manager timer");
2064
2065 Run();
2066
2067 ASSERT_EQ(2u, expected_times.size());
2068 ASSERT_EQ(expected_times[0] + kInterval, expected_times[1]);
2069}
2070
2071// Tests that a phased loop responds correctly to being rescheduled at a time in
2072// the distant future.
2073TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleFuture) {
2074 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2075 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2076
2077 auto loop1 = MakePrimary();
2078
2079 std::vector<::aos::monotonic_clock::time_point> expected_times;
2080
2081 PhasedLoopHandler *phased_loop;
2082
2083 bool should_exit = false;
2084 int expected_count = 1;
2085 TimerHandler *manager_timer = loop1->AddTimer(
2086 [&expected_count, &phased_loop, &loop1, &should_exit, this, kInterval]() {
2087 if (should_exit) {
2088 LOG(INFO) << "Exiting";
2089 this->Exit();
2090 return;
2091 }
2092 expected_count = 10;
2093 // Knock off 1 ns, since the scheduler rounds up when it is
2094 // scheduled to exactly a loop time.
2095 phased_loop->Reschedule(loop1->context().monotonic_event_time +
2096 kInterval * expected_count -
2097 std::chrono::nanoseconds(1));
2098 should_exit = true;
2099 });
2100
2101 phased_loop = loop1->AddPhasedLoop(
2102 [&expected_times, &loop1, manager_timer, &expected_count](int count) {
2103 EXPECT_EQ(count, expected_count);
2104 expected_times.push_back(loop1->context().monotonic_event_time);
2105
2106 manager_timer->Setup(loop1->context().monotonic_event_time);
2107 },
2108 kInterval, kOffset);
2109 phased_loop->set_name("Test loop");
2110 manager_timer->set_name("Manager timer");
2111
2112 Run();
2113
2114 ASSERT_EQ(2u, expected_times.size());
2115 ASSERT_EQ(expected_times[0] + expected_count * kInterval, expected_times[1]);
2116}
2117
2118// Tests that a phased loop responds correctly to having its phase offset
2119// incremented and then being scheduled after a set time, exercising a pattern
2120// where a phased loop's offset is changed while trying to maintain the trigger
2121// at a consistent period.
2122TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleWithLaterOffset) {
2123 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2124 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2125
2126 auto loop1 = MakePrimary();
2127
2128 std::vector<::aos::monotonic_clock::time_point> expected_times;
2129
2130 PhasedLoopHandler *phased_loop;
2131
2132 bool should_exit = false;
2133 TimerHandler *manager_timer = loop1->AddTimer(
2134 [&phased_loop, &loop1, &should_exit, this, kInterval, kOffset]() {
2135 if (should_exit) {
2136 LOG(INFO) << "Exiting";
2137 this->Exit();
2138 return;
2139 }
2140 // Schedule the next callback to be strictly later than the current time
2141 // + interval / 2, to ensure a consistent frequency.
2142 monotonic_clock::time_point half_time =
2143 loop1->context().monotonic_event_time + kInterval / 2;
2144 phased_loop->set_interval_and_offset(
2145 kInterval, kOffset + std::chrono::nanoseconds(1), half_time);
2146 phased_loop->Reschedule(half_time);
2147 should_exit = true;
2148 });
2149
2150 phased_loop = loop1->AddPhasedLoop(
2151 [&expected_times, &loop1, manager_timer](int count) {
2152 EXPECT_EQ(1, count);
2153 expected_times.push_back(loop1->context().monotonic_event_time);
2154
2155 manager_timer->Setup(loop1->context().monotonic_event_time);
2156 },
2157 kInterval, kOffset);
2158 phased_loop->set_name("Test loop");
2159 manager_timer->set_name("Manager timer");
2160
2161 Run();
2162
2163 ASSERT_EQ(2u, expected_times.size());
2164 ASSERT_EQ(expected_times[0] + kInterval + std::chrono::nanoseconds(1),
2165 expected_times[1]);
2166}
2167
2168// Tests that a phased loop responds correctly to having its phase offset
2169// decremented and then being scheduled after a set time, exercising a pattern
2170// where a phased loop's offset is changed while trying to maintain the trigger
2171// at a consistent period.
2172TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleWithEarlierOffset) {
2173 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2174 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2175
2176 auto loop1 = MakePrimary();
2177
2178 std::vector<::aos::monotonic_clock::time_point> expected_times;
2179
2180 PhasedLoopHandler *phased_loop;
2181
2182 bool should_exit = false;
2183 TimerHandler *manager_timer = loop1->AddTimer(
2184 [&phased_loop, &loop1, &should_exit, this, kInterval, kOffset]() {
2185 if (should_exit) {
2186 LOG(INFO) << "Exiting";
2187 this->Exit();
2188 return;
2189 }
2190 // Schedule the next callback to be strictly later than the current time
2191 // + interval / 2, to ensure a consistent frequency.
2192 const aos::monotonic_clock::time_point half_time =
2193 loop1->context().monotonic_event_time + kInterval / 2;
2194 phased_loop->set_interval_and_offset(
2195 kInterval, kOffset - std::chrono::nanoseconds(1), half_time);
2196 phased_loop->Reschedule(half_time);
2197 should_exit = true;
2198 });
2199
2200 phased_loop = loop1->AddPhasedLoop(
2201 [&expected_times, &loop1, manager_timer](int count) {
2202 EXPECT_EQ(1, count);
2203 expected_times.push_back(loop1->context().monotonic_event_time);
2204
2205 manager_timer->Setup(loop1->context().monotonic_event_time);
2206 },
2207 kInterval, kOffset);
2208 phased_loop->set_name("Test loop");
2209 manager_timer->set_name("Manager timer");
2210
2211 Run();
2212
2213 ASSERT_EQ(2u, expected_times.size());
2214 ASSERT_EQ(expected_times[0] + kInterval - std::chrono::nanoseconds(1),
2215 expected_times[1]);
2216}
2217
Austin Schuh39788ff2019-12-01 18:22:57 -08002218// Tests that senders count correctly in the timing report.
2219TEST_P(AbstractEventLoopTest, SenderTimingReport) {
2220 FLAGS_timing_report_ms = 1000;
2221 auto loop1 = MakePrimary();
2222
2223 auto loop2 = Make("watcher_loop");
2224 loop2->MakeWatcher("/test", [](const TestMessage &) {});
2225
2226 auto loop3 = Make();
2227
2228 Fetcher<timing::Report> report_fetcher =
2229 loop3->MakeFetcher<timing::Report>("/aos");
2230 EXPECT_FALSE(report_fetcher.Fetch());
2231
2232 auto sender = loop1->MakeSender<TestMessage>("/test");
2233
James Kuszmaul78514332022-04-06 15:08:34 -07002234 // Sanity check channel frequencies to ensure that we've designed the test
2235 // correctly.
2236 ASSERT_EQ(800, sender.channel()->frequency());
2237 ASSERT_EQ(2000000000, loop1->configuration()->channel_storage_duration());
2238 constexpr int kMaxAllowedMessages = 800 * 2;
2239 constexpr int kSendMessages = kMaxAllowedMessages * 2;
2240 constexpr int kDroppedMessages = kSendMessages - kMaxAllowedMessages;
2241
Austin Schuh39788ff2019-12-01 18:22:57 -08002242 // Add a timer to actually quit.
2243 auto test_timer = loop1->AddTimer([&sender]() {
James Kuszmaul78514332022-04-06 15:08:34 -07002244 for (int i = 0; i < kSendMessages; ++i) {
Austin Schuh39788ff2019-12-01 18:22:57 -08002245 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2246 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2247 builder.add_value(200 + i);
James Kuszmaul78514332022-04-06 15:08:34 -07002248 if (i < kMaxAllowedMessages) {
2249 msg.CheckOk(msg.Send(builder.Finish()));
2250 } else {
2251 EXPECT_EQ(RawSender::Error::kMessagesSentTooFast,
2252 msg.Send(builder.Finish()));
2253 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002254 }
2255 });
2256
2257 // Quit after 1 timing report, mid way through the next cycle.
2258 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2259
2260 loop1->OnRun([&test_timer, &loop1]() {
2261 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1500));
2262 });
2263
2264 Run();
2265
Austin Schuh6bae8252021-02-07 22:01:49 -08002266 if (do_timing_reports() == DoTimingReports::kYes) {
2267 // And, since we are here, check that the timing report makes sense.
2268 // Start by looking for our event loop's timing.
2269 FlatbufferDetachedBuffer<timing::Report> primary_report =
2270 FlatbufferDetachedBuffer<timing::Report>::Empty();
2271 while (report_fetcher.FetchNext()) {
Austin Schuh8902fa52021-03-14 22:39:24 -07002272 VLOG(1) << "Report " << FlatbufferToJson(report_fetcher.get());
Austin Schuh6bae8252021-02-07 22:01:49 -08002273 if (report_fetcher->name()->string_view() == "primary") {
2274 primary_report = CopyFlatBuffer(report_fetcher.get());
2275 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002276 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002277
Austin Schuh8902fa52021-03-14 22:39:24 -07002278 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
Austin Schuh6bae8252021-02-07 22:01:49 -08002279
2280 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2281
2282 ASSERT_NE(primary_report.message().senders(), nullptr);
2283 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2284
2285 // Confirm that the sender looks sane.
2286 EXPECT_EQ(
2287 loop1->configuration()
2288 ->channels()
2289 ->Get(primary_report.message().senders()->Get(0)->channel_index())
2290 ->name()
2291 ->string_view(),
2292 "/test");
James Kuszmaul78514332022-04-06 15:08:34 -07002293 EXPECT_EQ(primary_report.message().senders()->Get(0)->count(),
2294 kMaxAllowedMessages);
2295 ASSERT_TRUE(primary_report.message().senders()->Get(0)->has_error_counts());
2296 ASSERT_EQ(
2297 primary_report.message().senders()->Get(0)->error_counts()->size(), 2u);
2298 EXPECT_EQ(
2299 primary_report.message()
2300 .senders()
2301 ->Get(0)
2302 ->error_counts()
2303 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2304 ->count(),
2305 kDroppedMessages)
2306 << aos::FlatbufferToJson(primary_report);
2307 EXPECT_EQ(primary_report.message()
2308 .senders()
2309 ->Get(0)
2310 ->error_counts()
2311 ->Get(static_cast<size_t>(timing::SendError::INVALID_REDZONE))
2312 ->count(),
2313 0);
Austin Schuh6bae8252021-02-07 22:01:49 -08002314
2315 // Confirm that the timing primary_report sender looks sane.
2316 EXPECT_EQ(
2317 loop1->configuration()
2318 ->channels()
2319 ->Get(primary_report.message().senders()->Get(1)->channel_index())
2320 ->name()
2321 ->string_view(),
2322 "/aos");
2323 EXPECT_EQ(primary_report.message().senders()->Get(1)->count(), 1);
2324
2325 ASSERT_NE(primary_report.message().timers(), nullptr);
2326 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2327
2328 // Make sure there are no phased loops or watchers.
2329 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2330 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2331 } else {
2332 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002333 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002334}
2335
James Kuszmaul93abac12022-04-14 15:05:10 -07002336// Tests that the RawSender::Send(void*, size_t) overload tracks things properly
2337// in its timing report.
2338TEST_P(AbstractEventLoopTest, CopySenderTimingReport) {
2339 gflags::FlagSaver flag_saver;
2340 FLAGS_timing_report_ms = 1000;
2341 auto loop1 = Make();
2342 auto loop2 = MakePrimary();
2343
2344 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2345 JsonToFlatbuffer<TestMessage>("{}");
2346
2347 std::unique_ptr<aos::RawSender> sender =
2348 loop2->MakeRawSender(configuration::GetChannel(
2349 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
2350
2351 Fetcher<timing::Report> report_fetcher =
2352 loop1->MakeFetcher<timing::Report>("/aos");
2353 EXPECT_FALSE(report_fetcher.Fetch());
2354
2355 loop2->OnRun([&]() {
2356 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
2357 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2358 RawSender::Error::kOk);
2359 }
2360 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2361 RawSender::Error::kMessagesSentTooFast);
2362 });
2363 // Quit after 1 timing report, mid way through the next cycle.
2364 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
2365
2366 Run();
2367
2368 if (do_timing_reports() == DoTimingReports::kYes) {
2369 // Check that the sent too fast actually got recorded by the timing report.
2370 FlatbufferDetachedBuffer<timing::Report> primary_report =
2371 FlatbufferDetachedBuffer<timing::Report>::Empty();
2372 while (report_fetcher.FetchNext()) {
2373 if (report_fetcher->name()->string_view() == "primary") {
2374 primary_report = CopyFlatBuffer(report_fetcher.get());
2375 }
2376 }
2377
2378 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2379
2380 ASSERT_NE(primary_report.message().senders(), nullptr);
2381 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2382 EXPECT_EQ(
2383 primary_report.message()
2384 .senders()
2385 ->Get(0)
2386 ->error_counts()
2387 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2388 ->count(),
2389 1);
2390 }
2391}
2392
Austin Schuhe0ab4de2023-05-03 08:05:08 -07002393// Tests that the RawSender::Send(SharedSpan) overload works.
2394TEST_P(AbstractEventLoopTest, SharedSenderTimingReport) {
2395 gflags::FlagSaver flag_saver;
2396 FLAGS_timing_report_ms = 1000;
2397 auto loop1 = Make();
2398 auto loop2 = MakePrimary();
2399
2400 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2401 JsonToFlatbuffer<TestMessage>("{}");
2402
2403 std::unique_ptr<aos::RawSender> sender =
2404 loop2->MakeRawSender(configuration::GetChannel(
2405 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
2406
2407 Fetcher<timing::Report> report_fetcher =
2408 loop1->MakeFetcher<timing::Report>("/aos");
2409 EXPECT_FALSE(report_fetcher.Fetch());
2410
2411 loop2->OnRun([&]() {
2412 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
2413 auto shared_span = MakeSharedSpan(kMessage.span().size());
2414 memcpy(shared_span.second.data(), kMessage.span().data(),
2415 kMessage.span().size());
2416 EXPECT_EQ(sender->Send(std::move(shared_span.first)),
2417 RawSender::Error::kOk);
2418 }
2419 auto shared_span = MakeSharedSpan(kMessage.span().size());
2420 memcpy(shared_span.second.data(), kMessage.span().data(),
2421 kMessage.span().size());
2422 EXPECT_EQ(sender->Send(std::move(shared_span.first)),
2423 RawSender::Error::kMessagesSentTooFast);
2424 });
2425 // Quit after 1 timing report, mid way through the next cycle.
2426 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
2427
2428 Run();
2429
2430 if (do_timing_reports() == DoTimingReports::kYes) {
2431 // Check that the sent too fast actually got recorded by the timing report.
2432 FlatbufferDetachedBuffer<timing::Report> primary_report =
2433 FlatbufferDetachedBuffer<timing::Report>::Empty();
2434 while (report_fetcher.FetchNext()) {
2435 if (report_fetcher->name()->string_view() == "primary") {
2436 primary_report = CopyFlatBuffer(report_fetcher.get());
2437 }
2438 }
2439
2440 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2441
2442 ASSERT_NE(primary_report.message().senders(), nullptr);
2443 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2444 EXPECT_EQ(
2445 primary_report.message()
2446 .senders()
2447 ->Get(0)
2448 ->error_counts()
2449 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2450 ->count(),
2451 1);
2452 }
2453}
2454
Austin Schuh39788ff2019-12-01 18:22:57 -08002455// Tests that senders count correctly in the timing report.
2456TEST_P(AbstractEventLoopTest, WatcherTimingReport) {
2457 FLAGS_timing_report_ms = 1000;
2458 auto loop1 = MakePrimary();
2459 loop1->MakeWatcher("/test", [](const TestMessage &) {});
2460
2461 auto loop2 = Make("sender_loop");
2462
2463 auto loop3 = Make();
2464
2465 Fetcher<timing::Report> report_fetcher =
2466 loop3->MakeFetcher<timing::Report>("/aos");
2467 EXPECT_FALSE(report_fetcher.Fetch());
2468
2469 auto sender = loop2->MakeSender<TestMessage>("/test");
2470
2471 // Add a timer to actually quit.
2472 auto test_timer = loop1->AddTimer([&sender]() {
2473 for (int i = 0; i < 10; ++i) {
2474 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2475 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2476 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002477 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002478 }
2479 });
2480
2481 // Quit after 1 timing report, mid way through the next cycle.
2482 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2483
2484 loop1->OnRun([&test_timer, &loop1]() {
2485 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1500));
2486 });
2487
2488 Run();
2489
Austin Schuh6bae8252021-02-07 22:01:49 -08002490 if (do_timing_reports() == DoTimingReports::kYes) {
2491 // And, since we are here, check that the timing report makes sense.
2492 // Start by looking for our event loop's timing.
2493 FlatbufferDetachedBuffer<timing::Report> primary_report =
2494 FlatbufferDetachedBuffer<timing::Report>::Empty();
2495 while (report_fetcher.FetchNext()) {
2496 LOG(INFO) << "Report " << FlatbufferToJson(report_fetcher.get());
2497 if (report_fetcher->name()->string_view() == "primary") {
2498 primary_report = CopyFlatBuffer(report_fetcher.get());
2499 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002500 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002501
2502 // Check the watcher report.
2503 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2504
2505 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2506
2507 // Just the timing report timer.
2508 ASSERT_NE(primary_report.message().timers(), nullptr);
2509 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2510
2511 // No phased loops
2512 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2513
2514 ASSERT_NE(primary_report.message().watchers(), nullptr);
2515 ASSERT_EQ(primary_report.message().watchers()->size(), 1);
2516 EXPECT_EQ(primary_report.message().watchers()->Get(0)->count(), 10);
2517 } else {
2518 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002519 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002520}
2521
2522// Tests that fetchers count correctly in the timing report.
2523TEST_P(AbstractEventLoopTest, FetcherTimingReport) {
2524 FLAGS_timing_report_ms = 1000;
2525 auto loop1 = MakePrimary();
2526 auto loop2 = Make("sender_loop");
2527
2528 auto loop3 = Make();
2529
2530 Fetcher<timing::Report> report_fetcher =
2531 loop3->MakeFetcher<timing::Report>("/aos");
2532 EXPECT_FALSE(report_fetcher.Fetch());
2533
2534 auto sender = loop2->MakeSender<TestMessage>("/test");
2535 auto fetcher1 = loop1->MakeFetcher<TestMessage>("/test");
2536 auto fetcher2 = loop1->MakeFetcher<TestMessage>("/test");
2537 fetcher1.Fetch();
2538 fetcher2.Fetch();
2539
2540 // Add a timer to actually quit.
2541 auto test_timer = loop1->AddTimer([&sender]() {
2542 for (int i = 0; i < 10; ++i) {
2543 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2544 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2545 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002546 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002547 }
2548 });
2549
2550 auto test_timer2 = loop1->AddTimer([&fetcher1, &fetcher2]() {
2551 fetcher1.Fetch();
2552 while (fetcher2.FetchNext()) {
2553 }
2554 });
2555
2556 // Quit after 1 timing report, mid way through the next cycle.
2557 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2558
2559 loop1->OnRun([test_timer, test_timer2, &loop1]() {
2560 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1400));
2561 test_timer2->Setup(loop1->monotonic_now() + chrono::milliseconds(1600));
2562 });
2563
2564 Run();
2565
Austin Schuh6bae8252021-02-07 22:01:49 -08002566 if (do_timing_reports() == DoTimingReports::kYes) {
2567 // And, since we are here, check that the timing report makes sense.
2568 // Start by looking for our event loop's timing.
2569 FlatbufferDetachedBuffer<timing::Report> primary_report =
2570 FlatbufferDetachedBuffer<timing::Report>::Empty();
2571 while (report_fetcher.FetchNext()) {
2572 if (report_fetcher->name()->string_view() == "primary") {
2573 primary_report = CopyFlatBuffer(report_fetcher.get());
2574 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002575 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002576
2577 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2578
2579 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2580
2581 ASSERT_NE(primary_report.message().senders(), nullptr);
2582 EXPECT_EQ(primary_report.message().senders()->size(), 2);
2583
2584 ASSERT_NE(primary_report.message().timers(), nullptr);
2585 EXPECT_EQ(primary_report.message().timers()->size(), 4);
2586
2587 // Make sure there are no phased loops or watchers.
2588 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2589 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2590
2591 // Now look at the fetchrs.
2592 ASSERT_NE(primary_report.message().fetchers(), nullptr);
2593 ASSERT_EQ(primary_report.message().fetchers()->size(), 2);
2594
2595 EXPECT_EQ(primary_report.message().fetchers()->Get(0)->count(), 1);
2596 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->average(),
2597 0.1);
2598 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->min(),
2599 0.1);
2600 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->max(),
2601 0.1);
2602 EXPECT_EQ(primary_report.message()
2603 .fetchers()
2604 ->Get(0)
2605 ->latency()
2606 ->standard_deviation(),
2607 0.0);
2608
2609 EXPECT_EQ(primary_report.message().fetchers()->Get(1)->count(), 10);
2610 } else {
2611 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002612 }
Austin Schuh52d325c2019-06-23 18:59:06 -07002613}
2614
Austin Schuh67420a42019-12-21 21:55:04 -08002615// Tests that a raw watcher and raw fetcher can receive messages from a raw
2616// sender without messing up offsets.
2617TEST_P(AbstractEventLoopTest, RawBasic) {
2618 auto loop1 = Make();
2619 auto loop2 = MakePrimary();
2620 auto loop3 = Make();
2621
Austin Schuha9df9ad2021-06-16 14:49:39 -07002622 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2623 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuh67420a42019-12-21 21:55:04 -08002624
2625 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002626 loop1->MakeRawSender(configuration::GetChannel(
2627 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08002628
2629 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002630 loop3->MakeRawFetcher(configuration::GetChannel(
2631 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08002632
Austin Schuha9df9ad2021-06-16 14:49:39 -07002633 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002634 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2635 RawSender::Error::kOk);
Austin Schuha9df9ad2021-06-16 14:49:39 -07002636 });
Austin Schuh67420a42019-12-21 21:55:04 -08002637
2638 bool happened = false;
2639 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08002640 configuration::GetChannel(loop2->configuration(), "/test",
2641 "aos.TestMessage", "", nullptr),
Austin Schuha9df9ad2021-06-16 14:49:39 -07002642 [this, &kMessage, &fetcher, &happened](const Context &context,
2643 const void *message) {
Austin Schuh67420a42019-12-21 21:55:04 -08002644 happened = true;
Austin Schuha9df9ad2021-06-16 14:49:39 -07002645 EXPECT_EQ(
2646 kMessage.span(),
2647 absl::Span<const uint8_t>(
2648 reinterpret_cast<const uint8_t *>(message), context.size));
2649 EXPECT_EQ(message, context.data);
Austin Schuh67420a42019-12-21 21:55:04 -08002650
2651 ASSERT_TRUE(fetcher->Fetch());
2652
Austin Schuha9df9ad2021-06-16 14:49:39 -07002653 EXPECT_EQ(kMessage.span(),
2654 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
2655 fetcher->context().data),
2656 fetcher->context().size));
Austin Schuh67420a42019-12-21 21:55:04 -08002657
2658 this->Exit();
2659 });
2660
2661 EXPECT_FALSE(happened);
2662 Run();
2663 EXPECT_TRUE(happened);
2664}
2665
Austin Schuhad154822019-12-27 15:45:13 -08002666// Tests that a raw watcher and raw fetcher can receive messages from a raw
Brian Silvermanbf889922021-11-10 12:41:57 -08002667// sender without messing up offsets, using the RawSpan overload.
2668TEST_P(AbstractEventLoopTest, RawBasicSharedSpan) {
2669 auto loop1 = Make();
2670 auto loop2 = MakePrimary();
2671 auto loop3 = Make();
2672
2673 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2674 JsonToFlatbuffer<TestMessage>("{}");
2675
2676 std::unique_ptr<aos::RawSender> sender =
2677 loop1->MakeRawSender(configuration::GetChannel(
2678 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
2679
2680 std::unique_ptr<aos::RawFetcher> fetcher =
2681 loop3->MakeRawFetcher(configuration::GetChannel(
2682 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
2683
2684 loop2->OnRun([&]() {
Austin Schuhe0ab4de2023-05-03 08:05:08 -07002685 auto shared_span = MakeSharedSpan(kMessage.span().size());
2686 memcpy(shared_span.second.data(), kMessage.span().data(),
2687 kMessage.span().size());
2688 sender->CheckOk(sender->Send(std::move(shared_span.first)));
Brian Silvermanbf889922021-11-10 12:41:57 -08002689 });
2690
2691 bool happened = false;
2692 loop2->MakeRawWatcher(
2693 configuration::GetChannel(loop2->configuration(), "/test",
2694 "aos.TestMessage", "", nullptr),
2695 [this, &kMessage, &fetcher, &happened](const Context &context,
2696 const void *message) {
2697 happened = true;
2698 EXPECT_EQ(
2699 kMessage.span(),
2700 absl::Span<const uint8_t>(
2701 reinterpret_cast<const uint8_t *>(message), context.size));
2702 EXPECT_EQ(message, context.data);
2703
2704 ASSERT_TRUE(fetcher->Fetch());
2705
2706 EXPECT_EQ(kMessage.span(),
2707 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
2708 fetcher->context().data),
2709 fetcher->context().size));
2710
2711 this->Exit();
2712 });
2713
2714 EXPECT_FALSE(happened);
2715 Run();
2716 EXPECT_TRUE(happened);
2717}
2718
2719// Tests that a raw watcher and raw fetcher can receive messages from a raw
Austin Schuhad154822019-12-27 15:45:13 -08002720// sender with remote times filled out.
2721TEST_P(AbstractEventLoopTest, RawRemoteTimes) {
2722 auto loop1 = Make();
2723 auto loop2 = MakePrimary();
2724 auto loop3 = Make();
2725
Austin Schuha9df9ad2021-06-16 14:49:39 -07002726 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2727 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08002728
2729 const aos::monotonic_clock::time_point monotonic_remote_time =
2730 aos::monotonic_clock::time_point(chrono::seconds(1501));
2731 const aos::realtime_clock::time_point realtime_remote_time =
2732 aos::realtime_clock::time_point(chrono::seconds(3132));
Austin Schuhb5c6f972021-03-14 21:53:07 -07002733 const uint32_t remote_queue_index = 0x254971;
Austin Schuha9012be2021-07-21 15:19:11 -07002734 const UUID source_boot_uuid = UUID::Random();
Austin Schuhad154822019-12-27 15:45:13 -08002735
2736 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002737 loop1->MakeRawSender(configuration::GetChannel(
2738 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08002739
2740 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002741 loop3->MakeRawFetcher(configuration::GetChannel(
2742 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08002743
2744 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002745 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size(),
2746 monotonic_remote_time, realtime_remote_time,
2747 remote_queue_index, source_boot_uuid),
2748 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08002749 });
2750
2751 bool happened = false;
2752 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08002753 configuration::GetChannel(loop2->configuration(), "/test",
2754 "aos.TestMessage", "", nullptr),
Austin Schuha9012be2021-07-21 15:19:11 -07002755 [this, monotonic_remote_time, realtime_remote_time, source_boot_uuid,
Austin Schuhb5c6f972021-03-14 21:53:07 -07002756 remote_queue_index, &fetcher,
2757 &happened](const Context &context, const void * /*message*/) {
Austin Schuhad154822019-12-27 15:45:13 -08002758 happened = true;
2759 EXPECT_EQ(monotonic_remote_time, context.monotonic_remote_time);
2760 EXPECT_EQ(realtime_remote_time, context.realtime_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002761 EXPECT_EQ(source_boot_uuid, context.source_boot_uuid);
Austin Schuhb5c6f972021-03-14 21:53:07 -07002762 EXPECT_EQ(remote_queue_index, context.remote_queue_index);
Austin Schuhad154822019-12-27 15:45:13 -08002763
2764 ASSERT_TRUE(fetcher->Fetch());
2765 EXPECT_EQ(monotonic_remote_time,
2766 fetcher->context().monotonic_remote_time);
2767 EXPECT_EQ(realtime_remote_time,
2768 fetcher->context().realtime_remote_time);
2769
2770 this->Exit();
2771 });
2772
2773 EXPECT_FALSE(happened);
2774 Run();
2775 EXPECT_TRUE(happened);
2776}
2777
2778// Tests that a raw sender fills out sent data.
2779TEST_P(AbstractEventLoopTest, RawSenderSentData) {
2780 auto loop1 = MakePrimary();
2781
Austin Schuha9df9ad2021-06-16 14:49:39 -07002782 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2783 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08002784
2785 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002786 loop1->MakeRawSender(configuration::GetChannel(
2787 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08002788
Tyler Chatow67ddb032020-01-12 14:30:04 -08002789 const aos::monotonic_clock::time_point monotonic_now = loop1->monotonic_now();
2790 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08002791
milind1f1dca32021-07-03 13:50:07 -07002792 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2793 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08002794
2795 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
2796 EXPECT_LE(sender->monotonic_sent_time(),
2797 monotonic_now + chrono::milliseconds(100));
2798 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
2799 EXPECT_LE(sender->realtime_sent_time(),
2800 realtime_now + chrono::milliseconds(100));
2801 EXPECT_EQ(sender->sent_queue_index(), 0u);
2802
milind1f1dca32021-07-03 13:50:07 -07002803 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2804 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08002805
2806 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
2807 EXPECT_LE(sender->monotonic_sent_time(),
2808 monotonic_now + chrono::milliseconds(100));
2809 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
2810 EXPECT_LE(sender->realtime_sent_time(),
2811 realtime_now + chrono::milliseconds(100));
2812 EXPECT_EQ(sender->sent_queue_index(), 1u);
2813}
2814
Austin Schuh217a9782019-12-21 23:02:50 -08002815// Tests that not setting up nodes results in no node.
2816TEST_P(AbstractEventLoopTest, NoNode) {
2817 auto loop1 = Make();
2818 auto loop2 = MakePrimary();
2819
2820 EXPECT_EQ(loop1->node(), nullptr);
2821 EXPECT_EQ(loop2->node(), nullptr);
2822}
2823
2824// Tests that setting up nodes results in node being set.
2825TEST_P(AbstractEventLoopTest, Node) {
2826 EnableNodes("me");
2827
2828 auto loop1 = Make();
2829 auto loop2 = MakePrimary();
2830
2831 EXPECT_NE(loop1->node(), nullptr);
2832 EXPECT_NE(loop2->node(), nullptr);
2833}
2834
2835// Tests that watchers work with a node setup.
2836TEST_P(AbstractEventLoopTest, NodeWatcher) {
2837 EnableNodes("me");
2838
2839 auto loop1 = Make();
2840 auto loop2 = Make();
2841 loop1->MakeWatcher("/test", [](const TestMessage &) {});
Tyler Chatow67ddb032020-01-12 14:30:04 -08002842 loop2->MakeRawWatcher(
2843 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
2844 nullptr),
2845 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08002846}
2847
Brian Silverman454bc112020-03-05 14:21:25 -08002848// Tests that no-arg watchers work with a node setup.
2849TEST_P(AbstractEventLoopTest, NodeNoArgWatcher) {
2850 EnableNodes("me");
2851
2852 auto loop1 = Make();
2853 auto loop2 = Make();
2854 loop1->MakeWatcher("/test", [](const TestMessage &) {});
2855 loop2->MakeRawNoArgWatcher(
2856 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
2857 nullptr),
2858 [](const Context &) {});
2859}
2860
Austin Schuh217a9782019-12-21 23:02:50 -08002861// Tests that fetcher work with a node setup.
2862TEST_P(AbstractEventLoopTest, NodeFetcher) {
2863 EnableNodes("me");
2864 auto loop1 = Make();
2865
2866 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
Tyler Chatow67ddb032020-01-12 14:30:04 -08002867 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
2868 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08002869}
2870
2871// Tests that sender work with a node setup.
2872TEST_P(AbstractEventLoopTest, NodeSender) {
2873 EnableNodes("me");
2874 auto loop1 = Make();
2875
2876 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
2877}
2878
Austin Schuhcc6070c2020-10-10 20:25:56 -07002879// Tests that a non-realtime event loop timer is marked non-realtime.
2880TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopTimer) {
2881 auto loop1 = MakePrimary();
2882
2883 // Add a timer to actually quit.
2884 auto test_timer = loop1->AddTimer([this]() {
2885 CheckNotRealtime();
2886 this->Exit();
2887 });
2888
2889 loop1->OnRun([&test_timer, &loop1]() {
2890 CheckNotRealtime();
2891 test_timer->Setup(loop1->monotonic_now(), ::std::chrono::milliseconds(100));
2892 });
2893
2894 Run();
2895}
2896
2897// Tests that a realtime event loop timer is marked realtime.
Austin Schuh9b1d6282022-06-10 17:03:21 -07002898TEST_P(AbstractEventLoopTest, RealtimeSend) {
2899 auto loop1 = MakePrimary();
2900
2901 loop1->SetRuntimeRealtimePriority(1);
2902
2903 auto sender = loop1->MakeSender<TestMessage>("/test2");
2904
2905 loop1->OnRun([&]() {
2906 CheckRealtime();
2907
2908 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2909 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2910 builder.add_value(200);
2911 msg.CheckOk(msg.Send(builder.Finish()));
2912
2913 this->Exit();
2914 });
2915
2916 Run();
2917}
2918
2919// Tests that a realtime event loop timer is marked realtime.
Austin Schuhcc6070c2020-10-10 20:25:56 -07002920TEST_P(AbstractEventLoopTest, RealtimeEventLoopTimer) {
2921 auto loop1 = MakePrimary();
2922
2923 loop1->SetRuntimeRealtimePriority(1);
2924
2925 // Add a timer to actually quit.
2926 auto test_timer = loop1->AddTimer([this]() {
2927 CheckRealtime();
2928 this->Exit();
2929 });
2930
2931 loop1->OnRun([&test_timer, &loop1]() {
2932 CheckRealtime();
2933 test_timer->Setup(loop1->monotonic_now(), ::std::chrono::milliseconds(100));
2934 });
2935
2936 Run();
2937}
2938
2939// Tests that a non-realtime event loop phased loop is marked non-realtime.
2940TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopPhasedLoop) {
2941 auto loop1 = MakePrimary();
2942
2943 // Add a timer to actually quit.
2944 loop1->AddPhasedLoop(
2945 [this](int) {
2946 CheckNotRealtime();
2947 this->Exit();
2948 },
2949 chrono::seconds(1), chrono::seconds(0));
2950
2951 Run();
2952}
2953
2954// Tests that a realtime event loop phased loop is marked realtime.
2955TEST_P(AbstractEventLoopTest, RealtimeEventLoopPhasedLoop) {
2956 auto loop1 = MakePrimary();
2957
2958 loop1->SetRuntimeRealtimePriority(1);
2959
2960 // Add a timer to actually quit.
2961 loop1->AddPhasedLoop(
2962 [this](int) {
2963 CheckRealtime();
2964 this->Exit();
2965 },
2966 chrono::seconds(1), chrono::seconds(0));
2967
2968 Run();
2969}
2970
2971// Tests that a non-realtime event loop watcher is marked non-realtime.
2972TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopWatcher) {
2973 auto loop1 = MakePrimary();
2974 auto loop2 = Make();
2975
2976 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
2977
2978 loop1->OnRun([&]() {
2979 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2980 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07002981 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07002982 });
2983
2984 loop1->MakeWatcher("/test", [&](const TestMessage &) {
2985 CheckNotRealtime();
2986 this->Exit();
2987 });
2988
2989 Run();
2990}
2991
2992// Tests that a realtime event loop watcher is marked realtime.
2993TEST_P(AbstractEventLoopTest, RealtimeEventLoopWatcher) {
2994 auto loop1 = MakePrimary();
2995 auto loop2 = Make();
2996
2997 loop1->SetRuntimeRealtimePriority(1);
2998
2999 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
3000
3001 loop1->OnRun([&]() {
3002 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3003 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07003004 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003005 });
3006
3007 loop1->MakeWatcher("/test", [&](const TestMessage &) {
3008 CheckRealtime();
3009 this->Exit();
3010 });
3011
3012 Run();
3013}
3014
Austin Schuha9012be2021-07-21 15:19:11 -07003015// Tests that event loop's context's monotonic time is set to a value on OnRun.
3016TEST_P(AbstractEventLoopTest, SetContextOnRun) {
3017 auto loop = MakePrimary();
3018
Austin Schuh0debde12022-08-17 16:25:17 -07003019 EXPECT_EQ(loop->context().monotonic_event_time, monotonic_clock::min_time);
3020 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3021 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3022 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3023 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3024 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
3025 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
3026 EXPECT_EQ(loop->context().size, 0u);
3027 EXPECT_EQ(loop->context().data, nullptr);
3028 EXPECT_EQ(loop->context().buffer_index, -1);
3029
Austin Schuha9012be2021-07-21 15:19:11 -07003030 // We want to check that monotonic event time is before monotonic now
3031 // called inside of callback, but after time point obtained callback.
3032 aos::monotonic_clock::time_point monotonic_event_time_on_run;
3033
3034 loop->OnRun([&]() {
3035 monotonic_event_time_on_run = loop->context().monotonic_event_time;
3036 EXPECT_LE(monotonic_event_time_on_run, loop->monotonic_now());
3037 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3038 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3039 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3040 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3041 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
Austin Schuh0debde12022-08-17 16:25:17 -07003042 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
Austin Schuha9012be2021-07-21 15:19:11 -07003043 EXPECT_EQ(loop->context().size, 0u);
3044 EXPECT_EQ(loop->context().data, nullptr);
3045 EXPECT_EQ(loop->context().buffer_index, -1);
3046 });
3047
3048 EndEventLoop(loop.get(), ::std::chrono::milliseconds(200));
3049
3050 const aos::monotonic_clock::time_point before_run_time =
3051 loop->monotonic_now();
3052 Run();
3053 EXPECT_GE(monotonic_event_time_on_run, before_run_time);
Austin Schuh0debde12022-08-17 16:25:17 -07003054
3055 EXPECT_EQ(loop->context().monotonic_event_time, monotonic_clock::min_time);
3056 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3057 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3058 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3059 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3060 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
3061 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
3062 EXPECT_EQ(loop->context().size, 0u);
3063 EXPECT_EQ(loop->context().data, nullptr);
3064 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuha9012be2021-07-21 15:19:11 -07003065}
3066
Austin Schuh217a9782019-12-21 23:02:50 -08003067// Tests that watchers fail when created on the wrong node.
3068TEST_P(AbstractEventLoopDeathTest, NodeWatcher) {
3069 EnableNodes("them");
3070
3071 auto loop1 = Make();
3072 auto loop2 = Make();
3073 EXPECT_DEATH({ loop1->MakeWatcher("/test", [](const TestMessage &) {}); },
3074 "node");
3075 EXPECT_DEATH(
3076 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08003077 loop2->MakeRawWatcher(
3078 configuration::GetChannel(configuration(), "/test",
3079 "aos.TestMessage", "", nullptr),
3080 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08003081 },
3082 "node");
Brian Silverman454bc112020-03-05 14:21:25 -08003083 EXPECT_DEATH({ loop1->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
3084 "node");
3085 EXPECT_DEATH(
3086 {
3087 loop2->MakeRawNoArgWatcher(
3088 configuration::GetChannel(configuration(), "/test",
3089 "aos.TestMessage", "", nullptr),
3090 [](const Context &) {});
3091 },
3092 "node");
Austin Schuh217a9782019-12-21 23:02:50 -08003093}
3094
3095// Tests that fetchers fail when created on the wrong node.
3096TEST_P(AbstractEventLoopDeathTest, NodeFetcher) {
3097 EnableNodes("them");
3098 auto loop1 = Make();
3099
3100 EXPECT_DEATH({ auto fetcher = loop1->MakeFetcher<TestMessage>("/test"); },
3101 "node");
3102 EXPECT_DEATH(
3103 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08003104 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
3105 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08003106 },
3107 "node");
3108}
3109
3110// Tests that senders fail when created on the wrong node.
3111TEST_P(AbstractEventLoopDeathTest, NodeSender) {
3112 EnableNodes("them");
3113 auto loop1 = Make();
3114
3115 EXPECT_DEATH(
3116 {
3117 aos::Sender<TestMessage> sender =
3118 loop1->MakeSender<TestMessage>("/test");
3119 },
3120 "node");
3121
3122 // Note: Creating raw senders is always supported. Right now, this lets us
3123 // use them to create message_gateway.
3124}
3125
Brian Silverman341b57e2020-06-23 16:23:18 -07003126// Tests creating multiple Builders from a single Sender at the same time.
3127TEST_P(AbstractEventLoopDeathTest, MultipleBuilders) {
3128 auto loop1 = Make();
3129 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
3130
3131 { auto builder = sender.MakeBuilder(); }
3132 {
3133 auto builder = sender.MakeBuilder();
3134 builder.MakeBuilder<TestMessage>().Finish();
3135 }
3136 {
3137 // Creating this after the first one was destroyed should be fine.
3138 auto builder = sender.MakeBuilder();
3139 builder.MakeBuilder<TestMessage>().Finish();
3140 // But not a second one.
3141 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
3142 "May not overwrite in-use allocator");
3143 }
3144
3145 FlatbufferDetachedBuffer<TestMessage> detached =
3146 flatbuffers::DetachedBuffer();
3147 {
3148 auto builder = sender.MakeBuilder();
3149 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
3150 }
3151 {
3152 // This is the second one, after the detached one, so it should fail.
3153 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
3154 "May not overwrite in-use allocator");
3155 }
3156
3157 // Clear the detached one, and then we should be able to create another.
3158 detached = flatbuffers::DetachedBuffer();
3159 {
3160 auto builder = sender.MakeBuilder();
3161 builder.MakeBuilder<TestMessage>().Finish();
3162 }
3163
3164 // And then detach another one.
3165 {
3166 auto builder = sender.MakeBuilder();
3167 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
3168 }
3169}
3170
3171// Tests sending a buffer detached from a different builder.
3172TEST_P(AbstractEventLoopDeathTest, WrongDetachedBuffer) {
3173 auto loop1 = Make();
3174 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
3175 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
3176
3177 auto builder = sender1.MakeBuilder();
3178 FlatbufferDetachedBuffer<TestMessage> detached =
3179 builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
milind1f1dca32021-07-03 13:50:07 -07003180 EXPECT_DEATH(sender2.CheckOk(sender2.SendDetached(std::move(detached))),
Brian Silverman341b57e2020-06-23 16:23:18 -07003181 "May only send the buffer detached from this Sender");
3182}
3183
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003184int TestChannelFrequency(EventLoop *event_loop) {
3185 return event_loop->GetChannel<TestMessage>("/test")->frequency();
3186}
3187
3188int TestChannelQueueSize(EventLoop *event_loop) {
3189 const int frequency = TestChannelFrequency(event_loop);
3190 const auto channel_storage_duration = std::chrono::nanoseconds(
3191 event_loop->configuration()->channel_storage_duration());
3192 const int queue_size =
3193 frequency * std::chrono::duration_cast<std::chrono::duration<double>>(
3194 channel_storage_duration)
3195 .count();
3196
3197 return queue_size;
3198}
3199
3200RawSender::Error SendTestMessage(aos::Sender<TestMessage> &sender) {
3201 aos::Sender<TestMessage>::Builder builder = sender.MakeBuilder();
3202 TestMessage::Builder test_message_builder =
3203 builder.MakeBuilder<TestMessage>();
3204 test_message_builder.add_value(0);
3205 return builder.Send(test_message_builder.Finish());
3206}
3207
3208// Test that sending messages too fast returns
3209// RawSender::Error::kMessagesSentTooFast.
3210TEST_P(AbstractEventLoopTest, SendingMessagesTooFast) {
3211 auto event_loop = MakePrimary();
3212
3213 auto sender = event_loop->MakeSender<TestMessage>("/test");
3214
3215 // Send one message in the beginning, then wait until the
3216 // channel_storage_duration is almost done and start sending messages rapidly,
3217 // having some come in the next chanel_storage_duration. The queue_size is
3218 // 1600, so the 1601st message will be the last valid one (the initial message
3219 // having being sent more than a channel_storage_duration ago), and trying to
3220 // send the 1602nd message should return
3221 // RawSender::Error::kMessagesSentTooFast.
3222 EXPECT_EQ(SendTestMessage(sender), RawSender::Error::kOk);
3223 int msgs_sent = 1;
3224 const int queue_size = TestChannelQueueSize(event_loop.get());
3225
3226 const auto timer = event_loop->AddTimer([&]() {
3227 const bool done = (msgs_sent == queue_size + 1);
3228 ASSERT_EQ(
3229 SendTestMessage(sender),
3230 done ? RawSender::Error::kMessagesSentTooFast : RawSender::Error::kOk);
3231 msgs_sent++;
3232 if (done) {
3233 Exit();
3234 }
3235 });
3236
3237 const auto kRepeatOffset = std::chrono::milliseconds(1);
3238 const auto base_offset =
3239 std::chrono::nanoseconds(
3240 event_loop->configuration()->channel_storage_duration()) -
3241 (kRepeatOffset * (queue_size / 2));
3242 event_loop->OnRun([&event_loop, &timer, &base_offset, &kRepeatOffset]() {
3243 timer->Setup(event_loop->monotonic_now() + base_offset, kRepeatOffset);
3244 });
3245
3246 Run();
3247}
3248
3249// Tests that we are able to send messages successfully after sending messages
3250// too fast and waiting while continuously attempting to send messages.
3251// Also tests that SendFailureCounter is working correctly in this
3252// situation
3253TEST_P(AbstractEventLoopTest, SendingAfterSendingTooFast) {
3254 auto event_loop = MakePrimary();
3255
3256 auto sender = event_loop->MakeSender<TestMessage>("/test");
3257
Austin Schuh0e96d372023-05-08 10:10:21 -07003258 // We are sending bunches of messages at 100 Hz, so we will be sending too
3259 // fast after queue_size (800) ms. After this, keep sending messages, and
3260 // exactly a channel storage duration (2s) after we send the first message we
3261 // should be able to successfully send a message.
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003262
Austin Schuh0e96d372023-05-08 10:10:21 -07003263 const std::chrono::milliseconds kInterval = std::chrono::milliseconds(10);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003264 const monotonic_clock::duration channel_storage_duration =
3265 std::chrono::nanoseconds(
3266 event_loop->configuration()->channel_storage_duration());
3267 const int queue_size = TestChannelQueueSize(event_loop.get());
3268
3269 int msgs_sent = 0;
3270 SendFailureCounter counter;
3271 auto start = monotonic_clock::min_time;
3272
3273 event_loop->AddPhasedLoop(
Austin Schuh0e96d372023-05-08 10:10:21 -07003274 [&](int elapsed_cycles) {
3275 // The queue is setup for 800 messages/sec. We want to fill that up at
3276 // a rate of 2000 messages/sec so we make sure we fill it up.
3277 for (int i = 0; i < 2 * kInterval.count() * elapsed_cycles; ++i) {
3278 const auto actual_err = SendTestMessage(sender);
3279 const bool done_waiting = (start != monotonic_clock::min_time &&
3280 sender.monotonic_sent_time() >=
3281 (start + channel_storage_duration));
3282 const auto expected_err =
3283 (msgs_sent < queue_size || done_waiting
3284 ? RawSender::Error::kOk
3285 : RawSender::Error::kMessagesSentTooFast);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003286
Austin Schuh0e96d372023-05-08 10:10:21 -07003287 if (start == monotonic_clock::min_time) {
3288 start = sender.monotonic_sent_time();
3289 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003290
Austin Schuh0e96d372023-05-08 10:10:21 -07003291 ASSERT_EQ(actual_err, expected_err);
3292 counter.Count(actual_err);
3293 msgs_sent++;
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003294
Austin Schuh0e96d372023-05-08 10:10:21 -07003295 EXPECT_EQ(counter.failures(),
3296 msgs_sent <= queue_size
3297 ? 0
3298 : (msgs_sent - queue_size) -
3299 (actual_err == RawSender::Error::kOk ? 1 : 0));
3300 EXPECT_EQ(counter.just_failed(), actual_err != RawSender::Error::kOk);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003301
Austin Schuh0e96d372023-05-08 10:10:21 -07003302 if (done_waiting) {
3303 Exit();
3304 return;
3305 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003306 }
3307 },
3308 kInterval);
3309 Run();
3310}
3311
3312// Tests that RawSender::Error::kMessagesSentTooFast is returned
3313// when messages are sent too fast from senders in different loops
3314TEST_P(AbstractEventLoopTest, SendingTooFastWithMultipleLoops) {
3315 auto loop1 = MakePrimary();
3316 auto loop2 = Make();
3317
3318 auto sender1 = loop1->MakeSender<TestMessage>("/test");
3319 auto sender2 = loop2->MakeSender<TestMessage>("/test");
3320
3321 // Send queue_size messages split between the senders.
3322 const int queue_size = TestChannelQueueSize(loop1.get());
3323 for (int i = 0; i < queue_size / 2; i++) {
3324 ASSERT_EQ(SendTestMessage(sender1), RawSender::Error::kOk);
3325 ASSERT_EQ(SendTestMessage(sender2), RawSender::Error::kOk);
3326 }
3327
3328 // Since queue_size messages have been sent, this should return an error
3329 EXPECT_EQ(SendTestMessage(sender2), RawSender::Error::kMessagesSentTooFast);
3330}
3331
Parker Schuhe4a70d62017-12-27 20:10:20 -08003332} // namespace testing
3333} // namespace aos