blob: 207646719006cdeaa49ef090bb58d1d7d14ef290 [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
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07007#include "aos/events/test_message_generated.h"
Austin Schuh54cf95f2019-11-29 13:14:18 -08008#include "aos/flatbuffer_merge.h"
Austin Schuhad9e5eb2021-11-19 20:33:55 -08009#include "aos/logging/log_message_generated.h"
10#include "aos/logging/logging.h"
Austin Schuhcc6070c2020-10-10 20:25:56 -070011#include "aos/realtime.h"
Austin Schuh54cf95f2019-11-29 13:14:18 -080012#include "glog/logging.h"
Tyler Chatow67ddb032020-01-12 14:30:04 -080013#include "gmock/gmock.h"
14#include "gtest/gtest.h"
Austin Schuh9fe68f72019-08-10 19:32:03 -070015
Parker Schuhe4a70d62017-12-27 20:10:20 -080016namespace aos {
17namespace testing {
Austin Schuh52d325c2019-06-23 18:59:06 -070018namespace {
19namespace chrono = ::std::chrono;
20} // namespace
Parker Schuhe4a70d62017-12-27 20:10:20 -080021
Brian Silverman4f4e0612020-08-12 19:54:41 -070022::std::unique_ptr<EventLoop> AbstractEventLoopTest::Make(
23 std::string_view name) {
24 std::string name_copy(name);
25 if (name == "") {
26 name_copy = "loop";
27 name_copy += std::to_string(event_loop_count_);
28 }
29 ++event_loop_count_;
Austin Schuh6bae8252021-02-07 22:01:49 -080030 auto result = factory_->Make(name_copy);
31 if (do_timing_reports() == DoTimingReports::kNo) {
32 result->SkipTimingReport();
33 }
34 return result;
Brian Silverman4f4e0612020-08-12 19:54:41 -070035}
36
37void AbstractEventLoopTest::VerifyBuffers(
38 int number_buffers,
39 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>> fetchers,
40 std::vector<std::reference_wrapper<const Sender<TestMessage>>> senders) {
41 // The buffers which are in a sender.
42 std::unordered_set<int> in_sender;
43 for (const Sender<TestMessage> &sender : senders) {
44 const int this_buffer = sender.buffer_index();
45 CHECK_GE(this_buffer, 0);
46 CHECK_LT(this_buffer, number_buffers);
47 CHECK(in_sender.insert(this_buffer).second) << ": " << this_buffer;
48 }
49
50 if (read_method() != ReadMethod::PIN) {
51 // If we're not using PIN, we can't really verify anything about what
52 // buffers the fetchers have.
53 return;
54 }
55
56 // Mapping from TestMessage::value to buffer index.
57 std::unordered_map<int, int> fetcher_values;
58 for (const Fetcher<TestMessage> &fetcher : fetchers) {
59 if (!fetcher.get()) {
60 continue;
61 }
62 const int this_buffer = fetcher.context().buffer_index;
63 CHECK_GE(this_buffer, 0);
64 CHECK_LT(this_buffer, number_buffers);
65 CHECK(in_sender.count(this_buffer) == 0) << ": " << this_buffer;
66 const auto insert_result = fetcher_values.insert(
67 std::make_pair(fetcher.get()->value(), this_buffer));
68 if (!insert_result.second) {
69 CHECK_EQ(this_buffer, insert_result.first->second);
70 }
71 }
72}
73
Austin Schuh6b6dfa52019-06-12 20:16:20 -070074// Tests that watcher can receive messages from a sender.
Parker Schuhe4a70d62017-12-27 20:10:20 -080075// Also tests that OnRun() works.
76TEST_P(AbstractEventLoopTest, Basic) {
77 auto loop1 = Make();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070078 auto loop2 = MakePrimary();
79
Alex Perrycb7da4b2019-08-28 19:35:56 -070080 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
Austin Schuh6b6dfa52019-06-12 20:16:20 -070081
82 bool happened = false;
83
84 loop2->OnRun([&]() {
85 happened = true;
86
Alex Perrycb7da4b2019-08-28 19:35:56 -070087 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
88 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
89 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -070090 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -070091 });
92
93 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070094 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -070095 this->Exit();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070096 });
97
98 EXPECT_FALSE(happened);
99 Run();
100 EXPECT_TRUE(happened);
101}
102
Brian Silverman341b57e2020-06-23 16:23:18 -0700103// Tests that watcher can receive messages from a sender, sent via SendDetached.
104TEST_P(AbstractEventLoopTest, BasicSendDetached) {
105 auto loop1 = Make();
106 auto loop2 = MakePrimary();
107
108 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
109
110 FlatbufferDetachedBuffer<TestMessage> detached =
111 flatbuffers::DetachedBuffer();
112 {
113 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
114 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
115 builder.add_value(100);
116 detached = msg.Detach(builder.Finish());
117 }
118 detached = flatbuffers::DetachedBuffer();
119 {
120 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
121 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
122 builder.add_value(200);
123 detached = msg.Detach(builder.Finish());
124 }
milind1f1dca32021-07-03 13:50:07 -0700125 sender.CheckOk(sender.SendDetached(std::move(detached)));
Brian Silverman341b57e2020-06-23 16:23:18 -0700126
127 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
128 ASSERT_TRUE(fetcher.Fetch());
129 EXPECT_EQ(fetcher->value(), 200);
130}
131
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800132// Verifies that a no-arg watcher will not have a data pointer.
133TEST_P(AbstractEventLoopTest, NoArgNoData) {
134 auto loop1 = Make();
135 auto loop2 = MakePrimary();
136
137 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
138
139 bool happened = false;
140
141 loop2->OnRun([&]() {
142 happened = true;
143
144 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
145 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -0700146 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800147 });
148
149 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
150 EXPECT_GT(loop2->context().size, 0u);
151 EXPECT_EQ(nullptr, loop2->context().data);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700152 EXPECT_EQ(-1, loop2->context().buffer_index);
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800153 this->Exit();
154 });
155
156 EXPECT_FALSE(happened);
157 Run();
158 EXPECT_TRUE(happened);
159}
160
Brian Silverman454bc112020-03-05 14:21:25 -0800161// Tests that no-arg watcher can receive messages from a sender.
162// Also tests that OnRun() works.
163TEST_P(AbstractEventLoopTest, BasicNoArg) {
164 auto loop1 = Make();
165 auto loop2 = MakePrimary();
166
167 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
168
169 bool happened = false;
170
171 loop2->OnRun([&]() {
172 happened = true;
173
174 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
175 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
176 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700177 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -0800178 });
179
180 aos::Fetcher<TestMessage> fetcher = loop2->MakeFetcher<TestMessage>("/test");
181 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
182 ASSERT_TRUE(fetcher.Fetch());
183 EXPECT_EQ(fetcher->value(), 200);
184 this->Exit();
185 });
186
187 EXPECT_FALSE(happened);
188 Run();
189 EXPECT_TRUE(happened);
190}
191
192// Tests that a watcher can be created with an std::function.
193TEST_P(AbstractEventLoopTest, BasicFunction) {
194 auto loop1 = Make();
195 auto loop2 = MakePrimary();
196
197 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
198
199 bool happened = false;
200
201 loop2->OnRun([&]() {
202 happened = true;
203
204 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
205 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
206 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700207 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -0800208 });
209
210 loop2->MakeWatcher("/test", std::function<void(const TestMessage &)>(
211 [&](const TestMessage &message) {
212 EXPECT_EQ(message.value(), 200);
213 this->Exit();
214 }));
215
216 EXPECT_FALSE(happened);
217 Run();
218 EXPECT_TRUE(happened);
219}
220
Brian Silverman0fc69932020-01-24 21:54:02 -0800221// Tests that watcher can receive messages from two senders.
222// Also tests that OnRun() works.
223TEST_P(AbstractEventLoopTest, BasicTwoSenders) {
224 auto loop1 = Make();
225 auto loop2 = MakePrimary();
226
227 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
228 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
229
230 bool happened = false;
231
232 loop2->OnRun([&]() {
233 happened = true;
234
235 {
236 aos::Sender<TestMessage>::Builder msg = sender1.MakeBuilder();
237 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
238 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700239 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman0fc69932020-01-24 21:54:02 -0800240 }
241 {
242 aos::Sender<TestMessage>::Builder msg = sender2.MakeBuilder();
243 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
244 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700245 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman0fc69932020-01-24 21:54:02 -0800246 }
247 });
248
249 int messages_received = 0;
250 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
251 EXPECT_EQ(message.value(), 200);
252 this->Exit();
253 ++messages_received;
254 });
255
256 EXPECT_FALSE(happened);
257 Run();
258 EXPECT_TRUE(happened);
259 EXPECT_EQ(messages_received, 2);
260}
261
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700262// Tests that a fetcher can fetch from a sender.
263// Also tests that OnRun() works.
264TEST_P(AbstractEventLoopTest, FetchWithoutRun) {
265 auto loop1 = Make();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800266 auto loop2 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -0700267 auto loop3 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800268
269 auto sender = loop1->MakeSender<TestMessage>("/test");
270
271 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
272
Austin Schuhbbce72d2019-05-26 15:11:46 -0700273 EXPECT_FALSE(fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -0800274 EXPECT_EQ(fetcher.get(), nullptr);
275
Austin Schuhad154822019-12-27 15:45:13 -0800276 EXPECT_EQ(fetcher.context().monotonic_event_time, monotonic_clock::min_time);
277 EXPECT_EQ(fetcher.context().monotonic_remote_time, monotonic_clock::min_time);
278 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
279 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -0700280 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
Austin Schuh39788ff2019-12-01 18:22:57 -0800281 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
282 EXPECT_EQ(fetcher.context().size, 0u);
283 EXPECT_EQ(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700284 EXPECT_EQ(fetcher.context().buffer_index, -1);
Austin Schuhbbce72d2019-05-26 15:11:46 -0700285
Alex Perrycb7da4b2019-08-28 19:35:56 -0700286 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
287 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
288 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700289 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700290
291 EXPECT_TRUE(fetcher.Fetch());
292 ASSERT_FALSE(fetcher.get() == nullptr);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700293 EXPECT_EQ(fetcher.get()->value(), 200);
Austin Schuh39788ff2019-12-01 18:22:57 -0800294
295 const chrono::milliseconds kEpsilon(100);
296
Austin Schuhad154822019-12-27 15:45:13 -0800297 const aos::monotonic_clock::time_point monotonic_now = loop2->monotonic_now();
298 const aos::realtime_clock::time_point realtime_now = loop2->realtime_now();
299 EXPECT_EQ(fetcher.context().monotonic_event_time,
300 fetcher.context().monotonic_remote_time);
301 EXPECT_EQ(fetcher.context().realtime_event_time,
302 fetcher.context().realtime_remote_time);
303
304 EXPECT_GE(fetcher.context().monotonic_event_time, monotonic_now - kEpsilon);
305 EXPECT_LE(fetcher.context().monotonic_event_time, monotonic_now + kEpsilon);
306 EXPECT_GE(fetcher.context().realtime_event_time, realtime_now - kEpsilon);
307 EXPECT_LE(fetcher.context().realtime_event_time, realtime_now + kEpsilon);
Austin Schuha9012be2021-07-21 15:19:11 -0700308 EXPECT_EQ(fetcher.context().source_boot_uuid, loop2->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -0800309 EXPECT_EQ(fetcher.context().queue_index, 0x0u);
310 EXPECT_EQ(fetcher.context().size, 20u);
311 EXPECT_NE(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700312 if (read_method() == ReadMethod::PIN) {
313 EXPECT_GE(fetcher.context().buffer_index, 0);
314 EXPECT_LT(fetcher.context().buffer_index,
315 loop2->NumberBuffers(fetcher.channel()));
316 } else {
317 EXPECT_EQ(fetcher.context().buffer_index, -1);
318 }
Parker Schuhe4a70d62017-12-27 20:10:20 -0800319}
320
Austin Schuh3578a2e2019-05-25 18:17:59 -0700321// Tests that watcher will receive all messages sent if they are sent after
322// initialization and before running.
323TEST_P(AbstractEventLoopTest, DoubleSendAtStartup) {
324 auto loop1 = Make();
325 auto loop2 = MakePrimary();
326
327 auto sender = loop1->MakeSender<TestMessage>("/test");
328
329 ::std::vector<int> values;
330
331 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700332 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700333 if (values.size() == 2) {
Austin Schuh9fe68f72019-08-10 19:32:03 -0700334 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -0700335 }
336 });
337
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700338 // Before Run, should be ignored.
Austin Schuh3578a2e2019-05-25 18:17:59 -0700339 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700340 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
341 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
342 builder.add_value(199);
milind1f1dca32021-07-03 13:50:07 -0700343 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700344 }
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700345
346 loop2->OnRun([&]() {
347 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700348 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
349 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
350 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700351 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700352 }
353 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700354 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
355 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
356 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700357 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700358 }
359 });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700360
361 Run();
362
363 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
364}
365
366// Tests that watcher will not receive messages sent before the watcher is
367// created.
368TEST_P(AbstractEventLoopTest, DoubleSendAfterStartup) {
369 auto loop1 = Make();
370 auto loop2 = MakePrimary();
371
372 auto sender = loop1->MakeSender<TestMessage>("/test");
373
374 ::std::vector<int> values;
375
376 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700377 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
378 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
379 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700380 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700381 }
382 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700383 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
384 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
385 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700386 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700387 }
388
389 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700390 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700391 });
392
393 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700394 auto test_timer = loop2->AddTimer([this]() { this->Exit(); });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700395 loop2->OnRun([&test_timer, &loop2]() {
396 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
397 });
398
399 Run();
400 EXPECT_EQ(0, values.size());
401}
402
Austin Schuhbbce72d2019-05-26 15:11:46 -0700403// Tests that FetchNext gets all the messages sent after it is constructed.
404TEST_P(AbstractEventLoopTest, FetchNext) {
405 auto loop1 = Make();
406 auto loop2 = MakePrimary();
407
408 auto sender = loop1->MakeSender<TestMessage>("/test");
409 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
410
411 ::std::vector<int> values;
412
413 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700414 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
415 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
416 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700417 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700418 }
419 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700420 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
421 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
422 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700423 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700424 }
425
426 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700427 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700428 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700429 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700430 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700431 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700432 });
433
434 loop2->OnRun([&test_timer, &loop2]() {
435 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
436 });
437
438 Run();
439 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
440}
441
442// Tests that FetchNext gets no messages sent before it is constructed.
443TEST_P(AbstractEventLoopTest, FetchNextAfterSend) {
444 auto loop1 = Make();
445 auto loop2 = MakePrimary();
446
447 auto sender = loop1->MakeSender<TestMessage>("/test");
448
449 ::std::vector<int> values;
450
451 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700452 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
453 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
454 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700455 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700456 }
457 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700458 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
459 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
460 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700461 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700462 }
463
464 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
465
466 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700467 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700468 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700469 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700470 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700471 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700472 });
473
474 loop2->OnRun([&test_timer, &loop2]() {
475 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
476 });
477
478 Run();
479 EXPECT_THAT(0, values.size());
480}
481
482// Tests that Fetch returns the last message created before the loop was
483// started.
484TEST_P(AbstractEventLoopTest, FetchDataFromBeforeCreation) {
485 auto loop1 = Make();
486 auto loop2 = MakePrimary();
487
488 auto sender = loop1->MakeSender<TestMessage>("/test");
489
490 ::std::vector<int> values;
491
492 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700493 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
494 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
495 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700496 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700497 }
498 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700499 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
500 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
501 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700502 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700503 }
504
505 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
506
507 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700508 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700509 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700510 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700511 }
512 // Do it again to make sure we don't double fetch.
513 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700514 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700515 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700516 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700517 });
518
519 loop2->OnRun([&test_timer, &loop2]() {
520 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
521 });
522
523 Run();
524 EXPECT_THAT(values, ::testing::ElementsAreArray({201}));
525}
526
Naman Gupta4d13b0a2022-10-19 16:41:24 -0700527// Tests that timer handler is enabled after setup (even if it is in the past)
528// and is disabled after running
529TEST_P(AbstractEventLoopTest, CheckTimerDisabled) {
530 auto loop = MakePrimary("primary");
531
532 auto timer = loop->AddTimer([this]() {
533 LOG(INFO) << "timer called";
534 Exit();
535 });
536
537 loop->OnRun([&loop, timer]() {
538 EXPECT_TRUE(timer->IsDisabled());
539 timer->Setup(loop->monotonic_now() + chrono::milliseconds(100));
540 EXPECT_FALSE(timer->IsDisabled());
541 });
542
543 Run();
544 EXPECT_TRUE(timer->IsDisabled());
545}
546
547// Tests that timer handler is enabled after setup (even if it is in the past)
548// and is disabled after running
549TEST_P(AbstractEventLoopTest, CheckTimerRunInPastDisabled) {
550 auto loop = MakePrimary("primary");
551
552 auto timer2 = loop->AddTimer([this]() {
553 LOG(INFO) << "timer called";
554 Exit();
555 });
556
557 auto timer = loop->AddTimer([&loop, timer2]() {
558 timer2->Setup(loop->monotonic_now() - chrono::nanoseconds(1));
559 });
560
561 loop->OnRun([&loop, timer]() {
562 timer->Setup(loop->monotonic_now() + chrono::seconds(1));
563 EXPECT_FALSE(timer->IsDisabled());
564 });
565
566 Run();
567 EXPECT_TRUE(timer2->IsDisabled());
568}
569
570// Tests that timer handler is not disabled even after calling Exit on the event
571// loop within the timer
572TEST_P(AbstractEventLoopTest, CheckTimerRepeatOnCountDisabled) {
573 auto loop = MakePrimary("primary");
574 int counter = 0;
575
576 auto timer = loop->AddTimer([&counter, this]() {
577 LOG(INFO) << "timer called";
578 counter++;
579 if (counter >= 5) {
580 Exit();
581 }
582 });
583
584 loop->OnRun([&loop, timer]() {
585 timer->Setup(loop->monotonic_now() + chrono::seconds(1),
586 chrono::seconds(1));
587 EXPECT_FALSE(timer->IsDisabled());
588 });
589 Run();
590
591 // Sanity check
592 EXPECT_EQ(counter, 5);
593
594 // if you run the loop again, the timer will start running again
595 EXPECT_FALSE(timer->IsDisabled());
596
597 counter = 0;
598 Run();
599 timer->Disable();
600
601 EXPECT_TRUE(timer->IsDisabled());
602}
603
604// Tests that timer handler is not disabled even after calling Exit on the event
605// loop using an external timer
606TEST_P(AbstractEventLoopTest, CheckTimerRepeatTillEndTimerDisabled) {
607 auto loop = MakePrimary("primary");
608
609 auto timer = loop->AddTimer([]() { LOG(INFO) << "timer called"; });
610
611 loop->OnRun([&loop, timer]() {
612 timer->Setup(loop->monotonic_now() + chrono::seconds(1),
613 chrono::seconds(1));
614 EXPECT_FALSE(timer->IsDisabled());
615 });
616
617 EndEventLoop(loop.get(), chrono::seconds(5));
618 Run();
619 EXPECT_FALSE(timer->IsDisabled());
620
621 timer->Disable();
622 EXPECT_TRUE(timer->IsDisabled());
623}
624
Austin Schuhbbce72d2019-05-26 15:11:46 -0700625// Tests that Fetch and FetchNext interleave as expected.
626TEST_P(AbstractEventLoopTest, FetchAndFetchNextTogether) {
627 auto loop1 = Make();
628 auto loop2 = MakePrimary();
629
630 auto sender = loop1->MakeSender<TestMessage>("/test");
631
632 ::std::vector<int> values;
633
634 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700635 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
636 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
637 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700638 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700639 }
640 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700641 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
642 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
643 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700644 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700645 }
646
647 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
648
649 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700650 auto test_timer = loop2->AddTimer([&fetcher, &values, &sender, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700651 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700652 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700653 }
654
655 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700656 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
657 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
658 builder.add_value(202);
milind1f1dca32021-07-03 13:50:07 -0700659 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700660 }
661 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700662 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
663 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
664 builder.add_value(203);
milind1f1dca32021-07-03 13:50:07 -0700665 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700666 }
667 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700668 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
669 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
670 builder.add_value(204);
milind1f1dca32021-07-03 13:50:07 -0700671 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700672 }
673
674 if (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700675 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700676 }
677
678 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700679 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700680 }
681
Austin Schuh9fe68f72019-08-10 19:32:03 -0700682 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700683 });
684
685 loop2->OnRun([&test_timer, &loop2]() {
686 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
687 });
688
689 Run();
690 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
691}
692
Austin Schuh3115a202019-05-27 21:02:14 -0700693// Tests that FetchNext behaves correctly when we get two messages in the queue
694// but don't consume the first until after the second has been sent.
695TEST_P(AbstractEventLoopTest, FetchNextTest) {
Austin Schuh3115a202019-05-27 21:02:14 -0700696 auto send_loop = Make();
697 auto fetch_loop = Make();
698 auto sender = send_loop->MakeSender<TestMessage>("/test");
699 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
700
701 {
Tyler Chatow67ddb032020-01-12 14:30:04 -0800702 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
703 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
704 builder.add_value(100);
milind1f1dca32021-07-03 13:50:07 -0700705 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700706 }
707
708 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700709 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
710 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
711 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700712 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700713 }
714
715 ASSERT_TRUE(fetcher.FetchNext());
716 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700717 EXPECT_EQ(100, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700718
719 ASSERT_TRUE(fetcher.FetchNext());
720 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700721 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700722
723 // When we run off the end of the queue, expect to still have the old message:
724 ASSERT_FALSE(fetcher.FetchNext());
725 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700726 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700727}
728
Brian Silverman77162972020-08-12 19:52:40 -0700729// Verify that a fetcher still holds its data, even after falling behind.
730TEST_P(AbstractEventLoopTest, FetcherBehindData) {
731 auto send_loop = Make();
732 auto fetch_loop = Make();
733 auto sender = send_loop->MakeSender<TestMessage>("/test");
734 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
735 {
736 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
737 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
738 builder.add_value(1);
milind1f1dca32021-07-03 13:50:07 -0700739 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -0700740 }
741 ASSERT_TRUE(fetcher.Fetch());
742 EXPECT_EQ(1, fetcher.get()->value());
743 for (int i = 0; i < 300; ++i) {
744 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
745 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
746 builder.add_value(i + 2);
milind1f1dca32021-07-03 13:50:07 -0700747 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -0700748 }
749 EXPECT_EQ(1, fetcher.get()->value());
750}
751
752// Try a bunch of orderings of operations with fetchers and senders. Verify that
753// all the fetchers have the correct data at each step.
754TEST_P(AbstractEventLoopTest, FetcherPermutations) {
755 for (int max_save = 0; max_save < 5; ++max_save) {
756 SCOPED_TRACE("max_save=" + std::to_string(max_save));
757
758 auto send_loop = Make();
759 auto fetch_loop = Make();
760 auto sender = send_loop->MakeSender<TestMessage>("/test");
761 const auto send_message = [&sender](int i) {
762 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
763 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
764 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700765 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -0700766 };
767 std::vector<Fetcher<TestMessage>> fetchers;
768 for (int i = 0; i < 10; ++i) {
769 fetchers.emplace_back(fetch_loop->MakeFetcher<TestMessage>("/test"));
770 }
771 send_message(1);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700772 const auto verify_buffers = [&]() {
773 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>>
774 fetchers_copy;
775 for (const auto &fetcher : fetchers) {
776 fetchers_copy.emplace_back(fetcher);
777 }
778 std::vector<std::reference_wrapper<const Sender<TestMessage>>>
779 senders_copy;
780 senders_copy.emplace_back(sender);
781 VerifyBuffers(send_loop->NumberBuffers(sender.channel()), fetchers_copy,
782 senders_copy);
783 };
Brian Silverman77162972020-08-12 19:52:40 -0700784 for (auto &fetcher : fetchers) {
785 ASSERT_TRUE(fetcher.Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -0700786 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700787 EXPECT_EQ(1, fetcher.get()->value());
788 }
789
790 for (int save = 1; save <= max_save; ++save) {
791 SCOPED_TRACE("save=" + std::to_string(save));
792 send_message(100 + save);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700793 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700794 for (size_t i = 0; i < fetchers.size() - save; ++i) {
795 SCOPED_TRACE("fetcher=" + std::to_string(i));
796 ASSERT_TRUE(fetchers[i].Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -0700797 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700798 EXPECT_EQ(100 + save, fetchers[i].get()->value());
799 }
800 for (size_t i = fetchers.size() - save; i < fetchers.size() - 1; ++i) {
801 SCOPED_TRACE("fetcher=" + std::to_string(i));
802 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
803 }
804 EXPECT_EQ(1, fetchers.back().get()->value());
805 }
806
807 for (int i = 0; i < 300; ++i) {
808 send_message(200 + i);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700809 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700810 }
811
812 for (size_t i = 0; i < fetchers.size() - max_save; ++i) {
813 SCOPED_TRACE("fetcher=" + std::to_string(i));
814 if (max_save > 0) {
815 EXPECT_EQ(100 + max_save, fetchers[i].get()->value());
816 } else {
817 EXPECT_EQ(1, fetchers[i].get()->value());
818 }
819 }
820 for (size_t i = fetchers.size() - max_save; i < fetchers.size() - 1; ++i) {
821 SCOPED_TRACE("fetcher=" + std::to_string(i));
822 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
823 }
824 EXPECT_EQ(1, fetchers.back().get()->value());
825 }
826}
827
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800828// Verify that making a fetcher and watcher for "/test" succeeds.
829TEST_P(AbstractEventLoopTest, FetcherAndWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800830 auto loop = Make();
831 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800832 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Parker Schuhe4a70d62017-12-27 20:10:20 -0800833}
834
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800835// Verify that making 2 fetchers for "/test" succeeds.
Parker Schuhe4a70d62017-12-27 20:10:20 -0800836TEST_P(AbstractEventLoopTest, TwoFetcher) {
837 auto loop = Make();
838 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800839 auto fetcher2 = loop->MakeFetcher<TestMessage>("/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -0800840}
841
Alex Perrycb7da4b2019-08-28 19:35:56 -0700842// Verify that registering a watcher for an invalid channel name dies.
843TEST_P(AbstractEventLoopDeathTest, InvalidChannelName) {
844 auto loop = Make();
845 EXPECT_DEATH(
846 { loop->MakeWatcher("/test/invalid", [&](const TestMessage &) {}); },
847 "/test/invalid");
Brian Silverman454bc112020-03-05 14:21:25 -0800848 EXPECT_DEATH(
849 { loop->MakeNoArgWatcher<TestMessage>("/test/invalid", [&]() {}); },
850 "/test/invalid");
Alex Perrycb7da4b2019-08-28 19:35:56 -0700851}
852
James Kuszmaul8866e642022-06-10 16:00:36 -0700853// Verify that setting up a timer before monotonic_clock::epoch() fails.
James Kuszmaul86e86c32022-07-21 17:39:47 -0700854TEST_P(AbstractEventLoopDeathTest, NegativeTimeTimer) {
James Kuszmaul8866e642022-06-10 16:00:36 -0700855 auto loop = Make();
856 TimerHandler *time = loop->AddTimer([]() {});
857 EXPECT_DEATH(time->Setup(monotonic_clock::epoch() - std::chrono::seconds(1)),
858 "-1.000");
859}
860
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800861// Verify that registering a watcher twice for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700862TEST_P(AbstractEventLoopDeathTest, TwoWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800863 auto loop = Make();
864 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800865 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
866 "/test");
Brian Silverman454bc112020-03-05 14:21:25 -0800867 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
868}
869
870// Verify that registering a no-arg watcher twice for "/test" fails.
871TEST_P(AbstractEventLoopDeathTest, TwoNoArgWatcher) {
872 auto loop = Make();
873 loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {});
874 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
875 "/test");
876 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800877}
878
Austin Schuh3115a202019-05-27 21:02:14 -0700879// Verify that SetRuntimeRealtimePriority fails while running.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700880TEST_P(AbstractEventLoopDeathTest, SetRuntimeRealtimePriority) {
Austin Schuh3115a202019-05-27 21:02:14 -0700881 auto loop = MakePrimary();
Austin Schuh65493d62022-08-17 15:10:37 -0700882 EXPECT_EQ(0, loop->runtime_realtime_priority());
Austin Schuh3115a202019-05-27 21:02:14 -0700883 // Confirm that runtime priority calls work when not realtime.
884 loop->SetRuntimeRealtimePriority(5);
Austin Schuh65493d62022-08-17 15:10:37 -0700885 EXPECT_EQ(5, loop->runtime_realtime_priority());
Austin Schuh3115a202019-05-27 21:02:14 -0700886
887 loop->OnRun([&]() { loop->SetRuntimeRealtimePriority(5); });
888
889 EXPECT_DEATH(Run(), "realtime");
890}
891
Austin Schuh65493d62022-08-17 15:10:37 -0700892namespace {
893
894bool CpuSetEqual(const cpu_set_t &a, const cpu_set_t &b) {
895 return CPU_EQUAL(&a, &b);
896}
897
898} // namespace
899
Brian Silverman6a54ff32020-04-28 16:41:39 -0700900// Verify that SetRuntimeAffinity fails while running.
901TEST_P(AbstractEventLoopDeathTest, SetRuntimeAffinity) {
Austin Schuhde973292021-10-12 18:09:49 -0700902 const cpu_set_t available = GetCurrentThreadAffinity();
903 int first_cpu = -1;
904 for (int i = 0; i < CPU_SETSIZE; ++i) {
905 if (CPU_ISSET(i, &available)) {
906 first_cpu = i;
907 break;
908 continue;
909 }
910 }
911 CHECK_NE(first_cpu, -1) << ": Default affinity has no CPUs?";
912
Brian Silverman6a54ff32020-04-28 16:41:39 -0700913 auto loop = MakePrimary();
Austin Schuh65493d62022-08-17 15:10:37 -0700914 EXPECT_TRUE(
915 CpuSetEqual(EventLoop::DefaultAffinity(), loop->runtime_affinity()));
916 const cpu_set_t new_affinity = MakeCpusetFromCpus({first_cpu});
Brian Silverman6a54ff32020-04-28 16:41:39 -0700917 // Confirm that runtime priority calls work when not running.
Austin Schuh65493d62022-08-17 15:10:37 -0700918 loop->SetRuntimeAffinity(new_affinity);
919 EXPECT_TRUE(CpuSetEqual(new_affinity, loop->runtime_affinity()));
Brian Silverman6a54ff32020-04-28 16:41:39 -0700920
Austin Schuhde973292021-10-12 18:09:49 -0700921 loop->OnRun(
922 [&]() { loop->SetRuntimeAffinity(MakeCpusetFromCpus({first_cpu})); });
Brian Silverman6a54ff32020-04-28 16:41:39 -0700923
924 EXPECT_DEATH(Run(), "Cannot set affinity while running");
925}
926
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800927// Verify that registering a watcher and a sender for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700928TEST_P(AbstractEventLoopDeathTest, WatcherAndSender) {
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800929 auto loop = Make();
930 auto sender = loop->MakeSender<TestMessage>("/test");
931 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
932 "/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -0800933}
934
Austin Schuhe516ab02020-05-06 21:37:04 -0700935// Verify that creating too many senders fails.
936TEST_P(AbstractEventLoopDeathTest, TooManySenders) {
937 auto loop = Make();
938 std::vector<aos::Sender<TestMessage>> senders;
939 for (int i = 0; i < 10; ++i) {
940 senders.emplace_back(loop->MakeSender<TestMessage>("/test"));
941 }
942 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); },
943 "Failed to create sender on \\{ \"name\": \"/test\", \"type\": "
Brian Silverman77162972020-08-12 19:52:40 -0700944 "\"aos.TestMessage\"[^}]*\\ }, too many senders.");
945}
946
947// Verify that creating too many fetchers fails.
948TEST_P(AbstractEventLoopDeathTest, TooManyFetchers) {
949 if (read_method() != ReadMethod::PIN) {
950 // Other read methods don't limit the number of readers, so just skip this.
951 return;
952 }
953
954 auto loop = Make();
955 std::vector<aos::Fetcher<TestMessage>> fetchers;
956 for (int i = 0; i < 10; ++i) {
957 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
958 }
959 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
960 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
961 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
962}
963
964// Verify that creating too many fetchers, split between two event loops, fails.
965TEST_P(AbstractEventLoopDeathTest, TooManyFetchersTwoLoops) {
966 if (read_method() != ReadMethod::PIN) {
967 // Other read methods don't limit the number of readers, so just skip this.
968 return;
969 }
970
971 auto loop = Make();
972 auto loop2 = Make();
973 std::vector<aos::Fetcher<TestMessage>> fetchers;
974 for (int i = 0; i < 5; ++i) {
975 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
976 fetchers.emplace_back(loop2->MakeFetcher<TestMessage>("/test"));
977 }
978 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
979 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
980 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
981}
982
983// Verify that creating too many watchers fails.
984TEST_P(AbstractEventLoopDeathTest, TooManyWatchers) {
985 if (read_method() != ReadMethod::PIN) {
986 // Other read methods don't limit the number of readers, so just skip this.
987 return;
988 }
989
990 std::vector<std::unique_ptr<EventLoop>> loops;
991 for (int i = 0; i < 10; ++i) {
992 loops.emplace_back(Make());
993 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
994 }
995 EXPECT_DEATH({ Make()->MakeWatcher("/test", [](const TestMessage &) {}); },
996 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
997 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
998}
999
1000// Verify that creating too many watchers and fetchers combined fails.
1001TEST_P(AbstractEventLoopDeathTest, TooManyWatchersAndFetchers) {
1002 if (read_method() != ReadMethod::PIN) {
1003 // Other read methods don't limit the number of readers, so just skip this.
1004 return;
1005 }
1006
1007 auto loop = Make();
1008 std::vector<aos::Fetcher<TestMessage>> fetchers;
1009 std::vector<std::unique_ptr<EventLoop>> loops;
1010 for (int i = 0; i < 5; ++i) {
1011 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
1012 loops.emplace_back(Make());
1013 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
1014 }
1015 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
1016 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
1017 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
Austin Schuhe516ab02020-05-06 21:37:04 -07001018}
1019
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001020// Verify that we can't create a sender inside OnRun.
1021TEST_P(AbstractEventLoopDeathTest, SenderInOnRun) {
1022 auto loop1 = MakePrimary();
1023
1024 loop1->OnRun(
1025 [&]() { auto sender = loop1->MakeSender<TestMessage>("/test2"); });
1026
1027 EXPECT_DEATH(Run(), "running");
1028}
1029
1030// Verify that we can't create a watcher inside OnRun.
1031TEST_P(AbstractEventLoopDeathTest, WatcherInOnRun) {
1032 auto loop1 = MakePrimary();
1033
1034 loop1->OnRun(
1035 [&]() { loop1->MakeWatcher("/test", [&](const TestMessage &) {}); });
1036
1037 EXPECT_DEATH(Run(), "running");
1038}
1039
Brian Silverman454bc112020-03-05 14:21:25 -08001040// Verify that we can't create a no-arg watcher inside OnRun.
1041TEST_P(AbstractEventLoopDeathTest, NoArgWatcherInOnRun) {
1042 auto loop1 = MakePrimary();
1043
1044 loop1->OnRun(
1045 [&]() { loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {}); });
1046
1047 EXPECT_DEATH(Run(), "running");
1048}
1049
Parker Schuhe4a70d62017-12-27 20:10:20 -08001050// Verify that Quit() works when there are multiple watchers.
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001051TEST_P(AbstractEventLoopTest, MultipleWatcherQuit) {
1052 auto loop1 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -07001053 auto loop2 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -08001054
Austin Schuh3578a2e2019-05-25 18:17:59 -07001055 loop2->MakeWatcher("/test1", [&](const TestMessage &) {});
1056 loop2->MakeWatcher("/test2", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001057 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -07001058 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -07001059 });
1060
Austin Schuh81fc9cc2019-02-02 23:25:47 -08001061 auto sender = loop1->MakeSender<TestMessage>("/test2");
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001062
1063 loop2->OnRun([&]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001064 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1065 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1066 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001067 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001068 });
Parker Schuhe4a70d62017-12-27 20:10:20 -08001069
Austin Schuh44019f92019-05-19 19:58:27 -07001070 Run();
Parker Schuhe4a70d62017-12-27 20:10:20 -08001071}
1072
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001073// Verify that AOS_LOG has the right name.
1074TEST_P(AbstractEventLoopTest, AOSLog) {
1075 auto loop2 = MakePrimary("loop1");
1076 auto loop1 = Make("loop0");
1077
1078 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1079
1080 EXPECT_FALSE(fetcher.Fetch());
1081
1082 loop2->OnRun([&]() {
1083 AOS_LOG(INFO, "Testing123");
1084 this->Exit();
1085 });
1086
1087 Run();
1088 EXPECT_TRUE(fetcher.Fetch());
1089 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1090}
1091
1092// Verify that AOS_LOG has the right name in a watcher.
1093TEST_P(AbstractEventLoopTest, AOSLogWatcher) {
1094 auto loop2 = MakePrimary("loop1");
1095 auto loop1 = Make("loop0");
1096
1097 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1098
1099 EXPECT_FALSE(fetcher.Fetch());
1100
1101 auto sender = loop1->MakeSender<TestMessage>("/test2");
1102
1103 loop2->MakeWatcher("/test2", [&](const TestMessage & /*message*/) {
1104 AOS_LOG(INFO, "Testing123");
1105 this->Exit();
1106 });
1107
1108 loop2->OnRun([&]() {
1109 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1110 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1111 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001112 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001113 });
1114
1115 Run();
1116 EXPECT_TRUE(fetcher.Fetch());
1117 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1118}
1119
1120// Verify that AOS_LOG has the right name in a timer.
1121TEST_P(AbstractEventLoopTest, AOSLogTimer) {
1122 auto loop2 = MakePrimary("loop1");
1123 auto loop1 = Make("loop0");
1124
1125 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1126
1127 EXPECT_FALSE(fetcher.Fetch());
1128
1129 auto test_timer = loop2->AddTimer([&]() {
1130 AOS_LOG(INFO, "Testing123");
1131 this->Exit();
1132 });
1133
1134 loop2->OnRun([&]() { test_timer->Setup(loop2->monotonic_now()); });
1135
1136 Run();
1137 EXPECT_TRUE(fetcher.Fetch());
1138 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1139}
1140
Neil Balch229001a2018-01-07 18:22:52 -08001141// Verify that timer intervals and duration function properly.
1142TEST_P(AbstractEventLoopTest, TimerIntervalAndDuration) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001143 // Force a slower rate so we are guaranteed to have reports for our timer.
Austin Schuh39788ff2019-12-01 18:22:57 -08001144 FLAGS_timing_report_ms = 2000;
1145
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001146 const int kCount = 5;
Neil Balch229001a2018-01-07 18:22:52 -08001147
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001148 auto loop = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001149 auto loop2 = Make();
1150
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001151 ::std::vector<::aos::monotonic_clock::time_point> times;
1152 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
1153
Austin Schuh39788ff2019-12-01 18:22:57 -08001154 Fetcher<timing::Report> report_fetcher =
1155 loop2->MakeFetcher<timing::Report>("/aos");
1156 EXPECT_FALSE(report_fetcher.Fetch());
1157
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001158 auto test_timer = loop->AddTimer([this, &times, &expected_times, &loop]() {
1159 times.push_back(loop->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001160 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
1161 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
1162 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001163 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -08001164 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
1165 EXPECT_EQ(loop->context().size, 0u);
1166 EXPECT_EQ(loop->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001167 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001168
Austin Schuhad154822019-12-27 15:45:13 -08001169 expected_times.push_back(loop->context().monotonic_event_time);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001170 if (times.size() == kCount) {
1171 this->Exit();
1172 }
Neil Balch229001a2018-01-07 18:22:52 -08001173 });
Austin Schuh39788ff2019-12-01 18:22:57 -08001174 test_timer->set_name("Test loop");
Neil Balch229001a2018-01-07 18:22:52 -08001175
Austin Schuh39788ff2019-12-01 18:22:57 -08001176 const monotonic_clock::time_point start_time = loop->monotonic_now();
Austin Schuh52d325c2019-06-23 18:59:06 -07001177 // TODO(austin): This should be an error... Should be done in OnRun only.
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001178 test_timer->Setup(start_time + chrono::seconds(1), chrono::seconds(1));
1179
Austin Schuh44019f92019-05-19 19:58:27 -07001180 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001181
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001182 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001183 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
1184 ASSERT_EQ(times.size(), expected_times.size());
1185 ASSERT_EQ((times.size() % 2), 1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001186
1187 // Grab the middle sample.
1188 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
1189
1190 // Add up all the delays of all the times.
1191 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1192 for (const ::aos::monotonic_clock::time_point time : times) {
1193 sum += time - average_time;
1194 }
1195
1196 // Average and add to the middle to find the average time.
1197 sum /= times.size();
1198 average_time += sum;
1199
1200 // Compute the offset from the average and the expected average. It
1201 // should be pretty close to 0.
1202 const ::aos::monotonic_clock::duration remainder =
1203 average_time - start_time - chrono::seconds(times.size() / 2 + 1);
1204
1205 const chrono::milliseconds kEpsilon(100);
1206 EXPECT_LT(remainder, +kEpsilon);
1207 EXPECT_GT(remainder, -kEpsilon);
1208
1209 // Make sure that the average duration is close to 1 second.
1210 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1211 times.front())
1212 .count() /
1213 static_cast<double>(times.size() - 1),
1214 1.0, 0.1);
1215
1216 // Confirm that the ideal wakeup times increment correctly.
1217 for (size_t i = 1; i < expected_times.size(); ++i) {
1218 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1219 }
1220
1221 for (size_t i = 0; i < expected_times.size(); ++i) {
1222 EXPECT_EQ((expected_times[i] - start_time) % chrono::seconds(1),
1223 chrono::seconds(0));
1224 }
1225
1226 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1227 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001228
Austin Schuh6bae8252021-02-07 22:01:49 -08001229 if (do_timing_reports() == DoTimingReports::kYes) {
1230 // And, since we are here, check that the timing report makes sense.
1231 // Start by looking for our event loop's timing.
1232 FlatbufferDetachedBuffer<timing::Report> report =
1233 FlatbufferDetachedBuffer<timing::Report>::Empty();
1234 while (report_fetcher.FetchNext()) {
1235 if (report_fetcher->name()->string_view() == "primary") {
1236 report = CopyFlatBuffer(report_fetcher.get());
1237 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001238 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001239
1240 // Confirm that we have the right number of reports, and the contents are
1241 // sane.
1242 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
1243
1244 EXPECT_EQ(report.message().name()->string_view(), "primary");
1245
1246 ASSERT_NE(report.message().senders(), nullptr);
1247 EXPECT_EQ(report.message().senders()->size(), 2);
1248
1249 ASSERT_NE(report.message().timers(), nullptr);
1250 EXPECT_EQ(report.message().timers()->size(), 2);
1251
1252 EXPECT_EQ(report.message().timers()->Get(0)->name()->string_view(),
1253 "Test loop");
1254 EXPECT_GE(report.message().timers()->Get(0)->count(), 1);
1255
1256 EXPECT_EQ(report.message().timers()->Get(1)->name()->string_view(),
1257 "timing_reports");
1258 EXPECT_EQ(report.message().timers()->Get(1)->count(), 1);
1259
1260 // Make sure there is a single phased loop report with our report in it.
1261 ASSERT_EQ(report.message().phased_loops(), nullptr);
1262 } else {
1263 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001264 }
Neil Balch229001a2018-01-07 18:22:52 -08001265}
1266
1267// Verify that we can change a timer's parameters during execution.
1268TEST_P(AbstractEventLoopTest, TimerChangeParameters) {
Austin Schuh44019f92019-05-19 19:58:27 -07001269 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001270 loop->SetRuntimeRealtimePriority(1);
Austin Schuh7f20f512021-01-31 17:56:16 -08001271 std::vector<monotonic_clock::time_point> iteration_list;
Neil Balch229001a2018-01-07 18:22:52 -08001272
1273 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001274 ScopedNotRealtime nrt;
Austin Schuh7f20f512021-01-31 17:56:16 -08001275 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001276 });
1277
Austin Schuh7f20f512021-01-31 17:56:16 -08001278 monotonic_clock::time_point s;
1279 auto modifier_timer = loop->AddTimer([&test_timer, &s]() {
Austin Schuhd892f102021-10-12 18:01:46 -07001280 test_timer->Setup(s + chrono::milliseconds(1750),
1281 chrono::milliseconds(600));
Neil Balch229001a2018-01-07 18:22:52 -08001282 });
1283
Austin Schuh7f20f512021-01-31 17:56:16 -08001284 s = loop->monotonic_now();
Austin Schuhd892f102021-10-12 18:01:46 -07001285 test_timer->Setup(s, chrono::milliseconds(500));
1286 modifier_timer->Setup(s + chrono::milliseconds(1250));
1287 EndEventLoop(loop.get(), chrono::milliseconds(3950));
Austin Schuh44019f92019-05-19 19:58:27 -07001288 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001289
Austin Schuhd892f102021-10-12 18:01:46 -07001290 EXPECT_THAT(
1291 iteration_list,
1292 ::testing::ElementsAre(
1293 s, s + chrono::milliseconds(500), s + chrono::milliseconds(1000),
1294 s + chrono::milliseconds(1750), s + chrono::milliseconds(2350),
1295 s + chrono::milliseconds(2950), s + chrono::milliseconds(3550)));
Neil Balch229001a2018-01-07 18:22:52 -08001296}
1297
1298// Verify that we can disable a timer during execution.
1299TEST_P(AbstractEventLoopTest, TimerDisable) {
Austin Schuh44019f92019-05-19 19:58:27 -07001300 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001301 loop->SetRuntimeRealtimePriority(1);
Neil Balch229001a2018-01-07 18:22:52 -08001302 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
1303
1304 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001305 ScopedNotRealtime nrt;
Austin Schuhd892f102021-10-12 18:01:46 -07001306 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001307 });
1308
Tyler Chatow67ddb032020-01-12 14:30:04 -08001309 auto ender_timer = loop->AddTimer([&test_timer]() { test_timer->Disable(); });
Neil Balch229001a2018-01-07 18:22:52 -08001310
Austin Schuhd892f102021-10-12 18:01:46 -07001311 monotonic_clock::time_point s = loop->monotonic_now();
Austin Schuh73d99502021-12-08 12:05:39 -08001312 test_timer->Setup(s, ::std::chrono::milliseconds(500));
1313 ender_timer->Setup(s + ::std::chrono::milliseconds(1250));
1314 EndEventLoop(loop.get(), ::std::chrono::milliseconds(2000));
Austin Schuh44019f92019-05-19 19:58:27 -07001315 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001316
Austin Schuhd892f102021-10-12 18:01:46 -07001317 EXPECT_THAT(iteration_list,
Austin Schuh73d99502021-12-08 12:05:39 -08001318 ::testing::ElementsAre(s, s + chrono::milliseconds(500),
1319 s + chrono::milliseconds(1000)));
Neil Balch229001a2018-01-07 18:22:52 -08001320}
Austin Schuh7267c532019-05-19 19:55:53 -07001321
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001322// Verify that a timer can disable itself.
1323//
1324// TODO(Brian): Do something similar with phased loops, both with a quick
1325// handler and a handler that would miss a cycle except it got deferred. Current
1326// behavior doing that is a mess.
1327TEST_P(AbstractEventLoopTest, TimerDisableSelf) {
1328 auto loop = MakePrimary();
1329
1330 int count = 0;
1331 aos::TimerHandler *test_timer;
1332 test_timer = loop->AddTimer([&count, &test_timer]() {
1333 ++count;
1334 test_timer->Disable();
1335 });
1336
1337 test_timer->Setup(loop->monotonic_now(), ::std::chrono::milliseconds(20));
1338 EndEventLoop(loop.get(), ::std::chrono::milliseconds(80));
1339 Run();
1340
1341 EXPECT_EQ(count, 1);
1342}
1343
Brian Silvermanbd405c02020-06-23 16:25:23 -07001344// Verify that we can disable a timer during execution of another timer
1345// scheduled for the same time, with one ordering of creation for the timers.
1346//
1347// Also schedule some more events to reshuffle the heap in EventLoop used for
1348// tracking events to change up the order. This used to segfault
1349// SimulatedEventLoop.
1350TEST_P(AbstractEventLoopTest, TimerDisableOther) {
1351 for (bool creation_order : {true, false}) {
1352 for (bool setup_order : {true, false}) {
1353 for (int shuffle_events = 0; shuffle_events < 5; ++shuffle_events) {
1354 auto loop = MakePrimary();
1355 aos::TimerHandler *test_timer, *ender_timer;
1356 if (creation_order) {
1357 test_timer = loop->AddTimer([]() {});
1358 ender_timer =
1359 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1360 } else {
1361 ender_timer =
1362 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1363 test_timer = loop->AddTimer([]() {});
1364 }
1365
1366 const auto start = loop->monotonic_now();
1367
1368 for (int i = 0; i < shuffle_events; ++i) {
1369 loop->AddTimer([]() {})->Setup(start + std::chrono::milliseconds(10));
1370 }
1371
1372 if (setup_order) {
1373 test_timer->Setup(start + ::std::chrono::milliseconds(20));
1374 ender_timer->Setup(start + ::std::chrono::milliseconds(20));
1375 } else {
1376 ender_timer->Setup(start + ::std::chrono::milliseconds(20));
1377 test_timer->Setup(start + ::std::chrono::milliseconds(20));
1378 }
1379 EndEventLoop(loop.get(), ::std::chrono::milliseconds(40));
1380 Run();
1381 }
1382 }
1383 }
1384}
1385
Austin Schuh54cf95f2019-11-29 13:14:18 -08001386// Verifies that the event loop implementations detect when Channel is not a
Brian Silverman631b6262021-11-10 12:25:08 -08001387// pointer into configuration(), or a name doesn't map to a channel in
1388// configuration().
Austin Schuh54cf95f2019-11-29 13:14:18 -08001389TEST_P(AbstractEventLoopDeathTest, InvalidChannel) {
1390 auto loop = MakePrimary();
1391
Tyler Chatow67ddb032020-01-12 14:30:04 -08001392 const Channel *channel = configuration::GetChannel(
1393 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
Austin Schuh54cf95f2019-11-29 13:14:18 -08001394
1395 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1396
1397 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001398 loop->MakeRawSender(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001399 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1400
1401 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001402 loop->MakeSender<TestMessage>("/testbad"),
1403 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1404 " not found in config");
1405
1406 EXPECT_FALSE(loop->TryMakeSender<TestMessage>("/testbad"));
1407
1408 EXPECT_DEATH(
1409 loop->MakeRawFetcher(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001410 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1411
1412 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001413 loop->MakeFetcher<TestMessage>("/testbad"),
1414 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1415 " not found in config");
1416
1417 EXPECT_FALSE(loop->TryMakeFetcher<TestMessage>("/testbad").valid());
1418
1419 EXPECT_DEATH(
Austin Schuh54cf95f2019-11-29 13:14:18 -08001420 {
1421 loop->MakeRawWatcher(&channel_copy.message(),
1422 [](const Context, const void *) {});
1423 },
1424 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
Brian Silverman631b6262021-11-10 12:25:08 -08001425
1426 EXPECT_DEATH(
1427 { loop->MakeWatcher("/testbad", [](const TestMessage &) {}); },
1428 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1429 " not found in config");
1430}
1431
1432// Verifies that the event loop handles a channel which is not readable or
1433// writable on the current node nicely.
1434TEST_P(AbstractEventLoopDeathTest, InaccessibleChannel) {
1435 EnableNodes("me");
1436 auto loop = MakePrimary("me");
1437 auto loop2 = Make("them");
1438
1439 const Channel *channel = configuration::GetChannel(
1440 loop->configuration(), "/test_noforward", "aos.TestMessage", "", nullptr);
1441
1442 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1443
1444 EXPECT_DEATH(
1445 loop2->MakeSender<TestMessage>("/test_forward"),
1446 "Channel"
1447 " \\{ \"name\": \"/test_forward\", \"type\": \"aos.TestMessage\" \\}"
1448 " is not able to be sent on this node");
1449
1450 EXPECT_FALSE(loop2->TryMakeSender<TestMessage>("/test_forward"));
1451
1452 EXPECT_DEATH(
1453 loop2->MakeRawFetcher(channel),
1454 "Channel"
1455 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1456 " is not able to be fetched on this node");
1457
1458 EXPECT_DEATH(
1459 loop2->MakeFetcher<TestMessage>("/test_noforward"),
1460 "Channel"
1461 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1462 " is not able to be fetched on this node");
1463
1464 EXPECT_FALSE(loop2->TryMakeFetcher<TestMessage>("/test_noforward").valid());
1465
1466 EXPECT_DEATH(
1467 { loop2->MakeRawWatcher(channel, [](const Context, const void *) {}); },
1468 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1469 "\"source_node\": \"them\" \\}"
1470 " is not able to be watched on this node");
1471
1472 EXPECT_DEATH(
1473 { loop2->MakeWatcher("/test_noforward", [](const TestMessage &) {}); },
1474 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1475 "\"source_node\": \"them\" \\}"
1476 " is not able to be watched on this node");
Austin Schuh54cf95f2019-11-29 13:14:18 -08001477}
1478
Austin Schuhd54780b2020-10-03 16:26:02 -07001479// Verifies that the event loop implementations detect when Channel has an
1480// invalid alignment.
1481TEST_P(AbstractEventLoopDeathTest, InvalidChannelAlignment) {
1482 const char *const kError = "multiple of alignment";
1483 InvalidChannelAlignment();
1484
1485 auto loop = MakePrimary();
1486
1487 const Channel *channel = configuration::GetChannel(
1488 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
1489
1490 EXPECT_DEATH({ loop->MakeRawSender(channel); }, kError);
1491 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); }, kError);
1492
1493 EXPECT_DEATH({ loop->MakeRawFetcher(channel); }, kError);
1494 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); }, kError);
1495
1496 EXPECT_DEATH(
1497 { loop->MakeRawWatcher(channel, [](const Context &, const void *) {}); },
1498 kError);
1499 EXPECT_DEATH({ loop->MakeRawNoArgWatcher(channel, [](const Context &) {}); },
1500 kError);
1501
1502 EXPECT_DEATH({ loop->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
1503 kError);
1504 EXPECT_DEATH({ loop->MakeWatcher("/test", [](const TestMessage &) {}); },
1505 kError);
1506}
1507
Brian Silverman454bc112020-03-05 14:21:25 -08001508// Verify that the send time on a message is roughly right when using a watcher.
Austin Schuh7267c532019-05-19 19:55:53 -07001509TEST_P(AbstractEventLoopTest, MessageSendTime) {
Austin Schuh44019f92019-05-19 19:58:27 -07001510 auto loop1 = MakePrimary();
Austin Schuh7267c532019-05-19 19:55:53 -07001511 auto loop2 = Make();
Austin Schuhad154822019-12-27 15:45:13 -08001512 auto sender = loop2->MakeSender<TestMessage>("/test");
Austin Schuh7267c532019-05-19 19:55:53 -07001513 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
1514
1515 auto test_timer = loop1->AddTimer([&sender]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001516 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1517 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1518 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001519 msg.CheckOk(msg.Send(builder.Finish()));
Alex Perrycb7da4b2019-08-28 19:35:56 -07001520 });
1521
Austin Schuhad154822019-12-27 15:45:13 -08001522 bool triggered = false;
Brian Silverman454bc112020-03-05 14:21:25 -08001523 loop1->MakeWatcher("/test", [&](const TestMessage &msg) {
Austin Schuhad154822019-12-27 15:45:13 -08001524 // Confirm that the data pointer makes sense from a watcher, and all the
1525 // timestamps look right.
1526 EXPECT_GT(&msg, loop1->context().data);
1527 EXPECT_EQ(loop1->context().monotonic_remote_time,
1528 loop1->context().monotonic_event_time);
1529 EXPECT_EQ(loop1->context().realtime_remote_time,
1530 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001531 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001532
1533 const aos::monotonic_clock::time_point monotonic_now =
1534 loop1->monotonic_now();
Tyler Chatow67ddb032020-01-12 14:30:04 -08001535 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08001536
1537 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1538 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1539 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1540 monotonic_now);
1541 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1542 realtime_now);
1543
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001544 EXPECT_LT(&msg, reinterpret_cast<const void *>(
1545 reinterpret_cast<const char *>(loop1->context().data) +
Austin Schuhad154822019-12-27 15:45:13 -08001546 loop1->context().size));
Brian Silverman4f4e0612020-08-12 19:54:41 -07001547 if (read_method() == ReadMethod::PIN) {
1548 EXPECT_GE(loop1->context().buffer_index, 0);
1549 EXPECT_LT(loop1->context().buffer_index,
1550 loop1->NumberBuffers(
1551 configuration::GetChannel(loop1->configuration(), "/test",
1552 "aos.TestMessage", "", nullptr)));
1553 } else {
1554 EXPECT_EQ(-1, loop1->context().buffer_index);
1555 }
Austin Schuhad154822019-12-27 15:45:13 -08001556 triggered = true;
Austin Schuh7267c532019-05-19 19:55:53 -07001557 });
1558
1559 test_timer->Setup(loop1->monotonic_now() + ::std::chrono::seconds(1));
1560
1561 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
Austin Schuh44019f92019-05-19 19:58:27 -07001562 Run();
Austin Schuh7267c532019-05-19 19:55:53 -07001563
Austin Schuhad154822019-12-27 15:45:13 -08001564 EXPECT_TRUE(triggered);
1565
Brian Silverman454bc112020-03-05 14:21:25 -08001566 ASSERT_TRUE(fetcher.Fetch());
1567
1568 monotonic_clock::duration monotonic_time_offset =
1569 fetcher.context().monotonic_event_time -
1570 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1571 realtime_clock::duration realtime_time_offset =
1572 fetcher.context().realtime_event_time -
1573 (loop1->realtime_now() - ::std::chrono::seconds(1));
1574
1575 EXPECT_EQ(fetcher.context().realtime_event_time,
1576 fetcher.context().realtime_remote_time);
1577 EXPECT_EQ(fetcher.context().monotonic_event_time,
1578 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001579 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001580
1581 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1582 << ": Got "
1583 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1584 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1585 // Confirm that the data pointer makes sense.
1586 EXPECT_GT(fetcher.get(), fetcher.context().data);
1587 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001588 reinterpret_cast<const void *>(
1589 reinterpret_cast<const char *>(fetcher.context().data) +
Brian Silverman454bc112020-03-05 14:21:25 -08001590 fetcher.context().size));
1591 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1592 << ": Got "
1593 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1594 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1595
1596 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1597 << ": Got "
1598 << fetcher.context().realtime_event_time.time_since_epoch().count()
1599 << " expected " << loop1->realtime_now().time_since_epoch().count();
1600 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1601 << ": Got "
1602 << fetcher.context().realtime_event_time.time_since_epoch().count()
1603 << " expected " << loop1->realtime_now().time_since_epoch().count();
1604}
1605
1606// Verify that the send time on a message is roughly right when using a no-arg
1607// watcher. To get a message, we need to use a fetcher to actually access the
1608// message. This is also the main use case for no-arg fetchers.
1609TEST_P(AbstractEventLoopTest, MessageSendTimeNoArg) {
1610 auto loop1 = MakePrimary();
1611 auto loop2 = Make();
1612 auto sender = loop2->MakeSender<TestMessage>("/test");
1613 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
1614
1615 auto test_timer = loop1->AddTimer([&sender]() {
1616 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1617 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1618 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001619 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -08001620 });
1621
1622 bool triggered = false;
1623 loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {
1624 // Confirm that we can indeed use a fetcher on this channel from this
1625 // context, and it results in a sane data pointer and timestamps.
1626 ASSERT_TRUE(fetcher.Fetch());
1627
1628 EXPECT_EQ(loop1->context().monotonic_remote_time,
1629 loop1->context().monotonic_event_time);
1630 EXPECT_EQ(loop1->context().realtime_remote_time,
1631 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001632 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001633
1634 const aos::monotonic_clock::time_point monotonic_now =
1635 loop1->monotonic_now();
1636 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
1637
1638 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1639 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1640 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1641 monotonic_now);
1642 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1643 realtime_now);
1644
1645 triggered = true;
1646 });
1647
1648 test_timer->Setup(loop1->monotonic_now() + ::std::chrono::seconds(1));
1649
1650 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
1651 Run();
1652
1653 ASSERT_TRUE(triggered);
Austin Schuh7267c532019-05-19 19:55:53 -07001654
Alex Perrycb7da4b2019-08-28 19:35:56 -07001655 monotonic_clock::duration monotonic_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001656 fetcher.context().monotonic_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001657 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1658 realtime_clock::duration realtime_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001659 fetcher.context().realtime_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001660 (loop1->realtime_now() - ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07001661
Austin Schuhad154822019-12-27 15:45:13 -08001662 EXPECT_EQ(fetcher.context().realtime_event_time,
1663 fetcher.context().realtime_remote_time);
1664 EXPECT_EQ(fetcher.context().monotonic_event_time,
1665 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001666 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001667
Alex Perrycb7da4b2019-08-28 19:35:56 -07001668 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1669 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001670 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh52d325c2019-06-23 18:59:06 -07001671 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07001672 // Confirm that the data pointer makes sense.
1673 EXPECT_GT(fetcher.get(), fetcher.context().data);
1674 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001675 reinterpret_cast<const void *>(
1676 reinterpret_cast<const char *>(fetcher.context().data) +
Alex Perrycb7da4b2019-08-28 19:35:56 -07001677 fetcher.context().size));
1678 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1679 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001680 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh7267c532019-05-19 19:55:53 -07001681 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07001682
1683 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1684 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001685 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07001686 << " expected " << loop1->realtime_now().time_since_epoch().count();
1687 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1688 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001689 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07001690 << " expected " << loop1->realtime_now().time_since_epoch().count();
Austin Schuh7267c532019-05-19 19:55:53 -07001691}
1692
Austin Schuh52d325c2019-06-23 18:59:06 -07001693// Tests that a couple phased loops run in a row result in the correct offset
1694// and period.
1695TEST_P(AbstractEventLoopTest, PhasedLoopTest) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001696 // Force a slower rate so we are guaranteed to have reports for our phased
Austin Schuh39788ff2019-12-01 18:22:57 -08001697 // loop.
1698 FLAGS_timing_report_ms = 2000;
1699
Austin Schuh52d325c2019-06-23 18:59:06 -07001700 const chrono::milliseconds kOffset = chrono::milliseconds(400);
1701 const int kCount = 5;
1702
1703 auto loop1 = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001704 auto loop2 = Make();
1705
1706 Fetcher<timing::Report> report_fetcher =
1707 loop2->MakeFetcher<timing::Report>("/aos");
1708 EXPECT_FALSE(report_fetcher.Fetch());
Austin Schuh52d325c2019-06-23 18:59:06 -07001709
1710 // Collect up a couple of samples.
1711 ::std::vector<::aos::monotonic_clock::time_point> times;
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001712 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
Austin Schuh52d325c2019-06-23 18:59:06 -07001713
1714 // Run kCount iterations.
Austin Schuh39788ff2019-12-01 18:22:57 -08001715 loop1
1716 ->AddPhasedLoop(
1717 [&times, &expected_times, &loop1, this](int count) {
1718 EXPECT_EQ(count, 1);
1719 times.push_back(loop1->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001720 expected_times.push_back(loop1->context().monotonic_event_time);
Austin Schuh39788ff2019-12-01 18:22:57 -08001721
Austin Schuhad154822019-12-27 15:45:13 -08001722 EXPECT_EQ(loop1->context().monotonic_remote_time,
1723 monotonic_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001724 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001725 EXPECT_EQ(loop1->context().realtime_event_time,
1726 realtime_clock::min_time);
1727 EXPECT_EQ(loop1->context().realtime_remote_time,
Austin Schuh39788ff2019-12-01 18:22:57 -08001728 realtime_clock::min_time);
1729 EXPECT_EQ(loop1->context().queue_index, 0xffffffffu);
1730 EXPECT_EQ(loop1->context().size, 0u);
1731 EXPECT_EQ(loop1->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001732 EXPECT_EQ(loop1->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001733
1734 if (times.size() == kCount) {
1735 LOG(INFO) << "Exiting";
1736 this->Exit();
1737 }
1738 },
1739 chrono::seconds(1), kOffset)
1740 ->set_name("Test loop");
Austin Schuh52d325c2019-06-23 18:59:06 -07001741
1742 // Add a delay to make sure that delay during startup doesn't result in a
1743 // "missed cycle".
1744 SleepFor(chrono::seconds(2));
1745
1746 Run();
1747
1748 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001749 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
1750 ASSERT_EQ(times.size(), expected_times.size());
1751 ASSERT_EQ((times.size() % 2), 1);
Austin Schuh52d325c2019-06-23 18:59:06 -07001752
1753 // Grab the middle sample.
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001754 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
Austin Schuh52d325c2019-06-23 18:59:06 -07001755
1756 // Add up all the delays of all the times.
1757 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1758 for (const ::aos::monotonic_clock::time_point time : times) {
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001759 sum += time - average_time;
Austin Schuh52d325c2019-06-23 18:59:06 -07001760 }
1761
1762 // Average and add to the middle to find the average time.
1763 sum /= times.size();
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001764 average_time += sum;
Austin Schuh52d325c2019-06-23 18:59:06 -07001765
1766 // Compute the offset from the start of the second of the average time. This
1767 // should be pretty close to the offset.
1768 const ::aos::monotonic_clock::duration remainder =
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001769 average_time.time_since_epoch() -
1770 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
Austin Schuh52d325c2019-06-23 18:59:06 -07001771
1772 const chrono::milliseconds kEpsilon(100);
1773 EXPECT_LT(remainder, kOffset + kEpsilon);
1774 EXPECT_GT(remainder, kOffset - kEpsilon);
1775
1776 // Make sure that the average duration is close to 1 second.
1777 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1778 times.front())
1779 .count() /
1780 static_cast<double>(times.size() - 1),
1781 1.0, 0.1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001782
1783 // Confirm that the ideal wakeup times increment correctly.
1784 for (size_t i = 1; i < expected_times.size(); ++i) {
1785 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1786 }
1787
1788 for (size_t i = 0; i < expected_times.size(); ++i) {
1789 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
1790 kOffset);
1791 }
1792
1793 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1794 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001795
Austin Schuh6bae8252021-02-07 22:01:49 -08001796 if (do_timing_reports() == DoTimingReports::kYes) {
1797 // And, since we are here, check that the timing report makes sense.
1798 // Start by looking for our event loop's timing.
1799 FlatbufferDetachedBuffer<timing::Report> report =
1800 FlatbufferDetachedBuffer<timing::Report>::Empty();
1801 while (report_fetcher.FetchNext()) {
1802 if (report_fetcher->name()->string_view() == "primary") {
1803 report = CopyFlatBuffer(report_fetcher.get());
1804 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001805 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001806
1807 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
1808
1809 EXPECT_EQ(report.message().name()->string_view(), "primary");
1810
1811 ASSERT_NE(report.message().senders(), nullptr);
1812 EXPECT_EQ(report.message().senders()->size(), 2);
1813
1814 ASSERT_NE(report.message().timers(), nullptr);
1815 EXPECT_EQ(report.message().timers()->size(), 1);
1816
1817 // Make sure there is a single phased loop report with our report in it.
1818 ASSERT_NE(report.message().phased_loops(), nullptr);
1819 ASSERT_EQ(report.message().phased_loops()->size(), 1);
1820 EXPECT_EQ(report.message().phased_loops()->Get(0)->name()->string_view(),
1821 "Test loop");
1822 EXPECT_GE(report.message().phased_loops()->Get(0)->count(), 1);
1823 } else {
1824 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001825 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001826}
1827
Milind Upadhyay42589bb2021-05-19 20:05:16 -07001828// Tests that a phased loop responds correctly to a changing offset.
1829TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetTest) {
1830 // Force a slower rate so we are guaranteed to have reports for our phased
1831 // loop.
1832 FLAGS_timing_report_ms = 2000;
1833
1834 const chrono::milliseconds kOffset = chrono::milliseconds(400);
1835 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
1836 const int kCount = 5;
1837
1838 auto loop1 = MakePrimary();
1839
1840 // Collect up a couple of samples.
1841 ::std::vector<::aos::monotonic_clock::time_point> times;
1842 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
1843
1844 PhasedLoopHandler *phased_loop;
1845
1846 // Run kCount iterations.
1847 phased_loop = loop1->AddPhasedLoop(
1848 [&phased_loop, &times, &expected_times, &loop1, this, kOffset,
1849 kInterval](int count) {
1850 EXPECT_EQ(count, 1);
1851 times.push_back(loop1->monotonic_now());
1852
1853 expected_times.push_back(loop1->context().monotonic_event_time);
1854
1855 phased_loop->set_interval_and_offset(
1856 kInterval, kOffset - chrono::milliseconds(times.size()));
1857 LOG(INFO) << "new offset: "
1858 << (kOffset - chrono::milliseconds(times.size())).count();
1859
1860 if (times.size() == kCount) {
1861 LOG(INFO) << "Exiting";
1862 this->Exit();
1863 }
1864 },
1865 kInterval, kOffset);
1866 phased_loop->set_name("Test loop");
1867
1868 // Add a delay to make sure that delay during startup doesn't result in a
1869 // "missed cycle".
1870 SleepFor(chrono::seconds(2));
1871
1872 Run();
1873 // Confirm that we got both the right number of samples, and it's odd.
1874 EXPECT_EQ(times.size(), static_cast<size_t>(kCount));
1875 EXPECT_EQ(times.size(), expected_times.size());
1876 EXPECT_EQ((times.size() % 2), 1);
1877
1878 // Grab the middle sample.
1879 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
1880
1881 // Add up all the delays of all the times.
1882 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1883 for (const ::aos::monotonic_clock::time_point time : times) {
1884 sum += time - average_time;
1885 }
1886
1887 // Average and add to the middle to find the average time.
1888 sum /= times.size();
1889 average_time += sum;
1890
1891 // Compute the offset from the start of the second of the average time. This
1892 // should be pretty close to the offset.
1893 const ::aos::monotonic_clock::duration remainder =
1894 average_time.time_since_epoch() -
1895 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
1896
1897 const chrono::milliseconds kEpsilon(100);
1898 EXPECT_LT(remainder, kOffset + kEpsilon);
1899 EXPECT_GT(remainder, kOffset - kEpsilon);
1900
1901 // Make sure that the average duration is close to 1 second.
1902 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1903 times.front())
1904 .count() /
1905 static_cast<double>(times.size() - 1),
1906 1.0, 0.1);
1907
1908 // Confirm that the ideal wakeup times increment correctly.
1909 for (size_t i = 1; i < expected_times.size(); ++i) {
1910 LOG(INFO) << i - 1 << ": " << expected_times[i - 1] << ", " << i << ": "
1911 << expected_times[i];
1912 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1) -
1913 chrono::milliseconds(1));
1914 }
1915
1916 for (size_t i = 0; i < expected_times.size(); ++i) {
1917 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
1918 kOffset - chrono::milliseconds(i));
1919 }
1920
1921 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1922 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
1923}
1924
James Kuszmaul20dcc7c2023-01-20 11:06:31 -08001925// Tests that a phased loop responds correctly to a changing offset; sweep
1926// across a variety of potential offset changes, to ensure that we are
1927// exercising a variety of potential cases.
1928TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetSweep) {
1929 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
1930 const int kCount = 5;
1931
1932 auto loop1 = MakePrimary();
1933
1934 std::vector<aos::monotonic_clock::duration> offset_options;
1935 for (int ii = 0; ii < kCount; ++ii) {
1936 offset_options.push_back(ii * kInterval / kCount);
1937 }
1938 std::vector<aos::monotonic_clock::duration> offset_sweep;
1939 // Run over all the pair-wise combinations of offsets.
1940 for (int ii = 0; ii < kCount; ++ii) {
1941 for (int jj = 0; jj < kCount; ++jj) {
1942 offset_sweep.push_back(offset_options.at(ii));
1943 offset_sweep.push_back(offset_options.at(jj));
1944 }
1945 }
1946
1947 std::vector<::aos::monotonic_clock::time_point> expected_times;
1948
1949 PhasedLoopHandler *phased_loop;
1950
1951 // Run kCount iterations.
1952 size_t counter = 0;
1953 phased_loop = loop1->AddPhasedLoop(
1954 [&phased_loop, &expected_times, &loop1, this, kInterval, &counter,
1955 offset_sweep](int count) {
1956 EXPECT_EQ(count, 1);
1957 expected_times.push_back(loop1->context().monotonic_event_time);
1958
1959 counter++;
1960
1961 if (counter == offset_sweep.size()) {
1962 LOG(INFO) << "Exiting";
1963 this->Exit();
1964 return;
1965 }
1966
1967 phased_loop->set_interval_and_offset(kInterval,
1968 offset_sweep.at(counter));
1969 },
1970 kInterval, offset_sweep.at(0));
1971
1972 Run();
1973 ASSERT_EQ(expected_times.size(), offset_sweep.size());
1974 for (size_t ii = 1; ii < expected_times.size(); ++ii) {
1975 EXPECT_LE(expected_times.at(ii) - expected_times.at(ii - 1), kInterval);
1976 }
1977}
1978
1979// Tests that a phased loop responds correctly to being rescheduled with now
1980// equal to a time in the past.
1981TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleInPast) {
1982 const chrono::milliseconds kOffset = chrono::milliseconds(400);
1983 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
1984
1985 auto loop1 = MakePrimary();
1986
1987 std::vector<::aos::monotonic_clock::time_point> expected_times;
1988
1989 PhasedLoopHandler *phased_loop;
1990
1991 int expected_count = 1;
1992
1993 // Set up a timer that will get run immediately after the phased loop and
1994 // which will attempt to reschedule the phased loop to just before now. This
1995 // should succeed, but will result in 0 cycles elapsing.
1996 TimerHandler *manager_timer =
1997 loop1->AddTimer([&phased_loop, &loop1, &expected_count, this]() {
1998 if (expected_count == 0) {
1999 LOG(INFO) << "Exiting";
2000 this->Exit();
2001 return;
2002 }
2003 phased_loop->Reschedule(loop1->context().monotonic_event_time -
2004 std::chrono::nanoseconds(1));
2005 expected_count = 0;
2006 });
2007
2008 phased_loop = loop1->AddPhasedLoop(
2009 [&expected_count, &expected_times, &loop1, manager_timer](int count) {
2010 EXPECT_EQ(count, expected_count);
2011 expected_times.push_back(loop1->context().monotonic_event_time);
2012
2013 manager_timer->Setup(loop1->context().monotonic_event_time);
2014 },
2015 kInterval, kOffset);
2016 phased_loop->set_name("Test loop");
2017 manager_timer->set_name("Manager timer");
2018
2019 Run();
2020
2021 ASSERT_EQ(2u, expected_times.size());
2022 ASSERT_EQ(expected_times[0], expected_times[1]);
2023}
2024
2025// Tests that a phased loop responds correctly to being rescheduled at the time
2026// when it should be triggering (it should kick the trigger to the next cycle).
2027TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleNow) {
2028 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2029 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2030
2031 auto loop1 = MakePrimary();
2032
2033 std::vector<::aos::monotonic_clock::time_point> expected_times;
2034
2035 PhasedLoopHandler *phased_loop;
2036
2037 bool should_exit = false;
2038 // Set up a timer that will get run immediately after the phased loop and
2039 // which will attempt to reschedule the phased loop to now. This should
2040 // succeed, but will result in no change to the expected behavior (since this
2041 // is the same thing that is actually done internally).
2042 TimerHandler *manager_timer =
2043 loop1->AddTimer([&phased_loop, &loop1, &should_exit, this]() {
2044 if (should_exit) {
2045 LOG(INFO) << "Exiting";
2046 this->Exit();
2047 return;
2048 }
2049 phased_loop->Reschedule(loop1->context().monotonic_event_time);
2050 should_exit = true;
2051 });
2052
2053 phased_loop = loop1->AddPhasedLoop(
2054 [&expected_times, &loop1, manager_timer](int count) {
2055 EXPECT_EQ(count, 1);
2056 expected_times.push_back(loop1->context().monotonic_event_time);
2057
2058 manager_timer->Setup(loop1->context().monotonic_event_time);
2059 },
2060 kInterval, kOffset);
2061 phased_loop->set_name("Test loop");
2062 manager_timer->set_name("Manager timer");
2063
2064 Run();
2065
2066 ASSERT_EQ(2u, expected_times.size());
2067 ASSERT_EQ(expected_times[0] + kInterval, expected_times[1]);
2068}
2069
2070// Tests that a phased loop responds correctly to being rescheduled at a time in
2071// the distant future.
2072TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleFuture) {
2073 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2074 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2075
2076 auto loop1 = MakePrimary();
2077
2078 std::vector<::aos::monotonic_clock::time_point> expected_times;
2079
2080 PhasedLoopHandler *phased_loop;
2081
2082 bool should_exit = false;
2083 int expected_count = 1;
2084 TimerHandler *manager_timer = loop1->AddTimer(
2085 [&expected_count, &phased_loop, &loop1, &should_exit, this, kInterval]() {
2086 if (should_exit) {
2087 LOG(INFO) << "Exiting";
2088 this->Exit();
2089 return;
2090 }
2091 expected_count = 10;
2092 // Knock off 1 ns, since the scheduler rounds up when it is
2093 // scheduled to exactly a loop time.
2094 phased_loop->Reschedule(loop1->context().monotonic_event_time +
2095 kInterval * expected_count -
2096 std::chrono::nanoseconds(1));
2097 should_exit = true;
2098 });
2099
2100 phased_loop = loop1->AddPhasedLoop(
2101 [&expected_times, &loop1, manager_timer, &expected_count](int count) {
2102 EXPECT_EQ(count, expected_count);
2103 expected_times.push_back(loop1->context().monotonic_event_time);
2104
2105 manager_timer->Setup(loop1->context().monotonic_event_time);
2106 },
2107 kInterval, kOffset);
2108 phased_loop->set_name("Test loop");
2109 manager_timer->set_name("Manager timer");
2110
2111 Run();
2112
2113 ASSERT_EQ(2u, expected_times.size());
2114 ASSERT_EQ(expected_times[0] + expected_count * kInterval, expected_times[1]);
2115}
2116
2117// Tests that a phased loop responds correctly to having its phase offset
2118// incremented and then being scheduled after a set time, exercising a pattern
2119// where a phased loop's offset is changed while trying to maintain the trigger
2120// at a consistent period.
2121TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleWithLaterOffset) {
2122 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2123 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2124
2125 auto loop1 = MakePrimary();
2126
2127 std::vector<::aos::monotonic_clock::time_point> expected_times;
2128
2129 PhasedLoopHandler *phased_loop;
2130
2131 bool should_exit = false;
2132 TimerHandler *manager_timer = loop1->AddTimer(
2133 [&phased_loop, &loop1, &should_exit, this, kInterval, kOffset]() {
2134 if (should_exit) {
2135 LOG(INFO) << "Exiting";
2136 this->Exit();
2137 return;
2138 }
2139 // Schedule the next callback to be strictly later than the current time
2140 // + interval / 2, to ensure a consistent frequency.
2141 monotonic_clock::time_point half_time =
2142 loop1->context().monotonic_event_time + kInterval / 2;
2143 phased_loop->set_interval_and_offset(
2144 kInterval, kOffset + std::chrono::nanoseconds(1), half_time);
2145 phased_loop->Reschedule(half_time);
2146 should_exit = true;
2147 });
2148
2149 phased_loop = loop1->AddPhasedLoop(
2150 [&expected_times, &loop1, manager_timer](int count) {
2151 EXPECT_EQ(1, count);
2152 expected_times.push_back(loop1->context().monotonic_event_time);
2153
2154 manager_timer->Setup(loop1->context().monotonic_event_time);
2155 },
2156 kInterval, kOffset);
2157 phased_loop->set_name("Test loop");
2158 manager_timer->set_name("Manager timer");
2159
2160 Run();
2161
2162 ASSERT_EQ(2u, expected_times.size());
2163 ASSERT_EQ(expected_times[0] + kInterval + std::chrono::nanoseconds(1),
2164 expected_times[1]);
2165}
2166
2167// Tests that a phased loop responds correctly to having its phase offset
2168// decremented and then being scheduled after a set time, exercising a pattern
2169// where a phased loop's offset is changed while trying to maintain the trigger
2170// at a consistent period.
2171TEST_P(AbstractEventLoopTest, PhasedLoopRescheduleWithEarlierOffset) {
2172 const chrono::milliseconds kOffset = chrono::milliseconds(400);
2173 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
2174
2175 auto loop1 = MakePrimary();
2176
2177 std::vector<::aos::monotonic_clock::time_point> expected_times;
2178
2179 PhasedLoopHandler *phased_loop;
2180
2181 bool should_exit = false;
2182 TimerHandler *manager_timer = loop1->AddTimer(
2183 [&phased_loop, &loop1, &should_exit, this, kInterval, kOffset]() {
2184 if (should_exit) {
2185 LOG(INFO) << "Exiting";
2186 this->Exit();
2187 return;
2188 }
2189 // Schedule the next callback to be strictly later than the current time
2190 // + interval / 2, to ensure a consistent frequency.
2191 const aos::monotonic_clock::time_point half_time =
2192 loop1->context().monotonic_event_time + kInterval / 2;
2193 phased_loop->set_interval_and_offset(
2194 kInterval, kOffset - std::chrono::nanoseconds(1), half_time);
2195 phased_loop->Reschedule(half_time);
2196 should_exit = true;
2197 });
2198
2199 phased_loop = loop1->AddPhasedLoop(
2200 [&expected_times, &loop1, manager_timer](int count) {
2201 EXPECT_EQ(1, count);
2202 expected_times.push_back(loop1->context().monotonic_event_time);
2203
2204 manager_timer->Setup(loop1->context().monotonic_event_time);
2205 },
2206 kInterval, kOffset);
2207 phased_loop->set_name("Test loop");
2208 manager_timer->set_name("Manager timer");
2209
2210 Run();
2211
2212 ASSERT_EQ(2u, expected_times.size());
2213 ASSERT_EQ(expected_times[0] + kInterval - std::chrono::nanoseconds(1),
2214 expected_times[1]);
2215}
2216
Austin Schuh39788ff2019-12-01 18:22:57 -08002217// Tests that senders count correctly in the timing report.
2218TEST_P(AbstractEventLoopTest, SenderTimingReport) {
2219 FLAGS_timing_report_ms = 1000;
2220 auto loop1 = MakePrimary();
2221
2222 auto loop2 = Make("watcher_loop");
2223 loop2->MakeWatcher("/test", [](const TestMessage &) {});
2224
2225 auto loop3 = Make();
2226
2227 Fetcher<timing::Report> report_fetcher =
2228 loop3->MakeFetcher<timing::Report>("/aos");
2229 EXPECT_FALSE(report_fetcher.Fetch());
2230
2231 auto sender = loop1->MakeSender<TestMessage>("/test");
2232
James Kuszmaul78514332022-04-06 15:08:34 -07002233 // Sanity check channel frequencies to ensure that we've designed the test
2234 // correctly.
2235 ASSERT_EQ(800, sender.channel()->frequency());
2236 ASSERT_EQ(2000000000, loop1->configuration()->channel_storage_duration());
2237 constexpr int kMaxAllowedMessages = 800 * 2;
2238 constexpr int kSendMessages = kMaxAllowedMessages * 2;
2239 constexpr int kDroppedMessages = kSendMessages - kMaxAllowedMessages;
2240
Austin Schuh39788ff2019-12-01 18:22:57 -08002241 // Add a timer to actually quit.
2242 auto test_timer = loop1->AddTimer([&sender]() {
James Kuszmaul78514332022-04-06 15:08:34 -07002243 for (int i = 0; i < kSendMessages; ++i) {
Austin Schuh39788ff2019-12-01 18:22:57 -08002244 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2245 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2246 builder.add_value(200 + i);
James Kuszmaul78514332022-04-06 15:08:34 -07002247 if (i < kMaxAllowedMessages) {
2248 msg.CheckOk(msg.Send(builder.Finish()));
2249 } else {
2250 EXPECT_EQ(RawSender::Error::kMessagesSentTooFast,
2251 msg.Send(builder.Finish()));
2252 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002253 }
2254 });
2255
2256 // Quit after 1 timing report, mid way through the next cycle.
2257 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2258
2259 loop1->OnRun([&test_timer, &loop1]() {
2260 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1500));
2261 });
2262
2263 Run();
2264
Austin Schuh6bae8252021-02-07 22:01:49 -08002265 if (do_timing_reports() == DoTimingReports::kYes) {
2266 // And, since we are here, check that the timing report makes sense.
2267 // Start by looking for our event loop's timing.
2268 FlatbufferDetachedBuffer<timing::Report> primary_report =
2269 FlatbufferDetachedBuffer<timing::Report>::Empty();
2270 while (report_fetcher.FetchNext()) {
Austin Schuh8902fa52021-03-14 22:39:24 -07002271 VLOG(1) << "Report " << FlatbufferToJson(report_fetcher.get());
Austin Schuh6bae8252021-02-07 22:01:49 -08002272 if (report_fetcher->name()->string_view() == "primary") {
2273 primary_report = CopyFlatBuffer(report_fetcher.get());
2274 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002275 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002276
Austin Schuh8902fa52021-03-14 22:39:24 -07002277 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
Austin Schuh6bae8252021-02-07 22:01:49 -08002278
2279 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2280
2281 ASSERT_NE(primary_report.message().senders(), nullptr);
2282 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2283
2284 // Confirm that the sender looks sane.
2285 EXPECT_EQ(
2286 loop1->configuration()
2287 ->channels()
2288 ->Get(primary_report.message().senders()->Get(0)->channel_index())
2289 ->name()
2290 ->string_view(),
2291 "/test");
James Kuszmaul78514332022-04-06 15:08:34 -07002292 EXPECT_EQ(primary_report.message().senders()->Get(0)->count(),
2293 kMaxAllowedMessages);
2294 ASSERT_TRUE(primary_report.message().senders()->Get(0)->has_error_counts());
2295 ASSERT_EQ(
2296 primary_report.message().senders()->Get(0)->error_counts()->size(), 2u);
2297 EXPECT_EQ(
2298 primary_report.message()
2299 .senders()
2300 ->Get(0)
2301 ->error_counts()
2302 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2303 ->count(),
2304 kDroppedMessages)
2305 << aos::FlatbufferToJson(primary_report);
2306 EXPECT_EQ(primary_report.message()
2307 .senders()
2308 ->Get(0)
2309 ->error_counts()
2310 ->Get(static_cast<size_t>(timing::SendError::INVALID_REDZONE))
2311 ->count(),
2312 0);
Austin Schuh6bae8252021-02-07 22:01:49 -08002313
2314 // Confirm that the timing primary_report sender looks sane.
2315 EXPECT_EQ(
2316 loop1->configuration()
2317 ->channels()
2318 ->Get(primary_report.message().senders()->Get(1)->channel_index())
2319 ->name()
2320 ->string_view(),
2321 "/aos");
2322 EXPECT_EQ(primary_report.message().senders()->Get(1)->count(), 1);
2323
2324 ASSERT_NE(primary_report.message().timers(), nullptr);
2325 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2326
2327 // Make sure there are no phased loops or watchers.
2328 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2329 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2330 } else {
2331 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002332 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002333}
2334
James Kuszmaul93abac12022-04-14 15:05:10 -07002335// Tests that the RawSender::Send(void*, size_t) overload tracks things properly
2336// in its timing report.
2337TEST_P(AbstractEventLoopTest, CopySenderTimingReport) {
2338 gflags::FlagSaver flag_saver;
2339 FLAGS_timing_report_ms = 1000;
2340 auto loop1 = Make();
2341 auto loop2 = MakePrimary();
2342
2343 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2344 JsonToFlatbuffer<TestMessage>("{}");
2345
2346 std::unique_ptr<aos::RawSender> sender =
2347 loop2->MakeRawSender(configuration::GetChannel(
2348 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
2349
2350 Fetcher<timing::Report> report_fetcher =
2351 loop1->MakeFetcher<timing::Report>("/aos");
2352 EXPECT_FALSE(report_fetcher.Fetch());
2353
2354 loop2->OnRun([&]() {
2355 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
2356 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2357 RawSender::Error::kOk);
2358 }
2359 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2360 RawSender::Error::kMessagesSentTooFast);
2361 });
2362 // Quit after 1 timing report, mid way through the next cycle.
2363 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
2364
2365 Run();
2366
2367 if (do_timing_reports() == DoTimingReports::kYes) {
2368 // Check that the sent too fast actually got recorded by the timing report.
2369 FlatbufferDetachedBuffer<timing::Report> primary_report =
2370 FlatbufferDetachedBuffer<timing::Report>::Empty();
2371 while (report_fetcher.FetchNext()) {
2372 if (report_fetcher->name()->string_view() == "primary") {
2373 primary_report = CopyFlatBuffer(report_fetcher.get());
2374 }
2375 }
2376
2377 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2378
2379 ASSERT_NE(primary_report.message().senders(), nullptr);
2380 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2381 EXPECT_EQ(
2382 primary_report.message()
2383 .senders()
2384 ->Get(0)
2385 ->error_counts()
2386 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2387 ->count(),
2388 1);
2389 }
2390}
2391
Austin Schuhe0ab4de2023-05-03 08:05:08 -07002392// Tests that the RawSender::Send(SharedSpan) overload works.
2393TEST_P(AbstractEventLoopTest, SharedSenderTimingReport) {
2394 gflags::FlagSaver flag_saver;
2395 FLAGS_timing_report_ms = 1000;
2396 auto loop1 = Make();
2397 auto loop2 = MakePrimary();
2398
2399 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2400 JsonToFlatbuffer<TestMessage>("{}");
2401
2402 std::unique_ptr<aos::RawSender> sender =
2403 loop2->MakeRawSender(configuration::GetChannel(
2404 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
2405
2406 Fetcher<timing::Report> report_fetcher =
2407 loop1->MakeFetcher<timing::Report>("/aos");
2408 EXPECT_FALSE(report_fetcher.Fetch());
2409
2410 loop2->OnRun([&]() {
2411 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
2412 auto shared_span = MakeSharedSpan(kMessage.span().size());
2413 memcpy(shared_span.second.data(), kMessage.span().data(),
2414 kMessage.span().size());
2415 EXPECT_EQ(sender->Send(std::move(shared_span.first)),
2416 RawSender::Error::kOk);
2417 }
2418 auto shared_span = MakeSharedSpan(kMessage.span().size());
2419 memcpy(shared_span.second.data(), kMessage.span().data(),
2420 kMessage.span().size());
2421 EXPECT_EQ(sender->Send(std::move(shared_span.first)),
2422 RawSender::Error::kMessagesSentTooFast);
2423 });
2424 // Quit after 1 timing report, mid way through the next cycle.
2425 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
2426
2427 Run();
2428
2429 if (do_timing_reports() == DoTimingReports::kYes) {
2430 // Check that the sent too fast actually got recorded by the timing report.
2431 FlatbufferDetachedBuffer<timing::Report> primary_report =
2432 FlatbufferDetachedBuffer<timing::Report>::Empty();
2433 while (report_fetcher.FetchNext()) {
2434 if (report_fetcher->name()->string_view() == "primary") {
2435 primary_report = CopyFlatBuffer(report_fetcher.get());
2436 }
2437 }
2438
2439 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2440
2441 ASSERT_NE(primary_report.message().senders(), nullptr);
2442 EXPECT_EQ(primary_report.message().senders()->size(), 3);
2443 EXPECT_EQ(
2444 primary_report.message()
2445 .senders()
2446 ->Get(0)
2447 ->error_counts()
2448 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
2449 ->count(),
2450 1);
2451 }
2452}
2453
Austin Schuh39788ff2019-12-01 18:22:57 -08002454// Tests that senders count correctly in the timing report.
2455TEST_P(AbstractEventLoopTest, WatcherTimingReport) {
2456 FLAGS_timing_report_ms = 1000;
2457 auto loop1 = MakePrimary();
2458 loop1->MakeWatcher("/test", [](const TestMessage &) {});
2459
2460 auto loop2 = Make("sender_loop");
2461
2462 auto loop3 = Make();
2463
2464 Fetcher<timing::Report> report_fetcher =
2465 loop3->MakeFetcher<timing::Report>("/aos");
2466 EXPECT_FALSE(report_fetcher.Fetch());
2467
2468 auto sender = loop2->MakeSender<TestMessage>("/test");
2469
2470 // Add a timer to actually quit.
2471 auto test_timer = loop1->AddTimer([&sender]() {
2472 for (int i = 0; i < 10; ++i) {
2473 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2474 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2475 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002476 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002477 }
2478 });
2479
2480 // Quit after 1 timing report, mid way through the next cycle.
2481 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2482
2483 loop1->OnRun([&test_timer, &loop1]() {
2484 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1500));
2485 });
2486
2487 Run();
2488
Austin Schuh6bae8252021-02-07 22:01:49 -08002489 if (do_timing_reports() == DoTimingReports::kYes) {
2490 // And, since we are here, check that the timing report makes sense.
2491 // Start by looking for our event loop's timing.
2492 FlatbufferDetachedBuffer<timing::Report> primary_report =
2493 FlatbufferDetachedBuffer<timing::Report>::Empty();
2494 while (report_fetcher.FetchNext()) {
2495 LOG(INFO) << "Report " << FlatbufferToJson(report_fetcher.get());
2496 if (report_fetcher->name()->string_view() == "primary") {
2497 primary_report = CopyFlatBuffer(report_fetcher.get());
2498 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002499 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002500
2501 // Check the watcher report.
2502 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2503
2504 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2505
2506 // Just the timing report timer.
2507 ASSERT_NE(primary_report.message().timers(), nullptr);
2508 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2509
2510 // No phased loops
2511 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2512
2513 ASSERT_NE(primary_report.message().watchers(), nullptr);
2514 ASSERT_EQ(primary_report.message().watchers()->size(), 1);
2515 EXPECT_EQ(primary_report.message().watchers()->Get(0)->count(), 10);
2516 } else {
2517 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002518 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002519}
2520
2521// Tests that fetchers count correctly in the timing report.
2522TEST_P(AbstractEventLoopTest, FetcherTimingReport) {
2523 FLAGS_timing_report_ms = 1000;
2524 auto loop1 = MakePrimary();
2525 auto loop2 = Make("sender_loop");
2526
2527 auto loop3 = Make();
2528
2529 Fetcher<timing::Report> report_fetcher =
2530 loop3->MakeFetcher<timing::Report>("/aos");
2531 EXPECT_FALSE(report_fetcher.Fetch());
2532
2533 auto sender = loop2->MakeSender<TestMessage>("/test");
2534 auto fetcher1 = loop1->MakeFetcher<TestMessage>("/test");
2535 auto fetcher2 = loop1->MakeFetcher<TestMessage>("/test");
2536 fetcher1.Fetch();
2537 fetcher2.Fetch();
2538
2539 // Add a timer to actually quit.
2540 auto test_timer = loop1->AddTimer([&sender]() {
2541 for (int i = 0; i < 10; ++i) {
2542 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2543 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2544 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002545 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002546 }
2547 });
2548
2549 auto test_timer2 = loop1->AddTimer([&fetcher1, &fetcher2]() {
2550 fetcher1.Fetch();
2551 while (fetcher2.FetchNext()) {
2552 }
2553 });
2554
2555 // Quit after 1 timing report, mid way through the next cycle.
2556 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2557
2558 loop1->OnRun([test_timer, test_timer2, &loop1]() {
2559 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1400));
2560 test_timer2->Setup(loop1->monotonic_now() + chrono::milliseconds(1600));
2561 });
2562
2563 Run();
2564
Austin Schuh6bae8252021-02-07 22:01:49 -08002565 if (do_timing_reports() == DoTimingReports::kYes) {
2566 // And, since we are here, check that the timing report makes sense.
2567 // Start by looking for our event loop's timing.
2568 FlatbufferDetachedBuffer<timing::Report> primary_report =
2569 FlatbufferDetachedBuffer<timing::Report>::Empty();
2570 while (report_fetcher.FetchNext()) {
2571 if (report_fetcher->name()->string_view() == "primary") {
2572 primary_report = CopyFlatBuffer(report_fetcher.get());
2573 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002574 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002575
2576 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2577
2578 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2579
2580 ASSERT_NE(primary_report.message().senders(), nullptr);
2581 EXPECT_EQ(primary_report.message().senders()->size(), 2);
2582
2583 ASSERT_NE(primary_report.message().timers(), nullptr);
2584 EXPECT_EQ(primary_report.message().timers()->size(), 4);
2585
2586 // Make sure there are no phased loops or watchers.
2587 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2588 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2589
2590 // Now look at the fetchrs.
2591 ASSERT_NE(primary_report.message().fetchers(), nullptr);
2592 ASSERT_EQ(primary_report.message().fetchers()->size(), 2);
2593
2594 EXPECT_EQ(primary_report.message().fetchers()->Get(0)->count(), 1);
2595 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->average(),
2596 0.1);
2597 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->min(),
2598 0.1);
2599 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->max(),
2600 0.1);
2601 EXPECT_EQ(primary_report.message()
2602 .fetchers()
2603 ->Get(0)
2604 ->latency()
2605 ->standard_deviation(),
2606 0.0);
2607
2608 EXPECT_EQ(primary_report.message().fetchers()->Get(1)->count(), 10);
2609 } else {
2610 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002611 }
Austin Schuh52d325c2019-06-23 18:59:06 -07002612}
2613
Austin Schuh67420a42019-12-21 21:55:04 -08002614// Tests that a raw watcher and raw fetcher can receive messages from a raw
2615// sender without messing up offsets.
2616TEST_P(AbstractEventLoopTest, RawBasic) {
2617 auto loop1 = Make();
2618 auto loop2 = MakePrimary();
2619 auto loop3 = Make();
2620
Austin Schuha9df9ad2021-06-16 14:49:39 -07002621 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2622 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuh67420a42019-12-21 21:55:04 -08002623
2624 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002625 loop1->MakeRawSender(configuration::GetChannel(
2626 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08002627
2628 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002629 loop3->MakeRawFetcher(configuration::GetChannel(
2630 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08002631
Austin Schuha9df9ad2021-06-16 14:49:39 -07002632 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002633 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2634 RawSender::Error::kOk);
Austin Schuha9df9ad2021-06-16 14:49:39 -07002635 });
Austin Schuh67420a42019-12-21 21:55:04 -08002636
2637 bool happened = false;
2638 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08002639 configuration::GetChannel(loop2->configuration(), "/test",
2640 "aos.TestMessage", "", nullptr),
Austin Schuha9df9ad2021-06-16 14:49:39 -07002641 [this, &kMessage, &fetcher, &happened](const Context &context,
2642 const void *message) {
Austin Schuh67420a42019-12-21 21:55:04 -08002643 happened = true;
Austin Schuha9df9ad2021-06-16 14:49:39 -07002644 EXPECT_EQ(
2645 kMessage.span(),
2646 absl::Span<const uint8_t>(
2647 reinterpret_cast<const uint8_t *>(message), context.size));
2648 EXPECT_EQ(message, context.data);
Austin Schuh67420a42019-12-21 21:55:04 -08002649
2650 ASSERT_TRUE(fetcher->Fetch());
2651
Austin Schuha9df9ad2021-06-16 14:49:39 -07002652 EXPECT_EQ(kMessage.span(),
2653 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
2654 fetcher->context().data),
2655 fetcher->context().size));
Austin Schuh67420a42019-12-21 21:55:04 -08002656
2657 this->Exit();
2658 });
2659
2660 EXPECT_FALSE(happened);
2661 Run();
2662 EXPECT_TRUE(happened);
2663}
2664
Austin Schuhad154822019-12-27 15:45:13 -08002665// Tests that a raw watcher and raw fetcher can receive messages from a raw
Brian Silvermanbf889922021-11-10 12:41:57 -08002666// sender without messing up offsets, using the RawSpan overload.
2667TEST_P(AbstractEventLoopTest, RawBasicSharedSpan) {
2668 auto loop1 = Make();
2669 auto loop2 = MakePrimary();
2670 auto loop3 = Make();
2671
2672 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2673 JsonToFlatbuffer<TestMessage>("{}");
2674
2675 std::unique_ptr<aos::RawSender> sender =
2676 loop1->MakeRawSender(configuration::GetChannel(
2677 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
2678
2679 std::unique_ptr<aos::RawFetcher> fetcher =
2680 loop3->MakeRawFetcher(configuration::GetChannel(
2681 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
2682
2683 loop2->OnRun([&]() {
Austin Schuhe0ab4de2023-05-03 08:05:08 -07002684 auto shared_span = MakeSharedSpan(kMessage.span().size());
2685 memcpy(shared_span.second.data(), kMessage.span().data(),
2686 kMessage.span().size());
2687 sender->CheckOk(sender->Send(std::move(shared_span.first)));
Brian Silvermanbf889922021-11-10 12:41:57 -08002688 });
2689
2690 bool happened = false;
2691 loop2->MakeRawWatcher(
2692 configuration::GetChannel(loop2->configuration(), "/test",
2693 "aos.TestMessage", "", nullptr),
2694 [this, &kMessage, &fetcher, &happened](const Context &context,
2695 const void *message) {
2696 happened = true;
2697 EXPECT_EQ(
2698 kMessage.span(),
2699 absl::Span<const uint8_t>(
2700 reinterpret_cast<const uint8_t *>(message), context.size));
2701 EXPECT_EQ(message, context.data);
2702
2703 ASSERT_TRUE(fetcher->Fetch());
2704
2705 EXPECT_EQ(kMessage.span(),
2706 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
2707 fetcher->context().data),
2708 fetcher->context().size));
2709
2710 this->Exit();
2711 });
2712
2713 EXPECT_FALSE(happened);
2714 Run();
2715 EXPECT_TRUE(happened);
2716}
2717
2718// Tests that a raw watcher and raw fetcher can receive messages from a raw
Austin Schuhad154822019-12-27 15:45:13 -08002719// sender with remote times filled out.
2720TEST_P(AbstractEventLoopTest, RawRemoteTimes) {
2721 auto loop1 = Make();
2722 auto loop2 = MakePrimary();
2723 auto loop3 = Make();
2724
Austin Schuha9df9ad2021-06-16 14:49:39 -07002725 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2726 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08002727
2728 const aos::monotonic_clock::time_point monotonic_remote_time =
2729 aos::monotonic_clock::time_point(chrono::seconds(1501));
2730 const aos::realtime_clock::time_point realtime_remote_time =
2731 aos::realtime_clock::time_point(chrono::seconds(3132));
Austin Schuhb5c6f972021-03-14 21:53:07 -07002732 const uint32_t remote_queue_index = 0x254971;
Austin Schuha9012be2021-07-21 15:19:11 -07002733 const UUID source_boot_uuid = UUID::Random();
Austin Schuhad154822019-12-27 15:45:13 -08002734
2735 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002736 loop1->MakeRawSender(configuration::GetChannel(
2737 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08002738
2739 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002740 loop3->MakeRawFetcher(configuration::GetChannel(
2741 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08002742
2743 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002744 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size(),
2745 monotonic_remote_time, realtime_remote_time,
2746 remote_queue_index, source_boot_uuid),
2747 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08002748 });
2749
2750 bool happened = false;
2751 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08002752 configuration::GetChannel(loop2->configuration(), "/test",
2753 "aos.TestMessage", "", nullptr),
Austin Schuha9012be2021-07-21 15:19:11 -07002754 [this, monotonic_remote_time, realtime_remote_time, source_boot_uuid,
Austin Schuhb5c6f972021-03-14 21:53:07 -07002755 remote_queue_index, &fetcher,
2756 &happened](const Context &context, const void * /*message*/) {
Austin Schuhad154822019-12-27 15:45:13 -08002757 happened = true;
2758 EXPECT_EQ(monotonic_remote_time, context.monotonic_remote_time);
2759 EXPECT_EQ(realtime_remote_time, context.realtime_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002760 EXPECT_EQ(source_boot_uuid, context.source_boot_uuid);
Austin Schuhb5c6f972021-03-14 21:53:07 -07002761 EXPECT_EQ(remote_queue_index, context.remote_queue_index);
Austin Schuhad154822019-12-27 15:45:13 -08002762
2763 ASSERT_TRUE(fetcher->Fetch());
2764 EXPECT_EQ(monotonic_remote_time,
2765 fetcher->context().monotonic_remote_time);
2766 EXPECT_EQ(realtime_remote_time,
2767 fetcher->context().realtime_remote_time);
2768
2769 this->Exit();
2770 });
2771
2772 EXPECT_FALSE(happened);
2773 Run();
2774 EXPECT_TRUE(happened);
2775}
2776
2777// Tests that a raw sender fills out sent data.
2778TEST_P(AbstractEventLoopTest, RawSenderSentData) {
2779 auto loop1 = MakePrimary();
2780
Austin Schuha9df9ad2021-06-16 14:49:39 -07002781 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2782 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08002783
2784 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002785 loop1->MakeRawSender(configuration::GetChannel(
2786 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08002787
Tyler Chatow67ddb032020-01-12 14:30:04 -08002788 const aos::monotonic_clock::time_point monotonic_now = loop1->monotonic_now();
2789 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08002790
milind1f1dca32021-07-03 13:50:07 -07002791 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2792 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08002793
2794 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
2795 EXPECT_LE(sender->monotonic_sent_time(),
2796 monotonic_now + chrono::milliseconds(100));
2797 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
2798 EXPECT_LE(sender->realtime_sent_time(),
2799 realtime_now + chrono::milliseconds(100));
2800 EXPECT_EQ(sender->sent_queue_index(), 0u);
2801
milind1f1dca32021-07-03 13:50:07 -07002802 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2803 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08002804
2805 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
2806 EXPECT_LE(sender->monotonic_sent_time(),
2807 monotonic_now + chrono::milliseconds(100));
2808 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
2809 EXPECT_LE(sender->realtime_sent_time(),
2810 realtime_now + chrono::milliseconds(100));
2811 EXPECT_EQ(sender->sent_queue_index(), 1u);
2812}
2813
Austin Schuh217a9782019-12-21 23:02:50 -08002814// Tests that not setting up nodes results in no node.
2815TEST_P(AbstractEventLoopTest, NoNode) {
2816 auto loop1 = Make();
2817 auto loop2 = MakePrimary();
2818
2819 EXPECT_EQ(loop1->node(), nullptr);
2820 EXPECT_EQ(loop2->node(), nullptr);
2821}
2822
2823// Tests that setting up nodes results in node being set.
2824TEST_P(AbstractEventLoopTest, Node) {
2825 EnableNodes("me");
2826
2827 auto loop1 = Make();
2828 auto loop2 = MakePrimary();
2829
2830 EXPECT_NE(loop1->node(), nullptr);
2831 EXPECT_NE(loop2->node(), nullptr);
2832}
2833
2834// Tests that watchers work with a node setup.
2835TEST_P(AbstractEventLoopTest, NodeWatcher) {
2836 EnableNodes("me");
2837
2838 auto loop1 = Make();
2839 auto loop2 = Make();
2840 loop1->MakeWatcher("/test", [](const TestMessage &) {});
Tyler Chatow67ddb032020-01-12 14:30:04 -08002841 loop2->MakeRawWatcher(
2842 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
2843 nullptr),
2844 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08002845}
2846
Brian Silverman454bc112020-03-05 14:21:25 -08002847// Tests that no-arg watchers work with a node setup.
2848TEST_P(AbstractEventLoopTest, NodeNoArgWatcher) {
2849 EnableNodes("me");
2850
2851 auto loop1 = Make();
2852 auto loop2 = Make();
2853 loop1->MakeWatcher("/test", [](const TestMessage &) {});
2854 loop2->MakeRawNoArgWatcher(
2855 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
2856 nullptr),
2857 [](const Context &) {});
2858}
2859
Austin Schuh217a9782019-12-21 23:02:50 -08002860// Tests that fetcher work with a node setup.
2861TEST_P(AbstractEventLoopTest, NodeFetcher) {
2862 EnableNodes("me");
2863 auto loop1 = Make();
2864
2865 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
Tyler Chatow67ddb032020-01-12 14:30:04 -08002866 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
2867 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08002868}
2869
2870// Tests that sender work with a node setup.
2871TEST_P(AbstractEventLoopTest, NodeSender) {
2872 EnableNodes("me");
2873 auto loop1 = Make();
2874
2875 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
2876}
2877
Austin Schuhcc6070c2020-10-10 20:25:56 -07002878// Tests that a non-realtime event loop timer is marked non-realtime.
2879TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopTimer) {
2880 auto loop1 = MakePrimary();
2881
2882 // Add a timer to actually quit.
2883 auto test_timer = loop1->AddTimer([this]() {
2884 CheckNotRealtime();
2885 this->Exit();
2886 });
2887
2888 loop1->OnRun([&test_timer, &loop1]() {
2889 CheckNotRealtime();
2890 test_timer->Setup(loop1->monotonic_now(), ::std::chrono::milliseconds(100));
2891 });
2892
2893 Run();
2894}
2895
2896// Tests that a realtime event loop timer is marked realtime.
Austin Schuh9b1d6282022-06-10 17:03:21 -07002897TEST_P(AbstractEventLoopTest, RealtimeSend) {
2898 auto loop1 = MakePrimary();
2899
2900 loop1->SetRuntimeRealtimePriority(1);
2901
2902 auto sender = loop1->MakeSender<TestMessage>("/test2");
2903
2904 loop1->OnRun([&]() {
2905 CheckRealtime();
2906
2907 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2908 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2909 builder.add_value(200);
2910 msg.CheckOk(msg.Send(builder.Finish()));
2911
2912 this->Exit();
2913 });
2914
2915 Run();
2916}
2917
2918// Tests that a realtime event loop timer is marked realtime.
Austin Schuhcc6070c2020-10-10 20:25:56 -07002919TEST_P(AbstractEventLoopTest, RealtimeEventLoopTimer) {
2920 auto loop1 = MakePrimary();
2921
2922 loop1->SetRuntimeRealtimePriority(1);
2923
2924 // Add a timer to actually quit.
2925 auto test_timer = loop1->AddTimer([this]() {
2926 CheckRealtime();
2927 this->Exit();
2928 });
2929
2930 loop1->OnRun([&test_timer, &loop1]() {
2931 CheckRealtime();
2932 test_timer->Setup(loop1->monotonic_now(), ::std::chrono::milliseconds(100));
2933 });
2934
2935 Run();
2936}
2937
2938// Tests that a non-realtime event loop phased loop is marked non-realtime.
2939TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopPhasedLoop) {
2940 auto loop1 = MakePrimary();
2941
2942 // Add a timer to actually quit.
2943 loop1->AddPhasedLoop(
2944 [this](int) {
2945 CheckNotRealtime();
2946 this->Exit();
2947 },
2948 chrono::seconds(1), chrono::seconds(0));
2949
2950 Run();
2951}
2952
2953// Tests that a realtime event loop phased loop is marked realtime.
2954TEST_P(AbstractEventLoopTest, RealtimeEventLoopPhasedLoop) {
2955 auto loop1 = MakePrimary();
2956
2957 loop1->SetRuntimeRealtimePriority(1);
2958
2959 // Add a timer to actually quit.
2960 loop1->AddPhasedLoop(
2961 [this](int) {
2962 CheckRealtime();
2963 this->Exit();
2964 },
2965 chrono::seconds(1), chrono::seconds(0));
2966
2967 Run();
2968}
2969
2970// Tests that a non-realtime event loop watcher is marked non-realtime.
2971TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopWatcher) {
2972 auto loop1 = MakePrimary();
2973 auto loop2 = Make();
2974
2975 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
2976
2977 loop1->OnRun([&]() {
2978 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2979 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07002980 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07002981 });
2982
2983 loop1->MakeWatcher("/test", [&](const TestMessage &) {
2984 CheckNotRealtime();
2985 this->Exit();
2986 });
2987
2988 Run();
2989}
2990
2991// Tests that a realtime event loop watcher is marked realtime.
2992TEST_P(AbstractEventLoopTest, RealtimeEventLoopWatcher) {
2993 auto loop1 = MakePrimary();
2994 auto loop2 = Make();
2995
2996 loop1->SetRuntimeRealtimePriority(1);
2997
2998 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
2999
3000 loop1->OnRun([&]() {
3001 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
3002 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07003003 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07003004 });
3005
3006 loop1->MakeWatcher("/test", [&](const TestMessage &) {
3007 CheckRealtime();
3008 this->Exit();
3009 });
3010
3011 Run();
3012}
3013
Austin Schuha9012be2021-07-21 15:19:11 -07003014// Tests that event loop's context's monotonic time is set to a value on OnRun.
3015TEST_P(AbstractEventLoopTest, SetContextOnRun) {
3016 auto loop = MakePrimary();
3017
Austin Schuh0debde12022-08-17 16:25:17 -07003018 EXPECT_EQ(loop->context().monotonic_event_time, monotonic_clock::min_time);
3019 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3020 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3021 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3022 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3023 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
3024 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
3025 EXPECT_EQ(loop->context().size, 0u);
3026 EXPECT_EQ(loop->context().data, nullptr);
3027 EXPECT_EQ(loop->context().buffer_index, -1);
3028
Austin Schuha9012be2021-07-21 15:19:11 -07003029 // We want to check that monotonic event time is before monotonic now
3030 // called inside of callback, but after time point obtained callback.
3031 aos::monotonic_clock::time_point monotonic_event_time_on_run;
3032
3033 loop->OnRun([&]() {
3034 monotonic_event_time_on_run = loop->context().monotonic_event_time;
3035 EXPECT_LE(monotonic_event_time_on_run, loop->monotonic_now());
3036 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3037 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3038 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3039 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3040 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
Austin Schuh0debde12022-08-17 16:25:17 -07003041 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
Austin Schuha9012be2021-07-21 15:19:11 -07003042 EXPECT_EQ(loop->context().size, 0u);
3043 EXPECT_EQ(loop->context().data, nullptr);
3044 EXPECT_EQ(loop->context().buffer_index, -1);
3045 });
3046
3047 EndEventLoop(loop.get(), ::std::chrono::milliseconds(200));
3048
3049 const aos::monotonic_clock::time_point before_run_time =
3050 loop->monotonic_now();
3051 Run();
3052 EXPECT_GE(monotonic_event_time_on_run, before_run_time);
Austin Schuh0debde12022-08-17 16:25:17 -07003053
3054 EXPECT_EQ(loop->context().monotonic_event_time, monotonic_clock::min_time);
3055 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
3056 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
3057 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
3058 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
3059 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
3060 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
3061 EXPECT_EQ(loop->context().size, 0u);
3062 EXPECT_EQ(loop->context().data, nullptr);
3063 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuha9012be2021-07-21 15:19:11 -07003064}
3065
Austin Schuh217a9782019-12-21 23:02:50 -08003066// Tests that watchers fail when created on the wrong node.
3067TEST_P(AbstractEventLoopDeathTest, NodeWatcher) {
3068 EnableNodes("them");
3069
3070 auto loop1 = Make();
3071 auto loop2 = Make();
3072 EXPECT_DEATH({ loop1->MakeWatcher("/test", [](const TestMessage &) {}); },
3073 "node");
3074 EXPECT_DEATH(
3075 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08003076 loop2->MakeRawWatcher(
3077 configuration::GetChannel(configuration(), "/test",
3078 "aos.TestMessage", "", nullptr),
3079 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08003080 },
3081 "node");
Brian Silverman454bc112020-03-05 14:21:25 -08003082 EXPECT_DEATH({ loop1->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
3083 "node");
3084 EXPECT_DEATH(
3085 {
3086 loop2->MakeRawNoArgWatcher(
3087 configuration::GetChannel(configuration(), "/test",
3088 "aos.TestMessage", "", nullptr),
3089 [](const Context &) {});
3090 },
3091 "node");
Austin Schuh217a9782019-12-21 23:02:50 -08003092}
3093
3094// Tests that fetchers fail when created on the wrong node.
3095TEST_P(AbstractEventLoopDeathTest, NodeFetcher) {
3096 EnableNodes("them");
3097 auto loop1 = Make();
3098
3099 EXPECT_DEATH({ auto fetcher = loop1->MakeFetcher<TestMessage>("/test"); },
3100 "node");
3101 EXPECT_DEATH(
3102 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08003103 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
3104 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08003105 },
3106 "node");
3107}
3108
3109// Tests that senders fail when created on the wrong node.
3110TEST_P(AbstractEventLoopDeathTest, NodeSender) {
3111 EnableNodes("them");
3112 auto loop1 = Make();
3113
3114 EXPECT_DEATH(
3115 {
3116 aos::Sender<TestMessage> sender =
3117 loop1->MakeSender<TestMessage>("/test");
3118 },
3119 "node");
3120
3121 // Note: Creating raw senders is always supported. Right now, this lets us
3122 // use them to create message_gateway.
3123}
3124
Brian Silverman341b57e2020-06-23 16:23:18 -07003125// Tests creating multiple Builders from a single Sender at the same time.
3126TEST_P(AbstractEventLoopDeathTest, MultipleBuilders) {
3127 auto loop1 = Make();
3128 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
3129
3130 { auto builder = sender.MakeBuilder(); }
3131 {
3132 auto builder = sender.MakeBuilder();
3133 builder.MakeBuilder<TestMessage>().Finish();
3134 }
3135 {
3136 // Creating this after the first one was destroyed should be fine.
3137 auto builder = sender.MakeBuilder();
3138 builder.MakeBuilder<TestMessage>().Finish();
3139 // But not a second one.
3140 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
3141 "May not overwrite in-use allocator");
3142 }
3143
3144 FlatbufferDetachedBuffer<TestMessage> detached =
3145 flatbuffers::DetachedBuffer();
3146 {
3147 auto builder = sender.MakeBuilder();
3148 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
3149 }
3150 {
3151 // This is the second one, after the detached one, so it should fail.
3152 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
3153 "May not overwrite in-use allocator");
3154 }
3155
3156 // Clear the detached one, and then we should be able to create another.
3157 detached = flatbuffers::DetachedBuffer();
3158 {
3159 auto builder = sender.MakeBuilder();
3160 builder.MakeBuilder<TestMessage>().Finish();
3161 }
3162
3163 // And then detach another one.
3164 {
3165 auto builder = sender.MakeBuilder();
3166 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
3167 }
3168}
3169
3170// Tests sending a buffer detached from a different builder.
3171TEST_P(AbstractEventLoopDeathTest, WrongDetachedBuffer) {
3172 auto loop1 = Make();
3173 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
3174 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
3175
3176 auto builder = sender1.MakeBuilder();
3177 FlatbufferDetachedBuffer<TestMessage> detached =
3178 builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
milind1f1dca32021-07-03 13:50:07 -07003179 EXPECT_DEATH(sender2.CheckOk(sender2.SendDetached(std::move(detached))),
Brian Silverman341b57e2020-06-23 16:23:18 -07003180 "May only send the buffer detached from this Sender");
3181}
3182
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003183int TestChannelFrequency(EventLoop *event_loop) {
3184 return event_loop->GetChannel<TestMessage>("/test")->frequency();
3185}
3186
3187int TestChannelQueueSize(EventLoop *event_loop) {
3188 const int frequency = TestChannelFrequency(event_loop);
3189 const auto channel_storage_duration = std::chrono::nanoseconds(
3190 event_loop->configuration()->channel_storage_duration());
3191 const int queue_size =
3192 frequency * std::chrono::duration_cast<std::chrono::duration<double>>(
3193 channel_storage_duration)
3194 .count();
3195
3196 return queue_size;
3197}
3198
3199RawSender::Error SendTestMessage(aos::Sender<TestMessage> &sender) {
3200 aos::Sender<TestMessage>::Builder builder = sender.MakeBuilder();
3201 TestMessage::Builder test_message_builder =
3202 builder.MakeBuilder<TestMessage>();
3203 test_message_builder.add_value(0);
3204 return builder.Send(test_message_builder.Finish());
3205}
3206
3207// Test that sending messages too fast returns
3208// RawSender::Error::kMessagesSentTooFast.
3209TEST_P(AbstractEventLoopTest, SendingMessagesTooFast) {
3210 auto event_loop = MakePrimary();
3211
3212 auto sender = event_loop->MakeSender<TestMessage>("/test");
3213
3214 // Send one message in the beginning, then wait until the
3215 // channel_storage_duration is almost done and start sending messages rapidly,
3216 // having some come in the next chanel_storage_duration. The queue_size is
3217 // 1600, so the 1601st message will be the last valid one (the initial message
3218 // having being sent more than a channel_storage_duration ago), and trying to
3219 // send the 1602nd message should return
3220 // RawSender::Error::kMessagesSentTooFast.
3221 EXPECT_EQ(SendTestMessage(sender), RawSender::Error::kOk);
3222 int msgs_sent = 1;
3223 const int queue_size = TestChannelQueueSize(event_loop.get());
3224
3225 const auto timer = event_loop->AddTimer([&]() {
3226 const bool done = (msgs_sent == queue_size + 1);
3227 ASSERT_EQ(
3228 SendTestMessage(sender),
3229 done ? RawSender::Error::kMessagesSentTooFast : RawSender::Error::kOk);
3230 msgs_sent++;
3231 if (done) {
3232 Exit();
3233 }
3234 });
3235
3236 const auto kRepeatOffset = std::chrono::milliseconds(1);
3237 const auto base_offset =
3238 std::chrono::nanoseconds(
3239 event_loop->configuration()->channel_storage_duration()) -
3240 (kRepeatOffset * (queue_size / 2));
3241 event_loop->OnRun([&event_loop, &timer, &base_offset, &kRepeatOffset]() {
3242 timer->Setup(event_loop->monotonic_now() + base_offset, kRepeatOffset);
3243 });
3244
3245 Run();
3246}
3247
3248// Tests that we are able to send messages successfully after sending messages
3249// too fast and waiting while continuously attempting to send messages.
3250// Also tests that SendFailureCounter is working correctly in this
3251// situation
3252TEST_P(AbstractEventLoopTest, SendingAfterSendingTooFast) {
3253 auto event_loop = MakePrimary();
3254
3255 auto sender = event_loop->MakeSender<TestMessage>("/test");
3256
Austin Schuh0e96d372023-05-08 10:10:21 -07003257 // We are sending bunches of messages at 100 Hz, so we will be sending too
3258 // fast after queue_size (800) ms. After this, keep sending messages, and
3259 // exactly a channel storage duration (2s) after we send the first message we
3260 // should be able to successfully send a message.
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003261
Austin Schuh0e96d372023-05-08 10:10:21 -07003262 const std::chrono::milliseconds kInterval = std::chrono::milliseconds(10);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003263 const monotonic_clock::duration channel_storage_duration =
3264 std::chrono::nanoseconds(
3265 event_loop->configuration()->channel_storage_duration());
3266 const int queue_size = TestChannelQueueSize(event_loop.get());
3267
3268 int msgs_sent = 0;
3269 SendFailureCounter counter;
3270 auto start = monotonic_clock::min_time;
3271
3272 event_loop->AddPhasedLoop(
Austin Schuh0e96d372023-05-08 10:10:21 -07003273 [&](int elapsed_cycles) {
3274 // The queue is setup for 800 messages/sec. We want to fill that up at
3275 // a rate of 2000 messages/sec so we make sure we fill it up.
3276 for (int i = 0; i < 2 * kInterval.count() * elapsed_cycles; ++i) {
3277 const auto actual_err = SendTestMessage(sender);
3278 const bool done_waiting = (start != monotonic_clock::min_time &&
3279 sender.monotonic_sent_time() >=
3280 (start + channel_storage_duration));
3281 const auto expected_err =
3282 (msgs_sent < queue_size || done_waiting
3283 ? RawSender::Error::kOk
3284 : RawSender::Error::kMessagesSentTooFast);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003285
Austin Schuh0e96d372023-05-08 10:10:21 -07003286 if (start == monotonic_clock::min_time) {
3287 start = sender.monotonic_sent_time();
3288 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003289
Austin Schuh0e96d372023-05-08 10:10:21 -07003290 ASSERT_EQ(actual_err, expected_err);
3291 counter.Count(actual_err);
3292 msgs_sent++;
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003293
Austin Schuh0e96d372023-05-08 10:10:21 -07003294 EXPECT_EQ(counter.failures(),
3295 msgs_sent <= queue_size
3296 ? 0
3297 : (msgs_sent - queue_size) -
3298 (actual_err == RawSender::Error::kOk ? 1 : 0));
3299 EXPECT_EQ(counter.just_failed(), actual_err != RawSender::Error::kOk);
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003300
Austin Schuh0e96d372023-05-08 10:10:21 -07003301 if (done_waiting) {
3302 Exit();
3303 return;
3304 }
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07003305 }
3306 },
3307 kInterval);
3308 Run();
3309}
3310
3311// Tests that RawSender::Error::kMessagesSentTooFast is returned
3312// when messages are sent too fast from senders in different loops
3313TEST_P(AbstractEventLoopTest, SendingTooFastWithMultipleLoops) {
3314 auto loop1 = MakePrimary();
3315 auto loop2 = Make();
3316
3317 auto sender1 = loop1->MakeSender<TestMessage>("/test");
3318 auto sender2 = loop2->MakeSender<TestMessage>("/test");
3319
3320 // Send queue_size messages split between the senders.
3321 const int queue_size = TestChannelQueueSize(loop1.get());
3322 for (int i = 0; i < queue_size / 2; i++) {
3323 ASSERT_EQ(SendTestMessage(sender1), RawSender::Error::kOk);
3324 ASSERT_EQ(SendTestMessage(sender2), RawSender::Error::kOk);
3325 }
3326
3327 // Since queue_size messages have been sent, this should return an error
3328 EXPECT_EQ(SendTestMessage(sender2), RawSender::Error::kMessagesSentTooFast);
3329}
3330
Parker Schuhe4a70d62017-12-27 20:10:20 -08003331} // namespace testing
3332} // namespace aos