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