blob: 990cbe56aeab664c4bf34c000b7c54fb2ec87d92 [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
527// Tests that Fetch and FetchNext interleave as expected.
528TEST_P(AbstractEventLoopTest, FetchAndFetchNextTogether) {
529 auto loop1 = Make();
530 auto loop2 = MakePrimary();
531
532 auto sender = loop1->MakeSender<TestMessage>("/test");
533
534 ::std::vector<int> values;
535
536 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700537 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
538 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
539 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700540 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700541 }
542 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700543 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
544 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
545 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700546 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700547 }
548
549 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
550
551 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700552 auto test_timer = loop2->AddTimer([&fetcher, &values, &sender, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700553 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700554 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700555 }
556
557 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700558 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
559 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
560 builder.add_value(202);
milind1f1dca32021-07-03 13:50:07 -0700561 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700562 }
563 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700564 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
565 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
566 builder.add_value(203);
milind1f1dca32021-07-03 13:50:07 -0700567 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700568 }
569 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700570 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
571 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
572 builder.add_value(204);
milind1f1dca32021-07-03 13:50:07 -0700573 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700574 }
575
576 if (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700577 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700578 }
579
580 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700581 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700582 }
583
Austin Schuh9fe68f72019-08-10 19:32:03 -0700584 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700585 });
586
587 loop2->OnRun([&test_timer, &loop2]() {
588 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
589 });
590
591 Run();
592 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
593}
594
Austin Schuh3115a202019-05-27 21:02:14 -0700595// Tests that FetchNext behaves correctly when we get two messages in the queue
596// but don't consume the first until after the second has been sent.
597TEST_P(AbstractEventLoopTest, FetchNextTest) {
Austin Schuh3115a202019-05-27 21:02:14 -0700598 auto send_loop = Make();
599 auto fetch_loop = Make();
600 auto sender = send_loop->MakeSender<TestMessage>("/test");
601 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
602
603 {
Tyler Chatow67ddb032020-01-12 14:30:04 -0800604 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
605 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
606 builder.add_value(100);
milind1f1dca32021-07-03 13:50:07 -0700607 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700608 }
609
610 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700611 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
612 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
613 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700614 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700615 }
616
617 ASSERT_TRUE(fetcher.FetchNext());
618 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700619 EXPECT_EQ(100, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700620
621 ASSERT_TRUE(fetcher.FetchNext());
622 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700623 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700624
625 // When we run off the end of the queue, expect to still have the old message:
626 ASSERT_FALSE(fetcher.FetchNext());
627 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700628 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700629}
630
Brian Silverman77162972020-08-12 19:52:40 -0700631// Verify that a fetcher still holds its data, even after falling behind.
632TEST_P(AbstractEventLoopTest, FetcherBehindData) {
633 auto send_loop = Make();
634 auto fetch_loop = Make();
635 auto sender = send_loop->MakeSender<TestMessage>("/test");
636 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
637 {
638 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
639 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
640 builder.add_value(1);
milind1f1dca32021-07-03 13:50:07 -0700641 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -0700642 }
643 ASSERT_TRUE(fetcher.Fetch());
644 EXPECT_EQ(1, fetcher.get()->value());
645 for (int i = 0; i < 300; ++i) {
646 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
647 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
648 builder.add_value(i + 2);
milind1f1dca32021-07-03 13:50:07 -0700649 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -0700650 }
651 EXPECT_EQ(1, fetcher.get()->value());
652}
653
654// Try a bunch of orderings of operations with fetchers and senders. Verify that
655// all the fetchers have the correct data at each step.
656TEST_P(AbstractEventLoopTest, FetcherPermutations) {
657 for (int max_save = 0; max_save < 5; ++max_save) {
658 SCOPED_TRACE("max_save=" + std::to_string(max_save));
659
660 auto send_loop = Make();
661 auto fetch_loop = Make();
662 auto sender = send_loop->MakeSender<TestMessage>("/test");
663 const auto send_message = [&sender](int i) {
664 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
665 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
666 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700667 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -0700668 };
669 std::vector<Fetcher<TestMessage>> fetchers;
670 for (int i = 0; i < 10; ++i) {
671 fetchers.emplace_back(fetch_loop->MakeFetcher<TestMessage>("/test"));
672 }
673 send_message(1);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700674 const auto verify_buffers = [&]() {
675 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>>
676 fetchers_copy;
677 for (const auto &fetcher : fetchers) {
678 fetchers_copy.emplace_back(fetcher);
679 }
680 std::vector<std::reference_wrapper<const Sender<TestMessage>>>
681 senders_copy;
682 senders_copy.emplace_back(sender);
683 VerifyBuffers(send_loop->NumberBuffers(sender.channel()), fetchers_copy,
684 senders_copy);
685 };
Brian Silverman77162972020-08-12 19:52:40 -0700686 for (auto &fetcher : fetchers) {
687 ASSERT_TRUE(fetcher.Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -0700688 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700689 EXPECT_EQ(1, fetcher.get()->value());
690 }
691
692 for (int save = 1; save <= max_save; ++save) {
693 SCOPED_TRACE("save=" + std::to_string(save));
694 send_message(100 + save);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700695 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700696 for (size_t i = 0; i < fetchers.size() - save; ++i) {
697 SCOPED_TRACE("fetcher=" + std::to_string(i));
698 ASSERT_TRUE(fetchers[i].Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -0700699 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700700 EXPECT_EQ(100 + save, fetchers[i].get()->value());
701 }
702 for (size_t i = fetchers.size() - save; i < fetchers.size() - 1; ++i) {
703 SCOPED_TRACE("fetcher=" + std::to_string(i));
704 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
705 }
706 EXPECT_EQ(1, fetchers.back().get()->value());
707 }
708
709 for (int i = 0; i < 300; ++i) {
710 send_message(200 + i);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700711 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700712 }
713
714 for (size_t i = 0; i < fetchers.size() - max_save; ++i) {
715 SCOPED_TRACE("fetcher=" + std::to_string(i));
716 if (max_save > 0) {
717 EXPECT_EQ(100 + max_save, fetchers[i].get()->value());
718 } else {
719 EXPECT_EQ(1, fetchers[i].get()->value());
720 }
721 }
722 for (size_t i = fetchers.size() - max_save; i < fetchers.size() - 1; ++i) {
723 SCOPED_TRACE("fetcher=" + std::to_string(i));
724 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
725 }
726 EXPECT_EQ(1, fetchers.back().get()->value());
727 }
728}
729
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800730// Verify that making a fetcher and watcher for "/test" succeeds.
731TEST_P(AbstractEventLoopTest, FetcherAndWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800732 auto loop = Make();
733 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800734 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Parker Schuhe4a70d62017-12-27 20:10:20 -0800735}
736
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800737// Verify that making 2 fetchers for "/test" succeeds.
Parker Schuhe4a70d62017-12-27 20:10:20 -0800738TEST_P(AbstractEventLoopTest, TwoFetcher) {
739 auto loop = Make();
740 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800741 auto fetcher2 = loop->MakeFetcher<TestMessage>("/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -0800742}
743
Alex Perrycb7da4b2019-08-28 19:35:56 -0700744// Verify that registering a watcher for an invalid channel name dies.
745TEST_P(AbstractEventLoopDeathTest, InvalidChannelName) {
746 auto loop = Make();
747 EXPECT_DEATH(
748 { loop->MakeWatcher("/test/invalid", [&](const TestMessage &) {}); },
749 "/test/invalid");
Brian Silverman454bc112020-03-05 14:21:25 -0800750 EXPECT_DEATH(
751 { loop->MakeNoArgWatcher<TestMessage>("/test/invalid", [&]() {}); },
752 "/test/invalid");
Alex Perrycb7da4b2019-08-28 19:35:56 -0700753}
754
James Kuszmaul8866e642022-06-10 16:00:36 -0700755// Verify that setting up a timer before monotonic_clock::epoch() fails.
James Kuszmaul86e86c32022-07-21 17:39:47 -0700756TEST_P(AbstractEventLoopDeathTest, NegativeTimeTimer) {
James Kuszmaul8866e642022-06-10 16:00:36 -0700757 auto loop = Make();
758 TimerHandler *time = loop->AddTimer([]() {});
759 EXPECT_DEATH(time->Setup(monotonic_clock::epoch() - std::chrono::seconds(1)),
760 "-1.000");
761}
762
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800763// Verify that registering a watcher twice for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700764TEST_P(AbstractEventLoopDeathTest, TwoWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800765 auto loop = Make();
766 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800767 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
768 "/test");
Brian Silverman454bc112020-03-05 14:21:25 -0800769 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
770}
771
772// Verify that registering a no-arg watcher twice for "/test" fails.
773TEST_P(AbstractEventLoopDeathTest, TwoNoArgWatcher) {
774 auto loop = Make();
775 loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {});
776 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
777 "/test");
778 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800779}
780
Austin Schuh3115a202019-05-27 21:02:14 -0700781// Verify that SetRuntimeRealtimePriority fails while running.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700782TEST_P(AbstractEventLoopDeathTest, SetRuntimeRealtimePriority) {
Austin Schuh3115a202019-05-27 21:02:14 -0700783 auto loop = MakePrimary();
Austin Schuh65493d62022-08-17 15:10:37 -0700784 EXPECT_EQ(0, loop->runtime_realtime_priority());
Austin Schuh3115a202019-05-27 21:02:14 -0700785 // Confirm that runtime priority calls work when not realtime.
786 loop->SetRuntimeRealtimePriority(5);
Austin Schuh65493d62022-08-17 15:10:37 -0700787 EXPECT_EQ(5, loop->runtime_realtime_priority());
Austin Schuh3115a202019-05-27 21:02:14 -0700788
789 loop->OnRun([&]() { loop->SetRuntimeRealtimePriority(5); });
790
791 EXPECT_DEATH(Run(), "realtime");
792}
793
Austin Schuh65493d62022-08-17 15:10:37 -0700794namespace {
795
796bool CpuSetEqual(const cpu_set_t &a, const cpu_set_t &b) {
797 return CPU_EQUAL(&a, &b);
798}
799
800} // namespace
801
Brian Silverman6a54ff32020-04-28 16:41:39 -0700802// Verify that SetRuntimeAffinity fails while running.
803TEST_P(AbstractEventLoopDeathTest, SetRuntimeAffinity) {
Austin Schuhde973292021-10-12 18:09:49 -0700804 const cpu_set_t available = GetCurrentThreadAffinity();
805 int first_cpu = -1;
806 for (int i = 0; i < CPU_SETSIZE; ++i) {
807 if (CPU_ISSET(i, &available)) {
808 first_cpu = i;
809 break;
810 continue;
811 }
812 }
813 CHECK_NE(first_cpu, -1) << ": Default affinity has no CPUs?";
814
Brian Silverman6a54ff32020-04-28 16:41:39 -0700815 auto loop = MakePrimary();
Austin Schuh65493d62022-08-17 15:10:37 -0700816 EXPECT_TRUE(
817 CpuSetEqual(EventLoop::DefaultAffinity(), loop->runtime_affinity()));
818 const cpu_set_t new_affinity = MakeCpusetFromCpus({first_cpu});
Brian Silverman6a54ff32020-04-28 16:41:39 -0700819 // Confirm that runtime priority calls work when not running.
Austin Schuh65493d62022-08-17 15:10:37 -0700820 loop->SetRuntimeAffinity(new_affinity);
821 EXPECT_TRUE(CpuSetEqual(new_affinity, loop->runtime_affinity()));
Brian Silverman6a54ff32020-04-28 16:41:39 -0700822
Austin Schuhde973292021-10-12 18:09:49 -0700823 loop->OnRun(
824 [&]() { loop->SetRuntimeAffinity(MakeCpusetFromCpus({first_cpu})); });
Brian Silverman6a54ff32020-04-28 16:41:39 -0700825
826 EXPECT_DEATH(Run(), "Cannot set affinity while running");
827}
828
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800829// Verify that registering a watcher and a sender for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700830TEST_P(AbstractEventLoopDeathTest, WatcherAndSender) {
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800831 auto loop = Make();
832 auto sender = loop->MakeSender<TestMessage>("/test");
833 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
834 "/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -0800835}
836
Austin Schuhe516ab02020-05-06 21:37:04 -0700837// Verify that creating too many senders fails.
838TEST_P(AbstractEventLoopDeathTest, TooManySenders) {
839 auto loop = Make();
840 std::vector<aos::Sender<TestMessage>> senders;
841 for (int i = 0; i < 10; ++i) {
842 senders.emplace_back(loop->MakeSender<TestMessage>("/test"));
843 }
844 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); },
845 "Failed to create sender on \\{ \"name\": \"/test\", \"type\": "
Brian Silverman77162972020-08-12 19:52:40 -0700846 "\"aos.TestMessage\"[^}]*\\ }, too many senders.");
847}
848
849// Verify that creating too many fetchers fails.
850TEST_P(AbstractEventLoopDeathTest, TooManyFetchers) {
851 if (read_method() != ReadMethod::PIN) {
852 // Other read methods don't limit the number of readers, so just skip this.
853 return;
854 }
855
856 auto loop = Make();
857 std::vector<aos::Fetcher<TestMessage>> fetchers;
858 for (int i = 0; i < 10; ++i) {
859 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
860 }
861 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
862 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
863 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
864}
865
866// Verify that creating too many fetchers, split between two event loops, fails.
867TEST_P(AbstractEventLoopDeathTest, TooManyFetchersTwoLoops) {
868 if (read_method() != ReadMethod::PIN) {
869 // Other read methods don't limit the number of readers, so just skip this.
870 return;
871 }
872
873 auto loop = Make();
874 auto loop2 = Make();
875 std::vector<aos::Fetcher<TestMessage>> fetchers;
876 for (int i = 0; i < 5; ++i) {
877 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
878 fetchers.emplace_back(loop2->MakeFetcher<TestMessage>("/test"));
879 }
880 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
881 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
882 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
883}
884
885// Verify that creating too many watchers fails.
886TEST_P(AbstractEventLoopDeathTest, TooManyWatchers) {
887 if (read_method() != ReadMethod::PIN) {
888 // Other read methods don't limit the number of readers, so just skip this.
889 return;
890 }
891
892 std::vector<std::unique_ptr<EventLoop>> loops;
893 for (int i = 0; i < 10; ++i) {
894 loops.emplace_back(Make());
895 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
896 }
897 EXPECT_DEATH({ Make()->MakeWatcher("/test", [](const TestMessage &) {}); },
898 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
899 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
900}
901
902// Verify that creating too many watchers and fetchers combined fails.
903TEST_P(AbstractEventLoopDeathTest, TooManyWatchersAndFetchers) {
904 if (read_method() != ReadMethod::PIN) {
905 // Other read methods don't limit the number of readers, so just skip this.
906 return;
907 }
908
909 auto loop = Make();
910 std::vector<aos::Fetcher<TestMessage>> fetchers;
911 std::vector<std::unique_ptr<EventLoop>> loops;
912 for (int i = 0; i < 5; ++i) {
913 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
914 loops.emplace_back(Make());
915 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
916 }
917 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
918 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
919 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
Austin Schuhe516ab02020-05-06 21:37:04 -0700920}
921
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700922// Verify that we can't create a sender inside OnRun.
923TEST_P(AbstractEventLoopDeathTest, SenderInOnRun) {
924 auto loop1 = MakePrimary();
925
926 loop1->OnRun(
927 [&]() { auto sender = loop1->MakeSender<TestMessage>("/test2"); });
928
929 EXPECT_DEATH(Run(), "running");
930}
931
932// Verify that we can't create a watcher inside OnRun.
933TEST_P(AbstractEventLoopDeathTest, WatcherInOnRun) {
934 auto loop1 = MakePrimary();
935
936 loop1->OnRun(
937 [&]() { loop1->MakeWatcher("/test", [&](const TestMessage &) {}); });
938
939 EXPECT_DEATH(Run(), "running");
940}
941
Brian Silverman454bc112020-03-05 14:21:25 -0800942// Verify that we can't create a no-arg watcher inside OnRun.
943TEST_P(AbstractEventLoopDeathTest, NoArgWatcherInOnRun) {
944 auto loop1 = MakePrimary();
945
946 loop1->OnRun(
947 [&]() { loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {}); });
948
949 EXPECT_DEATH(Run(), "running");
950}
951
Parker Schuhe4a70d62017-12-27 20:10:20 -0800952// Verify that Quit() works when there are multiple watchers.
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800953TEST_P(AbstractEventLoopTest, MultipleWatcherQuit) {
954 auto loop1 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -0700955 auto loop2 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800956
Austin Schuh3578a2e2019-05-25 18:17:59 -0700957 loop2->MakeWatcher("/test1", [&](const TestMessage &) {});
958 loop2->MakeWatcher("/test2", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700959 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -0700960 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -0700961 });
962
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800963 auto sender = loop1->MakeSender<TestMessage>("/test2");
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700964
965 loop2->OnRun([&]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700966 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
967 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
968 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700969 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700970 });
Parker Schuhe4a70d62017-12-27 20:10:20 -0800971
Austin Schuh44019f92019-05-19 19:58:27 -0700972 Run();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800973}
974
Austin Schuhad9e5eb2021-11-19 20:33:55 -0800975// Verify that AOS_LOG has the right name.
976TEST_P(AbstractEventLoopTest, AOSLog) {
977 auto loop2 = MakePrimary("loop1");
978 auto loop1 = Make("loop0");
979
980 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
981
982 EXPECT_FALSE(fetcher.Fetch());
983
984 loop2->OnRun([&]() {
985 AOS_LOG(INFO, "Testing123");
986 this->Exit();
987 });
988
989 Run();
990 EXPECT_TRUE(fetcher.Fetch());
991 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
992}
993
994// Verify that AOS_LOG has the right name in a watcher.
995TEST_P(AbstractEventLoopTest, AOSLogWatcher) {
996 auto loop2 = MakePrimary("loop1");
997 auto loop1 = Make("loop0");
998
999 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1000
1001 EXPECT_FALSE(fetcher.Fetch());
1002
1003 auto sender = loop1->MakeSender<TestMessage>("/test2");
1004
1005 loop2->MakeWatcher("/test2", [&](const TestMessage & /*message*/) {
1006 AOS_LOG(INFO, "Testing123");
1007 this->Exit();
1008 });
1009
1010 loop2->OnRun([&]() {
1011 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1012 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1013 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001014 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001015 });
1016
1017 Run();
1018 EXPECT_TRUE(fetcher.Fetch());
1019 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1020}
1021
1022// Verify that AOS_LOG has the right name in a timer.
1023TEST_P(AbstractEventLoopTest, AOSLogTimer) {
1024 auto loop2 = MakePrimary("loop1");
1025 auto loop1 = Make("loop0");
1026
1027 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1028
1029 EXPECT_FALSE(fetcher.Fetch());
1030
1031 auto test_timer = loop2->AddTimer([&]() {
1032 AOS_LOG(INFO, "Testing123");
1033 this->Exit();
1034 });
1035
1036 loop2->OnRun([&]() { test_timer->Setup(loop2->monotonic_now()); });
1037
1038 Run();
1039 EXPECT_TRUE(fetcher.Fetch());
1040 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1041}
1042
Neil Balch229001a2018-01-07 18:22:52 -08001043// Verify that timer intervals and duration function properly.
1044TEST_P(AbstractEventLoopTest, TimerIntervalAndDuration) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001045 // Force a slower rate so we are guaranteed to have reports for our timer.
Austin Schuh39788ff2019-12-01 18:22:57 -08001046 FLAGS_timing_report_ms = 2000;
1047
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001048 const int kCount = 5;
Neil Balch229001a2018-01-07 18:22:52 -08001049
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001050 auto loop = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001051 auto loop2 = Make();
1052
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001053 ::std::vector<::aos::monotonic_clock::time_point> times;
1054 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
1055
Austin Schuh39788ff2019-12-01 18:22:57 -08001056 Fetcher<timing::Report> report_fetcher =
1057 loop2->MakeFetcher<timing::Report>("/aos");
1058 EXPECT_FALSE(report_fetcher.Fetch());
1059
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001060 auto test_timer = loop->AddTimer([this, &times, &expected_times, &loop]() {
1061 times.push_back(loop->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001062 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
1063 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
1064 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001065 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -08001066 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
1067 EXPECT_EQ(loop->context().size, 0u);
1068 EXPECT_EQ(loop->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001069 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001070
Austin Schuhad154822019-12-27 15:45:13 -08001071 expected_times.push_back(loop->context().monotonic_event_time);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001072 if (times.size() == kCount) {
1073 this->Exit();
1074 }
Neil Balch229001a2018-01-07 18:22:52 -08001075 });
Austin Schuh39788ff2019-12-01 18:22:57 -08001076 test_timer->set_name("Test loop");
Neil Balch229001a2018-01-07 18:22:52 -08001077
Austin Schuh39788ff2019-12-01 18:22:57 -08001078 const monotonic_clock::time_point start_time = loop->monotonic_now();
Austin Schuh52d325c2019-06-23 18:59:06 -07001079 // TODO(austin): This should be an error... Should be done in OnRun only.
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001080 test_timer->Setup(start_time + chrono::seconds(1), chrono::seconds(1));
1081
Austin Schuh44019f92019-05-19 19:58:27 -07001082 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001083
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001084 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001085 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
1086 ASSERT_EQ(times.size(), expected_times.size());
1087 ASSERT_EQ((times.size() % 2), 1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001088
1089 // Grab the middle sample.
1090 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
1091
1092 // Add up all the delays of all the times.
1093 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1094 for (const ::aos::monotonic_clock::time_point time : times) {
1095 sum += time - average_time;
1096 }
1097
1098 // Average and add to the middle to find the average time.
1099 sum /= times.size();
1100 average_time += sum;
1101
1102 // Compute the offset from the average and the expected average. It
1103 // should be pretty close to 0.
1104 const ::aos::monotonic_clock::duration remainder =
1105 average_time - start_time - chrono::seconds(times.size() / 2 + 1);
1106
1107 const chrono::milliseconds kEpsilon(100);
1108 EXPECT_LT(remainder, +kEpsilon);
1109 EXPECT_GT(remainder, -kEpsilon);
1110
1111 // Make sure that the average duration is close to 1 second.
1112 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1113 times.front())
1114 .count() /
1115 static_cast<double>(times.size() - 1),
1116 1.0, 0.1);
1117
1118 // Confirm that the ideal wakeup times increment correctly.
1119 for (size_t i = 1; i < expected_times.size(); ++i) {
1120 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1121 }
1122
1123 for (size_t i = 0; i < expected_times.size(); ++i) {
1124 EXPECT_EQ((expected_times[i] - start_time) % chrono::seconds(1),
1125 chrono::seconds(0));
1126 }
1127
1128 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1129 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001130
Austin Schuh6bae8252021-02-07 22:01:49 -08001131 if (do_timing_reports() == DoTimingReports::kYes) {
1132 // And, since we are here, check that the timing report makes sense.
1133 // Start by looking for our event loop's timing.
1134 FlatbufferDetachedBuffer<timing::Report> report =
1135 FlatbufferDetachedBuffer<timing::Report>::Empty();
1136 while (report_fetcher.FetchNext()) {
1137 if (report_fetcher->name()->string_view() == "primary") {
1138 report = CopyFlatBuffer(report_fetcher.get());
1139 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001140 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001141
1142 // Confirm that we have the right number of reports, and the contents are
1143 // sane.
1144 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
1145
1146 EXPECT_EQ(report.message().name()->string_view(), "primary");
1147
1148 ASSERT_NE(report.message().senders(), nullptr);
1149 EXPECT_EQ(report.message().senders()->size(), 2);
1150
1151 ASSERT_NE(report.message().timers(), nullptr);
1152 EXPECT_EQ(report.message().timers()->size(), 2);
1153
1154 EXPECT_EQ(report.message().timers()->Get(0)->name()->string_view(),
1155 "Test loop");
1156 EXPECT_GE(report.message().timers()->Get(0)->count(), 1);
1157
1158 EXPECT_EQ(report.message().timers()->Get(1)->name()->string_view(),
1159 "timing_reports");
1160 EXPECT_EQ(report.message().timers()->Get(1)->count(), 1);
1161
1162 // Make sure there is a single phased loop report with our report in it.
1163 ASSERT_EQ(report.message().phased_loops(), nullptr);
1164 } else {
1165 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001166 }
Neil Balch229001a2018-01-07 18:22:52 -08001167}
1168
1169// Verify that we can change a timer's parameters during execution.
1170TEST_P(AbstractEventLoopTest, TimerChangeParameters) {
Austin Schuh44019f92019-05-19 19:58:27 -07001171 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001172 loop->SetRuntimeRealtimePriority(1);
Austin Schuh7f20f512021-01-31 17:56:16 -08001173 std::vector<monotonic_clock::time_point> iteration_list;
Neil Balch229001a2018-01-07 18:22:52 -08001174
1175 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001176 ScopedNotRealtime nrt;
Austin Schuh7f20f512021-01-31 17:56:16 -08001177 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001178 });
1179
Austin Schuh7f20f512021-01-31 17:56:16 -08001180 monotonic_clock::time_point s;
1181 auto modifier_timer = loop->AddTimer([&test_timer, &s]() {
Austin Schuhd892f102021-10-12 18:01:46 -07001182 test_timer->Setup(s + chrono::milliseconds(1750),
1183 chrono::milliseconds(600));
Neil Balch229001a2018-01-07 18:22:52 -08001184 });
1185
Austin Schuh7f20f512021-01-31 17:56:16 -08001186 s = loop->monotonic_now();
Austin Schuhd892f102021-10-12 18:01:46 -07001187 test_timer->Setup(s, chrono::milliseconds(500));
1188 modifier_timer->Setup(s + chrono::milliseconds(1250));
1189 EndEventLoop(loop.get(), chrono::milliseconds(3950));
Austin Schuh44019f92019-05-19 19:58:27 -07001190 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001191
Austin Schuhd892f102021-10-12 18:01:46 -07001192 EXPECT_THAT(
1193 iteration_list,
1194 ::testing::ElementsAre(
1195 s, s + chrono::milliseconds(500), s + chrono::milliseconds(1000),
1196 s + chrono::milliseconds(1750), s + chrono::milliseconds(2350),
1197 s + chrono::milliseconds(2950), s + chrono::milliseconds(3550)));
Neil Balch229001a2018-01-07 18:22:52 -08001198}
1199
1200// Verify that we can disable a timer during execution.
1201TEST_P(AbstractEventLoopTest, TimerDisable) {
Austin Schuh44019f92019-05-19 19:58:27 -07001202 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001203 loop->SetRuntimeRealtimePriority(1);
Neil Balch229001a2018-01-07 18:22:52 -08001204 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
1205
1206 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001207 ScopedNotRealtime nrt;
Austin Schuhd892f102021-10-12 18:01:46 -07001208 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001209 });
1210
Tyler Chatow67ddb032020-01-12 14:30:04 -08001211 auto ender_timer = loop->AddTimer([&test_timer]() { test_timer->Disable(); });
Neil Balch229001a2018-01-07 18:22:52 -08001212
Austin Schuhd892f102021-10-12 18:01:46 -07001213 monotonic_clock::time_point s = loop->monotonic_now();
Austin Schuh73d99502021-12-08 12:05:39 -08001214 test_timer->Setup(s, ::std::chrono::milliseconds(500));
1215 ender_timer->Setup(s + ::std::chrono::milliseconds(1250));
1216 EndEventLoop(loop.get(), ::std::chrono::milliseconds(2000));
Austin Schuh44019f92019-05-19 19:58:27 -07001217 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001218
Austin Schuhd892f102021-10-12 18:01:46 -07001219 EXPECT_THAT(iteration_list,
Austin Schuh73d99502021-12-08 12:05:39 -08001220 ::testing::ElementsAre(s, s + chrono::milliseconds(500),
1221 s + chrono::milliseconds(1000)));
Neil Balch229001a2018-01-07 18:22:52 -08001222}
Austin Schuh7267c532019-05-19 19:55:53 -07001223
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001224// Verify that a timer can disable itself.
1225//
1226// TODO(Brian): Do something similar with phased loops, both with a quick
1227// handler and a handler that would miss a cycle except it got deferred. Current
1228// behavior doing that is a mess.
1229TEST_P(AbstractEventLoopTest, TimerDisableSelf) {
1230 auto loop = MakePrimary();
1231
1232 int count = 0;
1233 aos::TimerHandler *test_timer;
1234 test_timer = loop->AddTimer([&count, &test_timer]() {
1235 ++count;
1236 test_timer->Disable();
1237 });
1238
1239 test_timer->Setup(loop->monotonic_now(), ::std::chrono::milliseconds(20));
1240 EndEventLoop(loop.get(), ::std::chrono::milliseconds(80));
1241 Run();
1242
1243 EXPECT_EQ(count, 1);
1244}
1245
Brian Silvermanbd405c02020-06-23 16:25:23 -07001246// Verify that we can disable a timer during execution of another timer
1247// scheduled for the same time, with one ordering of creation for the timers.
1248//
1249// Also schedule some more events to reshuffle the heap in EventLoop used for
1250// tracking events to change up the order. This used to segfault
1251// SimulatedEventLoop.
1252TEST_P(AbstractEventLoopTest, TimerDisableOther) {
1253 for (bool creation_order : {true, false}) {
1254 for (bool setup_order : {true, false}) {
1255 for (int shuffle_events = 0; shuffle_events < 5; ++shuffle_events) {
1256 auto loop = MakePrimary();
1257 aos::TimerHandler *test_timer, *ender_timer;
1258 if (creation_order) {
1259 test_timer = loop->AddTimer([]() {});
1260 ender_timer =
1261 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1262 } else {
1263 ender_timer =
1264 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1265 test_timer = loop->AddTimer([]() {});
1266 }
1267
1268 const auto start = loop->monotonic_now();
1269
1270 for (int i = 0; i < shuffle_events; ++i) {
1271 loop->AddTimer([]() {})->Setup(start + std::chrono::milliseconds(10));
1272 }
1273
1274 if (setup_order) {
1275 test_timer->Setup(start + ::std::chrono::milliseconds(20));
1276 ender_timer->Setup(start + ::std::chrono::milliseconds(20));
1277 } else {
1278 ender_timer->Setup(start + ::std::chrono::milliseconds(20));
1279 test_timer->Setup(start + ::std::chrono::milliseconds(20));
1280 }
1281 EndEventLoop(loop.get(), ::std::chrono::milliseconds(40));
1282 Run();
1283 }
1284 }
1285 }
1286}
1287
Austin Schuh54cf95f2019-11-29 13:14:18 -08001288// Verifies that the event loop implementations detect when Channel is not a
Brian Silverman631b6262021-11-10 12:25:08 -08001289// pointer into configuration(), or a name doesn't map to a channel in
1290// configuration().
Austin Schuh54cf95f2019-11-29 13:14:18 -08001291TEST_P(AbstractEventLoopDeathTest, InvalidChannel) {
1292 auto loop = MakePrimary();
1293
Tyler Chatow67ddb032020-01-12 14:30:04 -08001294 const Channel *channel = configuration::GetChannel(
1295 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
Austin Schuh54cf95f2019-11-29 13:14:18 -08001296
1297 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1298
1299 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001300 loop->MakeRawSender(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001301 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1302
1303 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001304 loop->MakeSender<TestMessage>("/testbad"),
1305 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1306 " not found in config");
1307
1308 EXPECT_FALSE(loop->TryMakeSender<TestMessage>("/testbad"));
1309
1310 EXPECT_DEATH(
1311 loop->MakeRawFetcher(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001312 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1313
1314 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001315 loop->MakeFetcher<TestMessage>("/testbad"),
1316 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1317 " not found in config");
1318
1319 EXPECT_FALSE(loop->TryMakeFetcher<TestMessage>("/testbad").valid());
1320
1321 EXPECT_DEATH(
Austin Schuh54cf95f2019-11-29 13:14:18 -08001322 {
1323 loop->MakeRawWatcher(&channel_copy.message(),
1324 [](const Context, const void *) {});
1325 },
1326 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
Brian Silverman631b6262021-11-10 12:25:08 -08001327
1328 EXPECT_DEATH(
1329 { loop->MakeWatcher("/testbad", [](const TestMessage &) {}); },
1330 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1331 " not found in config");
1332}
1333
1334// Verifies that the event loop handles a channel which is not readable or
1335// writable on the current node nicely.
1336TEST_P(AbstractEventLoopDeathTest, InaccessibleChannel) {
1337 EnableNodes("me");
1338 auto loop = MakePrimary("me");
1339 auto loop2 = Make("them");
1340
1341 const Channel *channel = configuration::GetChannel(
1342 loop->configuration(), "/test_noforward", "aos.TestMessage", "", nullptr);
1343
1344 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1345
1346 EXPECT_DEATH(
1347 loop2->MakeSender<TestMessage>("/test_forward"),
1348 "Channel"
1349 " \\{ \"name\": \"/test_forward\", \"type\": \"aos.TestMessage\" \\}"
1350 " is not able to be sent on this node");
1351
1352 EXPECT_FALSE(loop2->TryMakeSender<TestMessage>("/test_forward"));
1353
1354 EXPECT_DEATH(
1355 loop2->MakeRawFetcher(channel),
1356 "Channel"
1357 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1358 " is not able to be fetched on this node");
1359
1360 EXPECT_DEATH(
1361 loop2->MakeFetcher<TestMessage>("/test_noforward"),
1362 "Channel"
1363 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1364 " is not able to be fetched on this node");
1365
1366 EXPECT_FALSE(loop2->TryMakeFetcher<TestMessage>("/test_noforward").valid());
1367
1368 EXPECT_DEATH(
1369 { loop2->MakeRawWatcher(channel, [](const Context, const void *) {}); },
1370 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1371 "\"source_node\": \"them\" \\}"
1372 " is not able to be watched on this node");
1373
1374 EXPECT_DEATH(
1375 { loop2->MakeWatcher("/test_noforward", [](const TestMessage &) {}); },
1376 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1377 "\"source_node\": \"them\" \\}"
1378 " is not able to be watched on this node");
Austin Schuh54cf95f2019-11-29 13:14:18 -08001379}
1380
Austin Schuhd54780b2020-10-03 16:26:02 -07001381// Verifies that the event loop implementations detect when Channel has an
1382// invalid alignment.
1383TEST_P(AbstractEventLoopDeathTest, InvalidChannelAlignment) {
1384 const char *const kError = "multiple of alignment";
1385 InvalidChannelAlignment();
1386
1387 auto loop = MakePrimary();
1388
1389 const Channel *channel = configuration::GetChannel(
1390 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
1391
1392 EXPECT_DEATH({ loop->MakeRawSender(channel); }, kError);
1393 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); }, kError);
1394
1395 EXPECT_DEATH({ loop->MakeRawFetcher(channel); }, kError);
1396 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); }, kError);
1397
1398 EXPECT_DEATH(
1399 { loop->MakeRawWatcher(channel, [](const Context &, const void *) {}); },
1400 kError);
1401 EXPECT_DEATH({ loop->MakeRawNoArgWatcher(channel, [](const Context &) {}); },
1402 kError);
1403
1404 EXPECT_DEATH({ loop->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
1405 kError);
1406 EXPECT_DEATH({ loop->MakeWatcher("/test", [](const TestMessage &) {}); },
1407 kError);
1408}
1409
Brian Silverman454bc112020-03-05 14:21:25 -08001410// Verify that the send time on a message is roughly right when using a watcher.
Austin Schuh7267c532019-05-19 19:55:53 -07001411TEST_P(AbstractEventLoopTest, MessageSendTime) {
Austin Schuh44019f92019-05-19 19:58:27 -07001412 auto loop1 = MakePrimary();
Austin Schuh7267c532019-05-19 19:55:53 -07001413 auto loop2 = Make();
Austin Schuhad154822019-12-27 15:45:13 -08001414 auto sender = loop2->MakeSender<TestMessage>("/test");
Austin Schuh7267c532019-05-19 19:55:53 -07001415 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
1416
1417 auto test_timer = loop1->AddTimer([&sender]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001418 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1419 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1420 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001421 msg.CheckOk(msg.Send(builder.Finish()));
Alex Perrycb7da4b2019-08-28 19:35:56 -07001422 });
1423
Austin Schuhad154822019-12-27 15:45:13 -08001424 bool triggered = false;
Brian Silverman454bc112020-03-05 14:21:25 -08001425 loop1->MakeWatcher("/test", [&](const TestMessage &msg) {
Austin Schuhad154822019-12-27 15:45:13 -08001426 // Confirm that the data pointer makes sense from a watcher, and all the
1427 // timestamps look right.
1428 EXPECT_GT(&msg, loop1->context().data);
1429 EXPECT_EQ(loop1->context().monotonic_remote_time,
1430 loop1->context().monotonic_event_time);
1431 EXPECT_EQ(loop1->context().realtime_remote_time,
1432 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001433 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001434
1435 const aos::monotonic_clock::time_point monotonic_now =
1436 loop1->monotonic_now();
Tyler Chatow67ddb032020-01-12 14:30:04 -08001437 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08001438
1439 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1440 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1441 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1442 monotonic_now);
1443 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1444 realtime_now);
1445
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001446 EXPECT_LT(&msg, reinterpret_cast<const void *>(
1447 reinterpret_cast<const char *>(loop1->context().data) +
Austin Schuhad154822019-12-27 15:45:13 -08001448 loop1->context().size));
Brian Silverman4f4e0612020-08-12 19:54:41 -07001449 if (read_method() == ReadMethod::PIN) {
1450 EXPECT_GE(loop1->context().buffer_index, 0);
1451 EXPECT_LT(loop1->context().buffer_index,
1452 loop1->NumberBuffers(
1453 configuration::GetChannel(loop1->configuration(), "/test",
1454 "aos.TestMessage", "", nullptr)));
1455 } else {
1456 EXPECT_EQ(-1, loop1->context().buffer_index);
1457 }
Austin Schuhad154822019-12-27 15:45:13 -08001458 triggered = true;
Austin Schuh7267c532019-05-19 19:55:53 -07001459 });
1460
1461 test_timer->Setup(loop1->monotonic_now() + ::std::chrono::seconds(1));
1462
1463 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
Austin Schuh44019f92019-05-19 19:58:27 -07001464 Run();
Austin Schuh7267c532019-05-19 19:55:53 -07001465
Austin Schuhad154822019-12-27 15:45:13 -08001466 EXPECT_TRUE(triggered);
1467
Brian Silverman454bc112020-03-05 14:21:25 -08001468 ASSERT_TRUE(fetcher.Fetch());
1469
1470 monotonic_clock::duration monotonic_time_offset =
1471 fetcher.context().monotonic_event_time -
1472 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1473 realtime_clock::duration realtime_time_offset =
1474 fetcher.context().realtime_event_time -
1475 (loop1->realtime_now() - ::std::chrono::seconds(1));
1476
1477 EXPECT_EQ(fetcher.context().realtime_event_time,
1478 fetcher.context().realtime_remote_time);
1479 EXPECT_EQ(fetcher.context().monotonic_event_time,
1480 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001481 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001482
1483 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1484 << ": Got "
1485 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1486 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1487 // Confirm that the data pointer makes sense.
1488 EXPECT_GT(fetcher.get(), fetcher.context().data);
1489 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001490 reinterpret_cast<const void *>(
1491 reinterpret_cast<const char *>(fetcher.context().data) +
Brian Silverman454bc112020-03-05 14:21:25 -08001492 fetcher.context().size));
1493 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1494 << ": Got "
1495 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1496 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1497
1498 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1499 << ": Got "
1500 << fetcher.context().realtime_event_time.time_since_epoch().count()
1501 << " expected " << loop1->realtime_now().time_since_epoch().count();
1502 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1503 << ": Got "
1504 << fetcher.context().realtime_event_time.time_since_epoch().count()
1505 << " expected " << loop1->realtime_now().time_since_epoch().count();
1506}
1507
1508// Verify that the send time on a message is roughly right when using a no-arg
1509// watcher. To get a message, we need to use a fetcher to actually access the
1510// message. This is also the main use case for no-arg fetchers.
1511TEST_P(AbstractEventLoopTest, MessageSendTimeNoArg) {
1512 auto loop1 = MakePrimary();
1513 auto loop2 = Make();
1514 auto sender = loop2->MakeSender<TestMessage>("/test");
1515 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
1516
1517 auto test_timer = loop1->AddTimer([&sender]() {
1518 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1519 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1520 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001521 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -08001522 });
1523
1524 bool triggered = false;
1525 loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {
1526 // Confirm that we can indeed use a fetcher on this channel from this
1527 // context, and it results in a sane data pointer and timestamps.
1528 ASSERT_TRUE(fetcher.Fetch());
1529
1530 EXPECT_EQ(loop1->context().monotonic_remote_time,
1531 loop1->context().monotonic_event_time);
1532 EXPECT_EQ(loop1->context().realtime_remote_time,
1533 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001534 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001535
1536 const aos::monotonic_clock::time_point monotonic_now =
1537 loop1->monotonic_now();
1538 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
1539
1540 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1541 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1542 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1543 monotonic_now);
1544 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1545 realtime_now);
1546
1547 triggered = true;
1548 });
1549
1550 test_timer->Setup(loop1->monotonic_now() + ::std::chrono::seconds(1));
1551
1552 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
1553 Run();
1554
1555 ASSERT_TRUE(triggered);
Austin Schuh7267c532019-05-19 19:55:53 -07001556
Alex Perrycb7da4b2019-08-28 19:35:56 -07001557 monotonic_clock::duration monotonic_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001558 fetcher.context().monotonic_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001559 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1560 realtime_clock::duration realtime_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001561 fetcher.context().realtime_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001562 (loop1->realtime_now() - ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07001563
Austin Schuhad154822019-12-27 15:45:13 -08001564 EXPECT_EQ(fetcher.context().realtime_event_time,
1565 fetcher.context().realtime_remote_time);
1566 EXPECT_EQ(fetcher.context().monotonic_event_time,
1567 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001568 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001569
Alex Perrycb7da4b2019-08-28 19:35:56 -07001570 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1571 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001572 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh52d325c2019-06-23 18:59:06 -07001573 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07001574 // Confirm that the data pointer makes sense.
1575 EXPECT_GT(fetcher.get(), fetcher.context().data);
1576 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001577 reinterpret_cast<const void *>(
1578 reinterpret_cast<const char *>(fetcher.context().data) +
Alex Perrycb7da4b2019-08-28 19:35:56 -07001579 fetcher.context().size));
1580 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1581 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001582 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh7267c532019-05-19 19:55:53 -07001583 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07001584
1585 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1586 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001587 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07001588 << " expected " << loop1->realtime_now().time_since_epoch().count();
1589 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1590 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001591 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07001592 << " expected " << loop1->realtime_now().time_since_epoch().count();
Austin Schuh7267c532019-05-19 19:55:53 -07001593}
1594
Austin Schuh52d325c2019-06-23 18:59:06 -07001595// Tests that a couple phased loops run in a row result in the correct offset
1596// and period.
1597TEST_P(AbstractEventLoopTest, PhasedLoopTest) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001598 // Force a slower rate so we are guaranteed to have reports for our phased
Austin Schuh39788ff2019-12-01 18:22:57 -08001599 // loop.
1600 FLAGS_timing_report_ms = 2000;
1601
Austin Schuh52d325c2019-06-23 18:59:06 -07001602 const chrono::milliseconds kOffset = chrono::milliseconds(400);
1603 const int kCount = 5;
1604
1605 auto loop1 = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001606 auto loop2 = Make();
1607
1608 Fetcher<timing::Report> report_fetcher =
1609 loop2->MakeFetcher<timing::Report>("/aos");
1610 EXPECT_FALSE(report_fetcher.Fetch());
Austin Schuh52d325c2019-06-23 18:59:06 -07001611
1612 // Collect up a couple of samples.
1613 ::std::vector<::aos::monotonic_clock::time_point> times;
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001614 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
Austin Schuh52d325c2019-06-23 18:59:06 -07001615
1616 // Run kCount iterations.
Austin Schuh39788ff2019-12-01 18:22:57 -08001617 loop1
1618 ->AddPhasedLoop(
1619 [&times, &expected_times, &loop1, this](int count) {
1620 EXPECT_EQ(count, 1);
1621 times.push_back(loop1->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001622 expected_times.push_back(loop1->context().monotonic_event_time);
Austin Schuh39788ff2019-12-01 18:22:57 -08001623
Austin Schuhad154822019-12-27 15:45:13 -08001624 EXPECT_EQ(loop1->context().monotonic_remote_time,
1625 monotonic_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001626 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001627 EXPECT_EQ(loop1->context().realtime_event_time,
1628 realtime_clock::min_time);
1629 EXPECT_EQ(loop1->context().realtime_remote_time,
Austin Schuh39788ff2019-12-01 18:22:57 -08001630 realtime_clock::min_time);
1631 EXPECT_EQ(loop1->context().queue_index, 0xffffffffu);
1632 EXPECT_EQ(loop1->context().size, 0u);
1633 EXPECT_EQ(loop1->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001634 EXPECT_EQ(loop1->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001635
1636 if (times.size() == kCount) {
1637 LOG(INFO) << "Exiting";
1638 this->Exit();
1639 }
1640 },
1641 chrono::seconds(1), kOffset)
1642 ->set_name("Test loop");
Austin Schuh52d325c2019-06-23 18:59:06 -07001643
1644 // Add a delay to make sure that delay during startup doesn't result in a
1645 // "missed cycle".
1646 SleepFor(chrono::seconds(2));
1647
1648 Run();
1649
1650 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001651 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
1652 ASSERT_EQ(times.size(), expected_times.size());
1653 ASSERT_EQ((times.size() % 2), 1);
Austin Schuh52d325c2019-06-23 18:59:06 -07001654
1655 // Grab the middle sample.
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001656 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
Austin Schuh52d325c2019-06-23 18:59:06 -07001657
1658 // Add up all the delays of all the times.
1659 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1660 for (const ::aos::monotonic_clock::time_point time : times) {
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001661 sum += time - average_time;
Austin Schuh52d325c2019-06-23 18:59:06 -07001662 }
1663
1664 // Average and add to the middle to find the average time.
1665 sum /= times.size();
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001666 average_time += sum;
Austin Schuh52d325c2019-06-23 18:59:06 -07001667
1668 // Compute the offset from the start of the second of the average time. This
1669 // should be pretty close to the offset.
1670 const ::aos::monotonic_clock::duration remainder =
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001671 average_time.time_since_epoch() -
1672 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
Austin Schuh52d325c2019-06-23 18:59:06 -07001673
1674 const chrono::milliseconds kEpsilon(100);
1675 EXPECT_LT(remainder, kOffset + kEpsilon);
1676 EXPECT_GT(remainder, kOffset - kEpsilon);
1677
1678 // Make sure that the average duration is close to 1 second.
1679 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1680 times.front())
1681 .count() /
1682 static_cast<double>(times.size() - 1),
1683 1.0, 0.1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001684
1685 // Confirm that the ideal wakeup times increment correctly.
1686 for (size_t i = 1; i < expected_times.size(); ++i) {
1687 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1688 }
1689
1690 for (size_t i = 0; i < expected_times.size(); ++i) {
1691 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
1692 kOffset);
1693 }
1694
1695 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1696 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001697
Austin Schuh6bae8252021-02-07 22:01:49 -08001698 if (do_timing_reports() == DoTimingReports::kYes) {
1699 // And, since we are here, check that the timing report makes sense.
1700 // Start by looking for our event loop's timing.
1701 FlatbufferDetachedBuffer<timing::Report> report =
1702 FlatbufferDetachedBuffer<timing::Report>::Empty();
1703 while (report_fetcher.FetchNext()) {
1704 if (report_fetcher->name()->string_view() == "primary") {
1705 report = CopyFlatBuffer(report_fetcher.get());
1706 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001707 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001708
1709 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
1710
1711 EXPECT_EQ(report.message().name()->string_view(), "primary");
1712
1713 ASSERT_NE(report.message().senders(), nullptr);
1714 EXPECT_EQ(report.message().senders()->size(), 2);
1715
1716 ASSERT_NE(report.message().timers(), nullptr);
1717 EXPECT_EQ(report.message().timers()->size(), 1);
1718
1719 // Make sure there is a single phased loop report with our report in it.
1720 ASSERT_NE(report.message().phased_loops(), nullptr);
1721 ASSERT_EQ(report.message().phased_loops()->size(), 1);
1722 EXPECT_EQ(report.message().phased_loops()->Get(0)->name()->string_view(),
1723 "Test loop");
1724 EXPECT_GE(report.message().phased_loops()->Get(0)->count(), 1);
1725 } else {
1726 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001727 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001728}
1729
Milind Upadhyay42589bb2021-05-19 20:05:16 -07001730// Tests that a phased loop responds correctly to a changing offset.
1731TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetTest) {
1732 // Force a slower rate so we are guaranteed to have reports for our phased
1733 // loop.
1734 FLAGS_timing_report_ms = 2000;
1735
1736 const chrono::milliseconds kOffset = chrono::milliseconds(400);
1737 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
1738 const int kCount = 5;
1739
1740 auto loop1 = MakePrimary();
1741
1742 // Collect up a couple of samples.
1743 ::std::vector<::aos::monotonic_clock::time_point> times;
1744 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
1745
1746 PhasedLoopHandler *phased_loop;
1747
1748 // Run kCount iterations.
1749 phased_loop = loop1->AddPhasedLoop(
1750 [&phased_loop, &times, &expected_times, &loop1, this, kOffset,
1751 kInterval](int count) {
1752 EXPECT_EQ(count, 1);
1753 times.push_back(loop1->monotonic_now());
1754
1755 expected_times.push_back(loop1->context().monotonic_event_time);
1756
1757 phased_loop->set_interval_and_offset(
1758 kInterval, kOffset - chrono::milliseconds(times.size()));
1759 LOG(INFO) << "new offset: "
1760 << (kOffset - chrono::milliseconds(times.size())).count();
1761
1762 if (times.size() == kCount) {
1763 LOG(INFO) << "Exiting";
1764 this->Exit();
1765 }
1766 },
1767 kInterval, kOffset);
1768 phased_loop->set_name("Test loop");
1769
1770 // Add a delay to make sure that delay during startup doesn't result in a
1771 // "missed cycle".
1772 SleepFor(chrono::seconds(2));
1773
1774 Run();
1775 // Confirm that we got both the right number of samples, and it's odd.
1776 EXPECT_EQ(times.size(), static_cast<size_t>(kCount));
1777 EXPECT_EQ(times.size(), expected_times.size());
1778 EXPECT_EQ((times.size() % 2), 1);
1779
1780 // Grab the middle sample.
1781 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
1782
1783 // Add up all the delays of all the times.
1784 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1785 for (const ::aos::monotonic_clock::time_point time : times) {
1786 sum += time - average_time;
1787 }
1788
1789 // Average and add to the middle to find the average time.
1790 sum /= times.size();
1791 average_time += sum;
1792
1793 // Compute the offset from the start of the second of the average time. This
1794 // should be pretty close to the offset.
1795 const ::aos::monotonic_clock::duration remainder =
1796 average_time.time_since_epoch() -
1797 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
1798
1799 const chrono::milliseconds kEpsilon(100);
1800 EXPECT_LT(remainder, kOffset + kEpsilon);
1801 EXPECT_GT(remainder, kOffset - kEpsilon);
1802
1803 // Make sure that the average duration is close to 1 second.
1804 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1805 times.front())
1806 .count() /
1807 static_cast<double>(times.size() - 1),
1808 1.0, 0.1);
1809
1810 // Confirm that the ideal wakeup times increment correctly.
1811 for (size_t i = 1; i < expected_times.size(); ++i) {
1812 LOG(INFO) << i - 1 << ": " << expected_times[i - 1] << ", " << i << ": "
1813 << expected_times[i];
1814 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1) -
1815 chrono::milliseconds(1));
1816 }
1817
1818 for (size_t i = 0; i < expected_times.size(); ++i) {
1819 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
1820 kOffset - chrono::milliseconds(i));
1821 }
1822
1823 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1824 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
1825}
1826
Austin Schuh39788ff2019-12-01 18:22:57 -08001827// Tests that senders count correctly in the timing report.
1828TEST_P(AbstractEventLoopTest, SenderTimingReport) {
1829 FLAGS_timing_report_ms = 1000;
1830 auto loop1 = MakePrimary();
1831
1832 auto loop2 = Make("watcher_loop");
1833 loop2->MakeWatcher("/test", [](const TestMessage &) {});
1834
1835 auto loop3 = Make();
1836
1837 Fetcher<timing::Report> report_fetcher =
1838 loop3->MakeFetcher<timing::Report>("/aos");
1839 EXPECT_FALSE(report_fetcher.Fetch());
1840
1841 auto sender = loop1->MakeSender<TestMessage>("/test");
1842
James Kuszmaul78514332022-04-06 15:08:34 -07001843 // Sanity check channel frequencies to ensure that we've designed the test
1844 // correctly.
1845 ASSERT_EQ(800, sender.channel()->frequency());
1846 ASSERT_EQ(2000000000, loop1->configuration()->channel_storage_duration());
1847 constexpr int kMaxAllowedMessages = 800 * 2;
1848 constexpr int kSendMessages = kMaxAllowedMessages * 2;
1849 constexpr int kDroppedMessages = kSendMessages - kMaxAllowedMessages;
1850
Austin Schuh39788ff2019-12-01 18:22:57 -08001851 // Add a timer to actually quit.
1852 auto test_timer = loop1->AddTimer([&sender]() {
James Kuszmaul78514332022-04-06 15:08:34 -07001853 for (int i = 0; i < kSendMessages; ++i) {
Austin Schuh39788ff2019-12-01 18:22:57 -08001854 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1855 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1856 builder.add_value(200 + i);
James Kuszmaul78514332022-04-06 15:08:34 -07001857 if (i < kMaxAllowedMessages) {
1858 msg.CheckOk(msg.Send(builder.Finish()));
1859 } else {
1860 EXPECT_EQ(RawSender::Error::kMessagesSentTooFast,
1861 msg.Send(builder.Finish()));
1862 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001863 }
1864 });
1865
1866 // Quit after 1 timing report, mid way through the next cycle.
1867 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
1868
1869 loop1->OnRun([&test_timer, &loop1]() {
1870 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1500));
1871 });
1872
1873 Run();
1874
Austin Schuh6bae8252021-02-07 22:01:49 -08001875 if (do_timing_reports() == DoTimingReports::kYes) {
1876 // And, since we are here, check that the timing report makes sense.
1877 // Start by looking for our event loop's timing.
1878 FlatbufferDetachedBuffer<timing::Report> primary_report =
1879 FlatbufferDetachedBuffer<timing::Report>::Empty();
1880 while (report_fetcher.FetchNext()) {
Austin Schuh8902fa52021-03-14 22:39:24 -07001881 VLOG(1) << "Report " << FlatbufferToJson(report_fetcher.get());
Austin Schuh6bae8252021-02-07 22:01:49 -08001882 if (report_fetcher->name()->string_view() == "primary") {
1883 primary_report = CopyFlatBuffer(report_fetcher.get());
1884 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001885 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001886
Austin Schuh8902fa52021-03-14 22:39:24 -07001887 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
Austin Schuh6bae8252021-02-07 22:01:49 -08001888
1889 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
1890
1891 ASSERT_NE(primary_report.message().senders(), nullptr);
1892 EXPECT_EQ(primary_report.message().senders()->size(), 3);
1893
1894 // Confirm that the sender looks sane.
1895 EXPECT_EQ(
1896 loop1->configuration()
1897 ->channels()
1898 ->Get(primary_report.message().senders()->Get(0)->channel_index())
1899 ->name()
1900 ->string_view(),
1901 "/test");
James Kuszmaul78514332022-04-06 15:08:34 -07001902 EXPECT_EQ(primary_report.message().senders()->Get(0)->count(),
1903 kMaxAllowedMessages);
1904 ASSERT_TRUE(primary_report.message().senders()->Get(0)->has_error_counts());
1905 ASSERT_EQ(
1906 primary_report.message().senders()->Get(0)->error_counts()->size(), 2u);
1907 EXPECT_EQ(
1908 primary_report.message()
1909 .senders()
1910 ->Get(0)
1911 ->error_counts()
1912 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
1913 ->count(),
1914 kDroppedMessages)
1915 << aos::FlatbufferToJson(primary_report);
1916 EXPECT_EQ(primary_report.message()
1917 .senders()
1918 ->Get(0)
1919 ->error_counts()
1920 ->Get(static_cast<size_t>(timing::SendError::INVALID_REDZONE))
1921 ->count(),
1922 0);
Austin Schuh6bae8252021-02-07 22:01:49 -08001923
1924 // Confirm that the timing primary_report sender looks sane.
1925 EXPECT_EQ(
1926 loop1->configuration()
1927 ->channels()
1928 ->Get(primary_report.message().senders()->Get(1)->channel_index())
1929 ->name()
1930 ->string_view(),
1931 "/aos");
1932 EXPECT_EQ(primary_report.message().senders()->Get(1)->count(), 1);
1933
1934 ASSERT_NE(primary_report.message().timers(), nullptr);
1935 EXPECT_EQ(primary_report.message().timers()->size(), 3);
1936
1937 // Make sure there are no phased loops or watchers.
1938 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
1939 ASSERT_EQ(primary_report.message().watchers(), nullptr);
1940 } else {
1941 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001942 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001943}
1944
James Kuszmaul93abac12022-04-14 15:05:10 -07001945// Tests that the RawSender::Send(void*, size_t) overload tracks things properly
1946// in its timing report.
1947TEST_P(AbstractEventLoopTest, CopySenderTimingReport) {
1948 gflags::FlagSaver flag_saver;
1949 FLAGS_timing_report_ms = 1000;
1950 auto loop1 = Make();
1951 auto loop2 = MakePrimary();
1952
1953 const FlatbufferDetachedBuffer<TestMessage> kMessage =
1954 JsonToFlatbuffer<TestMessage>("{}");
1955
1956 std::unique_ptr<aos::RawSender> sender =
1957 loop2->MakeRawSender(configuration::GetChannel(
1958 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
1959
1960 Fetcher<timing::Report> report_fetcher =
1961 loop1->MakeFetcher<timing::Report>("/aos");
1962 EXPECT_FALSE(report_fetcher.Fetch());
1963
1964 loop2->OnRun([&]() {
1965 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
1966 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
1967 RawSender::Error::kOk);
1968 }
1969 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
1970 RawSender::Error::kMessagesSentTooFast);
1971 });
1972 // Quit after 1 timing report, mid way through the next cycle.
1973 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
1974
1975 Run();
1976
1977 if (do_timing_reports() == DoTimingReports::kYes) {
1978 // Check that the sent too fast actually got recorded by the timing report.
1979 FlatbufferDetachedBuffer<timing::Report> primary_report =
1980 FlatbufferDetachedBuffer<timing::Report>::Empty();
1981 while (report_fetcher.FetchNext()) {
1982 if (report_fetcher->name()->string_view() == "primary") {
1983 primary_report = CopyFlatBuffer(report_fetcher.get());
1984 }
1985 }
1986
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 EXPECT_EQ(
1992 primary_report.message()
1993 .senders()
1994 ->Get(0)
1995 ->error_counts()
1996 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
1997 ->count(),
1998 1);
1999 }
2000}
2001
Austin Schuh39788ff2019-12-01 18:22:57 -08002002// Tests that senders count correctly in the timing report.
2003TEST_P(AbstractEventLoopTest, WatcherTimingReport) {
2004 FLAGS_timing_report_ms = 1000;
2005 auto loop1 = MakePrimary();
2006 loop1->MakeWatcher("/test", [](const TestMessage &) {});
2007
2008 auto loop2 = Make("sender_loop");
2009
2010 auto loop3 = Make();
2011
2012 Fetcher<timing::Report> report_fetcher =
2013 loop3->MakeFetcher<timing::Report>("/aos");
2014 EXPECT_FALSE(report_fetcher.Fetch());
2015
2016 auto sender = loop2->MakeSender<TestMessage>("/test");
2017
2018 // Add a timer to actually quit.
2019 auto test_timer = loop1->AddTimer([&sender]() {
2020 for (int i = 0; i < 10; ++i) {
2021 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2022 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2023 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002024 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002025 }
2026 });
2027
2028 // Quit after 1 timing report, mid way through the next cycle.
2029 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2030
2031 loop1->OnRun([&test_timer, &loop1]() {
2032 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1500));
2033 });
2034
2035 Run();
2036
Austin Schuh6bae8252021-02-07 22:01:49 -08002037 if (do_timing_reports() == DoTimingReports::kYes) {
2038 // And, since we are here, check that the timing report makes sense.
2039 // Start by looking for our event loop's timing.
2040 FlatbufferDetachedBuffer<timing::Report> primary_report =
2041 FlatbufferDetachedBuffer<timing::Report>::Empty();
2042 while (report_fetcher.FetchNext()) {
2043 LOG(INFO) << "Report " << FlatbufferToJson(report_fetcher.get());
2044 if (report_fetcher->name()->string_view() == "primary") {
2045 primary_report = CopyFlatBuffer(report_fetcher.get());
2046 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002047 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002048
2049 // Check the watcher report.
2050 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2051
2052 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2053
2054 // Just the timing report timer.
2055 ASSERT_NE(primary_report.message().timers(), nullptr);
2056 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2057
2058 // No phased loops
2059 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2060
2061 ASSERT_NE(primary_report.message().watchers(), nullptr);
2062 ASSERT_EQ(primary_report.message().watchers()->size(), 1);
2063 EXPECT_EQ(primary_report.message().watchers()->Get(0)->count(), 10);
2064 } else {
2065 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002066 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002067}
2068
2069// Tests that fetchers count correctly in the timing report.
2070TEST_P(AbstractEventLoopTest, FetcherTimingReport) {
2071 FLAGS_timing_report_ms = 1000;
2072 auto loop1 = MakePrimary();
2073 auto loop2 = Make("sender_loop");
2074
2075 auto loop3 = Make();
2076
2077 Fetcher<timing::Report> report_fetcher =
2078 loop3->MakeFetcher<timing::Report>("/aos");
2079 EXPECT_FALSE(report_fetcher.Fetch());
2080
2081 auto sender = loop2->MakeSender<TestMessage>("/test");
2082 auto fetcher1 = loop1->MakeFetcher<TestMessage>("/test");
2083 auto fetcher2 = loop1->MakeFetcher<TestMessage>("/test");
2084 fetcher1.Fetch();
2085 fetcher2.Fetch();
2086
2087 // Add a timer to actually quit.
2088 auto test_timer = loop1->AddTimer([&sender]() {
2089 for (int i = 0; i < 10; ++i) {
2090 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2091 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2092 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002093 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002094 }
2095 });
2096
2097 auto test_timer2 = loop1->AddTimer([&fetcher1, &fetcher2]() {
2098 fetcher1.Fetch();
2099 while (fetcher2.FetchNext()) {
2100 }
2101 });
2102
2103 // Quit after 1 timing report, mid way through the next cycle.
2104 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2105
2106 loop1->OnRun([test_timer, test_timer2, &loop1]() {
2107 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1400));
2108 test_timer2->Setup(loop1->monotonic_now() + chrono::milliseconds(1600));
2109 });
2110
2111 Run();
2112
Austin Schuh6bae8252021-02-07 22:01:49 -08002113 if (do_timing_reports() == DoTimingReports::kYes) {
2114 // And, since we are here, check that the timing report makes sense.
2115 // Start by looking for our event loop's timing.
2116 FlatbufferDetachedBuffer<timing::Report> primary_report =
2117 FlatbufferDetachedBuffer<timing::Report>::Empty();
2118 while (report_fetcher.FetchNext()) {
2119 if (report_fetcher->name()->string_view() == "primary") {
2120 primary_report = CopyFlatBuffer(report_fetcher.get());
2121 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002122 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002123
2124 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2125
2126 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2127
2128 ASSERT_NE(primary_report.message().senders(), nullptr);
2129 EXPECT_EQ(primary_report.message().senders()->size(), 2);
2130
2131 ASSERT_NE(primary_report.message().timers(), nullptr);
2132 EXPECT_EQ(primary_report.message().timers()->size(), 4);
2133
2134 // Make sure there are no phased loops or watchers.
2135 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2136 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2137
2138 // Now look at the fetchrs.
2139 ASSERT_NE(primary_report.message().fetchers(), nullptr);
2140 ASSERT_EQ(primary_report.message().fetchers()->size(), 2);
2141
2142 EXPECT_EQ(primary_report.message().fetchers()->Get(0)->count(), 1);
2143 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->average(),
2144 0.1);
2145 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->min(),
2146 0.1);
2147 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->max(),
2148 0.1);
2149 EXPECT_EQ(primary_report.message()
2150 .fetchers()
2151 ->Get(0)
2152 ->latency()
2153 ->standard_deviation(),
2154 0.0);
2155
2156 EXPECT_EQ(primary_report.message().fetchers()->Get(1)->count(), 10);
2157 } else {
2158 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002159 }
Austin Schuh52d325c2019-06-23 18:59:06 -07002160}
2161
Austin Schuh67420a42019-12-21 21:55:04 -08002162// Tests that a raw watcher and raw fetcher can receive messages from a raw
2163// sender without messing up offsets.
2164TEST_P(AbstractEventLoopTest, RawBasic) {
2165 auto loop1 = Make();
2166 auto loop2 = MakePrimary();
2167 auto loop3 = Make();
2168
Austin Schuha9df9ad2021-06-16 14:49:39 -07002169 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2170 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuh67420a42019-12-21 21:55:04 -08002171
2172 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002173 loop1->MakeRawSender(configuration::GetChannel(
2174 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08002175
2176 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002177 loop3->MakeRawFetcher(configuration::GetChannel(
2178 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08002179
Austin Schuha9df9ad2021-06-16 14:49:39 -07002180 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002181 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2182 RawSender::Error::kOk);
Austin Schuha9df9ad2021-06-16 14:49:39 -07002183 });
Austin Schuh67420a42019-12-21 21:55:04 -08002184
2185 bool happened = false;
2186 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08002187 configuration::GetChannel(loop2->configuration(), "/test",
2188 "aos.TestMessage", "", nullptr),
Austin Schuha9df9ad2021-06-16 14:49:39 -07002189 [this, &kMessage, &fetcher, &happened](const Context &context,
2190 const void *message) {
Austin Schuh67420a42019-12-21 21:55:04 -08002191 happened = true;
Austin Schuha9df9ad2021-06-16 14:49:39 -07002192 EXPECT_EQ(
2193 kMessage.span(),
2194 absl::Span<const uint8_t>(
2195 reinterpret_cast<const uint8_t *>(message), context.size));
2196 EXPECT_EQ(message, context.data);
Austin Schuh67420a42019-12-21 21:55:04 -08002197
2198 ASSERT_TRUE(fetcher->Fetch());
2199
Austin Schuha9df9ad2021-06-16 14:49:39 -07002200 EXPECT_EQ(kMessage.span(),
2201 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
2202 fetcher->context().data),
2203 fetcher->context().size));
Austin Schuh67420a42019-12-21 21:55:04 -08002204
2205 this->Exit();
2206 });
2207
2208 EXPECT_FALSE(happened);
2209 Run();
2210 EXPECT_TRUE(happened);
2211}
2212
Austin Schuhad154822019-12-27 15:45:13 -08002213// Tests that a raw watcher and raw fetcher can receive messages from a raw
Brian Silvermanbf889922021-11-10 12:41:57 -08002214// sender without messing up offsets, using the RawSpan overload.
2215TEST_P(AbstractEventLoopTest, RawBasicSharedSpan) {
2216 auto loop1 = Make();
2217 auto loop2 = MakePrimary();
2218 auto loop3 = Make();
2219
2220 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2221 JsonToFlatbuffer<TestMessage>("{}");
2222
2223 std::unique_ptr<aos::RawSender> sender =
2224 loop1->MakeRawSender(configuration::GetChannel(
2225 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
2226
2227 std::unique_ptr<aos::RawFetcher> fetcher =
2228 loop3->MakeRawFetcher(configuration::GetChannel(
2229 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
2230
2231 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002232 EXPECT_EQ(sender->Send(std::make_shared<absl::Span<const uint8_t>>(
2233 kMessage.span().data(), kMessage.span().size())),
2234 RawSender::Error::kOk);
Brian Silvermanbf889922021-11-10 12:41:57 -08002235 });
2236
2237 bool happened = false;
2238 loop2->MakeRawWatcher(
2239 configuration::GetChannel(loop2->configuration(), "/test",
2240 "aos.TestMessage", "", nullptr),
2241 [this, &kMessage, &fetcher, &happened](const Context &context,
2242 const void *message) {
2243 happened = true;
2244 EXPECT_EQ(
2245 kMessage.span(),
2246 absl::Span<const uint8_t>(
2247 reinterpret_cast<const uint8_t *>(message), context.size));
2248 EXPECT_EQ(message, context.data);
2249
2250 ASSERT_TRUE(fetcher->Fetch());
2251
2252 EXPECT_EQ(kMessage.span(),
2253 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
2254 fetcher->context().data),
2255 fetcher->context().size));
2256
2257 this->Exit();
2258 });
2259
2260 EXPECT_FALSE(happened);
2261 Run();
2262 EXPECT_TRUE(happened);
2263}
2264
2265// Tests that a raw watcher and raw fetcher can receive messages from a raw
Austin Schuhad154822019-12-27 15:45:13 -08002266// sender with remote times filled out.
2267TEST_P(AbstractEventLoopTest, RawRemoteTimes) {
2268 auto loop1 = Make();
2269 auto loop2 = MakePrimary();
2270 auto loop3 = Make();
2271
Austin Schuha9df9ad2021-06-16 14:49:39 -07002272 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2273 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08002274
2275 const aos::monotonic_clock::time_point monotonic_remote_time =
2276 aos::monotonic_clock::time_point(chrono::seconds(1501));
2277 const aos::realtime_clock::time_point realtime_remote_time =
2278 aos::realtime_clock::time_point(chrono::seconds(3132));
Austin Schuhb5c6f972021-03-14 21:53:07 -07002279 const uint32_t remote_queue_index = 0x254971;
Austin Schuha9012be2021-07-21 15:19:11 -07002280 const UUID source_boot_uuid = UUID::Random();
Austin Schuhad154822019-12-27 15:45:13 -08002281
2282 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002283 loop1->MakeRawSender(configuration::GetChannel(
2284 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08002285
2286 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002287 loop3->MakeRawFetcher(configuration::GetChannel(
2288 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08002289
2290 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002291 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size(),
2292 monotonic_remote_time, realtime_remote_time,
2293 remote_queue_index, source_boot_uuid),
2294 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08002295 });
2296
2297 bool happened = false;
2298 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08002299 configuration::GetChannel(loop2->configuration(), "/test",
2300 "aos.TestMessage", "", nullptr),
Austin Schuha9012be2021-07-21 15:19:11 -07002301 [this, monotonic_remote_time, realtime_remote_time, source_boot_uuid,
Austin Schuhb5c6f972021-03-14 21:53:07 -07002302 remote_queue_index, &fetcher,
2303 &happened](const Context &context, const void * /*message*/) {
Austin Schuhad154822019-12-27 15:45:13 -08002304 happened = true;
2305 EXPECT_EQ(monotonic_remote_time, context.monotonic_remote_time);
2306 EXPECT_EQ(realtime_remote_time, context.realtime_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002307 EXPECT_EQ(source_boot_uuid, context.source_boot_uuid);
Austin Schuhb5c6f972021-03-14 21:53:07 -07002308 EXPECT_EQ(remote_queue_index, context.remote_queue_index);
Austin Schuhad154822019-12-27 15:45:13 -08002309
2310 ASSERT_TRUE(fetcher->Fetch());
2311 EXPECT_EQ(monotonic_remote_time,
2312 fetcher->context().monotonic_remote_time);
2313 EXPECT_EQ(realtime_remote_time,
2314 fetcher->context().realtime_remote_time);
2315
2316 this->Exit();
2317 });
2318
2319 EXPECT_FALSE(happened);
2320 Run();
2321 EXPECT_TRUE(happened);
2322}
2323
2324// Tests that a raw sender fills out sent data.
2325TEST_P(AbstractEventLoopTest, RawSenderSentData) {
2326 auto loop1 = MakePrimary();
2327
Austin Schuha9df9ad2021-06-16 14:49:39 -07002328 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2329 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08002330
2331 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002332 loop1->MakeRawSender(configuration::GetChannel(
2333 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08002334
Tyler Chatow67ddb032020-01-12 14:30:04 -08002335 const aos::monotonic_clock::time_point monotonic_now = loop1->monotonic_now();
2336 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08002337
milind1f1dca32021-07-03 13:50:07 -07002338 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2339 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08002340
2341 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
2342 EXPECT_LE(sender->monotonic_sent_time(),
2343 monotonic_now + chrono::milliseconds(100));
2344 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
2345 EXPECT_LE(sender->realtime_sent_time(),
2346 realtime_now + chrono::milliseconds(100));
2347 EXPECT_EQ(sender->sent_queue_index(), 0u);
2348
milind1f1dca32021-07-03 13:50:07 -07002349 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2350 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08002351
2352 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
2353 EXPECT_LE(sender->monotonic_sent_time(),
2354 monotonic_now + chrono::milliseconds(100));
2355 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
2356 EXPECT_LE(sender->realtime_sent_time(),
2357 realtime_now + chrono::milliseconds(100));
2358 EXPECT_EQ(sender->sent_queue_index(), 1u);
2359}
2360
Austin Schuh217a9782019-12-21 23:02:50 -08002361// Tests that not setting up nodes results in no node.
2362TEST_P(AbstractEventLoopTest, NoNode) {
2363 auto loop1 = Make();
2364 auto loop2 = MakePrimary();
2365
2366 EXPECT_EQ(loop1->node(), nullptr);
2367 EXPECT_EQ(loop2->node(), nullptr);
2368}
2369
2370// Tests that setting up nodes results in node being set.
2371TEST_P(AbstractEventLoopTest, Node) {
2372 EnableNodes("me");
2373
2374 auto loop1 = Make();
2375 auto loop2 = MakePrimary();
2376
2377 EXPECT_NE(loop1->node(), nullptr);
2378 EXPECT_NE(loop2->node(), nullptr);
2379}
2380
2381// Tests that watchers work with a node setup.
2382TEST_P(AbstractEventLoopTest, NodeWatcher) {
2383 EnableNodes("me");
2384
2385 auto loop1 = Make();
2386 auto loop2 = Make();
2387 loop1->MakeWatcher("/test", [](const TestMessage &) {});
Tyler Chatow67ddb032020-01-12 14:30:04 -08002388 loop2->MakeRawWatcher(
2389 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
2390 nullptr),
2391 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08002392}
2393
Brian Silverman454bc112020-03-05 14:21:25 -08002394// Tests that no-arg watchers work with a node setup.
2395TEST_P(AbstractEventLoopTest, NodeNoArgWatcher) {
2396 EnableNodes("me");
2397
2398 auto loop1 = Make();
2399 auto loop2 = Make();
2400 loop1->MakeWatcher("/test", [](const TestMessage &) {});
2401 loop2->MakeRawNoArgWatcher(
2402 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
2403 nullptr),
2404 [](const Context &) {});
2405}
2406
Austin Schuh217a9782019-12-21 23:02:50 -08002407// Tests that fetcher work with a node setup.
2408TEST_P(AbstractEventLoopTest, NodeFetcher) {
2409 EnableNodes("me");
2410 auto loop1 = Make();
2411
2412 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
Tyler Chatow67ddb032020-01-12 14:30:04 -08002413 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
2414 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08002415}
2416
2417// Tests that sender work with a node setup.
2418TEST_P(AbstractEventLoopTest, NodeSender) {
2419 EnableNodes("me");
2420 auto loop1 = Make();
2421
2422 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
2423}
2424
Austin Schuhcc6070c2020-10-10 20:25:56 -07002425// Tests that a non-realtime event loop timer is marked non-realtime.
2426TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopTimer) {
2427 auto loop1 = MakePrimary();
2428
2429 // Add a timer to actually quit.
2430 auto test_timer = loop1->AddTimer([this]() {
2431 CheckNotRealtime();
2432 this->Exit();
2433 });
2434
2435 loop1->OnRun([&test_timer, &loop1]() {
2436 CheckNotRealtime();
2437 test_timer->Setup(loop1->monotonic_now(), ::std::chrono::milliseconds(100));
2438 });
2439
2440 Run();
2441}
2442
2443// Tests that a realtime event loop timer is marked realtime.
Austin Schuh9b1d6282022-06-10 17:03:21 -07002444TEST_P(AbstractEventLoopTest, RealtimeSend) {
2445 auto loop1 = MakePrimary();
2446
2447 loop1->SetRuntimeRealtimePriority(1);
2448
2449 auto sender = loop1->MakeSender<TestMessage>("/test2");
2450
2451 loop1->OnRun([&]() {
2452 CheckRealtime();
2453
2454 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2455 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2456 builder.add_value(200);
2457 msg.CheckOk(msg.Send(builder.Finish()));
2458
2459 this->Exit();
2460 });
2461
2462 Run();
2463}
2464
2465// Tests that a realtime event loop timer is marked realtime.
Austin Schuhcc6070c2020-10-10 20:25:56 -07002466TEST_P(AbstractEventLoopTest, RealtimeEventLoopTimer) {
2467 auto loop1 = MakePrimary();
2468
2469 loop1->SetRuntimeRealtimePriority(1);
2470
2471 // Add a timer to actually quit.
2472 auto test_timer = loop1->AddTimer([this]() {
2473 CheckRealtime();
2474 this->Exit();
2475 });
2476
2477 loop1->OnRun([&test_timer, &loop1]() {
2478 CheckRealtime();
2479 test_timer->Setup(loop1->monotonic_now(), ::std::chrono::milliseconds(100));
2480 });
2481
2482 Run();
2483}
2484
2485// Tests that a non-realtime event loop phased loop is marked non-realtime.
2486TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopPhasedLoop) {
2487 auto loop1 = MakePrimary();
2488
2489 // Add a timer to actually quit.
2490 loop1->AddPhasedLoop(
2491 [this](int) {
2492 CheckNotRealtime();
2493 this->Exit();
2494 },
2495 chrono::seconds(1), chrono::seconds(0));
2496
2497 Run();
2498}
2499
2500// Tests that a realtime event loop phased loop is marked realtime.
2501TEST_P(AbstractEventLoopTest, RealtimeEventLoopPhasedLoop) {
2502 auto loop1 = MakePrimary();
2503
2504 loop1->SetRuntimeRealtimePriority(1);
2505
2506 // Add a timer to actually quit.
2507 loop1->AddPhasedLoop(
2508 [this](int) {
2509 CheckRealtime();
2510 this->Exit();
2511 },
2512 chrono::seconds(1), chrono::seconds(0));
2513
2514 Run();
2515}
2516
2517// Tests that a non-realtime event loop watcher is marked non-realtime.
2518TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopWatcher) {
2519 auto loop1 = MakePrimary();
2520 auto loop2 = Make();
2521
2522 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
2523
2524 loop1->OnRun([&]() {
2525 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2526 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07002527 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07002528 });
2529
2530 loop1->MakeWatcher("/test", [&](const TestMessage &) {
2531 CheckNotRealtime();
2532 this->Exit();
2533 });
2534
2535 Run();
2536}
2537
2538// Tests that a realtime event loop watcher is marked realtime.
2539TEST_P(AbstractEventLoopTest, RealtimeEventLoopWatcher) {
2540 auto loop1 = MakePrimary();
2541 auto loop2 = Make();
2542
2543 loop1->SetRuntimeRealtimePriority(1);
2544
2545 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
2546
2547 loop1->OnRun([&]() {
2548 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2549 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07002550 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07002551 });
2552
2553 loop1->MakeWatcher("/test", [&](const TestMessage &) {
2554 CheckRealtime();
2555 this->Exit();
2556 });
2557
2558 Run();
2559}
2560
Austin Schuha9012be2021-07-21 15:19:11 -07002561// Tests that event loop's context's monotonic time is set to a value on OnRun.
2562TEST_P(AbstractEventLoopTest, SetContextOnRun) {
2563 auto loop = MakePrimary();
2564
Austin Schuh0debde12022-08-17 16:25:17 -07002565 EXPECT_EQ(loop->context().monotonic_event_time, monotonic_clock::min_time);
2566 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
2567 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
2568 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
2569 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
2570 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
2571 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
2572 EXPECT_EQ(loop->context().size, 0u);
2573 EXPECT_EQ(loop->context().data, nullptr);
2574 EXPECT_EQ(loop->context().buffer_index, -1);
2575
Austin Schuha9012be2021-07-21 15:19:11 -07002576 // We want to check that monotonic event time is before monotonic now
2577 // called inside of callback, but after time point obtained callback.
2578 aos::monotonic_clock::time_point monotonic_event_time_on_run;
2579
2580 loop->OnRun([&]() {
2581 monotonic_event_time_on_run = loop->context().monotonic_event_time;
2582 EXPECT_LE(monotonic_event_time_on_run, loop->monotonic_now());
2583 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
2584 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
2585 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
2586 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
2587 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
Austin Schuh0debde12022-08-17 16:25:17 -07002588 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
Austin Schuha9012be2021-07-21 15:19:11 -07002589 EXPECT_EQ(loop->context().size, 0u);
2590 EXPECT_EQ(loop->context().data, nullptr);
2591 EXPECT_EQ(loop->context().buffer_index, -1);
2592 });
2593
2594 EndEventLoop(loop.get(), ::std::chrono::milliseconds(200));
2595
2596 const aos::monotonic_clock::time_point before_run_time =
2597 loop->monotonic_now();
2598 Run();
2599 EXPECT_GE(monotonic_event_time_on_run, before_run_time);
Austin Schuh0debde12022-08-17 16:25:17 -07002600
2601 EXPECT_EQ(loop->context().monotonic_event_time, monotonic_clock::min_time);
2602 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
2603 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
2604 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
2605 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
2606 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
2607 EXPECT_EQ(loop->context().remote_queue_index, 0xffffffffu);
2608 EXPECT_EQ(loop->context().size, 0u);
2609 EXPECT_EQ(loop->context().data, nullptr);
2610 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuha9012be2021-07-21 15:19:11 -07002611}
2612
Austin Schuh217a9782019-12-21 23:02:50 -08002613// Tests that watchers fail when created on the wrong node.
2614TEST_P(AbstractEventLoopDeathTest, NodeWatcher) {
2615 EnableNodes("them");
2616
2617 auto loop1 = Make();
2618 auto loop2 = Make();
2619 EXPECT_DEATH({ loop1->MakeWatcher("/test", [](const TestMessage &) {}); },
2620 "node");
2621 EXPECT_DEATH(
2622 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08002623 loop2->MakeRawWatcher(
2624 configuration::GetChannel(configuration(), "/test",
2625 "aos.TestMessage", "", nullptr),
2626 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08002627 },
2628 "node");
Brian Silverman454bc112020-03-05 14:21:25 -08002629 EXPECT_DEATH({ loop1->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
2630 "node");
2631 EXPECT_DEATH(
2632 {
2633 loop2->MakeRawNoArgWatcher(
2634 configuration::GetChannel(configuration(), "/test",
2635 "aos.TestMessage", "", nullptr),
2636 [](const Context &) {});
2637 },
2638 "node");
Austin Schuh217a9782019-12-21 23:02:50 -08002639}
2640
2641// Tests that fetchers fail when created on the wrong node.
2642TEST_P(AbstractEventLoopDeathTest, NodeFetcher) {
2643 EnableNodes("them");
2644 auto loop1 = Make();
2645
2646 EXPECT_DEATH({ auto fetcher = loop1->MakeFetcher<TestMessage>("/test"); },
2647 "node");
2648 EXPECT_DEATH(
2649 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08002650 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
2651 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08002652 },
2653 "node");
2654}
2655
2656// Tests that senders fail when created on the wrong node.
2657TEST_P(AbstractEventLoopDeathTest, NodeSender) {
2658 EnableNodes("them");
2659 auto loop1 = Make();
2660
2661 EXPECT_DEATH(
2662 {
2663 aos::Sender<TestMessage> sender =
2664 loop1->MakeSender<TestMessage>("/test");
2665 },
2666 "node");
2667
2668 // Note: Creating raw senders is always supported. Right now, this lets us
2669 // use them to create message_gateway.
2670}
2671
Brian Silverman341b57e2020-06-23 16:23:18 -07002672// Tests creating multiple Builders from a single Sender at the same time.
2673TEST_P(AbstractEventLoopDeathTest, MultipleBuilders) {
2674 auto loop1 = Make();
2675 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
2676
2677 { auto builder = sender.MakeBuilder(); }
2678 {
2679 auto builder = sender.MakeBuilder();
2680 builder.MakeBuilder<TestMessage>().Finish();
2681 }
2682 {
2683 // Creating this after the first one was destroyed should be fine.
2684 auto builder = sender.MakeBuilder();
2685 builder.MakeBuilder<TestMessage>().Finish();
2686 // But not a second one.
2687 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
2688 "May not overwrite in-use allocator");
2689 }
2690
2691 FlatbufferDetachedBuffer<TestMessage> detached =
2692 flatbuffers::DetachedBuffer();
2693 {
2694 auto builder = sender.MakeBuilder();
2695 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
2696 }
2697 {
2698 // This is the second one, after the detached one, so it should fail.
2699 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
2700 "May not overwrite in-use allocator");
2701 }
2702
2703 // Clear the detached one, and then we should be able to create another.
2704 detached = flatbuffers::DetachedBuffer();
2705 {
2706 auto builder = sender.MakeBuilder();
2707 builder.MakeBuilder<TestMessage>().Finish();
2708 }
2709
2710 // And then detach another one.
2711 {
2712 auto builder = sender.MakeBuilder();
2713 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
2714 }
2715}
2716
2717// Tests sending a buffer detached from a different builder.
2718TEST_P(AbstractEventLoopDeathTest, WrongDetachedBuffer) {
2719 auto loop1 = Make();
2720 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
2721 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
2722
2723 auto builder = sender1.MakeBuilder();
2724 FlatbufferDetachedBuffer<TestMessage> detached =
2725 builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
milind1f1dca32021-07-03 13:50:07 -07002726 EXPECT_DEATH(sender2.CheckOk(sender2.SendDetached(std::move(detached))),
Brian Silverman341b57e2020-06-23 16:23:18 -07002727 "May only send the buffer detached from this Sender");
2728}
2729
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07002730int TestChannelFrequency(EventLoop *event_loop) {
2731 return event_loop->GetChannel<TestMessage>("/test")->frequency();
2732}
2733
2734int TestChannelQueueSize(EventLoop *event_loop) {
2735 const int frequency = TestChannelFrequency(event_loop);
2736 const auto channel_storage_duration = std::chrono::nanoseconds(
2737 event_loop->configuration()->channel_storage_duration());
2738 const int queue_size =
2739 frequency * std::chrono::duration_cast<std::chrono::duration<double>>(
2740 channel_storage_duration)
2741 .count();
2742
2743 return queue_size;
2744}
2745
2746RawSender::Error SendTestMessage(aos::Sender<TestMessage> &sender) {
2747 aos::Sender<TestMessage>::Builder builder = sender.MakeBuilder();
2748 TestMessage::Builder test_message_builder =
2749 builder.MakeBuilder<TestMessage>();
2750 test_message_builder.add_value(0);
2751 return builder.Send(test_message_builder.Finish());
2752}
2753
2754// Test that sending messages too fast returns
2755// RawSender::Error::kMessagesSentTooFast.
2756TEST_P(AbstractEventLoopTest, SendingMessagesTooFast) {
2757 auto event_loop = MakePrimary();
2758
2759 auto sender = event_loop->MakeSender<TestMessage>("/test");
2760
2761 // Send one message in the beginning, then wait until the
2762 // channel_storage_duration is almost done and start sending messages rapidly,
2763 // having some come in the next chanel_storage_duration. The queue_size is
2764 // 1600, so the 1601st message will be the last valid one (the initial message
2765 // having being sent more than a channel_storage_duration ago), and trying to
2766 // send the 1602nd message should return
2767 // RawSender::Error::kMessagesSentTooFast.
2768 EXPECT_EQ(SendTestMessage(sender), RawSender::Error::kOk);
2769 int msgs_sent = 1;
2770 const int queue_size = TestChannelQueueSize(event_loop.get());
2771
2772 const auto timer = event_loop->AddTimer([&]() {
2773 const bool done = (msgs_sent == queue_size + 1);
2774 ASSERT_EQ(
2775 SendTestMessage(sender),
2776 done ? RawSender::Error::kMessagesSentTooFast : RawSender::Error::kOk);
2777 msgs_sent++;
2778 if (done) {
2779 Exit();
2780 }
2781 });
2782
2783 const auto kRepeatOffset = std::chrono::milliseconds(1);
2784 const auto base_offset =
2785 std::chrono::nanoseconds(
2786 event_loop->configuration()->channel_storage_duration()) -
2787 (kRepeatOffset * (queue_size / 2));
2788 event_loop->OnRun([&event_loop, &timer, &base_offset, &kRepeatOffset]() {
2789 timer->Setup(event_loop->monotonic_now() + base_offset, kRepeatOffset);
2790 });
2791
2792 Run();
2793}
2794
2795// Tests that we are able to send messages successfully after sending messages
2796// too fast and waiting while continuously attempting to send messages.
2797// Also tests that SendFailureCounter is working correctly in this
2798// situation
2799TEST_P(AbstractEventLoopTest, SendingAfterSendingTooFast) {
2800 auto event_loop = MakePrimary();
2801
2802 auto sender = event_loop->MakeSender<TestMessage>("/test");
2803
2804 // We are sending messages at 1 kHz, so we will be sending too fast after
2805 // queue_size (1600) ms. After this, keep sending messages, and exactly a
2806 // channel storage duration (2s) after we send the first message we should
2807 // be able to successfully send a message.
2808
2809 const monotonic_clock::duration kInterval = std::chrono::milliseconds(1);
2810 const monotonic_clock::duration channel_storage_duration =
2811 std::chrono::nanoseconds(
2812 event_loop->configuration()->channel_storage_duration());
2813 const int queue_size = TestChannelQueueSize(event_loop.get());
2814
2815 int msgs_sent = 0;
2816 SendFailureCounter counter;
2817 auto start = monotonic_clock::min_time;
2818
2819 event_loop->AddPhasedLoop(
2820 [&](int) {
2821 const auto actual_err = SendTestMessage(sender);
2822 const bool done_waiting = (start != monotonic_clock::min_time &&
2823 sender.monotonic_sent_time() >=
2824 (start + channel_storage_duration));
2825 const auto expected_err =
2826 (msgs_sent < queue_size || done_waiting
2827 ? RawSender::Error::kOk
2828 : RawSender::Error::kMessagesSentTooFast);
2829
2830 if (start == monotonic_clock::min_time) {
2831 start = sender.monotonic_sent_time();
2832 }
2833
2834 ASSERT_EQ(actual_err, expected_err);
2835 counter.Count(actual_err);
2836 msgs_sent++;
2837
2838 EXPECT_EQ(counter.failures(),
2839 msgs_sent <= queue_size
2840 ? 0
2841 : (msgs_sent - queue_size) -
2842 (actual_err == RawSender::Error::kOk ? 1 : 0));
2843 EXPECT_EQ(counter.just_failed(), actual_err != RawSender::Error::kOk);
2844
2845 if (done_waiting) {
2846 Exit();
2847 }
2848 },
2849 kInterval);
2850 Run();
2851}
2852
2853// Tests that RawSender::Error::kMessagesSentTooFast is returned
2854// when messages are sent too fast from senders in different loops
2855TEST_P(AbstractEventLoopTest, SendingTooFastWithMultipleLoops) {
2856 auto loop1 = MakePrimary();
2857 auto loop2 = Make();
2858
2859 auto sender1 = loop1->MakeSender<TestMessage>("/test");
2860 auto sender2 = loop2->MakeSender<TestMessage>("/test");
2861
2862 // Send queue_size messages split between the senders.
2863 const int queue_size = TestChannelQueueSize(loop1.get());
2864 for (int i = 0; i < queue_size / 2; i++) {
2865 ASSERT_EQ(SendTestMessage(sender1), RawSender::Error::kOk);
2866 ASSERT_EQ(SendTestMessage(sender2), RawSender::Error::kOk);
2867 }
2868
2869 // Since queue_size messages have been sent, this should return an error
2870 EXPECT_EQ(SendTestMessage(sender2), RawSender::Error::kMessagesSentTooFast);
2871}
2872
Parker Schuhe4a70d62017-12-27 20:10:20 -08002873} // namespace testing
2874} // namespace aos