blob: 0eeecf87728f642e29c3eae595d7d5be7b73f1ee [file] [log] [blame]
Alex Perrycb7da4b2019-08-28 19:35:56 -07001#include "aos/events/event_loop_param_test.h"
Parker Schuhe4a70d62017-12-27 20:10:20 -08002
Austin Schuh52d325c2019-06-23 18:59:06 -07003#include <chrono>
Brian Silverman4f4e0612020-08-12 19:54:41 -07004#include <unordered_map>
5#include <unordered_set>
Austin Schuh52d325c2019-06-23 18:59:06 -07006
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07007#include "aos/events/test_message_generated.h"
Austin Schuh54cf95f2019-11-29 13:14:18 -08008#include "aos/flatbuffer_merge.h"
Austin Schuhad9e5eb2021-11-19 20:33:55 -08009#include "aos/logging/log_message_generated.h"
10#include "aos/logging/logging.h"
Austin Schuhcc6070c2020-10-10 20:25:56 -070011#include "aos/realtime.h"
Austin Schuh54cf95f2019-11-29 13:14:18 -080012#include "glog/logging.h"
Tyler Chatow67ddb032020-01-12 14:30:04 -080013#include "gmock/gmock.h"
14#include "gtest/gtest.h"
Austin Schuh9fe68f72019-08-10 19:32:03 -070015
Parker Schuhe4a70d62017-12-27 20:10:20 -080016namespace aos {
17namespace testing {
Austin Schuh52d325c2019-06-23 18:59:06 -070018namespace {
19namespace chrono = ::std::chrono;
20} // namespace
Parker Schuhe4a70d62017-12-27 20:10:20 -080021
Brian Silverman4f4e0612020-08-12 19:54:41 -070022::std::unique_ptr<EventLoop> AbstractEventLoopTest::Make(
23 std::string_view name) {
24 std::string name_copy(name);
25 if (name == "") {
26 name_copy = "loop";
27 name_copy += std::to_string(event_loop_count_);
28 }
29 ++event_loop_count_;
Austin Schuh6bae8252021-02-07 22:01:49 -080030 auto result = factory_->Make(name_copy);
31 if (do_timing_reports() == DoTimingReports::kNo) {
32 result->SkipTimingReport();
33 }
34 return result;
Brian Silverman4f4e0612020-08-12 19:54:41 -070035}
36
37void AbstractEventLoopTest::VerifyBuffers(
38 int number_buffers,
39 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>> fetchers,
40 std::vector<std::reference_wrapper<const Sender<TestMessage>>> senders) {
41 // The buffers which are in a sender.
42 std::unordered_set<int> in_sender;
43 for (const Sender<TestMessage> &sender : senders) {
44 const int this_buffer = sender.buffer_index();
45 CHECK_GE(this_buffer, 0);
46 CHECK_LT(this_buffer, number_buffers);
47 CHECK(in_sender.insert(this_buffer).second) << ": " << this_buffer;
48 }
49
50 if (read_method() != ReadMethod::PIN) {
51 // If we're not using PIN, we can't really verify anything about what
52 // buffers the fetchers have.
53 return;
54 }
55
56 // Mapping from TestMessage::value to buffer index.
57 std::unordered_map<int, int> fetcher_values;
58 for (const Fetcher<TestMessage> &fetcher : fetchers) {
59 if (!fetcher.get()) {
60 continue;
61 }
62 const int this_buffer = fetcher.context().buffer_index;
63 CHECK_GE(this_buffer, 0);
64 CHECK_LT(this_buffer, number_buffers);
65 CHECK(in_sender.count(this_buffer) == 0) << ": " << this_buffer;
66 const auto insert_result = fetcher_values.insert(
67 std::make_pair(fetcher.get()->value(), this_buffer));
68 if (!insert_result.second) {
69 CHECK_EQ(this_buffer, insert_result.first->second);
70 }
71 }
72}
73
Austin Schuh6b6dfa52019-06-12 20:16:20 -070074// Tests that watcher can receive messages from a sender.
Parker Schuhe4a70d62017-12-27 20:10:20 -080075// Also tests that OnRun() works.
76TEST_P(AbstractEventLoopTest, Basic) {
77 auto loop1 = Make();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070078 auto loop2 = MakePrimary();
79
Alex Perrycb7da4b2019-08-28 19:35:56 -070080 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
Austin Schuh6b6dfa52019-06-12 20:16:20 -070081
82 bool happened = false;
83
84 loop2->OnRun([&]() {
85 happened = true;
86
Alex Perrycb7da4b2019-08-28 19:35:56 -070087 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
88 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
89 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -070090 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -070091 });
92
93 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070094 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -070095 this->Exit();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070096 });
97
98 EXPECT_FALSE(happened);
99 Run();
100 EXPECT_TRUE(happened);
101}
102
Brian Silverman341b57e2020-06-23 16:23:18 -0700103// Tests that watcher can receive messages from a sender, sent via SendDetached.
104TEST_P(AbstractEventLoopTest, BasicSendDetached) {
105 auto loop1 = Make();
106 auto loop2 = MakePrimary();
107
108 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
109
110 FlatbufferDetachedBuffer<TestMessage> detached =
111 flatbuffers::DetachedBuffer();
112 {
113 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
114 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
115 builder.add_value(100);
116 detached = msg.Detach(builder.Finish());
117 }
118 detached = flatbuffers::DetachedBuffer();
119 {
120 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
121 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
122 builder.add_value(200);
123 detached = msg.Detach(builder.Finish());
124 }
milind1f1dca32021-07-03 13:50:07 -0700125 sender.CheckOk(sender.SendDetached(std::move(detached)));
Brian Silverman341b57e2020-06-23 16:23:18 -0700126
127 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
128 ASSERT_TRUE(fetcher.Fetch());
129 EXPECT_EQ(fetcher->value(), 200);
130}
131
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800132// Verifies that a no-arg watcher will not have a data pointer.
133TEST_P(AbstractEventLoopTest, NoArgNoData) {
134 auto loop1 = Make();
135 auto loop2 = MakePrimary();
136
137 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
138
139 bool happened = false;
140
141 loop2->OnRun([&]() {
142 happened = true;
143
144 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
145 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -0700146 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800147 });
148
149 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
150 EXPECT_GT(loop2->context().size, 0u);
151 EXPECT_EQ(nullptr, loop2->context().data);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700152 EXPECT_EQ(-1, loop2->context().buffer_index);
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800153 this->Exit();
154 });
155
156 EXPECT_FALSE(happened);
157 Run();
158 EXPECT_TRUE(happened);
159}
160
Brian Silverman454bc112020-03-05 14:21:25 -0800161// Tests that no-arg watcher can receive messages from a sender.
162// Also tests that OnRun() works.
163TEST_P(AbstractEventLoopTest, BasicNoArg) {
164 auto loop1 = Make();
165 auto loop2 = MakePrimary();
166
167 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
168
169 bool happened = false;
170
171 loop2->OnRun([&]() {
172 happened = true;
173
174 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
175 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
176 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700177 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -0800178 });
179
180 aos::Fetcher<TestMessage> fetcher = loop2->MakeFetcher<TestMessage>("/test");
181 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
182 ASSERT_TRUE(fetcher.Fetch());
183 EXPECT_EQ(fetcher->value(), 200);
184 this->Exit();
185 });
186
187 EXPECT_FALSE(happened);
188 Run();
189 EXPECT_TRUE(happened);
190}
191
192// Tests that a watcher can be created with an std::function.
193TEST_P(AbstractEventLoopTest, BasicFunction) {
194 auto loop1 = Make();
195 auto loop2 = MakePrimary();
196
197 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
198
199 bool happened = false;
200
201 loop2->OnRun([&]() {
202 happened = true;
203
204 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
205 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
206 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700207 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -0800208 });
209
210 loop2->MakeWatcher("/test", std::function<void(const TestMessage &)>(
211 [&](const TestMessage &message) {
212 EXPECT_EQ(message.value(), 200);
213 this->Exit();
214 }));
215
216 EXPECT_FALSE(happened);
217 Run();
218 EXPECT_TRUE(happened);
219}
220
Brian Silverman0fc69932020-01-24 21:54:02 -0800221// Tests that watcher can receive messages from two senders.
222// Also tests that OnRun() works.
223TEST_P(AbstractEventLoopTest, BasicTwoSenders) {
224 auto loop1 = Make();
225 auto loop2 = MakePrimary();
226
227 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
228 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
229
230 bool happened = false;
231
232 loop2->OnRun([&]() {
233 happened = true;
234
235 {
236 aos::Sender<TestMessage>::Builder msg = sender1.MakeBuilder();
237 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
238 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700239 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman0fc69932020-01-24 21:54:02 -0800240 }
241 {
242 aos::Sender<TestMessage>::Builder msg = sender2.MakeBuilder();
243 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
244 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700245 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman0fc69932020-01-24 21:54:02 -0800246 }
247 });
248
249 int messages_received = 0;
250 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
251 EXPECT_EQ(message.value(), 200);
252 this->Exit();
253 ++messages_received;
254 });
255
256 EXPECT_FALSE(happened);
257 Run();
258 EXPECT_TRUE(happened);
259 EXPECT_EQ(messages_received, 2);
260}
261
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700262// Tests that a fetcher can fetch from a sender.
263// Also tests that OnRun() works.
264TEST_P(AbstractEventLoopTest, FetchWithoutRun) {
265 auto loop1 = Make();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800266 auto loop2 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -0700267 auto loop3 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800268
269 auto sender = loop1->MakeSender<TestMessage>("/test");
270
271 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
272
Austin Schuhbbce72d2019-05-26 15:11:46 -0700273 EXPECT_FALSE(fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -0800274 EXPECT_EQ(fetcher.get(), nullptr);
275
Austin Schuhad154822019-12-27 15:45:13 -0800276 EXPECT_EQ(fetcher.context().monotonic_event_time, monotonic_clock::min_time);
277 EXPECT_EQ(fetcher.context().monotonic_remote_time, monotonic_clock::min_time);
278 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
279 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -0700280 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
Austin Schuh39788ff2019-12-01 18:22:57 -0800281 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
282 EXPECT_EQ(fetcher.context().size, 0u);
283 EXPECT_EQ(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700284 EXPECT_EQ(fetcher.context().buffer_index, -1);
Austin Schuhbbce72d2019-05-26 15:11:46 -0700285
Alex Perrycb7da4b2019-08-28 19:35:56 -0700286 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
287 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
288 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700289 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700290
291 EXPECT_TRUE(fetcher.Fetch());
292 ASSERT_FALSE(fetcher.get() == nullptr);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700293 EXPECT_EQ(fetcher.get()->value(), 200);
Austin Schuh39788ff2019-12-01 18:22:57 -0800294
295 const chrono::milliseconds kEpsilon(100);
296
Austin Schuhad154822019-12-27 15:45:13 -0800297 const aos::monotonic_clock::time_point monotonic_now = loop2->monotonic_now();
298 const aos::realtime_clock::time_point realtime_now = loop2->realtime_now();
299 EXPECT_EQ(fetcher.context().monotonic_event_time,
300 fetcher.context().monotonic_remote_time);
301 EXPECT_EQ(fetcher.context().realtime_event_time,
302 fetcher.context().realtime_remote_time);
303
304 EXPECT_GE(fetcher.context().monotonic_event_time, monotonic_now - kEpsilon);
305 EXPECT_LE(fetcher.context().monotonic_event_time, monotonic_now + kEpsilon);
306 EXPECT_GE(fetcher.context().realtime_event_time, realtime_now - kEpsilon);
307 EXPECT_LE(fetcher.context().realtime_event_time, realtime_now + kEpsilon);
Austin Schuha9012be2021-07-21 15:19:11 -0700308 EXPECT_EQ(fetcher.context().source_boot_uuid, loop2->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -0800309 EXPECT_EQ(fetcher.context().queue_index, 0x0u);
310 EXPECT_EQ(fetcher.context().size, 20u);
311 EXPECT_NE(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700312 if (read_method() == ReadMethod::PIN) {
313 EXPECT_GE(fetcher.context().buffer_index, 0);
314 EXPECT_LT(fetcher.context().buffer_index,
315 loop2->NumberBuffers(fetcher.channel()));
316 } else {
317 EXPECT_EQ(fetcher.context().buffer_index, -1);
318 }
Parker Schuhe4a70d62017-12-27 20:10:20 -0800319}
320
Austin Schuh3578a2e2019-05-25 18:17:59 -0700321// Tests that watcher will receive all messages sent if they are sent after
322// initialization and before running.
323TEST_P(AbstractEventLoopTest, DoubleSendAtStartup) {
324 auto loop1 = Make();
325 auto loop2 = MakePrimary();
326
327 auto sender = loop1->MakeSender<TestMessage>("/test");
328
329 ::std::vector<int> values;
330
331 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700332 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700333 if (values.size() == 2) {
Austin Schuh9fe68f72019-08-10 19:32:03 -0700334 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -0700335 }
336 });
337
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700338 // Before Run, should be ignored.
Austin Schuh3578a2e2019-05-25 18:17:59 -0700339 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700340 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
341 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
342 builder.add_value(199);
milind1f1dca32021-07-03 13:50:07 -0700343 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700344 }
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700345
346 loop2->OnRun([&]() {
347 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700348 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
349 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
350 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700351 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700352 }
353 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700354 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
355 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
356 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700357 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700358 }
359 });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700360
361 Run();
362
363 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
364}
365
366// Tests that watcher will not receive messages sent before the watcher is
367// created.
368TEST_P(AbstractEventLoopTest, DoubleSendAfterStartup) {
369 auto loop1 = Make();
370 auto loop2 = MakePrimary();
371
372 auto sender = loop1->MakeSender<TestMessage>("/test");
373
374 ::std::vector<int> values;
375
376 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700377 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
378 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
379 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700380 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700381 }
382 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700383 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
384 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
385 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700386 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700387 }
388
389 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700390 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700391 });
392
393 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700394 auto test_timer = loop2->AddTimer([this]() { this->Exit(); });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700395 loop2->OnRun([&test_timer, &loop2]() {
396 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
397 });
398
399 Run();
400 EXPECT_EQ(0, values.size());
401}
402
Austin Schuhbbce72d2019-05-26 15:11:46 -0700403// Tests that FetchNext gets all the messages sent after it is constructed.
404TEST_P(AbstractEventLoopTest, FetchNext) {
405 auto loop1 = Make();
406 auto loop2 = MakePrimary();
407
408 auto sender = loop1->MakeSender<TestMessage>("/test");
409 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
410
411 ::std::vector<int> values;
412
413 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700414 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
415 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
416 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700417 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700418 }
419 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700420 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
421 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
422 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700423 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700424 }
425
426 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700427 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700428 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700429 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700430 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700431 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700432 });
433
434 loop2->OnRun([&test_timer, &loop2]() {
435 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
436 });
437
438 Run();
439 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
440}
441
442// Tests that FetchNext gets no messages sent before it is constructed.
443TEST_P(AbstractEventLoopTest, FetchNextAfterSend) {
444 auto loop1 = Make();
445 auto loop2 = MakePrimary();
446
447 auto sender = loop1->MakeSender<TestMessage>("/test");
448
449 ::std::vector<int> values;
450
451 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700452 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
453 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
454 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700455 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700456 }
457 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700458 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
459 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
460 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700461 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700462 }
463
464 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
465
466 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700467 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700468 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700469 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700470 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700471 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700472 });
473
474 loop2->OnRun([&test_timer, &loop2]() {
475 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
476 });
477
478 Run();
479 EXPECT_THAT(0, values.size());
480}
481
482// Tests that Fetch returns the last message created before the loop was
483// started.
484TEST_P(AbstractEventLoopTest, FetchDataFromBeforeCreation) {
485 auto loop1 = Make();
486 auto loop2 = MakePrimary();
487
488 auto sender = loop1->MakeSender<TestMessage>("/test");
489
490 ::std::vector<int> values;
491
492 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700493 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
494 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
495 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700496 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700497 }
498 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700499 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
500 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
501 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700502 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700503 }
504
505 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
506
507 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700508 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700509 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700510 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700511 }
512 // Do it again to make sure we don't double fetch.
513 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700514 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700515 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700516 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700517 });
518
519 loop2->OnRun([&test_timer, &loop2]() {
520 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
521 });
522
523 Run();
524 EXPECT_THAT(values, ::testing::ElementsAreArray({201}));
525}
526
527// Tests that Fetch and FetchNext interleave as expected.
528TEST_P(AbstractEventLoopTest, FetchAndFetchNextTogether) {
529 auto loop1 = Make();
530 auto loop2 = MakePrimary();
531
532 auto sender = loop1->MakeSender<TestMessage>("/test");
533
534 ::std::vector<int> values;
535
536 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700537 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
538 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
539 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700540 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700541 }
542 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700543 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
544 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
545 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700546 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700547 }
548
549 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
550
551 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700552 auto test_timer = loop2->AddTimer([&fetcher, &values, &sender, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700553 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700554 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700555 }
556
557 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700558 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
559 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
560 builder.add_value(202);
milind1f1dca32021-07-03 13:50:07 -0700561 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700562 }
563 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700564 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
565 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
566 builder.add_value(203);
milind1f1dca32021-07-03 13:50:07 -0700567 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700568 }
569 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700570 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
571 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
572 builder.add_value(204);
milind1f1dca32021-07-03 13:50:07 -0700573 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700574 }
575
576 if (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700577 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700578 }
579
580 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700581 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700582 }
583
Austin Schuh9fe68f72019-08-10 19:32:03 -0700584 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700585 });
586
587 loop2->OnRun([&test_timer, &loop2]() {
588 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
589 });
590
591 Run();
592 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
593}
594
Austin Schuh3115a202019-05-27 21:02:14 -0700595// Tests that FetchNext behaves correctly when we get two messages in the queue
596// but don't consume the first until after the second has been sent.
597TEST_P(AbstractEventLoopTest, FetchNextTest) {
Austin Schuh3115a202019-05-27 21:02:14 -0700598 auto send_loop = Make();
599 auto fetch_loop = Make();
600 auto sender = send_loop->MakeSender<TestMessage>("/test");
601 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
602
603 {
Tyler Chatow67ddb032020-01-12 14:30:04 -0800604 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
605 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
606 builder.add_value(100);
milind1f1dca32021-07-03 13:50:07 -0700607 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700608 }
609
610 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700611 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
612 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
613 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700614 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700615 }
616
617 ASSERT_TRUE(fetcher.FetchNext());
618 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700619 EXPECT_EQ(100, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700620
621 ASSERT_TRUE(fetcher.FetchNext());
622 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700623 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700624
625 // When we run off the end of the queue, expect to still have the old message:
626 ASSERT_FALSE(fetcher.FetchNext());
627 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700628 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700629}
630
Brian Silverman77162972020-08-12 19:52:40 -0700631// Verify that a fetcher still holds its data, even after falling behind.
632TEST_P(AbstractEventLoopTest, FetcherBehindData) {
633 auto send_loop = Make();
634 auto fetch_loop = Make();
635 auto sender = send_loop->MakeSender<TestMessage>("/test");
636 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
637 {
638 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
639 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
640 builder.add_value(1);
milind1f1dca32021-07-03 13:50:07 -0700641 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -0700642 }
643 ASSERT_TRUE(fetcher.Fetch());
644 EXPECT_EQ(1, fetcher.get()->value());
645 for (int i = 0; i < 300; ++i) {
646 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
647 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
648 builder.add_value(i + 2);
milind1f1dca32021-07-03 13:50:07 -0700649 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -0700650 }
651 EXPECT_EQ(1, fetcher.get()->value());
652}
653
654// Try a bunch of orderings of operations with fetchers and senders. Verify that
655// all the fetchers have the correct data at each step.
656TEST_P(AbstractEventLoopTest, FetcherPermutations) {
657 for (int max_save = 0; max_save < 5; ++max_save) {
658 SCOPED_TRACE("max_save=" + std::to_string(max_save));
659
660 auto send_loop = Make();
661 auto fetch_loop = Make();
662 auto sender = send_loop->MakeSender<TestMessage>("/test");
663 const auto send_message = [&sender](int i) {
664 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
665 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
666 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700667 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -0700668 };
669 std::vector<Fetcher<TestMessage>> fetchers;
670 for (int i = 0; i < 10; ++i) {
671 fetchers.emplace_back(fetch_loop->MakeFetcher<TestMessage>("/test"));
672 }
673 send_message(1);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700674 const auto verify_buffers = [&]() {
675 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>>
676 fetchers_copy;
677 for (const auto &fetcher : fetchers) {
678 fetchers_copy.emplace_back(fetcher);
679 }
680 std::vector<std::reference_wrapper<const Sender<TestMessage>>>
681 senders_copy;
682 senders_copy.emplace_back(sender);
683 VerifyBuffers(send_loop->NumberBuffers(sender.channel()), fetchers_copy,
684 senders_copy);
685 };
Brian Silverman77162972020-08-12 19:52:40 -0700686 for (auto &fetcher : fetchers) {
687 ASSERT_TRUE(fetcher.Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -0700688 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700689 EXPECT_EQ(1, fetcher.get()->value());
690 }
691
692 for (int save = 1; save <= max_save; ++save) {
693 SCOPED_TRACE("save=" + std::to_string(save));
694 send_message(100 + save);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700695 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700696 for (size_t i = 0; i < fetchers.size() - save; ++i) {
697 SCOPED_TRACE("fetcher=" + std::to_string(i));
698 ASSERT_TRUE(fetchers[i].Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -0700699 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700700 EXPECT_EQ(100 + save, fetchers[i].get()->value());
701 }
702 for (size_t i = fetchers.size() - save; i < fetchers.size() - 1; ++i) {
703 SCOPED_TRACE("fetcher=" + std::to_string(i));
704 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
705 }
706 EXPECT_EQ(1, fetchers.back().get()->value());
707 }
708
709 for (int i = 0; i < 300; ++i) {
710 send_message(200 + i);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700711 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700712 }
713
714 for (size_t i = 0; i < fetchers.size() - max_save; ++i) {
715 SCOPED_TRACE("fetcher=" + std::to_string(i));
716 if (max_save > 0) {
717 EXPECT_EQ(100 + max_save, fetchers[i].get()->value());
718 } else {
719 EXPECT_EQ(1, fetchers[i].get()->value());
720 }
721 }
722 for (size_t i = fetchers.size() - max_save; i < fetchers.size() - 1; ++i) {
723 SCOPED_TRACE("fetcher=" + std::to_string(i));
724 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
725 }
726 EXPECT_EQ(1, fetchers.back().get()->value());
727 }
728}
729
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800730// Verify that making a fetcher and watcher for "/test" succeeds.
731TEST_P(AbstractEventLoopTest, FetcherAndWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800732 auto loop = Make();
733 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800734 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Parker Schuhe4a70d62017-12-27 20:10:20 -0800735}
736
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800737// Verify that making 2 fetchers for "/test" succeeds.
Parker Schuhe4a70d62017-12-27 20:10:20 -0800738TEST_P(AbstractEventLoopTest, TwoFetcher) {
739 auto loop = Make();
740 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800741 auto fetcher2 = loop->MakeFetcher<TestMessage>("/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -0800742}
743
Alex Perrycb7da4b2019-08-28 19:35:56 -0700744// Verify that registering a watcher for an invalid channel name dies.
745TEST_P(AbstractEventLoopDeathTest, InvalidChannelName) {
746 auto loop = Make();
747 EXPECT_DEATH(
748 { loop->MakeWatcher("/test/invalid", [&](const TestMessage &) {}); },
749 "/test/invalid");
Brian Silverman454bc112020-03-05 14:21:25 -0800750 EXPECT_DEATH(
751 { loop->MakeNoArgWatcher<TestMessage>("/test/invalid", [&]() {}); },
752 "/test/invalid");
Alex Perrycb7da4b2019-08-28 19:35:56 -0700753}
754
James Kuszmaul8866e642022-06-10 16:00:36 -0700755// Verify that setting up a timer before monotonic_clock::epoch() fails.
James Kuszmaul86e86c32022-07-21 17:39:47 -0700756TEST_P(AbstractEventLoopDeathTest, NegativeTimeTimer) {
James Kuszmaul8866e642022-06-10 16:00:36 -0700757 auto loop = Make();
758 TimerHandler *time = loop->AddTimer([]() {});
759 EXPECT_DEATH(time->Setup(monotonic_clock::epoch() - std::chrono::seconds(1)),
760 "-1.000");
761}
762
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800763// Verify that registering a watcher twice for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700764TEST_P(AbstractEventLoopDeathTest, TwoWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800765 auto loop = Make();
766 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800767 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
768 "/test");
Brian Silverman454bc112020-03-05 14:21:25 -0800769 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
770}
771
772// Verify that registering a no-arg watcher twice for "/test" fails.
773TEST_P(AbstractEventLoopDeathTest, TwoNoArgWatcher) {
774 auto loop = Make();
775 loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {});
776 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
777 "/test");
778 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800779}
780
Austin Schuh3115a202019-05-27 21:02:14 -0700781// Verify that SetRuntimeRealtimePriority fails while running.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700782TEST_P(AbstractEventLoopDeathTest, SetRuntimeRealtimePriority) {
Austin Schuh3115a202019-05-27 21:02:14 -0700783 auto loop = MakePrimary();
784 // Confirm that runtime priority calls work when not realtime.
785 loop->SetRuntimeRealtimePriority(5);
786
787 loop->OnRun([&]() { loop->SetRuntimeRealtimePriority(5); });
788
789 EXPECT_DEATH(Run(), "realtime");
790}
791
Brian Silverman6a54ff32020-04-28 16:41:39 -0700792// Verify that SetRuntimeAffinity fails while running.
793TEST_P(AbstractEventLoopDeathTest, SetRuntimeAffinity) {
Austin Schuhde973292021-10-12 18:09:49 -0700794 const cpu_set_t available = GetCurrentThreadAffinity();
795 int first_cpu = -1;
796 for (int i = 0; i < CPU_SETSIZE; ++i) {
797 if (CPU_ISSET(i, &available)) {
798 first_cpu = i;
799 break;
800 continue;
801 }
802 }
803 CHECK_NE(first_cpu, -1) << ": Default affinity has no CPUs?";
804
Brian Silverman6a54ff32020-04-28 16:41:39 -0700805 auto loop = MakePrimary();
806 // Confirm that runtime priority calls work when not running.
Austin Schuhde973292021-10-12 18:09:49 -0700807 loop->SetRuntimeAffinity(MakeCpusetFromCpus({first_cpu}));
Brian Silverman6a54ff32020-04-28 16:41:39 -0700808
Austin Schuhde973292021-10-12 18:09:49 -0700809 loop->OnRun(
810 [&]() { loop->SetRuntimeAffinity(MakeCpusetFromCpus({first_cpu})); });
Brian Silverman6a54ff32020-04-28 16:41:39 -0700811
812 EXPECT_DEATH(Run(), "Cannot set affinity while running");
813}
814
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800815// Verify that registering a watcher and a sender for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700816TEST_P(AbstractEventLoopDeathTest, WatcherAndSender) {
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800817 auto loop = Make();
818 auto sender = loop->MakeSender<TestMessage>("/test");
819 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
820 "/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -0800821}
822
Austin Schuhe516ab02020-05-06 21:37:04 -0700823// Verify that creating too many senders fails.
824TEST_P(AbstractEventLoopDeathTest, TooManySenders) {
825 auto loop = Make();
826 std::vector<aos::Sender<TestMessage>> senders;
827 for (int i = 0; i < 10; ++i) {
828 senders.emplace_back(loop->MakeSender<TestMessage>("/test"));
829 }
830 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); },
831 "Failed to create sender on \\{ \"name\": \"/test\", \"type\": "
Brian Silverman77162972020-08-12 19:52:40 -0700832 "\"aos.TestMessage\"[^}]*\\ }, too many senders.");
833}
834
835// Verify that creating too many fetchers fails.
836TEST_P(AbstractEventLoopDeathTest, TooManyFetchers) {
837 if (read_method() != ReadMethod::PIN) {
838 // Other read methods don't limit the number of readers, so just skip this.
839 return;
840 }
841
842 auto loop = Make();
843 std::vector<aos::Fetcher<TestMessage>> fetchers;
844 for (int i = 0; i < 10; ++i) {
845 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
846 }
847 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
848 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
849 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
850}
851
852// Verify that creating too many fetchers, split between two event loops, fails.
853TEST_P(AbstractEventLoopDeathTest, TooManyFetchersTwoLoops) {
854 if (read_method() != ReadMethod::PIN) {
855 // Other read methods don't limit the number of readers, so just skip this.
856 return;
857 }
858
859 auto loop = Make();
860 auto loop2 = Make();
861 std::vector<aos::Fetcher<TestMessage>> fetchers;
862 for (int i = 0; i < 5; ++i) {
863 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
864 fetchers.emplace_back(loop2->MakeFetcher<TestMessage>("/test"));
865 }
866 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
867 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
868 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
869}
870
871// Verify that creating too many watchers fails.
872TEST_P(AbstractEventLoopDeathTest, TooManyWatchers) {
873 if (read_method() != ReadMethod::PIN) {
874 // Other read methods don't limit the number of readers, so just skip this.
875 return;
876 }
877
878 std::vector<std::unique_ptr<EventLoop>> loops;
879 for (int i = 0; i < 10; ++i) {
880 loops.emplace_back(Make());
881 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
882 }
883 EXPECT_DEATH({ Make()->MakeWatcher("/test", [](const TestMessage &) {}); },
884 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
885 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
886}
887
888// Verify that creating too many watchers and fetchers combined fails.
889TEST_P(AbstractEventLoopDeathTest, TooManyWatchersAndFetchers) {
890 if (read_method() != ReadMethod::PIN) {
891 // Other read methods don't limit the number of readers, so just skip this.
892 return;
893 }
894
895 auto loop = Make();
896 std::vector<aos::Fetcher<TestMessage>> fetchers;
897 std::vector<std::unique_ptr<EventLoop>> loops;
898 for (int i = 0; i < 5; ++i) {
899 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
900 loops.emplace_back(Make());
901 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
902 }
903 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
904 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
905 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
Austin Schuhe516ab02020-05-06 21:37:04 -0700906}
907
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700908// Verify that we can't create a sender inside OnRun.
909TEST_P(AbstractEventLoopDeathTest, SenderInOnRun) {
910 auto loop1 = MakePrimary();
911
912 loop1->OnRun(
913 [&]() { auto sender = loop1->MakeSender<TestMessage>("/test2"); });
914
915 EXPECT_DEATH(Run(), "running");
916}
917
918// Verify that we can't create a watcher inside OnRun.
919TEST_P(AbstractEventLoopDeathTest, WatcherInOnRun) {
920 auto loop1 = MakePrimary();
921
922 loop1->OnRun(
923 [&]() { loop1->MakeWatcher("/test", [&](const TestMessage &) {}); });
924
925 EXPECT_DEATH(Run(), "running");
926}
927
Brian Silverman454bc112020-03-05 14:21:25 -0800928// Verify that we can't create a no-arg watcher inside OnRun.
929TEST_P(AbstractEventLoopDeathTest, NoArgWatcherInOnRun) {
930 auto loop1 = MakePrimary();
931
932 loop1->OnRun(
933 [&]() { loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {}); });
934
935 EXPECT_DEATH(Run(), "running");
936}
937
Parker Schuhe4a70d62017-12-27 20:10:20 -0800938// Verify that Quit() works when there are multiple watchers.
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800939TEST_P(AbstractEventLoopTest, MultipleWatcherQuit) {
940 auto loop1 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -0700941 auto loop2 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800942
Austin Schuh3578a2e2019-05-25 18:17:59 -0700943 loop2->MakeWatcher("/test1", [&](const TestMessage &) {});
944 loop2->MakeWatcher("/test2", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700945 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -0700946 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -0700947 });
948
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800949 auto sender = loop1->MakeSender<TestMessage>("/test2");
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700950
951 loop2->OnRun([&]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700952 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
953 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
954 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700955 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700956 });
Parker Schuhe4a70d62017-12-27 20:10:20 -0800957
Austin Schuh44019f92019-05-19 19:58:27 -0700958 Run();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800959}
960
Austin Schuhad9e5eb2021-11-19 20:33:55 -0800961// Verify that AOS_LOG has the right name.
962TEST_P(AbstractEventLoopTest, AOSLog) {
963 auto loop2 = MakePrimary("loop1");
964 auto loop1 = Make("loop0");
965
966 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
967
968 EXPECT_FALSE(fetcher.Fetch());
969
970 loop2->OnRun([&]() {
971 AOS_LOG(INFO, "Testing123");
972 this->Exit();
973 });
974
975 Run();
976 EXPECT_TRUE(fetcher.Fetch());
977 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
978}
979
980// Verify that AOS_LOG has the right name in a watcher.
981TEST_P(AbstractEventLoopTest, AOSLogWatcher) {
982 auto loop2 = MakePrimary("loop1");
983 auto loop1 = Make("loop0");
984
985 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
986
987 EXPECT_FALSE(fetcher.Fetch());
988
989 auto sender = loop1->MakeSender<TestMessage>("/test2");
990
991 loop2->MakeWatcher("/test2", [&](const TestMessage & /*message*/) {
992 AOS_LOG(INFO, "Testing123");
993 this->Exit();
994 });
995
996 loop2->OnRun([&]() {
997 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
998 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
999 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001000 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001001 });
1002
1003 Run();
1004 EXPECT_TRUE(fetcher.Fetch());
1005 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1006}
1007
1008// Verify that AOS_LOG has the right name in a timer.
1009TEST_P(AbstractEventLoopTest, AOSLogTimer) {
1010 auto loop2 = MakePrimary("loop1");
1011 auto loop1 = Make("loop0");
1012
1013 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1014
1015 EXPECT_FALSE(fetcher.Fetch());
1016
1017 auto test_timer = loop2->AddTimer([&]() {
1018 AOS_LOG(INFO, "Testing123");
1019 this->Exit();
1020 });
1021
1022 loop2->OnRun([&]() { test_timer->Setup(loop2->monotonic_now()); });
1023
1024 Run();
1025 EXPECT_TRUE(fetcher.Fetch());
1026 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1027}
1028
Neil Balch229001a2018-01-07 18:22:52 -08001029// Verify that timer intervals and duration function properly.
1030TEST_P(AbstractEventLoopTest, TimerIntervalAndDuration) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001031 // Force a slower rate so we are guaranteed to have reports for our timer.
Austin Schuh39788ff2019-12-01 18:22:57 -08001032 FLAGS_timing_report_ms = 2000;
1033
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001034 const int kCount = 5;
Neil Balch229001a2018-01-07 18:22:52 -08001035
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001036 auto loop = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001037 auto loop2 = Make();
1038
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001039 ::std::vector<::aos::monotonic_clock::time_point> times;
1040 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
1041
Austin Schuh39788ff2019-12-01 18:22:57 -08001042 Fetcher<timing::Report> report_fetcher =
1043 loop2->MakeFetcher<timing::Report>("/aos");
1044 EXPECT_FALSE(report_fetcher.Fetch());
1045
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001046 auto test_timer = loop->AddTimer([this, &times, &expected_times, &loop]() {
1047 times.push_back(loop->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001048 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
1049 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
1050 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001051 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -08001052 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
1053 EXPECT_EQ(loop->context().size, 0u);
1054 EXPECT_EQ(loop->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001055 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001056
Austin Schuhad154822019-12-27 15:45:13 -08001057 expected_times.push_back(loop->context().monotonic_event_time);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001058 if (times.size() == kCount) {
1059 this->Exit();
1060 }
Neil Balch229001a2018-01-07 18:22:52 -08001061 });
Austin Schuh39788ff2019-12-01 18:22:57 -08001062 test_timer->set_name("Test loop");
Neil Balch229001a2018-01-07 18:22:52 -08001063
Austin Schuh39788ff2019-12-01 18:22:57 -08001064 const monotonic_clock::time_point start_time = loop->monotonic_now();
Austin Schuh52d325c2019-06-23 18:59:06 -07001065 // TODO(austin): This should be an error... Should be done in OnRun only.
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001066 test_timer->Setup(start_time + chrono::seconds(1), chrono::seconds(1));
1067
Austin Schuh44019f92019-05-19 19:58:27 -07001068 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001069
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001070 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001071 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
1072 ASSERT_EQ(times.size(), expected_times.size());
1073 ASSERT_EQ((times.size() % 2), 1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001074
1075 // Grab the middle sample.
1076 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
1077
1078 // Add up all the delays of all the times.
1079 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1080 for (const ::aos::monotonic_clock::time_point time : times) {
1081 sum += time - average_time;
1082 }
1083
1084 // Average and add to the middle to find the average time.
1085 sum /= times.size();
1086 average_time += sum;
1087
1088 // Compute the offset from the average and the expected average. It
1089 // should be pretty close to 0.
1090 const ::aos::monotonic_clock::duration remainder =
1091 average_time - start_time - chrono::seconds(times.size() / 2 + 1);
1092
1093 const chrono::milliseconds kEpsilon(100);
1094 EXPECT_LT(remainder, +kEpsilon);
1095 EXPECT_GT(remainder, -kEpsilon);
1096
1097 // Make sure that the average duration is close to 1 second.
1098 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1099 times.front())
1100 .count() /
1101 static_cast<double>(times.size() - 1),
1102 1.0, 0.1);
1103
1104 // Confirm that the ideal wakeup times increment correctly.
1105 for (size_t i = 1; i < expected_times.size(); ++i) {
1106 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1107 }
1108
1109 for (size_t i = 0; i < expected_times.size(); ++i) {
1110 EXPECT_EQ((expected_times[i] - start_time) % chrono::seconds(1),
1111 chrono::seconds(0));
1112 }
1113
1114 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1115 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001116
Austin Schuh6bae8252021-02-07 22:01:49 -08001117 if (do_timing_reports() == DoTimingReports::kYes) {
1118 // And, since we are here, check that the timing report makes sense.
1119 // Start by looking for our event loop's timing.
1120 FlatbufferDetachedBuffer<timing::Report> report =
1121 FlatbufferDetachedBuffer<timing::Report>::Empty();
1122 while (report_fetcher.FetchNext()) {
1123 if (report_fetcher->name()->string_view() == "primary") {
1124 report = CopyFlatBuffer(report_fetcher.get());
1125 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001126 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001127
1128 // Confirm that we have the right number of reports, and the contents are
1129 // sane.
1130 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
1131
1132 EXPECT_EQ(report.message().name()->string_view(), "primary");
1133
1134 ASSERT_NE(report.message().senders(), nullptr);
1135 EXPECT_EQ(report.message().senders()->size(), 2);
1136
1137 ASSERT_NE(report.message().timers(), nullptr);
1138 EXPECT_EQ(report.message().timers()->size(), 2);
1139
1140 EXPECT_EQ(report.message().timers()->Get(0)->name()->string_view(),
1141 "Test loop");
1142 EXPECT_GE(report.message().timers()->Get(0)->count(), 1);
1143
1144 EXPECT_EQ(report.message().timers()->Get(1)->name()->string_view(),
1145 "timing_reports");
1146 EXPECT_EQ(report.message().timers()->Get(1)->count(), 1);
1147
1148 // Make sure there is a single phased loop report with our report in it.
1149 ASSERT_EQ(report.message().phased_loops(), nullptr);
1150 } else {
1151 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001152 }
Neil Balch229001a2018-01-07 18:22:52 -08001153}
1154
1155// Verify that we can change a timer's parameters during execution.
1156TEST_P(AbstractEventLoopTest, TimerChangeParameters) {
Austin Schuh44019f92019-05-19 19:58:27 -07001157 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001158 loop->SetRuntimeRealtimePriority(1);
Austin Schuh7f20f512021-01-31 17:56:16 -08001159 std::vector<monotonic_clock::time_point> iteration_list;
Neil Balch229001a2018-01-07 18:22:52 -08001160
1161 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001162 ScopedNotRealtime nrt;
Austin Schuh7f20f512021-01-31 17:56:16 -08001163 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001164 });
1165
Austin Schuh7f20f512021-01-31 17:56:16 -08001166 monotonic_clock::time_point s;
1167 auto modifier_timer = loop->AddTimer([&test_timer, &s]() {
Austin Schuhd892f102021-10-12 18:01:46 -07001168 test_timer->Setup(s + chrono::milliseconds(1750),
1169 chrono::milliseconds(600));
Neil Balch229001a2018-01-07 18:22:52 -08001170 });
1171
Austin Schuh7f20f512021-01-31 17:56:16 -08001172 s = loop->monotonic_now();
Austin Schuhd892f102021-10-12 18:01:46 -07001173 test_timer->Setup(s, chrono::milliseconds(500));
1174 modifier_timer->Setup(s + chrono::milliseconds(1250));
1175 EndEventLoop(loop.get(), chrono::milliseconds(3950));
Austin Schuh44019f92019-05-19 19:58:27 -07001176 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001177
Austin Schuhd892f102021-10-12 18:01:46 -07001178 EXPECT_THAT(
1179 iteration_list,
1180 ::testing::ElementsAre(
1181 s, s + chrono::milliseconds(500), s + chrono::milliseconds(1000),
1182 s + chrono::milliseconds(1750), s + chrono::milliseconds(2350),
1183 s + chrono::milliseconds(2950), s + chrono::milliseconds(3550)));
Neil Balch229001a2018-01-07 18:22:52 -08001184}
1185
1186// Verify that we can disable a timer during execution.
1187TEST_P(AbstractEventLoopTest, TimerDisable) {
Austin Schuh44019f92019-05-19 19:58:27 -07001188 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001189 loop->SetRuntimeRealtimePriority(1);
Neil Balch229001a2018-01-07 18:22:52 -08001190 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
1191
1192 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001193 ScopedNotRealtime nrt;
Austin Schuhd892f102021-10-12 18:01:46 -07001194 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001195 });
1196
Tyler Chatow67ddb032020-01-12 14:30:04 -08001197 auto ender_timer = loop->AddTimer([&test_timer]() { test_timer->Disable(); });
Neil Balch229001a2018-01-07 18:22:52 -08001198
Austin Schuhd892f102021-10-12 18:01:46 -07001199 monotonic_clock::time_point s = loop->monotonic_now();
Austin Schuh73d99502021-12-08 12:05:39 -08001200 test_timer->Setup(s, ::std::chrono::milliseconds(500));
1201 ender_timer->Setup(s + ::std::chrono::milliseconds(1250));
1202 EndEventLoop(loop.get(), ::std::chrono::milliseconds(2000));
Austin Schuh44019f92019-05-19 19:58:27 -07001203 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001204
Austin Schuhd892f102021-10-12 18:01:46 -07001205 EXPECT_THAT(iteration_list,
Austin Schuh73d99502021-12-08 12:05:39 -08001206 ::testing::ElementsAre(s, s + chrono::milliseconds(500),
1207 s + chrono::milliseconds(1000)));
Neil Balch229001a2018-01-07 18:22:52 -08001208}
Austin Schuh7267c532019-05-19 19:55:53 -07001209
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001210// Verify that a timer can disable itself.
1211//
1212// TODO(Brian): Do something similar with phased loops, both with a quick
1213// handler and a handler that would miss a cycle except it got deferred. Current
1214// behavior doing that is a mess.
1215TEST_P(AbstractEventLoopTest, TimerDisableSelf) {
1216 auto loop = MakePrimary();
1217
1218 int count = 0;
1219 aos::TimerHandler *test_timer;
1220 test_timer = loop->AddTimer([&count, &test_timer]() {
1221 ++count;
1222 test_timer->Disable();
1223 });
1224
1225 test_timer->Setup(loop->monotonic_now(), ::std::chrono::milliseconds(20));
1226 EndEventLoop(loop.get(), ::std::chrono::milliseconds(80));
1227 Run();
1228
1229 EXPECT_EQ(count, 1);
1230}
1231
Brian Silvermanbd405c02020-06-23 16:25:23 -07001232// Verify that we can disable a timer during execution of another timer
1233// scheduled for the same time, with one ordering of creation for the timers.
1234//
1235// Also schedule some more events to reshuffle the heap in EventLoop used for
1236// tracking events to change up the order. This used to segfault
1237// SimulatedEventLoop.
1238TEST_P(AbstractEventLoopTest, TimerDisableOther) {
1239 for (bool creation_order : {true, false}) {
1240 for (bool setup_order : {true, false}) {
1241 for (int shuffle_events = 0; shuffle_events < 5; ++shuffle_events) {
1242 auto loop = MakePrimary();
1243 aos::TimerHandler *test_timer, *ender_timer;
1244 if (creation_order) {
1245 test_timer = loop->AddTimer([]() {});
1246 ender_timer =
1247 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1248 } else {
1249 ender_timer =
1250 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1251 test_timer = loop->AddTimer([]() {});
1252 }
1253
1254 const auto start = loop->monotonic_now();
1255
1256 for (int i = 0; i < shuffle_events; ++i) {
1257 loop->AddTimer([]() {})->Setup(start + std::chrono::milliseconds(10));
1258 }
1259
1260 if (setup_order) {
1261 test_timer->Setup(start + ::std::chrono::milliseconds(20));
1262 ender_timer->Setup(start + ::std::chrono::milliseconds(20));
1263 } else {
1264 ender_timer->Setup(start + ::std::chrono::milliseconds(20));
1265 test_timer->Setup(start + ::std::chrono::milliseconds(20));
1266 }
1267 EndEventLoop(loop.get(), ::std::chrono::milliseconds(40));
1268 Run();
1269 }
1270 }
1271 }
1272}
1273
Austin Schuh54cf95f2019-11-29 13:14:18 -08001274// Verifies that the event loop implementations detect when Channel is not a
Brian Silverman631b6262021-11-10 12:25:08 -08001275// pointer into configuration(), or a name doesn't map to a channel in
1276// configuration().
Austin Schuh54cf95f2019-11-29 13:14:18 -08001277TEST_P(AbstractEventLoopDeathTest, InvalidChannel) {
1278 auto loop = MakePrimary();
1279
Tyler Chatow67ddb032020-01-12 14:30:04 -08001280 const Channel *channel = configuration::GetChannel(
1281 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
Austin Schuh54cf95f2019-11-29 13:14:18 -08001282
1283 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1284
1285 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001286 loop->MakeRawSender(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001287 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1288
1289 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001290 loop->MakeSender<TestMessage>("/testbad"),
1291 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1292 " not found in config");
1293
1294 EXPECT_FALSE(loop->TryMakeSender<TestMessage>("/testbad"));
1295
1296 EXPECT_DEATH(
1297 loop->MakeRawFetcher(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001298 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1299
1300 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001301 loop->MakeFetcher<TestMessage>("/testbad"),
1302 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1303 " not found in config");
1304
1305 EXPECT_FALSE(loop->TryMakeFetcher<TestMessage>("/testbad").valid());
1306
1307 EXPECT_DEATH(
Austin Schuh54cf95f2019-11-29 13:14:18 -08001308 {
1309 loop->MakeRawWatcher(&channel_copy.message(),
1310 [](const Context, const void *) {});
1311 },
1312 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
Brian Silverman631b6262021-11-10 12:25:08 -08001313
1314 EXPECT_DEATH(
1315 { loop->MakeWatcher("/testbad", [](const TestMessage &) {}); },
1316 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1317 " not found in config");
1318}
1319
1320// Verifies that the event loop handles a channel which is not readable or
1321// writable on the current node nicely.
1322TEST_P(AbstractEventLoopDeathTest, InaccessibleChannel) {
1323 EnableNodes("me");
1324 auto loop = MakePrimary("me");
1325 auto loop2 = Make("them");
1326
1327 const Channel *channel = configuration::GetChannel(
1328 loop->configuration(), "/test_noforward", "aos.TestMessage", "", nullptr);
1329
1330 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1331
1332 EXPECT_DEATH(
1333 loop2->MakeSender<TestMessage>("/test_forward"),
1334 "Channel"
1335 " \\{ \"name\": \"/test_forward\", \"type\": \"aos.TestMessage\" \\}"
1336 " is not able to be sent on this node");
1337
1338 EXPECT_FALSE(loop2->TryMakeSender<TestMessage>("/test_forward"));
1339
1340 EXPECT_DEATH(
1341 loop2->MakeRawFetcher(channel),
1342 "Channel"
1343 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1344 " is not able to be fetched on this node");
1345
1346 EXPECT_DEATH(
1347 loop2->MakeFetcher<TestMessage>("/test_noforward"),
1348 "Channel"
1349 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1350 " is not able to be fetched on this node");
1351
1352 EXPECT_FALSE(loop2->TryMakeFetcher<TestMessage>("/test_noforward").valid());
1353
1354 EXPECT_DEATH(
1355 { loop2->MakeRawWatcher(channel, [](const Context, const void *) {}); },
1356 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1357 "\"source_node\": \"them\" \\}"
1358 " is not able to be watched on this node");
1359
1360 EXPECT_DEATH(
1361 { loop2->MakeWatcher("/test_noforward", [](const TestMessage &) {}); },
1362 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1363 "\"source_node\": \"them\" \\}"
1364 " is not able to be watched on this node");
Austin Schuh54cf95f2019-11-29 13:14:18 -08001365}
1366
Austin Schuhd54780b2020-10-03 16:26:02 -07001367// Verifies that the event loop implementations detect when Channel has an
1368// invalid alignment.
1369TEST_P(AbstractEventLoopDeathTest, InvalidChannelAlignment) {
1370 const char *const kError = "multiple of alignment";
1371 InvalidChannelAlignment();
1372
1373 auto loop = MakePrimary();
1374
1375 const Channel *channel = configuration::GetChannel(
1376 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
1377
1378 EXPECT_DEATH({ loop->MakeRawSender(channel); }, kError);
1379 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); }, kError);
1380
1381 EXPECT_DEATH({ loop->MakeRawFetcher(channel); }, kError);
1382 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); }, kError);
1383
1384 EXPECT_DEATH(
1385 { loop->MakeRawWatcher(channel, [](const Context &, const void *) {}); },
1386 kError);
1387 EXPECT_DEATH({ loop->MakeRawNoArgWatcher(channel, [](const Context &) {}); },
1388 kError);
1389
1390 EXPECT_DEATH({ loop->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
1391 kError);
1392 EXPECT_DEATH({ loop->MakeWatcher("/test", [](const TestMessage &) {}); },
1393 kError);
1394}
1395
Brian Silverman454bc112020-03-05 14:21:25 -08001396// Verify that the send time on a message is roughly right when using a watcher.
Austin Schuh7267c532019-05-19 19:55:53 -07001397TEST_P(AbstractEventLoopTest, MessageSendTime) {
Austin Schuh44019f92019-05-19 19:58:27 -07001398 auto loop1 = MakePrimary();
Austin Schuh7267c532019-05-19 19:55:53 -07001399 auto loop2 = Make();
Austin Schuhad154822019-12-27 15:45:13 -08001400 auto sender = loop2->MakeSender<TestMessage>("/test");
Austin Schuh7267c532019-05-19 19:55:53 -07001401 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
1402
1403 auto test_timer = loop1->AddTimer([&sender]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001404 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1405 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1406 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001407 msg.CheckOk(msg.Send(builder.Finish()));
Alex Perrycb7da4b2019-08-28 19:35:56 -07001408 });
1409
Austin Schuhad154822019-12-27 15:45:13 -08001410 bool triggered = false;
Brian Silverman454bc112020-03-05 14:21:25 -08001411 loop1->MakeWatcher("/test", [&](const TestMessage &msg) {
Austin Schuhad154822019-12-27 15:45:13 -08001412 // Confirm that the data pointer makes sense from a watcher, and all the
1413 // timestamps look right.
1414 EXPECT_GT(&msg, loop1->context().data);
1415 EXPECT_EQ(loop1->context().monotonic_remote_time,
1416 loop1->context().monotonic_event_time);
1417 EXPECT_EQ(loop1->context().realtime_remote_time,
1418 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001419 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001420
1421 const aos::monotonic_clock::time_point monotonic_now =
1422 loop1->monotonic_now();
Tyler Chatow67ddb032020-01-12 14:30:04 -08001423 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08001424
1425 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1426 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1427 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1428 monotonic_now);
1429 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1430 realtime_now);
1431
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001432 EXPECT_LT(&msg, reinterpret_cast<const void *>(
1433 reinterpret_cast<const char *>(loop1->context().data) +
Austin Schuhad154822019-12-27 15:45:13 -08001434 loop1->context().size));
Brian Silverman4f4e0612020-08-12 19:54:41 -07001435 if (read_method() == ReadMethod::PIN) {
1436 EXPECT_GE(loop1->context().buffer_index, 0);
1437 EXPECT_LT(loop1->context().buffer_index,
1438 loop1->NumberBuffers(
1439 configuration::GetChannel(loop1->configuration(), "/test",
1440 "aos.TestMessage", "", nullptr)));
1441 } else {
1442 EXPECT_EQ(-1, loop1->context().buffer_index);
1443 }
Austin Schuhad154822019-12-27 15:45:13 -08001444 triggered = true;
Austin Schuh7267c532019-05-19 19:55:53 -07001445 });
1446
1447 test_timer->Setup(loop1->monotonic_now() + ::std::chrono::seconds(1));
1448
1449 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
Austin Schuh44019f92019-05-19 19:58:27 -07001450 Run();
Austin Schuh7267c532019-05-19 19:55:53 -07001451
Austin Schuhad154822019-12-27 15:45:13 -08001452 EXPECT_TRUE(triggered);
1453
Brian Silverman454bc112020-03-05 14:21:25 -08001454 ASSERT_TRUE(fetcher.Fetch());
1455
1456 monotonic_clock::duration monotonic_time_offset =
1457 fetcher.context().monotonic_event_time -
1458 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1459 realtime_clock::duration realtime_time_offset =
1460 fetcher.context().realtime_event_time -
1461 (loop1->realtime_now() - ::std::chrono::seconds(1));
1462
1463 EXPECT_EQ(fetcher.context().realtime_event_time,
1464 fetcher.context().realtime_remote_time);
1465 EXPECT_EQ(fetcher.context().monotonic_event_time,
1466 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001467 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001468
1469 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1470 << ": Got "
1471 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1472 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1473 // Confirm that the data pointer makes sense.
1474 EXPECT_GT(fetcher.get(), fetcher.context().data);
1475 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001476 reinterpret_cast<const void *>(
1477 reinterpret_cast<const char *>(fetcher.context().data) +
Brian Silverman454bc112020-03-05 14:21:25 -08001478 fetcher.context().size));
1479 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1480 << ": Got "
1481 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1482 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1483
1484 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1485 << ": Got "
1486 << fetcher.context().realtime_event_time.time_since_epoch().count()
1487 << " expected " << loop1->realtime_now().time_since_epoch().count();
1488 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1489 << ": Got "
1490 << fetcher.context().realtime_event_time.time_since_epoch().count()
1491 << " expected " << loop1->realtime_now().time_since_epoch().count();
1492}
1493
1494// Verify that the send time on a message is roughly right when using a no-arg
1495// watcher. To get a message, we need to use a fetcher to actually access the
1496// message. This is also the main use case for no-arg fetchers.
1497TEST_P(AbstractEventLoopTest, MessageSendTimeNoArg) {
1498 auto loop1 = MakePrimary();
1499 auto loop2 = Make();
1500 auto sender = loop2->MakeSender<TestMessage>("/test");
1501 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
1502
1503 auto test_timer = loop1->AddTimer([&sender]() {
1504 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1505 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1506 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001507 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -08001508 });
1509
1510 bool triggered = false;
1511 loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {
1512 // Confirm that we can indeed use a fetcher on this channel from this
1513 // context, and it results in a sane data pointer and timestamps.
1514 ASSERT_TRUE(fetcher.Fetch());
1515
1516 EXPECT_EQ(loop1->context().monotonic_remote_time,
1517 loop1->context().monotonic_event_time);
1518 EXPECT_EQ(loop1->context().realtime_remote_time,
1519 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001520 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001521
1522 const aos::monotonic_clock::time_point monotonic_now =
1523 loop1->monotonic_now();
1524 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
1525
1526 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1527 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1528 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1529 monotonic_now);
1530 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1531 realtime_now);
1532
1533 triggered = true;
1534 });
1535
1536 test_timer->Setup(loop1->monotonic_now() + ::std::chrono::seconds(1));
1537
1538 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
1539 Run();
1540
1541 ASSERT_TRUE(triggered);
Austin Schuh7267c532019-05-19 19:55:53 -07001542
Alex Perrycb7da4b2019-08-28 19:35:56 -07001543 monotonic_clock::duration monotonic_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001544 fetcher.context().monotonic_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001545 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1546 realtime_clock::duration realtime_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001547 fetcher.context().realtime_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001548 (loop1->realtime_now() - ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07001549
Austin Schuhad154822019-12-27 15:45:13 -08001550 EXPECT_EQ(fetcher.context().realtime_event_time,
1551 fetcher.context().realtime_remote_time);
1552 EXPECT_EQ(fetcher.context().monotonic_event_time,
1553 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001554 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001555
Alex Perrycb7da4b2019-08-28 19:35:56 -07001556 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1557 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001558 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh52d325c2019-06-23 18:59:06 -07001559 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07001560 // Confirm that the data pointer makes sense.
1561 EXPECT_GT(fetcher.get(), fetcher.context().data);
1562 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001563 reinterpret_cast<const void *>(
1564 reinterpret_cast<const char *>(fetcher.context().data) +
Alex Perrycb7da4b2019-08-28 19:35:56 -07001565 fetcher.context().size));
1566 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1567 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001568 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh7267c532019-05-19 19:55:53 -07001569 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07001570
1571 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1572 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001573 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07001574 << " expected " << loop1->realtime_now().time_since_epoch().count();
1575 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1576 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001577 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07001578 << " expected " << loop1->realtime_now().time_since_epoch().count();
Austin Schuh7267c532019-05-19 19:55:53 -07001579}
1580
Austin Schuh52d325c2019-06-23 18:59:06 -07001581// Tests that a couple phased loops run in a row result in the correct offset
1582// and period.
1583TEST_P(AbstractEventLoopTest, PhasedLoopTest) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001584 // Force a slower rate so we are guaranteed to have reports for our phased
Austin Schuh39788ff2019-12-01 18:22:57 -08001585 // loop.
1586 FLAGS_timing_report_ms = 2000;
1587
Austin Schuh52d325c2019-06-23 18:59:06 -07001588 const chrono::milliseconds kOffset = chrono::milliseconds(400);
1589 const int kCount = 5;
1590
1591 auto loop1 = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001592 auto loop2 = Make();
1593
1594 Fetcher<timing::Report> report_fetcher =
1595 loop2->MakeFetcher<timing::Report>("/aos");
1596 EXPECT_FALSE(report_fetcher.Fetch());
Austin Schuh52d325c2019-06-23 18:59:06 -07001597
1598 // Collect up a couple of samples.
1599 ::std::vector<::aos::monotonic_clock::time_point> times;
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001600 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
Austin Schuh52d325c2019-06-23 18:59:06 -07001601
1602 // Run kCount iterations.
Austin Schuh39788ff2019-12-01 18:22:57 -08001603 loop1
1604 ->AddPhasedLoop(
1605 [&times, &expected_times, &loop1, this](int count) {
1606 EXPECT_EQ(count, 1);
1607 times.push_back(loop1->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001608 expected_times.push_back(loop1->context().monotonic_event_time);
Austin Schuh39788ff2019-12-01 18:22:57 -08001609
Austin Schuhad154822019-12-27 15:45:13 -08001610 EXPECT_EQ(loop1->context().monotonic_remote_time,
1611 monotonic_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001612 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001613 EXPECT_EQ(loop1->context().realtime_event_time,
1614 realtime_clock::min_time);
1615 EXPECT_EQ(loop1->context().realtime_remote_time,
Austin Schuh39788ff2019-12-01 18:22:57 -08001616 realtime_clock::min_time);
1617 EXPECT_EQ(loop1->context().queue_index, 0xffffffffu);
1618 EXPECT_EQ(loop1->context().size, 0u);
1619 EXPECT_EQ(loop1->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001620 EXPECT_EQ(loop1->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001621
1622 if (times.size() == kCount) {
1623 LOG(INFO) << "Exiting";
1624 this->Exit();
1625 }
1626 },
1627 chrono::seconds(1), kOffset)
1628 ->set_name("Test loop");
Austin Schuh52d325c2019-06-23 18:59:06 -07001629
1630 // Add a delay to make sure that delay during startup doesn't result in a
1631 // "missed cycle".
1632 SleepFor(chrono::seconds(2));
1633
1634 Run();
1635
1636 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001637 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
1638 ASSERT_EQ(times.size(), expected_times.size());
1639 ASSERT_EQ((times.size() % 2), 1);
Austin Schuh52d325c2019-06-23 18:59:06 -07001640
1641 // Grab the middle sample.
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001642 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
Austin Schuh52d325c2019-06-23 18:59:06 -07001643
1644 // Add up all the delays of all the times.
1645 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1646 for (const ::aos::monotonic_clock::time_point time : times) {
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001647 sum += time - average_time;
Austin Schuh52d325c2019-06-23 18:59:06 -07001648 }
1649
1650 // Average and add to the middle to find the average time.
1651 sum /= times.size();
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001652 average_time += sum;
Austin Schuh52d325c2019-06-23 18:59:06 -07001653
1654 // Compute the offset from the start of the second of the average time. This
1655 // should be pretty close to the offset.
1656 const ::aos::monotonic_clock::duration remainder =
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001657 average_time.time_since_epoch() -
1658 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
Austin Schuh52d325c2019-06-23 18:59:06 -07001659
1660 const chrono::milliseconds kEpsilon(100);
1661 EXPECT_LT(remainder, kOffset + kEpsilon);
1662 EXPECT_GT(remainder, kOffset - kEpsilon);
1663
1664 // Make sure that the average duration is close to 1 second.
1665 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1666 times.front())
1667 .count() /
1668 static_cast<double>(times.size() - 1),
1669 1.0, 0.1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001670
1671 // Confirm that the ideal wakeup times increment correctly.
1672 for (size_t i = 1; i < expected_times.size(); ++i) {
1673 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1674 }
1675
1676 for (size_t i = 0; i < expected_times.size(); ++i) {
1677 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
1678 kOffset);
1679 }
1680
1681 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1682 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001683
Austin Schuh6bae8252021-02-07 22:01:49 -08001684 if (do_timing_reports() == DoTimingReports::kYes) {
1685 // And, since we are here, check that the timing report makes sense.
1686 // Start by looking for our event loop's timing.
1687 FlatbufferDetachedBuffer<timing::Report> report =
1688 FlatbufferDetachedBuffer<timing::Report>::Empty();
1689 while (report_fetcher.FetchNext()) {
1690 if (report_fetcher->name()->string_view() == "primary") {
1691 report = CopyFlatBuffer(report_fetcher.get());
1692 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001693 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001694
1695 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
1696
1697 EXPECT_EQ(report.message().name()->string_view(), "primary");
1698
1699 ASSERT_NE(report.message().senders(), nullptr);
1700 EXPECT_EQ(report.message().senders()->size(), 2);
1701
1702 ASSERT_NE(report.message().timers(), nullptr);
1703 EXPECT_EQ(report.message().timers()->size(), 1);
1704
1705 // Make sure there is a single phased loop report with our report in it.
1706 ASSERT_NE(report.message().phased_loops(), nullptr);
1707 ASSERT_EQ(report.message().phased_loops()->size(), 1);
1708 EXPECT_EQ(report.message().phased_loops()->Get(0)->name()->string_view(),
1709 "Test loop");
1710 EXPECT_GE(report.message().phased_loops()->Get(0)->count(), 1);
1711 } else {
1712 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001713 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001714}
1715
Milind Upadhyay42589bb2021-05-19 20:05:16 -07001716// Tests that a phased loop responds correctly to a changing offset.
1717TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetTest) {
1718 // Force a slower rate so we are guaranteed to have reports for our phased
1719 // loop.
1720 FLAGS_timing_report_ms = 2000;
1721
1722 const chrono::milliseconds kOffset = chrono::milliseconds(400);
1723 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
1724 const int kCount = 5;
1725
1726 auto loop1 = MakePrimary();
1727
1728 // Collect up a couple of samples.
1729 ::std::vector<::aos::monotonic_clock::time_point> times;
1730 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
1731
1732 PhasedLoopHandler *phased_loop;
1733
1734 // Run kCount iterations.
1735 phased_loop = loop1->AddPhasedLoop(
1736 [&phased_loop, &times, &expected_times, &loop1, this, kOffset,
1737 kInterval](int count) {
1738 EXPECT_EQ(count, 1);
1739 times.push_back(loop1->monotonic_now());
1740
1741 expected_times.push_back(loop1->context().monotonic_event_time);
1742
1743 phased_loop->set_interval_and_offset(
1744 kInterval, kOffset - chrono::milliseconds(times.size()));
1745 LOG(INFO) << "new offset: "
1746 << (kOffset - chrono::milliseconds(times.size())).count();
1747
1748 if (times.size() == kCount) {
1749 LOG(INFO) << "Exiting";
1750 this->Exit();
1751 }
1752 },
1753 kInterval, kOffset);
1754 phased_loop->set_name("Test loop");
1755
1756 // Add a delay to make sure that delay during startup doesn't result in a
1757 // "missed cycle".
1758 SleepFor(chrono::seconds(2));
1759
1760 Run();
1761 // Confirm that we got both the right number of samples, and it's odd.
1762 EXPECT_EQ(times.size(), static_cast<size_t>(kCount));
1763 EXPECT_EQ(times.size(), expected_times.size());
1764 EXPECT_EQ((times.size() % 2), 1);
1765
1766 // Grab the middle sample.
1767 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
1768
1769 // Add up all the delays of all the times.
1770 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1771 for (const ::aos::monotonic_clock::time_point time : times) {
1772 sum += time - average_time;
1773 }
1774
1775 // Average and add to the middle to find the average time.
1776 sum /= times.size();
1777 average_time += sum;
1778
1779 // Compute the offset from the start of the second of the average time. This
1780 // should be pretty close to the offset.
1781 const ::aos::monotonic_clock::duration remainder =
1782 average_time.time_since_epoch() -
1783 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
1784
1785 const chrono::milliseconds kEpsilon(100);
1786 EXPECT_LT(remainder, kOffset + kEpsilon);
1787 EXPECT_GT(remainder, kOffset - kEpsilon);
1788
1789 // Make sure that the average duration is close to 1 second.
1790 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1791 times.front())
1792 .count() /
1793 static_cast<double>(times.size() - 1),
1794 1.0, 0.1);
1795
1796 // Confirm that the ideal wakeup times increment correctly.
1797 for (size_t i = 1; i < expected_times.size(); ++i) {
1798 LOG(INFO) << i - 1 << ": " << expected_times[i - 1] << ", " << i << ": "
1799 << expected_times[i];
1800 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1) -
1801 chrono::milliseconds(1));
1802 }
1803
1804 for (size_t i = 0; i < expected_times.size(); ++i) {
1805 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
1806 kOffset - chrono::milliseconds(i));
1807 }
1808
1809 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1810 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
1811}
1812
Austin Schuh39788ff2019-12-01 18:22:57 -08001813// Tests that senders count correctly in the timing report.
1814TEST_P(AbstractEventLoopTest, SenderTimingReport) {
1815 FLAGS_timing_report_ms = 1000;
1816 auto loop1 = MakePrimary();
1817
1818 auto loop2 = Make("watcher_loop");
1819 loop2->MakeWatcher("/test", [](const TestMessage &) {});
1820
1821 auto loop3 = Make();
1822
1823 Fetcher<timing::Report> report_fetcher =
1824 loop3->MakeFetcher<timing::Report>("/aos");
1825 EXPECT_FALSE(report_fetcher.Fetch());
1826
1827 auto sender = loop1->MakeSender<TestMessage>("/test");
1828
James Kuszmaul78514332022-04-06 15:08:34 -07001829 // Sanity check channel frequencies to ensure that we've designed the test
1830 // correctly.
1831 ASSERT_EQ(800, sender.channel()->frequency());
1832 ASSERT_EQ(2000000000, loop1->configuration()->channel_storage_duration());
1833 constexpr int kMaxAllowedMessages = 800 * 2;
1834 constexpr int kSendMessages = kMaxAllowedMessages * 2;
1835 constexpr int kDroppedMessages = kSendMessages - kMaxAllowedMessages;
1836
Austin Schuh39788ff2019-12-01 18:22:57 -08001837 // Add a timer to actually quit.
1838 auto test_timer = loop1->AddTimer([&sender]() {
James Kuszmaul78514332022-04-06 15:08:34 -07001839 for (int i = 0; i < kSendMessages; ++i) {
Austin Schuh39788ff2019-12-01 18:22:57 -08001840 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1841 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1842 builder.add_value(200 + i);
James Kuszmaul78514332022-04-06 15:08:34 -07001843 if (i < kMaxAllowedMessages) {
1844 msg.CheckOk(msg.Send(builder.Finish()));
1845 } else {
1846 EXPECT_EQ(RawSender::Error::kMessagesSentTooFast,
1847 msg.Send(builder.Finish()));
1848 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001849 }
1850 });
1851
1852 // Quit after 1 timing report, mid way through the next cycle.
1853 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
1854
1855 loop1->OnRun([&test_timer, &loop1]() {
1856 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1500));
1857 });
1858
1859 Run();
1860
Austin Schuh6bae8252021-02-07 22:01:49 -08001861 if (do_timing_reports() == DoTimingReports::kYes) {
1862 // And, since we are here, check that the timing report makes sense.
1863 // Start by looking for our event loop's timing.
1864 FlatbufferDetachedBuffer<timing::Report> primary_report =
1865 FlatbufferDetachedBuffer<timing::Report>::Empty();
1866 while (report_fetcher.FetchNext()) {
Austin Schuh8902fa52021-03-14 22:39:24 -07001867 VLOG(1) << "Report " << FlatbufferToJson(report_fetcher.get());
Austin Schuh6bae8252021-02-07 22:01:49 -08001868 if (report_fetcher->name()->string_view() == "primary") {
1869 primary_report = CopyFlatBuffer(report_fetcher.get());
1870 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001871 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001872
Austin Schuh8902fa52021-03-14 22:39:24 -07001873 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
Austin Schuh6bae8252021-02-07 22:01:49 -08001874
1875 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
1876
1877 ASSERT_NE(primary_report.message().senders(), nullptr);
1878 EXPECT_EQ(primary_report.message().senders()->size(), 3);
1879
1880 // Confirm that the sender looks sane.
1881 EXPECT_EQ(
1882 loop1->configuration()
1883 ->channels()
1884 ->Get(primary_report.message().senders()->Get(0)->channel_index())
1885 ->name()
1886 ->string_view(),
1887 "/test");
James Kuszmaul78514332022-04-06 15:08:34 -07001888 EXPECT_EQ(primary_report.message().senders()->Get(0)->count(),
1889 kMaxAllowedMessages);
1890 ASSERT_TRUE(primary_report.message().senders()->Get(0)->has_error_counts());
1891 ASSERT_EQ(
1892 primary_report.message().senders()->Get(0)->error_counts()->size(), 2u);
1893 EXPECT_EQ(
1894 primary_report.message()
1895 .senders()
1896 ->Get(0)
1897 ->error_counts()
1898 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
1899 ->count(),
1900 kDroppedMessages)
1901 << aos::FlatbufferToJson(primary_report);
1902 EXPECT_EQ(primary_report.message()
1903 .senders()
1904 ->Get(0)
1905 ->error_counts()
1906 ->Get(static_cast<size_t>(timing::SendError::INVALID_REDZONE))
1907 ->count(),
1908 0);
Austin Schuh6bae8252021-02-07 22:01:49 -08001909
1910 // Confirm that the timing primary_report sender looks sane.
1911 EXPECT_EQ(
1912 loop1->configuration()
1913 ->channels()
1914 ->Get(primary_report.message().senders()->Get(1)->channel_index())
1915 ->name()
1916 ->string_view(),
1917 "/aos");
1918 EXPECT_EQ(primary_report.message().senders()->Get(1)->count(), 1);
1919
1920 ASSERT_NE(primary_report.message().timers(), nullptr);
1921 EXPECT_EQ(primary_report.message().timers()->size(), 3);
1922
1923 // Make sure there are no phased loops or watchers.
1924 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
1925 ASSERT_EQ(primary_report.message().watchers(), nullptr);
1926 } else {
1927 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001928 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001929}
1930
James Kuszmaul93abac12022-04-14 15:05:10 -07001931// Tests that the RawSender::Send(void*, size_t) overload tracks things properly
1932// in its timing report.
1933TEST_P(AbstractEventLoopTest, CopySenderTimingReport) {
1934 gflags::FlagSaver flag_saver;
1935 FLAGS_timing_report_ms = 1000;
1936 auto loop1 = Make();
1937 auto loop2 = MakePrimary();
1938
1939 const FlatbufferDetachedBuffer<TestMessage> kMessage =
1940 JsonToFlatbuffer<TestMessage>("{}");
1941
1942 std::unique_ptr<aos::RawSender> sender =
1943 loop2->MakeRawSender(configuration::GetChannel(
1944 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
1945
1946 Fetcher<timing::Report> report_fetcher =
1947 loop1->MakeFetcher<timing::Report>("/aos");
1948 EXPECT_FALSE(report_fetcher.Fetch());
1949
1950 loop2->OnRun([&]() {
1951 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
1952 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
1953 RawSender::Error::kOk);
1954 }
1955 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
1956 RawSender::Error::kMessagesSentTooFast);
1957 });
1958 // Quit after 1 timing report, mid way through the next cycle.
1959 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
1960
1961 Run();
1962
1963 if (do_timing_reports() == DoTimingReports::kYes) {
1964 // Check that the sent too fast actually got recorded by the timing report.
1965 FlatbufferDetachedBuffer<timing::Report> primary_report =
1966 FlatbufferDetachedBuffer<timing::Report>::Empty();
1967 while (report_fetcher.FetchNext()) {
1968 if (report_fetcher->name()->string_view() == "primary") {
1969 primary_report = CopyFlatBuffer(report_fetcher.get());
1970 }
1971 }
1972
1973 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
1974
1975 ASSERT_NE(primary_report.message().senders(), nullptr);
1976 EXPECT_EQ(primary_report.message().senders()->size(), 3);
1977 EXPECT_EQ(
1978 primary_report.message()
1979 .senders()
1980 ->Get(0)
1981 ->error_counts()
1982 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
1983 ->count(),
1984 1);
1985 }
1986}
1987
Austin Schuh39788ff2019-12-01 18:22:57 -08001988// Tests that senders count correctly in the timing report.
1989TEST_P(AbstractEventLoopTest, WatcherTimingReport) {
1990 FLAGS_timing_report_ms = 1000;
1991 auto loop1 = MakePrimary();
1992 loop1->MakeWatcher("/test", [](const TestMessage &) {});
1993
1994 auto loop2 = Make("sender_loop");
1995
1996 auto loop3 = Make();
1997
1998 Fetcher<timing::Report> report_fetcher =
1999 loop3->MakeFetcher<timing::Report>("/aos");
2000 EXPECT_FALSE(report_fetcher.Fetch());
2001
2002 auto sender = loop2->MakeSender<TestMessage>("/test");
2003
2004 // Add a timer to actually quit.
2005 auto test_timer = loop1->AddTimer([&sender]() {
2006 for (int i = 0; i < 10; ++i) {
2007 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2008 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2009 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002010 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002011 }
2012 });
2013
2014 // Quit after 1 timing report, mid way through the next cycle.
2015 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2016
2017 loop1->OnRun([&test_timer, &loop1]() {
2018 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1500));
2019 });
2020
2021 Run();
2022
Austin Schuh6bae8252021-02-07 22:01:49 -08002023 if (do_timing_reports() == DoTimingReports::kYes) {
2024 // And, since we are here, check that the timing report makes sense.
2025 // Start by looking for our event loop's timing.
2026 FlatbufferDetachedBuffer<timing::Report> primary_report =
2027 FlatbufferDetachedBuffer<timing::Report>::Empty();
2028 while (report_fetcher.FetchNext()) {
2029 LOG(INFO) << "Report " << FlatbufferToJson(report_fetcher.get());
2030 if (report_fetcher->name()->string_view() == "primary") {
2031 primary_report = CopyFlatBuffer(report_fetcher.get());
2032 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002033 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002034
2035 // Check the watcher report.
2036 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2037
2038 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2039
2040 // Just the timing report timer.
2041 ASSERT_NE(primary_report.message().timers(), nullptr);
2042 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2043
2044 // No phased loops
2045 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2046
2047 ASSERT_NE(primary_report.message().watchers(), nullptr);
2048 ASSERT_EQ(primary_report.message().watchers()->size(), 1);
2049 EXPECT_EQ(primary_report.message().watchers()->Get(0)->count(), 10);
2050 } else {
2051 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002052 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002053}
2054
2055// Tests that fetchers count correctly in the timing report.
2056TEST_P(AbstractEventLoopTest, FetcherTimingReport) {
2057 FLAGS_timing_report_ms = 1000;
2058 auto loop1 = MakePrimary();
2059 auto loop2 = Make("sender_loop");
2060
2061 auto loop3 = Make();
2062
2063 Fetcher<timing::Report> report_fetcher =
2064 loop3->MakeFetcher<timing::Report>("/aos");
2065 EXPECT_FALSE(report_fetcher.Fetch());
2066
2067 auto sender = loop2->MakeSender<TestMessage>("/test");
2068 auto fetcher1 = loop1->MakeFetcher<TestMessage>("/test");
2069 auto fetcher2 = loop1->MakeFetcher<TestMessage>("/test");
2070 fetcher1.Fetch();
2071 fetcher2.Fetch();
2072
2073 // Add a timer to actually quit.
2074 auto test_timer = loop1->AddTimer([&sender]() {
2075 for (int i = 0; i < 10; ++i) {
2076 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2077 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2078 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002079 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002080 }
2081 });
2082
2083 auto test_timer2 = loop1->AddTimer([&fetcher1, &fetcher2]() {
2084 fetcher1.Fetch();
2085 while (fetcher2.FetchNext()) {
2086 }
2087 });
2088
2089 // Quit after 1 timing report, mid way through the next cycle.
2090 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2091
2092 loop1->OnRun([test_timer, test_timer2, &loop1]() {
2093 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1400));
2094 test_timer2->Setup(loop1->monotonic_now() + chrono::milliseconds(1600));
2095 });
2096
2097 Run();
2098
Austin Schuh6bae8252021-02-07 22:01:49 -08002099 if (do_timing_reports() == DoTimingReports::kYes) {
2100 // And, since we are here, check that the timing report makes sense.
2101 // Start by looking for our event loop's timing.
2102 FlatbufferDetachedBuffer<timing::Report> primary_report =
2103 FlatbufferDetachedBuffer<timing::Report>::Empty();
2104 while (report_fetcher.FetchNext()) {
2105 if (report_fetcher->name()->string_view() == "primary") {
2106 primary_report = CopyFlatBuffer(report_fetcher.get());
2107 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002108 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002109
2110 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2111
2112 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2113
2114 ASSERT_NE(primary_report.message().senders(), nullptr);
2115 EXPECT_EQ(primary_report.message().senders()->size(), 2);
2116
2117 ASSERT_NE(primary_report.message().timers(), nullptr);
2118 EXPECT_EQ(primary_report.message().timers()->size(), 4);
2119
2120 // Make sure there are no phased loops or watchers.
2121 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2122 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2123
2124 // Now look at the fetchrs.
2125 ASSERT_NE(primary_report.message().fetchers(), nullptr);
2126 ASSERT_EQ(primary_report.message().fetchers()->size(), 2);
2127
2128 EXPECT_EQ(primary_report.message().fetchers()->Get(0)->count(), 1);
2129 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->average(),
2130 0.1);
2131 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->min(),
2132 0.1);
2133 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->max(),
2134 0.1);
2135 EXPECT_EQ(primary_report.message()
2136 .fetchers()
2137 ->Get(0)
2138 ->latency()
2139 ->standard_deviation(),
2140 0.0);
2141
2142 EXPECT_EQ(primary_report.message().fetchers()->Get(1)->count(), 10);
2143 } else {
2144 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002145 }
Austin Schuh52d325c2019-06-23 18:59:06 -07002146}
2147
Austin Schuh67420a42019-12-21 21:55:04 -08002148// Tests that a raw watcher and raw fetcher can receive messages from a raw
2149// sender without messing up offsets.
2150TEST_P(AbstractEventLoopTest, RawBasic) {
2151 auto loop1 = Make();
2152 auto loop2 = MakePrimary();
2153 auto loop3 = Make();
2154
Austin Schuha9df9ad2021-06-16 14:49:39 -07002155 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2156 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuh67420a42019-12-21 21:55:04 -08002157
2158 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002159 loop1->MakeRawSender(configuration::GetChannel(
2160 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08002161
2162 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002163 loop3->MakeRawFetcher(configuration::GetChannel(
2164 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08002165
Austin Schuha9df9ad2021-06-16 14:49:39 -07002166 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002167 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2168 RawSender::Error::kOk);
Austin Schuha9df9ad2021-06-16 14:49:39 -07002169 });
Austin Schuh67420a42019-12-21 21:55:04 -08002170
2171 bool happened = false;
2172 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08002173 configuration::GetChannel(loop2->configuration(), "/test",
2174 "aos.TestMessage", "", nullptr),
Austin Schuha9df9ad2021-06-16 14:49:39 -07002175 [this, &kMessage, &fetcher, &happened](const Context &context,
2176 const void *message) {
Austin Schuh67420a42019-12-21 21:55:04 -08002177 happened = true;
Austin Schuha9df9ad2021-06-16 14:49:39 -07002178 EXPECT_EQ(
2179 kMessage.span(),
2180 absl::Span<const uint8_t>(
2181 reinterpret_cast<const uint8_t *>(message), context.size));
2182 EXPECT_EQ(message, context.data);
Austin Schuh67420a42019-12-21 21:55:04 -08002183
2184 ASSERT_TRUE(fetcher->Fetch());
2185
Austin Schuha9df9ad2021-06-16 14:49:39 -07002186 EXPECT_EQ(kMessage.span(),
2187 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
2188 fetcher->context().data),
2189 fetcher->context().size));
Austin Schuh67420a42019-12-21 21:55:04 -08002190
2191 this->Exit();
2192 });
2193
2194 EXPECT_FALSE(happened);
2195 Run();
2196 EXPECT_TRUE(happened);
2197}
2198
Austin Schuhad154822019-12-27 15:45:13 -08002199// Tests that a raw watcher and raw fetcher can receive messages from a raw
Brian Silvermanbf889922021-11-10 12:41:57 -08002200// sender without messing up offsets, using the RawSpan overload.
2201TEST_P(AbstractEventLoopTest, RawBasicSharedSpan) {
2202 auto loop1 = Make();
2203 auto loop2 = MakePrimary();
2204 auto loop3 = Make();
2205
2206 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2207 JsonToFlatbuffer<TestMessage>("{}");
2208
2209 std::unique_ptr<aos::RawSender> sender =
2210 loop1->MakeRawSender(configuration::GetChannel(
2211 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
2212
2213 std::unique_ptr<aos::RawFetcher> fetcher =
2214 loop3->MakeRawFetcher(configuration::GetChannel(
2215 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
2216
2217 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002218 EXPECT_EQ(sender->Send(std::make_shared<absl::Span<const uint8_t>>(
2219 kMessage.span().data(), kMessage.span().size())),
2220 RawSender::Error::kOk);
Brian Silvermanbf889922021-11-10 12:41:57 -08002221 });
2222
2223 bool happened = false;
2224 loop2->MakeRawWatcher(
2225 configuration::GetChannel(loop2->configuration(), "/test",
2226 "aos.TestMessage", "", nullptr),
2227 [this, &kMessage, &fetcher, &happened](const Context &context,
2228 const void *message) {
2229 happened = true;
2230 EXPECT_EQ(
2231 kMessage.span(),
2232 absl::Span<const uint8_t>(
2233 reinterpret_cast<const uint8_t *>(message), context.size));
2234 EXPECT_EQ(message, context.data);
2235
2236 ASSERT_TRUE(fetcher->Fetch());
2237
2238 EXPECT_EQ(kMessage.span(),
2239 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
2240 fetcher->context().data),
2241 fetcher->context().size));
2242
2243 this->Exit();
2244 });
2245
2246 EXPECT_FALSE(happened);
2247 Run();
2248 EXPECT_TRUE(happened);
2249}
2250
2251// Tests that a raw watcher and raw fetcher can receive messages from a raw
Austin Schuhad154822019-12-27 15:45:13 -08002252// sender with remote times filled out.
2253TEST_P(AbstractEventLoopTest, RawRemoteTimes) {
2254 auto loop1 = Make();
2255 auto loop2 = MakePrimary();
2256 auto loop3 = Make();
2257
Austin Schuha9df9ad2021-06-16 14:49:39 -07002258 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2259 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08002260
2261 const aos::monotonic_clock::time_point monotonic_remote_time =
2262 aos::monotonic_clock::time_point(chrono::seconds(1501));
2263 const aos::realtime_clock::time_point realtime_remote_time =
2264 aos::realtime_clock::time_point(chrono::seconds(3132));
Austin Schuhb5c6f972021-03-14 21:53:07 -07002265 const uint32_t remote_queue_index = 0x254971;
Austin Schuha9012be2021-07-21 15:19:11 -07002266 const UUID source_boot_uuid = UUID::Random();
Austin Schuhad154822019-12-27 15:45:13 -08002267
2268 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002269 loop1->MakeRawSender(configuration::GetChannel(
2270 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08002271
2272 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002273 loop3->MakeRawFetcher(configuration::GetChannel(
2274 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08002275
2276 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002277 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size(),
2278 monotonic_remote_time, realtime_remote_time,
2279 remote_queue_index, source_boot_uuid),
2280 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08002281 });
2282
2283 bool happened = false;
2284 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08002285 configuration::GetChannel(loop2->configuration(), "/test",
2286 "aos.TestMessage", "", nullptr),
Austin Schuha9012be2021-07-21 15:19:11 -07002287 [this, monotonic_remote_time, realtime_remote_time, source_boot_uuid,
Austin Schuhb5c6f972021-03-14 21:53:07 -07002288 remote_queue_index, &fetcher,
2289 &happened](const Context &context, const void * /*message*/) {
Austin Schuhad154822019-12-27 15:45:13 -08002290 happened = true;
2291 EXPECT_EQ(monotonic_remote_time, context.monotonic_remote_time);
2292 EXPECT_EQ(realtime_remote_time, context.realtime_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002293 EXPECT_EQ(source_boot_uuid, context.source_boot_uuid);
Austin Schuhb5c6f972021-03-14 21:53:07 -07002294 EXPECT_EQ(remote_queue_index, context.remote_queue_index);
Austin Schuhad154822019-12-27 15:45:13 -08002295
2296 ASSERT_TRUE(fetcher->Fetch());
2297 EXPECT_EQ(monotonic_remote_time,
2298 fetcher->context().monotonic_remote_time);
2299 EXPECT_EQ(realtime_remote_time,
2300 fetcher->context().realtime_remote_time);
2301
2302 this->Exit();
2303 });
2304
2305 EXPECT_FALSE(happened);
2306 Run();
2307 EXPECT_TRUE(happened);
2308}
2309
2310// Tests that a raw sender fills out sent data.
2311TEST_P(AbstractEventLoopTest, RawSenderSentData) {
2312 auto loop1 = MakePrimary();
2313
Austin Schuha9df9ad2021-06-16 14:49:39 -07002314 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2315 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08002316
2317 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002318 loop1->MakeRawSender(configuration::GetChannel(
2319 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08002320
Tyler Chatow67ddb032020-01-12 14:30:04 -08002321 const aos::monotonic_clock::time_point monotonic_now = loop1->monotonic_now();
2322 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08002323
milind1f1dca32021-07-03 13:50:07 -07002324 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2325 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08002326
2327 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
2328 EXPECT_LE(sender->monotonic_sent_time(),
2329 monotonic_now + chrono::milliseconds(100));
2330 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
2331 EXPECT_LE(sender->realtime_sent_time(),
2332 realtime_now + chrono::milliseconds(100));
2333 EXPECT_EQ(sender->sent_queue_index(), 0u);
2334
milind1f1dca32021-07-03 13:50:07 -07002335 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2336 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08002337
2338 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
2339 EXPECT_LE(sender->monotonic_sent_time(),
2340 monotonic_now + chrono::milliseconds(100));
2341 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
2342 EXPECT_LE(sender->realtime_sent_time(),
2343 realtime_now + chrono::milliseconds(100));
2344 EXPECT_EQ(sender->sent_queue_index(), 1u);
2345}
2346
Austin Schuh217a9782019-12-21 23:02:50 -08002347// Tests that not setting up nodes results in no node.
2348TEST_P(AbstractEventLoopTest, NoNode) {
2349 auto loop1 = Make();
2350 auto loop2 = MakePrimary();
2351
2352 EXPECT_EQ(loop1->node(), nullptr);
2353 EXPECT_EQ(loop2->node(), nullptr);
2354}
2355
2356// Tests that setting up nodes results in node being set.
2357TEST_P(AbstractEventLoopTest, Node) {
2358 EnableNodes("me");
2359
2360 auto loop1 = Make();
2361 auto loop2 = MakePrimary();
2362
2363 EXPECT_NE(loop1->node(), nullptr);
2364 EXPECT_NE(loop2->node(), nullptr);
2365}
2366
2367// Tests that watchers work with a node setup.
2368TEST_P(AbstractEventLoopTest, NodeWatcher) {
2369 EnableNodes("me");
2370
2371 auto loop1 = Make();
2372 auto loop2 = Make();
2373 loop1->MakeWatcher("/test", [](const TestMessage &) {});
Tyler Chatow67ddb032020-01-12 14:30:04 -08002374 loop2->MakeRawWatcher(
2375 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
2376 nullptr),
2377 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08002378}
2379
Brian Silverman454bc112020-03-05 14:21:25 -08002380// Tests that no-arg watchers work with a node setup.
2381TEST_P(AbstractEventLoopTest, NodeNoArgWatcher) {
2382 EnableNodes("me");
2383
2384 auto loop1 = Make();
2385 auto loop2 = Make();
2386 loop1->MakeWatcher("/test", [](const TestMessage &) {});
2387 loop2->MakeRawNoArgWatcher(
2388 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
2389 nullptr),
2390 [](const Context &) {});
2391}
2392
Austin Schuh217a9782019-12-21 23:02:50 -08002393// Tests that fetcher work with a node setup.
2394TEST_P(AbstractEventLoopTest, NodeFetcher) {
2395 EnableNodes("me");
2396 auto loop1 = Make();
2397
2398 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
Tyler Chatow67ddb032020-01-12 14:30:04 -08002399 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
2400 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08002401}
2402
2403// Tests that sender work with a node setup.
2404TEST_P(AbstractEventLoopTest, NodeSender) {
2405 EnableNodes("me");
2406 auto loop1 = Make();
2407
2408 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
2409}
2410
Austin Schuhcc6070c2020-10-10 20:25:56 -07002411// Tests that a non-realtime event loop timer is marked non-realtime.
2412TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopTimer) {
2413 auto loop1 = MakePrimary();
2414
2415 // Add a timer to actually quit.
2416 auto test_timer = loop1->AddTimer([this]() {
2417 CheckNotRealtime();
2418 this->Exit();
2419 });
2420
2421 loop1->OnRun([&test_timer, &loop1]() {
2422 CheckNotRealtime();
2423 test_timer->Setup(loop1->monotonic_now(), ::std::chrono::milliseconds(100));
2424 });
2425
2426 Run();
2427}
2428
2429// Tests that a realtime event loop timer is marked realtime.
Austin Schuh9b1d6282022-06-10 17:03:21 -07002430TEST_P(AbstractEventLoopTest, RealtimeSend) {
2431 auto loop1 = MakePrimary();
2432
2433 loop1->SetRuntimeRealtimePriority(1);
2434
2435 auto sender = loop1->MakeSender<TestMessage>("/test2");
2436
2437 loop1->OnRun([&]() {
2438 CheckRealtime();
2439
2440 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2441 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2442 builder.add_value(200);
2443 msg.CheckOk(msg.Send(builder.Finish()));
2444
2445 this->Exit();
2446 });
2447
2448 Run();
2449}
2450
2451// Tests that a realtime event loop timer is marked realtime.
Austin Schuhcc6070c2020-10-10 20:25:56 -07002452TEST_P(AbstractEventLoopTest, RealtimeEventLoopTimer) {
2453 auto loop1 = MakePrimary();
2454
2455 loop1->SetRuntimeRealtimePriority(1);
2456
2457 // Add a timer to actually quit.
2458 auto test_timer = loop1->AddTimer([this]() {
2459 CheckRealtime();
2460 this->Exit();
2461 });
2462
2463 loop1->OnRun([&test_timer, &loop1]() {
2464 CheckRealtime();
2465 test_timer->Setup(loop1->monotonic_now(), ::std::chrono::milliseconds(100));
2466 });
2467
2468 Run();
2469}
2470
2471// Tests that a non-realtime event loop phased loop is marked non-realtime.
2472TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopPhasedLoop) {
2473 auto loop1 = MakePrimary();
2474
2475 // Add a timer to actually quit.
2476 loop1->AddPhasedLoop(
2477 [this](int) {
2478 CheckNotRealtime();
2479 this->Exit();
2480 },
2481 chrono::seconds(1), chrono::seconds(0));
2482
2483 Run();
2484}
2485
2486// Tests that a realtime event loop phased loop is marked realtime.
2487TEST_P(AbstractEventLoopTest, RealtimeEventLoopPhasedLoop) {
2488 auto loop1 = MakePrimary();
2489
2490 loop1->SetRuntimeRealtimePriority(1);
2491
2492 // Add a timer to actually quit.
2493 loop1->AddPhasedLoop(
2494 [this](int) {
2495 CheckRealtime();
2496 this->Exit();
2497 },
2498 chrono::seconds(1), chrono::seconds(0));
2499
2500 Run();
2501}
2502
2503// Tests that a non-realtime event loop watcher is marked non-realtime.
2504TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopWatcher) {
2505 auto loop1 = MakePrimary();
2506 auto loop2 = Make();
2507
2508 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
2509
2510 loop1->OnRun([&]() {
2511 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2512 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07002513 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07002514 });
2515
2516 loop1->MakeWatcher("/test", [&](const TestMessage &) {
2517 CheckNotRealtime();
2518 this->Exit();
2519 });
2520
2521 Run();
2522}
2523
2524// Tests that a realtime event loop watcher is marked realtime.
2525TEST_P(AbstractEventLoopTest, RealtimeEventLoopWatcher) {
2526 auto loop1 = MakePrimary();
2527 auto loop2 = Make();
2528
2529 loop1->SetRuntimeRealtimePriority(1);
2530
2531 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
2532
2533 loop1->OnRun([&]() {
2534 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2535 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07002536 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07002537 });
2538
2539 loop1->MakeWatcher("/test", [&](const TestMessage &) {
2540 CheckRealtime();
2541 this->Exit();
2542 });
2543
2544 Run();
2545}
2546
Austin Schuha9012be2021-07-21 15:19:11 -07002547// Tests that event loop's context's monotonic time is set to a value on OnRun.
2548TEST_P(AbstractEventLoopTest, SetContextOnRun) {
2549 auto loop = MakePrimary();
2550
2551 // We want to check that monotonic event time is before monotonic now
2552 // called inside of callback, but after time point obtained callback.
2553 aos::monotonic_clock::time_point monotonic_event_time_on_run;
2554
2555 loop->OnRun([&]() {
2556 monotonic_event_time_on_run = loop->context().monotonic_event_time;
2557 EXPECT_LE(monotonic_event_time_on_run, loop->monotonic_now());
2558 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
2559 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
2560 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
2561 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
2562 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
2563 EXPECT_EQ(loop->context().size, 0u);
2564 EXPECT_EQ(loop->context().data, nullptr);
2565 EXPECT_EQ(loop->context().buffer_index, -1);
2566 });
2567
2568 EndEventLoop(loop.get(), ::std::chrono::milliseconds(200));
2569
2570 const aos::monotonic_clock::time_point before_run_time =
2571 loop->monotonic_now();
2572 Run();
2573 EXPECT_GE(monotonic_event_time_on_run, before_run_time);
2574}
2575
Austin Schuh217a9782019-12-21 23:02:50 -08002576// Tests that watchers fail when created on the wrong node.
2577TEST_P(AbstractEventLoopDeathTest, NodeWatcher) {
2578 EnableNodes("them");
2579
2580 auto loop1 = Make();
2581 auto loop2 = Make();
2582 EXPECT_DEATH({ loop1->MakeWatcher("/test", [](const TestMessage &) {}); },
2583 "node");
2584 EXPECT_DEATH(
2585 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08002586 loop2->MakeRawWatcher(
2587 configuration::GetChannel(configuration(), "/test",
2588 "aos.TestMessage", "", nullptr),
2589 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08002590 },
2591 "node");
Brian Silverman454bc112020-03-05 14:21:25 -08002592 EXPECT_DEATH({ loop1->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
2593 "node");
2594 EXPECT_DEATH(
2595 {
2596 loop2->MakeRawNoArgWatcher(
2597 configuration::GetChannel(configuration(), "/test",
2598 "aos.TestMessage", "", nullptr),
2599 [](const Context &) {});
2600 },
2601 "node");
Austin Schuh217a9782019-12-21 23:02:50 -08002602}
2603
2604// Tests that fetchers fail when created on the wrong node.
2605TEST_P(AbstractEventLoopDeathTest, NodeFetcher) {
2606 EnableNodes("them");
2607 auto loop1 = Make();
2608
2609 EXPECT_DEATH({ auto fetcher = loop1->MakeFetcher<TestMessage>("/test"); },
2610 "node");
2611 EXPECT_DEATH(
2612 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08002613 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
2614 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08002615 },
2616 "node");
2617}
2618
2619// Tests that senders fail when created on the wrong node.
2620TEST_P(AbstractEventLoopDeathTest, NodeSender) {
2621 EnableNodes("them");
2622 auto loop1 = Make();
2623
2624 EXPECT_DEATH(
2625 {
2626 aos::Sender<TestMessage> sender =
2627 loop1->MakeSender<TestMessage>("/test");
2628 },
2629 "node");
2630
2631 // Note: Creating raw senders is always supported. Right now, this lets us
2632 // use them to create message_gateway.
2633}
2634
Brian Silverman341b57e2020-06-23 16:23:18 -07002635// Tests creating multiple Builders from a single Sender at the same time.
2636TEST_P(AbstractEventLoopDeathTest, MultipleBuilders) {
2637 auto loop1 = Make();
2638 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
2639
2640 { auto builder = sender.MakeBuilder(); }
2641 {
2642 auto builder = sender.MakeBuilder();
2643 builder.MakeBuilder<TestMessage>().Finish();
2644 }
2645 {
2646 // Creating this after the first one was destroyed should be fine.
2647 auto builder = sender.MakeBuilder();
2648 builder.MakeBuilder<TestMessage>().Finish();
2649 // But not a second one.
2650 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
2651 "May not overwrite in-use allocator");
2652 }
2653
2654 FlatbufferDetachedBuffer<TestMessage> detached =
2655 flatbuffers::DetachedBuffer();
2656 {
2657 auto builder = sender.MakeBuilder();
2658 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
2659 }
2660 {
2661 // This is the second one, after the detached one, so it should fail.
2662 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
2663 "May not overwrite in-use allocator");
2664 }
2665
2666 // Clear the detached one, and then we should be able to create another.
2667 detached = flatbuffers::DetachedBuffer();
2668 {
2669 auto builder = sender.MakeBuilder();
2670 builder.MakeBuilder<TestMessage>().Finish();
2671 }
2672
2673 // And then detach another one.
2674 {
2675 auto builder = sender.MakeBuilder();
2676 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
2677 }
2678}
2679
2680// Tests sending a buffer detached from a different builder.
2681TEST_P(AbstractEventLoopDeathTest, WrongDetachedBuffer) {
2682 auto loop1 = Make();
2683 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
2684 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
2685
2686 auto builder = sender1.MakeBuilder();
2687 FlatbufferDetachedBuffer<TestMessage> detached =
2688 builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
milind1f1dca32021-07-03 13:50:07 -07002689 EXPECT_DEATH(sender2.CheckOk(sender2.SendDetached(std::move(detached))),
Brian Silverman341b57e2020-06-23 16:23:18 -07002690 "May only send the buffer detached from this Sender");
2691}
2692
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07002693int TestChannelFrequency(EventLoop *event_loop) {
2694 return event_loop->GetChannel<TestMessage>("/test")->frequency();
2695}
2696
2697int TestChannelQueueSize(EventLoop *event_loop) {
2698 const int frequency = TestChannelFrequency(event_loop);
2699 const auto channel_storage_duration = std::chrono::nanoseconds(
2700 event_loop->configuration()->channel_storage_duration());
2701 const int queue_size =
2702 frequency * std::chrono::duration_cast<std::chrono::duration<double>>(
2703 channel_storage_duration)
2704 .count();
2705
2706 return queue_size;
2707}
2708
2709RawSender::Error SendTestMessage(aos::Sender<TestMessage> &sender) {
2710 aos::Sender<TestMessage>::Builder builder = sender.MakeBuilder();
2711 TestMessage::Builder test_message_builder =
2712 builder.MakeBuilder<TestMessage>();
2713 test_message_builder.add_value(0);
2714 return builder.Send(test_message_builder.Finish());
2715}
2716
2717// Test that sending messages too fast returns
2718// RawSender::Error::kMessagesSentTooFast.
2719TEST_P(AbstractEventLoopTest, SendingMessagesTooFast) {
2720 auto event_loop = MakePrimary();
2721
2722 auto sender = event_loop->MakeSender<TestMessage>("/test");
2723
2724 // Send one message in the beginning, then wait until the
2725 // channel_storage_duration is almost done and start sending messages rapidly,
2726 // having some come in the next chanel_storage_duration. The queue_size is
2727 // 1600, so the 1601st message will be the last valid one (the initial message
2728 // having being sent more than a channel_storage_duration ago), and trying to
2729 // send the 1602nd message should return
2730 // RawSender::Error::kMessagesSentTooFast.
2731 EXPECT_EQ(SendTestMessage(sender), RawSender::Error::kOk);
2732 int msgs_sent = 1;
2733 const int queue_size = TestChannelQueueSize(event_loop.get());
2734
2735 const auto timer = event_loop->AddTimer([&]() {
2736 const bool done = (msgs_sent == queue_size + 1);
2737 ASSERT_EQ(
2738 SendTestMessage(sender),
2739 done ? RawSender::Error::kMessagesSentTooFast : RawSender::Error::kOk);
2740 msgs_sent++;
2741 if (done) {
2742 Exit();
2743 }
2744 });
2745
2746 const auto kRepeatOffset = std::chrono::milliseconds(1);
2747 const auto base_offset =
2748 std::chrono::nanoseconds(
2749 event_loop->configuration()->channel_storage_duration()) -
2750 (kRepeatOffset * (queue_size / 2));
2751 event_loop->OnRun([&event_loop, &timer, &base_offset, &kRepeatOffset]() {
2752 timer->Setup(event_loop->monotonic_now() + base_offset, kRepeatOffset);
2753 });
2754
2755 Run();
2756}
2757
2758// Tests that we are able to send messages successfully after sending messages
2759// too fast and waiting while continuously attempting to send messages.
2760// Also tests that SendFailureCounter is working correctly in this
2761// situation
2762TEST_P(AbstractEventLoopTest, SendingAfterSendingTooFast) {
2763 auto event_loop = MakePrimary();
2764
2765 auto sender = event_loop->MakeSender<TestMessage>("/test");
2766
2767 // We are sending messages at 1 kHz, so we will be sending too fast after
2768 // queue_size (1600) ms. After this, keep sending messages, and exactly a
2769 // channel storage duration (2s) after we send the first message we should
2770 // be able to successfully send a message.
2771
2772 const monotonic_clock::duration kInterval = std::chrono::milliseconds(1);
2773 const monotonic_clock::duration channel_storage_duration =
2774 std::chrono::nanoseconds(
2775 event_loop->configuration()->channel_storage_duration());
2776 const int queue_size = TestChannelQueueSize(event_loop.get());
2777
2778 int msgs_sent = 0;
2779 SendFailureCounter counter;
2780 auto start = monotonic_clock::min_time;
2781
2782 event_loop->AddPhasedLoop(
2783 [&](int) {
2784 const auto actual_err = SendTestMessage(sender);
2785 const bool done_waiting = (start != monotonic_clock::min_time &&
2786 sender.monotonic_sent_time() >=
2787 (start + channel_storage_duration));
2788 const auto expected_err =
2789 (msgs_sent < queue_size || done_waiting
2790 ? RawSender::Error::kOk
2791 : RawSender::Error::kMessagesSentTooFast);
2792
2793 if (start == monotonic_clock::min_time) {
2794 start = sender.monotonic_sent_time();
2795 }
2796
2797 ASSERT_EQ(actual_err, expected_err);
2798 counter.Count(actual_err);
2799 msgs_sent++;
2800
2801 EXPECT_EQ(counter.failures(),
2802 msgs_sent <= queue_size
2803 ? 0
2804 : (msgs_sent - queue_size) -
2805 (actual_err == RawSender::Error::kOk ? 1 : 0));
2806 EXPECT_EQ(counter.just_failed(), actual_err != RawSender::Error::kOk);
2807
2808 if (done_waiting) {
2809 Exit();
2810 }
2811 },
2812 kInterval);
2813 Run();
2814}
2815
2816// Tests that RawSender::Error::kMessagesSentTooFast is returned
2817// when messages are sent too fast from senders in different loops
2818TEST_P(AbstractEventLoopTest, SendingTooFastWithMultipleLoops) {
2819 auto loop1 = MakePrimary();
2820 auto loop2 = Make();
2821
2822 auto sender1 = loop1->MakeSender<TestMessage>("/test");
2823 auto sender2 = loop2->MakeSender<TestMessage>("/test");
2824
2825 // Send queue_size messages split between the senders.
2826 const int queue_size = TestChannelQueueSize(loop1.get());
2827 for (int i = 0; i < queue_size / 2; i++) {
2828 ASSERT_EQ(SendTestMessage(sender1), RawSender::Error::kOk);
2829 ASSERT_EQ(SendTestMessage(sender2), RawSender::Error::kOk);
2830 }
2831
2832 // Since queue_size messages have been sent, this should return an error
2833 EXPECT_EQ(SendTestMessage(sender2), RawSender::Error::kMessagesSentTooFast);
2834}
2835
Parker Schuhe4a70d62017-12-27 20:10:20 -08002836} // namespace testing
2837} // namespace aos