blob: ee77b8a5413f1096cff25cb357bb0309a1afee43 [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
Austin Schuh54cf95f2019-11-29 13:14:18 -08007#include "aos/flatbuffer_merge.h"
Austin Schuhcc6070c2020-10-10 20:25:56 -07008#include "aos/realtime.h"
Austin Schuh54cf95f2019-11-29 13:14:18 -08009#include "glog/logging.h"
Tyler Chatow67ddb032020-01-12 14:30:04 -080010#include "gmock/gmock.h"
11#include "gtest/gtest.h"
Austin Schuh9fe68f72019-08-10 19:32:03 -070012
Parker Schuhe4a70d62017-12-27 20:10:20 -080013namespace aos {
14namespace testing {
Austin Schuh52d325c2019-06-23 18:59:06 -070015namespace {
16namespace chrono = ::std::chrono;
17} // namespace
Parker Schuhe4a70d62017-12-27 20:10:20 -080018
Brian Silverman4f4e0612020-08-12 19:54:41 -070019::std::unique_ptr<EventLoop> AbstractEventLoopTest::Make(
20 std::string_view name) {
21 std::string name_copy(name);
22 if (name == "") {
23 name_copy = "loop";
24 name_copy += std::to_string(event_loop_count_);
25 }
26 ++event_loop_count_;
Austin Schuh6bae8252021-02-07 22:01:49 -080027 auto result = factory_->Make(name_copy);
28 if (do_timing_reports() == DoTimingReports::kNo) {
29 result->SkipTimingReport();
30 }
31 return result;
Brian Silverman4f4e0612020-08-12 19:54:41 -070032}
33
34void AbstractEventLoopTest::VerifyBuffers(
35 int number_buffers,
36 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>> fetchers,
37 std::vector<std::reference_wrapper<const Sender<TestMessage>>> senders) {
38 // The buffers which are in a sender.
39 std::unordered_set<int> in_sender;
40 for (const Sender<TestMessage> &sender : senders) {
41 const int this_buffer = sender.buffer_index();
42 CHECK_GE(this_buffer, 0);
43 CHECK_LT(this_buffer, number_buffers);
44 CHECK(in_sender.insert(this_buffer).second) << ": " << this_buffer;
45 }
46
47 if (read_method() != ReadMethod::PIN) {
48 // If we're not using PIN, we can't really verify anything about what
49 // buffers the fetchers have.
50 return;
51 }
52
53 // Mapping from TestMessage::value to buffer index.
54 std::unordered_map<int, int> fetcher_values;
55 for (const Fetcher<TestMessage> &fetcher : fetchers) {
56 if (!fetcher.get()) {
57 continue;
58 }
59 const int this_buffer = fetcher.context().buffer_index;
60 CHECK_GE(this_buffer, 0);
61 CHECK_LT(this_buffer, number_buffers);
62 CHECK(in_sender.count(this_buffer) == 0) << ": " << this_buffer;
63 const auto insert_result = fetcher_values.insert(
64 std::make_pair(fetcher.get()->value(), this_buffer));
65 if (!insert_result.second) {
66 CHECK_EQ(this_buffer, insert_result.first->second);
67 }
68 }
69}
70
Austin Schuh6b6dfa52019-06-12 20:16:20 -070071// Tests that watcher can receive messages from a sender.
Parker Schuhe4a70d62017-12-27 20:10:20 -080072// Also tests that OnRun() works.
73TEST_P(AbstractEventLoopTest, Basic) {
74 auto loop1 = Make();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070075 auto loop2 = MakePrimary();
76
Alex Perrycb7da4b2019-08-28 19:35:56 -070077 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
Austin Schuh6b6dfa52019-06-12 20:16:20 -070078
79 bool happened = false;
80
81 loop2->OnRun([&]() {
82 happened = true;
83
Alex Perrycb7da4b2019-08-28 19:35:56 -070084 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
85 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
86 builder.add_value(200);
87 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -070088 });
89
90 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070091 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -070092 this->Exit();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070093 });
94
95 EXPECT_FALSE(happened);
96 Run();
97 EXPECT_TRUE(happened);
98}
99
Brian Silverman341b57e2020-06-23 16:23:18 -0700100// Tests that watcher can receive messages from a sender, sent via SendDetached.
101TEST_P(AbstractEventLoopTest, BasicSendDetached) {
102 auto loop1 = Make();
103 auto loop2 = MakePrimary();
104
105 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
106
107 FlatbufferDetachedBuffer<TestMessage> detached =
108 flatbuffers::DetachedBuffer();
109 {
110 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
111 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
112 builder.add_value(100);
113 detached = msg.Detach(builder.Finish());
114 }
115 detached = flatbuffers::DetachedBuffer();
116 {
117 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
118 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
119 builder.add_value(200);
120 detached = msg.Detach(builder.Finish());
121 }
122 ASSERT_TRUE(sender.SendDetached(std::move(detached)));
123
124 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
125 ASSERT_TRUE(fetcher.Fetch());
126 EXPECT_EQ(fetcher->value(), 200);
127}
128
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800129// Verifies that a no-arg watcher will not have a data pointer.
130TEST_P(AbstractEventLoopTest, NoArgNoData) {
131 auto loop1 = Make();
132 auto loop2 = MakePrimary();
133
134 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
135
136 bool happened = false;
137
138 loop2->OnRun([&]() {
139 happened = true;
140
141 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
142 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
143 ASSERT_TRUE(msg.Send(builder.Finish()));
144 });
145
146 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
147 EXPECT_GT(loop2->context().size, 0u);
148 EXPECT_EQ(nullptr, loop2->context().data);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700149 EXPECT_EQ(-1, loop2->context().buffer_index);
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800150 this->Exit();
151 });
152
153 EXPECT_FALSE(happened);
154 Run();
155 EXPECT_TRUE(happened);
156}
157
Brian Silverman454bc112020-03-05 14:21:25 -0800158// Tests that no-arg watcher can receive messages from a sender.
159// Also tests that OnRun() works.
160TEST_P(AbstractEventLoopTest, BasicNoArg) {
161 auto loop1 = Make();
162 auto loop2 = MakePrimary();
163
164 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
165
166 bool happened = false;
167
168 loop2->OnRun([&]() {
169 happened = true;
170
171 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
172 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
173 builder.add_value(200);
174 ASSERT_TRUE(msg.Send(builder.Finish()));
175 });
176
177 aos::Fetcher<TestMessage> fetcher = loop2->MakeFetcher<TestMessage>("/test");
178 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
179 ASSERT_TRUE(fetcher.Fetch());
180 EXPECT_EQ(fetcher->value(), 200);
181 this->Exit();
182 });
183
184 EXPECT_FALSE(happened);
185 Run();
186 EXPECT_TRUE(happened);
187}
188
189// Tests that a watcher can be created with an std::function.
190TEST_P(AbstractEventLoopTest, BasicFunction) {
191 auto loop1 = Make();
192 auto loop2 = MakePrimary();
193
194 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
195
196 bool happened = false;
197
198 loop2->OnRun([&]() {
199 happened = true;
200
201 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
202 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
203 builder.add_value(200);
204 ASSERT_TRUE(msg.Send(builder.Finish()));
205 });
206
207 loop2->MakeWatcher("/test", std::function<void(const TestMessage &)>(
208 [&](const TestMessage &message) {
209 EXPECT_EQ(message.value(), 200);
210 this->Exit();
211 }));
212
213 EXPECT_FALSE(happened);
214 Run();
215 EXPECT_TRUE(happened);
216}
217
Brian Silverman0fc69932020-01-24 21:54:02 -0800218// Tests that watcher can receive messages from two senders.
219// Also tests that OnRun() works.
220TEST_P(AbstractEventLoopTest, BasicTwoSenders) {
221 auto loop1 = Make();
222 auto loop2 = MakePrimary();
223
224 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
225 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
226
227 bool happened = false;
228
229 loop2->OnRun([&]() {
230 happened = true;
231
232 {
233 aos::Sender<TestMessage>::Builder msg = sender1.MakeBuilder();
234 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
235 builder.add_value(200);
236 ASSERT_TRUE(msg.Send(builder.Finish()));
237 }
238 {
239 aos::Sender<TestMessage>::Builder msg = sender2.MakeBuilder();
240 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
241 builder.add_value(200);
242 ASSERT_TRUE(msg.Send(builder.Finish()));
243 }
244 });
245
246 int messages_received = 0;
247 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
248 EXPECT_EQ(message.value(), 200);
249 this->Exit();
250 ++messages_received;
251 });
252
253 EXPECT_FALSE(happened);
254 Run();
255 EXPECT_TRUE(happened);
256 EXPECT_EQ(messages_received, 2);
257}
258
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700259// Tests that a fetcher can fetch from a sender.
260// Also tests that OnRun() works.
261TEST_P(AbstractEventLoopTest, FetchWithoutRun) {
262 auto loop1 = Make();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800263 auto loop2 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -0700264 auto loop3 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800265
266 auto sender = loop1->MakeSender<TestMessage>("/test");
267
268 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
269
Austin Schuhbbce72d2019-05-26 15:11:46 -0700270 EXPECT_FALSE(fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -0800271 EXPECT_EQ(fetcher.get(), nullptr);
272
Austin Schuhad154822019-12-27 15:45:13 -0800273 EXPECT_EQ(fetcher.context().monotonic_event_time, monotonic_clock::min_time);
274 EXPECT_EQ(fetcher.context().monotonic_remote_time, monotonic_clock::min_time);
275 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
276 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
Austin Schuh8902fa52021-03-14 22:39:24 -0700277 EXPECT_EQ(fetcher.context().remote_boot_uuid, UUID::Zero());
Austin Schuh39788ff2019-12-01 18:22:57 -0800278 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
279 EXPECT_EQ(fetcher.context().size, 0u);
280 EXPECT_EQ(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700281 EXPECT_EQ(fetcher.context().buffer_index, -1);
Austin Schuhbbce72d2019-05-26 15:11:46 -0700282
Alex Perrycb7da4b2019-08-28 19:35:56 -0700283 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
284 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
285 builder.add_value(200);
286 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700287
288 EXPECT_TRUE(fetcher.Fetch());
289 ASSERT_FALSE(fetcher.get() == nullptr);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700290 EXPECT_EQ(fetcher.get()->value(), 200);
Austin Schuh39788ff2019-12-01 18:22:57 -0800291
292 const chrono::milliseconds kEpsilon(100);
293
Austin Schuhad154822019-12-27 15:45:13 -0800294 const aos::monotonic_clock::time_point monotonic_now = loop2->monotonic_now();
295 const aos::realtime_clock::time_point realtime_now = loop2->realtime_now();
296 EXPECT_EQ(fetcher.context().monotonic_event_time,
297 fetcher.context().monotonic_remote_time);
298 EXPECT_EQ(fetcher.context().realtime_event_time,
299 fetcher.context().realtime_remote_time);
300
301 EXPECT_GE(fetcher.context().monotonic_event_time, monotonic_now - kEpsilon);
302 EXPECT_LE(fetcher.context().monotonic_event_time, monotonic_now + kEpsilon);
303 EXPECT_GE(fetcher.context().realtime_event_time, realtime_now - kEpsilon);
304 EXPECT_LE(fetcher.context().realtime_event_time, realtime_now + kEpsilon);
Austin Schuh8902fa52021-03-14 22:39:24 -0700305 EXPECT_EQ(fetcher.context().remote_boot_uuid, loop2->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -0800306 EXPECT_EQ(fetcher.context().queue_index, 0x0u);
307 EXPECT_EQ(fetcher.context().size, 20u);
308 EXPECT_NE(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700309 if (read_method() == ReadMethod::PIN) {
310 EXPECT_GE(fetcher.context().buffer_index, 0);
311 EXPECT_LT(fetcher.context().buffer_index,
312 loop2->NumberBuffers(fetcher.channel()));
313 } else {
314 EXPECT_EQ(fetcher.context().buffer_index, -1);
315 }
Parker Schuhe4a70d62017-12-27 20:10:20 -0800316}
317
Austin Schuh3578a2e2019-05-25 18:17:59 -0700318// Tests that watcher will receive all messages sent if they are sent after
319// initialization and before running.
320TEST_P(AbstractEventLoopTest, DoubleSendAtStartup) {
321 auto loop1 = Make();
322 auto loop2 = MakePrimary();
323
324 auto sender = loop1->MakeSender<TestMessage>("/test");
325
326 ::std::vector<int> values;
327
328 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700329 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700330 if (values.size() == 2) {
Austin Schuh9fe68f72019-08-10 19:32:03 -0700331 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -0700332 }
333 });
334
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700335 // Before Run, should be ignored.
Austin Schuh3578a2e2019-05-25 18:17:59 -0700336 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700337 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
338 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
339 builder.add_value(199);
340 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700341 }
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700342
343 loop2->OnRun([&]() {
344 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700345 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
346 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
347 builder.add_value(200);
348 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700349 }
350 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700351 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
352 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
353 builder.add_value(201);
354 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700355 }
356 });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700357
358 Run();
359
360 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
361}
362
363// Tests that watcher will not receive messages sent before the watcher is
364// created.
365TEST_P(AbstractEventLoopTest, DoubleSendAfterStartup) {
366 auto loop1 = Make();
367 auto loop2 = MakePrimary();
368
369 auto sender = loop1->MakeSender<TestMessage>("/test");
370
371 ::std::vector<int> values;
372
373 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700374 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
375 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
376 builder.add_value(200);
377 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700378 }
379 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700380 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
381 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
382 builder.add_value(201);
383 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700384 }
385
386 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700387 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700388 });
389
390 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700391 auto test_timer = loop2->AddTimer([this]() { this->Exit(); });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700392 loop2->OnRun([&test_timer, &loop2]() {
393 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
394 });
395
396 Run();
397 EXPECT_EQ(0, values.size());
398}
399
Austin Schuhbbce72d2019-05-26 15:11:46 -0700400// Tests that FetchNext gets all the messages sent after it is constructed.
401TEST_P(AbstractEventLoopTest, FetchNext) {
402 auto loop1 = Make();
403 auto loop2 = MakePrimary();
404
405 auto sender = loop1->MakeSender<TestMessage>("/test");
406 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
407
408 ::std::vector<int> values;
409
410 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700411 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
412 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
413 builder.add_value(200);
414 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700415 }
416 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700417 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
418 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
419 builder.add_value(201);
420 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700421 }
422
423 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700424 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700425 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700426 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700427 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700428 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700429 });
430
431 loop2->OnRun([&test_timer, &loop2]() {
432 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
433 });
434
435 Run();
436 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
437}
438
439// Tests that FetchNext gets no messages sent before it is constructed.
440TEST_P(AbstractEventLoopTest, FetchNextAfterSend) {
441 auto loop1 = Make();
442 auto loop2 = MakePrimary();
443
444 auto sender = loop1->MakeSender<TestMessage>("/test");
445
446 ::std::vector<int> values;
447
448 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700449 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
450 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
451 builder.add_value(200);
452 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700453 }
454 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700455 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
456 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
457 builder.add_value(201);
458 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700459 }
460
461 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
462
463 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700464 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700465 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700466 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700467 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700468 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700469 });
470
471 loop2->OnRun([&test_timer, &loop2]() {
472 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
473 });
474
475 Run();
476 EXPECT_THAT(0, values.size());
477}
478
479// Tests that Fetch returns the last message created before the loop was
480// started.
481TEST_P(AbstractEventLoopTest, FetchDataFromBeforeCreation) {
482 auto loop1 = Make();
483 auto loop2 = MakePrimary();
484
485 auto sender = loop1->MakeSender<TestMessage>("/test");
486
487 ::std::vector<int> values;
488
489 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700490 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
491 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
492 builder.add_value(200);
493 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700494 }
495 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700496 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
497 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
498 builder.add_value(201);
499 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700500 }
501
502 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
503
504 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700505 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700506 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700507 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700508 }
509 // Do it again to make sure we don't double fetch.
510 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700511 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700512 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700513 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700514 });
515
516 loop2->OnRun([&test_timer, &loop2]() {
517 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
518 });
519
520 Run();
521 EXPECT_THAT(values, ::testing::ElementsAreArray({201}));
522}
523
524// Tests that Fetch and FetchNext interleave as expected.
525TEST_P(AbstractEventLoopTest, FetchAndFetchNextTogether) {
526 auto loop1 = Make();
527 auto loop2 = MakePrimary();
528
529 auto sender = loop1->MakeSender<TestMessage>("/test");
530
531 ::std::vector<int> values;
532
533 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700534 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
535 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
536 builder.add_value(200);
537 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700538 }
539 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700540 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
541 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
542 builder.add_value(201);
543 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700544 }
545
546 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
547
548 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700549 auto test_timer = loop2->AddTimer([&fetcher, &values, &sender, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700550 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700551 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700552 }
553
554 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700555 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
556 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
557 builder.add_value(202);
558 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700559 }
560 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700561 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
562 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
563 builder.add_value(203);
564 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700565 }
566 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700567 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
568 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
569 builder.add_value(204);
570 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700571 }
572
573 if (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700574 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700575 }
576
577 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700578 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700579 }
580
Austin Schuh9fe68f72019-08-10 19:32:03 -0700581 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700582 });
583
584 loop2->OnRun([&test_timer, &loop2]() {
585 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
586 });
587
588 Run();
589 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
590}
591
Austin Schuh3115a202019-05-27 21:02:14 -0700592// Tests that FetchNext behaves correctly when we get two messages in the queue
593// but don't consume the first until after the second has been sent.
594TEST_P(AbstractEventLoopTest, FetchNextTest) {
Austin Schuh3115a202019-05-27 21:02:14 -0700595 auto send_loop = Make();
596 auto fetch_loop = Make();
597 auto sender = send_loop->MakeSender<TestMessage>("/test");
598 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
599
600 {
Tyler Chatow67ddb032020-01-12 14:30:04 -0800601 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
602 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
603 builder.add_value(100);
604 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700605 }
606
607 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700608 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
609 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
610 builder.add_value(200);
611 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700612 }
613
614 ASSERT_TRUE(fetcher.FetchNext());
615 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700616 EXPECT_EQ(100, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700617
618 ASSERT_TRUE(fetcher.FetchNext());
619 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700620 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700621
622 // When we run off the end of the queue, expect to still have the old message:
623 ASSERT_FALSE(fetcher.FetchNext());
624 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700625 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700626}
627
Brian Silverman77162972020-08-12 19:52:40 -0700628// Verify that a fetcher still holds its data, even after falling behind.
629TEST_P(AbstractEventLoopTest, FetcherBehindData) {
630 auto send_loop = Make();
631 auto fetch_loop = Make();
632 auto sender = send_loop->MakeSender<TestMessage>("/test");
633 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
634 {
635 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
636 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
637 builder.add_value(1);
638 ASSERT_TRUE(msg.Send(builder.Finish()));
639 }
640 ASSERT_TRUE(fetcher.Fetch());
641 EXPECT_EQ(1, fetcher.get()->value());
642 for (int i = 0; i < 300; ++i) {
643 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
644 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
645 builder.add_value(i + 2);
646 ASSERT_TRUE(msg.Send(builder.Finish()));
647 }
648 EXPECT_EQ(1, fetcher.get()->value());
649}
650
651// Try a bunch of orderings of operations with fetchers and senders. Verify that
652// all the fetchers have the correct data at each step.
653TEST_P(AbstractEventLoopTest, FetcherPermutations) {
654 for (int max_save = 0; max_save < 5; ++max_save) {
655 SCOPED_TRACE("max_save=" + std::to_string(max_save));
656
657 auto send_loop = Make();
658 auto fetch_loop = Make();
659 auto sender = send_loop->MakeSender<TestMessage>("/test");
660 const auto send_message = [&sender](int i) {
661 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
662 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
663 builder.add_value(i);
664 ASSERT_TRUE(msg.Send(builder.Finish()));
665 };
666 std::vector<Fetcher<TestMessage>> fetchers;
667 for (int i = 0; i < 10; ++i) {
668 fetchers.emplace_back(fetch_loop->MakeFetcher<TestMessage>("/test"));
669 }
670 send_message(1);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700671 const auto verify_buffers = [&]() {
672 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>>
673 fetchers_copy;
674 for (const auto &fetcher : fetchers) {
675 fetchers_copy.emplace_back(fetcher);
676 }
677 std::vector<std::reference_wrapper<const Sender<TestMessage>>>
678 senders_copy;
679 senders_copy.emplace_back(sender);
680 VerifyBuffers(send_loop->NumberBuffers(sender.channel()), fetchers_copy,
681 senders_copy);
682 };
Brian Silverman77162972020-08-12 19:52:40 -0700683 for (auto &fetcher : fetchers) {
684 ASSERT_TRUE(fetcher.Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -0700685 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700686 EXPECT_EQ(1, fetcher.get()->value());
687 }
688
689 for (int save = 1; save <= max_save; ++save) {
690 SCOPED_TRACE("save=" + std::to_string(save));
691 send_message(100 + save);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700692 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700693 for (size_t i = 0; i < fetchers.size() - save; ++i) {
694 SCOPED_TRACE("fetcher=" + std::to_string(i));
695 ASSERT_TRUE(fetchers[i].Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -0700696 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700697 EXPECT_EQ(100 + save, fetchers[i].get()->value());
698 }
699 for (size_t i = fetchers.size() - save; i < fetchers.size() - 1; ++i) {
700 SCOPED_TRACE("fetcher=" + std::to_string(i));
701 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
702 }
703 EXPECT_EQ(1, fetchers.back().get()->value());
704 }
705
706 for (int i = 0; i < 300; ++i) {
707 send_message(200 + i);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700708 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700709 }
710
711 for (size_t i = 0; i < fetchers.size() - max_save; ++i) {
712 SCOPED_TRACE("fetcher=" + std::to_string(i));
713 if (max_save > 0) {
714 EXPECT_EQ(100 + max_save, fetchers[i].get()->value());
715 } else {
716 EXPECT_EQ(1, fetchers[i].get()->value());
717 }
718 }
719 for (size_t i = fetchers.size() - max_save; i < fetchers.size() - 1; ++i) {
720 SCOPED_TRACE("fetcher=" + std::to_string(i));
721 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
722 }
723 EXPECT_EQ(1, fetchers.back().get()->value());
724 }
725}
726
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800727// Verify that making a fetcher and watcher for "/test" succeeds.
728TEST_P(AbstractEventLoopTest, FetcherAndWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800729 auto loop = Make();
730 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800731 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Parker Schuhe4a70d62017-12-27 20:10:20 -0800732}
733
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800734// Verify that making 2 fetchers for "/test" succeeds.
Parker Schuhe4a70d62017-12-27 20:10:20 -0800735TEST_P(AbstractEventLoopTest, TwoFetcher) {
736 auto loop = Make();
737 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800738 auto fetcher2 = loop->MakeFetcher<TestMessage>("/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -0800739}
740
Alex Perrycb7da4b2019-08-28 19:35:56 -0700741// Verify that registering a watcher for an invalid channel name dies.
742TEST_P(AbstractEventLoopDeathTest, InvalidChannelName) {
743 auto loop = Make();
744 EXPECT_DEATH(
745 { loop->MakeWatcher("/test/invalid", [&](const TestMessage &) {}); },
746 "/test/invalid");
Brian Silverman454bc112020-03-05 14:21:25 -0800747 EXPECT_DEATH(
748 { loop->MakeNoArgWatcher<TestMessage>("/test/invalid", [&]() {}); },
749 "/test/invalid");
Alex Perrycb7da4b2019-08-28 19:35:56 -0700750}
751
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800752// Verify that registering a watcher twice for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700753TEST_P(AbstractEventLoopDeathTest, TwoWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800754 auto loop = Make();
755 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800756 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
757 "/test");
Brian Silverman454bc112020-03-05 14:21:25 -0800758 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
759}
760
761// Verify that registering a no-arg watcher twice for "/test" fails.
762TEST_P(AbstractEventLoopDeathTest, TwoNoArgWatcher) {
763 auto loop = Make();
764 loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {});
765 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
766 "/test");
767 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800768}
769
Austin Schuh3115a202019-05-27 21:02:14 -0700770// Verify that SetRuntimeRealtimePriority fails while running.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700771TEST_P(AbstractEventLoopDeathTest, SetRuntimeRealtimePriority) {
Austin Schuh3115a202019-05-27 21:02:14 -0700772 auto loop = MakePrimary();
773 // Confirm that runtime priority calls work when not realtime.
774 loop->SetRuntimeRealtimePriority(5);
775
776 loop->OnRun([&]() { loop->SetRuntimeRealtimePriority(5); });
777
778 EXPECT_DEATH(Run(), "realtime");
779}
780
Brian Silverman6a54ff32020-04-28 16:41:39 -0700781// Verify that SetRuntimeAffinity fails while running.
782TEST_P(AbstractEventLoopDeathTest, SetRuntimeAffinity) {
783 auto loop = MakePrimary();
784 // Confirm that runtime priority calls work when not running.
785 loop->SetRuntimeAffinity(MakeCpusetFromCpus({0}));
786
787 loop->OnRun([&]() { loop->SetRuntimeAffinity(MakeCpusetFromCpus({1})); });
788
789 EXPECT_DEATH(Run(), "Cannot set affinity while running");
790}
791
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800792// Verify that registering a watcher and a sender for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700793TEST_P(AbstractEventLoopDeathTest, WatcherAndSender) {
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800794 auto loop = Make();
795 auto sender = loop->MakeSender<TestMessage>("/test");
796 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
797 "/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -0800798}
799
Austin Schuhe516ab02020-05-06 21:37:04 -0700800// Verify that creating too many senders fails.
801TEST_P(AbstractEventLoopDeathTest, TooManySenders) {
802 auto loop = Make();
803 std::vector<aos::Sender<TestMessage>> senders;
804 for (int i = 0; i < 10; ++i) {
805 senders.emplace_back(loop->MakeSender<TestMessage>("/test"));
806 }
807 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); },
808 "Failed to create sender on \\{ \"name\": \"/test\", \"type\": "
Brian Silverman77162972020-08-12 19:52:40 -0700809 "\"aos.TestMessage\"[^}]*\\ }, too many senders.");
810}
811
812// Verify that creating too many fetchers fails.
813TEST_P(AbstractEventLoopDeathTest, TooManyFetchers) {
814 if (read_method() != ReadMethod::PIN) {
815 // Other read methods don't limit the number of readers, so just skip this.
816 return;
817 }
818
819 auto loop = Make();
820 std::vector<aos::Fetcher<TestMessage>> fetchers;
821 for (int i = 0; i < 10; ++i) {
822 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
823 }
824 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
825 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
826 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
827}
828
829// Verify that creating too many fetchers, split between two event loops, fails.
830TEST_P(AbstractEventLoopDeathTest, TooManyFetchersTwoLoops) {
831 if (read_method() != ReadMethod::PIN) {
832 // Other read methods don't limit the number of readers, so just skip this.
833 return;
834 }
835
836 auto loop = Make();
837 auto loop2 = Make();
838 std::vector<aos::Fetcher<TestMessage>> fetchers;
839 for (int i = 0; i < 5; ++i) {
840 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
841 fetchers.emplace_back(loop2->MakeFetcher<TestMessage>("/test"));
842 }
843 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
844 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
845 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
846}
847
848// Verify that creating too many watchers fails.
849TEST_P(AbstractEventLoopDeathTest, TooManyWatchers) {
850 if (read_method() != ReadMethod::PIN) {
851 // Other read methods don't limit the number of readers, so just skip this.
852 return;
853 }
854
855 std::vector<std::unique_ptr<EventLoop>> loops;
856 for (int i = 0; i < 10; ++i) {
857 loops.emplace_back(Make());
858 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
859 }
860 EXPECT_DEATH({ Make()->MakeWatcher("/test", [](const TestMessage &) {}); },
861 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
862 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
863}
864
865// Verify that creating too many watchers and fetchers combined fails.
866TEST_P(AbstractEventLoopDeathTest, TooManyWatchersAndFetchers) {
867 if (read_method() != ReadMethod::PIN) {
868 // Other read methods don't limit the number of readers, so just skip this.
869 return;
870 }
871
872 auto loop = Make();
873 std::vector<aos::Fetcher<TestMessage>> fetchers;
874 std::vector<std::unique_ptr<EventLoop>> loops;
875 for (int i = 0; i < 5; ++i) {
876 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
877 loops.emplace_back(Make());
878 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
879 }
880 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
881 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
882 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
Austin Schuhe516ab02020-05-06 21:37:04 -0700883}
884
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700885// Verify that we can't create a sender inside OnRun.
886TEST_P(AbstractEventLoopDeathTest, SenderInOnRun) {
887 auto loop1 = MakePrimary();
888
889 loop1->OnRun(
890 [&]() { auto sender = loop1->MakeSender<TestMessage>("/test2"); });
891
892 EXPECT_DEATH(Run(), "running");
893}
894
895// Verify that we can't create a watcher inside OnRun.
896TEST_P(AbstractEventLoopDeathTest, WatcherInOnRun) {
897 auto loop1 = MakePrimary();
898
899 loop1->OnRun(
900 [&]() { loop1->MakeWatcher("/test", [&](const TestMessage &) {}); });
901
902 EXPECT_DEATH(Run(), "running");
903}
904
Brian Silverman454bc112020-03-05 14:21:25 -0800905// Verify that we can't create a no-arg watcher inside OnRun.
906TEST_P(AbstractEventLoopDeathTest, NoArgWatcherInOnRun) {
907 auto loop1 = MakePrimary();
908
909 loop1->OnRun(
910 [&]() { loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {}); });
911
912 EXPECT_DEATH(Run(), "running");
913}
914
Parker Schuhe4a70d62017-12-27 20:10:20 -0800915// Verify that Quit() works when there are multiple watchers.
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800916TEST_P(AbstractEventLoopTest, MultipleWatcherQuit) {
917 auto loop1 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -0700918 auto loop2 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800919
Austin Schuh3578a2e2019-05-25 18:17:59 -0700920 loop2->MakeWatcher("/test1", [&](const TestMessage &) {});
921 loop2->MakeWatcher("/test2", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700922 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -0700923 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -0700924 });
925
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800926 auto sender = loop1->MakeSender<TestMessage>("/test2");
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700927
928 loop2->OnRun([&]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700929 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
930 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
931 builder.add_value(200);
932 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700933 });
Parker Schuhe4a70d62017-12-27 20:10:20 -0800934
Austin Schuh44019f92019-05-19 19:58:27 -0700935 Run();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800936}
937
Neil Balch229001a2018-01-07 18:22:52 -0800938// Verify that timer intervals and duration function properly.
939TEST_P(AbstractEventLoopTest, TimerIntervalAndDuration) {
Austin Schuh39788ff2019-12-01 18:22:57 -0800940 // Force a slower rate so we are guarenteed to have reports for our timer.
941 FLAGS_timing_report_ms = 2000;
942
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800943 const int kCount = 5;
Neil Balch229001a2018-01-07 18:22:52 -0800944
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800945 auto loop = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -0800946 auto loop2 = Make();
947
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800948 ::std::vector<::aos::monotonic_clock::time_point> times;
949 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
950
Austin Schuh39788ff2019-12-01 18:22:57 -0800951 Fetcher<timing::Report> report_fetcher =
952 loop2->MakeFetcher<timing::Report>("/aos");
953 EXPECT_FALSE(report_fetcher.Fetch());
954
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800955 auto test_timer = loop->AddTimer([this, &times, &expected_times, &loop]() {
956 times.push_back(loop->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -0800957 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
958 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
959 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
Austin Schuh8902fa52021-03-14 22:39:24 -0700960 EXPECT_EQ(loop->context().remote_boot_uuid, loop->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -0800961 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
962 EXPECT_EQ(loop->context().size, 0u);
963 EXPECT_EQ(loop->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700964 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -0800965
Austin Schuhad154822019-12-27 15:45:13 -0800966 expected_times.push_back(loop->context().monotonic_event_time);
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800967 if (times.size() == kCount) {
968 this->Exit();
969 }
Neil Balch229001a2018-01-07 18:22:52 -0800970 });
Austin Schuh39788ff2019-12-01 18:22:57 -0800971 test_timer->set_name("Test loop");
Neil Balch229001a2018-01-07 18:22:52 -0800972
Austin Schuh39788ff2019-12-01 18:22:57 -0800973 const monotonic_clock::time_point start_time = loop->monotonic_now();
Austin Schuh52d325c2019-06-23 18:59:06 -0700974 // TODO(austin): This should be an error... Should be done in OnRun only.
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800975 test_timer->Setup(start_time + chrono::seconds(1), chrono::seconds(1));
976
Austin Schuh44019f92019-05-19 19:58:27 -0700977 Run();
Neil Balch229001a2018-01-07 18:22:52 -0800978
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800979 // Confirm that we got both the right number of samples, and it's odd.
980 EXPECT_EQ(times.size(), static_cast<size_t>(kCount));
981 EXPECT_EQ(times.size(), expected_times.size());
982 EXPECT_EQ((times.size() % 2), 1);
983
984 // Grab the middle sample.
985 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
986
987 // Add up all the delays of all the times.
988 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
989 for (const ::aos::monotonic_clock::time_point time : times) {
990 sum += time - average_time;
991 }
992
993 // Average and add to the middle to find the average time.
994 sum /= times.size();
995 average_time += sum;
996
997 // Compute the offset from the average and the expected average. It
998 // should be pretty close to 0.
999 const ::aos::monotonic_clock::duration remainder =
1000 average_time - start_time - chrono::seconds(times.size() / 2 + 1);
1001
1002 const chrono::milliseconds kEpsilon(100);
1003 EXPECT_LT(remainder, +kEpsilon);
1004 EXPECT_GT(remainder, -kEpsilon);
1005
1006 // Make sure that the average duration is close to 1 second.
1007 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1008 times.front())
1009 .count() /
1010 static_cast<double>(times.size() - 1),
1011 1.0, 0.1);
1012
1013 // Confirm that the ideal wakeup times increment correctly.
1014 for (size_t i = 1; i < expected_times.size(); ++i) {
1015 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1016 }
1017
1018 for (size_t i = 0; i < expected_times.size(); ++i) {
1019 EXPECT_EQ((expected_times[i] - start_time) % chrono::seconds(1),
1020 chrono::seconds(0));
1021 }
1022
1023 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1024 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001025
Austin Schuh6bae8252021-02-07 22:01:49 -08001026 if (do_timing_reports() == DoTimingReports::kYes) {
1027 // And, since we are here, check that the timing report makes sense.
1028 // Start by looking for our event loop's timing.
1029 FlatbufferDetachedBuffer<timing::Report> report =
1030 FlatbufferDetachedBuffer<timing::Report>::Empty();
1031 while (report_fetcher.FetchNext()) {
1032 if (report_fetcher->name()->string_view() == "primary") {
1033 report = CopyFlatBuffer(report_fetcher.get());
1034 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001035 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001036
1037 // Confirm that we have the right number of reports, and the contents are
1038 // sane.
1039 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
1040
1041 EXPECT_EQ(report.message().name()->string_view(), "primary");
1042
1043 ASSERT_NE(report.message().senders(), nullptr);
1044 EXPECT_EQ(report.message().senders()->size(), 2);
1045
1046 ASSERT_NE(report.message().timers(), nullptr);
1047 EXPECT_EQ(report.message().timers()->size(), 2);
1048
1049 EXPECT_EQ(report.message().timers()->Get(0)->name()->string_view(),
1050 "Test loop");
1051 EXPECT_GE(report.message().timers()->Get(0)->count(), 1);
1052
1053 EXPECT_EQ(report.message().timers()->Get(1)->name()->string_view(),
1054 "timing_reports");
1055 EXPECT_EQ(report.message().timers()->Get(1)->count(), 1);
1056
1057 // Make sure there is a single phased loop report with our report in it.
1058 ASSERT_EQ(report.message().phased_loops(), nullptr);
1059 } else {
1060 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001061 }
Neil Balch229001a2018-01-07 18:22:52 -08001062}
1063
1064// Verify that we can change a timer's parameters during execution.
1065TEST_P(AbstractEventLoopTest, TimerChangeParameters) {
Austin Schuh44019f92019-05-19 19:58:27 -07001066 auto loop = MakePrimary();
Austin Schuh7f20f512021-01-31 17:56:16 -08001067 std::vector<monotonic_clock::time_point> iteration_list;
Neil Balch229001a2018-01-07 18:22:52 -08001068
1069 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh7f20f512021-01-31 17:56:16 -08001070 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001071 });
1072
Austin Schuh7f20f512021-01-31 17:56:16 -08001073 monotonic_clock::time_point s;
1074 auto modifier_timer = loop->AddTimer([&test_timer, &s]() {
1075 test_timer->Setup(s + chrono::milliseconds(45), chrono::milliseconds(30));
Neil Balch229001a2018-01-07 18:22:52 -08001076 });
1077
Austin Schuh7f20f512021-01-31 17:56:16 -08001078 s = loop->monotonic_now();
1079 test_timer->Setup(s, chrono::milliseconds(20));
1080 modifier_timer->Setup(s + chrono::milliseconds(45));
1081 EndEventLoop(loop.get(), chrono::milliseconds(150));
Austin Schuh44019f92019-05-19 19:58:27 -07001082 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001083
1084 EXPECT_EQ(iteration_list.size(), 7);
Austin Schuh7f20f512021-01-31 17:56:16 -08001085 EXPECT_EQ(iteration_list[0], s);
1086 EXPECT_EQ(iteration_list[1], s + chrono::milliseconds(20));
1087 EXPECT_EQ(iteration_list[2], s + chrono::milliseconds(40));
1088 EXPECT_EQ(iteration_list[3], s + chrono::milliseconds(45));
1089 EXPECT_EQ(iteration_list[4], s + chrono::milliseconds(75));
1090 EXPECT_EQ(iteration_list[5], s + chrono::milliseconds(105));
1091 EXPECT_EQ(iteration_list[6], s + chrono::milliseconds(135));
Neil Balch229001a2018-01-07 18:22:52 -08001092}
1093
1094// Verify that we can disable a timer during execution.
1095TEST_P(AbstractEventLoopTest, TimerDisable) {
Austin Schuh44019f92019-05-19 19:58:27 -07001096 auto loop = MakePrimary();
Neil Balch229001a2018-01-07 18:22:52 -08001097 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
1098
1099 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
1100 iteration_list.push_back(loop->monotonic_now());
1101 });
1102
Tyler Chatow67ddb032020-01-12 14:30:04 -08001103 auto ender_timer = loop->AddTimer([&test_timer]() { test_timer->Disable(); });
Neil Balch229001a2018-01-07 18:22:52 -08001104
1105 test_timer->Setup(loop->monotonic_now(), ::std::chrono::milliseconds(20));
Tyler Chatow67ddb032020-01-12 14:30:04 -08001106 ender_timer->Setup(loop->monotonic_now() + ::std::chrono::milliseconds(45));
Neil Balch229001a2018-01-07 18:22:52 -08001107 EndEventLoop(loop.get(), ::std::chrono::milliseconds(150));
Austin Schuh44019f92019-05-19 19:58:27 -07001108 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001109
1110 EXPECT_EQ(iteration_list.size(), 3);
1111}
Austin Schuh7267c532019-05-19 19:55:53 -07001112
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001113// Verify that a timer can disable itself.
1114//
1115// TODO(Brian): Do something similar with phased loops, both with a quick
1116// handler and a handler that would miss a cycle except it got deferred. Current
1117// behavior doing that is a mess.
1118TEST_P(AbstractEventLoopTest, TimerDisableSelf) {
1119 auto loop = MakePrimary();
1120
1121 int count = 0;
1122 aos::TimerHandler *test_timer;
1123 test_timer = loop->AddTimer([&count, &test_timer]() {
1124 ++count;
1125 test_timer->Disable();
1126 });
1127
1128 test_timer->Setup(loop->monotonic_now(), ::std::chrono::milliseconds(20));
1129 EndEventLoop(loop.get(), ::std::chrono::milliseconds(80));
1130 Run();
1131
1132 EXPECT_EQ(count, 1);
1133}
1134
Brian Silvermanbd405c02020-06-23 16:25:23 -07001135// Verify that we can disable a timer during execution of another timer
1136// scheduled for the same time, with one ordering of creation for the timers.
1137//
1138// Also schedule some more events to reshuffle the heap in EventLoop used for
1139// tracking events to change up the order. This used to segfault
1140// SimulatedEventLoop.
1141TEST_P(AbstractEventLoopTest, TimerDisableOther) {
1142 for (bool creation_order : {true, false}) {
1143 for (bool setup_order : {true, false}) {
1144 for (int shuffle_events = 0; shuffle_events < 5; ++shuffle_events) {
1145 auto loop = MakePrimary();
1146 aos::TimerHandler *test_timer, *ender_timer;
1147 if (creation_order) {
1148 test_timer = loop->AddTimer([]() {});
1149 ender_timer =
1150 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1151 } else {
1152 ender_timer =
1153 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1154 test_timer = loop->AddTimer([]() {});
1155 }
1156
1157 const auto start = loop->monotonic_now();
1158
1159 for (int i = 0; i < shuffle_events; ++i) {
1160 loop->AddTimer([]() {})->Setup(start + std::chrono::milliseconds(10));
1161 }
1162
1163 if (setup_order) {
1164 test_timer->Setup(start + ::std::chrono::milliseconds(20));
1165 ender_timer->Setup(start + ::std::chrono::milliseconds(20));
1166 } else {
1167 ender_timer->Setup(start + ::std::chrono::milliseconds(20));
1168 test_timer->Setup(start + ::std::chrono::milliseconds(20));
1169 }
1170 EndEventLoop(loop.get(), ::std::chrono::milliseconds(40));
1171 Run();
1172 }
1173 }
1174 }
1175}
1176
Austin Schuh54cf95f2019-11-29 13:14:18 -08001177// Verifies that the event loop implementations detect when Channel is not a
1178// pointer into confguration()
1179TEST_P(AbstractEventLoopDeathTest, InvalidChannel) {
1180 auto loop = MakePrimary();
1181
Tyler Chatow67ddb032020-01-12 14:30:04 -08001182 const Channel *channel = configuration::GetChannel(
1183 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
Austin Schuh54cf95f2019-11-29 13:14:18 -08001184
1185 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1186
1187 EXPECT_DEATH(
1188 { loop->MakeRawSender(&channel_copy.message()); },
1189 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1190
1191 EXPECT_DEATH(
1192 { loop->MakeRawFetcher(&channel_copy.message()); },
1193 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1194
1195 EXPECT_DEATH(
1196 {
1197 loop->MakeRawWatcher(&channel_copy.message(),
1198 [](const Context, const void *) {});
1199 },
1200 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1201}
1202
Austin Schuhd54780b2020-10-03 16:26:02 -07001203// Verifies that the event loop implementations detect when Channel has an
1204// invalid alignment.
1205TEST_P(AbstractEventLoopDeathTest, InvalidChannelAlignment) {
1206 const char *const kError = "multiple of alignment";
1207 InvalidChannelAlignment();
1208
1209 auto loop = MakePrimary();
1210
1211 const Channel *channel = configuration::GetChannel(
1212 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
1213
1214 EXPECT_DEATH({ loop->MakeRawSender(channel); }, kError);
1215 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); }, kError);
1216
1217 EXPECT_DEATH({ loop->MakeRawFetcher(channel); }, kError);
1218 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); }, kError);
1219
1220 EXPECT_DEATH(
1221 { loop->MakeRawWatcher(channel, [](const Context &, const void *) {}); },
1222 kError);
1223 EXPECT_DEATH({ loop->MakeRawNoArgWatcher(channel, [](const Context &) {}); },
1224 kError);
1225
1226 EXPECT_DEATH({ loop->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
1227 kError);
1228 EXPECT_DEATH({ loop->MakeWatcher("/test", [](const TestMessage &) {}); },
1229 kError);
1230}
1231
Brian Silverman454bc112020-03-05 14:21:25 -08001232// Verify that the send time on a message is roughly right when using a watcher.
Austin Schuh7267c532019-05-19 19:55:53 -07001233TEST_P(AbstractEventLoopTest, MessageSendTime) {
Austin Schuh44019f92019-05-19 19:58:27 -07001234 auto loop1 = MakePrimary();
Austin Schuh7267c532019-05-19 19:55:53 -07001235 auto loop2 = Make();
Austin Schuhad154822019-12-27 15:45:13 -08001236 auto sender = loop2->MakeSender<TestMessage>("/test");
Austin Schuh7267c532019-05-19 19:55:53 -07001237 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
1238
1239 auto test_timer = loop1->AddTimer([&sender]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001240 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1241 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1242 builder.add_value(200);
1243 ASSERT_TRUE(msg.Send(builder.Finish()));
1244 });
1245
Austin Schuhad154822019-12-27 15:45:13 -08001246 bool triggered = false;
Brian Silverman454bc112020-03-05 14:21:25 -08001247 loop1->MakeWatcher("/test", [&](const TestMessage &msg) {
Austin Schuhad154822019-12-27 15:45:13 -08001248 // Confirm that the data pointer makes sense from a watcher, and all the
1249 // timestamps look right.
1250 EXPECT_GT(&msg, loop1->context().data);
1251 EXPECT_EQ(loop1->context().monotonic_remote_time,
1252 loop1->context().monotonic_event_time);
1253 EXPECT_EQ(loop1->context().realtime_remote_time,
1254 loop1->context().realtime_event_time);
Austin Schuh8902fa52021-03-14 22:39:24 -07001255 EXPECT_EQ(loop1->context().remote_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001256
1257 const aos::monotonic_clock::time_point monotonic_now =
1258 loop1->monotonic_now();
Tyler Chatow67ddb032020-01-12 14:30:04 -08001259 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08001260
1261 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1262 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1263 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1264 monotonic_now);
1265 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1266 realtime_now);
1267
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001268 EXPECT_LT(&msg, reinterpret_cast<const void *>(
1269 reinterpret_cast<const char *>(loop1->context().data) +
Austin Schuhad154822019-12-27 15:45:13 -08001270 loop1->context().size));
Brian Silverman4f4e0612020-08-12 19:54:41 -07001271 if (read_method() == ReadMethod::PIN) {
1272 EXPECT_GE(loop1->context().buffer_index, 0);
1273 EXPECT_LT(loop1->context().buffer_index,
1274 loop1->NumberBuffers(
1275 configuration::GetChannel(loop1->configuration(), "/test",
1276 "aos.TestMessage", "", nullptr)));
1277 } else {
1278 EXPECT_EQ(-1, loop1->context().buffer_index);
1279 }
Austin Schuhad154822019-12-27 15:45:13 -08001280 triggered = true;
Austin Schuh7267c532019-05-19 19:55:53 -07001281 });
1282
1283 test_timer->Setup(loop1->monotonic_now() + ::std::chrono::seconds(1));
1284
1285 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
Austin Schuh44019f92019-05-19 19:58:27 -07001286 Run();
Austin Schuh7267c532019-05-19 19:55:53 -07001287
Austin Schuhad154822019-12-27 15:45:13 -08001288 EXPECT_TRUE(triggered);
1289
Brian Silverman454bc112020-03-05 14:21:25 -08001290 ASSERT_TRUE(fetcher.Fetch());
1291
1292 monotonic_clock::duration monotonic_time_offset =
1293 fetcher.context().monotonic_event_time -
1294 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1295 realtime_clock::duration realtime_time_offset =
1296 fetcher.context().realtime_event_time -
1297 (loop1->realtime_now() - ::std::chrono::seconds(1));
1298
1299 EXPECT_EQ(fetcher.context().realtime_event_time,
1300 fetcher.context().realtime_remote_time);
1301 EXPECT_EQ(fetcher.context().monotonic_event_time,
1302 fetcher.context().monotonic_remote_time);
Austin Schuh8902fa52021-03-14 22:39:24 -07001303 EXPECT_EQ(fetcher.context().remote_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001304
1305 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1306 << ": Got "
1307 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1308 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1309 // Confirm that the data pointer makes sense.
1310 EXPECT_GT(fetcher.get(), fetcher.context().data);
1311 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001312 reinterpret_cast<const void *>(
1313 reinterpret_cast<const char *>(fetcher.context().data) +
Brian Silverman454bc112020-03-05 14:21:25 -08001314 fetcher.context().size));
1315 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1316 << ": Got "
1317 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1318 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1319
1320 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1321 << ": Got "
1322 << fetcher.context().realtime_event_time.time_since_epoch().count()
1323 << " expected " << loop1->realtime_now().time_since_epoch().count();
1324 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1325 << ": Got "
1326 << fetcher.context().realtime_event_time.time_since_epoch().count()
1327 << " expected " << loop1->realtime_now().time_since_epoch().count();
1328}
1329
1330// Verify that the send time on a message is roughly right when using a no-arg
1331// watcher. To get a message, we need to use a fetcher to actually access the
1332// message. This is also the main use case for no-arg fetchers.
1333TEST_P(AbstractEventLoopTest, MessageSendTimeNoArg) {
1334 auto loop1 = MakePrimary();
1335 auto loop2 = Make();
1336 auto sender = loop2->MakeSender<TestMessage>("/test");
1337 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
1338
1339 auto test_timer = loop1->AddTimer([&sender]() {
1340 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1341 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1342 builder.add_value(200);
1343 ASSERT_TRUE(msg.Send(builder.Finish()));
1344 });
1345
1346 bool triggered = false;
1347 loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {
1348 // Confirm that we can indeed use a fetcher on this channel from this
1349 // context, and it results in a sane data pointer and timestamps.
1350 ASSERT_TRUE(fetcher.Fetch());
1351
1352 EXPECT_EQ(loop1->context().monotonic_remote_time,
1353 loop1->context().monotonic_event_time);
1354 EXPECT_EQ(loop1->context().realtime_remote_time,
1355 loop1->context().realtime_event_time);
Austin Schuh8902fa52021-03-14 22:39:24 -07001356 EXPECT_EQ(loop1->context().remote_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001357
1358 const aos::monotonic_clock::time_point monotonic_now =
1359 loop1->monotonic_now();
1360 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
1361
1362 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1363 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1364 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1365 monotonic_now);
1366 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1367 realtime_now);
1368
1369 triggered = true;
1370 });
1371
1372 test_timer->Setup(loop1->monotonic_now() + ::std::chrono::seconds(1));
1373
1374 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
1375 Run();
1376
1377 ASSERT_TRUE(triggered);
Austin Schuh7267c532019-05-19 19:55:53 -07001378
Alex Perrycb7da4b2019-08-28 19:35:56 -07001379 monotonic_clock::duration monotonic_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001380 fetcher.context().monotonic_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001381 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1382 realtime_clock::duration realtime_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001383 fetcher.context().realtime_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001384 (loop1->realtime_now() - ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07001385
Austin Schuhad154822019-12-27 15:45:13 -08001386 EXPECT_EQ(fetcher.context().realtime_event_time,
1387 fetcher.context().realtime_remote_time);
1388 EXPECT_EQ(fetcher.context().monotonic_event_time,
1389 fetcher.context().monotonic_remote_time);
Austin Schuh8902fa52021-03-14 22:39:24 -07001390 EXPECT_EQ(fetcher.context().remote_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001391
Alex Perrycb7da4b2019-08-28 19:35:56 -07001392 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1393 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001394 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh52d325c2019-06-23 18:59:06 -07001395 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07001396 // Confirm that the data pointer makes sense.
1397 EXPECT_GT(fetcher.get(), fetcher.context().data);
1398 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001399 reinterpret_cast<const void *>(
1400 reinterpret_cast<const char *>(fetcher.context().data) +
Alex Perrycb7da4b2019-08-28 19:35:56 -07001401 fetcher.context().size));
1402 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1403 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001404 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh7267c532019-05-19 19:55:53 -07001405 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07001406
1407 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1408 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001409 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07001410 << " expected " << loop1->realtime_now().time_since_epoch().count();
1411 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1412 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001413 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07001414 << " expected " << loop1->realtime_now().time_since_epoch().count();
Austin Schuh7267c532019-05-19 19:55:53 -07001415}
1416
Austin Schuh52d325c2019-06-23 18:59:06 -07001417// Tests that a couple phased loops run in a row result in the correct offset
1418// and period.
1419TEST_P(AbstractEventLoopTest, PhasedLoopTest) {
Austin Schuh39788ff2019-12-01 18:22:57 -08001420 // Force a slower rate so we are guarenteed to have reports for our phased
1421 // loop.
1422 FLAGS_timing_report_ms = 2000;
1423
Austin Schuh52d325c2019-06-23 18:59:06 -07001424 const chrono::milliseconds kOffset = chrono::milliseconds(400);
1425 const int kCount = 5;
1426
1427 auto loop1 = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001428 auto loop2 = Make();
1429
1430 Fetcher<timing::Report> report_fetcher =
1431 loop2->MakeFetcher<timing::Report>("/aos");
1432 EXPECT_FALSE(report_fetcher.Fetch());
Austin Schuh52d325c2019-06-23 18:59:06 -07001433
1434 // Collect up a couple of samples.
1435 ::std::vector<::aos::monotonic_clock::time_point> times;
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001436 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
Austin Schuh52d325c2019-06-23 18:59:06 -07001437
1438 // Run kCount iterations.
Austin Schuh39788ff2019-12-01 18:22:57 -08001439 loop1
1440 ->AddPhasedLoop(
1441 [&times, &expected_times, &loop1, this](int count) {
1442 EXPECT_EQ(count, 1);
1443 times.push_back(loop1->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001444 expected_times.push_back(loop1->context().monotonic_event_time);
Austin Schuh39788ff2019-12-01 18:22:57 -08001445
Austin Schuhad154822019-12-27 15:45:13 -08001446 EXPECT_EQ(loop1->context().monotonic_remote_time,
1447 monotonic_clock::min_time);
Austin Schuh8902fa52021-03-14 22:39:24 -07001448 EXPECT_EQ(loop1->context().remote_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001449 EXPECT_EQ(loop1->context().realtime_event_time,
1450 realtime_clock::min_time);
1451 EXPECT_EQ(loop1->context().realtime_remote_time,
Austin Schuh39788ff2019-12-01 18:22:57 -08001452 realtime_clock::min_time);
1453 EXPECT_EQ(loop1->context().queue_index, 0xffffffffu);
1454 EXPECT_EQ(loop1->context().size, 0u);
1455 EXPECT_EQ(loop1->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001456 EXPECT_EQ(loop1->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001457
1458 if (times.size() == kCount) {
1459 LOG(INFO) << "Exiting";
1460 this->Exit();
1461 }
1462 },
1463 chrono::seconds(1), kOffset)
1464 ->set_name("Test loop");
Austin Schuh52d325c2019-06-23 18:59:06 -07001465
1466 // Add a delay to make sure that delay during startup doesn't result in a
1467 // "missed cycle".
1468 SleepFor(chrono::seconds(2));
1469
1470 Run();
1471
1472 // Confirm that we got both the right number of samples, and it's odd.
1473 EXPECT_EQ(times.size(), static_cast<size_t>(kCount));
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001474 EXPECT_EQ(times.size(), expected_times.size());
Austin Schuh52d325c2019-06-23 18:59:06 -07001475 EXPECT_EQ((times.size() % 2), 1);
1476
1477 // Grab the middle sample.
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001478 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
Austin Schuh52d325c2019-06-23 18:59:06 -07001479
1480 // Add up all the delays of all the times.
1481 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1482 for (const ::aos::monotonic_clock::time_point time : times) {
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001483 sum += time - average_time;
Austin Schuh52d325c2019-06-23 18:59:06 -07001484 }
1485
1486 // Average and add to the middle to find the average time.
1487 sum /= times.size();
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001488 average_time += sum;
Austin Schuh52d325c2019-06-23 18:59:06 -07001489
1490 // Compute the offset from the start of the second of the average time. This
1491 // should be pretty close to the offset.
1492 const ::aos::monotonic_clock::duration remainder =
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001493 average_time.time_since_epoch() -
1494 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
Austin Schuh52d325c2019-06-23 18:59:06 -07001495
1496 const chrono::milliseconds kEpsilon(100);
1497 EXPECT_LT(remainder, kOffset + kEpsilon);
1498 EXPECT_GT(remainder, kOffset - kEpsilon);
1499
1500 // Make sure that the average duration is close to 1 second.
1501 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1502 times.front())
1503 .count() /
1504 static_cast<double>(times.size() - 1),
1505 1.0, 0.1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001506
1507 // Confirm that the ideal wakeup times increment correctly.
1508 for (size_t i = 1; i < expected_times.size(); ++i) {
1509 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1510 }
1511
1512 for (size_t i = 0; i < expected_times.size(); ++i) {
1513 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
1514 kOffset);
1515 }
1516
1517 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1518 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001519
Austin Schuh6bae8252021-02-07 22:01:49 -08001520 if (do_timing_reports() == DoTimingReports::kYes) {
1521 // And, since we are here, check that the timing report makes sense.
1522 // Start by looking for our event loop's timing.
1523 FlatbufferDetachedBuffer<timing::Report> report =
1524 FlatbufferDetachedBuffer<timing::Report>::Empty();
1525 while (report_fetcher.FetchNext()) {
1526 if (report_fetcher->name()->string_view() == "primary") {
1527 report = CopyFlatBuffer(report_fetcher.get());
1528 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001529 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001530
1531 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
1532
1533 EXPECT_EQ(report.message().name()->string_view(), "primary");
1534
1535 ASSERT_NE(report.message().senders(), nullptr);
1536 EXPECT_EQ(report.message().senders()->size(), 2);
1537
1538 ASSERT_NE(report.message().timers(), nullptr);
1539 EXPECT_EQ(report.message().timers()->size(), 1);
1540
1541 // Make sure there is a single phased loop report with our report in it.
1542 ASSERT_NE(report.message().phased_loops(), nullptr);
1543 ASSERT_EQ(report.message().phased_loops()->size(), 1);
1544 EXPECT_EQ(report.message().phased_loops()->Get(0)->name()->string_view(),
1545 "Test loop");
1546 EXPECT_GE(report.message().phased_loops()->Get(0)->count(), 1);
1547 } else {
1548 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001549 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001550}
1551
1552// Tests that senders count correctly in the timing report.
1553TEST_P(AbstractEventLoopTest, SenderTimingReport) {
1554 FLAGS_timing_report_ms = 1000;
1555 auto loop1 = MakePrimary();
1556
1557 auto loop2 = Make("watcher_loop");
1558 loop2->MakeWatcher("/test", [](const TestMessage &) {});
1559
1560 auto loop3 = Make();
1561
1562 Fetcher<timing::Report> report_fetcher =
1563 loop3->MakeFetcher<timing::Report>("/aos");
1564 EXPECT_FALSE(report_fetcher.Fetch());
1565
1566 auto sender = loop1->MakeSender<TestMessage>("/test");
1567
1568 // Add a timer to actually quit.
1569 auto test_timer = loop1->AddTimer([&sender]() {
1570 for (int i = 0; i < 10; ++i) {
1571 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1572 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1573 builder.add_value(200 + i);
1574 ASSERT_TRUE(msg.Send(builder.Finish()));
1575 }
1576 });
1577
1578 // Quit after 1 timing report, mid way through the next cycle.
1579 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
1580
1581 loop1->OnRun([&test_timer, &loop1]() {
1582 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1500));
1583 });
1584
1585 Run();
1586
Austin Schuh6bae8252021-02-07 22:01:49 -08001587 if (do_timing_reports() == DoTimingReports::kYes) {
1588 // And, since we are here, check that the timing report makes sense.
1589 // Start by looking for our event loop's timing.
1590 FlatbufferDetachedBuffer<timing::Report> primary_report =
1591 FlatbufferDetachedBuffer<timing::Report>::Empty();
1592 while (report_fetcher.FetchNext()) {
Austin Schuh8902fa52021-03-14 22:39:24 -07001593 VLOG(1) << "Report " << FlatbufferToJson(report_fetcher.get());
Austin Schuh6bae8252021-02-07 22:01:49 -08001594 if (report_fetcher->name()->string_view() == "primary") {
1595 primary_report = CopyFlatBuffer(report_fetcher.get());
1596 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001597 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001598
Austin Schuh8902fa52021-03-14 22:39:24 -07001599 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
Austin Schuh6bae8252021-02-07 22:01:49 -08001600
1601 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
1602
1603 ASSERT_NE(primary_report.message().senders(), nullptr);
1604 EXPECT_EQ(primary_report.message().senders()->size(), 3);
1605
1606 // Confirm that the sender looks sane.
1607 EXPECT_EQ(
1608 loop1->configuration()
1609 ->channels()
1610 ->Get(primary_report.message().senders()->Get(0)->channel_index())
1611 ->name()
1612 ->string_view(),
1613 "/test");
1614 EXPECT_EQ(primary_report.message().senders()->Get(0)->count(), 10);
1615
1616 // Confirm that the timing primary_report sender looks sane.
1617 EXPECT_EQ(
1618 loop1->configuration()
1619 ->channels()
1620 ->Get(primary_report.message().senders()->Get(1)->channel_index())
1621 ->name()
1622 ->string_view(),
1623 "/aos");
1624 EXPECT_EQ(primary_report.message().senders()->Get(1)->count(), 1);
1625
1626 ASSERT_NE(primary_report.message().timers(), nullptr);
1627 EXPECT_EQ(primary_report.message().timers()->size(), 3);
1628
1629 // Make sure there are no phased loops or watchers.
1630 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
1631 ASSERT_EQ(primary_report.message().watchers(), nullptr);
1632 } else {
1633 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001634 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001635}
1636
1637// Tests that senders count correctly in the timing report.
1638TEST_P(AbstractEventLoopTest, WatcherTimingReport) {
1639 FLAGS_timing_report_ms = 1000;
1640 auto loop1 = MakePrimary();
1641 loop1->MakeWatcher("/test", [](const TestMessage &) {});
1642
1643 auto loop2 = Make("sender_loop");
1644
1645 auto loop3 = Make();
1646
1647 Fetcher<timing::Report> report_fetcher =
1648 loop3->MakeFetcher<timing::Report>("/aos");
1649 EXPECT_FALSE(report_fetcher.Fetch());
1650
1651 auto sender = loop2->MakeSender<TestMessage>("/test");
1652
1653 // Add a timer to actually quit.
1654 auto test_timer = loop1->AddTimer([&sender]() {
1655 for (int i = 0; i < 10; ++i) {
1656 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1657 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1658 builder.add_value(200 + i);
1659 ASSERT_TRUE(msg.Send(builder.Finish()));
1660 }
1661 });
1662
1663 // Quit after 1 timing report, mid way through the next cycle.
1664 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
1665
1666 loop1->OnRun([&test_timer, &loop1]() {
1667 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1500));
1668 });
1669
1670 Run();
1671
Austin Schuh6bae8252021-02-07 22:01:49 -08001672 if (do_timing_reports() == DoTimingReports::kYes) {
1673 // And, since we are here, check that the timing report makes sense.
1674 // Start by looking for our event loop's timing.
1675 FlatbufferDetachedBuffer<timing::Report> primary_report =
1676 FlatbufferDetachedBuffer<timing::Report>::Empty();
1677 while (report_fetcher.FetchNext()) {
1678 LOG(INFO) << "Report " << FlatbufferToJson(report_fetcher.get());
1679 if (report_fetcher->name()->string_view() == "primary") {
1680 primary_report = CopyFlatBuffer(report_fetcher.get());
1681 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001682 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001683
1684 // Check the watcher report.
1685 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
1686
1687 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
1688
1689 // Just the timing report timer.
1690 ASSERT_NE(primary_report.message().timers(), nullptr);
1691 EXPECT_EQ(primary_report.message().timers()->size(), 3);
1692
1693 // No phased loops
1694 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
1695
1696 ASSERT_NE(primary_report.message().watchers(), nullptr);
1697 ASSERT_EQ(primary_report.message().watchers()->size(), 1);
1698 EXPECT_EQ(primary_report.message().watchers()->Get(0)->count(), 10);
1699 } else {
1700 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001701 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001702}
1703
1704// Tests that fetchers count correctly in the timing report.
1705TEST_P(AbstractEventLoopTest, FetcherTimingReport) {
1706 FLAGS_timing_report_ms = 1000;
1707 auto loop1 = MakePrimary();
1708 auto loop2 = Make("sender_loop");
1709
1710 auto loop3 = Make();
1711
1712 Fetcher<timing::Report> report_fetcher =
1713 loop3->MakeFetcher<timing::Report>("/aos");
1714 EXPECT_FALSE(report_fetcher.Fetch());
1715
1716 auto sender = loop2->MakeSender<TestMessage>("/test");
1717 auto fetcher1 = loop1->MakeFetcher<TestMessage>("/test");
1718 auto fetcher2 = loop1->MakeFetcher<TestMessage>("/test");
1719 fetcher1.Fetch();
1720 fetcher2.Fetch();
1721
1722 // Add a timer to actually quit.
1723 auto test_timer = loop1->AddTimer([&sender]() {
1724 for (int i = 0; i < 10; ++i) {
1725 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1726 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1727 builder.add_value(200 + i);
1728 ASSERT_TRUE(msg.Send(builder.Finish()));
1729 }
1730 });
1731
1732 auto test_timer2 = loop1->AddTimer([&fetcher1, &fetcher2]() {
1733 fetcher1.Fetch();
1734 while (fetcher2.FetchNext()) {
1735 }
1736 });
1737
1738 // Quit after 1 timing report, mid way through the next cycle.
1739 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
1740
1741 loop1->OnRun([test_timer, test_timer2, &loop1]() {
1742 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1400));
1743 test_timer2->Setup(loop1->monotonic_now() + chrono::milliseconds(1600));
1744 });
1745
1746 Run();
1747
Austin Schuh6bae8252021-02-07 22:01:49 -08001748 if (do_timing_reports() == DoTimingReports::kYes) {
1749 // And, since we are here, check that the timing report makes sense.
1750 // Start by looking for our event loop's timing.
1751 FlatbufferDetachedBuffer<timing::Report> primary_report =
1752 FlatbufferDetachedBuffer<timing::Report>::Empty();
1753 while (report_fetcher.FetchNext()) {
1754 if (report_fetcher->name()->string_view() == "primary") {
1755 primary_report = CopyFlatBuffer(report_fetcher.get());
1756 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001757 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001758
1759 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
1760
1761 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
1762
1763 ASSERT_NE(primary_report.message().senders(), nullptr);
1764 EXPECT_EQ(primary_report.message().senders()->size(), 2);
1765
1766 ASSERT_NE(primary_report.message().timers(), nullptr);
1767 EXPECT_EQ(primary_report.message().timers()->size(), 4);
1768
1769 // Make sure there are no phased loops or watchers.
1770 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
1771 ASSERT_EQ(primary_report.message().watchers(), nullptr);
1772
1773 // Now look at the fetchrs.
1774 ASSERT_NE(primary_report.message().fetchers(), nullptr);
1775 ASSERT_EQ(primary_report.message().fetchers()->size(), 2);
1776
1777 EXPECT_EQ(primary_report.message().fetchers()->Get(0)->count(), 1);
1778 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->average(),
1779 0.1);
1780 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->min(),
1781 0.1);
1782 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->max(),
1783 0.1);
1784 EXPECT_EQ(primary_report.message()
1785 .fetchers()
1786 ->Get(0)
1787 ->latency()
1788 ->standard_deviation(),
1789 0.0);
1790
1791 EXPECT_EQ(primary_report.message().fetchers()->Get(1)->count(), 10);
1792 } else {
1793 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001794 }
Austin Schuh52d325c2019-06-23 18:59:06 -07001795}
1796
Austin Schuh67420a42019-12-21 21:55:04 -08001797// Tests that a raw watcher and raw fetcher can receive messages from a raw
1798// sender without messing up offsets.
1799TEST_P(AbstractEventLoopTest, RawBasic) {
1800 auto loop1 = Make();
1801 auto loop2 = MakePrimary();
1802 auto loop3 = Make();
1803
1804 const std::string kData("971 is the best");
1805
1806 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08001807 loop1->MakeRawSender(configuration::GetChannel(
1808 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08001809
1810 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08001811 loop3->MakeRawFetcher(configuration::GetChannel(
1812 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08001813
1814 loop2->OnRun(
1815 [&]() { EXPECT_TRUE(sender->Send(kData.data(), kData.size())); });
1816
1817 bool happened = false;
1818 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08001819 configuration::GetChannel(loop2->configuration(), "/test",
1820 "aos.TestMessage", "", nullptr),
Austin Schuh67420a42019-12-21 21:55:04 -08001821 [this, &kData, &fetcher, &happened](const Context &context,
1822 const void *message) {
1823 happened = true;
1824 EXPECT_EQ(std::string_view(kData),
1825 std::string_view(reinterpret_cast<const char *>(message),
1826 context.size));
1827 EXPECT_EQ(std::string_view(kData),
1828 std::string_view(reinterpret_cast<const char *>(context.data),
1829 context.size));
1830
1831 ASSERT_TRUE(fetcher->Fetch());
1832
1833 EXPECT_EQ(std::string_view(kData),
1834 std::string_view(
1835 reinterpret_cast<const char *>(fetcher->context().data),
1836 fetcher->context().size));
1837
1838 this->Exit();
1839 });
1840
1841 EXPECT_FALSE(happened);
1842 Run();
1843 EXPECT_TRUE(happened);
1844}
1845
Austin Schuhad154822019-12-27 15:45:13 -08001846// Tests that a raw watcher and raw fetcher can receive messages from a raw
1847// sender with remote times filled out.
1848TEST_P(AbstractEventLoopTest, RawRemoteTimes) {
1849 auto loop1 = Make();
1850 auto loop2 = MakePrimary();
1851 auto loop3 = Make();
1852
1853 const std::string kData("971 is the best");
1854
1855 const aos::monotonic_clock::time_point monotonic_remote_time =
1856 aos::monotonic_clock::time_point(chrono::seconds(1501));
1857 const aos::realtime_clock::time_point realtime_remote_time =
1858 aos::realtime_clock::time_point(chrono::seconds(3132));
Austin Schuhb5c6f972021-03-14 21:53:07 -07001859 const uint32_t remote_queue_index = 0x254971;
Austin Schuh8902fa52021-03-14 22:39:24 -07001860 const UUID remote_boot_uuid = UUID::Random();
Austin Schuhad154822019-12-27 15:45:13 -08001861
1862 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08001863 loop1->MakeRawSender(configuration::GetChannel(
1864 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08001865
1866 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08001867 loop3->MakeRawFetcher(configuration::GetChannel(
1868 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08001869
1870 loop2->OnRun([&]() {
1871 EXPECT_TRUE(sender->Send(kData.data(), kData.size(), monotonic_remote_time,
Austin Schuh8902fa52021-03-14 22:39:24 -07001872 realtime_remote_time, remote_queue_index,
1873 remote_boot_uuid));
Austin Schuhad154822019-12-27 15:45:13 -08001874 });
1875
1876 bool happened = false;
1877 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08001878 configuration::GetChannel(loop2->configuration(), "/test",
1879 "aos.TestMessage", "", nullptr),
Austin Schuh8902fa52021-03-14 22:39:24 -07001880 [this, monotonic_remote_time, realtime_remote_time, remote_boot_uuid,
Austin Schuhb5c6f972021-03-14 21:53:07 -07001881 remote_queue_index, &fetcher,
1882 &happened](const Context &context, const void * /*message*/) {
Austin Schuhad154822019-12-27 15:45:13 -08001883 happened = true;
1884 EXPECT_EQ(monotonic_remote_time, context.monotonic_remote_time);
1885 EXPECT_EQ(realtime_remote_time, context.realtime_remote_time);
Austin Schuh8902fa52021-03-14 22:39:24 -07001886 EXPECT_EQ(remote_boot_uuid, context.remote_boot_uuid);
Austin Schuhb5c6f972021-03-14 21:53:07 -07001887 EXPECT_EQ(remote_queue_index, context.remote_queue_index);
Austin Schuhad154822019-12-27 15:45:13 -08001888
1889 ASSERT_TRUE(fetcher->Fetch());
1890 EXPECT_EQ(monotonic_remote_time,
1891 fetcher->context().monotonic_remote_time);
1892 EXPECT_EQ(realtime_remote_time,
1893 fetcher->context().realtime_remote_time);
1894
1895 this->Exit();
1896 });
1897
1898 EXPECT_FALSE(happened);
1899 Run();
1900 EXPECT_TRUE(happened);
1901}
1902
1903// Tests that a raw sender fills out sent data.
1904TEST_P(AbstractEventLoopTest, RawSenderSentData) {
1905 auto loop1 = MakePrimary();
1906
1907 const std::string kData("971 is the best");
1908
1909 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08001910 loop1->MakeRawSender(configuration::GetChannel(
1911 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08001912
Tyler Chatow67ddb032020-01-12 14:30:04 -08001913 const aos::monotonic_clock::time_point monotonic_now = loop1->monotonic_now();
1914 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08001915
1916 EXPECT_TRUE(sender->Send(kData.data(), kData.size()));
1917
1918 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
1919 EXPECT_LE(sender->monotonic_sent_time(),
1920 monotonic_now + chrono::milliseconds(100));
1921 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
1922 EXPECT_LE(sender->realtime_sent_time(),
1923 realtime_now + chrono::milliseconds(100));
1924 EXPECT_EQ(sender->sent_queue_index(), 0u);
1925
1926 EXPECT_TRUE(sender->Send(kData.data(), kData.size()));
1927
1928 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
1929 EXPECT_LE(sender->monotonic_sent_time(),
1930 monotonic_now + chrono::milliseconds(100));
1931 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
1932 EXPECT_LE(sender->realtime_sent_time(),
1933 realtime_now + chrono::milliseconds(100));
1934 EXPECT_EQ(sender->sent_queue_index(), 1u);
1935}
1936
Austin Schuh217a9782019-12-21 23:02:50 -08001937// Tests that not setting up nodes results in no node.
1938TEST_P(AbstractEventLoopTest, NoNode) {
1939 auto loop1 = Make();
1940 auto loop2 = MakePrimary();
1941
1942 EXPECT_EQ(loop1->node(), nullptr);
1943 EXPECT_EQ(loop2->node(), nullptr);
1944}
1945
1946// Tests that setting up nodes results in node being set.
1947TEST_P(AbstractEventLoopTest, Node) {
1948 EnableNodes("me");
1949
1950 auto loop1 = Make();
1951 auto loop2 = MakePrimary();
1952
1953 EXPECT_NE(loop1->node(), nullptr);
1954 EXPECT_NE(loop2->node(), nullptr);
1955}
1956
1957// Tests that watchers work with a node setup.
1958TEST_P(AbstractEventLoopTest, NodeWatcher) {
1959 EnableNodes("me");
1960
1961 auto loop1 = Make();
1962 auto loop2 = Make();
1963 loop1->MakeWatcher("/test", [](const TestMessage &) {});
Tyler Chatow67ddb032020-01-12 14:30:04 -08001964 loop2->MakeRawWatcher(
1965 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
1966 nullptr),
1967 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08001968}
1969
Brian Silverman454bc112020-03-05 14:21:25 -08001970// Tests that no-arg watchers work with a node setup.
1971TEST_P(AbstractEventLoopTest, NodeNoArgWatcher) {
1972 EnableNodes("me");
1973
1974 auto loop1 = Make();
1975 auto loop2 = Make();
1976 loop1->MakeWatcher("/test", [](const TestMessage &) {});
1977 loop2->MakeRawNoArgWatcher(
1978 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
1979 nullptr),
1980 [](const Context &) {});
1981}
1982
Austin Schuh217a9782019-12-21 23:02:50 -08001983// Tests that fetcher work with a node setup.
1984TEST_P(AbstractEventLoopTest, NodeFetcher) {
1985 EnableNodes("me");
1986 auto loop1 = Make();
1987
1988 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
Tyler Chatow67ddb032020-01-12 14:30:04 -08001989 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
1990 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08001991}
1992
1993// Tests that sender work with a node setup.
1994TEST_P(AbstractEventLoopTest, NodeSender) {
1995 EnableNodes("me");
1996 auto loop1 = Make();
1997
1998 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
1999}
2000
Austin Schuhcc6070c2020-10-10 20:25:56 -07002001// Tests that a non-realtime event loop timer is marked non-realtime.
2002TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopTimer) {
2003 auto loop1 = MakePrimary();
2004
2005 // Add a timer to actually quit.
2006 auto test_timer = loop1->AddTimer([this]() {
2007 CheckNotRealtime();
2008 this->Exit();
2009 });
2010
2011 loop1->OnRun([&test_timer, &loop1]() {
2012 CheckNotRealtime();
2013 test_timer->Setup(loop1->monotonic_now(), ::std::chrono::milliseconds(100));
2014 });
2015
2016 Run();
2017}
2018
2019// Tests that a realtime event loop timer is marked realtime.
2020TEST_P(AbstractEventLoopTest, RealtimeEventLoopTimer) {
2021 auto loop1 = MakePrimary();
2022
2023 loop1->SetRuntimeRealtimePriority(1);
2024
2025 // Add a timer to actually quit.
2026 auto test_timer = loop1->AddTimer([this]() {
2027 CheckRealtime();
2028 this->Exit();
2029 });
2030
2031 loop1->OnRun([&test_timer, &loop1]() {
2032 CheckRealtime();
2033 test_timer->Setup(loop1->monotonic_now(), ::std::chrono::milliseconds(100));
2034 });
2035
2036 Run();
2037}
2038
2039// Tests that a non-realtime event loop phased loop is marked non-realtime.
2040TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopPhasedLoop) {
2041 auto loop1 = MakePrimary();
2042
2043 // Add a timer to actually quit.
2044 loop1->AddPhasedLoop(
2045 [this](int) {
2046 CheckNotRealtime();
2047 this->Exit();
2048 },
2049 chrono::seconds(1), chrono::seconds(0));
2050
2051 Run();
2052}
2053
2054// Tests that a realtime event loop phased loop is marked realtime.
2055TEST_P(AbstractEventLoopTest, RealtimeEventLoopPhasedLoop) {
2056 auto loop1 = MakePrimary();
2057
2058 loop1->SetRuntimeRealtimePriority(1);
2059
2060 // Add a timer to actually quit.
2061 loop1->AddPhasedLoop(
2062 [this](int) {
2063 CheckRealtime();
2064 this->Exit();
2065 },
2066 chrono::seconds(1), chrono::seconds(0));
2067
2068 Run();
2069}
2070
2071// Tests that a non-realtime event loop watcher is marked non-realtime.
2072TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopWatcher) {
2073 auto loop1 = MakePrimary();
2074 auto loop2 = Make();
2075
2076 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
2077
2078 loop1->OnRun([&]() {
2079 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2080 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2081 ASSERT_TRUE(msg.Send(builder.Finish()));
2082 });
2083
2084 loop1->MakeWatcher("/test", [&](const TestMessage &) {
2085 CheckNotRealtime();
2086 this->Exit();
2087 });
2088
2089 Run();
2090}
2091
2092// Tests that a realtime event loop watcher is marked realtime.
2093TEST_P(AbstractEventLoopTest, RealtimeEventLoopWatcher) {
2094 auto loop1 = MakePrimary();
2095 auto loop2 = Make();
2096
2097 loop1->SetRuntimeRealtimePriority(1);
2098
2099 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
2100
2101 loop1->OnRun([&]() {
2102 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2103 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2104 ASSERT_TRUE(msg.Send(builder.Finish()));
2105 });
2106
2107 loop1->MakeWatcher("/test", [&](const TestMessage &) {
2108 CheckRealtime();
2109 this->Exit();
2110 });
2111
2112 Run();
2113}
2114
Austin Schuh217a9782019-12-21 23:02:50 -08002115// Tests that watchers fail when created on the wrong node.
2116TEST_P(AbstractEventLoopDeathTest, NodeWatcher) {
2117 EnableNodes("them");
2118
2119 auto loop1 = Make();
2120 auto loop2 = Make();
2121 EXPECT_DEATH({ loop1->MakeWatcher("/test", [](const TestMessage &) {}); },
2122 "node");
2123 EXPECT_DEATH(
2124 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08002125 loop2->MakeRawWatcher(
2126 configuration::GetChannel(configuration(), "/test",
2127 "aos.TestMessage", "", nullptr),
2128 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08002129 },
2130 "node");
Brian Silverman454bc112020-03-05 14:21:25 -08002131 EXPECT_DEATH({ loop1->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
2132 "node");
2133 EXPECT_DEATH(
2134 {
2135 loop2->MakeRawNoArgWatcher(
2136 configuration::GetChannel(configuration(), "/test",
2137 "aos.TestMessage", "", nullptr),
2138 [](const Context &) {});
2139 },
2140 "node");
Austin Schuh217a9782019-12-21 23:02:50 -08002141}
2142
2143// Tests that fetchers fail when created on the wrong node.
2144TEST_P(AbstractEventLoopDeathTest, NodeFetcher) {
2145 EnableNodes("them");
2146 auto loop1 = Make();
2147
2148 EXPECT_DEATH({ auto fetcher = loop1->MakeFetcher<TestMessage>("/test"); },
2149 "node");
2150 EXPECT_DEATH(
2151 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08002152 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
2153 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08002154 },
2155 "node");
2156}
2157
2158// Tests that senders fail when created on the wrong node.
2159TEST_P(AbstractEventLoopDeathTest, NodeSender) {
2160 EnableNodes("them");
2161 auto loop1 = Make();
2162
2163 EXPECT_DEATH(
2164 {
2165 aos::Sender<TestMessage> sender =
2166 loop1->MakeSender<TestMessage>("/test");
2167 },
2168 "node");
2169
2170 // Note: Creating raw senders is always supported. Right now, this lets us
2171 // use them to create message_gateway.
2172}
2173
Brian Silverman341b57e2020-06-23 16:23:18 -07002174// Tests creating multiple Builders from a single Sender at the same time.
2175TEST_P(AbstractEventLoopDeathTest, MultipleBuilders) {
2176 auto loop1 = Make();
2177 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
2178
2179 { auto builder = sender.MakeBuilder(); }
2180 {
2181 auto builder = sender.MakeBuilder();
2182 builder.MakeBuilder<TestMessage>().Finish();
2183 }
2184 {
2185 // Creating this after the first one was destroyed should be fine.
2186 auto builder = sender.MakeBuilder();
2187 builder.MakeBuilder<TestMessage>().Finish();
2188 // But not a second one.
2189 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
2190 "May not overwrite in-use allocator");
2191 }
2192
2193 FlatbufferDetachedBuffer<TestMessage> detached =
2194 flatbuffers::DetachedBuffer();
2195 {
2196 auto builder = sender.MakeBuilder();
2197 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
2198 }
2199 {
2200 // This is the second one, after the detached one, so it should fail.
2201 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
2202 "May not overwrite in-use allocator");
2203 }
2204
2205 // Clear the detached one, and then we should be able to create another.
2206 detached = flatbuffers::DetachedBuffer();
2207 {
2208 auto builder = sender.MakeBuilder();
2209 builder.MakeBuilder<TestMessage>().Finish();
2210 }
2211
2212 // And then detach another one.
2213 {
2214 auto builder = sender.MakeBuilder();
2215 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
2216 }
2217}
2218
2219// Tests sending a buffer detached from a different builder.
2220TEST_P(AbstractEventLoopDeathTest, WrongDetachedBuffer) {
2221 auto loop1 = Make();
2222 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
2223 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
2224
2225 auto builder = sender1.MakeBuilder();
2226 FlatbufferDetachedBuffer<TestMessage> detached =
2227 builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
2228 EXPECT_DEATH(sender2.SendDetached(std::move(detached)),
2229 "May only send the buffer detached from this Sender");
2230}
2231
Parker Schuhe4a70d62017-12-27 20:10:20 -08002232} // namespace testing
2233} // namespace aos