blob: 2d7decc4aedca07d8fa64f2b94bc4b2e41c6e9bc [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
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800755// Verify that registering a watcher twice for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700756TEST_P(AbstractEventLoopDeathTest, TwoWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800757 auto loop = Make();
758 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800759 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
760 "/test");
Brian Silverman454bc112020-03-05 14:21:25 -0800761 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
762}
763
764// Verify that registering a no-arg watcher twice for "/test" fails.
765TEST_P(AbstractEventLoopDeathTest, TwoNoArgWatcher) {
766 auto loop = Make();
767 loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {});
768 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
769 "/test");
770 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800771}
772
Austin Schuh3115a202019-05-27 21:02:14 -0700773// Verify that SetRuntimeRealtimePriority fails while running.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700774TEST_P(AbstractEventLoopDeathTest, SetRuntimeRealtimePriority) {
Austin Schuh3115a202019-05-27 21:02:14 -0700775 auto loop = MakePrimary();
776 // Confirm that runtime priority calls work when not realtime.
777 loop->SetRuntimeRealtimePriority(5);
778
779 loop->OnRun([&]() { loop->SetRuntimeRealtimePriority(5); });
780
781 EXPECT_DEATH(Run(), "realtime");
782}
783
Brian Silverman6a54ff32020-04-28 16:41:39 -0700784// Verify that SetRuntimeAffinity fails while running.
785TEST_P(AbstractEventLoopDeathTest, SetRuntimeAffinity) {
Austin Schuhde973292021-10-12 18:09:49 -0700786 const cpu_set_t available = GetCurrentThreadAffinity();
787 int first_cpu = -1;
788 for (int i = 0; i < CPU_SETSIZE; ++i) {
789 if (CPU_ISSET(i, &available)) {
790 first_cpu = i;
791 break;
792 continue;
793 }
794 }
795 CHECK_NE(first_cpu, -1) << ": Default affinity has no CPUs?";
796
Brian Silverman6a54ff32020-04-28 16:41:39 -0700797 auto loop = MakePrimary();
798 // Confirm that runtime priority calls work when not running.
Austin Schuhde973292021-10-12 18:09:49 -0700799 loop->SetRuntimeAffinity(MakeCpusetFromCpus({first_cpu}));
Brian Silverman6a54ff32020-04-28 16:41:39 -0700800
Austin Schuhde973292021-10-12 18:09:49 -0700801 loop->OnRun(
802 [&]() { loop->SetRuntimeAffinity(MakeCpusetFromCpus({first_cpu})); });
Brian Silverman6a54ff32020-04-28 16:41:39 -0700803
804 EXPECT_DEATH(Run(), "Cannot set affinity while running");
805}
806
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800807// Verify that registering a watcher and a sender for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700808TEST_P(AbstractEventLoopDeathTest, WatcherAndSender) {
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800809 auto loop = Make();
810 auto sender = loop->MakeSender<TestMessage>("/test");
811 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
812 "/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -0800813}
814
Austin Schuhe516ab02020-05-06 21:37:04 -0700815// Verify that creating too many senders fails.
816TEST_P(AbstractEventLoopDeathTest, TooManySenders) {
817 auto loop = Make();
818 std::vector<aos::Sender<TestMessage>> senders;
819 for (int i = 0; i < 10; ++i) {
820 senders.emplace_back(loop->MakeSender<TestMessage>("/test"));
821 }
822 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); },
823 "Failed to create sender on \\{ \"name\": \"/test\", \"type\": "
Brian Silverman77162972020-08-12 19:52:40 -0700824 "\"aos.TestMessage\"[^}]*\\ }, too many senders.");
825}
826
827// Verify that creating too many fetchers fails.
828TEST_P(AbstractEventLoopDeathTest, TooManyFetchers) {
829 if (read_method() != ReadMethod::PIN) {
830 // Other read methods don't limit the number of readers, so just skip this.
831 return;
832 }
833
834 auto loop = Make();
835 std::vector<aos::Fetcher<TestMessage>> fetchers;
836 for (int i = 0; i < 10; ++i) {
837 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
838 }
839 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
840 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
841 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
842}
843
844// Verify that creating too many fetchers, split between two event loops, fails.
845TEST_P(AbstractEventLoopDeathTest, TooManyFetchersTwoLoops) {
846 if (read_method() != ReadMethod::PIN) {
847 // Other read methods don't limit the number of readers, so just skip this.
848 return;
849 }
850
851 auto loop = Make();
852 auto loop2 = Make();
853 std::vector<aos::Fetcher<TestMessage>> fetchers;
854 for (int i = 0; i < 5; ++i) {
855 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
856 fetchers.emplace_back(loop2->MakeFetcher<TestMessage>("/test"));
857 }
858 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
859 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
860 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
861}
862
863// Verify that creating too many watchers fails.
864TEST_P(AbstractEventLoopDeathTest, TooManyWatchers) {
865 if (read_method() != ReadMethod::PIN) {
866 // Other read methods don't limit the number of readers, so just skip this.
867 return;
868 }
869
870 std::vector<std::unique_ptr<EventLoop>> loops;
871 for (int i = 0; i < 10; ++i) {
872 loops.emplace_back(Make());
873 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
874 }
875 EXPECT_DEATH({ Make()->MakeWatcher("/test", [](const TestMessage &) {}); },
876 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
877 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
878}
879
880// Verify that creating too many watchers and fetchers combined fails.
881TEST_P(AbstractEventLoopDeathTest, TooManyWatchersAndFetchers) {
882 if (read_method() != ReadMethod::PIN) {
883 // Other read methods don't limit the number of readers, so just skip this.
884 return;
885 }
886
887 auto loop = Make();
888 std::vector<aos::Fetcher<TestMessage>> fetchers;
889 std::vector<std::unique_ptr<EventLoop>> loops;
890 for (int i = 0; i < 5; ++i) {
891 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
892 loops.emplace_back(Make());
893 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
894 }
895 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
896 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
897 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
Austin Schuhe516ab02020-05-06 21:37:04 -0700898}
899
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700900// Verify that we can't create a sender inside OnRun.
901TEST_P(AbstractEventLoopDeathTest, SenderInOnRun) {
902 auto loop1 = MakePrimary();
903
904 loop1->OnRun(
905 [&]() { auto sender = loop1->MakeSender<TestMessage>("/test2"); });
906
907 EXPECT_DEATH(Run(), "running");
908}
909
910// Verify that we can't create a watcher inside OnRun.
911TEST_P(AbstractEventLoopDeathTest, WatcherInOnRun) {
912 auto loop1 = MakePrimary();
913
914 loop1->OnRun(
915 [&]() { loop1->MakeWatcher("/test", [&](const TestMessage &) {}); });
916
917 EXPECT_DEATH(Run(), "running");
918}
919
Brian Silverman454bc112020-03-05 14:21:25 -0800920// Verify that we can't create a no-arg watcher inside OnRun.
921TEST_P(AbstractEventLoopDeathTest, NoArgWatcherInOnRun) {
922 auto loop1 = MakePrimary();
923
924 loop1->OnRun(
925 [&]() { loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {}); });
926
927 EXPECT_DEATH(Run(), "running");
928}
929
Parker Schuhe4a70d62017-12-27 20:10:20 -0800930// Verify that Quit() works when there are multiple watchers.
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800931TEST_P(AbstractEventLoopTest, MultipleWatcherQuit) {
932 auto loop1 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -0700933 auto loop2 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800934
Austin Schuh3578a2e2019-05-25 18:17:59 -0700935 loop2->MakeWatcher("/test1", [&](const TestMessage &) {});
936 loop2->MakeWatcher("/test2", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700937 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -0700938 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -0700939 });
940
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800941 auto sender = loop1->MakeSender<TestMessage>("/test2");
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700942
943 loop2->OnRun([&]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700944 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
945 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
946 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700947 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700948 });
Parker Schuhe4a70d62017-12-27 20:10:20 -0800949
Austin Schuh44019f92019-05-19 19:58:27 -0700950 Run();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800951}
952
Austin Schuhad9e5eb2021-11-19 20:33:55 -0800953// Verify that AOS_LOG has the right name.
954TEST_P(AbstractEventLoopTest, AOSLog) {
955 auto loop2 = MakePrimary("loop1");
956 auto loop1 = Make("loop0");
957
958 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
959
960 EXPECT_FALSE(fetcher.Fetch());
961
962 loop2->OnRun([&]() {
963 AOS_LOG(INFO, "Testing123");
964 this->Exit();
965 });
966
967 Run();
968 EXPECT_TRUE(fetcher.Fetch());
969 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
970}
971
972// Verify that AOS_LOG has the right name in a watcher.
973TEST_P(AbstractEventLoopTest, AOSLogWatcher) {
974 auto loop2 = MakePrimary("loop1");
975 auto loop1 = Make("loop0");
976
977 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
978
979 EXPECT_FALSE(fetcher.Fetch());
980
981 auto sender = loop1->MakeSender<TestMessage>("/test2");
982
983 loop2->MakeWatcher("/test2", [&](const TestMessage & /*message*/) {
984 AOS_LOG(INFO, "Testing123");
985 this->Exit();
986 });
987
988 loop2->OnRun([&]() {
989 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
990 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
991 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700992 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhad9e5eb2021-11-19 20:33:55 -0800993 });
994
995 Run();
996 EXPECT_TRUE(fetcher.Fetch());
997 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
998}
999
1000// Verify that AOS_LOG has the right name in a timer.
1001TEST_P(AbstractEventLoopTest, AOSLogTimer) {
1002 auto loop2 = MakePrimary("loop1");
1003 auto loop1 = Make("loop0");
1004
1005 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1006
1007 EXPECT_FALSE(fetcher.Fetch());
1008
1009 auto test_timer = loop2->AddTimer([&]() {
1010 AOS_LOG(INFO, "Testing123");
1011 this->Exit();
1012 });
1013
1014 loop2->OnRun([&]() { test_timer->Setup(loop2->monotonic_now()); });
1015
1016 Run();
1017 EXPECT_TRUE(fetcher.Fetch());
1018 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1019}
1020
Neil Balch229001a2018-01-07 18:22:52 -08001021// Verify that timer intervals and duration function properly.
1022TEST_P(AbstractEventLoopTest, TimerIntervalAndDuration) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001023 // Force a slower rate so we are guaranteed to have reports for our timer.
Austin Schuh39788ff2019-12-01 18:22:57 -08001024 FLAGS_timing_report_ms = 2000;
1025
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001026 const int kCount = 5;
Neil Balch229001a2018-01-07 18:22:52 -08001027
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001028 auto loop = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001029 auto loop2 = Make();
1030
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001031 ::std::vector<::aos::monotonic_clock::time_point> times;
1032 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
1033
Austin Schuh39788ff2019-12-01 18:22:57 -08001034 Fetcher<timing::Report> report_fetcher =
1035 loop2->MakeFetcher<timing::Report>("/aos");
1036 EXPECT_FALSE(report_fetcher.Fetch());
1037
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001038 auto test_timer = loop->AddTimer([this, &times, &expected_times, &loop]() {
1039 times.push_back(loop->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001040 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
1041 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
1042 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001043 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -08001044 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
1045 EXPECT_EQ(loop->context().size, 0u);
1046 EXPECT_EQ(loop->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001047 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001048
Austin Schuhad154822019-12-27 15:45:13 -08001049 expected_times.push_back(loop->context().monotonic_event_time);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001050 if (times.size() == kCount) {
1051 this->Exit();
1052 }
Neil Balch229001a2018-01-07 18:22:52 -08001053 });
Austin Schuh39788ff2019-12-01 18:22:57 -08001054 test_timer->set_name("Test loop");
Neil Balch229001a2018-01-07 18:22:52 -08001055
Austin Schuh39788ff2019-12-01 18:22:57 -08001056 const monotonic_clock::time_point start_time = loop->monotonic_now();
Austin Schuh52d325c2019-06-23 18:59:06 -07001057 // TODO(austin): This should be an error... Should be done in OnRun only.
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001058 test_timer->Setup(start_time + chrono::seconds(1), chrono::seconds(1));
1059
Austin Schuh44019f92019-05-19 19:58:27 -07001060 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001061
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001062 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001063 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
1064 ASSERT_EQ(times.size(), expected_times.size());
1065 ASSERT_EQ((times.size() % 2), 1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001066
1067 // Grab the middle sample.
1068 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
1069
1070 // Add up all the delays of all the times.
1071 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1072 for (const ::aos::monotonic_clock::time_point time : times) {
1073 sum += time - average_time;
1074 }
1075
1076 // Average and add to the middle to find the average time.
1077 sum /= times.size();
1078 average_time += sum;
1079
1080 // Compute the offset from the average and the expected average. It
1081 // should be pretty close to 0.
1082 const ::aos::monotonic_clock::duration remainder =
1083 average_time - start_time - chrono::seconds(times.size() / 2 + 1);
1084
1085 const chrono::milliseconds kEpsilon(100);
1086 EXPECT_LT(remainder, +kEpsilon);
1087 EXPECT_GT(remainder, -kEpsilon);
1088
1089 // Make sure that the average duration is close to 1 second.
1090 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1091 times.front())
1092 .count() /
1093 static_cast<double>(times.size() - 1),
1094 1.0, 0.1);
1095
1096 // Confirm that the ideal wakeup times increment correctly.
1097 for (size_t i = 1; i < expected_times.size(); ++i) {
1098 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1099 }
1100
1101 for (size_t i = 0; i < expected_times.size(); ++i) {
1102 EXPECT_EQ((expected_times[i] - start_time) % chrono::seconds(1),
1103 chrono::seconds(0));
1104 }
1105
1106 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1107 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001108
Austin Schuh6bae8252021-02-07 22:01:49 -08001109 if (do_timing_reports() == DoTimingReports::kYes) {
1110 // And, since we are here, check that the timing report makes sense.
1111 // Start by looking for our event loop's timing.
1112 FlatbufferDetachedBuffer<timing::Report> report =
1113 FlatbufferDetachedBuffer<timing::Report>::Empty();
1114 while (report_fetcher.FetchNext()) {
1115 if (report_fetcher->name()->string_view() == "primary") {
1116 report = CopyFlatBuffer(report_fetcher.get());
1117 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001118 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001119
1120 // Confirm that we have the right number of reports, and the contents are
1121 // sane.
1122 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
1123
1124 EXPECT_EQ(report.message().name()->string_view(), "primary");
1125
1126 ASSERT_NE(report.message().senders(), nullptr);
1127 EXPECT_EQ(report.message().senders()->size(), 2);
1128
1129 ASSERT_NE(report.message().timers(), nullptr);
1130 EXPECT_EQ(report.message().timers()->size(), 2);
1131
1132 EXPECT_EQ(report.message().timers()->Get(0)->name()->string_view(),
1133 "Test loop");
1134 EXPECT_GE(report.message().timers()->Get(0)->count(), 1);
1135
1136 EXPECT_EQ(report.message().timers()->Get(1)->name()->string_view(),
1137 "timing_reports");
1138 EXPECT_EQ(report.message().timers()->Get(1)->count(), 1);
1139
1140 // Make sure there is a single phased loop report with our report in it.
1141 ASSERT_EQ(report.message().phased_loops(), nullptr);
1142 } else {
1143 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001144 }
Neil Balch229001a2018-01-07 18:22:52 -08001145}
1146
1147// Verify that we can change a timer's parameters during execution.
1148TEST_P(AbstractEventLoopTest, TimerChangeParameters) {
Austin Schuh44019f92019-05-19 19:58:27 -07001149 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001150 loop->SetRuntimeRealtimePriority(1);
Austin Schuh7f20f512021-01-31 17:56:16 -08001151 std::vector<monotonic_clock::time_point> iteration_list;
Neil Balch229001a2018-01-07 18:22:52 -08001152
1153 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001154 ScopedNotRealtime nrt;
Austin Schuh7f20f512021-01-31 17:56:16 -08001155 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001156 });
1157
Austin Schuh7f20f512021-01-31 17:56:16 -08001158 monotonic_clock::time_point s;
1159 auto modifier_timer = loop->AddTimer([&test_timer, &s]() {
Austin Schuhd892f102021-10-12 18:01:46 -07001160 test_timer->Setup(s + chrono::milliseconds(1750),
1161 chrono::milliseconds(600));
Neil Balch229001a2018-01-07 18:22:52 -08001162 });
1163
Austin Schuh7f20f512021-01-31 17:56:16 -08001164 s = loop->monotonic_now();
Austin Schuhd892f102021-10-12 18:01:46 -07001165 test_timer->Setup(s, chrono::milliseconds(500));
1166 modifier_timer->Setup(s + chrono::milliseconds(1250));
1167 EndEventLoop(loop.get(), chrono::milliseconds(3950));
Austin Schuh44019f92019-05-19 19:58:27 -07001168 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001169
Austin Schuhd892f102021-10-12 18:01:46 -07001170 EXPECT_THAT(
1171 iteration_list,
1172 ::testing::ElementsAre(
1173 s, s + chrono::milliseconds(500), s + chrono::milliseconds(1000),
1174 s + chrono::milliseconds(1750), s + chrono::milliseconds(2350),
1175 s + chrono::milliseconds(2950), s + chrono::milliseconds(3550)));
Neil Balch229001a2018-01-07 18:22:52 -08001176}
1177
1178// Verify that we can disable a timer during execution.
1179TEST_P(AbstractEventLoopTest, TimerDisable) {
Austin Schuh44019f92019-05-19 19:58:27 -07001180 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001181 loop->SetRuntimeRealtimePriority(1);
Neil Balch229001a2018-01-07 18:22:52 -08001182 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
1183
1184 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001185 ScopedNotRealtime nrt;
Austin Schuhd892f102021-10-12 18:01:46 -07001186 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001187 });
1188
Tyler Chatow67ddb032020-01-12 14:30:04 -08001189 auto ender_timer = loop->AddTimer([&test_timer]() { test_timer->Disable(); });
Neil Balch229001a2018-01-07 18:22:52 -08001190
Austin Schuhd892f102021-10-12 18:01:46 -07001191 monotonic_clock::time_point s = loop->monotonic_now();
Austin Schuh73d99502021-12-08 12:05:39 -08001192 test_timer->Setup(s, ::std::chrono::milliseconds(500));
1193 ender_timer->Setup(s + ::std::chrono::milliseconds(1250));
1194 EndEventLoop(loop.get(), ::std::chrono::milliseconds(2000));
Austin Schuh44019f92019-05-19 19:58:27 -07001195 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001196
Austin Schuhd892f102021-10-12 18:01:46 -07001197 EXPECT_THAT(iteration_list,
Austin Schuh73d99502021-12-08 12:05:39 -08001198 ::testing::ElementsAre(s, s + chrono::milliseconds(500),
1199 s + chrono::milliseconds(1000)));
Neil Balch229001a2018-01-07 18:22:52 -08001200}
Austin Schuh7267c532019-05-19 19:55:53 -07001201
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001202// Verify that a timer can disable itself.
1203//
1204// TODO(Brian): Do something similar with phased loops, both with a quick
1205// handler and a handler that would miss a cycle except it got deferred. Current
1206// behavior doing that is a mess.
1207TEST_P(AbstractEventLoopTest, TimerDisableSelf) {
1208 auto loop = MakePrimary();
1209
1210 int count = 0;
1211 aos::TimerHandler *test_timer;
1212 test_timer = loop->AddTimer([&count, &test_timer]() {
1213 ++count;
1214 test_timer->Disable();
1215 });
1216
1217 test_timer->Setup(loop->monotonic_now(), ::std::chrono::milliseconds(20));
1218 EndEventLoop(loop.get(), ::std::chrono::milliseconds(80));
1219 Run();
1220
1221 EXPECT_EQ(count, 1);
1222}
1223
Brian Silvermanbd405c02020-06-23 16:25:23 -07001224// Verify that we can disable a timer during execution of another timer
1225// scheduled for the same time, with one ordering of creation for the timers.
1226//
1227// Also schedule some more events to reshuffle the heap in EventLoop used for
1228// tracking events to change up the order. This used to segfault
1229// SimulatedEventLoop.
1230TEST_P(AbstractEventLoopTest, TimerDisableOther) {
1231 for (bool creation_order : {true, false}) {
1232 for (bool setup_order : {true, false}) {
1233 for (int shuffle_events = 0; shuffle_events < 5; ++shuffle_events) {
1234 auto loop = MakePrimary();
1235 aos::TimerHandler *test_timer, *ender_timer;
1236 if (creation_order) {
1237 test_timer = loop->AddTimer([]() {});
1238 ender_timer =
1239 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1240 } else {
1241 ender_timer =
1242 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1243 test_timer = loop->AddTimer([]() {});
1244 }
1245
1246 const auto start = loop->monotonic_now();
1247
1248 for (int i = 0; i < shuffle_events; ++i) {
1249 loop->AddTimer([]() {})->Setup(start + std::chrono::milliseconds(10));
1250 }
1251
1252 if (setup_order) {
1253 test_timer->Setup(start + ::std::chrono::milliseconds(20));
1254 ender_timer->Setup(start + ::std::chrono::milliseconds(20));
1255 } else {
1256 ender_timer->Setup(start + ::std::chrono::milliseconds(20));
1257 test_timer->Setup(start + ::std::chrono::milliseconds(20));
1258 }
1259 EndEventLoop(loop.get(), ::std::chrono::milliseconds(40));
1260 Run();
1261 }
1262 }
1263 }
1264}
1265
Austin Schuh54cf95f2019-11-29 13:14:18 -08001266// Verifies that the event loop implementations detect when Channel is not a
Brian Silverman631b6262021-11-10 12:25:08 -08001267// pointer into configuration(), or a name doesn't map to a channel in
1268// configuration().
Austin Schuh54cf95f2019-11-29 13:14:18 -08001269TEST_P(AbstractEventLoopDeathTest, InvalidChannel) {
1270 auto loop = MakePrimary();
1271
Tyler Chatow67ddb032020-01-12 14:30:04 -08001272 const Channel *channel = configuration::GetChannel(
1273 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
Austin Schuh54cf95f2019-11-29 13:14:18 -08001274
1275 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1276
1277 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001278 loop->MakeRawSender(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001279 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1280
1281 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001282 loop->MakeSender<TestMessage>("/testbad"),
1283 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1284 " not found in config");
1285
1286 EXPECT_FALSE(loop->TryMakeSender<TestMessage>("/testbad"));
1287
1288 EXPECT_DEATH(
1289 loop->MakeRawFetcher(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001290 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1291
1292 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001293 loop->MakeFetcher<TestMessage>("/testbad"),
1294 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1295 " not found in config");
1296
1297 EXPECT_FALSE(loop->TryMakeFetcher<TestMessage>("/testbad").valid());
1298
1299 EXPECT_DEATH(
Austin Schuh54cf95f2019-11-29 13:14:18 -08001300 {
1301 loop->MakeRawWatcher(&channel_copy.message(),
1302 [](const Context, const void *) {});
1303 },
1304 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
Brian Silverman631b6262021-11-10 12:25:08 -08001305
1306 EXPECT_DEATH(
1307 { loop->MakeWatcher("/testbad", [](const TestMessage &) {}); },
1308 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1309 " not found in config");
1310}
1311
1312// Verifies that the event loop handles a channel which is not readable or
1313// writable on the current node nicely.
1314TEST_P(AbstractEventLoopDeathTest, InaccessibleChannel) {
1315 EnableNodes("me");
1316 auto loop = MakePrimary("me");
1317 auto loop2 = Make("them");
1318
1319 const Channel *channel = configuration::GetChannel(
1320 loop->configuration(), "/test_noforward", "aos.TestMessage", "", nullptr);
1321
1322 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1323
1324 EXPECT_DEATH(
1325 loop2->MakeSender<TestMessage>("/test_forward"),
1326 "Channel"
1327 " \\{ \"name\": \"/test_forward\", \"type\": \"aos.TestMessage\" \\}"
1328 " is not able to be sent on this node");
1329
1330 EXPECT_FALSE(loop2->TryMakeSender<TestMessage>("/test_forward"));
1331
1332 EXPECT_DEATH(
1333 loop2->MakeRawFetcher(channel),
1334 "Channel"
1335 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1336 " is not able to be fetched on this node");
1337
1338 EXPECT_DEATH(
1339 loop2->MakeFetcher<TestMessage>("/test_noforward"),
1340 "Channel"
1341 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1342 " is not able to be fetched on this node");
1343
1344 EXPECT_FALSE(loop2->TryMakeFetcher<TestMessage>("/test_noforward").valid());
1345
1346 EXPECT_DEATH(
1347 { loop2->MakeRawWatcher(channel, [](const Context, const void *) {}); },
1348 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1349 "\"source_node\": \"them\" \\}"
1350 " is not able to be watched on this node");
1351
1352 EXPECT_DEATH(
1353 { loop2->MakeWatcher("/test_noforward", [](const TestMessage &) {}); },
1354 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1355 "\"source_node\": \"them\" \\}"
1356 " is not able to be watched on this node");
Austin Schuh54cf95f2019-11-29 13:14:18 -08001357}
1358
Austin Schuhd54780b2020-10-03 16:26:02 -07001359// Verifies that the event loop implementations detect when Channel has an
1360// invalid alignment.
1361TEST_P(AbstractEventLoopDeathTest, InvalidChannelAlignment) {
1362 const char *const kError = "multiple of alignment";
1363 InvalidChannelAlignment();
1364
1365 auto loop = MakePrimary();
1366
1367 const Channel *channel = configuration::GetChannel(
1368 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
1369
1370 EXPECT_DEATH({ loop->MakeRawSender(channel); }, kError);
1371 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); }, kError);
1372
1373 EXPECT_DEATH({ loop->MakeRawFetcher(channel); }, kError);
1374 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); }, kError);
1375
1376 EXPECT_DEATH(
1377 { loop->MakeRawWatcher(channel, [](const Context &, const void *) {}); },
1378 kError);
1379 EXPECT_DEATH({ loop->MakeRawNoArgWatcher(channel, [](const Context &) {}); },
1380 kError);
1381
1382 EXPECT_DEATH({ loop->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
1383 kError);
1384 EXPECT_DEATH({ loop->MakeWatcher("/test", [](const TestMessage &) {}); },
1385 kError);
1386}
1387
Brian Silverman454bc112020-03-05 14:21:25 -08001388// Verify that the send time on a message is roughly right when using a watcher.
Austin Schuh7267c532019-05-19 19:55:53 -07001389TEST_P(AbstractEventLoopTest, MessageSendTime) {
Austin Schuh44019f92019-05-19 19:58:27 -07001390 auto loop1 = MakePrimary();
Austin Schuh7267c532019-05-19 19:55:53 -07001391 auto loop2 = Make();
Austin Schuhad154822019-12-27 15:45:13 -08001392 auto sender = loop2->MakeSender<TestMessage>("/test");
Austin Schuh7267c532019-05-19 19:55:53 -07001393 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
1394
1395 auto test_timer = loop1->AddTimer([&sender]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001396 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1397 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1398 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001399 msg.CheckOk(msg.Send(builder.Finish()));
Alex Perrycb7da4b2019-08-28 19:35:56 -07001400 });
1401
Austin Schuhad154822019-12-27 15:45:13 -08001402 bool triggered = false;
Brian Silverman454bc112020-03-05 14:21:25 -08001403 loop1->MakeWatcher("/test", [&](const TestMessage &msg) {
Austin Schuhad154822019-12-27 15:45:13 -08001404 // Confirm that the data pointer makes sense from a watcher, and all the
1405 // timestamps look right.
1406 EXPECT_GT(&msg, loop1->context().data);
1407 EXPECT_EQ(loop1->context().monotonic_remote_time,
1408 loop1->context().monotonic_event_time);
1409 EXPECT_EQ(loop1->context().realtime_remote_time,
1410 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001411 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001412
1413 const aos::monotonic_clock::time_point monotonic_now =
1414 loop1->monotonic_now();
Tyler Chatow67ddb032020-01-12 14:30:04 -08001415 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08001416
1417 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1418 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1419 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1420 monotonic_now);
1421 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1422 realtime_now);
1423
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001424 EXPECT_LT(&msg, reinterpret_cast<const void *>(
1425 reinterpret_cast<const char *>(loop1->context().data) +
Austin Schuhad154822019-12-27 15:45:13 -08001426 loop1->context().size));
Brian Silverman4f4e0612020-08-12 19:54:41 -07001427 if (read_method() == ReadMethod::PIN) {
1428 EXPECT_GE(loop1->context().buffer_index, 0);
1429 EXPECT_LT(loop1->context().buffer_index,
1430 loop1->NumberBuffers(
1431 configuration::GetChannel(loop1->configuration(), "/test",
1432 "aos.TestMessage", "", nullptr)));
1433 } else {
1434 EXPECT_EQ(-1, loop1->context().buffer_index);
1435 }
Austin Schuhad154822019-12-27 15:45:13 -08001436 triggered = true;
Austin Schuh7267c532019-05-19 19:55:53 -07001437 });
1438
1439 test_timer->Setup(loop1->monotonic_now() + ::std::chrono::seconds(1));
1440
1441 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
Austin Schuh44019f92019-05-19 19:58:27 -07001442 Run();
Austin Schuh7267c532019-05-19 19:55:53 -07001443
Austin Schuhad154822019-12-27 15:45:13 -08001444 EXPECT_TRUE(triggered);
1445
Brian Silverman454bc112020-03-05 14:21:25 -08001446 ASSERT_TRUE(fetcher.Fetch());
1447
1448 monotonic_clock::duration monotonic_time_offset =
1449 fetcher.context().monotonic_event_time -
1450 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1451 realtime_clock::duration realtime_time_offset =
1452 fetcher.context().realtime_event_time -
1453 (loop1->realtime_now() - ::std::chrono::seconds(1));
1454
1455 EXPECT_EQ(fetcher.context().realtime_event_time,
1456 fetcher.context().realtime_remote_time);
1457 EXPECT_EQ(fetcher.context().monotonic_event_time,
1458 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001459 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001460
1461 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1462 << ": Got "
1463 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1464 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1465 // Confirm that the data pointer makes sense.
1466 EXPECT_GT(fetcher.get(), fetcher.context().data);
1467 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001468 reinterpret_cast<const void *>(
1469 reinterpret_cast<const char *>(fetcher.context().data) +
Brian Silverman454bc112020-03-05 14:21:25 -08001470 fetcher.context().size));
1471 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1472 << ": Got "
1473 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1474 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1475
1476 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1477 << ": Got "
1478 << fetcher.context().realtime_event_time.time_since_epoch().count()
1479 << " expected " << loop1->realtime_now().time_since_epoch().count();
1480 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1481 << ": Got "
1482 << fetcher.context().realtime_event_time.time_since_epoch().count()
1483 << " expected " << loop1->realtime_now().time_since_epoch().count();
1484}
1485
1486// Verify that the send time on a message is roughly right when using a no-arg
1487// watcher. To get a message, we need to use a fetcher to actually access the
1488// message. This is also the main use case for no-arg fetchers.
1489TEST_P(AbstractEventLoopTest, MessageSendTimeNoArg) {
1490 auto loop1 = MakePrimary();
1491 auto loop2 = Make();
1492 auto sender = loop2->MakeSender<TestMessage>("/test");
1493 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
1494
1495 auto test_timer = loop1->AddTimer([&sender]() {
1496 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1497 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1498 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001499 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -08001500 });
1501
1502 bool triggered = false;
1503 loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {
1504 // Confirm that we can indeed use a fetcher on this channel from this
1505 // context, and it results in a sane data pointer and timestamps.
1506 ASSERT_TRUE(fetcher.Fetch());
1507
1508 EXPECT_EQ(loop1->context().monotonic_remote_time,
1509 loop1->context().monotonic_event_time);
1510 EXPECT_EQ(loop1->context().realtime_remote_time,
1511 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001512 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001513
1514 const aos::monotonic_clock::time_point monotonic_now =
1515 loop1->monotonic_now();
1516 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
1517
1518 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1519 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1520 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1521 monotonic_now);
1522 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1523 realtime_now);
1524
1525 triggered = true;
1526 });
1527
1528 test_timer->Setup(loop1->monotonic_now() + ::std::chrono::seconds(1));
1529
1530 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
1531 Run();
1532
1533 ASSERT_TRUE(triggered);
Austin Schuh7267c532019-05-19 19:55:53 -07001534
Alex Perrycb7da4b2019-08-28 19:35:56 -07001535 monotonic_clock::duration monotonic_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001536 fetcher.context().monotonic_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001537 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1538 realtime_clock::duration realtime_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001539 fetcher.context().realtime_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001540 (loop1->realtime_now() - ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07001541
Austin Schuhad154822019-12-27 15:45:13 -08001542 EXPECT_EQ(fetcher.context().realtime_event_time,
1543 fetcher.context().realtime_remote_time);
1544 EXPECT_EQ(fetcher.context().monotonic_event_time,
1545 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001546 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001547
Alex Perrycb7da4b2019-08-28 19:35:56 -07001548 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1549 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001550 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh52d325c2019-06-23 18:59:06 -07001551 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07001552 // Confirm that the data pointer makes sense.
1553 EXPECT_GT(fetcher.get(), fetcher.context().data);
1554 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001555 reinterpret_cast<const void *>(
1556 reinterpret_cast<const char *>(fetcher.context().data) +
Alex Perrycb7da4b2019-08-28 19:35:56 -07001557 fetcher.context().size));
1558 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1559 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001560 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh7267c532019-05-19 19:55:53 -07001561 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07001562
1563 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1564 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001565 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07001566 << " expected " << loop1->realtime_now().time_since_epoch().count();
1567 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1568 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001569 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07001570 << " expected " << loop1->realtime_now().time_since_epoch().count();
Austin Schuh7267c532019-05-19 19:55:53 -07001571}
1572
Austin Schuh52d325c2019-06-23 18:59:06 -07001573// Tests that a couple phased loops run in a row result in the correct offset
1574// and period.
1575TEST_P(AbstractEventLoopTest, PhasedLoopTest) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001576 // Force a slower rate so we are guaranteed to have reports for our phased
Austin Schuh39788ff2019-12-01 18:22:57 -08001577 // loop.
1578 FLAGS_timing_report_ms = 2000;
1579
Austin Schuh52d325c2019-06-23 18:59:06 -07001580 const chrono::milliseconds kOffset = chrono::milliseconds(400);
1581 const int kCount = 5;
1582
1583 auto loop1 = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001584 auto loop2 = Make();
1585
1586 Fetcher<timing::Report> report_fetcher =
1587 loop2->MakeFetcher<timing::Report>("/aos");
1588 EXPECT_FALSE(report_fetcher.Fetch());
Austin Schuh52d325c2019-06-23 18:59:06 -07001589
1590 // Collect up a couple of samples.
1591 ::std::vector<::aos::monotonic_clock::time_point> times;
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001592 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
Austin Schuh52d325c2019-06-23 18:59:06 -07001593
1594 // Run kCount iterations.
Austin Schuh39788ff2019-12-01 18:22:57 -08001595 loop1
1596 ->AddPhasedLoop(
1597 [&times, &expected_times, &loop1, this](int count) {
1598 EXPECT_EQ(count, 1);
1599 times.push_back(loop1->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001600 expected_times.push_back(loop1->context().monotonic_event_time);
Austin Schuh39788ff2019-12-01 18:22:57 -08001601
Austin Schuhad154822019-12-27 15:45:13 -08001602 EXPECT_EQ(loop1->context().monotonic_remote_time,
1603 monotonic_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001604 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001605 EXPECT_EQ(loop1->context().realtime_event_time,
1606 realtime_clock::min_time);
1607 EXPECT_EQ(loop1->context().realtime_remote_time,
Austin Schuh39788ff2019-12-01 18:22:57 -08001608 realtime_clock::min_time);
1609 EXPECT_EQ(loop1->context().queue_index, 0xffffffffu);
1610 EXPECT_EQ(loop1->context().size, 0u);
1611 EXPECT_EQ(loop1->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001612 EXPECT_EQ(loop1->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001613
1614 if (times.size() == kCount) {
1615 LOG(INFO) << "Exiting";
1616 this->Exit();
1617 }
1618 },
1619 chrono::seconds(1), kOffset)
1620 ->set_name("Test loop");
Austin Schuh52d325c2019-06-23 18:59:06 -07001621
1622 // Add a delay to make sure that delay during startup doesn't result in a
1623 // "missed cycle".
1624 SleepFor(chrono::seconds(2));
1625
1626 Run();
1627
1628 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001629 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
1630 ASSERT_EQ(times.size(), expected_times.size());
1631 ASSERT_EQ((times.size() % 2), 1);
Austin Schuh52d325c2019-06-23 18:59:06 -07001632
1633 // Grab the middle sample.
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001634 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
Austin Schuh52d325c2019-06-23 18:59:06 -07001635
1636 // Add up all the delays of all the times.
1637 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1638 for (const ::aos::monotonic_clock::time_point time : times) {
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001639 sum += time - average_time;
Austin Schuh52d325c2019-06-23 18:59:06 -07001640 }
1641
1642 // Average and add to the middle to find the average time.
1643 sum /= times.size();
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001644 average_time += sum;
Austin Schuh52d325c2019-06-23 18:59:06 -07001645
1646 // Compute the offset from the start of the second of the average time. This
1647 // should be pretty close to the offset.
1648 const ::aos::monotonic_clock::duration remainder =
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001649 average_time.time_since_epoch() -
1650 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
Austin Schuh52d325c2019-06-23 18:59:06 -07001651
1652 const chrono::milliseconds kEpsilon(100);
1653 EXPECT_LT(remainder, kOffset + kEpsilon);
1654 EXPECT_GT(remainder, kOffset - kEpsilon);
1655
1656 // Make sure that the average duration is close to 1 second.
1657 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1658 times.front())
1659 .count() /
1660 static_cast<double>(times.size() - 1),
1661 1.0, 0.1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001662
1663 // Confirm that the ideal wakeup times increment correctly.
1664 for (size_t i = 1; i < expected_times.size(); ++i) {
1665 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1666 }
1667
1668 for (size_t i = 0; i < expected_times.size(); ++i) {
1669 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
1670 kOffset);
1671 }
1672
1673 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1674 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001675
Austin Schuh6bae8252021-02-07 22:01:49 -08001676 if (do_timing_reports() == DoTimingReports::kYes) {
1677 // And, since we are here, check that the timing report makes sense.
1678 // Start by looking for our event loop's timing.
1679 FlatbufferDetachedBuffer<timing::Report> report =
1680 FlatbufferDetachedBuffer<timing::Report>::Empty();
1681 while (report_fetcher.FetchNext()) {
1682 if (report_fetcher->name()->string_view() == "primary") {
1683 report = CopyFlatBuffer(report_fetcher.get());
1684 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001685 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001686
1687 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
1688
1689 EXPECT_EQ(report.message().name()->string_view(), "primary");
1690
1691 ASSERT_NE(report.message().senders(), nullptr);
1692 EXPECT_EQ(report.message().senders()->size(), 2);
1693
1694 ASSERT_NE(report.message().timers(), nullptr);
1695 EXPECT_EQ(report.message().timers()->size(), 1);
1696
1697 // Make sure there is a single phased loop report with our report in it.
1698 ASSERT_NE(report.message().phased_loops(), nullptr);
1699 ASSERT_EQ(report.message().phased_loops()->size(), 1);
1700 EXPECT_EQ(report.message().phased_loops()->Get(0)->name()->string_view(),
1701 "Test loop");
1702 EXPECT_GE(report.message().phased_loops()->Get(0)->count(), 1);
1703 } else {
1704 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001705 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001706}
1707
Milind Upadhyay42589bb2021-05-19 20:05:16 -07001708// Tests that a phased loop responds correctly to a changing offset.
1709TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetTest) {
1710 // Force a slower rate so we are guaranteed to have reports for our phased
1711 // loop.
1712 FLAGS_timing_report_ms = 2000;
1713
1714 const chrono::milliseconds kOffset = chrono::milliseconds(400);
1715 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
1716 const int kCount = 5;
1717
1718 auto loop1 = MakePrimary();
1719
1720 // Collect up a couple of samples.
1721 ::std::vector<::aos::monotonic_clock::time_point> times;
1722 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
1723
1724 PhasedLoopHandler *phased_loop;
1725
1726 // Run kCount iterations.
1727 phased_loop = loop1->AddPhasedLoop(
1728 [&phased_loop, &times, &expected_times, &loop1, this, kOffset,
1729 kInterval](int count) {
1730 EXPECT_EQ(count, 1);
1731 times.push_back(loop1->monotonic_now());
1732
1733 expected_times.push_back(loop1->context().monotonic_event_time);
1734
1735 phased_loop->set_interval_and_offset(
1736 kInterval, kOffset - chrono::milliseconds(times.size()));
1737 LOG(INFO) << "new offset: "
1738 << (kOffset - chrono::milliseconds(times.size())).count();
1739
1740 if (times.size() == kCount) {
1741 LOG(INFO) << "Exiting";
1742 this->Exit();
1743 }
1744 },
1745 kInterval, kOffset);
1746 phased_loop->set_name("Test loop");
1747
1748 // Add a delay to make sure that delay during startup doesn't result in a
1749 // "missed cycle".
1750 SleepFor(chrono::seconds(2));
1751
1752 Run();
1753 // Confirm that we got both the right number of samples, and it's odd.
1754 EXPECT_EQ(times.size(), static_cast<size_t>(kCount));
1755 EXPECT_EQ(times.size(), expected_times.size());
1756 EXPECT_EQ((times.size() % 2), 1);
1757
1758 // Grab the middle sample.
1759 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
1760
1761 // Add up all the delays of all the times.
1762 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1763 for (const ::aos::monotonic_clock::time_point time : times) {
1764 sum += time - average_time;
1765 }
1766
1767 // Average and add to the middle to find the average time.
1768 sum /= times.size();
1769 average_time += sum;
1770
1771 // Compute the offset from the start of the second of the average time. This
1772 // should be pretty close to the offset.
1773 const ::aos::monotonic_clock::duration remainder =
1774 average_time.time_since_epoch() -
1775 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
1776
1777 const chrono::milliseconds kEpsilon(100);
1778 EXPECT_LT(remainder, kOffset + kEpsilon);
1779 EXPECT_GT(remainder, kOffset - kEpsilon);
1780
1781 // Make sure that the average duration is close to 1 second.
1782 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1783 times.front())
1784 .count() /
1785 static_cast<double>(times.size() - 1),
1786 1.0, 0.1);
1787
1788 // Confirm that the ideal wakeup times increment correctly.
1789 for (size_t i = 1; i < expected_times.size(); ++i) {
1790 LOG(INFO) << i - 1 << ": " << expected_times[i - 1] << ", " << i << ": "
1791 << expected_times[i];
1792 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1) -
1793 chrono::milliseconds(1));
1794 }
1795
1796 for (size_t i = 0; i < expected_times.size(); ++i) {
1797 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
1798 kOffset - chrono::milliseconds(i));
1799 }
1800
1801 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1802 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
1803}
1804
Austin Schuh39788ff2019-12-01 18:22:57 -08001805// Tests that senders count correctly in the timing report.
1806TEST_P(AbstractEventLoopTest, SenderTimingReport) {
1807 FLAGS_timing_report_ms = 1000;
1808 auto loop1 = MakePrimary();
1809
1810 auto loop2 = Make("watcher_loop");
1811 loop2->MakeWatcher("/test", [](const TestMessage &) {});
1812
1813 auto loop3 = Make();
1814
1815 Fetcher<timing::Report> report_fetcher =
1816 loop3->MakeFetcher<timing::Report>("/aos");
1817 EXPECT_FALSE(report_fetcher.Fetch());
1818
1819 auto sender = loop1->MakeSender<TestMessage>("/test");
1820
James Kuszmaul78514332022-04-06 15:08:34 -07001821 // Sanity check channel frequencies to ensure that we've designed the test
1822 // correctly.
1823 ASSERT_EQ(800, sender.channel()->frequency());
1824 ASSERT_EQ(2000000000, loop1->configuration()->channel_storage_duration());
1825 constexpr int kMaxAllowedMessages = 800 * 2;
1826 constexpr int kSendMessages = kMaxAllowedMessages * 2;
1827 constexpr int kDroppedMessages = kSendMessages - kMaxAllowedMessages;
1828
Austin Schuh39788ff2019-12-01 18:22:57 -08001829 // Add a timer to actually quit.
1830 auto test_timer = loop1->AddTimer([&sender]() {
James Kuszmaul78514332022-04-06 15:08:34 -07001831 for (int i = 0; i < kSendMessages; ++i) {
Austin Schuh39788ff2019-12-01 18:22:57 -08001832 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1833 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1834 builder.add_value(200 + i);
James Kuszmaul78514332022-04-06 15:08:34 -07001835 if (i < kMaxAllowedMessages) {
1836 msg.CheckOk(msg.Send(builder.Finish()));
1837 } else {
1838 EXPECT_EQ(RawSender::Error::kMessagesSentTooFast,
1839 msg.Send(builder.Finish()));
1840 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001841 }
1842 });
1843
1844 // Quit after 1 timing report, mid way through the next cycle.
1845 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
1846
1847 loop1->OnRun([&test_timer, &loop1]() {
1848 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1500));
1849 });
1850
1851 Run();
1852
Austin Schuh6bae8252021-02-07 22:01:49 -08001853 if (do_timing_reports() == DoTimingReports::kYes) {
1854 // And, since we are here, check that the timing report makes sense.
1855 // Start by looking for our event loop's timing.
1856 FlatbufferDetachedBuffer<timing::Report> primary_report =
1857 FlatbufferDetachedBuffer<timing::Report>::Empty();
1858 while (report_fetcher.FetchNext()) {
Austin Schuh8902fa52021-03-14 22:39:24 -07001859 VLOG(1) << "Report " << FlatbufferToJson(report_fetcher.get());
Austin Schuh6bae8252021-02-07 22:01:49 -08001860 if (report_fetcher->name()->string_view() == "primary") {
1861 primary_report = CopyFlatBuffer(report_fetcher.get());
1862 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001863 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001864
Austin Schuh8902fa52021-03-14 22:39:24 -07001865 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
Austin Schuh6bae8252021-02-07 22:01:49 -08001866
1867 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
1868
1869 ASSERT_NE(primary_report.message().senders(), nullptr);
1870 EXPECT_EQ(primary_report.message().senders()->size(), 3);
1871
1872 // Confirm that the sender looks sane.
1873 EXPECT_EQ(
1874 loop1->configuration()
1875 ->channels()
1876 ->Get(primary_report.message().senders()->Get(0)->channel_index())
1877 ->name()
1878 ->string_view(),
1879 "/test");
James Kuszmaul78514332022-04-06 15:08:34 -07001880 EXPECT_EQ(primary_report.message().senders()->Get(0)->count(),
1881 kMaxAllowedMessages);
1882 ASSERT_TRUE(primary_report.message().senders()->Get(0)->has_error_counts());
1883 ASSERT_EQ(
1884 primary_report.message().senders()->Get(0)->error_counts()->size(), 2u);
1885 EXPECT_EQ(
1886 primary_report.message()
1887 .senders()
1888 ->Get(0)
1889 ->error_counts()
1890 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
1891 ->count(),
1892 kDroppedMessages)
1893 << aos::FlatbufferToJson(primary_report);
1894 EXPECT_EQ(primary_report.message()
1895 .senders()
1896 ->Get(0)
1897 ->error_counts()
1898 ->Get(static_cast<size_t>(timing::SendError::INVALID_REDZONE))
1899 ->count(),
1900 0);
Austin Schuh6bae8252021-02-07 22:01:49 -08001901
1902 // Confirm that the timing primary_report sender looks sane.
1903 EXPECT_EQ(
1904 loop1->configuration()
1905 ->channels()
1906 ->Get(primary_report.message().senders()->Get(1)->channel_index())
1907 ->name()
1908 ->string_view(),
1909 "/aos");
1910 EXPECT_EQ(primary_report.message().senders()->Get(1)->count(), 1);
1911
1912 ASSERT_NE(primary_report.message().timers(), nullptr);
1913 EXPECT_EQ(primary_report.message().timers()->size(), 3);
1914
1915 // Make sure there are no phased loops or watchers.
1916 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
1917 ASSERT_EQ(primary_report.message().watchers(), nullptr);
1918 } else {
1919 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001920 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001921}
1922
James Kuszmaul93abac12022-04-14 15:05:10 -07001923// Tests that the RawSender::Send(void*, size_t) overload tracks things properly
1924// in its timing report.
1925TEST_P(AbstractEventLoopTest, CopySenderTimingReport) {
1926 gflags::FlagSaver flag_saver;
1927 FLAGS_timing_report_ms = 1000;
1928 auto loop1 = Make();
1929 auto loop2 = MakePrimary();
1930
1931 const FlatbufferDetachedBuffer<TestMessage> kMessage =
1932 JsonToFlatbuffer<TestMessage>("{}");
1933
1934 std::unique_ptr<aos::RawSender> sender =
1935 loop2->MakeRawSender(configuration::GetChannel(
1936 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
1937
1938 Fetcher<timing::Report> report_fetcher =
1939 loop1->MakeFetcher<timing::Report>("/aos");
1940 EXPECT_FALSE(report_fetcher.Fetch());
1941
1942 loop2->OnRun([&]() {
1943 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
1944 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
1945 RawSender::Error::kOk);
1946 }
1947 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
1948 RawSender::Error::kMessagesSentTooFast);
1949 });
1950 // Quit after 1 timing report, mid way through the next cycle.
1951 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
1952
1953 Run();
1954
1955 if (do_timing_reports() == DoTimingReports::kYes) {
1956 // Check that the sent too fast actually got recorded by the timing report.
1957 FlatbufferDetachedBuffer<timing::Report> primary_report =
1958 FlatbufferDetachedBuffer<timing::Report>::Empty();
1959 while (report_fetcher.FetchNext()) {
1960 if (report_fetcher->name()->string_view() == "primary") {
1961 primary_report = CopyFlatBuffer(report_fetcher.get());
1962 }
1963 }
1964
1965 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
1966
1967 ASSERT_NE(primary_report.message().senders(), nullptr);
1968 EXPECT_EQ(primary_report.message().senders()->size(), 3);
1969 EXPECT_EQ(
1970 primary_report.message()
1971 .senders()
1972 ->Get(0)
1973 ->error_counts()
1974 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
1975 ->count(),
1976 1);
1977 }
1978}
1979
Austin Schuh39788ff2019-12-01 18:22:57 -08001980// Tests that senders count correctly in the timing report.
1981TEST_P(AbstractEventLoopTest, WatcherTimingReport) {
1982 FLAGS_timing_report_ms = 1000;
1983 auto loop1 = MakePrimary();
1984 loop1->MakeWatcher("/test", [](const TestMessage &) {});
1985
1986 auto loop2 = Make("sender_loop");
1987
1988 auto loop3 = Make();
1989
1990 Fetcher<timing::Report> report_fetcher =
1991 loop3->MakeFetcher<timing::Report>("/aos");
1992 EXPECT_FALSE(report_fetcher.Fetch());
1993
1994 auto sender = loop2->MakeSender<TestMessage>("/test");
1995
1996 // Add a timer to actually quit.
1997 auto test_timer = loop1->AddTimer([&sender]() {
1998 for (int i = 0; i < 10; ++i) {
1999 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2000 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2001 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002002 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002003 }
2004 });
2005
2006 // Quit after 1 timing report, mid way through the next cycle.
2007 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2008
2009 loop1->OnRun([&test_timer, &loop1]() {
2010 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1500));
2011 });
2012
2013 Run();
2014
Austin Schuh6bae8252021-02-07 22:01:49 -08002015 if (do_timing_reports() == DoTimingReports::kYes) {
2016 // And, since we are here, check that the timing report makes sense.
2017 // Start by looking for our event loop's timing.
2018 FlatbufferDetachedBuffer<timing::Report> primary_report =
2019 FlatbufferDetachedBuffer<timing::Report>::Empty();
2020 while (report_fetcher.FetchNext()) {
2021 LOG(INFO) << "Report " << FlatbufferToJson(report_fetcher.get());
2022 if (report_fetcher->name()->string_view() == "primary") {
2023 primary_report = CopyFlatBuffer(report_fetcher.get());
2024 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002025 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002026
2027 // Check the watcher report.
2028 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2029
2030 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2031
2032 // Just the timing report timer.
2033 ASSERT_NE(primary_report.message().timers(), nullptr);
2034 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2035
2036 // No phased loops
2037 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2038
2039 ASSERT_NE(primary_report.message().watchers(), nullptr);
2040 ASSERT_EQ(primary_report.message().watchers()->size(), 1);
2041 EXPECT_EQ(primary_report.message().watchers()->Get(0)->count(), 10);
2042 } else {
2043 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002044 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002045}
2046
2047// Tests that fetchers count correctly in the timing report.
2048TEST_P(AbstractEventLoopTest, FetcherTimingReport) {
2049 FLAGS_timing_report_ms = 1000;
2050 auto loop1 = MakePrimary();
2051 auto loop2 = Make("sender_loop");
2052
2053 auto loop3 = Make();
2054
2055 Fetcher<timing::Report> report_fetcher =
2056 loop3->MakeFetcher<timing::Report>("/aos");
2057 EXPECT_FALSE(report_fetcher.Fetch());
2058
2059 auto sender = loop2->MakeSender<TestMessage>("/test");
2060 auto fetcher1 = loop1->MakeFetcher<TestMessage>("/test");
2061 auto fetcher2 = loop1->MakeFetcher<TestMessage>("/test");
2062 fetcher1.Fetch();
2063 fetcher2.Fetch();
2064
2065 // Add a timer to actually quit.
2066 auto test_timer = loop1->AddTimer([&sender]() {
2067 for (int i = 0; i < 10; ++i) {
2068 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2069 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2070 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002071 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002072 }
2073 });
2074
2075 auto test_timer2 = loop1->AddTimer([&fetcher1, &fetcher2]() {
2076 fetcher1.Fetch();
2077 while (fetcher2.FetchNext()) {
2078 }
2079 });
2080
2081 // Quit after 1 timing report, mid way through the next cycle.
2082 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2083
2084 loop1->OnRun([test_timer, test_timer2, &loop1]() {
2085 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1400));
2086 test_timer2->Setup(loop1->monotonic_now() + chrono::milliseconds(1600));
2087 });
2088
2089 Run();
2090
Austin Schuh6bae8252021-02-07 22:01:49 -08002091 if (do_timing_reports() == DoTimingReports::kYes) {
2092 // And, since we are here, check that the timing report makes sense.
2093 // Start by looking for our event loop's timing.
2094 FlatbufferDetachedBuffer<timing::Report> primary_report =
2095 FlatbufferDetachedBuffer<timing::Report>::Empty();
2096 while (report_fetcher.FetchNext()) {
2097 if (report_fetcher->name()->string_view() == "primary") {
2098 primary_report = CopyFlatBuffer(report_fetcher.get());
2099 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002100 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002101
2102 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2103
2104 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2105
2106 ASSERT_NE(primary_report.message().senders(), nullptr);
2107 EXPECT_EQ(primary_report.message().senders()->size(), 2);
2108
2109 ASSERT_NE(primary_report.message().timers(), nullptr);
2110 EXPECT_EQ(primary_report.message().timers()->size(), 4);
2111
2112 // Make sure there are no phased loops or watchers.
2113 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2114 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2115
2116 // Now look at the fetchrs.
2117 ASSERT_NE(primary_report.message().fetchers(), nullptr);
2118 ASSERT_EQ(primary_report.message().fetchers()->size(), 2);
2119
2120 EXPECT_EQ(primary_report.message().fetchers()->Get(0)->count(), 1);
2121 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->average(),
2122 0.1);
2123 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->min(),
2124 0.1);
2125 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->max(),
2126 0.1);
2127 EXPECT_EQ(primary_report.message()
2128 .fetchers()
2129 ->Get(0)
2130 ->latency()
2131 ->standard_deviation(),
2132 0.0);
2133
2134 EXPECT_EQ(primary_report.message().fetchers()->Get(1)->count(), 10);
2135 } else {
2136 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002137 }
Austin Schuh52d325c2019-06-23 18:59:06 -07002138}
2139
Austin Schuh67420a42019-12-21 21:55:04 -08002140// Tests that a raw watcher and raw fetcher can receive messages from a raw
2141// sender without messing up offsets.
2142TEST_P(AbstractEventLoopTest, RawBasic) {
2143 auto loop1 = Make();
2144 auto loop2 = MakePrimary();
2145 auto loop3 = Make();
2146
Austin Schuha9df9ad2021-06-16 14:49:39 -07002147 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2148 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuh67420a42019-12-21 21:55:04 -08002149
2150 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002151 loop1->MakeRawSender(configuration::GetChannel(
2152 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08002153
2154 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002155 loop3->MakeRawFetcher(configuration::GetChannel(
2156 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08002157
Austin Schuha9df9ad2021-06-16 14:49:39 -07002158 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002159 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2160 RawSender::Error::kOk);
Austin Schuha9df9ad2021-06-16 14:49:39 -07002161 });
Austin Schuh67420a42019-12-21 21:55:04 -08002162
2163 bool happened = false;
2164 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08002165 configuration::GetChannel(loop2->configuration(), "/test",
2166 "aos.TestMessage", "", nullptr),
Austin Schuha9df9ad2021-06-16 14:49:39 -07002167 [this, &kMessage, &fetcher, &happened](const Context &context,
2168 const void *message) {
Austin Schuh67420a42019-12-21 21:55:04 -08002169 happened = true;
Austin Schuha9df9ad2021-06-16 14:49:39 -07002170 EXPECT_EQ(
2171 kMessage.span(),
2172 absl::Span<const uint8_t>(
2173 reinterpret_cast<const uint8_t *>(message), context.size));
2174 EXPECT_EQ(message, context.data);
Austin Schuh67420a42019-12-21 21:55:04 -08002175
2176 ASSERT_TRUE(fetcher->Fetch());
2177
Austin Schuha9df9ad2021-06-16 14:49:39 -07002178 EXPECT_EQ(kMessage.span(),
2179 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
2180 fetcher->context().data),
2181 fetcher->context().size));
Austin Schuh67420a42019-12-21 21:55:04 -08002182
2183 this->Exit();
2184 });
2185
2186 EXPECT_FALSE(happened);
2187 Run();
2188 EXPECT_TRUE(happened);
2189}
2190
Austin Schuhad154822019-12-27 15:45:13 -08002191// Tests that a raw watcher and raw fetcher can receive messages from a raw
Brian Silvermanbf889922021-11-10 12:41:57 -08002192// sender without messing up offsets, using the RawSpan overload.
2193TEST_P(AbstractEventLoopTest, RawBasicSharedSpan) {
2194 auto loop1 = Make();
2195 auto loop2 = MakePrimary();
2196 auto loop3 = Make();
2197
2198 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2199 JsonToFlatbuffer<TestMessage>("{}");
2200
2201 std::unique_ptr<aos::RawSender> sender =
2202 loop1->MakeRawSender(configuration::GetChannel(
2203 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
2204
2205 std::unique_ptr<aos::RawFetcher> fetcher =
2206 loop3->MakeRawFetcher(configuration::GetChannel(
2207 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
2208
2209 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002210 EXPECT_EQ(sender->Send(std::make_shared<absl::Span<const uint8_t>>(
2211 kMessage.span().data(), kMessage.span().size())),
2212 RawSender::Error::kOk);
Brian Silvermanbf889922021-11-10 12:41:57 -08002213 });
2214
2215 bool happened = false;
2216 loop2->MakeRawWatcher(
2217 configuration::GetChannel(loop2->configuration(), "/test",
2218 "aos.TestMessage", "", nullptr),
2219 [this, &kMessage, &fetcher, &happened](const Context &context,
2220 const void *message) {
2221 happened = true;
2222 EXPECT_EQ(
2223 kMessage.span(),
2224 absl::Span<const uint8_t>(
2225 reinterpret_cast<const uint8_t *>(message), context.size));
2226 EXPECT_EQ(message, context.data);
2227
2228 ASSERT_TRUE(fetcher->Fetch());
2229
2230 EXPECT_EQ(kMessage.span(),
2231 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
2232 fetcher->context().data),
2233 fetcher->context().size));
2234
2235 this->Exit();
2236 });
2237
2238 EXPECT_FALSE(happened);
2239 Run();
2240 EXPECT_TRUE(happened);
2241}
2242
2243// Tests that a raw watcher and raw fetcher can receive messages from a raw
Austin Schuhad154822019-12-27 15:45:13 -08002244// sender with remote times filled out.
2245TEST_P(AbstractEventLoopTest, RawRemoteTimes) {
2246 auto loop1 = Make();
2247 auto loop2 = MakePrimary();
2248 auto loop3 = Make();
2249
Austin Schuha9df9ad2021-06-16 14:49:39 -07002250 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2251 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08002252
2253 const aos::monotonic_clock::time_point monotonic_remote_time =
2254 aos::monotonic_clock::time_point(chrono::seconds(1501));
2255 const aos::realtime_clock::time_point realtime_remote_time =
2256 aos::realtime_clock::time_point(chrono::seconds(3132));
Austin Schuhb5c6f972021-03-14 21:53:07 -07002257 const uint32_t remote_queue_index = 0x254971;
Austin Schuha9012be2021-07-21 15:19:11 -07002258 const UUID source_boot_uuid = UUID::Random();
Austin Schuhad154822019-12-27 15:45:13 -08002259
2260 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002261 loop1->MakeRawSender(configuration::GetChannel(
2262 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08002263
2264 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002265 loop3->MakeRawFetcher(configuration::GetChannel(
2266 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08002267
2268 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002269 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size(),
2270 monotonic_remote_time, realtime_remote_time,
2271 remote_queue_index, source_boot_uuid),
2272 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08002273 });
2274
2275 bool happened = false;
2276 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08002277 configuration::GetChannel(loop2->configuration(), "/test",
2278 "aos.TestMessage", "", nullptr),
Austin Schuha9012be2021-07-21 15:19:11 -07002279 [this, monotonic_remote_time, realtime_remote_time, source_boot_uuid,
Austin Schuhb5c6f972021-03-14 21:53:07 -07002280 remote_queue_index, &fetcher,
2281 &happened](const Context &context, const void * /*message*/) {
Austin Schuhad154822019-12-27 15:45:13 -08002282 happened = true;
2283 EXPECT_EQ(monotonic_remote_time, context.monotonic_remote_time);
2284 EXPECT_EQ(realtime_remote_time, context.realtime_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002285 EXPECT_EQ(source_boot_uuid, context.source_boot_uuid);
Austin Schuhb5c6f972021-03-14 21:53:07 -07002286 EXPECT_EQ(remote_queue_index, context.remote_queue_index);
Austin Schuhad154822019-12-27 15:45:13 -08002287
2288 ASSERT_TRUE(fetcher->Fetch());
2289 EXPECT_EQ(monotonic_remote_time,
2290 fetcher->context().monotonic_remote_time);
2291 EXPECT_EQ(realtime_remote_time,
2292 fetcher->context().realtime_remote_time);
2293
2294 this->Exit();
2295 });
2296
2297 EXPECT_FALSE(happened);
2298 Run();
2299 EXPECT_TRUE(happened);
2300}
2301
2302// Tests that a raw sender fills out sent data.
2303TEST_P(AbstractEventLoopTest, RawSenderSentData) {
2304 auto loop1 = MakePrimary();
2305
Austin Schuha9df9ad2021-06-16 14:49:39 -07002306 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2307 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08002308
2309 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002310 loop1->MakeRawSender(configuration::GetChannel(
2311 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08002312
Tyler Chatow67ddb032020-01-12 14:30:04 -08002313 const aos::monotonic_clock::time_point monotonic_now = loop1->monotonic_now();
2314 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08002315
milind1f1dca32021-07-03 13:50:07 -07002316 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2317 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08002318
2319 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
2320 EXPECT_LE(sender->monotonic_sent_time(),
2321 monotonic_now + chrono::milliseconds(100));
2322 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
2323 EXPECT_LE(sender->realtime_sent_time(),
2324 realtime_now + chrono::milliseconds(100));
2325 EXPECT_EQ(sender->sent_queue_index(), 0u);
2326
milind1f1dca32021-07-03 13:50:07 -07002327 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2328 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08002329
2330 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
2331 EXPECT_LE(sender->monotonic_sent_time(),
2332 monotonic_now + chrono::milliseconds(100));
2333 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
2334 EXPECT_LE(sender->realtime_sent_time(),
2335 realtime_now + chrono::milliseconds(100));
2336 EXPECT_EQ(sender->sent_queue_index(), 1u);
2337}
2338
Austin Schuh217a9782019-12-21 23:02:50 -08002339// Tests that not setting up nodes results in no node.
2340TEST_P(AbstractEventLoopTest, NoNode) {
2341 auto loop1 = Make();
2342 auto loop2 = MakePrimary();
2343
2344 EXPECT_EQ(loop1->node(), nullptr);
2345 EXPECT_EQ(loop2->node(), nullptr);
2346}
2347
2348// Tests that setting up nodes results in node being set.
2349TEST_P(AbstractEventLoopTest, Node) {
2350 EnableNodes("me");
2351
2352 auto loop1 = Make();
2353 auto loop2 = MakePrimary();
2354
2355 EXPECT_NE(loop1->node(), nullptr);
2356 EXPECT_NE(loop2->node(), nullptr);
2357}
2358
2359// Tests that watchers work with a node setup.
2360TEST_P(AbstractEventLoopTest, NodeWatcher) {
2361 EnableNodes("me");
2362
2363 auto loop1 = Make();
2364 auto loop2 = Make();
2365 loop1->MakeWatcher("/test", [](const TestMessage &) {});
Tyler Chatow67ddb032020-01-12 14:30:04 -08002366 loop2->MakeRawWatcher(
2367 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
2368 nullptr),
2369 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08002370}
2371
Brian Silverman454bc112020-03-05 14:21:25 -08002372// Tests that no-arg watchers work with a node setup.
2373TEST_P(AbstractEventLoopTest, NodeNoArgWatcher) {
2374 EnableNodes("me");
2375
2376 auto loop1 = Make();
2377 auto loop2 = Make();
2378 loop1->MakeWatcher("/test", [](const TestMessage &) {});
2379 loop2->MakeRawNoArgWatcher(
2380 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
2381 nullptr),
2382 [](const Context &) {});
2383}
2384
Austin Schuh217a9782019-12-21 23:02:50 -08002385// Tests that fetcher work with a node setup.
2386TEST_P(AbstractEventLoopTest, NodeFetcher) {
2387 EnableNodes("me");
2388 auto loop1 = Make();
2389
2390 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
Tyler Chatow67ddb032020-01-12 14:30:04 -08002391 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
2392 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08002393}
2394
2395// Tests that sender work with a node setup.
2396TEST_P(AbstractEventLoopTest, NodeSender) {
2397 EnableNodes("me");
2398 auto loop1 = Make();
2399
2400 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
2401}
2402
Austin Schuhcc6070c2020-10-10 20:25:56 -07002403// Tests that a non-realtime event loop timer is marked non-realtime.
2404TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopTimer) {
2405 auto loop1 = MakePrimary();
2406
2407 // Add a timer to actually quit.
2408 auto test_timer = loop1->AddTimer([this]() {
2409 CheckNotRealtime();
2410 this->Exit();
2411 });
2412
2413 loop1->OnRun([&test_timer, &loop1]() {
2414 CheckNotRealtime();
2415 test_timer->Setup(loop1->monotonic_now(), ::std::chrono::milliseconds(100));
2416 });
2417
2418 Run();
2419}
2420
2421// Tests that a realtime event loop timer is marked realtime.
Austin Schuh9b1d6282022-06-10 17:03:21 -07002422TEST_P(AbstractEventLoopTest, RealtimeSend) {
2423 auto loop1 = MakePrimary();
2424
2425 loop1->SetRuntimeRealtimePriority(1);
2426
2427 auto sender = loop1->MakeSender<TestMessage>("/test2");
2428
2429 loop1->OnRun([&]() {
2430 CheckRealtime();
2431
2432 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2433 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2434 builder.add_value(200);
2435 msg.CheckOk(msg.Send(builder.Finish()));
2436
2437 this->Exit();
2438 });
2439
2440 Run();
2441}
2442
2443// Tests that a realtime event loop timer is marked realtime.
Austin Schuhcc6070c2020-10-10 20:25:56 -07002444TEST_P(AbstractEventLoopTest, RealtimeEventLoopTimer) {
2445 auto loop1 = MakePrimary();
2446
2447 loop1->SetRuntimeRealtimePriority(1);
2448
2449 // Add a timer to actually quit.
2450 auto test_timer = loop1->AddTimer([this]() {
2451 CheckRealtime();
2452 this->Exit();
2453 });
2454
2455 loop1->OnRun([&test_timer, &loop1]() {
2456 CheckRealtime();
2457 test_timer->Setup(loop1->monotonic_now(), ::std::chrono::milliseconds(100));
2458 });
2459
2460 Run();
2461}
2462
2463// Tests that a non-realtime event loop phased loop is marked non-realtime.
2464TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopPhasedLoop) {
2465 auto loop1 = MakePrimary();
2466
2467 // Add a timer to actually quit.
2468 loop1->AddPhasedLoop(
2469 [this](int) {
2470 CheckNotRealtime();
2471 this->Exit();
2472 },
2473 chrono::seconds(1), chrono::seconds(0));
2474
2475 Run();
2476}
2477
2478// Tests that a realtime event loop phased loop is marked realtime.
2479TEST_P(AbstractEventLoopTest, RealtimeEventLoopPhasedLoop) {
2480 auto loop1 = MakePrimary();
2481
2482 loop1->SetRuntimeRealtimePriority(1);
2483
2484 // Add a timer to actually quit.
2485 loop1->AddPhasedLoop(
2486 [this](int) {
2487 CheckRealtime();
2488 this->Exit();
2489 },
2490 chrono::seconds(1), chrono::seconds(0));
2491
2492 Run();
2493}
2494
2495// Tests that a non-realtime event loop watcher is marked non-realtime.
2496TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopWatcher) {
2497 auto loop1 = MakePrimary();
2498 auto loop2 = Make();
2499
2500 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
2501
2502 loop1->OnRun([&]() {
2503 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2504 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07002505 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07002506 });
2507
2508 loop1->MakeWatcher("/test", [&](const TestMessage &) {
2509 CheckNotRealtime();
2510 this->Exit();
2511 });
2512
2513 Run();
2514}
2515
2516// Tests that a realtime event loop watcher is marked realtime.
2517TEST_P(AbstractEventLoopTest, RealtimeEventLoopWatcher) {
2518 auto loop1 = MakePrimary();
2519 auto loop2 = Make();
2520
2521 loop1->SetRuntimeRealtimePriority(1);
2522
2523 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
2524
2525 loop1->OnRun([&]() {
2526 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2527 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07002528 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07002529 });
2530
2531 loop1->MakeWatcher("/test", [&](const TestMessage &) {
2532 CheckRealtime();
2533 this->Exit();
2534 });
2535
2536 Run();
2537}
2538
Austin Schuha9012be2021-07-21 15:19:11 -07002539// Tests that event loop's context's monotonic time is set to a value on OnRun.
2540TEST_P(AbstractEventLoopTest, SetContextOnRun) {
2541 auto loop = MakePrimary();
2542
2543 // We want to check that monotonic event time is before monotonic now
2544 // called inside of callback, but after time point obtained callback.
2545 aos::monotonic_clock::time_point monotonic_event_time_on_run;
2546
2547 loop->OnRun([&]() {
2548 monotonic_event_time_on_run = loop->context().monotonic_event_time;
2549 EXPECT_LE(monotonic_event_time_on_run, loop->monotonic_now());
2550 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
2551 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
2552 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
2553 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
2554 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
2555 EXPECT_EQ(loop->context().size, 0u);
2556 EXPECT_EQ(loop->context().data, nullptr);
2557 EXPECT_EQ(loop->context().buffer_index, -1);
2558 });
2559
2560 EndEventLoop(loop.get(), ::std::chrono::milliseconds(200));
2561
2562 const aos::monotonic_clock::time_point before_run_time =
2563 loop->monotonic_now();
2564 Run();
2565 EXPECT_GE(monotonic_event_time_on_run, before_run_time);
2566}
2567
Austin Schuh217a9782019-12-21 23:02:50 -08002568// Tests that watchers fail when created on the wrong node.
2569TEST_P(AbstractEventLoopDeathTest, NodeWatcher) {
2570 EnableNodes("them");
2571
2572 auto loop1 = Make();
2573 auto loop2 = Make();
2574 EXPECT_DEATH({ loop1->MakeWatcher("/test", [](const TestMessage &) {}); },
2575 "node");
2576 EXPECT_DEATH(
2577 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08002578 loop2->MakeRawWatcher(
2579 configuration::GetChannel(configuration(), "/test",
2580 "aos.TestMessage", "", nullptr),
2581 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08002582 },
2583 "node");
Brian Silverman454bc112020-03-05 14:21:25 -08002584 EXPECT_DEATH({ loop1->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
2585 "node");
2586 EXPECT_DEATH(
2587 {
2588 loop2->MakeRawNoArgWatcher(
2589 configuration::GetChannel(configuration(), "/test",
2590 "aos.TestMessage", "", nullptr),
2591 [](const Context &) {});
2592 },
2593 "node");
Austin Schuh217a9782019-12-21 23:02:50 -08002594}
2595
2596// Tests that fetchers fail when created on the wrong node.
2597TEST_P(AbstractEventLoopDeathTest, NodeFetcher) {
2598 EnableNodes("them");
2599 auto loop1 = Make();
2600
2601 EXPECT_DEATH({ auto fetcher = loop1->MakeFetcher<TestMessage>("/test"); },
2602 "node");
2603 EXPECT_DEATH(
2604 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08002605 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
2606 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08002607 },
2608 "node");
2609}
2610
2611// Tests that senders fail when created on the wrong node.
2612TEST_P(AbstractEventLoopDeathTest, NodeSender) {
2613 EnableNodes("them");
2614 auto loop1 = Make();
2615
2616 EXPECT_DEATH(
2617 {
2618 aos::Sender<TestMessage> sender =
2619 loop1->MakeSender<TestMessage>("/test");
2620 },
2621 "node");
2622
2623 // Note: Creating raw senders is always supported. Right now, this lets us
2624 // use them to create message_gateway.
2625}
2626
Brian Silverman341b57e2020-06-23 16:23:18 -07002627// Tests creating multiple Builders from a single Sender at the same time.
2628TEST_P(AbstractEventLoopDeathTest, MultipleBuilders) {
2629 auto loop1 = Make();
2630 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
2631
2632 { auto builder = sender.MakeBuilder(); }
2633 {
2634 auto builder = sender.MakeBuilder();
2635 builder.MakeBuilder<TestMessage>().Finish();
2636 }
2637 {
2638 // Creating this after the first one was destroyed should be fine.
2639 auto builder = sender.MakeBuilder();
2640 builder.MakeBuilder<TestMessage>().Finish();
2641 // But not a second one.
2642 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
2643 "May not overwrite in-use allocator");
2644 }
2645
2646 FlatbufferDetachedBuffer<TestMessage> detached =
2647 flatbuffers::DetachedBuffer();
2648 {
2649 auto builder = sender.MakeBuilder();
2650 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
2651 }
2652 {
2653 // This is the second one, after the detached one, so it should fail.
2654 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
2655 "May not overwrite in-use allocator");
2656 }
2657
2658 // Clear the detached one, and then we should be able to create another.
2659 detached = flatbuffers::DetachedBuffer();
2660 {
2661 auto builder = sender.MakeBuilder();
2662 builder.MakeBuilder<TestMessage>().Finish();
2663 }
2664
2665 // And then detach another one.
2666 {
2667 auto builder = sender.MakeBuilder();
2668 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
2669 }
2670}
2671
2672// Tests sending a buffer detached from a different builder.
2673TEST_P(AbstractEventLoopDeathTest, WrongDetachedBuffer) {
2674 auto loop1 = Make();
2675 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
2676 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
2677
2678 auto builder = sender1.MakeBuilder();
2679 FlatbufferDetachedBuffer<TestMessage> detached =
2680 builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
milind1f1dca32021-07-03 13:50:07 -07002681 EXPECT_DEATH(sender2.CheckOk(sender2.SendDetached(std::move(detached))),
Brian Silverman341b57e2020-06-23 16:23:18 -07002682 "May only send the buffer detached from this Sender");
2683}
2684
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07002685int TestChannelFrequency(EventLoop *event_loop) {
2686 return event_loop->GetChannel<TestMessage>("/test")->frequency();
2687}
2688
2689int TestChannelQueueSize(EventLoop *event_loop) {
2690 const int frequency = TestChannelFrequency(event_loop);
2691 const auto channel_storage_duration = std::chrono::nanoseconds(
2692 event_loop->configuration()->channel_storage_duration());
2693 const int queue_size =
2694 frequency * std::chrono::duration_cast<std::chrono::duration<double>>(
2695 channel_storage_duration)
2696 .count();
2697
2698 return queue_size;
2699}
2700
2701RawSender::Error SendTestMessage(aos::Sender<TestMessage> &sender) {
2702 aos::Sender<TestMessage>::Builder builder = sender.MakeBuilder();
2703 TestMessage::Builder test_message_builder =
2704 builder.MakeBuilder<TestMessage>();
2705 test_message_builder.add_value(0);
2706 return builder.Send(test_message_builder.Finish());
2707}
2708
2709// Test that sending messages too fast returns
2710// RawSender::Error::kMessagesSentTooFast.
2711TEST_P(AbstractEventLoopTest, SendingMessagesTooFast) {
2712 auto event_loop = MakePrimary();
2713
2714 auto sender = event_loop->MakeSender<TestMessage>("/test");
2715
2716 // Send one message in the beginning, then wait until the
2717 // channel_storage_duration is almost done and start sending messages rapidly,
2718 // having some come in the next chanel_storage_duration. The queue_size is
2719 // 1600, so the 1601st message will be the last valid one (the initial message
2720 // having being sent more than a channel_storage_duration ago), and trying to
2721 // send the 1602nd message should return
2722 // RawSender::Error::kMessagesSentTooFast.
2723 EXPECT_EQ(SendTestMessage(sender), RawSender::Error::kOk);
2724 int msgs_sent = 1;
2725 const int queue_size = TestChannelQueueSize(event_loop.get());
2726
2727 const auto timer = event_loop->AddTimer([&]() {
2728 const bool done = (msgs_sent == queue_size + 1);
2729 ASSERT_EQ(
2730 SendTestMessage(sender),
2731 done ? RawSender::Error::kMessagesSentTooFast : RawSender::Error::kOk);
2732 msgs_sent++;
2733 if (done) {
2734 Exit();
2735 }
2736 });
2737
2738 const auto kRepeatOffset = std::chrono::milliseconds(1);
2739 const auto base_offset =
2740 std::chrono::nanoseconds(
2741 event_loop->configuration()->channel_storage_duration()) -
2742 (kRepeatOffset * (queue_size / 2));
2743 event_loop->OnRun([&event_loop, &timer, &base_offset, &kRepeatOffset]() {
2744 timer->Setup(event_loop->monotonic_now() + base_offset, kRepeatOffset);
2745 });
2746
2747 Run();
2748}
2749
2750// Tests that we are able to send messages successfully after sending messages
2751// too fast and waiting while continuously attempting to send messages.
2752// Also tests that SendFailureCounter is working correctly in this
2753// situation
2754TEST_P(AbstractEventLoopTest, SendingAfterSendingTooFast) {
2755 auto event_loop = MakePrimary();
2756
2757 auto sender = event_loop->MakeSender<TestMessage>("/test");
2758
2759 // We are sending messages at 1 kHz, so we will be sending too fast after
2760 // queue_size (1600) ms. After this, keep sending messages, and exactly a
2761 // channel storage duration (2s) after we send the first message we should
2762 // be able to successfully send a message.
2763
2764 const monotonic_clock::duration kInterval = std::chrono::milliseconds(1);
2765 const monotonic_clock::duration channel_storage_duration =
2766 std::chrono::nanoseconds(
2767 event_loop->configuration()->channel_storage_duration());
2768 const int queue_size = TestChannelQueueSize(event_loop.get());
2769
2770 int msgs_sent = 0;
2771 SendFailureCounter counter;
2772 auto start = monotonic_clock::min_time;
2773
2774 event_loop->AddPhasedLoop(
2775 [&](int) {
2776 const auto actual_err = SendTestMessage(sender);
2777 const bool done_waiting = (start != monotonic_clock::min_time &&
2778 sender.monotonic_sent_time() >=
2779 (start + channel_storage_duration));
2780 const auto expected_err =
2781 (msgs_sent < queue_size || done_waiting
2782 ? RawSender::Error::kOk
2783 : RawSender::Error::kMessagesSentTooFast);
2784
2785 if (start == monotonic_clock::min_time) {
2786 start = sender.monotonic_sent_time();
2787 }
2788
2789 ASSERT_EQ(actual_err, expected_err);
2790 counter.Count(actual_err);
2791 msgs_sent++;
2792
2793 EXPECT_EQ(counter.failures(),
2794 msgs_sent <= queue_size
2795 ? 0
2796 : (msgs_sent - queue_size) -
2797 (actual_err == RawSender::Error::kOk ? 1 : 0));
2798 EXPECT_EQ(counter.just_failed(), actual_err != RawSender::Error::kOk);
2799
2800 if (done_waiting) {
2801 Exit();
2802 }
2803 },
2804 kInterval);
2805 Run();
2806}
2807
2808// Tests that RawSender::Error::kMessagesSentTooFast is returned
2809// when messages are sent too fast from senders in different loops
2810TEST_P(AbstractEventLoopTest, SendingTooFastWithMultipleLoops) {
2811 auto loop1 = MakePrimary();
2812 auto loop2 = Make();
2813
2814 auto sender1 = loop1->MakeSender<TestMessage>("/test");
2815 auto sender2 = loop2->MakeSender<TestMessage>("/test");
2816
2817 // Send queue_size messages split between the senders.
2818 const int queue_size = TestChannelQueueSize(loop1.get());
2819 for (int i = 0; i < queue_size / 2; i++) {
2820 ASSERT_EQ(SendTestMessage(sender1), RawSender::Error::kOk);
2821 ASSERT_EQ(SendTestMessage(sender2), RawSender::Error::kOk);
2822 }
2823
2824 // Since queue_size messages have been sent, this should return an error
2825 EXPECT_EQ(SendTestMessage(sender2), RawSender::Error::kMessagesSentTooFast);
2826}
2827
Parker Schuhe4a70d62017-12-27 20:10:20 -08002828} // namespace testing
2829} // namespace aos