blob: 30e293dbb0ca43fb8133f6897014306cd61ac8d2 [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 Schuhad9e5eb2021-11-19 20:33:55 -08008#include "aos/logging/log_message_generated.h"
9#include "aos/logging/logging.h"
Austin Schuhcc6070c2020-10-10 20:25:56 -070010#include "aos/realtime.h"
Austin Schuh54cf95f2019-11-29 13:14:18 -080011#include "glog/logging.h"
Tyler Chatow67ddb032020-01-12 14:30:04 -080012#include "gmock/gmock.h"
13#include "gtest/gtest.h"
Austin Schuh9fe68f72019-08-10 19:32:03 -070014
Parker Schuhe4a70d62017-12-27 20:10:20 -080015namespace aos {
16namespace testing {
Austin Schuh52d325c2019-06-23 18:59:06 -070017namespace {
18namespace chrono = ::std::chrono;
19} // namespace
Parker Schuhe4a70d62017-12-27 20:10:20 -080020
Brian Silverman4f4e0612020-08-12 19:54:41 -070021::std::unique_ptr<EventLoop> AbstractEventLoopTest::Make(
22 std::string_view name) {
23 std::string name_copy(name);
24 if (name == "") {
25 name_copy = "loop";
26 name_copy += std::to_string(event_loop_count_);
27 }
28 ++event_loop_count_;
Austin Schuh6bae8252021-02-07 22:01:49 -080029 auto result = factory_->Make(name_copy);
30 if (do_timing_reports() == DoTimingReports::kNo) {
31 result->SkipTimingReport();
32 }
33 return result;
Brian Silverman4f4e0612020-08-12 19:54:41 -070034}
35
36void AbstractEventLoopTest::VerifyBuffers(
37 int number_buffers,
38 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>> fetchers,
39 std::vector<std::reference_wrapper<const Sender<TestMessage>>> senders) {
40 // The buffers which are in a sender.
41 std::unordered_set<int> in_sender;
42 for (const Sender<TestMessage> &sender : senders) {
43 const int this_buffer = sender.buffer_index();
44 CHECK_GE(this_buffer, 0);
45 CHECK_LT(this_buffer, number_buffers);
46 CHECK(in_sender.insert(this_buffer).second) << ": " << this_buffer;
47 }
48
49 if (read_method() != ReadMethod::PIN) {
50 // If we're not using PIN, we can't really verify anything about what
51 // buffers the fetchers have.
52 return;
53 }
54
55 // Mapping from TestMessage::value to buffer index.
56 std::unordered_map<int, int> fetcher_values;
57 for (const Fetcher<TestMessage> &fetcher : fetchers) {
58 if (!fetcher.get()) {
59 continue;
60 }
61 const int this_buffer = fetcher.context().buffer_index;
62 CHECK_GE(this_buffer, 0);
63 CHECK_LT(this_buffer, number_buffers);
64 CHECK(in_sender.count(this_buffer) == 0) << ": " << this_buffer;
65 const auto insert_result = fetcher_values.insert(
66 std::make_pair(fetcher.get()->value(), this_buffer));
67 if (!insert_result.second) {
68 CHECK_EQ(this_buffer, insert_result.first->second);
69 }
70 }
71}
72
Austin Schuh6b6dfa52019-06-12 20:16:20 -070073// Tests that watcher can receive messages from a sender.
Parker Schuhe4a70d62017-12-27 20:10:20 -080074// Also tests that OnRun() works.
75TEST_P(AbstractEventLoopTest, Basic) {
76 auto loop1 = Make();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070077 auto loop2 = MakePrimary();
78
Alex Perrycb7da4b2019-08-28 19:35:56 -070079 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
Austin Schuh6b6dfa52019-06-12 20:16:20 -070080
81 bool happened = false;
82
83 loop2->OnRun([&]() {
84 happened = true;
85
Alex Perrycb7da4b2019-08-28 19:35:56 -070086 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
87 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
88 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -070089 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -070090 });
91
92 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070093 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -070094 this->Exit();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070095 });
96
97 EXPECT_FALSE(happened);
98 Run();
99 EXPECT_TRUE(happened);
100}
101
Brian Silverman341b57e2020-06-23 16:23:18 -0700102// Tests that watcher can receive messages from a sender, sent via SendDetached.
103TEST_P(AbstractEventLoopTest, BasicSendDetached) {
104 auto loop1 = Make();
105 auto loop2 = MakePrimary();
106
107 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
108
109 FlatbufferDetachedBuffer<TestMessage> detached =
110 flatbuffers::DetachedBuffer();
111 {
112 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
113 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
114 builder.add_value(100);
115 detached = msg.Detach(builder.Finish());
116 }
117 detached = flatbuffers::DetachedBuffer();
118 {
119 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
120 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
121 builder.add_value(200);
122 detached = msg.Detach(builder.Finish());
123 }
milind1f1dca32021-07-03 13:50:07 -0700124 sender.CheckOk(sender.SendDetached(std::move(detached)));
Brian Silverman341b57e2020-06-23 16:23:18 -0700125
126 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
127 ASSERT_TRUE(fetcher.Fetch());
128 EXPECT_EQ(fetcher->value(), 200);
129}
130
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800131// Verifies that a no-arg watcher will not have a data pointer.
132TEST_P(AbstractEventLoopTest, NoArgNoData) {
133 auto loop1 = Make();
134 auto loop2 = MakePrimary();
135
136 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
137
138 bool happened = false;
139
140 loop2->OnRun([&]() {
141 happened = true;
142
143 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
144 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -0700145 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800146 });
147
148 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
149 EXPECT_GT(loop2->context().size, 0u);
150 EXPECT_EQ(nullptr, loop2->context().data);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700151 EXPECT_EQ(-1, loop2->context().buffer_index);
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800152 this->Exit();
153 });
154
155 EXPECT_FALSE(happened);
156 Run();
157 EXPECT_TRUE(happened);
158}
159
Brian Silverman454bc112020-03-05 14:21:25 -0800160// Tests that no-arg watcher can receive messages from a sender.
161// Also tests that OnRun() works.
162TEST_P(AbstractEventLoopTest, BasicNoArg) {
163 auto loop1 = Make();
164 auto loop2 = MakePrimary();
165
166 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
167
168 bool happened = false;
169
170 loop2->OnRun([&]() {
171 happened = true;
172
173 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
174 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
175 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700176 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -0800177 });
178
179 aos::Fetcher<TestMessage> fetcher = loop2->MakeFetcher<TestMessage>("/test");
180 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
181 ASSERT_TRUE(fetcher.Fetch());
182 EXPECT_EQ(fetcher->value(), 200);
183 this->Exit();
184 });
185
186 EXPECT_FALSE(happened);
187 Run();
188 EXPECT_TRUE(happened);
189}
190
191// Tests that a watcher can be created with an std::function.
192TEST_P(AbstractEventLoopTest, BasicFunction) {
193 auto loop1 = Make();
194 auto loop2 = MakePrimary();
195
196 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
197
198 bool happened = false;
199
200 loop2->OnRun([&]() {
201 happened = true;
202
203 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
204 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
205 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700206 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -0800207 });
208
209 loop2->MakeWatcher("/test", std::function<void(const TestMessage &)>(
210 [&](const TestMessage &message) {
211 EXPECT_EQ(message.value(), 200);
212 this->Exit();
213 }));
214
215 EXPECT_FALSE(happened);
216 Run();
217 EXPECT_TRUE(happened);
218}
219
Brian Silverman0fc69932020-01-24 21:54:02 -0800220// Tests that watcher can receive messages from two senders.
221// Also tests that OnRun() works.
222TEST_P(AbstractEventLoopTest, BasicTwoSenders) {
223 auto loop1 = Make();
224 auto loop2 = MakePrimary();
225
226 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
227 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
228
229 bool happened = false;
230
231 loop2->OnRun([&]() {
232 happened = true;
233
234 {
235 aos::Sender<TestMessage>::Builder msg = sender1.MakeBuilder();
236 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
237 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700238 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman0fc69932020-01-24 21:54:02 -0800239 }
240 {
241 aos::Sender<TestMessage>::Builder msg = sender2.MakeBuilder();
242 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
243 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700244 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman0fc69932020-01-24 21:54:02 -0800245 }
246 });
247
248 int messages_received = 0;
249 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
250 EXPECT_EQ(message.value(), 200);
251 this->Exit();
252 ++messages_received;
253 });
254
255 EXPECT_FALSE(happened);
256 Run();
257 EXPECT_TRUE(happened);
258 EXPECT_EQ(messages_received, 2);
259}
260
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700261// Tests that a fetcher can fetch from a sender.
262// Also tests that OnRun() works.
263TEST_P(AbstractEventLoopTest, FetchWithoutRun) {
264 auto loop1 = Make();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800265 auto loop2 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -0700266 auto loop3 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800267
268 auto sender = loop1->MakeSender<TestMessage>("/test");
269
270 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
271
Austin Schuhbbce72d2019-05-26 15:11:46 -0700272 EXPECT_FALSE(fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -0800273 EXPECT_EQ(fetcher.get(), nullptr);
274
Austin Schuhad154822019-12-27 15:45:13 -0800275 EXPECT_EQ(fetcher.context().monotonic_event_time, monotonic_clock::min_time);
276 EXPECT_EQ(fetcher.context().monotonic_remote_time, monotonic_clock::min_time);
277 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
278 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -0700279 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
Austin Schuh39788ff2019-12-01 18:22:57 -0800280 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
281 EXPECT_EQ(fetcher.context().size, 0u);
282 EXPECT_EQ(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700283 EXPECT_EQ(fetcher.context().buffer_index, -1);
Austin Schuhbbce72d2019-05-26 15:11:46 -0700284
Alex Perrycb7da4b2019-08-28 19:35:56 -0700285 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
286 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
287 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700288 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700289
290 EXPECT_TRUE(fetcher.Fetch());
291 ASSERT_FALSE(fetcher.get() == nullptr);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700292 EXPECT_EQ(fetcher.get()->value(), 200);
Austin Schuh39788ff2019-12-01 18:22:57 -0800293
294 const chrono::milliseconds kEpsilon(100);
295
Austin Schuhad154822019-12-27 15:45:13 -0800296 const aos::monotonic_clock::time_point monotonic_now = loop2->monotonic_now();
297 const aos::realtime_clock::time_point realtime_now = loop2->realtime_now();
298 EXPECT_EQ(fetcher.context().monotonic_event_time,
299 fetcher.context().monotonic_remote_time);
300 EXPECT_EQ(fetcher.context().realtime_event_time,
301 fetcher.context().realtime_remote_time);
302
303 EXPECT_GE(fetcher.context().monotonic_event_time, monotonic_now - kEpsilon);
304 EXPECT_LE(fetcher.context().monotonic_event_time, monotonic_now + kEpsilon);
305 EXPECT_GE(fetcher.context().realtime_event_time, realtime_now - kEpsilon);
306 EXPECT_LE(fetcher.context().realtime_event_time, realtime_now + kEpsilon);
Austin Schuha9012be2021-07-21 15:19:11 -0700307 EXPECT_EQ(fetcher.context().source_boot_uuid, loop2->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -0800308 EXPECT_EQ(fetcher.context().queue_index, 0x0u);
309 EXPECT_EQ(fetcher.context().size, 20u);
310 EXPECT_NE(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700311 if (read_method() == ReadMethod::PIN) {
312 EXPECT_GE(fetcher.context().buffer_index, 0);
313 EXPECT_LT(fetcher.context().buffer_index,
314 loop2->NumberBuffers(fetcher.channel()));
315 } else {
316 EXPECT_EQ(fetcher.context().buffer_index, -1);
317 }
Parker Schuhe4a70d62017-12-27 20:10:20 -0800318}
319
Austin Schuh3578a2e2019-05-25 18:17:59 -0700320// Tests that watcher will receive all messages sent if they are sent after
321// initialization and before running.
322TEST_P(AbstractEventLoopTest, DoubleSendAtStartup) {
323 auto loop1 = Make();
324 auto loop2 = MakePrimary();
325
326 auto sender = loop1->MakeSender<TestMessage>("/test");
327
328 ::std::vector<int> values;
329
330 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700331 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700332 if (values.size() == 2) {
Austin Schuh9fe68f72019-08-10 19:32:03 -0700333 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -0700334 }
335 });
336
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700337 // Before Run, should be ignored.
Austin Schuh3578a2e2019-05-25 18:17:59 -0700338 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700339 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
340 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
341 builder.add_value(199);
milind1f1dca32021-07-03 13:50:07 -0700342 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700343 }
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700344
345 loop2->OnRun([&]() {
346 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700347 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
348 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
349 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700350 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700351 }
352 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700353 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
354 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
355 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700356 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700357 }
358 });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700359
360 Run();
361
362 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
363}
364
365// Tests that watcher will not receive messages sent before the watcher is
366// created.
367TEST_P(AbstractEventLoopTest, DoubleSendAfterStartup) {
368 auto loop1 = Make();
369 auto loop2 = MakePrimary();
370
371 auto sender = loop1->MakeSender<TestMessage>("/test");
372
373 ::std::vector<int> values;
374
375 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700376 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
377 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
378 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700379 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700380 }
381 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700382 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
383 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
384 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700385 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700386 }
387
388 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700389 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700390 });
391
392 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700393 auto test_timer = loop2->AddTimer([this]() { this->Exit(); });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700394 loop2->OnRun([&test_timer, &loop2]() {
395 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
396 });
397
398 Run();
399 EXPECT_EQ(0, values.size());
400}
401
Austin Schuhbbce72d2019-05-26 15:11:46 -0700402// Tests that FetchNext gets all the messages sent after it is constructed.
403TEST_P(AbstractEventLoopTest, FetchNext) {
404 auto loop1 = Make();
405 auto loop2 = MakePrimary();
406
407 auto sender = loop1->MakeSender<TestMessage>("/test");
408 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
409
410 ::std::vector<int> values;
411
412 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700413 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
414 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
415 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700416 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700417 }
418 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700419 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
420 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
421 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700422 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700423 }
424
425 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700426 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700427 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700428 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700429 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700430 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700431 });
432
433 loop2->OnRun([&test_timer, &loop2]() {
434 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
435 });
436
437 Run();
438 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
439}
440
441// Tests that FetchNext gets no messages sent before it is constructed.
442TEST_P(AbstractEventLoopTest, FetchNextAfterSend) {
443 auto loop1 = Make();
444 auto loop2 = MakePrimary();
445
446 auto sender = loop1->MakeSender<TestMessage>("/test");
447
448 ::std::vector<int> values;
449
450 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700451 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
452 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
453 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700454 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700455 }
456 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700457 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
458 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
459 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700460 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700461 }
462
463 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
464
465 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700466 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700467 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700468 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700469 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700470 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700471 });
472
473 loop2->OnRun([&test_timer, &loop2]() {
474 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
475 });
476
477 Run();
478 EXPECT_THAT(0, values.size());
479}
480
481// Tests that Fetch returns the last message created before the loop was
482// started.
483TEST_P(AbstractEventLoopTest, FetchDataFromBeforeCreation) {
484 auto loop1 = Make();
485 auto loop2 = MakePrimary();
486
487 auto sender = loop1->MakeSender<TestMessage>("/test");
488
489 ::std::vector<int> values;
490
491 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700492 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
493 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
494 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700495 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700496 }
497 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700498 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
499 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
500 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700501 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700502 }
503
504 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
505
506 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700507 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700508 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700509 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700510 }
511 // Do it again to make sure we don't double fetch.
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 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700515 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700516 });
517
518 loop2->OnRun([&test_timer, &loop2]() {
519 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
520 });
521
522 Run();
523 EXPECT_THAT(values, ::testing::ElementsAreArray({201}));
524}
525
526// Tests that Fetch and FetchNext interleave as expected.
527TEST_P(AbstractEventLoopTest, FetchAndFetchNextTogether) {
528 auto loop1 = Make();
529 auto loop2 = MakePrimary();
530
531 auto sender = loop1->MakeSender<TestMessage>("/test");
532
533 ::std::vector<int> values;
534
535 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700536 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
537 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
538 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700539 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700540 }
541 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700542 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
543 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
544 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700545 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700546 }
547
548 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
549
550 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700551 auto test_timer = loop2->AddTimer([&fetcher, &values, &sender, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700552 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700553 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700554 }
555
556 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700557 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
558 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
559 builder.add_value(202);
milind1f1dca32021-07-03 13:50:07 -0700560 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700561 }
562 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700563 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
564 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
565 builder.add_value(203);
milind1f1dca32021-07-03 13:50:07 -0700566 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700567 }
568 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700569 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
570 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
571 builder.add_value(204);
milind1f1dca32021-07-03 13:50:07 -0700572 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700573 }
574
575 if (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700576 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700577 }
578
579 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700580 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700581 }
582
Austin Schuh9fe68f72019-08-10 19:32:03 -0700583 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700584 });
585
586 loop2->OnRun([&test_timer, &loop2]() {
587 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
588 });
589
590 Run();
591 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
592}
593
Austin Schuh3115a202019-05-27 21:02:14 -0700594// Tests that FetchNext behaves correctly when we get two messages in the queue
595// but don't consume the first until after the second has been sent.
596TEST_P(AbstractEventLoopTest, FetchNextTest) {
Austin Schuh3115a202019-05-27 21:02:14 -0700597 auto send_loop = Make();
598 auto fetch_loop = Make();
599 auto sender = send_loop->MakeSender<TestMessage>("/test");
600 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
601
602 {
Tyler Chatow67ddb032020-01-12 14:30:04 -0800603 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
604 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
605 builder.add_value(100);
milind1f1dca32021-07-03 13:50:07 -0700606 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700607 }
608
609 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700610 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
611 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
612 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700613 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700614 }
615
616 ASSERT_TRUE(fetcher.FetchNext());
617 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700618 EXPECT_EQ(100, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700619
620 ASSERT_TRUE(fetcher.FetchNext());
621 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700622 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700623
624 // When we run off the end of the queue, expect to still have the old message:
625 ASSERT_FALSE(fetcher.FetchNext());
626 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700627 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700628}
629
Brian Silverman77162972020-08-12 19:52:40 -0700630// Verify that a fetcher still holds its data, even after falling behind.
631TEST_P(AbstractEventLoopTest, FetcherBehindData) {
632 auto send_loop = Make();
633 auto fetch_loop = Make();
634 auto sender = send_loop->MakeSender<TestMessage>("/test");
635 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
636 {
637 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
638 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
639 builder.add_value(1);
milind1f1dca32021-07-03 13:50:07 -0700640 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -0700641 }
642 ASSERT_TRUE(fetcher.Fetch());
643 EXPECT_EQ(1, fetcher.get()->value());
644 for (int i = 0; i < 300; ++i) {
645 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
646 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
647 builder.add_value(i + 2);
milind1f1dca32021-07-03 13:50:07 -0700648 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -0700649 }
650 EXPECT_EQ(1, fetcher.get()->value());
651}
652
653// Try a bunch of orderings of operations with fetchers and senders. Verify that
654// all the fetchers have the correct data at each step.
655TEST_P(AbstractEventLoopTest, FetcherPermutations) {
656 for (int max_save = 0; max_save < 5; ++max_save) {
657 SCOPED_TRACE("max_save=" + std::to_string(max_save));
658
659 auto send_loop = Make();
660 auto fetch_loop = Make();
661 auto sender = send_loop->MakeSender<TestMessage>("/test");
662 const auto send_message = [&sender](int i) {
663 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
664 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
665 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700666 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -0700667 };
668 std::vector<Fetcher<TestMessage>> fetchers;
669 for (int i = 0; i < 10; ++i) {
670 fetchers.emplace_back(fetch_loop->MakeFetcher<TestMessage>("/test"));
671 }
672 send_message(1);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700673 const auto verify_buffers = [&]() {
674 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>>
675 fetchers_copy;
676 for (const auto &fetcher : fetchers) {
677 fetchers_copy.emplace_back(fetcher);
678 }
679 std::vector<std::reference_wrapper<const Sender<TestMessage>>>
680 senders_copy;
681 senders_copy.emplace_back(sender);
682 VerifyBuffers(send_loop->NumberBuffers(sender.channel()), fetchers_copy,
683 senders_copy);
684 };
Brian Silverman77162972020-08-12 19:52:40 -0700685 for (auto &fetcher : fetchers) {
686 ASSERT_TRUE(fetcher.Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -0700687 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700688 EXPECT_EQ(1, fetcher.get()->value());
689 }
690
691 for (int save = 1; save <= max_save; ++save) {
692 SCOPED_TRACE("save=" + std::to_string(save));
693 send_message(100 + save);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700694 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700695 for (size_t i = 0; i < fetchers.size() - save; ++i) {
696 SCOPED_TRACE("fetcher=" + std::to_string(i));
697 ASSERT_TRUE(fetchers[i].Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -0700698 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700699 EXPECT_EQ(100 + save, fetchers[i].get()->value());
700 }
701 for (size_t i = fetchers.size() - save; i < fetchers.size() - 1; ++i) {
702 SCOPED_TRACE("fetcher=" + std::to_string(i));
703 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
704 }
705 EXPECT_EQ(1, fetchers.back().get()->value());
706 }
707
708 for (int i = 0; i < 300; ++i) {
709 send_message(200 + i);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700710 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700711 }
712
713 for (size_t i = 0; i < fetchers.size() - max_save; ++i) {
714 SCOPED_TRACE("fetcher=" + std::to_string(i));
715 if (max_save > 0) {
716 EXPECT_EQ(100 + max_save, fetchers[i].get()->value());
717 } else {
718 EXPECT_EQ(1, fetchers[i].get()->value());
719 }
720 }
721 for (size_t i = fetchers.size() - max_save; i < fetchers.size() - 1; ++i) {
722 SCOPED_TRACE("fetcher=" + std::to_string(i));
723 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
724 }
725 EXPECT_EQ(1, fetchers.back().get()->value());
726 }
727}
728
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800729// Verify that making a fetcher and watcher for "/test" succeeds.
730TEST_P(AbstractEventLoopTest, FetcherAndWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800731 auto loop = Make();
732 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800733 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Parker Schuhe4a70d62017-12-27 20:10:20 -0800734}
735
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800736// Verify that making 2 fetchers for "/test" succeeds.
Parker Schuhe4a70d62017-12-27 20:10:20 -0800737TEST_P(AbstractEventLoopTest, TwoFetcher) {
738 auto loop = Make();
739 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800740 auto fetcher2 = loop->MakeFetcher<TestMessage>("/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -0800741}
742
Alex Perrycb7da4b2019-08-28 19:35:56 -0700743// Verify that registering a watcher for an invalid channel name dies.
744TEST_P(AbstractEventLoopDeathTest, InvalidChannelName) {
745 auto loop = Make();
746 EXPECT_DEATH(
747 { loop->MakeWatcher("/test/invalid", [&](const TestMessage &) {}); },
748 "/test/invalid");
Brian Silverman454bc112020-03-05 14:21:25 -0800749 EXPECT_DEATH(
750 { loop->MakeNoArgWatcher<TestMessage>("/test/invalid", [&]() {}); },
751 "/test/invalid");
Alex Perrycb7da4b2019-08-28 19:35:56 -0700752}
753
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800754// Verify that registering a watcher twice for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700755TEST_P(AbstractEventLoopDeathTest, TwoWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800756 auto loop = Make();
757 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800758 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
759 "/test");
Brian Silverman454bc112020-03-05 14:21:25 -0800760 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
761}
762
763// Verify that registering a no-arg watcher twice for "/test" fails.
764TEST_P(AbstractEventLoopDeathTest, TwoNoArgWatcher) {
765 auto loop = Make();
766 loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {});
767 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
768 "/test");
769 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800770}
771
Austin Schuh3115a202019-05-27 21:02:14 -0700772// Verify that SetRuntimeRealtimePriority fails while running.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700773TEST_P(AbstractEventLoopDeathTest, SetRuntimeRealtimePriority) {
Austin Schuh3115a202019-05-27 21:02:14 -0700774 auto loop = MakePrimary();
775 // Confirm that runtime priority calls work when not realtime.
776 loop->SetRuntimeRealtimePriority(5);
777
778 loop->OnRun([&]() { loop->SetRuntimeRealtimePriority(5); });
779
780 EXPECT_DEATH(Run(), "realtime");
781}
782
Brian Silverman6a54ff32020-04-28 16:41:39 -0700783// Verify that SetRuntimeAffinity fails while running.
784TEST_P(AbstractEventLoopDeathTest, SetRuntimeAffinity) {
Austin Schuhde973292021-10-12 18:09:49 -0700785 const cpu_set_t available = GetCurrentThreadAffinity();
786 int first_cpu = -1;
787 for (int i = 0; i < CPU_SETSIZE; ++i) {
788 if (CPU_ISSET(i, &available)) {
789 first_cpu = i;
790 break;
791 continue;
792 }
793 }
794 CHECK_NE(first_cpu, -1) << ": Default affinity has no CPUs?";
795
Brian Silverman6a54ff32020-04-28 16:41:39 -0700796 auto loop = MakePrimary();
797 // Confirm that runtime priority calls work when not running.
Austin Schuhde973292021-10-12 18:09:49 -0700798 loop->SetRuntimeAffinity(MakeCpusetFromCpus({first_cpu}));
Brian Silverman6a54ff32020-04-28 16:41:39 -0700799
Austin Schuhde973292021-10-12 18:09:49 -0700800 loop->OnRun(
801 [&]() { loop->SetRuntimeAffinity(MakeCpusetFromCpus({first_cpu})); });
Brian Silverman6a54ff32020-04-28 16:41:39 -0700802
803 EXPECT_DEATH(Run(), "Cannot set affinity while running");
804}
805
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800806// Verify that registering a watcher and a sender for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700807TEST_P(AbstractEventLoopDeathTest, WatcherAndSender) {
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800808 auto loop = Make();
809 auto sender = loop->MakeSender<TestMessage>("/test");
810 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
811 "/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -0800812}
813
Austin Schuhe516ab02020-05-06 21:37:04 -0700814// Verify that creating too many senders fails.
815TEST_P(AbstractEventLoopDeathTest, TooManySenders) {
816 auto loop = Make();
817 std::vector<aos::Sender<TestMessage>> senders;
818 for (int i = 0; i < 10; ++i) {
819 senders.emplace_back(loop->MakeSender<TestMessage>("/test"));
820 }
821 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); },
822 "Failed to create sender on \\{ \"name\": \"/test\", \"type\": "
Brian Silverman77162972020-08-12 19:52:40 -0700823 "\"aos.TestMessage\"[^}]*\\ }, too many senders.");
824}
825
826// Verify that creating too many fetchers fails.
827TEST_P(AbstractEventLoopDeathTest, TooManyFetchers) {
828 if (read_method() != ReadMethod::PIN) {
829 // Other read methods don't limit the number of readers, so just skip this.
830 return;
831 }
832
833 auto loop = Make();
834 std::vector<aos::Fetcher<TestMessage>> fetchers;
835 for (int i = 0; i < 10; ++i) {
836 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
837 }
838 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
839 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
840 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
841}
842
843// Verify that creating too many fetchers, split between two event loops, fails.
844TEST_P(AbstractEventLoopDeathTest, TooManyFetchersTwoLoops) {
845 if (read_method() != ReadMethod::PIN) {
846 // Other read methods don't limit the number of readers, so just skip this.
847 return;
848 }
849
850 auto loop = Make();
851 auto loop2 = Make();
852 std::vector<aos::Fetcher<TestMessage>> fetchers;
853 for (int i = 0; i < 5; ++i) {
854 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
855 fetchers.emplace_back(loop2->MakeFetcher<TestMessage>("/test"));
856 }
857 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
858 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
859 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
860}
861
862// Verify that creating too many watchers fails.
863TEST_P(AbstractEventLoopDeathTest, TooManyWatchers) {
864 if (read_method() != ReadMethod::PIN) {
865 // Other read methods don't limit the number of readers, so just skip this.
866 return;
867 }
868
869 std::vector<std::unique_ptr<EventLoop>> loops;
870 for (int i = 0; i < 10; ++i) {
871 loops.emplace_back(Make());
872 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
873 }
874 EXPECT_DEATH({ Make()->MakeWatcher("/test", [](const TestMessage &) {}); },
875 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
876 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
877}
878
879// Verify that creating too many watchers and fetchers combined fails.
880TEST_P(AbstractEventLoopDeathTest, TooManyWatchersAndFetchers) {
881 if (read_method() != ReadMethod::PIN) {
882 // Other read methods don't limit the number of readers, so just skip this.
883 return;
884 }
885
886 auto loop = Make();
887 std::vector<aos::Fetcher<TestMessage>> fetchers;
888 std::vector<std::unique_ptr<EventLoop>> loops;
889 for (int i = 0; i < 5; ++i) {
890 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
891 loops.emplace_back(Make());
892 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
893 }
894 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
895 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
896 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
Austin Schuhe516ab02020-05-06 21:37:04 -0700897}
898
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700899// Verify that we can't create a sender inside OnRun.
900TEST_P(AbstractEventLoopDeathTest, SenderInOnRun) {
901 auto loop1 = MakePrimary();
902
903 loop1->OnRun(
904 [&]() { auto sender = loop1->MakeSender<TestMessage>("/test2"); });
905
906 EXPECT_DEATH(Run(), "running");
907}
908
909// Verify that we can't create a watcher inside OnRun.
910TEST_P(AbstractEventLoopDeathTest, WatcherInOnRun) {
911 auto loop1 = MakePrimary();
912
913 loop1->OnRun(
914 [&]() { loop1->MakeWatcher("/test", [&](const TestMessage &) {}); });
915
916 EXPECT_DEATH(Run(), "running");
917}
918
Brian Silverman454bc112020-03-05 14:21:25 -0800919// Verify that we can't create a no-arg watcher inside OnRun.
920TEST_P(AbstractEventLoopDeathTest, NoArgWatcherInOnRun) {
921 auto loop1 = MakePrimary();
922
923 loop1->OnRun(
924 [&]() { loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {}); });
925
926 EXPECT_DEATH(Run(), "running");
927}
928
Parker Schuhe4a70d62017-12-27 20:10:20 -0800929// Verify that Quit() works when there are multiple watchers.
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800930TEST_P(AbstractEventLoopTest, MultipleWatcherQuit) {
931 auto loop1 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -0700932 auto loop2 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800933
Austin Schuh3578a2e2019-05-25 18:17:59 -0700934 loop2->MakeWatcher("/test1", [&](const TestMessage &) {});
935 loop2->MakeWatcher("/test2", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700936 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -0700937 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -0700938 });
939
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800940 auto sender = loop1->MakeSender<TestMessage>("/test2");
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700941
942 loop2->OnRun([&]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700943 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
944 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
945 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700946 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700947 });
Parker Schuhe4a70d62017-12-27 20:10:20 -0800948
Austin Schuh44019f92019-05-19 19:58:27 -0700949 Run();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800950}
951
Austin Schuhad9e5eb2021-11-19 20:33:55 -0800952// Verify that AOS_LOG has the right name.
953TEST_P(AbstractEventLoopTest, AOSLog) {
954 auto loop2 = MakePrimary("loop1");
955 auto loop1 = Make("loop0");
956
957 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
958
959 EXPECT_FALSE(fetcher.Fetch());
960
961 loop2->OnRun([&]() {
962 AOS_LOG(INFO, "Testing123");
963 this->Exit();
964 });
965
966 Run();
967 EXPECT_TRUE(fetcher.Fetch());
968 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
969}
970
971// Verify that AOS_LOG has the right name in a watcher.
972TEST_P(AbstractEventLoopTest, AOSLogWatcher) {
973 auto loop2 = MakePrimary("loop1");
974 auto loop1 = Make("loop0");
975
976 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
977
978 EXPECT_FALSE(fetcher.Fetch());
979
980 auto sender = loop1->MakeSender<TestMessage>("/test2");
981
982 loop2->MakeWatcher("/test2", [&](const TestMessage & /*message*/) {
983 AOS_LOG(INFO, "Testing123");
984 this->Exit();
985 });
986
987 loop2->OnRun([&]() {
988 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
989 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
990 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700991 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhad9e5eb2021-11-19 20:33:55 -0800992 });
993
994 Run();
995 EXPECT_TRUE(fetcher.Fetch());
996 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
997}
998
999// Verify that AOS_LOG has the right name in a timer.
1000TEST_P(AbstractEventLoopTest, AOSLogTimer) {
1001 auto loop2 = MakePrimary("loop1");
1002 auto loop1 = Make("loop0");
1003
1004 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1005
1006 EXPECT_FALSE(fetcher.Fetch());
1007
1008 auto test_timer = loop2->AddTimer([&]() {
1009 AOS_LOG(INFO, "Testing123");
1010 this->Exit();
1011 });
1012
1013 loop2->OnRun([&]() { test_timer->Setup(loop2->monotonic_now()); });
1014
1015 Run();
1016 EXPECT_TRUE(fetcher.Fetch());
1017 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1018}
1019
Neil Balch229001a2018-01-07 18:22:52 -08001020// Verify that timer intervals and duration function properly.
1021TEST_P(AbstractEventLoopTest, TimerIntervalAndDuration) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001022 // Force a slower rate so we are guaranteed to have reports for our timer.
Austin Schuh39788ff2019-12-01 18:22:57 -08001023 FLAGS_timing_report_ms = 2000;
1024
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001025 const int kCount = 5;
Neil Balch229001a2018-01-07 18:22:52 -08001026
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001027 auto loop = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001028 auto loop2 = Make();
1029
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001030 ::std::vector<::aos::monotonic_clock::time_point> times;
1031 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
1032
Austin Schuh39788ff2019-12-01 18:22:57 -08001033 Fetcher<timing::Report> report_fetcher =
1034 loop2->MakeFetcher<timing::Report>("/aos");
1035 EXPECT_FALSE(report_fetcher.Fetch());
1036
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001037 auto test_timer = loop->AddTimer([this, &times, &expected_times, &loop]() {
1038 times.push_back(loop->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001039 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
1040 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
1041 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001042 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -08001043 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
1044 EXPECT_EQ(loop->context().size, 0u);
1045 EXPECT_EQ(loop->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001046 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001047
Austin Schuhad154822019-12-27 15:45:13 -08001048 expected_times.push_back(loop->context().monotonic_event_time);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001049 if (times.size() == kCount) {
1050 this->Exit();
1051 }
Neil Balch229001a2018-01-07 18:22:52 -08001052 });
Austin Schuh39788ff2019-12-01 18:22:57 -08001053 test_timer->set_name("Test loop");
Neil Balch229001a2018-01-07 18:22:52 -08001054
Austin Schuh39788ff2019-12-01 18:22:57 -08001055 const monotonic_clock::time_point start_time = loop->monotonic_now();
Austin Schuh52d325c2019-06-23 18:59:06 -07001056 // TODO(austin): This should be an error... Should be done in OnRun only.
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001057 test_timer->Setup(start_time + chrono::seconds(1), chrono::seconds(1));
1058
Austin Schuh44019f92019-05-19 19:58:27 -07001059 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001060
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001061 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001062 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
1063 ASSERT_EQ(times.size(), expected_times.size());
1064 ASSERT_EQ((times.size() % 2), 1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001065
1066 // Grab the middle sample.
1067 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
1068
1069 // Add up all the delays of all the times.
1070 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1071 for (const ::aos::monotonic_clock::time_point time : times) {
1072 sum += time - average_time;
1073 }
1074
1075 // Average and add to the middle to find the average time.
1076 sum /= times.size();
1077 average_time += sum;
1078
1079 // Compute the offset from the average and the expected average. It
1080 // should be pretty close to 0.
1081 const ::aos::monotonic_clock::duration remainder =
1082 average_time - start_time - chrono::seconds(times.size() / 2 + 1);
1083
1084 const chrono::milliseconds kEpsilon(100);
1085 EXPECT_LT(remainder, +kEpsilon);
1086 EXPECT_GT(remainder, -kEpsilon);
1087
1088 // Make sure that the average duration is close to 1 second.
1089 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1090 times.front())
1091 .count() /
1092 static_cast<double>(times.size() - 1),
1093 1.0, 0.1);
1094
1095 // Confirm that the ideal wakeup times increment correctly.
1096 for (size_t i = 1; i < expected_times.size(); ++i) {
1097 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1098 }
1099
1100 for (size_t i = 0; i < expected_times.size(); ++i) {
1101 EXPECT_EQ((expected_times[i] - start_time) % chrono::seconds(1),
1102 chrono::seconds(0));
1103 }
1104
1105 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1106 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001107
Austin Schuh6bae8252021-02-07 22:01:49 -08001108 if (do_timing_reports() == DoTimingReports::kYes) {
1109 // And, since we are here, check that the timing report makes sense.
1110 // Start by looking for our event loop's timing.
1111 FlatbufferDetachedBuffer<timing::Report> report =
1112 FlatbufferDetachedBuffer<timing::Report>::Empty();
1113 while (report_fetcher.FetchNext()) {
1114 if (report_fetcher->name()->string_view() == "primary") {
1115 report = CopyFlatBuffer(report_fetcher.get());
1116 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001117 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001118
1119 // Confirm that we have the right number of reports, and the contents are
1120 // sane.
1121 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
1122
1123 EXPECT_EQ(report.message().name()->string_view(), "primary");
1124
1125 ASSERT_NE(report.message().senders(), nullptr);
1126 EXPECT_EQ(report.message().senders()->size(), 2);
1127
1128 ASSERT_NE(report.message().timers(), nullptr);
1129 EXPECT_EQ(report.message().timers()->size(), 2);
1130
1131 EXPECT_EQ(report.message().timers()->Get(0)->name()->string_view(),
1132 "Test loop");
1133 EXPECT_GE(report.message().timers()->Get(0)->count(), 1);
1134
1135 EXPECT_EQ(report.message().timers()->Get(1)->name()->string_view(),
1136 "timing_reports");
1137 EXPECT_EQ(report.message().timers()->Get(1)->count(), 1);
1138
1139 // Make sure there is a single phased loop report with our report in it.
1140 ASSERT_EQ(report.message().phased_loops(), nullptr);
1141 } else {
1142 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001143 }
Neil Balch229001a2018-01-07 18:22:52 -08001144}
1145
1146// Verify that we can change a timer's parameters during execution.
1147TEST_P(AbstractEventLoopTest, TimerChangeParameters) {
Austin Schuh44019f92019-05-19 19:58:27 -07001148 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001149 loop->SetRuntimeRealtimePriority(1);
Austin Schuh7f20f512021-01-31 17:56:16 -08001150 std::vector<monotonic_clock::time_point> iteration_list;
Neil Balch229001a2018-01-07 18:22:52 -08001151
1152 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh7f20f512021-01-31 17:56:16 -08001153 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001154 });
1155
Austin Schuh7f20f512021-01-31 17:56:16 -08001156 monotonic_clock::time_point s;
1157 auto modifier_timer = loop->AddTimer([&test_timer, &s]() {
Austin Schuhd892f102021-10-12 18:01:46 -07001158 test_timer->Setup(s + chrono::milliseconds(1750),
1159 chrono::milliseconds(600));
Neil Balch229001a2018-01-07 18:22:52 -08001160 });
1161
Austin Schuh7f20f512021-01-31 17:56:16 -08001162 s = loop->monotonic_now();
Austin Schuhd892f102021-10-12 18:01:46 -07001163 test_timer->Setup(s, chrono::milliseconds(500));
1164 modifier_timer->Setup(s + chrono::milliseconds(1250));
1165 EndEventLoop(loop.get(), chrono::milliseconds(3950));
Austin Schuh44019f92019-05-19 19:58:27 -07001166 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001167
Austin Schuhd892f102021-10-12 18:01:46 -07001168 EXPECT_THAT(
1169 iteration_list,
1170 ::testing::ElementsAre(
1171 s, s + chrono::milliseconds(500), s + chrono::milliseconds(1000),
1172 s + chrono::milliseconds(1750), s + chrono::milliseconds(2350),
1173 s + chrono::milliseconds(2950), s + chrono::milliseconds(3550)));
Neil Balch229001a2018-01-07 18:22:52 -08001174}
1175
1176// Verify that we can disable a timer during execution.
1177TEST_P(AbstractEventLoopTest, TimerDisable) {
Austin Schuh44019f92019-05-19 19:58:27 -07001178 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001179 loop->SetRuntimeRealtimePriority(1);
Neil Balch229001a2018-01-07 18:22:52 -08001180 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
1181
1182 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuhd892f102021-10-12 18:01:46 -07001183 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001184 });
1185
Tyler Chatow67ddb032020-01-12 14:30:04 -08001186 auto ender_timer = loop->AddTimer([&test_timer]() { test_timer->Disable(); });
Neil Balch229001a2018-01-07 18:22:52 -08001187
Austin Schuhd892f102021-10-12 18:01:46 -07001188 monotonic_clock::time_point s = loop->monotonic_now();
1189 test_timer->Setup(s, ::std::chrono::milliseconds(70));
1190 ender_timer->Setup(s + ::std::chrono::milliseconds(200));
1191 EndEventLoop(loop.get(), ::std::chrono::milliseconds(350));
Austin Schuh44019f92019-05-19 19:58:27 -07001192 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001193
Austin Schuhd892f102021-10-12 18:01:46 -07001194 EXPECT_THAT(iteration_list,
1195 ::testing::ElementsAre(s, s + chrono::milliseconds(70),
1196 s + chrono::milliseconds(140)));
Neil Balch229001a2018-01-07 18:22:52 -08001197}
Austin Schuh7267c532019-05-19 19:55:53 -07001198
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001199// Verify that a timer can disable itself.
1200//
1201// TODO(Brian): Do something similar with phased loops, both with a quick
1202// handler and a handler that would miss a cycle except it got deferred. Current
1203// behavior doing that is a mess.
1204TEST_P(AbstractEventLoopTest, TimerDisableSelf) {
1205 auto loop = MakePrimary();
1206
1207 int count = 0;
1208 aos::TimerHandler *test_timer;
1209 test_timer = loop->AddTimer([&count, &test_timer]() {
1210 ++count;
1211 test_timer->Disable();
1212 });
1213
1214 test_timer->Setup(loop->monotonic_now(), ::std::chrono::milliseconds(20));
1215 EndEventLoop(loop.get(), ::std::chrono::milliseconds(80));
1216 Run();
1217
1218 EXPECT_EQ(count, 1);
1219}
1220
Brian Silvermanbd405c02020-06-23 16:25:23 -07001221// Verify that we can disable a timer during execution of another timer
1222// scheduled for the same time, with one ordering of creation for the timers.
1223//
1224// Also schedule some more events to reshuffle the heap in EventLoop used for
1225// tracking events to change up the order. This used to segfault
1226// SimulatedEventLoop.
1227TEST_P(AbstractEventLoopTest, TimerDisableOther) {
1228 for (bool creation_order : {true, false}) {
1229 for (bool setup_order : {true, false}) {
1230 for (int shuffle_events = 0; shuffle_events < 5; ++shuffle_events) {
1231 auto loop = MakePrimary();
1232 aos::TimerHandler *test_timer, *ender_timer;
1233 if (creation_order) {
1234 test_timer = loop->AddTimer([]() {});
1235 ender_timer =
1236 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1237 } else {
1238 ender_timer =
1239 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1240 test_timer = loop->AddTimer([]() {});
1241 }
1242
1243 const auto start = loop->monotonic_now();
1244
1245 for (int i = 0; i < shuffle_events; ++i) {
1246 loop->AddTimer([]() {})->Setup(start + std::chrono::milliseconds(10));
1247 }
1248
1249 if (setup_order) {
1250 test_timer->Setup(start + ::std::chrono::milliseconds(20));
1251 ender_timer->Setup(start + ::std::chrono::milliseconds(20));
1252 } else {
1253 ender_timer->Setup(start + ::std::chrono::milliseconds(20));
1254 test_timer->Setup(start + ::std::chrono::milliseconds(20));
1255 }
1256 EndEventLoop(loop.get(), ::std::chrono::milliseconds(40));
1257 Run();
1258 }
1259 }
1260 }
1261}
1262
Austin Schuh54cf95f2019-11-29 13:14:18 -08001263// Verifies that the event loop implementations detect when Channel is not a
Brian Silverman631b6262021-11-10 12:25:08 -08001264// pointer into configuration(), or a name doesn't map to a channel in
1265// configuration().
Austin Schuh54cf95f2019-11-29 13:14:18 -08001266TEST_P(AbstractEventLoopDeathTest, InvalidChannel) {
1267 auto loop = MakePrimary();
1268
Tyler Chatow67ddb032020-01-12 14:30:04 -08001269 const Channel *channel = configuration::GetChannel(
1270 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
Austin Schuh54cf95f2019-11-29 13:14:18 -08001271
1272 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1273
1274 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001275 loop->MakeRawSender(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001276 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1277
1278 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001279 loop->MakeSender<TestMessage>("/testbad"),
1280 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1281 " not found in config");
1282
1283 EXPECT_FALSE(loop->TryMakeSender<TestMessage>("/testbad"));
1284
1285 EXPECT_DEATH(
1286 loop->MakeRawFetcher(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001287 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1288
1289 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001290 loop->MakeFetcher<TestMessage>("/testbad"),
1291 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1292 " not found in config");
1293
1294 EXPECT_FALSE(loop->TryMakeFetcher<TestMessage>("/testbad").valid());
1295
1296 EXPECT_DEATH(
Austin Schuh54cf95f2019-11-29 13:14:18 -08001297 {
1298 loop->MakeRawWatcher(&channel_copy.message(),
1299 [](const Context, const void *) {});
1300 },
1301 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
Brian Silverman631b6262021-11-10 12:25:08 -08001302
1303 EXPECT_DEATH(
1304 { loop->MakeWatcher("/testbad", [](const TestMessage &) {}); },
1305 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1306 " not found in config");
1307}
1308
1309// Verifies that the event loop handles a channel which is not readable or
1310// writable on the current node nicely.
1311TEST_P(AbstractEventLoopDeathTest, InaccessibleChannel) {
1312 EnableNodes("me");
1313 auto loop = MakePrimary("me");
1314 auto loop2 = Make("them");
1315
1316 const Channel *channel = configuration::GetChannel(
1317 loop->configuration(), "/test_noforward", "aos.TestMessage", "", nullptr);
1318
1319 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1320
1321 EXPECT_DEATH(
1322 loop2->MakeSender<TestMessage>("/test_forward"),
1323 "Channel"
1324 " \\{ \"name\": \"/test_forward\", \"type\": \"aos.TestMessage\" \\}"
1325 " is not able to be sent on this node");
1326
1327 EXPECT_FALSE(loop2->TryMakeSender<TestMessage>("/test_forward"));
1328
1329 EXPECT_DEATH(
1330 loop2->MakeRawFetcher(channel),
1331 "Channel"
1332 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1333 " is not able to be fetched on this node");
1334
1335 EXPECT_DEATH(
1336 loop2->MakeFetcher<TestMessage>("/test_noforward"),
1337 "Channel"
1338 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1339 " is not able to be fetched on this node");
1340
1341 EXPECT_FALSE(loop2->TryMakeFetcher<TestMessage>("/test_noforward").valid());
1342
1343 EXPECT_DEATH(
1344 { loop2->MakeRawWatcher(channel, [](const Context, const void *) {}); },
1345 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1346 "\"source_node\": \"them\" \\}"
1347 " is not able to be watched on this node");
1348
1349 EXPECT_DEATH(
1350 { loop2->MakeWatcher("/test_noforward", [](const TestMessage &) {}); },
1351 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1352 "\"source_node\": \"them\" \\}"
1353 " is not able to be watched on this node");
Austin Schuh54cf95f2019-11-29 13:14:18 -08001354}
1355
Austin Schuhd54780b2020-10-03 16:26:02 -07001356// Verifies that the event loop implementations detect when Channel has an
1357// invalid alignment.
1358TEST_P(AbstractEventLoopDeathTest, InvalidChannelAlignment) {
1359 const char *const kError = "multiple of alignment";
1360 InvalidChannelAlignment();
1361
1362 auto loop = MakePrimary();
1363
1364 const Channel *channel = configuration::GetChannel(
1365 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
1366
1367 EXPECT_DEATH({ loop->MakeRawSender(channel); }, kError);
1368 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); }, kError);
1369
1370 EXPECT_DEATH({ loop->MakeRawFetcher(channel); }, kError);
1371 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); }, kError);
1372
1373 EXPECT_DEATH(
1374 { loop->MakeRawWatcher(channel, [](const Context &, const void *) {}); },
1375 kError);
1376 EXPECT_DEATH({ loop->MakeRawNoArgWatcher(channel, [](const Context &) {}); },
1377 kError);
1378
1379 EXPECT_DEATH({ loop->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
1380 kError);
1381 EXPECT_DEATH({ loop->MakeWatcher("/test", [](const TestMessage &) {}); },
1382 kError);
1383}
1384
Brian Silverman454bc112020-03-05 14:21:25 -08001385// Verify that the send time on a message is roughly right when using a watcher.
Austin Schuh7267c532019-05-19 19:55:53 -07001386TEST_P(AbstractEventLoopTest, MessageSendTime) {
Austin Schuh44019f92019-05-19 19:58:27 -07001387 auto loop1 = MakePrimary();
Austin Schuh7267c532019-05-19 19:55:53 -07001388 auto loop2 = Make();
Austin Schuhad154822019-12-27 15:45:13 -08001389 auto sender = loop2->MakeSender<TestMessage>("/test");
Austin Schuh7267c532019-05-19 19:55:53 -07001390 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
1391
1392 auto test_timer = loop1->AddTimer([&sender]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001393 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1394 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1395 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001396 msg.CheckOk(msg.Send(builder.Finish()));
Alex Perrycb7da4b2019-08-28 19:35:56 -07001397 });
1398
Austin Schuhad154822019-12-27 15:45:13 -08001399 bool triggered = false;
Brian Silverman454bc112020-03-05 14:21:25 -08001400 loop1->MakeWatcher("/test", [&](const TestMessage &msg) {
Austin Schuhad154822019-12-27 15:45:13 -08001401 // Confirm that the data pointer makes sense from a watcher, and all the
1402 // timestamps look right.
1403 EXPECT_GT(&msg, loop1->context().data);
1404 EXPECT_EQ(loop1->context().monotonic_remote_time,
1405 loop1->context().monotonic_event_time);
1406 EXPECT_EQ(loop1->context().realtime_remote_time,
1407 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001408 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001409
1410 const aos::monotonic_clock::time_point monotonic_now =
1411 loop1->monotonic_now();
Tyler Chatow67ddb032020-01-12 14:30:04 -08001412 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08001413
1414 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1415 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1416 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1417 monotonic_now);
1418 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1419 realtime_now);
1420
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001421 EXPECT_LT(&msg, reinterpret_cast<const void *>(
1422 reinterpret_cast<const char *>(loop1->context().data) +
Austin Schuhad154822019-12-27 15:45:13 -08001423 loop1->context().size));
Brian Silverman4f4e0612020-08-12 19:54:41 -07001424 if (read_method() == ReadMethod::PIN) {
1425 EXPECT_GE(loop1->context().buffer_index, 0);
1426 EXPECT_LT(loop1->context().buffer_index,
1427 loop1->NumberBuffers(
1428 configuration::GetChannel(loop1->configuration(), "/test",
1429 "aos.TestMessage", "", nullptr)));
1430 } else {
1431 EXPECT_EQ(-1, loop1->context().buffer_index);
1432 }
Austin Schuhad154822019-12-27 15:45:13 -08001433 triggered = true;
Austin Schuh7267c532019-05-19 19:55:53 -07001434 });
1435
1436 test_timer->Setup(loop1->monotonic_now() + ::std::chrono::seconds(1));
1437
1438 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
Austin Schuh44019f92019-05-19 19:58:27 -07001439 Run();
Austin Schuh7267c532019-05-19 19:55:53 -07001440
Austin Schuhad154822019-12-27 15:45:13 -08001441 EXPECT_TRUE(triggered);
1442
Brian Silverman454bc112020-03-05 14:21:25 -08001443 ASSERT_TRUE(fetcher.Fetch());
1444
1445 monotonic_clock::duration monotonic_time_offset =
1446 fetcher.context().monotonic_event_time -
1447 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1448 realtime_clock::duration realtime_time_offset =
1449 fetcher.context().realtime_event_time -
1450 (loop1->realtime_now() - ::std::chrono::seconds(1));
1451
1452 EXPECT_EQ(fetcher.context().realtime_event_time,
1453 fetcher.context().realtime_remote_time);
1454 EXPECT_EQ(fetcher.context().monotonic_event_time,
1455 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001456 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001457
1458 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1459 << ": Got "
1460 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1461 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1462 // Confirm that the data pointer makes sense.
1463 EXPECT_GT(fetcher.get(), fetcher.context().data);
1464 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001465 reinterpret_cast<const void *>(
1466 reinterpret_cast<const char *>(fetcher.context().data) +
Brian Silverman454bc112020-03-05 14:21:25 -08001467 fetcher.context().size));
1468 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1469 << ": Got "
1470 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1471 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1472
1473 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1474 << ": Got "
1475 << fetcher.context().realtime_event_time.time_since_epoch().count()
1476 << " expected " << loop1->realtime_now().time_since_epoch().count();
1477 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1478 << ": Got "
1479 << fetcher.context().realtime_event_time.time_since_epoch().count()
1480 << " expected " << loop1->realtime_now().time_since_epoch().count();
1481}
1482
1483// Verify that the send time on a message is roughly right when using a no-arg
1484// watcher. To get a message, we need to use a fetcher to actually access the
1485// message. This is also the main use case for no-arg fetchers.
1486TEST_P(AbstractEventLoopTest, MessageSendTimeNoArg) {
1487 auto loop1 = MakePrimary();
1488 auto loop2 = Make();
1489 auto sender = loop2->MakeSender<TestMessage>("/test");
1490 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
1491
1492 auto test_timer = loop1->AddTimer([&sender]() {
1493 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1494 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1495 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001496 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -08001497 });
1498
1499 bool triggered = false;
1500 loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {
1501 // Confirm that we can indeed use a fetcher on this channel from this
1502 // context, and it results in a sane data pointer and timestamps.
1503 ASSERT_TRUE(fetcher.Fetch());
1504
1505 EXPECT_EQ(loop1->context().monotonic_remote_time,
1506 loop1->context().monotonic_event_time);
1507 EXPECT_EQ(loop1->context().realtime_remote_time,
1508 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001509 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001510
1511 const aos::monotonic_clock::time_point monotonic_now =
1512 loop1->monotonic_now();
1513 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
1514
1515 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1516 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1517 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1518 monotonic_now);
1519 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1520 realtime_now);
1521
1522 triggered = true;
1523 });
1524
1525 test_timer->Setup(loop1->monotonic_now() + ::std::chrono::seconds(1));
1526
1527 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
1528 Run();
1529
1530 ASSERT_TRUE(triggered);
Austin Schuh7267c532019-05-19 19:55:53 -07001531
Alex Perrycb7da4b2019-08-28 19:35:56 -07001532 monotonic_clock::duration monotonic_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001533 fetcher.context().monotonic_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001534 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1535 realtime_clock::duration realtime_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001536 fetcher.context().realtime_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001537 (loop1->realtime_now() - ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07001538
Austin Schuhad154822019-12-27 15:45:13 -08001539 EXPECT_EQ(fetcher.context().realtime_event_time,
1540 fetcher.context().realtime_remote_time);
1541 EXPECT_EQ(fetcher.context().monotonic_event_time,
1542 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001543 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001544
Alex Perrycb7da4b2019-08-28 19:35:56 -07001545 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1546 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001547 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh52d325c2019-06-23 18:59:06 -07001548 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07001549 // Confirm that the data pointer makes sense.
1550 EXPECT_GT(fetcher.get(), fetcher.context().data);
1551 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001552 reinterpret_cast<const void *>(
1553 reinterpret_cast<const char *>(fetcher.context().data) +
Alex Perrycb7da4b2019-08-28 19:35:56 -07001554 fetcher.context().size));
1555 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1556 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001557 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh7267c532019-05-19 19:55:53 -07001558 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07001559
1560 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1561 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001562 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07001563 << " expected " << loop1->realtime_now().time_since_epoch().count();
1564 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1565 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001566 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07001567 << " expected " << loop1->realtime_now().time_since_epoch().count();
Austin Schuh7267c532019-05-19 19:55:53 -07001568}
1569
Austin Schuh52d325c2019-06-23 18:59:06 -07001570// Tests that a couple phased loops run in a row result in the correct offset
1571// and period.
1572TEST_P(AbstractEventLoopTest, PhasedLoopTest) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001573 // Force a slower rate so we are guaranteed to have reports for our phased
Austin Schuh39788ff2019-12-01 18:22:57 -08001574 // loop.
1575 FLAGS_timing_report_ms = 2000;
1576
Austin Schuh52d325c2019-06-23 18:59:06 -07001577 const chrono::milliseconds kOffset = chrono::milliseconds(400);
1578 const int kCount = 5;
1579
1580 auto loop1 = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001581 auto loop2 = Make();
1582
1583 Fetcher<timing::Report> report_fetcher =
1584 loop2->MakeFetcher<timing::Report>("/aos");
1585 EXPECT_FALSE(report_fetcher.Fetch());
Austin Schuh52d325c2019-06-23 18:59:06 -07001586
1587 // Collect up a couple of samples.
1588 ::std::vector<::aos::monotonic_clock::time_point> times;
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001589 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
Austin Schuh52d325c2019-06-23 18:59:06 -07001590
1591 // Run kCount iterations.
Austin Schuh39788ff2019-12-01 18:22:57 -08001592 loop1
1593 ->AddPhasedLoop(
1594 [&times, &expected_times, &loop1, this](int count) {
1595 EXPECT_EQ(count, 1);
1596 times.push_back(loop1->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001597 expected_times.push_back(loop1->context().monotonic_event_time);
Austin Schuh39788ff2019-12-01 18:22:57 -08001598
Austin Schuhad154822019-12-27 15:45:13 -08001599 EXPECT_EQ(loop1->context().monotonic_remote_time,
1600 monotonic_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001601 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001602 EXPECT_EQ(loop1->context().realtime_event_time,
1603 realtime_clock::min_time);
1604 EXPECT_EQ(loop1->context().realtime_remote_time,
Austin Schuh39788ff2019-12-01 18:22:57 -08001605 realtime_clock::min_time);
1606 EXPECT_EQ(loop1->context().queue_index, 0xffffffffu);
1607 EXPECT_EQ(loop1->context().size, 0u);
1608 EXPECT_EQ(loop1->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001609 EXPECT_EQ(loop1->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001610
1611 if (times.size() == kCount) {
1612 LOG(INFO) << "Exiting";
1613 this->Exit();
1614 }
1615 },
1616 chrono::seconds(1), kOffset)
1617 ->set_name("Test loop");
Austin Schuh52d325c2019-06-23 18:59:06 -07001618
1619 // Add a delay to make sure that delay during startup doesn't result in a
1620 // "missed cycle".
1621 SleepFor(chrono::seconds(2));
1622
1623 Run();
1624
1625 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001626 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
1627 ASSERT_EQ(times.size(), expected_times.size());
1628 ASSERT_EQ((times.size() % 2), 1);
Austin Schuh52d325c2019-06-23 18:59:06 -07001629
1630 // Grab the middle sample.
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001631 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
Austin Schuh52d325c2019-06-23 18:59:06 -07001632
1633 // Add up all the delays of all the times.
1634 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1635 for (const ::aos::monotonic_clock::time_point time : times) {
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001636 sum += time - average_time;
Austin Schuh52d325c2019-06-23 18:59:06 -07001637 }
1638
1639 // Average and add to the middle to find the average time.
1640 sum /= times.size();
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001641 average_time += sum;
Austin Schuh52d325c2019-06-23 18:59:06 -07001642
1643 // Compute the offset from the start of the second of the average time. This
1644 // should be pretty close to the offset.
1645 const ::aos::monotonic_clock::duration remainder =
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001646 average_time.time_since_epoch() -
1647 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
Austin Schuh52d325c2019-06-23 18:59:06 -07001648
1649 const chrono::milliseconds kEpsilon(100);
1650 EXPECT_LT(remainder, kOffset + kEpsilon);
1651 EXPECT_GT(remainder, kOffset - kEpsilon);
1652
1653 // Make sure that the average duration is close to 1 second.
1654 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1655 times.front())
1656 .count() /
1657 static_cast<double>(times.size() - 1),
1658 1.0, 0.1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001659
1660 // Confirm that the ideal wakeup times increment correctly.
1661 for (size_t i = 1; i < expected_times.size(); ++i) {
1662 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1663 }
1664
1665 for (size_t i = 0; i < expected_times.size(); ++i) {
1666 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
1667 kOffset);
1668 }
1669
1670 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1671 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001672
Austin Schuh6bae8252021-02-07 22:01:49 -08001673 if (do_timing_reports() == DoTimingReports::kYes) {
1674 // And, since we are here, check that the timing report makes sense.
1675 // Start by looking for our event loop's timing.
1676 FlatbufferDetachedBuffer<timing::Report> report =
1677 FlatbufferDetachedBuffer<timing::Report>::Empty();
1678 while (report_fetcher.FetchNext()) {
1679 if (report_fetcher->name()->string_view() == "primary") {
1680 report = CopyFlatBuffer(report_fetcher.get());
1681 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001682 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001683
1684 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
1685
1686 EXPECT_EQ(report.message().name()->string_view(), "primary");
1687
1688 ASSERT_NE(report.message().senders(), nullptr);
1689 EXPECT_EQ(report.message().senders()->size(), 2);
1690
1691 ASSERT_NE(report.message().timers(), nullptr);
1692 EXPECT_EQ(report.message().timers()->size(), 1);
1693
1694 // Make sure there is a single phased loop report with our report in it.
1695 ASSERT_NE(report.message().phased_loops(), nullptr);
1696 ASSERT_EQ(report.message().phased_loops()->size(), 1);
1697 EXPECT_EQ(report.message().phased_loops()->Get(0)->name()->string_view(),
1698 "Test loop");
1699 EXPECT_GE(report.message().phased_loops()->Get(0)->count(), 1);
1700 } else {
1701 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001702 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001703}
1704
Milind Upadhyay42589bb2021-05-19 20:05:16 -07001705// Tests that a phased loop responds correctly to a changing offset.
1706TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetTest) {
1707 // Force a slower rate so we are guaranteed to have reports for our phased
1708 // loop.
1709 FLAGS_timing_report_ms = 2000;
1710
1711 const chrono::milliseconds kOffset = chrono::milliseconds(400);
1712 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
1713 const int kCount = 5;
1714
1715 auto loop1 = MakePrimary();
1716
1717 // Collect up a couple of samples.
1718 ::std::vector<::aos::monotonic_clock::time_point> times;
1719 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
1720
1721 PhasedLoopHandler *phased_loop;
1722
1723 // Run kCount iterations.
1724 phased_loop = loop1->AddPhasedLoop(
1725 [&phased_loop, &times, &expected_times, &loop1, this, kOffset,
1726 kInterval](int count) {
1727 EXPECT_EQ(count, 1);
1728 times.push_back(loop1->monotonic_now());
1729
1730 expected_times.push_back(loop1->context().monotonic_event_time);
1731
1732 phased_loop->set_interval_and_offset(
1733 kInterval, kOffset - chrono::milliseconds(times.size()));
1734 LOG(INFO) << "new offset: "
1735 << (kOffset - chrono::milliseconds(times.size())).count();
1736
1737 if (times.size() == kCount) {
1738 LOG(INFO) << "Exiting";
1739 this->Exit();
1740 }
1741 },
1742 kInterval, kOffset);
1743 phased_loop->set_name("Test loop");
1744
1745 // Add a delay to make sure that delay during startup doesn't result in a
1746 // "missed cycle".
1747 SleepFor(chrono::seconds(2));
1748
1749 Run();
1750 // Confirm that we got both the right number of samples, and it's odd.
1751 EXPECT_EQ(times.size(), static_cast<size_t>(kCount));
1752 EXPECT_EQ(times.size(), expected_times.size());
1753 EXPECT_EQ((times.size() % 2), 1);
1754
1755 // Grab the middle sample.
1756 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
1757
1758 // Add up all the delays of all the times.
1759 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1760 for (const ::aos::monotonic_clock::time_point time : times) {
1761 sum += time - average_time;
1762 }
1763
1764 // Average and add to the middle to find the average time.
1765 sum /= times.size();
1766 average_time += sum;
1767
1768 // Compute the offset from the start of the second of the average time. This
1769 // should be pretty close to the offset.
1770 const ::aos::monotonic_clock::duration remainder =
1771 average_time.time_since_epoch() -
1772 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
1773
1774 const chrono::milliseconds kEpsilon(100);
1775 EXPECT_LT(remainder, kOffset + kEpsilon);
1776 EXPECT_GT(remainder, kOffset - kEpsilon);
1777
1778 // Make sure that the average duration is close to 1 second.
1779 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1780 times.front())
1781 .count() /
1782 static_cast<double>(times.size() - 1),
1783 1.0, 0.1);
1784
1785 // Confirm that the ideal wakeup times increment correctly.
1786 for (size_t i = 1; i < expected_times.size(); ++i) {
1787 LOG(INFO) << i - 1 << ": " << expected_times[i - 1] << ", " << i << ": "
1788 << expected_times[i];
1789 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1) -
1790 chrono::milliseconds(1));
1791 }
1792
1793 for (size_t i = 0; i < expected_times.size(); ++i) {
1794 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
1795 kOffset - chrono::milliseconds(i));
1796 }
1797
1798 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1799 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
1800}
1801
Austin Schuh39788ff2019-12-01 18:22:57 -08001802// Tests that senders count correctly in the timing report.
1803TEST_P(AbstractEventLoopTest, SenderTimingReport) {
1804 FLAGS_timing_report_ms = 1000;
1805 auto loop1 = MakePrimary();
1806
1807 auto loop2 = Make("watcher_loop");
1808 loop2->MakeWatcher("/test", [](const TestMessage &) {});
1809
1810 auto loop3 = Make();
1811
1812 Fetcher<timing::Report> report_fetcher =
1813 loop3->MakeFetcher<timing::Report>("/aos");
1814 EXPECT_FALSE(report_fetcher.Fetch());
1815
1816 auto sender = loop1->MakeSender<TestMessage>("/test");
1817
1818 // Add a timer to actually quit.
1819 auto test_timer = loop1->AddTimer([&sender]() {
1820 for (int i = 0; i < 10; ++i) {
1821 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1822 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1823 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07001824 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08001825 }
1826 });
1827
1828 // Quit after 1 timing report, mid way through the next cycle.
1829 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
1830
1831 loop1->OnRun([&test_timer, &loop1]() {
1832 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1500));
1833 });
1834
1835 Run();
1836
Austin Schuh6bae8252021-02-07 22:01:49 -08001837 if (do_timing_reports() == DoTimingReports::kYes) {
1838 // And, since we are here, check that the timing report makes sense.
1839 // Start by looking for our event loop's timing.
1840 FlatbufferDetachedBuffer<timing::Report> primary_report =
1841 FlatbufferDetachedBuffer<timing::Report>::Empty();
1842 while (report_fetcher.FetchNext()) {
Austin Schuh8902fa52021-03-14 22:39:24 -07001843 VLOG(1) << "Report " << FlatbufferToJson(report_fetcher.get());
Austin Schuh6bae8252021-02-07 22:01:49 -08001844 if (report_fetcher->name()->string_view() == "primary") {
1845 primary_report = CopyFlatBuffer(report_fetcher.get());
1846 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001847 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001848
Austin Schuh8902fa52021-03-14 22:39:24 -07001849 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
Austin Schuh6bae8252021-02-07 22:01:49 -08001850
1851 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
1852
1853 ASSERT_NE(primary_report.message().senders(), nullptr);
1854 EXPECT_EQ(primary_report.message().senders()->size(), 3);
1855
1856 // Confirm that the sender looks sane.
1857 EXPECT_EQ(
1858 loop1->configuration()
1859 ->channels()
1860 ->Get(primary_report.message().senders()->Get(0)->channel_index())
1861 ->name()
1862 ->string_view(),
1863 "/test");
1864 EXPECT_EQ(primary_report.message().senders()->Get(0)->count(), 10);
1865
1866 // Confirm that the timing primary_report sender looks sane.
1867 EXPECT_EQ(
1868 loop1->configuration()
1869 ->channels()
1870 ->Get(primary_report.message().senders()->Get(1)->channel_index())
1871 ->name()
1872 ->string_view(),
1873 "/aos");
1874 EXPECT_EQ(primary_report.message().senders()->Get(1)->count(), 1);
1875
1876 ASSERT_NE(primary_report.message().timers(), nullptr);
1877 EXPECT_EQ(primary_report.message().timers()->size(), 3);
1878
1879 // Make sure there are no phased loops or watchers.
1880 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
1881 ASSERT_EQ(primary_report.message().watchers(), nullptr);
1882 } else {
1883 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001884 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001885}
1886
1887// Tests that senders count correctly in the timing report.
1888TEST_P(AbstractEventLoopTest, WatcherTimingReport) {
1889 FLAGS_timing_report_ms = 1000;
1890 auto loop1 = MakePrimary();
1891 loop1->MakeWatcher("/test", [](const TestMessage &) {});
1892
1893 auto loop2 = Make("sender_loop");
1894
1895 auto loop3 = Make();
1896
1897 Fetcher<timing::Report> report_fetcher =
1898 loop3->MakeFetcher<timing::Report>("/aos");
1899 EXPECT_FALSE(report_fetcher.Fetch());
1900
1901 auto sender = loop2->MakeSender<TestMessage>("/test");
1902
1903 // Add a timer to actually quit.
1904 auto test_timer = loop1->AddTimer([&sender]() {
1905 for (int i = 0; i < 10; ++i) {
1906 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1907 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1908 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07001909 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08001910 }
1911 });
1912
1913 // Quit after 1 timing report, mid way through the next cycle.
1914 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
1915
1916 loop1->OnRun([&test_timer, &loop1]() {
1917 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1500));
1918 });
1919
1920 Run();
1921
Austin Schuh6bae8252021-02-07 22:01:49 -08001922 if (do_timing_reports() == DoTimingReports::kYes) {
1923 // And, since we are here, check that the timing report makes sense.
1924 // Start by looking for our event loop's timing.
1925 FlatbufferDetachedBuffer<timing::Report> primary_report =
1926 FlatbufferDetachedBuffer<timing::Report>::Empty();
1927 while (report_fetcher.FetchNext()) {
1928 LOG(INFO) << "Report " << FlatbufferToJson(report_fetcher.get());
1929 if (report_fetcher->name()->string_view() == "primary") {
1930 primary_report = CopyFlatBuffer(report_fetcher.get());
1931 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001932 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001933
1934 // Check the watcher report.
1935 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
1936
1937 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
1938
1939 // Just the timing report timer.
1940 ASSERT_NE(primary_report.message().timers(), nullptr);
1941 EXPECT_EQ(primary_report.message().timers()->size(), 3);
1942
1943 // No phased loops
1944 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
1945
1946 ASSERT_NE(primary_report.message().watchers(), nullptr);
1947 ASSERT_EQ(primary_report.message().watchers()->size(), 1);
1948 EXPECT_EQ(primary_report.message().watchers()->Get(0)->count(), 10);
1949 } else {
1950 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001951 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001952}
1953
1954// Tests that fetchers count correctly in the timing report.
1955TEST_P(AbstractEventLoopTest, FetcherTimingReport) {
1956 FLAGS_timing_report_ms = 1000;
1957 auto loop1 = MakePrimary();
1958 auto loop2 = Make("sender_loop");
1959
1960 auto loop3 = Make();
1961
1962 Fetcher<timing::Report> report_fetcher =
1963 loop3->MakeFetcher<timing::Report>("/aos");
1964 EXPECT_FALSE(report_fetcher.Fetch());
1965
1966 auto sender = loop2->MakeSender<TestMessage>("/test");
1967 auto fetcher1 = loop1->MakeFetcher<TestMessage>("/test");
1968 auto fetcher2 = loop1->MakeFetcher<TestMessage>("/test");
1969 fetcher1.Fetch();
1970 fetcher2.Fetch();
1971
1972 // Add a timer to actually quit.
1973 auto test_timer = loop1->AddTimer([&sender]() {
1974 for (int i = 0; i < 10; ++i) {
1975 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1976 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1977 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07001978 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08001979 }
1980 });
1981
1982 auto test_timer2 = loop1->AddTimer([&fetcher1, &fetcher2]() {
1983 fetcher1.Fetch();
1984 while (fetcher2.FetchNext()) {
1985 }
1986 });
1987
1988 // Quit after 1 timing report, mid way through the next cycle.
1989 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
1990
1991 loop1->OnRun([test_timer, test_timer2, &loop1]() {
1992 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1400));
1993 test_timer2->Setup(loop1->monotonic_now() + chrono::milliseconds(1600));
1994 });
1995
1996 Run();
1997
Austin Schuh6bae8252021-02-07 22:01:49 -08001998 if (do_timing_reports() == DoTimingReports::kYes) {
1999 // And, since we are here, check that the timing report makes sense.
2000 // Start by looking for our event loop's timing.
2001 FlatbufferDetachedBuffer<timing::Report> primary_report =
2002 FlatbufferDetachedBuffer<timing::Report>::Empty();
2003 while (report_fetcher.FetchNext()) {
2004 if (report_fetcher->name()->string_view() == "primary") {
2005 primary_report = CopyFlatBuffer(report_fetcher.get());
2006 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002007 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002008
2009 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2010
2011 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2012
2013 ASSERT_NE(primary_report.message().senders(), nullptr);
2014 EXPECT_EQ(primary_report.message().senders()->size(), 2);
2015
2016 ASSERT_NE(primary_report.message().timers(), nullptr);
2017 EXPECT_EQ(primary_report.message().timers()->size(), 4);
2018
2019 // Make sure there are no phased loops or watchers.
2020 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2021 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2022
2023 // Now look at the fetchrs.
2024 ASSERT_NE(primary_report.message().fetchers(), nullptr);
2025 ASSERT_EQ(primary_report.message().fetchers()->size(), 2);
2026
2027 EXPECT_EQ(primary_report.message().fetchers()->Get(0)->count(), 1);
2028 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->average(),
2029 0.1);
2030 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->min(),
2031 0.1);
2032 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->max(),
2033 0.1);
2034 EXPECT_EQ(primary_report.message()
2035 .fetchers()
2036 ->Get(0)
2037 ->latency()
2038 ->standard_deviation(),
2039 0.0);
2040
2041 EXPECT_EQ(primary_report.message().fetchers()->Get(1)->count(), 10);
2042 } else {
2043 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002044 }
Austin Schuh52d325c2019-06-23 18:59:06 -07002045}
2046
Austin Schuh67420a42019-12-21 21:55:04 -08002047// Tests that a raw watcher and raw fetcher can receive messages from a raw
2048// sender without messing up offsets.
2049TEST_P(AbstractEventLoopTest, RawBasic) {
2050 auto loop1 = Make();
2051 auto loop2 = MakePrimary();
2052 auto loop3 = Make();
2053
Austin Schuha9df9ad2021-06-16 14:49:39 -07002054 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2055 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuh67420a42019-12-21 21:55:04 -08002056
2057 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002058 loop1->MakeRawSender(configuration::GetChannel(
2059 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08002060
2061 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002062 loop3->MakeRawFetcher(configuration::GetChannel(
2063 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08002064
Austin Schuha9df9ad2021-06-16 14:49:39 -07002065 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002066 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2067 RawSender::Error::kOk);
Austin Schuha9df9ad2021-06-16 14:49:39 -07002068 });
Austin Schuh67420a42019-12-21 21:55:04 -08002069
2070 bool happened = false;
2071 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08002072 configuration::GetChannel(loop2->configuration(), "/test",
2073 "aos.TestMessage", "", nullptr),
Austin Schuha9df9ad2021-06-16 14:49:39 -07002074 [this, &kMessage, &fetcher, &happened](const Context &context,
2075 const void *message) {
Austin Schuh67420a42019-12-21 21:55:04 -08002076 happened = true;
Austin Schuha9df9ad2021-06-16 14:49:39 -07002077 EXPECT_EQ(
2078 kMessage.span(),
2079 absl::Span<const uint8_t>(
2080 reinterpret_cast<const uint8_t *>(message), context.size));
2081 EXPECT_EQ(message, context.data);
Austin Schuh67420a42019-12-21 21:55:04 -08002082
2083 ASSERT_TRUE(fetcher->Fetch());
2084
Austin Schuha9df9ad2021-06-16 14:49:39 -07002085 EXPECT_EQ(kMessage.span(),
2086 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
2087 fetcher->context().data),
2088 fetcher->context().size));
Austin Schuh67420a42019-12-21 21:55:04 -08002089
2090 this->Exit();
2091 });
2092
2093 EXPECT_FALSE(happened);
2094 Run();
2095 EXPECT_TRUE(happened);
2096}
2097
Austin Schuhad154822019-12-27 15:45:13 -08002098// Tests that a raw watcher and raw fetcher can receive messages from a raw
Brian Silvermanbf889922021-11-10 12:41:57 -08002099// sender without messing up offsets, using the RawSpan overload.
2100TEST_P(AbstractEventLoopTest, RawBasicSharedSpan) {
2101 auto loop1 = Make();
2102 auto loop2 = MakePrimary();
2103 auto loop3 = Make();
2104
2105 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2106 JsonToFlatbuffer<TestMessage>("{}");
2107
2108 std::unique_ptr<aos::RawSender> sender =
2109 loop1->MakeRawSender(configuration::GetChannel(
2110 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
2111
2112 std::unique_ptr<aos::RawFetcher> fetcher =
2113 loop3->MakeRawFetcher(configuration::GetChannel(
2114 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
2115
2116 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002117 EXPECT_EQ(sender->Send(std::make_shared<absl::Span<const uint8_t>>(
2118 kMessage.span().data(), kMessage.span().size())),
2119 RawSender::Error::kOk);
Brian Silvermanbf889922021-11-10 12:41:57 -08002120 });
2121
2122 bool happened = false;
2123 loop2->MakeRawWatcher(
2124 configuration::GetChannel(loop2->configuration(), "/test",
2125 "aos.TestMessage", "", nullptr),
2126 [this, &kMessage, &fetcher, &happened](const Context &context,
2127 const void *message) {
2128 happened = true;
2129 EXPECT_EQ(
2130 kMessage.span(),
2131 absl::Span<const uint8_t>(
2132 reinterpret_cast<const uint8_t *>(message), context.size));
2133 EXPECT_EQ(message, context.data);
2134
2135 ASSERT_TRUE(fetcher->Fetch());
2136
2137 EXPECT_EQ(kMessage.span(),
2138 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
2139 fetcher->context().data),
2140 fetcher->context().size));
2141
2142 this->Exit();
2143 });
2144
2145 EXPECT_FALSE(happened);
2146 Run();
2147 EXPECT_TRUE(happened);
2148}
2149
2150// Tests that a raw watcher and raw fetcher can receive messages from a raw
Austin Schuhad154822019-12-27 15:45:13 -08002151// sender with remote times filled out.
2152TEST_P(AbstractEventLoopTest, RawRemoteTimes) {
2153 auto loop1 = Make();
2154 auto loop2 = MakePrimary();
2155 auto loop3 = Make();
2156
Austin Schuha9df9ad2021-06-16 14:49:39 -07002157 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2158 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08002159
2160 const aos::monotonic_clock::time_point monotonic_remote_time =
2161 aos::monotonic_clock::time_point(chrono::seconds(1501));
2162 const aos::realtime_clock::time_point realtime_remote_time =
2163 aos::realtime_clock::time_point(chrono::seconds(3132));
Austin Schuhb5c6f972021-03-14 21:53:07 -07002164 const uint32_t remote_queue_index = 0x254971;
Austin Schuha9012be2021-07-21 15:19:11 -07002165 const UUID source_boot_uuid = UUID::Random();
Austin Schuhad154822019-12-27 15:45:13 -08002166
2167 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002168 loop1->MakeRawSender(configuration::GetChannel(
2169 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08002170
2171 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002172 loop3->MakeRawFetcher(configuration::GetChannel(
2173 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08002174
2175 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002176 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size(),
2177 monotonic_remote_time, realtime_remote_time,
2178 remote_queue_index, source_boot_uuid),
2179 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08002180 });
2181
2182 bool happened = false;
2183 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08002184 configuration::GetChannel(loop2->configuration(), "/test",
2185 "aos.TestMessage", "", nullptr),
Austin Schuha9012be2021-07-21 15:19:11 -07002186 [this, monotonic_remote_time, realtime_remote_time, source_boot_uuid,
Austin Schuhb5c6f972021-03-14 21:53:07 -07002187 remote_queue_index, &fetcher,
2188 &happened](const Context &context, const void * /*message*/) {
Austin Schuhad154822019-12-27 15:45:13 -08002189 happened = true;
2190 EXPECT_EQ(monotonic_remote_time, context.monotonic_remote_time);
2191 EXPECT_EQ(realtime_remote_time, context.realtime_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002192 EXPECT_EQ(source_boot_uuid, context.source_boot_uuid);
Austin Schuhb5c6f972021-03-14 21:53:07 -07002193 EXPECT_EQ(remote_queue_index, context.remote_queue_index);
Austin Schuhad154822019-12-27 15:45:13 -08002194
2195 ASSERT_TRUE(fetcher->Fetch());
2196 EXPECT_EQ(monotonic_remote_time,
2197 fetcher->context().monotonic_remote_time);
2198 EXPECT_EQ(realtime_remote_time,
2199 fetcher->context().realtime_remote_time);
2200
2201 this->Exit();
2202 });
2203
2204 EXPECT_FALSE(happened);
2205 Run();
2206 EXPECT_TRUE(happened);
2207}
2208
2209// Tests that a raw sender fills out sent data.
2210TEST_P(AbstractEventLoopTest, RawSenderSentData) {
2211 auto loop1 = MakePrimary();
2212
Austin Schuha9df9ad2021-06-16 14:49:39 -07002213 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2214 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08002215
2216 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002217 loop1->MakeRawSender(configuration::GetChannel(
2218 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08002219
Tyler Chatow67ddb032020-01-12 14:30:04 -08002220 const aos::monotonic_clock::time_point monotonic_now = loop1->monotonic_now();
2221 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08002222
milind1f1dca32021-07-03 13:50:07 -07002223 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2224 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08002225
2226 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
2227 EXPECT_LE(sender->monotonic_sent_time(),
2228 monotonic_now + chrono::milliseconds(100));
2229 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
2230 EXPECT_LE(sender->realtime_sent_time(),
2231 realtime_now + chrono::milliseconds(100));
2232 EXPECT_EQ(sender->sent_queue_index(), 0u);
2233
milind1f1dca32021-07-03 13:50:07 -07002234 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2235 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08002236
2237 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
2238 EXPECT_LE(sender->monotonic_sent_time(),
2239 monotonic_now + chrono::milliseconds(100));
2240 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
2241 EXPECT_LE(sender->realtime_sent_time(),
2242 realtime_now + chrono::milliseconds(100));
2243 EXPECT_EQ(sender->sent_queue_index(), 1u);
2244}
2245
Austin Schuh217a9782019-12-21 23:02:50 -08002246// Tests that not setting up nodes results in no node.
2247TEST_P(AbstractEventLoopTest, NoNode) {
2248 auto loop1 = Make();
2249 auto loop2 = MakePrimary();
2250
2251 EXPECT_EQ(loop1->node(), nullptr);
2252 EXPECT_EQ(loop2->node(), nullptr);
2253}
2254
2255// Tests that setting up nodes results in node being set.
2256TEST_P(AbstractEventLoopTest, Node) {
2257 EnableNodes("me");
2258
2259 auto loop1 = Make();
2260 auto loop2 = MakePrimary();
2261
2262 EXPECT_NE(loop1->node(), nullptr);
2263 EXPECT_NE(loop2->node(), nullptr);
2264}
2265
2266// Tests that watchers work with a node setup.
2267TEST_P(AbstractEventLoopTest, NodeWatcher) {
2268 EnableNodes("me");
2269
2270 auto loop1 = Make();
2271 auto loop2 = Make();
2272 loop1->MakeWatcher("/test", [](const TestMessage &) {});
Tyler Chatow67ddb032020-01-12 14:30:04 -08002273 loop2->MakeRawWatcher(
2274 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
2275 nullptr),
2276 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08002277}
2278
Brian Silverman454bc112020-03-05 14:21:25 -08002279// Tests that no-arg watchers work with a node setup.
2280TEST_P(AbstractEventLoopTest, NodeNoArgWatcher) {
2281 EnableNodes("me");
2282
2283 auto loop1 = Make();
2284 auto loop2 = Make();
2285 loop1->MakeWatcher("/test", [](const TestMessage &) {});
2286 loop2->MakeRawNoArgWatcher(
2287 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
2288 nullptr),
2289 [](const Context &) {});
2290}
2291
Austin Schuh217a9782019-12-21 23:02:50 -08002292// Tests that fetcher work with a node setup.
2293TEST_P(AbstractEventLoopTest, NodeFetcher) {
2294 EnableNodes("me");
2295 auto loop1 = Make();
2296
2297 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
Tyler Chatow67ddb032020-01-12 14:30:04 -08002298 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
2299 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08002300}
2301
2302// Tests that sender work with a node setup.
2303TEST_P(AbstractEventLoopTest, NodeSender) {
2304 EnableNodes("me");
2305 auto loop1 = Make();
2306
2307 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
2308}
2309
Austin Schuhcc6070c2020-10-10 20:25:56 -07002310// Tests that a non-realtime event loop timer is marked non-realtime.
2311TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopTimer) {
2312 auto loop1 = MakePrimary();
2313
2314 // Add a timer to actually quit.
2315 auto test_timer = loop1->AddTimer([this]() {
2316 CheckNotRealtime();
2317 this->Exit();
2318 });
2319
2320 loop1->OnRun([&test_timer, &loop1]() {
2321 CheckNotRealtime();
2322 test_timer->Setup(loop1->monotonic_now(), ::std::chrono::milliseconds(100));
2323 });
2324
2325 Run();
2326}
2327
2328// Tests that a realtime event loop timer is marked realtime.
2329TEST_P(AbstractEventLoopTest, RealtimeEventLoopTimer) {
2330 auto loop1 = MakePrimary();
2331
2332 loop1->SetRuntimeRealtimePriority(1);
2333
2334 // Add a timer to actually quit.
2335 auto test_timer = loop1->AddTimer([this]() {
2336 CheckRealtime();
2337 this->Exit();
2338 });
2339
2340 loop1->OnRun([&test_timer, &loop1]() {
2341 CheckRealtime();
2342 test_timer->Setup(loop1->monotonic_now(), ::std::chrono::milliseconds(100));
2343 });
2344
2345 Run();
2346}
2347
2348// Tests that a non-realtime event loop phased loop is marked non-realtime.
2349TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopPhasedLoop) {
2350 auto loop1 = MakePrimary();
2351
2352 // Add a timer to actually quit.
2353 loop1->AddPhasedLoop(
2354 [this](int) {
2355 CheckNotRealtime();
2356 this->Exit();
2357 },
2358 chrono::seconds(1), chrono::seconds(0));
2359
2360 Run();
2361}
2362
2363// Tests that a realtime event loop phased loop is marked realtime.
2364TEST_P(AbstractEventLoopTest, RealtimeEventLoopPhasedLoop) {
2365 auto loop1 = MakePrimary();
2366
2367 loop1->SetRuntimeRealtimePriority(1);
2368
2369 // Add a timer to actually quit.
2370 loop1->AddPhasedLoop(
2371 [this](int) {
2372 CheckRealtime();
2373 this->Exit();
2374 },
2375 chrono::seconds(1), chrono::seconds(0));
2376
2377 Run();
2378}
2379
2380// Tests that a non-realtime event loop watcher is marked non-realtime.
2381TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopWatcher) {
2382 auto loop1 = MakePrimary();
2383 auto loop2 = Make();
2384
2385 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
2386
2387 loop1->OnRun([&]() {
2388 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2389 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07002390 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07002391 });
2392
2393 loop1->MakeWatcher("/test", [&](const TestMessage &) {
2394 CheckNotRealtime();
2395 this->Exit();
2396 });
2397
2398 Run();
2399}
2400
2401// Tests that a realtime event loop watcher is marked realtime.
2402TEST_P(AbstractEventLoopTest, RealtimeEventLoopWatcher) {
2403 auto loop1 = MakePrimary();
2404 auto loop2 = Make();
2405
2406 loop1->SetRuntimeRealtimePriority(1);
2407
2408 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
2409
2410 loop1->OnRun([&]() {
2411 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2412 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07002413 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07002414 });
2415
2416 loop1->MakeWatcher("/test", [&](const TestMessage &) {
2417 CheckRealtime();
2418 this->Exit();
2419 });
2420
2421 Run();
2422}
2423
Austin Schuha9012be2021-07-21 15:19:11 -07002424// Tests that event loop's context's monotonic time is set to a value on OnRun.
2425TEST_P(AbstractEventLoopTest, SetContextOnRun) {
2426 auto loop = MakePrimary();
2427
2428 // We want to check that monotonic event time is before monotonic now
2429 // called inside of callback, but after time point obtained callback.
2430 aos::monotonic_clock::time_point monotonic_event_time_on_run;
2431
2432 loop->OnRun([&]() {
2433 monotonic_event_time_on_run = loop->context().monotonic_event_time;
2434 EXPECT_LE(monotonic_event_time_on_run, loop->monotonic_now());
2435 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
2436 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
2437 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
2438 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
2439 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
2440 EXPECT_EQ(loop->context().size, 0u);
2441 EXPECT_EQ(loop->context().data, nullptr);
2442 EXPECT_EQ(loop->context().buffer_index, -1);
2443 });
2444
2445 EndEventLoop(loop.get(), ::std::chrono::milliseconds(200));
2446
2447 const aos::monotonic_clock::time_point before_run_time =
2448 loop->monotonic_now();
2449 Run();
2450 EXPECT_GE(monotonic_event_time_on_run, before_run_time);
2451}
2452
Austin Schuh217a9782019-12-21 23:02:50 -08002453// Tests that watchers fail when created on the wrong node.
2454TEST_P(AbstractEventLoopDeathTest, NodeWatcher) {
2455 EnableNodes("them");
2456
2457 auto loop1 = Make();
2458 auto loop2 = Make();
2459 EXPECT_DEATH({ loop1->MakeWatcher("/test", [](const TestMessage &) {}); },
2460 "node");
2461 EXPECT_DEATH(
2462 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08002463 loop2->MakeRawWatcher(
2464 configuration::GetChannel(configuration(), "/test",
2465 "aos.TestMessage", "", nullptr),
2466 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08002467 },
2468 "node");
Brian Silverman454bc112020-03-05 14:21:25 -08002469 EXPECT_DEATH({ loop1->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
2470 "node");
2471 EXPECT_DEATH(
2472 {
2473 loop2->MakeRawNoArgWatcher(
2474 configuration::GetChannel(configuration(), "/test",
2475 "aos.TestMessage", "", nullptr),
2476 [](const Context &) {});
2477 },
2478 "node");
Austin Schuh217a9782019-12-21 23:02:50 -08002479}
2480
2481// Tests that fetchers fail when created on the wrong node.
2482TEST_P(AbstractEventLoopDeathTest, NodeFetcher) {
2483 EnableNodes("them");
2484 auto loop1 = Make();
2485
2486 EXPECT_DEATH({ auto fetcher = loop1->MakeFetcher<TestMessage>("/test"); },
2487 "node");
2488 EXPECT_DEATH(
2489 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08002490 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
2491 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08002492 },
2493 "node");
2494}
2495
2496// Tests that senders fail when created on the wrong node.
2497TEST_P(AbstractEventLoopDeathTest, NodeSender) {
2498 EnableNodes("them");
2499 auto loop1 = Make();
2500
2501 EXPECT_DEATH(
2502 {
2503 aos::Sender<TestMessage> sender =
2504 loop1->MakeSender<TestMessage>("/test");
2505 },
2506 "node");
2507
2508 // Note: Creating raw senders is always supported. Right now, this lets us
2509 // use them to create message_gateway.
2510}
2511
Brian Silverman341b57e2020-06-23 16:23:18 -07002512// Tests creating multiple Builders from a single Sender at the same time.
2513TEST_P(AbstractEventLoopDeathTest, MultipleBuilders) {
2514 auto loop1 = Make();
2515 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
2516
2517 { auto builder = sender.MakeBuilder(); }
2518 {
2519 auto builder = sender.MakeBuilder();
2520 builder.MakeBuilder<TestMessage>().Finish();
2521 }
2522 {
2523 // Creating this after the first one was destroyed should be fine.
2524 auto builder = sender.MakeBuilder();
2525 builder.MakeBuilder<TestMessage>().Finish();
2526 // But not a second one.
2527 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
2528 "May not overwrite in-use allocator");
2529 }
2530
2531 FlatbufferDetachedBuffer<TestMessage> detached =
2532 flatbuffers::DetachedBuffer();
2533 {
2534 auto builder = sender.MakeBuilder();
2535 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
2536 }
2537 {
2538 // This is the second one, after the detached one, so it should fail.
2539 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
2540 "May not overwrite in-use allocator");
2541 }
2542
2543 // Clear the detached one, and then we should be able to create another.
2544 detached = flatbuffers::DetachedBuffer();
2545 {
2546 auto builder = sender.MakeBuilder();
2547 builder.MakeBuilder<TestMessage>().Finish();
2548 }
2549
2550 // And then detach another one.
2551 {
2552 auto builder = sender.MakeBuilder();
2553 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
2554 }
2555}
2556
2557// Tests sending a buffer detached from a different builder.
2558TEST_P(AbstractEventLoopDeathTest, WrongDetachedBuffer) {
2559 auto loop1 = Make();
2560 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
2561 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
2562
2563 auto builder = sender1.MakeBuilder();
2564 FlatbufferDetachedBuffer<TestMessage> detached =
2565 builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
milind1f1dca32021-07-03 13:50:07 -07002566 EXPECT_DEATH(sender2.CheckOk(sender2.SendDetached(std::move(detached))),
Brian Silverman341b57e2020-06-23 16:23:18 -07002567 "May only send the buffer detached from this Sender");
2568}
2569
Parker Schuhe4a70d62017-12-27 20:10:20 -08002570} // namespace testing
2571} // namespace aos