blob: 378c4112359850fab2c9c608f8c63af5b6947e5d [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>
4
Alex Perrycb7da4b2019-08-28 19:35:56 -07005#include "aos/events/test_message_generated.h"
Austin Schuh54cf95f2019-11-29 13:14:18 -08006#include "aos/flatbuffer_merge.h"
7#include "glog/logging.h"
Tyler Chatow67ddb032020-01-12 14:30:04 -08008#include "gmock/gmock.h"
9#include "gtest/gtest.h"
Austin Schuh9fe68f72019-08-10 19:32:03 -070010
Parker Schuhe4a70d62017-12-27 20:10:20 -080011namespace aos {
12namespace testing {
Austin Schuh52d325c2019-06-23 18:59:06 -070013namespace {
14namespace chrono = ::std::chrono;
15} // namespace
Parker Schuhe4a70d62017-12-27 20:10:20 -080016
Austin Schuh6b6dfa52019-06-12 20:16:20 -070017// Tests that watcher can receive messages from a sender.
Parker Schuhe4a70d62017-12-27 20:10:20 -080018// Also tests that OnRun() works.
19TEST_P(AbstractEventLoopTest, Basic) {
20 auto loop1 = Make();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070021 auto loop2 = MakePrimary();
22
Alex Perrycb7da4b2019-08-28 19:35:56 -070023 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
Austin Schuh6b6dfa52019-06-12 20:16:20 -070024
25 bool happened = false;
26
27 loop2->OnRun([&]() {
28 happened = true;
29
Alex Perrycb7da4b2019-08-28 19:35:56 -070030 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
31 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
32 builder.add_value(200);
33 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -070034 });
35
36 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070037 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -070038 this->Exit();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070039 });
40
41 EXPECT_FALSE(happened);
42 Run();
43 EXPECT_TRUE(happened);
44}
45
Brian Silverman341b57e2020-06-23 16:23:18 -070046// Tests that watcher can receive messages from a sender, sent via SendDetached.
47TEST_P(AbstractEventLoopTest, BasicSendDetached) {
48 auto loop1 = Make();
49 auto loop2 = MakePrimary();
50
51 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
52
53 FlatbufferDetachedBuffer<TestMessage> detached =
54 flatbuffers::DetachedBuffer();
55 {
56 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
57 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
58 builder.add_value(100);
59 detached = msg.Detach(builder.Finish());
60 }
61 detached = flatbuffers::DetachedBuffer();
62 {
63 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
64 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
65 builder.add_value(200);
66 detached = msg.Detach(builder.Finish());
67 }
68 ASSERT_TRUE(sender.SendDetached(std::move(detached)));
69
70 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
71 ASSERT_TRUE(fetcher.Fetch());
72 EXPECT_EQ(fetcher->value(), 200);
73}
74
Brian Silverman6b8a3c32020-03-06 11:26:14 -080075// Verifies that a no-arg watcher will not have a data pointer.
76TEST_P(AbstractEventLoopTest, NoArgNoData) {
77 auto loop1 = Make();
78 auto loop2 = MakePrimary();
79
80 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
81
82 bool happened = false;
83
84 loop2->OnRun([&]() {
85 happened = true;
86
87 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
88 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
89 ASSERT_TRUE(msg.Send(builder.Finish()));
90 });
91
92 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
93 EXPECT_GT(loop2->context().size, 0u);
94 EXPECT_EQ(nullptr, loop2->context().data);
95 this->Exit();
96 });
97
98 EXPECT_FALSE(happened);
99 Run();
100 EXPECT_TRUE(happened);
101}
102
Brian Silverman454bc112020-03-05 14:21:25 -0800103// Tests that no-arg watcher can receive messages from a sender.
104// Also tests that OnRun() works.
105TEST_P(AbstractEventLoopTest, BasicNoArg) {
106 auto loop1 = Make();
107 auto loop2 = MakePrimary();
108
109 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
110
111 bool happened = false;
112
113 loop2->OnRun([&]() {
114 happened = true;
115
116 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
117 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
118 builder.add_value(200);
119 ASSERT_TRUE(msg.Send(builder.Finish()));
120 });
121
122 aos::Fetcher<TestMessage> fetcher = loop2->MakeFetcher<TestMessage>("/test");
123 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
124 ASSERT_TRUE(fetcher.Fetch());
125 EXPECT_EQ(fetcher->value(), 200);
126 this->Exit();
127 });
128
129 EXPECT_FALSE(happened);
130 Run();
131 EXPECT_TRUE(happened);
132}
133
134// Tests that a watcher can be created with an std::function.
135TEST_P(AbstractEventLoopTest, BasicFunction) {
136 auto loop1 = Make();
137 auto loop2 = MakePrimary();
138
139 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
140
141 bool happened = false;
142
143 loop2->OnRun([&]() {
144 happened = true;
145
146 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
147 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
148 builder.add_value(200);
149 ASSERT_TRUE(msg.Send(builder.Finish()));
150 });
151
152 loop2->MakeWatcher("/test", std::function<void(const TestMessage &)>(
153 [&](const TestMessage &message) {
154 EXPECT_EQ(message.value(), 200);
155 this->Exit();
156 }));
157
158 EXPECT_FALSE(happened);
159 Run();
160 EXPECT_TRUE(happened);
161}
162
Brian Silverman0fc69932020-01-24 21:54:02 -0800163// Tests that watcher can receive messages from two senders.
164// Also tests that OnRun() works.
165TEST_P(AbstractEventLoopTest, BasicTwoSenders) {
166 auto loop1 = Make();
167 auto loop2 = MakePrimary();
168
169 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
170 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
171
172 bool happened = false;
173
174 loop2->OnRun([&]() {
175 happened = true;
176
177 {
178 aos::Sender<TestMessage>::Builder msg = sender1.MakeBuilder();
179 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
180 builder.add_value(200);
181 ASSERT_TRUE(msg.Send(builder.Finish()));
182 }
183 {
184 aos::Sender<TestMessage>::Builder msg = sender2.MakeBuilder();
185 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
186 builder.add_value(200);
187 ASSERT_TRUE(msg.Send(builder.Finish()));
188 }
189 });
190
191 int messages_received = 0;
192 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
193 EXPECT_EQ(message.value(), 200);
194 this->Exit();
195 ++messages_received;
196 });
197
198 EXPECT_FALSE(happened);
199 Run();
200 EXPECT_TRUE(happened);
201 EXPECT_EQ(messages_received, 2);
202}
203
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700204// Tests that a fetcher can fetch from a sender.
205// Also tests that OnRun() works.
206TEST_P(AbstractEventLoopTest, FetchWithoutRun) {
207 auto loop1 = Make();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800208 auto loop2 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -0700209 auto loop3 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800210
211 auto sender = loop1->MakeSender<TestMessage>("/test");
212
213 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
214
Austin Schuhbbce72d2019-05-26 15:11:46 -0700215 EXPECT_FALSE(fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -0800216 EXPECT_EQ(fetcher.get(), nullptr);
217
Austin Schuhad154822019-12-27 15:45:13 -0800218 EXPECT_EQ(fetcher.context().monotonic_event_time, monotonic_clock::min_time);
219 EXPECT_EQ(fetcher.context().monotonic_remote_time, monotonic_clock::min_time);
220 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
221 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
Austin Schuh39788ff2019-12-01 18:22:57 -0800222 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
223 EXPECT_EQ(fetcher.context().size, 0u);
224 EXPECT_EQ(fetcher.context().data, nullptr);
Austin Schuhbbce72d2019-05-26 15:11:46 -0700225
Alex Perrycb7da4b2019-08-28 19:35:56 -0700226 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
227 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
228 builder.add_value(200);
229 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700230
231 EXPECT_TRUE(fetcher.Fetch());
232 ASSERT_FALSE(fetcher.get() == nullptr);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700233 EXPECT_EQ(fetcher.get()->value(), 200);
Austin Schuh39788ff2019-12-01 18:22:57 -0800234
235 const chrono::milliseconds kEpsilon(100);
236
Austin Schuhad154822019-12-27 15:45:13 -0800237 const aos::monotonic_clock::time_point monotonic_now = loop2->monotonic_now();
238 const aos::realtime_clock::time_point realtime_now = loop2->realtime_now();
239 EXPECT_EQ(fetcher.context().monotonic_event_time,
240 fetcher.context().monotonic_remote_time);
241 EXPECT_EQ(fetcher.context().realtime_event_time,
242 fetcher.context().realtime_remote_time);
243
244 EXPECT_GE(fetcher.context().monotonic_event_time, monotonic_now - kEpsilon);
245 EXPECT_LE(fetcher.context().monotonic_event_time, monotonic_now + kEpsilon);
246 EXPECT_GE(fetcher.context().realtime_event_time, realtime_now - kEpsilon);
247 EXPECT_LE(fetcher.context().realtime_event_time, realtime_now + kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -0800248 EXPECT_EQ(fetcher.context().queue_index, 0x0u);
249 EXPECT_EQ(fetcher.context().size, 20u);
250 EXPECT_NE(fetcher.context().data, nullptr);
Parker Schuhe4a70d62017-12-27 20:10:20 -0800251}
252
Austin Schuh3578a2e2019-05-25 18:17:59 -0700253// Tests that watcher will receive all messages sent if they are sent after
254// initialization and before running.
255TEST_P(AbstractEventLoopTest, DoubleSendAtStartup) {
256 auto loop1 = Make();
257 auto loop2 = MakePrimary();
258
259 auto sender = loop1->MakeSender<TestMessage>("/test");
260
261 ::std::vector<int> values;
262
263 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700264 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700265 if (values.size() == 2) {
Austin Schuh9fe68f72019-08-10 19:32:03 -0700266 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -0700267 }
268 });
269
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700270 // Before Run, should be ignored.
Austin Schuh3578a2e2019-05-25 18:17:59 -0700271 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700272 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
273 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
274 builder.add_value(199);
275 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700276 }
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700277
278 loop2->OnRun([&]() {
279 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700280 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
281 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
282 builder.add_value(200);
283 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700284 }
285 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700286 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
287 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
288 builder.add_value(201);
289 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700290 }
291 });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700292
293 Run();
294
295 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
296}
297
298// Tests that watcher will not receive messages sent before the watcher is
299// created.
300TEST_P(AbstractEventLoopTest, DoubleSendAfterStartup) {
301 auto loop1 = Make();
302 auto loop2 = MakePrimary();
303
304 auto sender = loop1->MakeSender<TestMessage>("/test");
305
306 ::std::vector<int> values;
307
308 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700309 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
310 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
311 builder.add_value(200);
312 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700313 }
314 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700315 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
316 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
317 builder.add_value(201);
318 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700319 }
320
321 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700322 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700323 });
324
325 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700326 auto test_timer = loop2->AddTimer([this]() { this->Exit(); });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700327 loop2->OnRun([&test_timer, &loop2]() {
328 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
329 });
330
331 Run();
332 EXPECT_EQ(0, values.size());
333}
334
Austin Schuhbbce72d2019-05-26 15:11:46 -0700335// Tests that FetchNext gets all the messages sent after it is constructed.
336TEST_P(AbstractEventLoopTest, FetchNext) {
337 auto loop1 = Make();
338 auto loop2 = MakePrimary();
339
340 auto sender = loop1->MakeSender<TestMessage>("/test");
341 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
342
343 ::std::vector<int> values;
344
345 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700346 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
347 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
348 builder.add_value(200);
349 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700350 }
351 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700352 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
353 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
354 builder.add_value(201);
355 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700356 }
357
358 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700359 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700360 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700361 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700362 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700363 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700364 });
365
366 loop2->OnRun([&test_timer, &loop2]() {
367 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
368 });
369
370 Run();
371 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
372}
373
374// Tests that FetchNext gets no messages sent before it is constructed.
375TEST_P(AbstractEventLoopTest, FetchNextAfterSend) {
376 auto loop1 = Make();
377 auto loop2 = MakePrimary();
378
379 auto sender = loop1->MakeSender<TestMessage>("/test");
380
381 ::std::vector<int> values;
382
383 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700384 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
385 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
386 builder.add_value(200);
387 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700388 }
389 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700390 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
391 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
392 builder.add_value(201);
393 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700394 }
395
396 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
397
398 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700399 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700400 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700401 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700402 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700403 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700404 });
405
406 loop2->OnRun([&test_timer, &loop2]() {
407 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
408 });
409
410 Run();
411 EXPECT_THAT(0, values.size());
412}
413
414// Tests that Fetch returns the last message created before the loop was
415// started.
416TEST_P(AbstractEventLoopTest, FetchDataFromBeforeCreation) {
417 auto loop1 = Make();
418 auto loop2 = MakePrimary();
419
420 auto sender = loop1->MakeSender<TestMessage>("/test");
421
422 ::std::vector<int> values;
423
424 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700425 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
426 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
427 builder.add_value(200);
428 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700429 }
430 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700431 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
432 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
433 builder.add_value(201);
434 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700435 }
436
437 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
438
439 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700440 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700441 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700442 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700443 }
444 // Do it again to make sure we don't double fetch.
445 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700446 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700447 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700448 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700449 });
450
451 loop2->OnRun([&test_timer, &loop2]() {
452 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
453 });
454
455 Run();
456 EXPECT_THAT(values, ::testing::ElementsAreArray({201}));
457}
458
459// Tests that Fetch and FetchNext interleave as expected.
460TEST_P(AbstractEventLoopTest, FetchAndFetchNextTogether) {
461 auto loop1 = Make();
462 auto loop2 = MakePrimary();
463
464 auto sender = loop1->MakeSender<TestMessage>("/test");
465
466 ::std::vector<int> values;
467
468 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700469 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
470 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
471 builder.add_value(200);
472 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700473 }
474 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700475 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
476 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
477 builder.add_value(201);
478 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700479 }
480
481 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
482
483 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700484 auto test_timer = loop2->AddTimer([&fetcher, &values, &sender, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700485 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700486 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700487 }
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(202);
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(203);
499 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700500 }
501 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700502 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
503 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
504 builder.add_value(204);
505 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700506 }
507
508 if (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700509 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700510 }
511
512 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700513 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700514 }
515
Austin Schuh9fe68f72019-08-10 19:32:03 -0700516 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700517 });
518
519 loop2->OnRun([&test_timer, &loop2]() {
520 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
521 });
522
523 Run();
524 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
525}
526
Austin Schuh3115a202019-05-27 21:02:14 -0700527// Tests that FetchNext behaves correctly when we get two messages in the queue
528// but don't consume the first until after the second has been sent.
529TEST_P(AbstractEventLoopTest, FetchNextTest) {
Austin Schuh3115a202019-05-27 21:02:14 -0700530 auto send_loop = Make();
531 auto fetch_loop = Make();
532 auto sender = send_loop->MakeSender<TestMessage>("/test");
533 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
534
535 {
Tyler Chatow67ddb032020-01-12 14:30:04 -0800536 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
537 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
538 builder.add_value(100);
539 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700540 }
541
542 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700543 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
544 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
545 builder.add_value(200);
546 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700547 }
548
549 ASSERT_TRUE(fetcher.FetchNext());
550 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700551 EXPECT_EQ(100, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700552
553 ASSERT_TRUE(fetcher.FetchNext());
554 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700555 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700556
557 // When we run off the end of the queue, expect to still have the old message:
558 ASSERT_FALSE(fetcher.FetchNext());
559 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700560 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700561}
562
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800563// Verify that making a fetcher and watcher for "/test" succeeds.
564TEST_P(AbstractEventLoopTest, FetcherAndWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800565 auto loop = Make();
566 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800567 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Parker Schuhe4a70d62017-12-27 20:10:20 -0800568}
569
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800570// Verify that making 2 fetchers for "/test" succeeds.
Parker Schuhe4a70d62017-12-27 20:10:20 -0800571TEST_P(AbstractEventLoopTest, TwoFetcher) {
572 auto loop = Make();
573 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800574 auto fetcher2 = loop->MakeFetcher<TestMessage>("/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -0800575}
576
Alex Perrycb7da4b2019-08-28 19:35:56 -0700577// Verify that registering a watcher for an invalid channel name dies.
578TEST_P(AbstractEventLoopDeathTest, InvalidChannelName) {
579 auto loop = Make();
580 EXPECT_DEATH(
581 { loop->MakeWatcher("/test/invalid", [&](const TestMessage &) {}); },
582 "/test/invalid");
Brian Silverman454bc112020-03-05 14:21:25 -0800583 EXPECT_DEATH(
584 { loop->MakeNoArgWatcher<TestMessage>("/test/invalid", [&]() {}); },
585 "/test/invalid");
Alex Perrycb7da4b2019-08-28 19:35:56 -0700586}
587
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800588// Verify that registering a watcher twice for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700589TEST_P(AbstractEventLoopDeathTest, TwoWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800590 auto loop = Make();
591 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800592 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
593 "/test");
Brian Silverman454bc112020-03-05 14:21:25 -0800594 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
595}
596
597// Verify that registering a no-arg watcher twice for "/test" fails.
598TEST_P(AbstractEventLoopDeathTest, TwoNoArgWatcher) {
599 auto loop = Make();
600 loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {});
601 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
602 "/test");
603 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800604}
605
Austin Schuh3115a202019-05-27 21:02:14 -0700606// Verify that SetRuntimeRealtimePriority fails while running.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700607TEST_P(AbstractEventLoopDeathTest, SetRuntimeRealtimePriority) {
Austin Schuh3115a202019-05-27 21:02:14 -0700608 auto loop = MakePrimary();
609 // Confirm that runtime priority calls work when not realtime.
610 loop->SetRuntimeRealtimePriority(5);
611
612 loop->OnRun([&]() { loop->SetRuntimeRealtimePriority(5); });
613
614 EXPECT_DEATH(Run(), "realtime");
615}
616
Brian Silverman6a54ff32020-04-28 16:41:39 -0700617// Verify that SetRuntimeAffinity fails while running.
618TEST_P(AbstractEventLoopDeathTest, SetRuntimeAffinity) {
619 auto loop = MakePrimary();
620 // Confirm that runtime priority calls work when not running.
621 loop->SetRuntimeAffinity(MakeCpusetFromCpus({0}));
622
623 loop->OnRun([&]() { loop->SetRuntimeAffinity(MakeCpusetFromCpus({1})); });
624
625 EXPECT_DEATH(Run(), "Cannot set affinity while running");
626}
627
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800628// Verify that registering a watcher and a sender for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700629TEST_P(AbstractEventLoopDeathTest, WatcherAndSender) {
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800630 auto loop = Make();
631 auto sender = loop->MakeSender<TestMessage>("/test");
632 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
633 "/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -0800634}
635
Austin Schuhe516ab02020-05-06 21:37:04 -0700636// Verify that creating too many senders fails.
637TEST_P(AbstractEventLoopDeathTest, TooManySenders) {
638 auto loop = Make();
639 std::vector<aos::Sender<TestMessage>> senders;
640 for (int i = 0; i < 10; ++i) {
641 senders.emplace_back(loop->MakeSender<TestMessage>("/test"));
642 }
643 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); },
644 "Failed to create sender on \\{ \"name\": \"/test\", \"type\": "
645 "\"aos.TestMessage\" \\}, too many senders.");
646}
647
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700648// Verify that we can't create a sender inside OnRun.
649TEST_P(AbstractEventLoopDeathTest, SenderInOnRun) {
650 auto loop1 = MakePrimary();
651
652 loop1->OnRun(
653 [&]() { auto sender = loop1->MakeSender<TestMessage>("/test2"); });
654
655 EXPECT_DEATH(Run(), "running");
656}
657
658// Verify that we can't create a watcher inside OnRun.
659TEST_P(AbstractEventLoopDeathTest, WatcherInOnRun) {
660 auto loop1 = MakePrimary();
661
662 loop1->OnRun(
663 [&]() { loop1->MakeWatcher("/test", [&](const TestMessage &) {}); });
664
665 EXPECT_DEATH(Run(), "running");
666}
667
Brian Silverman454bc112020-03-05 14:21:25 -0800668// Verify that we can't create a no-arg watcher inside OnRun.
669TEST_P(AbstractEventLoopDeathTest, NoArgWatcherInOnRun) {
670 auto loop1 = MakePrimary();
671
672 loop1->OnRun(
673 [&]() { loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {}); });
674
675 EXPECT_DEATH(Run(), "running");
676}
677
Parker Schuhe4a70d62017-12-27 20:10:20 -0800678// Verify that Quit() works when there are multiple watchers.
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800679TEST_P(AbstractEventLoopTest, MultipleWatcherQuit) {
680 auto loop1 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -0700681 auto loop2 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800682
Austin Schuh3578a2e2019-05-25 18:17:59 -0700683 loop2->MakeWatcher("/test1", [&](const TestMessage &) {});
684 loop2->MakeWatcher("/test2", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700685 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -0700686 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -0700687 });
688
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800689 auto sender = loop1->MakeSender<TestMessage>("/test2");
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700690
691 loop2->OnRun([&]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700692 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
693 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
694 builder.add_value(200);
695 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700696 });
Parker Schuhe4a70d62017-12-27 20:10:20 -0800697
Austin Schuh44019f92019-05-19 19:58:27 -0700698 Run();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800699}
700
Neil Balch229001a2018-01-07 18:22:52 -0800701// Verify that timer intervals and duration function properly.
702TEST_P(AbstractEventLoopTest, TimerIntervalAndDuration) {
Austin Schuh39788ff2019-12-01 18:22:57 -0800703 // Force a slower rate so we are guarenteed to have reports for our timer.
704 FLAGS_timing_report_ms = 2000;
705
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800706 const int kCount = 5;
Neil Balch229001a2018-01-07 18:22:52 -0800707
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800708 auto loop = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -0800709 auto loop2 = Make();
710
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800711 ::std::vector<::aos::monotonic_clock::time_point> times;
712 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
713
Austin Schuh39788ff2019-12-01 18:22:57 -0800714 Fetcher<timing::Report> report_fetcher =
715 loop2->MakeFetcher<timing::Report>("/aos");
716 EXPECT_FALSE(report_fetcher.Fetch());
717
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800718 auto test_timer = loop->AddTimer([this, &times, &expected_times, &loop]() {
719 times.push_back(loop->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -0800720 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
721 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
722 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
Austin Schuh39788ff2019-12-01 18:22:57 -0800723 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
724 EXPECT_EQ(loop->context().size, 0u);
725 EXPECT_EQ(loop->context().data, nullptr);
726
Austin Schuhad154822019-12-27 15:45:13 -0800727 expected_times.push_back(loop->context().monotonic_event_time);
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800728 if (times.size() == kCount) {
729 this->Exit();
730 }
Neil Balch229001a2018-01-07 18:22:52 -0800731 });
Austin Schuh39788ff2019-12-01 18:22:57 -0800732 test_timer->set_name("Test loop");
Neil Balch229001a2018-01-07 18:22:52 -0800733
Austin Schuh39788ff2019-12-01 18:22:57 -0800734 const monotonic_clock::time_point start_time = loop->monotonic_now();
Austin Schuh52d325c2019-06-23 18:59:06 -0700735 // TODO(austin): This should be an error... Should be done in OnRun only.
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800736 test_timer->Setup(start_time + chrono::seconds(1), chrono::seconds(1));
737
Austin Schuh44019f92019-05-19 19:58:27 -0700738 Run();
Neil Balch229001a2018-01-07 18:22:52 -0800739
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800740 // Confirm that we got both the right number of samples, and it's odd.
741 EXPECT_EQ(times.size(), static_cast<size_t>(kCount));
742 EXPECT_EQ(times.size(), expected_times.size());
743 EXPECT_EQ((times.size() % 2), 1);
744
745 // Grab the middle sample.
746 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
747
748 // Add up all the delays of all the times.
749 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
750 for (const ::aos::monotonic_clock::time_point time : times) {
751 sum += time - average_time;
752 }
753
754 // Average and add to the middle to find the average time.
755 sum /= times.size();
756 average_time += sum;
757
758 // Compute the offset from the average and the expected average. It
759 // should be pretty close to 0.
760 const ::aos::monotonic_clock::duration remainder =
761 average_time - start_time - chrono::seconds(times.size() / 2 + 1);
762
763 const chrono::milliseconds kEpsilon(100);
764 EXPECT_LT(remainder, +kEpsilon);
765 EXPECT_GT(remainder, -kEpsilon);
766
767 // Make sure that the average duration is close to 1 second.
768 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
769 times.front())
770 .count() /
771 static_cast<double>(times.size() - 1),
772 1.0, 0.1);
773
774 // Confirm that the ideal wakeup times increment correctly.
775 for (size_t i = 1; i < expected_times.size(); ++i) {
776 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
777 }
778
779 for (size_t i = 0; i < expected_times.size(); ++i) {
780 EXPECT_EQ((expected_times[i] - start_time) % chrono::seconds(1),
781 chrono::seconds(0));
782 }
783
784 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
785 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -0800786
787 // And, since we are here, check that the timing report makes sense.
788 // Start by looking for our event loop's timing.
789 FlatbufferDetachedBuffer<timing::Report> report =
790 FlatbufferDetachedBuffer<timing::Report>::Empty();
791 while (report_fetcher.FetchNext()) {
792 if (report_fetcher->name()->string_view() == "primary") {
793 report = CopyFlatBuffer(report_fetcher.get());
794 }
795 }
796
797 // Confirm that we have the right number of reports, and the contents are
798 // sane.
799 VLOG(1) << FlatbufferToJson(report, true);
800
801 EXPECT_EQ(report.message().name()->string_view(), "primary");
802
803 ASSERT_NE(report.message().senders(), nullptr);
Tyler Chatow67ddb032020-01-12 14:30:04 -0800804 EXPECT_EQ(report.message().senders()->size(), 2);
Austin Schuh39788ff2019-12-01 18:22:57 -0800805
806 ASSERT_NE(report.message().timers(), nullptr);
807 EXPECT_EQ(report.message().timers()->size(), 2);
808
809 EXPECT_EQ(report.message().timers()->Get(0)->name()->string_view(),
810 "Test loop");
811 EXPECT_GE(report.message().timers()->Get(0)->count(), 1);
812
813 EXPECT_EQ(report.message().timers()->Get(1)->name()->string_view(),
814 "timing_reports");
815 EXPECT_EQ(report.message().timers()->Get(1)->count(), 1);
816
817 // Make sure there is a single phased loop report with our report in it.
818 ASSERT_EQ(report.message().phased_loops(), nullptr);
Neil Balch229001a2018-01-07 18:22:52 -0800819}
820
821// Verify that we can change a timer's parameters during execution.
822TEST_P(AbstractEventLoopTest, TimerChangeParameters) {
Austin Schuh44019f92019-05-19 19:58:27 -0700823 auto loop = MakePrimary();
Neil Balch229001a2018-01-07 18:22:52 -0800824 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
825
826 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
827 iteration_list.push_back(loop->monotonic_now());
828 });
829
830 auto modifier_timer = loop->AddTimer([&loop, &test_timer]() {
831 test_timer->Setup(loop->monotonic_now(), ::std::chrono::milliseconds(30));
832 });
833
Neil Balch229001a2018-01-07 18:22:52 -0800834 test_timer->Setup(loop->monotonic_now(), ::std::chrono::milliseconds(20));
835 modifier_timer->Setup(loop->monotonic_now() +
836 ::std::chrono::milliseconds(45));
837 EndEventLoop(loop.get(), ::std::chrono::milliseconds(150));
Austin Schuh44019f92019-05-19 19:58:27 -0700838 Run();
Neil Balch229001a2018-01-07 18:22:52 -0800839
840 EXPECT_EQ(iteration_list.size(), 7);
841}
842
843// Verify that we can disable a timer during execution.
844TEST_P(AbstractEventLoopTest, TimerDisable) {
Austin Schuh44019f92019-05-19 19:58:27 -0700845 auto loop = MakePrimary();
Neil Balch229001a2018-01-07 18:22:52 -0800846 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
847
848 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
849 iteration_list.push_back(loop->monotonic_now());
850 });
851
Tyler Chatow67ddb032020-01-12 14:30:04 -0800852 auto ender_timer = loop->AddTimer([&test_timer]() { test_timer->Disable(); });
Neil Balch229001a2018-01-07 18:22:52 -0800853
854 test_timer->Setup(loop->monotonic_now(), ::std::chrono::milliseconds(20));
Tyler Chatow67ddb032020-01-12 14:30:04 -0800855 ender_timer->Setup(loop->monotonic_now() + ::std::chrono::milliseconds(45));
Neil Balch229001a2018-01-07 18:22:52 -0800856 EndEventLoop(loop.get(), ::std::chrono::milliseconds(150));
Austin Schuh44019f92019-05-19 19:58:27 -0700857 Run();
Neil Balch229001a2018-01-07 18:22:52 -0800858
859 EXPECT_EQ(iteration_list.size(), 3);
860}
Austin Schuh7267c532019-05-19 19:55:53 -0700861
Austin Schuh54cf95f2019-11-29 13:14:18 -0800862// Verifies that the event loop implementations detect when Channel is not a
863// pointer into confguration()
864TEST_P(AbstractEventLoopDeathTest, InvalidChannel) {
865 auto loop = MakePrimary();
866
Tyler Chatow67ddb032020-01-12 14:30:04 -0800867 const Channel *channel = configuration::GetChannel(
868 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
Austin Schuh54cf95f2019-11-29 13:14:18 -0800869
870 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
871
872 EXPECT_DEATH(
873 { loop->MakeRawSender(&channel_copy.message()); },
874 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
875
876 EXPECT_DEATH(
877 { loop->MakeRawFetcher(&channel_copy.message()); },
878 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
879
880 EXPECT_DEATH(
881 {
882 loop->MakeRawWatcher(&channel_copy.message(),
883 [](const Context, const void *) {});
884 },
885 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
886}
887
Brian Silverman454bc112020-03-05 14:21:25 -0800888// Verify that the send time on a message is roughly right when using a watcher.
Austin Schuh7267c532019-05-19 19:55:53 -0700889TEST_P(AbstractEventLoopTest, MessageSendTime) {
Austin Schuh44019f92019-05-19 19:58:27 -0700890 auto loop1 = MakePrimary();
Austin Schuh7267c532019-05-19 19:55:53 -0700891 auto loop2 = Make();
Austin Schuhad154822019-12-27 15:45:13 -0800892 auto sender = loop2->MakeSender<TestMessage>("/test");
Austin Schuh7267c532019-05-19 19:55:53 -0700893 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
894
895 auto test_timer = loop1->AddTimer([&sender]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700896 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
897 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
898 builder.add_value(200);
899 ASSERT_TRUE(msg.Send(builder.Finish()));
900 });
901
Austin Schuhad154822019-12-27 15:45:13 -0800902 bool triggered = false;
Brian Silverman454bc112020-03-05 14:21:25 -0800903 loop1->MakeWatcher("/test", [&](const TestMessage &msg) {
Austin Schuhad154822019-12-27 15:45:13 -0800904 // Confirm that the data pointer makes sense from a watcher, and all the
905 // timestamps look right.
906 EXPECT_GT(&msg, loop1->context().data);
907 EXPECT_EQ(loop1->context().monotonic_remote_time,
908 loop1->context().monotonic_event_time);
909 EXPECT_EQ(loop1->context().realtime_remote_time,
910 loop1->context().realtime_event_time);
911
912 const aos::monotonic_clock::time_point monotonic_now =
913 loop1->monotonic_now();
Tyler Chatow67ddb032020-01-12 14:30:04 -0800914 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -0800915
916 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
917 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
918 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
919 monotonic_now);
920 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
921 realtime_now);
922
Alex Perrycb7da4b2019-08-28 19:35:56 -0700923 EXPECT_LT(&msg, reinterpret_cast<void *>(
Austin Schuhad154822019-12-27 15:45:13 -0800924 reinterpret_cast<char *>(loop1->context().data) +
925 loop1->context().size));
926 triggered = true;
Austin Schuh7267c532019-05-19 19:55:53 -0700927 });
928
929 test_timer->Setup(loop1->monotonic_now() + ::std::chrono::seconds(1));
930
931 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
Austin Schuh44019f92019-05-19 19:58:27 -0700932 Run();
Austin Schuh7267c532019-05-19 19:55:53 -0700933
Austin Schuhad154822019-12-27 15:45:13 -0800934 EXPECT_TRUE(triggered);
935
Brian Silverman454bc112020-03-05 14:21:25 -0800936 ASSERT_TRUE(fetcher.Fetch());
937
938 monotonic_clock::duration monotonic_time_offset =
939 fetcher.context().monotonic_event_time -
940 (loop1->monotonic_now() - ::std::chrono::seconds(1));
941 realtime_clock::duration realtime_time_offset =
942 fetcher.context().realtime_event_time -
943 (loop1->realtime_now() - ::std::chrono::seconds(1));
944
945 EXPECT_EQ(fetcher.context().realtime_event_time,
946 fetcher.context().realtime_remote_time);
947 EXPECT_EQ(fetcher.context().monotonic_event_time,
948 fetcher.context().monotonic_remote_time);
949
950 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
951 << ": Got "
952 << fetcher.context().monotonic_event_time.time_since_epoch().count()
953 << " expected " << loop1->monotonic_now().time_since_epoch().count();
954 // Confirm that the data pointer makes sense.
955 EXPECT_GT(fetcher.get(), fetcher.context().data);
956 EXPECT_LT(fetcher.get(),
957 reinterpret_cast<void *>(
958 reinterpret_cast<char *>(fetcher.context().data) +
959 fetcher.context().size));
960 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
961 << ": Got "
962 << fetcher.context().monotonic_event_time.time_since_epoch().count()
963 << " expected " << loop1->monotonic_now().time_since_epoch().count();
964
965 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
966 << ": Got "
967 << fetcher.context().realtime_event_time.time_since_epoch().count()
968 << " expected " << loop1->realtime_now().time_since_epoch().count();
969 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
970 << ": Got "
971 << fetcher.context().realtime_event_time.time_since_epoch().count()
972 << " expected " << loop1->realtime_now().time_since_epoch().count();
973}
974
975// Verify that the send time on a message is roughly right when using a no-arg
976// watcher. To get a message, we need to use a fetcher to actually access the
977// message. This is also the main use case for no-arg fetchers.
978TEST_P(AbstractEventLoopTest, MessageSendTimeNoArg) {
979 auto loop1 = MakePrimary();
980 auto loop2 = Make();
981 auto sender = loop2->MakeSender<TestMessage>("/test");
982 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
983
984 auto test_timer = loop1->AddTimer([&sender]() {
985 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
986 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
987 builder.add_value(200);
988 ASSERT_TRUE(msg.Send(builder.Finish()));
989 });
990
991 bool triggered = false;
992 loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {
993 // Confirm that we can indeed use a fetcher on this channel from this
994 // context, and it results in a sane data pointer and timestamps.
995 ASSERT_TRUE(fetcher.Fetch());
996
997 EXPECT_EQ(loop1->context().monotonic_remote_time,
998 loop1->context().monotonic_event_time);
999 EXPECT_EQ(loop1->context().realtime_remote_time,
1000 loop1->context().realtime_event_time);
1001
1002 const aos::monotonic_clock::time_point monotonic_now =
1003 loop1->monotonic_now();
1004 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
1005
1006 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1007 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1008 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1009 monotonic_now);
1010 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1011 realtime_now);
1012
1013 triggered = true;
1014 });
1015
1016 test_timer->Setup(loop1->monotonic_now() + ::std::chrono::seconds(1));
1017
1018 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
1019 Run();
1020
1021 ASSERT_TRUE(triggered);
Austin Schuh7267c532019-05-19 19:55:53 -07001022
Alex Perrycb7da4b2019-08-28 19:35:56 -07001023 monotonic_clock::duration monotonic_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001024 fetcher.context().monotonic_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001025 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1026 realtime_clock::duration realtime_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001027 fetcher.context().realtime_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001028 (loop1->realtime_now() - ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07001029
Austin Schuhad154822019-12-27 15:45:13 -08001030 EXPECT_EQ(fetcher.context().realtime_event_time,
1031 fetcher.context().realtime_remote_time);
1032 EXPECT_EQ(fetcher.context().monotonic_event_time,
1033 fetcher.context().monotonic_remote_time);
1034
Alex Perrycb7da4b2019-08-28 19:35:56 -07001035 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1036 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001037 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh52d325c2019-06-23 18:59:06 -07001038 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07001039 // Confirm that the data pointer makes sense.
1040 EXPECT_GT(fetcher.get(), fetcher.context().data);
1041 EXPECT_LT(fetcher.get(),
1042 reinterpret_cast<void *>(
1043 reinterpret_cast<char *>(fetcher.context().data) +
1044 fetcher.context().size));
1045 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1046 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001047 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh7267c532019-05-19 19:55:53 -07001048 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07001049
1050 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1051 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001052 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07001053 << " expected " << loop1->realtime_now().time_since_epoch().count();
1054 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1055 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001056 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07001057 << " expected " << loop1->realtime_now().time_since_epoch().count();
Austin Schuh7267c532019-05-19 19:55:53 -07001058}
1059
Austin Schuh52d325c2019-06-23 18:59:06 -07001060// Tests that a couple phased loops run in a row result in the correct offset
1061// and period.
1062TEST_P(AbstractEventLoopTest, PhasedLoopTest) {
Austin Schuh39788ff2019-12-01 18:22:57 -08001063 // Force a slower rate so we are guarenteed to have reports for our phased
1064 // loop.
1065 FLAGS_timing_report_ms = 2000;
1066
Austin Schuh52d325c2019-06-23 18:59:06 -07001067 const chrono::milliseconds kOffset = chrono::milliseconds(400);
1068 const int kCount = 5;
1069
1070 auto loop1 = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001071 auto loop2 = Make();
1072
1073 Fetcher<timing::Report> report_fetcher =
1074 loop2->MakeFetcher<timing::Report>("/aos");
1075 EXPECT_FALSE(report_fetcher.Fetch());
Austin Schuh52d325c2019-06-23 18:59:06 -07001076
1077 // Collect up a couple of samples.
1078 ::std::vector<::aos::monotonic_clock::time_point> times;
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001079 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
Austin Schuh52d325c2019-06-23 18:59:06 -07001080
1081 // Run kCount iterations.
Austin Schuh39788ff2019-12-01 18:22:57 -08001082 loop1
1083 ->AddPhasedLoop(
1084 [&times, &expected_times, &loop1, this](int count) {
1085 EXPECT_EQ(count, 1);
1086 times.push_back(loop1->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001087 expected_times.push_back(loop1->context().monotonic_event_time);
Austin Schuh39788ff2019-12-01 18:22:57 -08001088
Austin Schuhad154822019-12-27 15:45:13 -08001089 EXPECT_EQ(loop1->context().monotonic_remote_time,
1090 monotonic_clock::min_time);
1091 EXPECT_EQ(loop1->context().realtime_event_time,
1092 realtime_clock::min_time);
1093 EXPECT_EQ(loop1->context().realtime_remote_time,
Austin Schuh39788ff2019-12-01 18:22:57 -08001094 realtime_clock::min_time);
1095 EXPECT_EQ(loop1->context().queue_index, 0xffffffffu);
1096 EXPECT_EQ(loop1->context().size, 0u);
1097 EXPECT_EQ(loop1->context().data, nullptr);
1098
1099 if (times.size() == kCount) {
1100 LOG(INFO) << "Exiting";
1101 this->Exit();
1102 }
1103 },
1104 chrono::seconds(1), kOffset)
1105 ->set_name("Test loop");
Austin Schuh52d325c2019-06-23 18:59:06 -07001106
1107 // Add a delay to make sure that delay during startup doesn't result in a
1108 // "missed cycle".
1109 SleepFor(chrono::seconds(2));
1110
1111 Run();
1112
1113 // Confirm that we got both the right number of samples, and it's odd.
1114 EXPECT_EQ(times.size(), static_cast<size_t>(kCount));
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001115 EXPECT_EQ(times.size(), expected_times.size());
Austin Schuh52d325c2019-06-23 18:59:06 -07001116 EXPECT_EQ((times.size() % 2), 1);
1117
1118 // Grab the middle sample.
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001119 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
Austin Schuh52d325c2019-06-23 18:59:06 -07001120
1121 // Add up all the delays of all the times.
1122 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1123 for (const ::aos::monotonic_clock::time_point time : times) {
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001124 sum += time - average_time;
Austin Schuh52d325c2019-06-23 18:59:06 -07001125 }
1126
1127 // Average and add to the middle to find the average time.
1128 sum /= times.size();
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001129 average_time += sum;
Austin Schuh52d325c2019-06-23 18:59:06 -07001130
1131 // Compute the offset from the start of the second of the average time. This
1132 // should be pretty close to the offset.
1133 const ::aos::monotonic_clock::duration remainder =
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001134 average_time.time_since_epoch() -
1135 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
Austin Schuh52d325c2019-06-23 18:59:06 -07001136
1137 const chrono::milliseconds kEpsilon(100);
1138 EXPECT_LT(remainder, kOffset + kEpsilon);
1139 EXPECT_GT(remainder, kOffset - kEpsilon);
1140
1141 // Make sure that the average duration is close to 1 second.
1142 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1143 times.front())
1144 .count() /
1145 static_cast<double>(times.size() - 1),
1146 1.0, 0.1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001147
1148 // Confirm that the ideal wakeup times increment correctly.
1149 for (size_t i = 1; i < expected_times.size(); ++i) {
1150 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1151 }
1152
1153 for (size_t i = 0; i < expected_times.size(); ++i) {
1154 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
1155 kOffset);
1156 }
1157
1158 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1159 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001160
1161 // And, since we are here, check that the timing report makes sense.
1162 // Start by looking for our event loop's timing.
1163 FlatbufferDetachedBuffer<timing::Report> report =
1164 FlatbufferDetachedBuffer<timing::Report>::Empty();
1165 while (report_fetcher.FetchNext()) {
1166 if (report_fetcher->name()->string_view() == "primary") {
1167 report = CopyFlatBuffer(report_fetcher.get());
1168 }
1169 }
1170
1171 VLOG(1) << FlatbufferToJson(report, true);
1172
1173 EXPECT_EQ(report.message().name()->string_view(), "primary");
1174
1175 ASSERT_NE(report.message().senders(), nullptr);
Tyler Chatow67ddb032020-01-12 14:30:04 -08001176 EXPECT_EQ(report.message().senders()->size(), 2);
Austin Schuh39788ff2019-12-01 18:22:57 -08001177
1178 ASSERT_NE(report.message().timers(), nullptr);
1179 EXPECT_EQ(report.message().timers()->size(), 1);
1180
1181 // Make sure there is a single phased loop report with our report in it.
1182 ASSERT_NE(report.message().phased_loops(), nullptr);
1183 ASSERT_EQ(report.message().phased_loops()->size(), 1);
1184 EXPECT_EQ(report.message().phased_loops()->Get(0)->name()->string_view(),
1185 "Test loop");
1186 EXPECT_GE(report.message().phased_loops()->Get(0)->count(), 1);
1187}
1188
1189// Tests that senders count correctly in the timing report.
1190TEST_P(AbstractEventLoopTest, SenderTimingReport) {
1191 FLAGS_timing_report_ms = 1000;
1192 auto loop1 = MakePrimary();
1193
1194 auto loop2 = Make("watcher_loop");
1195 loop2->MakeWatcher("/test", [](const TestMessage &) {});
1196
1197 auto loop3 = Make();
1198
1199 Fetcher<timing::Report> report_fetcher =
1200 loop3->MakeFetcher<timing::Report>("/aos");
1201 EXPECT_FALSE(report_fetcher.Fetch());
1202
1203 auto sender = loop1->MakeSender<TestMessage>("/test");
1204
1205 // Add a timer to actually quit.
1206 auto test_timer = loop1->AddTimer([&sender]() {
1207 for (int i = 0; i < 10; ++i) {
1208 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1209 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1210 builder.add_value(200 + i);
1211 ASSERT_TRUE(msg.Send(builder.Finish()));
1212 }
1213 });
1214
1215 // Quit after 1 timing report, mid way through the next cycle.
1216 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
1217
1218 loop1->OnRun([&test_timer, &loop1]() {
1219 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1500));
1220 });
1221
1222 Run();
1223
1224 // And, since we are here, check that the timing report makes sense.
1225 // Start by looking for our event loop's timing.
1226 FlatbufferDetachedBuffer<timing::Report> primary_report =
1227 FlatbufferDetachedBuffer<timing::Report>::Empty();
1228 while (report_fetcher.FetchNext()) {
1229 LOG(INFO) << "Report " << FlatbufferToJson(report_fetcher.get());
1230 if (report_fetcher->name()->string_view() == "primary") {
1231 primary_report = CopyFlatBuffer(report_fetcher.get());
1232 }
1233 }
1234
1235 LOG(INFO) << FlatbufferToJson(primary_report, true);
1236
1237 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
1238
1239 ASSERT_NE(primary_report.message().senders(), nullptr);
Tyler Chatow67ddb032020-01-12 14:30:04 -08001240 EXPECT_EQ(primary_report.message().senders()->size(), 3);
Austin Schuh39788ff2019-12-01 18:22:57 -08001241
1242 // Confirm that the sender looks sane.
1243 EXPECT_EQ(
1244 loop1->configuration()
1245 ->channels()
1246 ->Get(primary_report.message().senders()->Get(0)->channel_index())
1247 ->name()
1248 ->string_view(),
1249 "/test");
1250 EXPECT_EQ(primary_report.message().senders()->Get(0)->count(), 10);
1251
1252 // Confirm that the timing primary_report sender looks sane.
1253 EXPECT_EQ(
1254 loop1->configuration()
1255 ->channels()
1256 ->Get(primary_report.message().senders()->Get(1)->channel_index())
1257 ->name()
1258 ->string_view(),
1259 "/aos");
1260 EXPECT_EQ(primary_report.message().senders()->Get(1)->count(), 1);
1261
1262 ASSERT_NE(primary_report.message().timers(), nullptr);
1263 EXPECT_EQ(primary_report.message().timers()->size(), 3);
1264
1265 // Make sure there are no phased loops or watchers.
1266 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
1267 ASSERT_EQ(primary_report.message().watchers(), nullptr);
1268}
1269
1270// Tests that senders count correctly in the timing report.
1271TEST_P(AbstractEventLoopTest, WatcherTimingReport) {
1272 FLAGS_timing_report_ms = 1000;
1273 auto loop1 = MakePrimary();
1274 loop1->MakeWatcher("/test", [](const TestMessage &) {});
1275
1276 auto loop2 = Make("sender_loop");
1277
1278 auto loop3 = Make();
1279
1280 Fetcher<timing::Report> report_fetcher =
1281 loop3->MakeFetcher<timing::Report>("/aos");
1282 EXPECT_FALSE(report_fetcher.Fetch());
1283
1284 auto sender = loop2->MakeSender<TestMessage>("/test");
1285
1286 // Add a timer to actually quit.
1287 auto test_timer = loop1->AddTimer([&sender]() {
1288 for (int i = 0; i < 10; ++i) {
1289 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1290 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1291 builder.add_value(200 + i);
1292 ASSERT_TRUE(msg.Send(builder.Finish()));
1293 }
1294 });
1295
1296 // Quit after 1 timing report, mid way through the next cycle.
1297 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
1298
1299 loop1->OnRun([&test_timer, &loop1]() {
1300 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1500));
1301 });
1302
1303 Run();
1304
1305 // And, since we are here, check that the timing report makes sense.
1306 // Start by looking for our event loop's timing.
1307 FlatbufferDetachedBuffer<timing::Report> primary_report =
1308 FlatbufferDetachedBuffer<timing::Report>::Empty();
1309 while (report_fetcher.FetchNext()) {
1310 LOG(INFO) << "Report " << FlatbufferToJson(report_fetcher.get());
1311 if (report_fetcher->name()->string_view() == "primary") {
1312 primary_report = CopyFlatBuffer(report_fetcher.get());
1313 }
1314 }
1315
1316 // Check the watcher report.
1317 VLOG(1) << FlatbufferToJson(primary_report, true);
1318
1319 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
1320
1321 // Just the timing report timer.
1322 ASSERT_NE(primary_report.message().timers(), nullptr);
1323 EXPECT_EQ(primary_report.message().timers()->size(), 3);
1324
1325 // No phased loops
1326 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
1327
1328 ASSERT_NE(primary_report.message().watchers(), nullptr);
1329 ASSERT_EQ(primary_report.message().watchers()->size(), 1);
1330 EXPECT_EQ(primary_report.message().watchers()->Get(0)->count(), 10);
1331}
1332
1333// Tests that fetchers count correctly in the timing report.
1334TEST_P(AbstractEventLoopTest, FetcherTimingReport) {
1335 FLAGS_timing_report_ms = 1000;
1336 auto loop1 = MakePrimary();
1337 auto loop2 = Make("sender_loop");
1338
1339 auto loop3 = Make();
1340
1341 Fetcher<timing::Report> report_fetcher =
1342 loop3->MakeFetcher<timing::Report>("/aos");
1343 EXPECT_FALSE(report_fetcher.Fetch());
1344
1345 auto sender = loop2->MakeSender<TestMessage>("/test");
1346 auto fetcher1 = loop1->MakeFetcher<TestMessage>("/test");
1347 auto fetcher2 = loop1->MakeFetcher<TestMessage>("/test");
1348 fetcher1.Fetch();
1349 fetcher2.Fetch();
1350
1351 // Add a timer to actually quit.
1352 auto test_timer = loop1->AddTimer([&sender]() {
1353 for (int i = 0; i < 10; ++i) {
1354 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1355 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1356 builder.add_value(200 + i);
1357 ASSERT_TRUE(msg.Send(builder.Finish()));
1358 }
1359 });
1360
1361 auto test_timer2 = loop1->AddTimer([&fetcher1, &fetcher2]() {
1362 fetcher1.Fetch();
1363 while (fetcher2.FetchNext()) {
1364 }
1365 });
1366
1367 // Quit after 1 timing report, mid way through the next cycle.
1368 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
1369
1370 loop1->OnRun([test_timer, test_timer2, &loop1]() {
1371 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1400));
1372 test_timer2->Setup(loop1->monotonic_now() + chrono::milliseconds(1600));
1373 });
1374
1375 Run();
1376
1377 // And, since we are here, check that the timing report makes sense.
1378 // Start by looking for our event loop's timing.
1379 FlatbufferDetachedBuffer<timing::Report> primary_report =
1380 FlatbufferDetachedBuffer<timing::Report>::Empty();
1381 while (report_fetcher.FetchNext()) {
1382 if (report_fetcher->name()->string_view() == "primary") {
1383 primary_report = CopyFlatBuffer(report_fetcher.get());
1384 }
1385 }
1386
1387 VLOG(1) << FlatbufferToJson(primary_report, true);
1388
1389 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
1390
1391 ASSERT_NE(primary_report.message().senders(), nullptr);
Tyler Chatow67ddb032020-01-12 14:30:04 -08001392 EXPECT_EQ(primary_report.message().senders()->size(), 2);
Austin Schuh39788ff2019-12-01 18:22:57 -08001393
1394 ASSERT_NE(primary_report.message().timers(), nullptr);
1395 EXPECT_EQ(primary_report.message().timers()->size(), 4);
1396
1397 // Make sure there are no phased loops or watchers.
1398 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
1399 ASSERT_EQ(primary_report.message().watchers(), nullptr);
1400
1401 // Now look at the fetchrs.
1402 ASSERT_NE(primary_report.message().fetchers(), nullptr);
1403 ASSERT_EQ(primary_report.message().fetchers()->size(), 2);
1404
1405 EXPECT_EQ(primary_report.message().fetchers()->Get(0)->count(), 1);
1406 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->average(),
1407 0.1);
Tyler Chatow67ddb032020-01-12 14:30:04 -08001408 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->min(), 0.1);
1409 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->max(), 0.1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001410 EXPECT_EQ(primary_report.message()
1411 .fetchers()
1412 ->Get(0)
1413 ->latency()
1414 ->standard_deviation(),
1415 0.0);
1416
1417 EXPECT_EQ(primary_report.message().fetchers()->Get(1)->count(), 10);
Austin Schuh52d325c2019-06-23 18:59:06 -07001418}
1419
Austin Schuh67420a42019-12-21 21:55:04 -08001420// Tests that a raw watcher and raw fetcher can receive messages from a raw
1421// sender without messing up offsets.
1422TEST_P(AbstractEventLoopTest, RawBasic) {
1423 auto loop1 = Make();
1424 auto loop2 = MakePrimary();
1425 auto loop3 = Make();
1426
1427 const std::string kData("971 is the best");
1428
1429 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08001430 loop1->MakeRawSender(configuration::GetChannel(
1431 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08001432
1433 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08001434 loop3->MakeRawFetcher(configuration::GetChannel(
1435 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08001436
1437 loop2->OnRun(
1438 [&]() { EXPECT_TRUE(sender->Send(kData.data(), kData.size())); });
1439
1440 bool happened = false;
1441 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08001442 configuration::GetChannel(loop2->configuration(), "/test",
1443 "aos.TestMessage", "", nullptr),
Austin Schuh67420a42019-12-21 21:55:04 -08001444 [this, &kData, &fetcher, &happened](const Context &context,
1445 const void *message) {
1446 happened = true;
1447 EXPECT_EQ(std::string_view(kData),
1448 std::string_view(reinterpret_cast<const char *>(message),
1449 context.size));
1450 EXPECT_EQ(std::string_view(kData),
1451 std::string_view(reinterpret_cast<const char *>(context.data),
1452 context.size));
1453
1454 ASSERT_TRUE(fetcher->Fetch());
1455
1456 EXPECT_EQ(std::string_view(kData),
1457 std::string_view(
1458 reinterpret_cast<const char *>(fetcher->context().data),
1459 fetcher->context().size));
1460
1461 this->Exit();
1462 });
1463
1464 EXPECT_FALSE(happened);
1465 Run();
1466 EXPECT_TRUE(happened);
1467}
1468
Austin Schuhad154822019-12-27 15:45:13 -08001469// Tests that a raw watcher and raw fetcher can receive messages from a raw
1470// sender with remote times filled out.
1471TEST_P(AbstractEventLoopTest, RawRemoteTimes) {
1472 auto loop1 = Make();
1473 auto loop2 = MakePrimary();
1474 auto loop3 = Make();
1475
1476 const std::string kData("971 is the best");
1477
1478 const aos::monotonic_clock::time_point monotonic_remote_time =
1479 aos::monotonic_clock::time_point(chrono::seconds(1501));
1480 const aos::realtime_clock::time_point realtime_remote_time =
1481 aos::realtime_clock::time_point(chrono::seconds(3132));
1482
1483 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08001484 loop1->MakeRawSender(configuration::GetChannel(
1485 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08001486
1487 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08001488 loop3->MakeRawFetcher(configuration::GetChannel(
1489 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08001490
1491 loop2->OnRun([&]() {
1492 EXPECT_TRUE(sender->Send(kData.data(), kData.size(), monotonic_remote_time,
1493 realtime_remote_time));
1494 });
1495
1496 bool happened = false;
1497 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08001498 configuration::GetChannel(loop2->configuration(), "/test",
1499 "aos.TestMessage", "", nullptr),
Austin Schuhad154822019-12-27 15:45:13 -08001500 [this, monotonic_remote_time, realtime_remote_time, &fetcher, &happened](
1501 const Context &context, const void * /*message*/) {
1502 happened = true;
1503 EXPECT_EQ(monotonic_remote_time, context.monotonic_remote_time);
1504 EXPECT_EQ(realtime_remote_time, context.realtime_remote_time);
1505
1506 ASSERT_TRUE(fetcher->Fetch());
1507 EXPECT_EQ(monotonic_remote_time,
1508 fetcher->context().monotonic_remote_time);
1509 EXPECT_EQ(realtime_remote_time,
1510 fetcher->context().realtime_remote_time);
1511
1512 this->Exit();
1513 });
1514
1515 EXPECT_FALSE(happened);
1516 Run();
1517 EXPECT_TRUE(happened);
1518}
1519
1520// Tests that a raw sender fills out sent data.
1521TEST_P(AbstractEventLoopTest, RawSenderSentData) {
1522 auto loop1 = MakePrimary();
1523
1524 const std::string kData("971 is the best");
1525
1526 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08001527 loop1->MakeRawSender(configuration::GetChannel(
1528 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08001529
Tyler Chatow67ddb032020-01-12 14:30:04 -08001530 const aos::monotonic_clock::time_point monotonic_now = loop1->monotonic_now();
1531 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08001532
1533 EXPECT_TRUE(sender->Send(kData.data(), kData.size()));
1534
1535 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
1536 EXPECT_LE(sender->monotonic_sent_time(),
1537 monotonic_now + chrono::milliseconds(100));
1538 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
1539 EXPECT_LE(sender->realtime_sent_time(),
1540 realtime_now + chrono::milliseconds(100));
1541 EXPECT_EQ(sender->sent_queue_index(), 0u);
1542
1543 EXPECT_TRUE(sender->Send(kData.data(), kData.size()));
1544
1545 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
1546 EXPECT_LE(sender->monotonic_sent_time(),
1547 monotonic_now + chrono::milliseconds(100));
1548 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
1549 EXPECT_LE(sender->realtime_sent_time(),
1550 realtime_now + chrono::milliseconds(100));
1551 EXPECT_EQ(sender->sent_queue_index(), 1u);
1552}
1553
Austin Schuh217a9782019-12-21 23:02:50 -08001554// Tests that not setting up nodes results in no node.
1555TEST_P(AbstractEventLoopTest, NoNode) {
1556 auto loop1 = Make();
1557 auto loop2 = MakePrimary();
1558
1559 EXPECT_EQ(loop1->node(), nullptr);
1560 EXPECT_EQ(loop2->node(), nullptr);
1561}
1562
1563// Tests that setting up nodes results in node being set.
1564TEST_P(AbstractEventLoopTest, Node) {
1565 EnableNodes("me");
1566
1567 auto loop1 = Make();
1568 auto loop2 = MakePrimary();
1569
1570 EXPECT_NE(loop1->node(), nullptr);
1571 EXPECT_NE(loop2->node(), nullptr);
1572}
1573
1574// Tests that watchers work with a node setup.
1575TEST_P(AbstractEventLoopTest, NodeWatcher) {
1576 EnableNodes("me");
1577
1578 auto loop1 = Make();
1579 auto loop2 = Make();
1580 loop1->MakeWatcher("/test", [](const TestMessage &) {});
Tyler Chatow67ddb032020-01-12 14:30:04 -08001581 loop2->MakeRawWatcher(
1582 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
1583 nullptr),
1584 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08001585}
1586
Brian Silverman454bc112020-03-05 14:21:25 -08001587// Tests that no-arg watchers work with a node setup.
1588TEST_P(AbstractEventLoopTest, NodeNoArgWatcher) {
1589 EnableNodes("me");
1590
1591 auto loop1 = Make();
1592 auto loop2 = Make();
1593 loop1->MakeWatcher("/test", [](const TestMessage &) {});
1594 loop2->MakeRawNoArgWatcher(
1595 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
1596 nullptr),
1597 [](const Context &) {});
1598}
1599
Austin Schuh217a9782019-12-21 23:02:50 -08001600// Tests that fetcher work with a node setup.
1601TEST_P(AbstractEventLoopTest, NodeFetcher) {
1602 EnableNodes("me");
1603 auto loop1 = Make();
1604
1605 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
Tyler Chatow67ddb032020-01-12 14:30:04 -08001606 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
1607 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08001608}
1609
1610// Tests that sender work with a node setup.
1611TEST_P(AbstractEventLoopTest, NodeSender) {
1612 EnableNodes("me");
1613 auto loop1 = Make();
1614
1615 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
1616}
1617
1618// Tests that watchers fail when created on the wrong node.
1619TEST_P(AbstractEventLoopDeathTest, NodeWatcher) {
1620 EnableNodes("them");
1621
1622 auto loop1 = Make();
1623 auto loop2 = Make();
1624 EXPECT_DEATH({ loop1->MakeWatcher("/test", [](const TestMessage &) {}); },
1625 "node");
1626 EXPECT_DEATH(
1627 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08001628 loop2->MakeRawWatcher(
1629 configuration::GetChannel(configuration(), "/test",
1630 "aos.TestMessage", "", nullptr),
1631 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08001632 },
1633 "node");
Brian Silverman454bc112020-03-05 14:21:25 -08001634 EXPECT_DEATH({ loop1->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
1635 "node");
1636 EXPECT_DEATH(
1637 {
1638 loop2->MakeRawNoArgWatcher(
1639 configuration::GetChannel(configuration(), "/test",
1640 "aos.TestMessage", "", nullptr),
1641 [](const Context &) {});
1642 },
1643 "node");
Austin Schuh217a9782019-12-21 23:02:50 -08001644}
1645
1646// Tests that fetchers fail when created on the wrong node.
1647TEST_P(AbstractEventLoopDeathTest, NodeFetcher) {
1648 EnableNodes("them");
1649 auto loop1 = Make();
1650
1651 EXPECT_DEATH({ auto fetcher = loop1->MakeFetcher<TestMessage>("/test"); },
1652 "node");
1653 EXPECT_DEATH(
1654 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08001655 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
1656 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08001657 },
1658 "node");
1659}
1660
1661// Tests that senders fail when created on the wrong node.
1662TEST_P(AbstractEventLoopDeathTest, NodeSender) {
1663 EnableNodes("them");
1664 auto loop1 = Make();
1665
1666 EXPECT_DEATH(
1667 {
1668 aos::Sender<TestMessage> sender =
1669 loop1->MakeSender<TestMessage>("/test");
1670 },
1671 "node");
1672
1673 // Note: Creating raw senders is always supported. Right now, this lets us
1674 // use them to create message_gateway.
1675}
1676
Brian Silverman341b57e2020-06-23 16:23:18 -07001677// Tests creating multiple Builders from a single Sender at the same time.
1678TEST_P(AbstractEventLoopDeathTest, MultipleBuilders) {
1679 auto loop1 = Make();
1680 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
1681
1682 { auto builder = sender.MakeBuilder(); }
1683 {
1684 auto builder = sender.MakeBuilder();
1685 builder.MakeBuilder<TestMessage>().Finish();
1686 }
1687 {
1688 // Creating this after the first one was destroyed should be fine.
1689 auto builder = sender.MakeBuilder();
1690 builder.MakeBuilder<TestMessage>().Finish();
1691 // But not a second one.
1692 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
1693 "May not overwrite in-use allocator");
1694 }
1695
1696 FlatbufferDetachedBuffer<TestMessage> detached =
1697 flatbuffers::DetachedBuffer();
1698 {
1699 auto builder = sender.MakeBuilder();
1700 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
1701 }
1702 {
1703 // This is the second one, after the detached one, so it should fail.
1704 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
1705 "May not overwrite in-use allocator");
1706 }
1707
1708 // Clear the detached one, and then we should be able to create another.
1709 detached = flatbuffers::DetachedBuffer();
1710 {
1711 auto builder = sender.MakeBuilder();
1712 builder.MakeBuilder<TestMessage>().Finish();
1713 }
1714
1715 // And then detach another one.
1716 {
1717 auto builder = sender.MakeBuilder();
1718 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
1719 }
1720}
1721
1722// Tests sending a buffer detached from a different builder.
1723TEST_P(AbstractEventLoopDeathTest, WrongDetachedBuffer) {
1724 auto loop1 = Make();
1725 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
1726 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
1727
1728 auto builder = sender1.MakeBuilder();
1729 FlatbufferDetachedBuffer<TestMessage> detached =
1730 builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
1731 EXPECT_DEATH(sender2.SendDetached(std::move(detached)),
1732 "May only send the buffer detached from this Sender");
1733}
1734
Parker Schuhe4a70d62017-12-27 20:10:20 -08001735} // namespace testing
1736} // namespace aos