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