blob: e8ad5af04e22fb02a4edd6bcc322790e6c8f1f66 [file] [log] [blame]
Alex Perrycb7da4b2019-08-28 19:35:56 -07001#include "aos/events/event_loop_param_test.h"
Parker Schuhe4a70d62017-12-27 20:10:20 -08002
Austin Schuh52d325c2019-06-23 18:59:06 -07003#include <chrono>
Brian Silverman4f4e0612020-08-12 19:54:41 -07004#include <unordered_map>
5#include <unordered_set>
Austin Schuh52d325c2019-06-23 18:59:06 -07006
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07007#include "aos/events/test_message_generated.h"
Austin Schuh54cf95f2019-11-29 13:14:18 -08008#include "aos/flatbuffer_merge.h"
Austin Schuhad9e5eb2021-11-19 20:33:55 -08009#include "aos/logging/log_message_generated.h"
10#include "aos/logging/logging.h"
Austin Schuhcc6070c2020-10-10 20:25:56 -070011#include "aos/realtime.h"
Austin Schuh54cf95f2019-11-29 13:14:18 -080012#include "glog/logging.h"
Tyler Chatow67ddb032020-01-12 14:30:04 -080013#include "gmock/gmock.h"
14#include "gtest/gtest.h"
Austin Schuh9fe68f72019-08-10 19:32:03 -070015
Parker Schuhe4a70d62017-12-27 20:10:20 -080016namespace aos {
17namespace testing {
Austin Schuh52d325c2019-06-23 18:59:06 -070018namespace {
19namespace chrono = ::std::chrono;
20} // namespace
Parker Schuhe4a70d62017-12-27 20:10:20 -080021
Brian Silverman4f4e0612020-08-12 19:54:41 -070022::std::unique_ptr<EventLoop> AbstractEventLoopTest::Make(
23 std::string_view name) {
24 std::string name_copy(name);
25 if (name == "") {
26 name_copy = "loop";
27 name_copy += std::to_string(event_loop_count_);
28 }
29 ++event_loop_count_;
Austin Schuh6bae8252021-02-07 22:01:49 -080030 auto result = factory_->Make(name_copy);
31 if (do_timing_reports() == DoTimingReports::kNo) {
32 result->SkipTimingReport();
33 }
34 return result;
Brian Silverman4f4e0612020-08-12 19:54:41 -070035}
36
37void AbstractEventLoopTest::VerifyBuffers(
38 int number_buffers,
39 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>> fetchers,
40 std::vector<std::reference_wrapper<const Sender<TestMessage>>> senders) {
41 // The buffers which are in a sender.
42 std::unordered_set<int> in_sender;
43 for (const Sender<TestMessage> &sender : senders) {
44 const int this_buffer = sender.buffer_index();
45 CHECK_GE(this_buffer, 0);
46 CHECK_LT(this_buffer, number_buffers);
47 CHECK(in_sender.insert(this_buffer).second) << ": " << this_buffer;
48 }
49
50 if (read_method() != ReadMethod::PIN) {
51 // If we're not using PIN, we can't really verify anything about what
52 // buffers the fetchers have.
53 return;
54 }
55
56 // Mapping from TestMessage::value to buffer index.
57 std::unordered_map<int, int> fetcher_values;
58 for (const Fetcher<TestMessage> &fetcher : fetchers) {
59 if (!fetcher.get()) {
60 continue;
61 }
62 const int this_buffer = fetcher.context().buffer_index;
63 CHECK_GE(this_buffer, 0);
64 CHECK_LT(this_buffer, number_buffers);
65 CHECK(in_sender.count(this_buffer) == 0) << ": " << this_buffer;
66 const auto insert_result = fetcher_values.insert(
67 std::make_pair(fetcher.get()->value(), this_buffer));
68 if (!insert_result.second) {
69 CHECK_EQ(this_buffer, insert_result.first->second);
70 }
71 }
72}
73
Austin Schuh6b6dfa52019-06-12 20:16:20 -070074// Tests that watcher can receive messages from a sender.
Parker Schuhe4a70d62017-12-27 20:10:20 -080075// Also tests that OnRun() works.
76TEST_P(AbstractEventLoopTest, Basic) {
77 auto loop1 = Make();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070078 auto loop2 = MakePrimary();
79
Alex Perrycb7da4b2019-08-28 19:35:56 -070080 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
Austin Schuh6b6dfa52019-06-12 20:16:20 -070081
82 bool happened = false;
83
84 loop2->OnRun([&]() {
85 happened = true;
86
Alex Perrycb7da4b2019-08-28 19:35:56 -070087 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
88 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
89 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -070090 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -070091 });
92
93 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070094 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -070095 this->Exit();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070096 });
97
98 EXPECT_FALSE(happened);
99 Run();
100 EXPECT_TRUE(happened);
101}
102
Brian Silverman341b57e2020-06-23 16:23:18 -0700103// Tests that watcher can receive messages from a sender, sent via SendDetached.
104TEST_P(AbstractEventLoopTest, BasicSendDetached) {
105 auto loop1 = Make();
106 auto loop2 = MakePrimary();
107
108 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
109
110 FlatbufferDetachedBuffer<TestMessage> detached =
111 flatbuffers::DetachedBuffer();
112 {
113 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
114 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
115 builder.add_value(100);
116 detached = msg.Detach(builder.Finish());
117 }
118 detached = flatbuffers::DetachedBuffer();
119 {
120 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
121 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
122 builder.add_value(200);
123 detached = msg.Detach(builder.Finish());
124 }
milind1f1dca32021-07-03 13:50:07 -0700125 sender.CheckOk(sender.SendDetached(std::move(detached)));
Brian Silverman341b57e2020-06-23 16:23:18 -0700126
127 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
128 ASSERT_TRUE(fetcher.Fetch());
129 EXPECT_EQ(fetcher->value(), 200);
130}
131
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800132// Verifies that a no-arg watcher will not have a data pointer.
133TEST_P(AbstractEventLoopTest, NoArgNoData) {
134 auto loop1 = Make();
135 auto loop2 = MakePrimary();
136
137 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
138
139 bool happened = false;
140
141 loop2->OnRun([&]() {
142 happened = true;
143
144 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
145 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -0700146 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800147 });
148
149 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
150 EXPECT_GT(loop2->context().size, 0u);
151 EXPECT_EQ(nullptr, loop2->context().data);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700152 EXPECT_EQ(-1, loop2->context().buffer_index);
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800153 this->Exit();
154 });
155
156 EXPECT_FALSE(happened);
157 Run();
158 EXPECT_TRUE(happened);
159}
160
Brian Silverman454bc112020-03-05 14:21:25 -0800161// Tests that no-arg watcher can receive messages from a sender.
162// Also tests that OnRun() works.
163TEST_P(AbstractEventLoopTest, BasicNoArg) {
164 auto loop1 = Make();
165 auto loop2 = MakePrimary();
166
167 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
168
169 bool happened = false;
170
171 loop2->OnRun([&]() {
172 happened = true;
173
174 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
175 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
176 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700177 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -0800178 });
179
180 aos::Fetcher<TestMessage> fetcher = loop2->MakeFetcher<TestMessage>("/test");
181 loop2->MakeNoArgWatcher<TestMessage>("/test", [&]() {
182 ASSERT_TRUE(fetcher.Fetch());
183 EXPECT_EQ(fetcher->value(), 200);
184 this->Exit();
185 });
186
187 EXPECT_FALSE(happened);
188 Run();
189 EXPECT_TRUE(happened);
190}
191
192// Tests that a watcher can be created with an std::function.
193TEST_P(AbstractEventLoopTest, BasicFunction) {
194 auto loop1 = Make();
195 auto loop2 = MakePrimary();
196
197 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
198
199 bool happened = false;
200
201 loop2->OnRun([&]() {
202 happened = true;
203
204 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
205 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
206 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700207 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -0800208 });
209
210 loop2->MakeWatcher("/test", std::function<void(const TestMessage &)>(
211 [&](const TestMessage &message) {
212 EXPECT_EQ(message.value(), 200);
213 this->Exit();
214 }));
215
216 EXPECT_FALSE(happened);
217 Run();
218 EXPECT_TRUE(happened);
219}
220
Brian Silverman0fc69932020-01-24 21:54:02 -0800221// Tests that watcher can receive messages from two senders.
222// Also tests that OnRun() works.
223TEST_P(AbstractEventLoopTest, BasicTwoSenders) {
224 auto loop1 = Make();
225 auto loop2 = MakePrimary();
226
227 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
228 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
229
230 bool happened = false;
231
232 loop2->OnRun([&]() {
233 happened = true;
234
235 {
236 aos::Sender<TestMessage>::Builder msg = sender1.MakeBuilder();
237 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
238 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700239 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman0fc69932020-01-24 21:54:02 -0800240 }
241 {
242 aos::Sender<TestMessage>::Builder msg = sender2.MakeBuilder();
243 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
244 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700245 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman0fc69932020-01-24 21:54:02 -0800246 }
247 });
248
249 int messages_received = 0;
250 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
251 EXPECT_EQ(message.value(), 200);
252 this->Exit();
253 ++messages_received;
254 });
255
256 EXPECT_FALSE(happened);
257 Run();
258 EXPECT_TRUE(happened);
259 EXPECT_EQ(messages_received, 2);
260}
261
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700262// Tests that a fetcher can fetch from a sender.
263// Also tests that OnRun() works.
264TEST_P(AbstractEventLoopTest, FetchWithoutRun) {
265 auto loop1 = Make();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800266 auto loop2 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -0700267 auto loop3 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800268
269 auto sender = loop1->MakeSender<TestMessage>("/test");
270
271 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
272
Austin Schuhbbce72d2019-05-26 15:11:46 -0700273 EXPECT_FALSE(fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -0800274 EXPECT_EQ(fetcher.get(), nullptr);
275
Austin Schuhad154822019-12-27 15:45:13 -0800276 EXPECT_EQ(fetcher.context().monotonic_event_time, monotonic_clock::min_time);
277 EXPECT_EQ(fetcher.context().monotonic_remote_time, monotonic_clock::min_time);
278 EXPECT_EQ(fetcher.context().realtime_event_time, realtime_clock::min_time);
279 EXPECT_EQ(fetcher.context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -0700280 EXPECT_EQ(fetcher.context().source_boot_uuid, UUID::Zero());
Austin Schuh39788ff2019-12-01 18:22:57 -0800281 EXPECT_EQ(fetcher.context().queue_index, 0xffffffffu);
282 EXPECT_EQ(fetcher.context().size, 0u);
283 EXPECT_EQ(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700284 EXPECT_EQ(fetcher.context().buffer_index, -1);
Austin Schuhbbce72d2019-05-26 15:11:46 -0700285
Alex Perrycb7da4b2019-08-28 19:35:56 -0700286 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
287 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
288 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700289 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700290
291 EXPECT_TRUE(fetcher.Fetch());
292 ASSERT_FALSE(fetcher.get() == nullptr);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700293 EXPECT_EQ(fetcher.get()->value(), 200);
Austin Schuh39788ff2019-12-01 18:22:57 -0800294
295 const chrono::milliseconds kEpsilon(100);
296
Austin Schuhad154822019-12-27 15:45:13 -0800297 const aos::monotonic_clock::time_point monotonic_now = loop2->monotonic_now();
298 const aos::realtime_clock::time_point realtime_now = loop2->realtime_now();
299 EXPECT_EQ(fetcher.context().monotonic_event_time,
300 fetcher.context().monotonic_remote_time);
301 EXPECT_EQ(fetcher.context().realtime_event_time,
302 fetcher.context().realtime_remote_time);
303
304 EXPECT_GE(fetcher.context().monotonic_event_time, monotonic_now - kEpsilon);
305 EXPECT_LE(fetcher.context().monotonic_event_time, monotonic_now + kEpsilon);
306 EXPECT_GE(fetcher.context().realtime_event_time, realtime_now - kEpsilon);
307 EXPECT_LE(fetcher.context().realtime_event_time, realtime_now + kEpsilon);
Austin Schuha9012be2021-07-21 15:19:11 -0700308 EXPECT_EQ(fetcher.context().source_boot_uuid, loop2->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -0800309 EXPECT_EQ(fetcher.context().queue_index, 0x0u);
310 EXPECT_EQ(fetcher.context().size, 20u);
311 EXPECT_NE(fetcher.context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700312 if (read_method() == ReadMethod::PIN) {
313 EXPECT_GE(fetcher.context().buffer_index, 0);
314 EXPECT_LT(fetcher.context().buffer_index,
315 loop2->NumberBuffers(fetcher.channel()));
316 } else {
317 EXPECT_EQ(fetcher.context().buffer_index, -1);
318 }
Parker Schuhe4a70d62017-12-27 20:10:20 -0800319}
320
Austin Schuh3578a2e2019-05-25 18:17:59 -0700321// Tests that watcher will receive all messages sent if they are sent after
322// initialization and before running.
323TEST_P(AbstractEventLoopTest, DoubleSendAtStartup) {
324 auto loop1 = Make();
325 auto loop2 = MakePrimary();
326
327 auto sender = loop1->MakeSender<TestMessage>("/test");
328
329 ::std::vector<int> values;
330
331 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700332 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700333 if (values.size() == 2) {
Austin Schuh9fe68f72019-08-10 19:32:03 -0700334 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -0700335 }
336 });
337
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700338 // Before Run, should be ignored.
Austin Schuh3578a2e2019-05-25 18:17:59 -0700339 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700340 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
341 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
342 builder.add_value(199);
milind1f1dca32021-07-03 13:50:07 -0700343 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700344 }
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700345
346 loop2->OnRun([&]() {
347 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700348 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
349 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
350 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700351 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700352 }
353 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700354 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
355 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
356 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700357 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700358 }
359 });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700360
361 Run();
362
363 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
364}
365
366// Tests that watcher will not receive messages sent before the watcher is
367// created.
368TEST_P(AbstractEventLoopTest, DoubleSendAfterStartup) {
369 auto loop1 = Make();
370 auto loop2 = MakePrimary();
371
372 auto sender = loop1->MakeSender<TestMessage>("/test");
373
374 ::std::vector<int> values;
375
376 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700377 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
378 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
379 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700380 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700381 }
382 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700383 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
384 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
385 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700386 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700387 }
388
389 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700390 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700391 });
392
393 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700394 auto test_timer = loop2->AddTimer([this]() { this->Exit(); });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700395 loop2->OnRun([&test_timer, &loop2]() {
396 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
397 });
398
399 Run();
400 EXPECT_EQ(0, values.size());
401}
402
Austin Schuhbbce72d2019-05-26 15:11:46 -0700403// Tests that FetchNext gets all the messages sent after it is constructed.
404TEST_P(AbstractEventLoopTest, FetchNext) {
405 auto loop1 = Make();
406 auto loop2 = MakePrimary();
407
408 auto sender = loop1->MakeSender<TestMessage>("/test");
409 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
410
411 ::std::vector<int> values;
412
413 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700414 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
415 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
416 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700417 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700418 }
419 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700420 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
421 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
422 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700423 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700424 }
425
426 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700427 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700428 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700429 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700430 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700431 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700432 });
433
434 loop2->OnRun([&test_timer, &loop2]() {
435 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
436 });
437
438 Run();
439 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
440}
441
442// Tests that FetchNext gets no messages sent before it is constructed.
443TEST_P(AbstractEventLoopTest, FetchNextAfterSend) {
444 auto loop1 = Make();
445 auto loop2 = MakePrimary();
446
447 auto sender = loop1->MakeSender<TestMessage>("/test");
448
449 ::std::vector<int> values;
450
451 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700452 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
453 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
454 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700455 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700456 }
457 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700458 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
459 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
460 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700461 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700462 }
463
464 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
465
466 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700467 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700468 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700469 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700470 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700471 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700472 });
473
474 loop2->OnRun([&test_timer, &loop2]() {
475 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
476 });
477
478 Run();
479 EXPECT_THAT(0, values.size());
480}
481
482// Tests that Fetch returns the last message created before the loop was
483// started.
484TEST_P(AbstractEventLoopTest, FetchDataFromBeforeCreation) {
485 auto loop1 = Make();
486 auto loop2 = MakePrimary();
487
488 auto sender = loop1->MakeSender<TestMessage>("/test");
489
490 ::std::vector<int> values;
491
492 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700493 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
494 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
495 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700496 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700497 }
498 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700499 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
500 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
501 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700502 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700503 }
504
505 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
506
507 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700508 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700509 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700510 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700511 }
512 // Do it again to make sure we don't double fetch.
513 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700514 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700515 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700516 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700517 });
518
519 loop2->OnRun([&test_timer, &loop2]() {
520 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
521 });
522
523 Run();
524 EXPECT_THAT(values, ::testing::ElementsAreArray({201}));
525}
526
527// Tests that Fetch and FetchNext interleave as expected.
528TEST_P(AbstractEventLoopTest, FetchAndFetchNextTogether) {
529 auto loop1 = Make();
530 auto loop2 = MakePrimary();
531
532 auto sender = loop1->MakeSender<TestMessage>("/test");
533
534 ::std::vector<int> values;
535
536 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700537 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
538 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
539 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700540 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700541 }
542 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700543 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
544 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
545 builder.add_value(201);
milind1f1dca32021-07-03 13:50:07 -0700546 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700547 }
548
549 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
550
551 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700552 auto test_timer = loop2->AddTimer([&fetcher, &values, &sender, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700553 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700554 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700555 }
556
557 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700558 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
559 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
560 builder.add_value(202);
milind1f1dca32021-07-03 13:50:07 -0700561 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700562 }
563 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700564 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
565 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
566 builder.add_value(203);
milind1f1dca32021-07-03 13:50:07 -0700567 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700568 }
569 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700570 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
571 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
572 builder.add_value(204);
milind1f1dca32021-07-03 13:50:07 -0700573 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700574 }
575
576 if (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700577 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700578 }
579
580 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700581 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700582 }
583
Austin Schuh9fe68f72019-08-10 19:32:03 -0700584 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700585 });
586
587 loop2->OnRun([&test_timer, &loop2]() {
588 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
589 });
590
591 Run();
592 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
593}
594
Austin Schuh3115a202019-05-27 21:02:14 -0700595// Tests that FetchNext behaves correctly when we get two messages in the queue
596// but don't consume the first until after the second has been sent.
597TEST_P(AbstractEventLoopTest, FetchNextTest) {
Austin Schuh3115a202019-05-27 21:02:14 -0700598 auto send_loop = Make();
599 auto fetch_loop = Make();
600 auto sender = send_loop->MakeSender<TestMessage>("/test");
601 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
602
603 {
Tyler Chatow67ddb032020-01-12 14:30:04 -0800604 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
605 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
606 builder.add_value(100);
milind1f1dca32021-07-03 13:50:07 -0700607 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700608 }
609
610 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700611 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
612 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
613 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700614 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700615 }
616
617 ASSERT_TRUE(fetcher.FetchNext());
618 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700619 EXPECT_EQ(100, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700620
621 ASSERT_TRUE(fetcher.FetchNext());
622 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700623 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700624
625 // When we run off the end of the queue, expect to still have the old message:
626 ASSERT_FALSE(fetcher.FetchNext());
627 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700628 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700629}
630
Brian Silverman77162972020-08-12 19:52:40 -0700631// Verify that a fetcher still holds its data, even after falling behind.
632TEST_P(AbstractEventLoopTest, FetcherBehindData) {
633 auto send_loop = Make();
634 auto fetch_loop = Make();
635 auto sender = send_loop->MakeSender<TestMessage>("/test");
636 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
637 {
638 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
639 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
640 builder.add_value(1);
milind1f1dca32021-07-03 13:50:07 -0700641 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -0700642 }
643 ASSERT_TRUE(fetcher.Fetch());
644 EXPECT_EQ(1, fetcher.get()->value());
645 for (int i = 0; i < 300; ++i) {
646 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
647 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
648 builder.add_value(i + 2);
milind1f1dca32021-07-03 13:50:07 -0700649 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -0700650 }
651 EXPECT_EQ(1, fetcher.get()->value());
652}
653
654// Try a bunch of orderings of operations with fetchers and senders. Verify that
655// all the fetchers have the correct data at each step.
656TEST_P(AbstractEventLoopTest, FetcherPermutations) {
657 for (int max_save = 0; max_save < 5; ++max_save) {
658 SCOPED_TRACE("max_save=" + std::to_string(max_save));
659
660 auto send_loop = Make();
661 auto fetch_loop = Make();
662 auto sender = send_loop->MakeSender<TestMessage>("/test");
663 const auto send_message = [&sender](int i) {
664 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
665 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
666 builder.add_value(i);
milind1f1dca32021-07-03 13:50:07 -0700667 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman77162972020-08-12 19:52:40 -0700668 };
669 std::vector<Fetcher<TestMessage>> fetchers;
670 for (int i = 0; i < 10; ++i) {
671 fetchers.emplace_back(fetch_loop->MakeFetcher<TestMessage>("/test"));
672 }
673 send_message(1);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700674 const auto verify_buffers = [&]() {
675 std::vector<std::reference_wrapper<const Fetcher<TestMessage>>>
676 fetchers_copy;
677 for (const auto &fetcher : fetchers) {
678 fetchers_copy.emplace_back(fetcher);
679 }
680 std::vector<std::reference_wrapper<const Sender<TestMessage>>>
681 senders_copy;
682 senders_copy.emplace_back(sender);
683 VerifyBuffers(send_loop->NumberBuffers(sender.channel()), fetchers_copy,
684 senders_copy);
685 };
Brian Silverman77162972020-08-12 19:52:40 -0700686 for (auto &fetcher : fetchers) {
687 ASSERT_TRUE(fetcher.Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -0700688 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700689 EXPECT_EQ(1, fetcher.get()->value());
690 }
691
692 for (int save = 1; save <= max_save; ++save) {
693 SCOPED_TRACE("save=" + std::to_string(save));
694 send_message(100 + save);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700695 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700696 for (size_t i = 0; i < fetchers.size() - save; ++i) {
697 SCOPED_TRACE("fetcher=" + std::to_string(i));
698 ASSERT_TRUE(fetchers[i].Fetch());
Brian Silverman4f4e0612020-08-12 19:54:41 -0700699 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700700 EXPECT_EQ(100 + save, fetchers[i].get()->value());
701 }
702 for (size_t i = fetchers.size() - save; i < fetchers.size() - 1; ++i) {
703 SCOPED_TRACE("fetcher=" + std::to_string(i));
704 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
705 }
706 EXPECT_EQ(1, fetchers.back().get()->value());
707 }
708
709 for (int i = 0; i < 300; ++i) {
710 send_message(200 + i);
Brian Silverman4f4e0612020-08-12 19:54:41 -0700711 verify_buffers();
Brian Silverman77162972020-08-12 19:52:40 -0700712 }
713
714 for (size_t i = 0; i < fetchers.size() - max_save; ++i) {
715 SCOPED_TRACE("fetcher=" + std::to_string(i));
716 if (max_save > 0) {
717 EXPECT_EQ(100 + max_save, fetchers[i].get()->value());
718 } else {
719 EXPECT_EQ(1, fetchers[i].get()->value());
720 }
721 }
722 for (size_t i = fetchers.size() - max_save; i < fetchers.size() - 1; ++i) {
723 SCOPED_TRACE("fetcher=" + std::to_string(i));
724 EXPECT_EQ(100 + (fetchers.size() - 1 - i), fetchers[i].get()->value());
725 }
726 EXPECT_EQ(1, fetchers.back().get()->value());
727 }
728}
729
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800730// Verify that making a fetcher and watcher for "/test" succeeds.
731TEST_P(AbstractEventLoopTest, FetcherAndWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800732 auto loop = Make();
733 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800734 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Parker Schuhe4a70d62017-12-27 20:10:20 -0800735}
736
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800737// Verify that making 2 fetchers for "/test" succeeds.
Parker Schuhe4a70d62017-12-27 20:10:20 -0800738TEST_P(AbstractEventLoopTest, TwoFetcher) {
739 auto loop = Make();
740 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800741 auto fetcher2 = loop->MakeFetcher<TestMessage>("/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -0800742}
743
Alex Perrycb7da4b2019-08-28 19:35:56 -0700744// Verify that registering a watcher for an invalid channel name dies.
745TEST_P(AbstractEventLoopDeathTest, InvalidChannelName) {
746 auto loop = Make();
747 EXPECT_DEATH(
748 { loop->MakeWatcher("/test/invalid", [&](const TestMessage &) {}); },
749 "/test/invalid");
Brian Silverman454bc112020-03-05 14:21:25 -0800750 EXPECT_DEATH(
751 { loop->MakeNoArgWatcher<TestMessage>("/test/invalid", [&]() {}); },
752 "/test/invalid");
Alex Perrycb7da4b2019-08-28 19:35:56 -0700753}
754
James Kuszmaul8866e642022-06-10 16:00:36 -0700755// Verify that setting up a timer before monotonic_clock::epoch() fails.
James Kuszmauleb31d922022-07-19 09:51:50 -0700756// TODO(james): Re-enable when LogReader handles startup correctly.
757TEST_P(AbstractEventLoopDeathTest, DISABLED_NegativeTimeTimer) {
James Kuszmaul8866e642022-06-10 16:00:36 -0700758 auto loop = Make();
759 TimerHandler *time = loop->AddTimer([]() {});
760 EXPECT_DEATH(time->Setup(monotonic_clock::epoch() - std::chrono::seconds(1)),
761 "-1.000");
762}
763
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800764// Verify that registering a watcher twice for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700765TEST_P(AbstractEventLoopDeathTest, TwoWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800766 auto loop = Make();
767 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800768 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
769 "/test");
Brian Silverman454bc112020-03-05 14:21:25 -0800770 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
771}
772
773// Verify that registering a no-arg watcher twice for "/test" fails.
774TEST_P(AbstractEventLoopDeathTest, TwoNoArgWatcher) {
775 auto loop = Make();
776 loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {});
777 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
778 "/test");
779 EXPECT_DEATH(loop->MakeNoArgWatcher<TestMessage>("/test", [&]() {}), "/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800780}
781
Austin Schuh3115a202019-05-27 21:02:14 -0700782// Verify that SetRuntimeRealtimePriority fails while running.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700783TEST_P(AbstractEventLoopDeathTest, SetRuntimeRealtimePriority) {
Austin Schuh3115a202019-05-27 21:02:14 -0700784 auto loop = MakePrimary();
785 // Confirm that runtime priority calls work when not realtime.
786 loop->SetRuntimeRealtimePriority(5);
787
788 loop->OnRun([&]() { loop->SetRuntimeRealtimePriority(5); });
789
790 EXPECT_DEATH(Run(), "realtime");
791}
792
Brian Silverman6a54ff32020-04-28 16:41:39 -0700793// Verify that SetRuntimeAffinity fails while running.
794TEST_P(AbstractEventLoopDeathTest, SetRuntimeAffinity) {
Austin Schuhde973292021-10-12 18:09:49 -0700795 const cpu_set_t available = GetCurrentThreadAffinity();
796 int first_cpu = -1;
797 for (int i = 0; i < CPU_SETSIZE; ++i) {
798 if (CPU_ISSET(i, &available)) {
799 first_cpu = i;
800 break;
801 continue;
802 }
803 }
804 CHECK_NE(first_cpu, -1) << ": Default affinity has no CPUs?";
805
Brian Silverman6a54ff32020-04-28 16:41:39 -0700806 auto loop = MakePrimary();
807 // Confirm that runtime priority calls work when not running.
Austin Schuhde973292021-10-12 18:09:49 -0700808 loop->SetRuntimeAffinity(MakeCpusetFromCpus({first_cpu}));
Brian Silverman6a54ff32020-04-28 16:41:39 -0700809
Austin Schuhde973292021-10-12 18:09:49 -0700810 loop->OnRun(
811 [&]() { loop->SetRuntimeAffinity(MakeCpusetFromCpus({first_cpu})); });
Brian Silverman6a54ff32020-04-28 16:41:39 -0700812
813 EXPECT_DEATH(Run(), "Cannot set affinity while running");
814}
815
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800816// Verify that registering a watcher and a sender for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700817TEST_P(AbstractEventLoopDeathTest, WatcherAndSender) {
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800818 auto loop = Make();
819 auto sender = loop->MakeSender<TestMessage>("/test");
820 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
821 "/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -0800822}
823
Austin Schuhe516ab02020-05-06 21:37:04 -0700824// Verify that creating too many senders fails.
825TEST_P(AbstractEventLoopDeathTest, TooManySenders) {
826 auto loop = Make();
827 std::vector<aos::Sender<TestMessage>> senders;
828 for (int i = 0; i < 10; ++i) {
829 senders.emplace_back(loop->MakeSender<TestMessage>("/test"));
830 }
831 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); },
832 "Failed to create sender on \\{ \"name\": \"/test\", \"type\": "
Brian Silverman77162972020-08-12 19:52:40 -0700833 "\"aos.TestMessage\"[^}]*\\ }, too many senders.");
834}
835
836// Verify that creating too many fetchers fails.
837TEST_P(AbstractEventLoopDeathTest, TooManyFetchers) {
838 if (read_method() != ReadMethod::PIN) {
839 // Other read methods don't limit the number of readers, so just skip this.
840 return;
841 }
842
843 auto loop = Make();
844 std::vector<aos::Fetcher<TestMessage>> fetchers;
845 for (int i = 0; i < 10; ++i) {
846 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
847 }
848 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
849 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
850 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
851}
852
853// Verify that creating too many fetchers, split between two event loops, fails.
854TEST_P(AbstractEventLoopDeathTest, TooManyFetchersTwoLoops) {
855 if (read_method() != ReadMethod::PIN) {
856 // Other read methods don't limit the number of readers, so just skip this.
857 return;
858 }
859
860 auto loop = Make();
861 auto loop2 = Make();
862 std::vector<aos::Fetcher<TestMessage>> fetchers;
863 for (int i = 0; i < 5; ++i) {
864 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
865 fetchers.emplace_back(loop2->MakeFetcher<TestMessage>("/test"));
866 }
867 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
868 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
869 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
870}
871
872// Verify that creating too many watchers fails.
873TEST_P(AbstractEventLoopDeathTest, TooManyWatchers) {
874 if (read_method() != ReadMethod::PIN) {
875 // Other read methods don't limit the number of readers, so just skip this.
876 return;
877 }
878
879 std::vector<std::unique_ptr<EventLoop>> loops;
880 for (int i = 0; i < 10; ++i) {
881 loops.emplace_back(Make());
882 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
883 }
884 EXPECT_DEATH({ Make()->MakeWatcher("/test", [](const TestMessage &) {}); },
885 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
886 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
887}
888
889// Verify that creating too many watchers and fetchers combined fails.
890TEST_P(AbstractEventLoopDeathTest, TooManyWatchersAndFetchers) {
891 if (read_method() != ReadMethod::PIN) {
892 // Other read methods don't limit the number of readers, so just skip this.
893 return;
894 }
895
896 auto loop = Make();
897 std::vector<aos::Fetcher<TestMessage>> fetchers;
898 std::vector<std::unique_ptr<EventLoop>> loops;
899 for (int i = 0; i < 5; ++i) {
900 fetchers.emplace_back(loop->MakeFetcher<TestMessage>("/test"));
901 loops.emplace_back(Make());
902 loops.back()->MakeWatcher("/test", [](const TestMessage &) {});
903 }
904 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); },
905 "Failed to create reader on \\{ \"name\": \"/test\", \"type\": "
906 "\"aos.TestMessage\"[^}]*\\ }, too many readers.");
Austin Schuhe516ab02020-05-06 21:37:04 -0700907}
908
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700909// Verify that we can't create a sender inside OnRun.
910TEST_P(AbstractEventLoopDeathTest, SenderInOnRun) {
911 auto loop1 = MakePrimary();
912
913 loop1->OnRun(
914 [&]() { auto sender = loop1->MakeSender<TestMessage>("/test2"); });
915
916 EXPECT_DEATH(Run(), "running");
917}
918
919// Verify that we can't create a watcher inside OnRun.
920TEST_P(AbstractEventLoopDeathTest, WatcherInOnRun) {
921 auto loop1 = MakePrimary();
922
923 loop1->OnRun(
924 [&]() { loop1->MakeWatcher("/test", [&](const TestMessage &) {}); });
925
926 EXPECT_DEATH(Run(), "running");
927}
928
Brian Silverman454bc112020-03-05 14:21:25 -0800929// Verify that we can't create a no-arg watcher inside OnRun.
930TEST_P(AbstractEventLoopDeathTest, NoArgWatcherInOnRun) {
931 auto loop1 = MakePrimary();
932
933 loop1->OnRun(
934 [&]() { loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {}); });
935
936 EXPECT_DEATH(Run(), "running");
937}
938
Parker Schuhe4a70d62017-12-27 20:10:20 -0800939// Verify that Quit() works when there are multiple watchers.
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800940TEST_P(AbstractEventLoopTest, MultipleWatcherQuit) {
941 auto loop1 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -0700942 auto loop2 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800943
Austin Schuh3578a2e2019-05-25 18:17:59 -0700944 loop2->MakeWatcher("/test1", [&](const TestMessage &) {});
945 loop2->MakeWatcher("/test2", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700946 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -0700947 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -0700948 });
949
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800950 auto sender = loop1->MakeSender<TestMessage>("/test2");
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700951
952 loop2->OnRun([&]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700953 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
954 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
955 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700956 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700957 });
Parker Schuhe4a70d62017-12-27 20:10:20 -0800958
Austin Schuh44019f92019-05-19 19:58:27 -0700959 Run();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800960}
961
Austin Schuhad9e5eb2021-11-19 20:33:55 -0800962// Verify that AOS_LOG has the right name.
963TEST_P(AbstractEventLoopTest, AOSLog) {
964 auto loop2 = MakePrimary("loop1");
965 auto loop1 = Make("loop0");
966
967 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
968
969 EXPECT_FALSE(fetcher.Fetch());
970
971 loop2->OnRun([&]() {
972 AOS_LOG(INFO, "Testing123");
973 this->Exit();
974 });
975
976 Run();
977 EXPECT_TRUE(fetcher.Fetch());
978 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
979}
980
981// Verify that AOS_LOG has the right name in a watcher.
982TEST_P(AbstractEventLoopTest, AOSLogWatcher) {
983 auto loop2 = MakePrimary("loop1");
984 auto loop1 = Make("loop0");
985
986 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
987
988 EXPECT_FALSE(fetcher.Fetch());
989
990 auto sender = loop1->MakeSender<TestMessage>("/test2");
991
992 loop2->MakeWatcher("/test2", [&](const TestMessage & /*message*/) {
993 AOS_LOG(INFO, "Testing123");
994 this->Exit();
995 });
996
997 loop2->OnRun([&]() {
998 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
999 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1000 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001001 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhad9e5eb2021-11-19 20:33:55 -08001002 });
1003
1004 Run();
1005 EXPECT_TRUE(fetcher.Fetch());
1006 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1007}
1008
1009// Verify that AOS_LOG has the right name in a timer.
1010TEST_P(AbstractEventLoopTest, AOSLogTimer) {
1011 auto loop2 = MakePrimary("loop1");
1012 auto loop1 = Make("loop0");
1013
1014 auto fetcher = loop1->MakeFetcher<aos::logging::LogMessageFbs>("/aos");
1015
1016 EXPECT_FALSE(fetcher.Fetch());
1017
1018 auto test_timer = loop2->AddTimer([&]() {
1019 AOS_LOG(INFO, "Testing123");
1020 this->Exit();
1021 });
1022
1023 loop2->OnRun([&]() { test_timer->Setup(loop2->monotonic_now()); });
1024
1025 Run();
1026 EXPECT_TRUE(fetcher.Fetch());
1027 EXPECT_EQ(fetcher->name()->string_view(), "loop1");
1028}
1029
Neil Balch229001a2018-01-07 18:22:52 -08001030// Verify that timer intervals and duration function properly.
1031TEST_P(AbstractEventLoopTest, TimerIntervalAndDuration) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001032 // Force a slower rate so we are guaranteed to have reports for our timer.
Austin Schuh39788ff2019-12-01 18:22:57 -08001033 FLAGS_timing_report_ms = 2000;
1034
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001035 const int kCount = 5;
Neil Balch229001a2018-01-07 18:22:52 -08001036
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001037 auto loop = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001038 auto loop2 = Make();
1039
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001040 ::std::vector<::aos::monotonic_clock::time_point> times;
1041 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
1042
Austin Schuh39788ff2019-12-01 18:22:57 -08001043 Fetcher<timing::Report> report_fetcher =
1044 loop2->MakeFetcher<timing::Report>("/aos");
1045 EXPECT_FALSE(report_fetcher.Fetch());
1046
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001047 auto test_timer = loop->AddTimer([this, &times, &expected_times, &loop]() {
1048 times.push_back(loop->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001049 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
1050 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
1051 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001052 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
Austin Schuh39788ff2019-12-01 18:22:57 -08001053 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
1054 EXPECT_EQ(loop->context().size, 0u);
1055 EXPECT_EQ(loop->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001056 EXPECT_EQ(loop->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001057
Austin Schuhad154822019-12-27 15:45:13 -08001058 expected_times.push_back(loop->context().monotonic_event_time);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001059 if (times.size() == kCount) {
1060 this->Exit();
1061 }
Neil Balch229001a2018-01-07 18:22:52 -08001062 });
Austin Schuh39788ff2019-12-01 18:22:57 -08001063 test_timer->set_name("Test loop");
Neil Balch229001a2018-01-07 18:22:52 -08001064
Austin Schuh39788ff2019-12-01 18:22:57 -08001065 const monotonic_clock::time_point start_time = loop->monotonic_now();
Austin Schuh52d325c2019-06-23 18:59:06 -07001066 // TODO(austin): This should be an error... Should be done in OnRun only.
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001067 test_timer->Setup(start_time + chrono::seconds(1), chrono::seconds(1));
1068
Austin Schuh44019f92019-05-19 19:58:27 -07001069 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001070
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001071 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001072 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
1073 ASSERT_EQ(times.size(), expected_times.size());
1074 ASSERT_EQ((times.size() % 2), 1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001075
1076 // Grab the middle sample.
1077 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
1078
1079 // Add up all the delays of all the times.
1080 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1081 for (const ::aos::monotonic_clock::time_point time : times) {
1082 sum += time - average_time;
1083 }
1084
1085 // Average and add to the middle to find the average time.
1086 sum /= times.size();
1087 average_time += sum;
1088
1089 // Compute the offset from the average and the expected average. It
1090 // should be pretty close to 0.
1091 const ::aos::monotonic_clock::duration remainder =
1092 average_time - start_time - chrono::seconds(times.size() / 2 + 1);
1093
1094 const chrono::milliseconds kEpsilon(100);
1095 EXPECT_LT(remainder, +kEpsilon);
1096 EXPECT_GT(remainder, -kEpsilon);
1097
1098 // Make sure that the average duration is close to 1 second.
1099 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1100 times.front())
1101 .count() /
1102 static_cast<double>(times.size() - 1),
1103 1.0, 0.1);
1104
1105 // Confirm that the ideal wakeup times increment correctly.
1106 for (size_t i = 1; i < expected_times.size(); ++i) {
1107 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1108 }
1109
1110 for (size_t i = 0; i < expected_times.size(); ++i) {
1111 EXPECT_EQ((expected_times[i] - start_time) % chrono::seconds(1),
1112 chrono::seconds(0));
1113 }
1114
1115 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1116 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001117
Austin Schuh6bae8252021-02-07 22:01:49 -08001118 if (do_timing_reports() == DoTimingReports::kYes) {
1119 // And, since we are here, check that the timing report makes sense.
1120 // Start by looking for our event loop's timing.
1121 FlatbufferDetachedBuffer<timing::Report> report =
1122 FlatbufferDetachedBuffer<timing::Report>::Empty();
1123 while (report_fetcher.FetchNext()) {
1124 if (report_fetcher->name()->string_view() == "primary") {
1125 report = CopyFlatBuffer(report_fetcher.get());
1126 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001127 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001128
1129 // Confirm that we have the right number of reports, and the contents are
1130 // sane.
1131 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
1132
1133 EXPECT_EQ(report.message().name()->string_view(), "primary");
1134
1135 ASSERT_NE(report.message().senders(), nullptr);
1136 EXPECT_EQ(report.message().senders()->size(), 2);
1137
1138 ASSERT_NE(report.message().timers(), nullptr);
1139 EXPECT_EQ(report.message().timers()->size(), 2);
1140
1141 EXPECT_EQ(report.message().timers()->Get(0)->name()->string_view(),
1142 "Test loop");
1143 EXPECT_GE(report.message().timers()->Get(0)->count(), 1);
1144
1145 EXPECT_EQ(report.message().timers()->Get(1)->name()->string_view(),
1146 "timing_reports");
1147 EXPECT_EQ(report.message().timers()->Get(1)->count(), 1);
1148
1149 // Make sure there is a single phased loop report with our report in it.
1150 ASSERT_EQ(report.message().phased_loops(), nullptr);
1151 } else {
1152 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001153 }
Neil Balch229001a2018-01-07 18:22:52 -08001154}
1155
1156// Verify that we can change a timer's parameters during execution.
1157TEST_P(AbstractEventLoopTest, TimerChangeParameters) {
Austin Schuh44019f92019-05-19 19:58:27 -07001158 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001159 loop->SetRuntimeRealtimePriority(1);
Austin Schuh7f20f512021-01-31 17:56:16 -08001160 std::vector<monotonic_clock::time_point> iteration_list;
Neil Balch229001a2018-01-07 18:22:52 -08001161
1162 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001163 ScopedNotRealtime nrt;
Austin Schuh7f20f512021-01-31 17:56:16 -08001164 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001165 });
1166
Austin Schuh7f20f512021-01-31 17:56:16 -08001167 monotonic_clock::time_point s;
1168 auto modifier_timer = loop->AddTimer([&test_timer, &s]() {
Austin Schuhd892f102021-10-12 18:01:46 -07001169 test_timer->Setup(s + chrono::milliseconds(1750),
1170 chrono::milliseconds(600));
Neil Balch229001a2018-01-07 18:22:52 -08001171 });
1172
Austin Schuh7f20f512021-01-31 17:56:16 -08001173 s = loop->monotonic_now();
Austin Schuhd892f102021-10-12 18:01:46 -07001174 test_timer->Setup(s, chrono::milliseconds(500));
1175 modifier_timer->Setup(s + chrono::milliseconds(1250));
1176 EndEventLoop(loop.get(), chrono::milliseconds(3950));
Austin Schuh44019f92019-05-19 19:58:27 -07001177 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001178
Austin Schuhd892f102021-10-12 18:01:46 -07001179 EXPECT_THAT(
1180 iteration_list,
1181 ::testing::ElementsAre(
1182 s, s + chrono::milliseconds(500), s + chrono::milliseconds(1000),
1183 s + chrono::milliseconds(1750), s + chrono::milliseconds(2350),
1184 s + chrono::milliseconds(2950), s + chrono::milliseconds(3550)));
Neil Balch229001a2018-01-07 18:22:52 -08001185}
1186
1187// Verify that we can disable a timer during execution.
1188TEST_P(AbstractEventLoopTest, TimerDisable) {
Austin Schuh44019f92019-05-19 19:58:27 -07001189 auto loop = MakePrimary();
Austin Schuhd892f102021-10-12 18:01:46 -07001190 loop->SetRuntimeRealtimePriority(1);
Neil Balch229001a2018-01-07 18:22:52 -08001191 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
1192
1193 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
Austin Schuh9b1d6282022-06-10 17:03:21 -07001194 ScopedNotRealtime nrt;
Austin Schuhd892f102021-10-12 18:01:46 -07001195 iteration_list.push_back(loop->context().monotonic_event_time);
Neil Balch229001a2018-01-07 18:22:52 -08001196 });
1197
Tyler Chatow67ddb032020-01-12 14:30:04 -08001198 auto ender_timer = loop->AddTimer([&test_timer]() { test_timer->Disable(); });
Neil Balch229001a2018-01-07 18:22:52 -08001199
Austin Schuhd892f102021-10-12 18:01:46 -07001200 monotonic_clock::time_point s = loop->monotonic_now();
Austin Schuh73d99502021-12-08 12:05:39 -08001201 test_timer->Setup(s, ::std::chrono::milliseconds(500));
1202 ender_timer->Setup(s + ::std::chrono::milliseconds(1250));
1203 EndEventLoop(loop.get(), ::std::chrono::milliseconds(2000));
Austin Schuh44019f92019-05-19 19:58:27 -07001204 Run();
Neil Balch229001a2018-01-07 18:22:52 -08001205
Austin Schuhd892f102021-10-12 18:01:46 -07001206 EXPECT_THAT(iteration_list,
Austin Schuh73d99502021-12-08 12:05:39 -08001207 ::testing::ElementsAre(s, s + chrono::milliseconds(500),
1208 s + chrono::milliseconds(1000)));
Neil Balch229001a2018-01-07 18:22:52 -08001209}
Austin Schuh7267c532019-05-19 19:55:53 -07001210
Brian Silvermanaf9a4d82020-10-06 15:10:58 -07001211// Verify that a timer can disable itself.
1212//
1213// TODO(Brian): Do something similar with phased loops, both with a quick
1214// handler and a handler that would miss a cycle except it got deferred. Current
1215// behavior doing that is a mess.
1216TEST_P(AbstractEventLoopTest, TimerDisableSelf) {
1217 auto loop = MakePrimary();
1218
1219 int count = 0;
1220 aos::TimerHandler *test_timer;
1221 test_timer = loop->AddTimer([&count, &test_timer]() {
1222 ++count;
1223 test_timer->Disable();
1224 });
1225
1226 test_timer->Setup(loop->monotonic_now(), ::std::chrono::milliseconds(20));
1227 EndEventLoop(loop.get(), ::std::chrono::milliseconds(80));
1228 Run();
1229
1230 EXPECT_EQ(count, 1);
1231}
1232
Brian Silvermanbd405c02020-06-23 16:25:23 -07001233// Verify that we can disable a timer during execution of another timer
1234// scheduled for the same time, with one ordering of creation for the timers.
1235//
1236// Also schedule some more events to reshuffle the heap in EventLoop used for
1237// tracking events to change up the order. This used to segfault
1238// SimulatedEventLoop.
1239TEST_P(AbstractEventLoopTest, TimerDisableOther) {
1240 for (bool creation_order : {true, false}) {
1241 for (bool setup_order : {true, false}) {
1242 for (int shuffle_events = 0; shuffle_events < 5; ++shuffle_events) {
1243 auto loop = MakePrimary();
1244 aos::TimerHandler *test_timer, *ender_timer;
1245 if (creation_order) {
1246 test_timer = loop->AddTimer([]() {});
1247 ender_timer =
1248 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1249 } else {
1250 ender_timer =
1251 loop->AddTimer([&test_timer]() { test_timer->Disable(); });
1252 test_timer = loop->AddTimer([]() {});
1253 }
1254
1255 const auto start = loop->monotonic_now();
1256
1257 for (int i = 0; i < shuffle_events; ++i) {
1258 loop->AddTimer([]() {})->Setup(start + std::chrono::milliseconds(10));
1259 }
1260
1261 if (setup_order) {
1262 test_timer->Setup(start + ::std::chrono::milliseconds(20));
1263 ender_timer->Setup(start + ::std::chrono::milliseconds(20));
1264 } else {
1265 ender_timer->Setup(start + ::std::chrono::milliseconds(20));
1266 test_timer->Setup(start + ::std::chrono::milliseconds(20));
1267 }
1268 EndEventLoop(loop.get(), ::std::chrono::milliseconds(40));
1269 Run();
1270 }
1271 }
1272 }
1273}
1274
Austin Schuh54cf95f2019-11-29 13:14:18 -08001275// Verifies that the event loop implementations detect when Channel is not a
Brian Silverman631b6262021-11-10 12:25:08 -08001276// pointer into configuration(), or a name doesn't map to a channel in
1277// configuration().
Austin Schuh54cf95f2019-11-29 13:14:18 -08001278TEST_P(AbstractEventLoopDeathTest, InvalidChannel) {
1279 auto loop = MakePrimary();
1280
Tyler Chatow67ddb032020-01-12 14:30:04 -08001281 const Channel *channel = configuration::GetChannel(
1282 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
Austin Schuh54cf95f2019-11-29 13:14:18 -08001283
1284 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1285
1286 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001287 loop->MakeRawSender(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001288 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1289
1290 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001291 loop->MakeSender<TestMessage>("/testbad"),
1292 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1293 " not found in config");
1294
1295 EXPECT_FALSE(loop->TryMakeSender<TestMessage>("/testbad"));
1296
1297 EXPECT_DEATH(
1298 loop->MakeRawFetcher(&channel_copy.message()),
Austin Schuh54cf95f2019-11-29 13:14:18 -08001299 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
1300
1301 EXPECT_DEATH(
Brian Silverman631b6262021-11-10 12:25:08 -08001302 loop->MakeFetcher<TestMessage>("/testbad"),
1303 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1304 " not found in config");
1305
1306 EXPECT_FALSE(loop->TryMakeFetcher<TestMessage>("/testbad").valid());
1307
1308 EXPECT_DEATH(
Austin Schuh54cf95f2019-11-29 13:14:18 -08001309 {
1310 loop->MakeRawWatcher(&channel_copy.message(),
1311 [](const Context, const void *) {});
1312 },
1313 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
Brian Silverman631b6262021-11-10 12:25:08 -08001314
1315 EXPECT_DEATH(
1316 { loop->MakeWatcher("/testbad", [](const TestMessage &) {}); },
1317 "Channel \\{ \"name\": \"/testbad\", \"type\": \"aos.TestMessage\" \\}"
1318 " not found in config");
1319}
1320
1321// Verifies that the event loop handles a channel which is not readable or
1322// writable on the current node nicely.
1323TEST_P(AbstractEventLoopDeathTest, InaccessibleChannel) {
1324 EnableNodes("me");
1325 auto loop = MakePrimary("me");
1326 auto loop2 = Make("them");
1327
1328 const Channel *channel = configuration::GetChannel(
1329 loop->configuration(), "/test_noforward", "aos.TestMessage", "", nullptr);
1330
1331 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
1332
1333 EXPECT_DEATH(
1334 loop2->MakeSender<TestMessage>("/test_forward"),
1335 "Channel"
1336 " \\{ \"name\": \"/test_forward\", \"type\": \"aos.TestMessage\" \\}"
1337 " is not able to be sent on this node");
1338
1339 EXPECT_FALSE(loop2->TryMakeSender<TestMessage>("/test_forward"));
1340
1341 EXPECT_DEATH(
1342 loop2->MakeRawFetcher(channel),
1343 "Channel"
1344 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1345 " is not able to be fetched on this node");
1346
1347 EXPECT_DEATH(
1348 loop2->MakeFetcher<TestMessage>("/test_noforward"),
1349 "Channel"
1350 " \\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\" \\}"
1351 " is not able to be fetched on this node");
1352
1353 EXPECT_FALSE(loop2->TryMakeFetcher<TestMessage>("/test_noforward").valid());
1354
1355 EXPECT_DEATH(
1356 { loop2->MakeRawWatcher(channel, [](const Context, const void *) {}); },
1357 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1358 "\"source_node\": \"them\" \\}"
1359 " is not able to be watched on this node");
1360
1361 EXPECT_DEATH(
1362 { loop2->MakeWatcher("/test_noforward", [](const TestMessage &) {}); },
1363 "\\{ \"name\": \"/test_noforward\", \"type\": \"aos.TestMessage\", "
1364 "\"source_node\": \"them\" \\}"
1365 " is not able to be watched on this node");
Austin Schuh54cf95f2019-11-29 13:14:18 -08001366}
1367
Austin Schuhd54780b2020-10-03 16:26:02 -07001368// Verifies that the event loop implementations detect when Channel has an
1369// invalid alignment.
1370TEST_P(AbstractEventLoopDeathTest, InvalidChannelAlignment) {
1371 const char *const kError = "multiple of alignment";
1372 InvalidChannelAlignment();
1373
1374 auto loop = MakePrimary();
1375
1376 const Channel *channel = configuration::GetChannel(
1377 loop->configuration(), "/test", "aos.TestMessage", "", nullptr);
1378
1379 EXPECT_DEATH({ loop->MakeRawSender(channel); }, kError);
1380 EXPECT_DEATH({ loop->MakeSender<TestMessage>("/test"); }, kError);
1381
1382 EXPECT_DEATH({ loop->MakeRawFetcher(channel); }, kError);
1383 EXPECT_DEATH({ loop->MakeFetcher<TestMessage>("/test"); }, kError);
1384
1385 EXPECT_DEATH(
1386 { loop->MakeRawWatcher(channel, [](const Context &, const void *) {}); },
1387 kError);
1388 EXPECT_DEATH({ loop->MakeRawNoArgWatcher(channel, [](const Context &) {}); },
1389 kError);
1390
1391 EXPECT_DEATH({ loop->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
1392 kError);
1393 EXPECT_DEATH({ loop->MakeWatcher("/test", [](const TestMessage &) {}); },
1394 kError);
1395}
1396
Brian Silverman454bc112020-03-05 14:21:25 -08001397// Verify that the send time on a message is roughly right when using a watcher.
Austin Schuh7267c532019-05-19 19:55:53 -07001398TEST_P(AbstractEventLoopTest, MessageSendTime) {
Austin Schuh44019f92019-05-19 19:58:27 -07001399 auto loop1 = MakePrimary();
Austin Schuh7267c532019-05-19 19:55:53 -07001400 auto loop2 = Make();
Austin Schuhad154822019-12-27 15:45:13 -08001401 auto sender = loop2->MakeSender<TestMessage>("/test");
Austin Schuh7267c532019-05-19 19:55:53 -07001402 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
1403
1404 auto test_timer = loop1->AddTimer([&sender]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -07001405 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1406 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1407 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001408 msg.CheckOk(msg.Send(builder.Finish()));
Alex Perrycb7da4b2019-08-28 19:35:56 -07001409 });
1410
Austin Schuhad154822019-12-27 15:45:13 -08001411 bool triggered = false;
Brian Silverman454bc112020-03-05 14:21:25 -08001412 loop1->MakeWatcher("/test", [&](const TestMessage &msg) {
Austin Schuhad154822019-12-27 15:45:13 -08001413 // Confirm that the data pointer makes sense from a watcher, and all the
1414 // timestamps look right.
1415 EXPECT_GT(&msg, loop1->context().data);
1416 EXPECT_EQ(loop1->context().monotonic_remote_time,
1417 loop1->context().monotonic_event_time);
1418 EXPECT_EQ(loop1->context().realtime_remote_time,
1419 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001420 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001421
1422 const aos::monotonic_clock::time_point monotonic_now =
1423 loop1->monotonic_now();
Tyler Chatow67ddb032020-01-12 14:30:04 -08001424 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08001425
1426 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1427 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1428 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1429 monotonic_now);
1430 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1431 realtime_now);
1432
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001433 EXPECT_LT(&msg, reinterpret_cast<const void *>(
1434 reinterpret_cast<const char *>(loop1->context().data) +
Austin Schuhad154822019-12-27 15:45:13 -08001435 loop1->context().size));
Brian Silverman4f4e0612020-08-12 19:54:41 -07001436 if (read_method() == ReadMethod::PIN) {
1437 EXPECT_GE(loop1->context().buffer_index, 0);
1438 EXPECT_LT(loop1->context().buffer_index,
1439 loop1->NumberBuffers(
1440 configuration::GetChannel(loop1->configuration(), "/test",
1441 "aos.TestMessage", "", nullptr)));
1442 } else {
1443 EXPECT_EQ(-1, loop1->context().buffer_index);
1444 }
Austin Schuhad154822019-12-27 15:45:13 -08001445 triggered = true;
Austin Schuh7267c532019-05-19 19:55:53 -07001446 });
1447
1448 test_timer->Setup(loop1->monotonic_now() + ::std::chrono::seconds(1));
1449
1450 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
Austin Schuh44019f92019-05-19 19:58:27 -07001451 Run();
Austin Schuh7267c532019-05-19 19:55:53 -07001452
Austin Schuhad154822019-12-27 15:45:13 -08001453 EXPECT_TRUE(triggered);
1454
Brian Silverman454bc112020-03-05 14:21:25 -08001455 ASSERT_TRUE(fetcher.Fetch());
1456
1457 monotonic_clock::duration monotonic_time_offset =
1458 fetcher.context().monotonic_event_time -
1459 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1460 realtime_clock::duration realtime_time_offset =
1461 fetcher.context().realtime_event_time -
1462 (loop1->realtime_now() - ::std::chrono::seconds(1));
1463
1464 EXPECT_EQ(fetcher.context().realtime_event_time,
1465 fetcher.context().realtime_remote_time);
1466 EXPECT_EQ(fetcher.context().monotonic_event_time,
1467 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001468 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001469
1470 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1471 << ": Got "
1472 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1473 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1474 // Confirm that the data pointer makes sense.
1475 EXPECT_GT(fetcher.get(), fetcher.context().data);
1476 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001477 reinterpret_cast<const void *>(
1478 reinterpret_cast<const char *>(fetcher.context().data) +
Brian Silverman454bc112020-03-05 14:21:25 -08001479 fetcher.context().size));
1480 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1481 << ": Got "
1482 << fetcher.context().monotonic_event_time.time_since_epoch().count()
1483 << " expected " << loop1->monotonic_now().time_since_epoch().count();
1484
1485 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1486 << ": Got "
1487 << fetcher.context().realtime_event_time.time_since_epoch().count()
1488 << " expected " << loop1->realtime_now().time_since_epoch().count();
1489 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1490 << ": Got "
1491 << fetcher.context().realtime_event_time.time_since_epoch().count()
1492 << " expected " << loop1->realtime_now().time_since_epoch().count();
1493}
1494
1495// Verify that the send time on a message is roughly right when using a no-arg
1496// watcher. To get a message, we need to use a fetcher to actually access the
1497// message. This is also the main use case for no-arg fetchers.
1498TEST_P(AbstractEventLoopTest, MessageSendTimeNoArg) {
1499 auto loop1 = MakePrimary();
1500 auto loop2 = Make();
1501 auto sender = loop2->MakeSender<TestMessage>("/test");
1502 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
1503
1504 auto test_timer = loop1->AddTimer([&sender]() {
1505 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1506 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1507 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -07001508 msg.CheckOk(msg.Send(builder.Finish()));
Brian Silverman454bc112020-03-05 14:21:25 -08001509 });
1510
1511 bool triggered = false;
1512 loop1->MakeNoArgWatcher<TestMessage>("/test", [&]() {
1513 // Confirm that we can indeed use a fetcher on this channel from this
1514 // context, and it results in a sane data pointer and timestamps.
1515 ASSERT_TRUE(fetcher.Fetch());
1516
1517 EXPECT_EQ(loop1->context().monotonic_remote_time,
1518 loop1->context().monotonic_event_time);
1519 EXPECT_EQ(loop1->context().realtime_remote_time,
1520 loop1->context().realtime_event_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001521 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Brian Silverman454bc112020-03-05 14:21:25 -08001522
1523 const aos::monotonic_clock::time_point monotonic_now =
1524 loop1->monotonic_now();
1525 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
1526
1527 EXPECT_LE(loop1->context().monotonic_event_time, monotonic_now);
1528 EXPECT_LE(loop1->context().realtime_event_time, realtime_now);
1529 EXPECT_GE(loop1->context().monotonic_event_time + chrono::milliseconds(500),
1530 monotonic_now);
1531 EXPECT_GE(loop1->context().realtime_event_time + chrono::milliseconds(500),
1532 realtime_now);
1533
1534 triggered = true;
1535 });
1536
1537 test_timer->Setup(loop1->monotonic_now() + ::std::chrono::seconds(1));
1538
1539 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
1540 Run();
1541
1542 ASSERT_TRUE(triggered);
Austin Schuh7267c532019-05-19 19:55:53 -07001543
Alex Perrycb7da4b2019-08-28 19:35:56 -07001544 monotonic_clock::duration monotonic_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001545 fetcher.context().monotonic_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001546 (loop1->monotonic_now() - ::std::chrono::seconds(1));
1547 realtime_clock::duration realtime_time_offset =
Austin Schuhad154822019-12-27 15:45:13 -08001548 fetcher.context().realtime_event_time -
Alex Perrycb7da4b2019-08-28 19:35:56 -07001549 (loop1->realtime_now() - ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -07001550
Austin Schuhad154822019-12-27 15:45:13 -08001551 EXPECT_EQ(fetcher.context().realtime_event_time,
1552 fetcher.context().realtime_remote_time);
1553 EXPECT_EQ(fetcher.context().monotonic_event_time,
1554 fetcher.context().monotonic_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001555 EXPECT_EQ(fetcher.context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001556
Alex Perrycb7da4b2019-08-28 19:35:56 -07001557 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
1558 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001559 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh52d325c2019-06-23 18:59:06 -07001560 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07001561 // Confirm that the data pointer makes sense.
1562 EXPECT_GT(fetcher.get(), fetcher.context().data);
1563 EXPECT_LT(fetcher.get(),
Brian Silvermaneaa41d62020-07-08 19:47:35 -07001564 reinterpret_cast<const void *>(
1565 reinterpret_cast<const char *>(fetcher.context().data) +
Alex Perrycb7da4b2019-08-28 19:35:56 -07001566 fetcher.context().size));
1567 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
1568 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001569 << fetcher.context().monotonic_event_time.time_since_epoch().count()
Austin Schuh7267c532019-05-19 19:55:53 -07001570 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -07001571
1572 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
1573 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001574 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07001575 << " expected " << loop1->realtime_now().time_since_epoch().count();
1576 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
1577 << ": Got "
Austin Schuhad154822019-12-27 15:45:13 -08001578 << fetcher.context().realtime_event_time.time_since_epoch().count()
Alex Perrycb7da4b2019-08-28 19:35:56 -07001579 << " expected " << loop1->realtime_now().time_since_epoch().count();
Austin Schuh7267c532019-05-19 19:55:53 -07001580}
1581
Austin Schuh52d325c2019-06-23 18:59:06 -07001582// Tests that a couple phased loops run in a row result in the correct offset
1583// and period.
1584TEST_P(AbstractEventLoopTest, PhasedLoopTest) {
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001585 // Force a slower rate so we are guaranteed to have reports for our phased
Austin Schuh39788ff2019-12-01 18:22:57 -08001586 // loop.
1587 FLAGS_timing_report_ms = 2000;
1588
Austin Schuh52d325c2019-06-23 18:59:06 -07001589 const chrono::milliseconds kOffset = chrono::milliseconds(400);
1590 const int kCount = 5;
1591
1592 auto loop1 = MakePrimary();
Austin Schuh39788ff2019-12-01 18:22:57 -08001593 auto loop2 = Make();
1594
1595 Fetcher<timing::Report> report_fetcher =
1596 loop2->MakeFetcher<timing::Report>("/aos");
1597 EXPECT_FALSE(report_fetcher.Fetch());
Austin Schuh52d325c2019-06-23 18:59:06 -07001598
1599 // Collect up a couple of samples.
1600 ::std::vector<::aos::monotonic_clock::time_point> times;
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001601 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
Austin Schuh52d325c2019-06-23 18:59:06 -07001602
1603 // Run kCount iterations.
Austin Schuh39788ff2019-12-01 18:22:57 -08001604 loop1
1605 ->AddPhasedLoop(
1606 [&times, &expected_times, &loop1, this](int count) {
1607 EXPECT_EQ(count, 1);
1608 times.push_back(loop1->monotonic_now());
Austin Schuhad154822019-12-27 15:45:13 -08001609 expected_times.push_back(loop1->context().monotonic_event_time);
Austin Schuh39788ff2019-12-01 18:22:57 -08001610
Austin Schuhad154822019-12-27 15:45:13 -08001611 EXPECT_EQ(loop1->context().monotonic_remote_time,
1612 monotonic_clock::min_time);
Austin Schuha9012be2021-07-21 15:19:11 -07001613 EXPECT_EQ(loop1->context().source_boot_uuid, loop1->boot_uuid());
Austin Schuhad154822019-12-27 15:45:13 -08001614 EXPECT_EQ(loop1->context().realtime_event_time,
1615 realtime_clock::min_time);
1616 EXPECT_EQ(loop1->context().realtime_remote_time,
Austin Schuh39788ff2019-12-01 18:22:57 -08001617 realtime_clock::min_time);
1618 EXPECT_EQ(loop1->context().queue_index, 0xffffffffu);
1619 EXPECT_EQ(loop1->context().size, 0u);
1620 EXPECT_EQ(loop1->context().data, nullptr);
Brian Silverman4f4e0612020-08-12 19:54:41 -07001621 EXPECT_EQ(loop1->context().buffer_index, -1);
Austin Schuh39788ff2019-12-01 18:22:57 -08001622
1623 if (times.size() == kCount) {
1624 LOG(INFO) << "Exiting";
1625 this->Exit();
1626 }
1627 },
1628 chrono::seconds(1), kOffset)
1629 ->set_name("Test loop");
Austin Schuh52d325c2019-06-23 18:59:06 -07001630
1631 // Add a delay to make sure that delay during startup doesn't result in a
1632 // "missed cycle".
1633 SleepFor(chrono::seconds(2));
1634
1635 Run();
1636
1637 // Confirm that we got both the right number of samples, and it's odd.
Stephan Pleines3dce7ea2021-06-22 13:19:26 -07001638 ASSERT_EQ(times.size(), static_cast<size_t>(kCount));
1639 ASSERT_EQ(times.size(), expected_times.size());
1640 ASSERT_EQ((times.size() % 2), 1);
Austin Schuh52d325c2019-06-23 18:59:06 -07001641
1642 // Grab the middle sample.
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001643 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
Austin Schuh52d325c2019-06-23 18:59:06 -07001644
1645 // Add up all the delays of all the times.
1646 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1647 for (const ::aos::monotonic_clock::time_point time : times) {
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001648 sum += time - average_time;
Austin Schuh52d325c2019-06-23 18:59:06 -07001649 }
1650
1651 // Average and add to the middle to find the average time.
1652 sum /= times.size();
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001653 average_time += sum;
Austin Schuh52d325c2019-06-23 18:59:06 -07001654
1655 // Compute the offset from the start of the second of the average time. This
1656 // should be pretty close to the offset.
1657 const ::aos::monotonic_clock::duration remainder =
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001658 average_time.time_since_epoch() -
1659 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
Austin Schuh52d325c2019-06-23 18:59:06 -07001660
1661 const chrono::milliseconds kEpsilon(100);
1662 EXPECT_LT(remainder, kOffset + kEpsilon);
1663 EXPECT_GT(remainder, kOffset - kEpsilon);
1664
1665 // Make sure that the average duration is close to 1 second.
1666 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1667 times.front())
1668 .count() /
1669 static_cast<double>(times.size() - 1),
1670 1.0, 0.1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -08001671
1672 // Confirm that the ideal wakeup times increment correctly.
1673 for (size_t i = 1; i < expected_times.size(); ++i) {
1674 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
1675 }
1676
1677 for (size_t i = 0; i < expected_times.size(); ++i) {
1678 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
1679 kOffset);
1680 }
1681
1682 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1683 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh39788ff2019-12-01 18:22:57 -08001684
Austin Schuh6bae8252021-02-07 22:01:49 -08001685 if (do_timing_reports() == DoTimingReports::kYes) {
1686 // And, since we are here, check that the timing report makes sense.
1687 // Start by looking for our event loop's timing.
1688 FlatbufferDetachedBuffer<timing::Report> report =
1689 FlatbufferDetachedBuffer<timing::Report>::Empty();
1690 while (report_fetcher.FetchNext()) {
1691 if (report_fetcher->name()->string_view() == "primary") {
1692 report = CopyFlatBuffer(report_fetcher.get());
1693 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001694 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001695
1696 VLOG(1) << FlatbufferToJson(report, {.multi_line = true});
1697
1698 EXPECT_EQ(report.message().name()->string_view(), "primary");
1699
1700 ASSERT_NE(report.message().senders(), nullptr);
1701 EXPECT_EQ(report.message().senders()->size(), 2);
1702
1703 ASSERT_NE(report.message().timers(), nullptr);
1704 EXPECT_EQ(report.message().timers()->size(), 1);
1705
1706 // Make sure there is a single phased loop report with our report in it.
1707 ASSERT_NE(report.message().phased_loops(), nullptr);
1708 ASSERT_EQ(report.message().phased_loops()->size(), 1);
1709 EXPECT_EQ(report.message().phased_loops()->Get(0)->name()->string_view(),
1710 "Test loop");
1711 EXPECT_GE(report.message().phased_loops()->Get(0)->count(), 1);
1712 } else {
1713 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001714 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001715}
1716
Milind Upadhyay42589bb2021-05-19 20:05:16 -07001717// Tests that a phased loop responds correctly to a changing offset.
1718TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetTest) {
1719 // Force a slower rate so we are guaranteed to have reports for our phased
1720 // loop.
1721 FLAGS_timing_report_ms = 2000;
1722
1723 const chrono::milliseconds kOffset = chrono::milliseconds(400);
1724 const chrono::milliseconds kInterval = chrono::milliseconds(1000);
1725 const int kCount = 5;
1726
1727 auto loop1 = MakePrimary();
1728
1729 // Collect up a couple of samples.
1730 ::std::vector<::aos::monotonic_clock::time_point> times;
1731 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
1732
1733 PhasedLoopHandler *phased_loop;
1734
1735 // Run kCount iterations.
1736 phased_loop = loop1->AddPhasedLoop(
1737 [&phased_loop, &times, &expected_times, &loop1, this, kOffset,
1738 kInterval](int count) {
1739 EXPECT_EQ(count, 1);
1740 times.push_back(loop1->monotonic_now());
1741
1742 expected_times.push_back(loop1->context().monotonic_event_time);
1743
1744 phased_loop->set_interval_and_offset(
1745 kInterval, kOffset - chrono::milliseconds(times.size()));
1746 LOG(INFO) << "new offset: "
1747 << (kOffset - chrono::milliseconds(times.size())).count();
1748
1749 if (times.size() == kCount) {
1750 LOG(INFO) << "Exiting";
1751 this->Exit();
1752 }
1753 },
1754 kInterval, kOffset);
1755 phased_loop->set_name("Test loop");
1756
1757 // Add a delay to make sure that delay during startup doesn't result in a
1758 // "missed cycle".
1759 SleepFor(chrono::seconds(2));
1760
1761 Run();
1762 // Confirm that we got both the right number of samples, and it's odd.
1763 EXPECT_EQ(times.size(), static_cast<size_t>(kCount));
1764 EXPECT_EQ(times.size(), expected_times.size());
1765 EXPECT_EQ((times.size() % 2), 1);
1766
1767 // Grab the middle sample.
1768 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
1769
1770 // Add up all the delays of all the times.
1771 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
1772 for (const ::aos::monotonic_clock::time_point time : times) {
1773 sum += time - average_time;
1774 }
1775
1776 // Average and add to the middle to find the average time.
1777 sum /= times.size();
1778 average_time += sum;
1779
1780 // Compute the offset from the start of the second of the average time. This
1781 // should be pretty close to the offset.
1782 const ::aos::monotonic_clock::duration remainder =
1783 average_time.time_since_epoch() -
1784 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
1785
1786 const chrono::milliseconds kEpsilon(100);
1787 EXPECT_LT(remainder, kOffset + kEpsilon);
1788 EXPECT_GT(remainder, kOffset - kEpsilon);
1789
1790 // Make sure that the average duration is close to 1 second.
1791 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
1792 times.front())
1793 .count() /
1794 static_cast<double>(times.size() - 1),
1795 1.0, 0.1);
1796
1797 // Confirm that the ideal wakeup times increment correctly.
1798 for (size_t i = 1; i < expected_times.size(); ++i) {
1799 LOG(INFO) << i - 1 << ": " << expected_times[i - 1] << ", " << i << ": "
1800 << expected_times[i];
1801 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1) -
1802 chrono::milliseconds(1));
1803 }
1804
1805 for (size_t i = 0; i < expected_times.size(); ++i) {
1806 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
1807 kOffset - chrono::milliseconds(i));
1808 }
1809
1810 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
1811 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
1812}
1813
Austin Schuh39788ff2019-12-01 18:22:57 -08001814// Tests that senders count correctly in the timing report.
1815TEST_P(AbstractEventLoopTest, SenderTimingReport) {
1816 FLAGS_timing_report_ms = 1000;
1817 auto loop1 = MakePrimary();
1818
1819 auto loop2 = Make("watcher_loop");
1820 loop2->MakeWatcher("/test", [](const TestMessage &) {});
1821
1822 auto loop3 = Make();
1823
1824 Fetcher<timing::Report> report_fetcher =
1825 loop3->MakeFetcher<timing::Report>("/aos");
1826 EXPECT_FALSE(report_fetcher.Fetch());
1827
1828 auto sender = loop1->MakeSender<TestMessage>("/test");
1829
James Kuszmaul78514332022-04-06 15:08:34 -07001830 // Sanity check channel frequencies to ensure that we've designed the test
1831 // correctly.
1832 ASSERT_EQ(800, sender.channel()->frequency());
1833 ASSERT_EQ(2000000000, loop1->configuration()->channel_storage_duration());
1834 constexpr int kMaxAllowedMessages = 800 * 2;
1835 constexpr int kSendMessages = kMaxAllowedMessages * 2;
1836 constexpr int kDroppedMessages = kSendMessages - kMaxAllowedMessages;
1837
Austin Schuh39788ff2019-12-01 18:22:57 -08001838 // Add a timer to actually quit.
1839 auto test_timer = loop1->AddTimer([&sender]() {
James Kuszmaul78514332022-04-06 15:08:34 -07001840 for (int i = 0; i < kSendMessages; ++i) {
Austin Schuh39788ff2019-12-01 18:22:57 -08001841 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
1842 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
1843 builder.add_value(200 + i);
James Kuszmaul78514332022-04-06 15:08:34 -07001844 if (i < kMaxAllowedMessages) {
1845 msg.CheckOk(msg.Send(builder.Finish()));
1846 } else {
1847 EXPECT_EQ(RawSender::Error::kMessagesSentTooFast,
1848 msg.Send(builder.Finish()));
1849 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001850 }
1851 });
1852
1853 // Quit after 1 timing report, mid way through the next cycle.
1854 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
1855
1856 loop1->OnRun([&test_timer, &loop1]() {
1857 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1500));
1858 });
1859
1860 Run();
1861
Austin Schuh6bae8252021-02-07 22:01:49 -08001862 if (do_timing_reports() == DoTimingReports::kYes) {
1863 // And, since we are here, check that the timing report makes sense.
1864 // Start by looking for our event loop's timing.
1865 FlatbufferDetachedBuffer<timing::Report> primary_report =
1866 FlatbufferDetachedBuffer<timing::Report>::Empty();
1867 while (report_fetcher.FetchNext()) {
Austin Schuh8902fa52021-03-14 22:39:24 -07001868 VLOG(1) << "Report " << FlatbufferToJson(report_fetcher.get());
Austin Schuh6bae8252021-02-07 22:01:49 -08001869 if (report_fetcher->name()->string_view() == "primary") {
1870 primary_report = CopyFlatBuffer(report_fetcher.get());
1871 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001872 }
Austin Schuh6bae8252021-02-07 22:01:49 -08001873
Austin Schuh8902fa52021-03-14 22:39:24 -07001874 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
Austin Schuh6bae8252021-02-07 22:01:49 -08001875
1876 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
1877
1878 ASSERT_NE(primary_report.message().senders(), nullptr);
1879 EXPECT_EQ(primary_report.message().senders()->size(), 3);
1880
1881 // Confirm that the sender looks sane.
1882 EXPECT_EQ(
1883 loop1->configuration()
1884 ->channels()
1885 ->Get(primary_report.message().senders()->Get(0)->channel_index())
1886 ->name()
1887 ->string_view(),
1888 "/test");
James Kuszmaul78514332022-04-06 15:08:34 -07001889 EXPECT_EQ(primary_report.message().senders()->Get(0)->count(),
1890 kMaxAllowedMessages);
1891 ASSERT_TRUE(primary_report.message().senders()->Get(0)->has_error_counts());
1892 ASSERT_EQ(
1893 primary_report.message().senders()->Get(0)->error_counts()->size(), 2u);
1894 EXPECT_EQ(
1895 primary_report.message()
1896 .senders()
1897 ->Get(0)
1898 ->error_counts()
1899 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
1900 ->count(),
1901 kDroppedMessages)
1902 << aos::FlatbufferToJson(primary_report);
1903 EXPECT_EQ(primary_report.message()
1904 .senders()
1905 ->Get(0)
1906 ->error_counts()
1907 ->Get(static_cast<size_t>(timing::SendError::INVALID_REDZONE))
1908 ->count(),
1909 0);
Austin Schuh6bae8252021-02-07 22:01:49 -08001910
1911 // Confirm that the timing primary_report sender looks sane.
1912 EXPECT_EQ(
1913 loop1->configuration()
1914 ->channels()
1915 ->Get(primary_report.message().senders()->Get(1)->channel_index())
1916 ->name()
1917 ->string_view(),
1918 "/aos");
1919 EXPECT_EQ(primary_report.message().senders()->Get(1)->count(), 1);
1920
1921 ASSERT_NE(primary_report.message().timers(), nullptr);
1922 EXPECT_EQ(primary_report.message().timers()->size(), 3);
1923
1924 // Make sure there are no phased loops or watchers.
1925 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
1926 ASSERT_EQ(primary_report.message().watchers(), nullptr);
1927 } else {
1928 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08001929 }
Austin Schuh39788ff2019-12-01 18:22:57 -08001930}
1931
James Kuszmaul93abac12022-04-14 15:05:10 -07001932// Tests that the RawSender::Send(void*, size_t) overload tracks things properly
1933// in its timing report.
1934TEST_P(AbstractEventLoopTest, CopySenderTimingReport) {
1935 gflags::FlagSaver flag_saver;
1936 FLAGS_timing_report_ms = 1000;
1937 auto loop1 = Make();
1938 auto loop2 = MakePrimary();
1939
1940 const FlatbufferDetachedBuffer<TestMessage> kMessage =
1941 JsonToFlatbuffer<TestMessage>("{}");
1942
1943 std::unique_ptr<aos::RawSender> sender =
1944 loop2->MakeRawSender(configuration::GetChannel(
1945 loop2->configuration(), "/test", "aos.TestMessage", "", nullptr));
1946
1947 Fetcher<timing::Report> report_fetcher =
1948 loop1->MakeFetcher<timing::Report>("/aos");
1949 EXPECT_FALSE(report_fetcher.Fetch());
1950
1951 loop2->OnRun([&]() {
1952 for (int ii = 0; ii < TestChannelQueueSize(loop2.get()); ++ii) {
1953 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
1954 RawSender::Error::kOk);
1955 }
1956 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
1957 RawSender::Error::kMessagesSentTooFast);
1958 });
1959 // Quit after 1 timing report, mid way through the next cycle.
1960 EndEventLoop(loop2.get(), chrono::milliseconds(1500));
1961
1962 Run();
1963
1964 if (do_timing_reports() == DoTimingReports::kYes) {
1965 // Check that the sent too fast actually got recorded by the timing report.
1966 FlatbufferDetachedBuffer<timing::Report> primary_report =
1967 FlatbufferDetachedBuffer<timing::Report>::Empty();
1968 while (report_fetcher.FetchNext()) {
1969 if (report_fetcher->name()->string_view() == "primary") {
1970 primary_report = CopyFlatBuffer(report_fetcher.get());
1971 }
1972 }
1973
1974 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
1975
1976 ASSERT_NE(primary_report.message().senders(), nullptr);
1977 EXPECT_EQ(primary_report.message().senders()->size(), 3);
1978 EXPECT_EQ(
1979 primary_report.message()
1980 .senders()
1981 ->Get(0)
1982 ->error_counts()
1983 ->Get(static_cast<size_t>(timing::SendError::MESSAGE_SENT_TOO_FAST))
1984 ->count(),
1985 1);
1986 }
1987}
1988
Austin Schuh39788ff2019-12-01 18:22:57 -08001989// Tests that senders count correctly in the timing report.
1990TEST_P(AbstractEventLoopTest, WatcherTimingReport) {
1991 FLAGS_timing_report_ms = 1000;
1992 auto loop1 = MakePrimary();
1993 loop1->MakeWatcher("/test", [](const TestMessage &) {});
1994
1995 auto loop2 = Make("sender_loop");
1996
1997 auto loop3 = Make();
1998
1999 Fetcher<timing::Report> report_fetcher =
2000 loop3->MakeFetcher<timing::Report>("/aos");
2001 EXPECT_FALSE(report_fetcher.Fetch());
2002
2003 auto sender = loop2->MakeSender<TestMessage>("/test");
2004
2005 // Add a timer to actually quit.
2006 auto test_timer = loop1->AddTimer([&sender]() {
2007 for (int i = 0; i < 10; ++i) {
2008 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2009 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2010 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002011 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002012 }
2013 });
2014
2015 // Quit after 1 timing report, mid way through the next cycle.
2016 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2017
2018 loop1->OnRun([&test_timer, &loop1]() {
2019 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1500));
2020 });
2021
2022 Run();
2023
Austin Schuh6bae8252021-02-07 22:01:49 -08002024 if (do_timing_reports() == DoTimingReports::kYes) {
2025 // And, since we are here, check that the timing report makes sense.
2026 // Start by looking for our event loop's timing.
2027 FlatbufferDetachedBuffer<timing::Report> primary_report =
2028 FlatbufferDetachedBuffer<timing::Report>::Empty();
2029 while (report_fetcher.FetchNext()) {
2030 LOG(INFO) << "Report " << FlatbufferToJson(report_fetcher.get());
2031 if (report_fetcher->name()->string_view() == "primary") {
2032 primary_report = CopyFlatBuffer(report_fetcher.get());
2033 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002034 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002035
2036 // Check the watcher report.
2037 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2038
2039 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2040
2041 // Just the timing report timer.
2042 ASSERT_NE(primary_report.message().timers(), nullptr);
2043 EXPECT_EQ(primary_report.message().timers()->size(), 3);
2044
2045 // No phased loops
2046 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2047
2048 ASSERT_NE(primary_report.message().watchers(), nullptr);
2049 ASSERT_EQ(primary_report.message().watchers()->size(), 1);
2050 EXPECT_EQ(primary_report.message().watchers()->Get(0)->count(), 10);
2051 } else {
2052 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002053 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002054}
2055
2056// Tests that fetchers count correctly in the timing report.
2057TEST_P(AbstractEventLoopTest, FetcherTimingReport) {
2058 FLAGS_timing_report_ms = 1000;
2059 auto loop1 = MakePrimary();
2060 auto loop2 = Make("sender_loop");
2061
2062 auto loop3 = Make();
2063
2064 Fetcher<timing::Report> report_fetcher =
2065 loop3->MakeFetcher<timing::Report>("/aos");
2066 EXPECT_FALSE(report_fetcher.Fetch());
2067
2068 auto sender = loop2->MakeSender<TestMessage>("/test");
2069 auto fetcher1 = loop1->MakeFetcher<TestMessage>("/test");
2070 auto fetcher2 = loop1->MakeFetcher<TestMessage>("/test");
2071 fetcher1.Fetch();
2072 fetcher2.Fetch();
2073
2074 // Add a timer to actually quit.
2075 auto test_timer = loop1->AddTimer([&sender]() {
2076 for (int i = 0; i < 10; ++i) {
2077 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2078 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2079 builder.add_value(200 + i);
milind1f1dca32021-07-03 13:50:07 -07002080 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh39788ff2019-12-01 18:22:57 -08002081 }
2082 });
2083
2084 auto test_timer2 = loop1->AddTimer([&fetcher1, &fetcher2]() {
2085 fetcher1.Fetch();
2086 while (fetcher2.FetchNext()) {
2087 }
2088 });
2089
2090 // Quit after 1 timing report, mid way through the next cycle.
2091 EndEventLoop(loop1.get(), chrono::milliseconds(2500));
2092
2093 loop1->OnRun([test_timer, test_timer2, &loop1]() {
2094 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1400));
2095 test_timer2->Setup(loop1->monotonic_now() + chrono::milliseconds(1600));
2096 });
2097
2098 Run();
2099
Austin Schuh6bae8252021-02-07 22:01:49 -08002100 if (do_timing_reports() == DoTimingReports::kYes) {
2101 // And, since we are here, check that the timing report makes sense.
2102 // Start by looking for our event loop's timing.
2103 FlatbufferDetachedBuffer<timing::Report> primary_report =
2104 FlatbufferDetachedBuffer<timing::Report>::Empty();
2105 while (report_fetcher.FetchNext()) {
2106 if (report_fetcher->name()->string_view() == "primary") {
2107 primary_report = CopyFlatBuffer(report_fetcher.get());
2108 }
Austin Schuh39788ff2019-12-01 18:22:57 -08002109 }
Austin Schuh6bae8252021-02-07 22:01:49 -08002110
2111 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
2112
2113 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
2114
2115 ASSERT_NE(primary_report.message().senders(), nullptr);
2116 EXPECT_EQ(primary_report.message().senders()->size(), 2);
2117
2118 ASSERT_NE(primary_report.message().timers(), nullptr);
2119 EXPECT_EQ(primary_report.message().timers()->size(), 4);
2120
2121 // Make sure there are no phased loops or watchers.
2122 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
2123 ASSERT_EQ(primary_report.message().watchers(), nullptr);
2124
2125 // Now look at the fetchrs.
2126 ASSERT_NE(primary_report.message().fetchers(), nullptr);
2127 ASSERT_EQ(primary_report.message().fetchers()->size(), 2);
2128
2129 EXPECT_EQ(primary_report.message().fetchers()->Get(0)->count(), 1);
2130 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->average(),
2131 0.1);
2132 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->min(),
2133 0.1);
2134 EXPECT_GE(primary_report.message().fetchers()->Get(0)->latency()->max(),
2135 0.1);
2136 EXPECT_EQ(primary_report.message()
2137 .fetchers()
2138 ->Get(0)
2139 ->latency()
2140 ->standard_deviation(),
2141 0.0);
2142
2143 EXPECT_EQ(primary_report.message().fetchers()->Get(1)->count(), 10);
2144 } else {
2145 ASSERT_FALSE(report_fetcher.Fetch());
Austin Schuh39788ff2019-12-01 18:22:57 -08002146 }
Austin Schuh52d325c2019-06-23 18:59:06 -07002147}
2148
Austin Schuh67420a42019-12-21 21:55:04 -08002149// Tests that a raw watcher and raw fetcher can receive messages from a raw
2150// sender without messing up offsets.
2151TEST_P(AbstractEventLoopTest, RawBasic) {
2152 auto loop1 = Make();
2153 auto loop2 = MakePrimary();
2154 auto loop3 = Make();
2155
Austin Schuha9df9ad2021-06-16 14:49:39 -07002156 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2157 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuh67420a42019-12-21 21:55:04 -08002158
2159 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002160 loop1->MakeRawSender(configuration::GetChannel(
2161 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08002162
2163 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002164 loop3->MakeRawFetcher(configuration::GetChannel(
2165 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh67420a42019-12-21 21:55:04 -08002166
Austin Schuha9df9ad2021-06-16 14:49:39 -07002167 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002168 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2169 RawSender::Error::kOk);
Austin Schuha9df9ad2021-06-16 14:49:39 -07002170 });
Austin Schuh67420a42019-12-21 21:55:04 -08002171
2172 bool happened = false;
2173 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08002174 configuration::GetChannel(loop2->configuration(), "/test",
2175 "aos.TestMessage", "", nullptr),
Austin Schuha9df9ad2021-06-16 14:49:39 -07002176 [this, &kMessage, &fetcher, &happened](const Context &context,
2177 const void *message) {
Austin Schuh67420a42019-12-21 21:55:04 -08002178 happened = true;
Austin Schuha9df9ad2021-06-16 14:49:39 -07002179 EXPECT_EQ(
2180 kMessage.span(),
2181 absl::Span<const uint8_t>(
2182 reinterpret_cast<const uint8_t *>(message), context.size));
2183 EXPECT_EQ(message, context.data);
Austin Schuh67420a42019-12-21 21:55:04 -08002184
2185 ASSERT_TRUE(fetcher->Fetch());
2186
Austin Schuha9df9ad2021-06-16 14:49:39 -07002187 EXPECT_EQ(kMessage.span(),
2188 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
2189 fetcher->context().data),
2190 fetcher->context().size));
Austin Schuh67420a42019-12-21 21:55:04 -08002191
2192 this->Exit();
2193 });
2194
2195 EXPECT_FALSE(happened);
2196 Run();
2197 EXPECT_TRUE(happened);
2198}
2199
Austin Schuhad154822019-12-27 15:45:13 -08002200// Tests that a raw watcher and raw fetcher can receive messages from a raw
Brian Silvermanbf889922021-11-10 12:41:57 -08002201// sender without messing up offsets, using the RawSpan overload.
2202TEST_P(AbstractEventLoopTest, RawBasicSharedSpan) {
2203 auto loop1 = Make();
2204 auto loop2 = MakePrimary();
2205 auto loop3 = Make();
2206
2207 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2208 JsonToFlatbuffer<TestMessage>("{}");
2209
2210 std::unique_ptr<aos::RawSender> sender =
2211 loop1->MakeRawSender(configuration::GetChannel(
2212 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
2213
2214 std::unique_ptr<aos::RawFetcher> fetcher =
2215 loop3->MakeRawFetcher(configuration::GetChannel(
2216 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
2217
2218 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002219 EXPECT_EQ(sender->Send(std::make_shared<absl::Span<const uint8_t>>(
2220 kMessage.span().data(), kMessage.span().size())),
2221 RawSender::Error::kOk);
Brian Silvermanbf889922021-11-10 12:41:57 -08002222 });
2223
2224 bool happened = false;
2225 loop2->MakeRawWatcher(
2226 configuration::GetChannel(loop2->configuration(), "/test",
2227 "aos.TestMessage", "", nullptr),
2228 [this, &kMessage, &fetcher, &happened](const Context &context,
2229 const void *message) {
2230 happened = true;
2231 EXPECT_EQ(
2232 kMessage.span(),
2233 absl::Span<const uint8_t>(
2234 reinterpret_cast<const uint8_t *>(message), context.size));
2235 EXPECT_EQ(message, context.data);
2236
2237 ASSERT_TRUE(fetcher->Fetch());
2238
2239 EXPECT_EQ(kMessage.span(),
2240 absl::Span<const uint8_t>(reinterpret_cast<const uint8_t *>(
2241 fetcher->context().data),
2242 fetcher->context().size));
2243
2244 this->Exit();
2245 });
2246
2247 EXPECT_FALSE(happened);
2248 Run();
2249 EXPECT_TRUE(happened);
2250}
2251
2252// Tests that a raw watcher and raw fetcher can receive messages from a raw
Austin Schuhad154822019-12-27 15:45:13 -08002253// sender with remote times filled out.
2254TEST_P(AbstractEventLoopTest, RawRemoteTimes) {
2255 auto loop1 = Make();
2256 auto loop2 = MakePrimary();
2257 auto loop3 = Make();
2258
Austin Schuha9df9ad2021-06-16 14:49:39 -07002259 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2260 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08002261
2262 const aos::monotonic_clock::time_point monotonic_remote_time =
2263 aos::monotonic_clock::time_point(chrono::seconds(1501));
2264 const aos::realtime_clock::time_point realtime_remote_time =
2265 aos::realtime_clock::time_point(chrono::seconds(3132));
Austin Schuhb5c6f972021-03-14 21:53:07 -07002266 const uint32_t remote_queue_index = 0x254971;
Austin Schuha9012be2021-07-21 15:19:11 -07002267 const UUID source_boot_uuid = UUID::Random();
Austin Schuhad154822019-12-27 15:45:13 -08002268
2269 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002270 loop1->MakeRawSender(configuration::GetChannel(
2271 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08002272
2273 std::unique_ptr<aos::RawFetcher> fetcher =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002274 loop3->MakeRawFetcher(configuration::GetChannel(
2275 loop3->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08002276
2277 loop2->OnRun([&]() {
milind1f1dca32021-07-03 13:50:07 -07002278 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size(),
2279 monotonic_remote_time, realtime_remote_time,
2280 remote_queue_index, source_boot_uuid),
2281 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08002282 });
2283
2284 bool happened = false;
2285 loop2->MakeRawWatcher(
Tyler Chatow67ddb032020-01-12 14:30:04 -08002286 configuration::GetChannel(loop2->configuration(), "/test",
2287 "aos.TestMessage", "", nullptr),
Austin Schuha9012be2021-07-21 15:19:11 -07002288 [this, monotonic_remote_time, realtime_remote_time, source_boot_uuid,
Austin Schuhb5c6f972021-03-14 21:53:07 -07002289 remote_queue_index, &fetcher,
2290 &happened](const Context &context, const void * /*message*/) {
Austin Schuhad154822019-12-27 15:45:13 -08002291 happened = true;
2292 EXPECT_EQ(monotonic_remote_time, context.monotonic_remote_time);
2293 EXPECT_EQ(realtime_remote_time, context.realtime_remote_time);
Austin Schuha9012be2021-07-21 15:19:11 -07002294 EXPECT_EQ(source_boot_uuid, context.source_boot_uuid);
Austin Schuhb5c6f972021-03-14 21:53:07 -07002295 EXPECT_EQ(remote_queue_index, context.remote_queue_index);
Austin Schuhad154822019-12-27 15:45:13 -08002296
2297 ASSERT_TRUE(fetcher->Fetch());
2298 EXPECT_EQ(monotonic_remote_time,
2299 fetcher->context().monotonic_remote_time);
2300 EXPECT_EQ(realtime_remote_time,
2301 fetcher->context().realtime_remote_time);
2302
2303 this->Exit();
2304 });
2305
2306 EXPECT_FALSE(happened);
2307 Run();
2308 EXPECT_TRUE(happened);
2309}
2310
2311// Tests that a raw sender fills out sent data.
2312TEST_P(AbstractEventLoopTest, RawSenderSentData) {
2313 auto loop1 = MakePrimary();
2314
Austin Schuha9df9ad2021-06-16 14:49:39 -07002315 const FlatbufferDetachedBuffer<TestMessage> kMessage =
2316 JsonToFlatbuffer<TestMessage>("{}");
Austin Schuhad154822019-12-27 15:45:13 -08002317
2318 std::unique_ptr<aos::RawSender> sender =
Tyler Chatow67ddb032020-01-12 14:30:04 -08002319 loop1->MakeRawSender(configuration::GetChannel(
2320 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuhad154822019-12-27 15:45:13 -08002321
Tyler Chatow67ddb032020-01-12 14:30:04 -08002322 const aos::monotonic_clock::time_point monotonic_now = loop1->monotonic_now();
2323 const aos::realtime_clock::time_point realtime_now = loop1->realtime_now();
Austin Schuhad154822019-12-27 15:45:13 -08002324
milind1f1dca32021-07-03 13:50:07 -07002325 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2326 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08002327
2328 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
2329 EXPECT_LE(sender->monotonic_sent_time(),
2330 monotonic_now + chrono::milliseconds(100));
2331 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
2332 EXPECT_LE(sender->realtime_sent_time(),
2333 realtime_now + chrono::milliseconds(100));
2334 EXPECT_EQ(sender->sent_queue_index(), 0u);
2335
milind1f1dca32021-07-03 13:50:07 -07002336 EXPECT_EQ(sender->Send(kMessage.span().data(), kMessage.span().size()),
2337 RawSender::Error::kOk);
Austin Schuhad154822019-12-27 15:45:13 -08002338
2339 EXPECT_GE(sender->monotonic_sent_time(), monotonic_now);
2340 EXPECT_LE(sender->monotonic_sent_time(),
2341 monotonic_now + chrono::milliseconds(100));
2342 EXPECT_GE(sender->realtime_sent_time(), realtime_now);
2343 EXPECT_LE(sender->realtime_sent_time(),
2344 realtime_now + chrono::milliseconds(100));
2345 EXPECT_EQ(sender->sent_queue_index(), 1u);
2346}
2347
Austin Schuh217a9782019-12-21 23:02:50 -08002348// Tests that not setting up nodes results in no node.
2349TEST_P(AbstractEventLoopTest, NoNode) {
2350 auto loop1 = Make();
2351 auto loop2 = MakePrimary();
2352
2353 EXPECT_EQ(loop1->node(), nullptr);
2354 EXPECT_EQ(loop2->node(), nullptr);
2355}
2356
2357// Tests that setting up nodes results in node being set.
2358TEST_P(AbstractEventLoopTest, Node) {
2359 EnableNodes("me");
2360
2361 auto loop1 = Make();
2362 auto loop2 = MakePrimary();
2363
2364 EXPECT_NE(loop1->node(), nullptr);
2365 EXPECT_NE(loop2->node(), nullptr);
2366}
2367
2368// Tests that watchers work with a node setup.
2369TEST_P(AbstractEventLoopTest, NodeWatcher) {
2370 EnableNodes("me");
2371
2372 auto loop1 = Make();
2373 auto loop2 = Make();
2374 loop1->MakeWatcher("/test", [](const TestMessage &) {});
Tyler Chatow67ddb032020-01-12 14:30:04 -08002375 loop2->MakeRawWatcher(
2376 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
2377 nullptr),
2378 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08002379}
2380
Brian Silverman454bc112020-03-05 14:21:25 -08002381// Tests that no-arg watchers work with a node setup.
2382TEST_P(AbstractEventLoopTest, NodeNoArgWatcher) {
2383 EnableNodes("me");
2384
2385 auto loop1 = Make();
2386 auto loop2 = Make();
2387 loop1->MakeWatcher("/test", [](const TestMessage &) {});
2388 loop2->MakeRawNoArgWatcher(
2389 configuration::GetChannel(configuration(), "/test", "aos.TestMessage", "",
2390 nullptr),
2391 [](const Context &) {});
2392}
2393
Austin Schuh217a9782019-12-21 23:02:50 -08002394// Tests that fetcher work with a node setup.
2395TEST_P(AbstractEventLoopTest, NodeFetcher) {
2396 EnableNodes("me");
2397 auto loop1 = Make();
2398
2399 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
Tyler Chatow67ddb032020-01-12 14:30:04 -08002400 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
2401 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08002402}
2403
2404// Tests that sender work with a node setup.
2405TEST_P(AbstractEventLoopTest, NodeSender) {
2406 EnableNodes("me");
2407 auto loop1 = Make();
2408
2409 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
2410}
2411
Austin Schuhcc6070c2020-10-10 20:25:56 -07002412// Tests that a non-realtime event loop timer is marked non-realtime.
2413TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopTimer) {
2414 auto loop1 = MakePrimary();
2415
2416 // Add a timer to actually quit.
2417 auto test_timer = loop1->AddTimer([this]() {
2418 CheckNotRealtime();
2419 this->Exit();
2420 });
2421
2422 loop1->OnRun([&test_timer, &loop1]() {
2423 CheckNotRealtime();
2424 test_timer->Setup(loop1->monotonic_now(), ::std::chrono::milliseconds(100));
2425 });
2426
2427 Run();
2428}
2429
2430// Tests that a realtime event loop timer is marked realtime.
Austin Schuh9b1d6282022-06-10 17:03:21 -07002431TEST_P(AbstractEventLoopTest, RealtimeSend) {
2432 auto loop1 = MakePrimary();
2433
2434 loop1->SetRuntimeRealtimePriority(1);
2435
2436 auto sender = loop1->MakeSender<TestMessage>("/test2");
2437
2438 loop1->OnRun([&]() {
2439 CheckRealtime();
2440
2441 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2442 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
2443 builder.add_value(200);
2444 msg.CheckOk(msg.Send(builder.Finish()));
2445
2446 this->Exit();
2447 });
2448
2449 Run();
2450}
2451
2452// Tests that a realtime event loop timer is marked realtime.
Austin Schuhcc6070c2020-10-10 20:25:56 -07002453TEST_P(AbstractEventLoopTest, RealtimeEventLoopTimer) {
2454 auto loop1 = MakePrimary();
2455
2456 loop1->SetRuntimeRealtimePriority(1);
2457
2458 // Add a timer to actually quit.
2459 auto test_timer = loop1->AddTimer([this]() {
2460 CheckRealtime();
2461 this->Exit();
2462 });
2463
2464 loop1->OnRun([&test_timer, &loop1]() {
2465 CheckRealtime();
2466 test_timer->Setup(loop1->monotonic_now(), ::std::chrono::milliseconds(100));
2467 });
2468
2469 Run();
2470}
2471
2472// Tests that a non-realtime event loop phased loop is marked non-realtime.
2473TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopPhasedLoop) {
2474 auto loop1 = MakePrimary();
2475
2476 // Add a timer to actually quit.
2477 loop1->AddPhasedLoop(
2478 [this](int) {
2479 CheckNotRealtime();
2480 this->Exit();
2481 },
2482 chrono::seconds(1), chrono::seconds(0));
2483
2484 Run();
2485}
2486
2487// Tests that a realtime event loop phased loop is marked realtime.
2488TEST_P(AbstractEventLoopTest, RealtimeEventLoopPhasedLoop) {
2489 auto loop1 = MakePrimary();
2490
2491 loop1->SetRuntimeRealtimePriority(1);
2492
2493 // Add a timer to actually quit.
2494 loop1->AddPhasedLoop(
2495 [this](int) {
2496 CheckRealtime();
2497 this->Exit();
2498 },
2499 chrono::seconds(1), chrono::seconds(0));
2500
2501 Run();
2502}
2503
2504// Tests that a non-realtime event loop watcher is marked non-realtime.
2505TEST_P(AbstractEventLoopTest, NonRealtimeEventLoopWatcher) {
2506 auto loop1 = MakePrimary();
2507 auto loop2 = Make();
2508
2509 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
2510
2511 loop1->OnRun([&]() {
2512 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2513 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07002514 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07002515 });
2516
2517 loop1->MakeWatcher("/test", [&](const TestMessage &) {
2518 CheckNotRealtime();
2519 this->Exit();
2520 });
2521
2522 Run();
2523}
2524
2525// Tests that a realtime event loop watcher is marked realtime.
2526TEST_P(AbstractEventLoopTest, RealtimeEventLoopWatcher) {
2527 auto loop1 = MakePrimary();
2528 auto loop2 = Make();
2529
2530 loop1->SetRuntimeRealtimePriority(1);
2531
2532 aos::Sender<TestMessage> sender = loop2->MakeSender<TestMessage>("/test");
2533
2534 loop1->OnRun([&]() {
2535 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
2536 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
milind1f1dca32021-07-03 13:50:07 -07002537 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuhcc6070c2020-10-10 20:25:56 -07002538 });
2539
2540 loop1->MakeWatcher("/test", [&](const TestMessage &) {
2541 CheckRealtime();
2542 this->Exit();
2543 });
2544
2545 Run();
2546}
2547
Austin Schuha9012be2021-07-21 15:19:11 -07002548// Tests that event loop's context's monotonic time is set to a value on OnRun.
2549TEST_P(AbstractEventLoopTest, SetContextOnRun) {
2550 auto loop = MakePrimary();
2551
2552 // We want to check that monotonic event time is before monotonic now
2553 // called inside of callback, but after time point obtained callback.
2554 aos::monotonic_clock::time_point monotonic_event_time_on_run;
2555
2556 loop->OnRun([&]() {
2557 monotonic_event_time_on_run = loop->context().monotonic_event_time;
2558 EXPECT_LE(monotonic_event_time_on_run, loop->monotonic_now());
2559 EXPECT_EQ(loop->context().monotonic_remote_time, monotonic_clock::min_time);
2560 EXPECT_EQ(loop->context().realtime_event_time, realtime_clock::min_time);
2561 EXPECT_EQ(loop->context().realtime_remote_time, realtime_clock::min_time);
2562 EXPECT_EQ(loop->context().source_boot_uuid, loop->boot_uuid());
2563 EXPECT_EQ(loop->context().queue_index, 0xffffffffu);
2564 EXPECT_EQ(loop->context().size, 0u);
2565 EXPECT_EQ(loop->context().data, nullptr);
2566 EXPECT_EQ(loop->context().buffer_index, -1);
2567 });
2568
2569 EndEventLoop(loop.get(), ::std::chrono::milliseconds(200));
2570
2571 const aos::monotonic_clock::time_point before_run_time =
2572 loop->monotonic_now();
2573 Run();
2574 EXPECT_GE(monotonic_event_time_on_run, before_run_time);
2575}
2576
Austin Schuh217a9782019-12-21 23:02:50 -08002577// Tests that watchers fail when created on the wrong node.
2578TEST_P(AbstractEventLoopDeathTest, NodeWatcher) {
2579 EnableNodes("them");
2580
2581 auto loop1 = Make();
2582 auto loop2 = Make();
2583 EXPECT_DEATH({ loop1->MakeWatcher("/test", [](const TestMessage &) {}); },
2584 "node");
2585 EXPECT_DEATH(
2586 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08002587 loop2->MakeRawWatcher(
2588 configuration::GetChannel(configuration(), "/test",
2589 "aos.TestMessage", "", nullptr),
2590 [](const Context &, const void *) {});
Austin Schuh217a9782019-12-21 23:02:50 -08002591 },
2592 "node");
Brian Silverman454bc112020-03-05 14:21:25 -08002593 EXPECT_DEATH({ loop1->MakeNoArgWatcher<TestMessage>("/test", []() {}); },
2594 "node");
2595 EXPECT_DEATH(
2596 {
2597 loop2->MakeRawNoArgWatcher(
2598 configuration::GetChannel(configuration(), "/test",
2599 "aos.TestMessage", "", nullptr),
2600 [](const Context &) {});
2601 },
2602 "node");
Austin Schuh217a9782019-12-21 23:02:50 -08002603}
2604
2605// Tests that fetchers fail when created on the wrong node.
2606TEST_P(AbstractEventLoopDeathTest, NodeFetcher) {
2607 EnableNodes("them");
2608 auto loop1 = Make();
2609
2610 EXPECT_DEATH({ auto fetcher = loop1->MakeFetcher<TestMessage>("/test"); },
2611 "node");
2612 EXPECT_DEATH(
2613 {
Tyler Chatow67ddb032020-01-12 14:30:04 -08002614 auto raw_fetcher = loop1->MakeRawFetcher(configuration::GetChannel(
2615 configuration(), "/test", "aos.TestMessage", "", nullptr));
Austin Schuh217a9782019-12-21 23:02:50 -08002616 },
2617 "node");
2618}
2619
2620// Tests that senders fail when created on the wrong node.
2621TEST_P(AbstractEventLoopDeathTest, NodeSender) {
2622 EnableNodes("them");
2623 auto loop1 = Make();
2624
2625 EXPECT_DEATH(
2626 {
2627 aos::Sender<TestMessage> sender =
2628 loop1->MakeSender<TestMessage>("/test");
2629 },
2630 "node");
2631
2632 // Note: Creating raw senders is always supported. Right now, this lets us
2633 // use them to create message_gateway.
2634}
2635
Brian Silverman341b57e2020-06-23 16:23:18 -07002636// Tests creating multiple Builders from a single Sender at the same time.
2637TEST_P(AbstractEventLoopDeathTest, MultipleBuilders) {
2638 auto loop1 = Make();
2639 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
2640
2641 { auto builder = sender.MakeBuilder(); }
2642 {
2643 auto builder = sender.MakeBuilder();
2644 builder.MakeBuilder<TestMessage>().Finish();
2645 }
2646 {
2647 // Creating this after the first one was destroyed should be fine.
2648 auto builder = sender.MakeBuilder();
2649 builder.MakeBuilder<TestMessage>().Finish();
2650 // But not a second one.
2651 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
2652 "May not overwrite in-use allocator");
2653 }
2654
2655 FlatbufferDetachedBuffer<TestMessage> detached =
2656 flatbuffers::DetachedBuffer();
2657 {
2658 auto builder = sender.MakeBuilder();
2659 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
2660 }
2661 {
2662 // This is the second one, after the detached one, so it should fail.
2663 EXPECT_DEATH(sender.MakeBuilder().MakeBuilder<TestMessage>().Finish(),
2664 "May not overwrite in-use allocator");
2665 }
2666
2667 // Clear the detached one, and then we should be able to create another.
2668 detached = flatbuffers::DetachedBuffer();
2669 {
2670 auto builder = sender.MakeBuilder();
2671 builder.MakeBuilder<TestMessage>().Finish();
2672 }
2673
2674 // And then detach another one.
2675 {
2676 auto builder = sender.MakeBuilder();
2677 detached = builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
2678 }
2679}
2680
2681// Tests sending a buffer detached from a different builder.
2682TEST_P(AbstractEventLoopDeathTest, WrongDetachedBuffer) {
2683 auto loop1 = Make();
2684 aos::Sender<TestMessage> sender1 = loop1->MakeSender<TestMessage>("/test");
2685 aos::Sender<TestMessage> sender2 = loop1->MakeSender<TestMessage>("/test");
2686
2687 auto builder = sender1.MakeBuilder();
2688 FlatbufferDetachedBuffer<TestMessage> detached =
2689 builder.Detach(builder.MakeBuilder<TestMessage>().Finish());
milind1f1dca32021-07-03 13:50:07 -07002690 EXPECT_DEATH(sender2.CheckOk(sender2.SendDetached(std::move(detached))),
Brian Silverman341b57e2020-06-23 16:23:18 -07002691 "May only send the buffer detached from this Sender");
2692}
2693
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -07002694int TestChannelFrequency(EventLoop *event_loop) {
2695 return event_loop->GetChannel<TestMessage>("/test")->frequency();
2696}
2697
2698int TestChannelQueueSize(EventLoop *event_loop) {
2699 const int frequency = TestChannelFrequency(event_loop);
2700 const auto channel_storage_duration = std::chrono::nanoseconds(
2701 event_loop->configuration()->channel_storage_duration());
2702 const int queue_size =
2703 frequency * std::chrono::duration_cast<std::chrono::duration<double>>(
2704 channel_storage_duration)
2705 .count();
2706
2707 return queue_size;
2708}
2709
2710RawSender::Error SendTestMessage(aos::Sender<TestMessage> &sender) {
2711 aos::Sender<TestMessage>::Builder builder = sender.MakeBuilder();
2712 TestMessage::Builder test_message_builder =
2713 builder.MakeBuilder<TestMessage>();
2714 test_message_builder.add_value(0);
2715 return builder.Send(test_message_builder.Finish());
2716}
2717
2718// Test that sending messages too fast returns
2719// RawSender::Error::kMessagesSentTooFast.
2720TEST_P(AbstractEventLoopTest, SendingMessagesTooFast) {
2721 auto event_loop = MakePrimary();
2722
2723 auto sender = event_loop->MakeSender<TestMessage>("/test");
2724
2725 // Send one message in the beginning, then wait until the
2726 // channel_storage_duration is almost done and start sending messages rapidly,
2727 // having some come in the next chanel_storage_duration. The queue_size is
2728 // 1600, so the 1601st message will be the last valid one (the initial message
2729 // having being sent more than a channel_storage_duration ago), and trying to
2730 // send the 1602nd message should return
2731 // RawSender::Error::kMessagesSentTooFast.
2732 EXPECT_EQ(SendTestMessage(sender), RawSender::Error::kOk);
2733 int msgs_sent = 1;
2734 const int queue_size = TestChannelQueueSize(event_loop.get());
2735
2736 const auto timer = event_loop->AddTimer([&]() {
2737 const bool done = (msgs_sent == queue_size + 1);
2738 ASSERT_EQ(
2739 SendTestMessage(sender),
2740 done ? RawSender::Error::kMessagesSentTooFast : RawSender::Error::kOk);
2741 msgs_sent++;
2742 if (done) {
2743 Exit();
2744 }
2745 });
2746
2747 const auto kRepeatOffset = std::chrono::milliseconds(1);
2748 const auto base_offset =
2749 std::chrono::nanoseconds(
2750 event_loop->configuration()->channel_storage_duration()) -
2751 (kRepeatOffset * (queue_size / 2));
2752 event_loop->OnRun([&event_loop, &timer, &base_offset, &kRepeatOffset]() {
2753 timer->Setup(event_loop->monotonic_now() + base_offset, kRepeatOffset);
2754 });
2755
2756 Run();
2757}
2758
2759// Tests that we are able to send messages successfully after sending messages
2760// too fast and waiting while continuously attempting to send messages.
2761// Also tests that SendFailureCounter is working correctly in this
2762// situation
2763TEST_P(AbstractEventLoopTest, SendingAfterSendingTooFast) {
2764 auto event_loop = MakePrimary();
2765
2766 auto sender = event_loop->MakeSender<TestMessage>("/test");
2767
2768 // We are sending messages at 1 kHz, so we will be sending too fast after
2769 // queue_size (1600) ms. After this, keep sending messages, and exactly a
2770 // channel storage duration (2s) after we send the first message we should
2771 // be able to successfully send a message.
2772
2773 const monotonic_clock::duration kInterval = std::chrono::milliseconds(1);
2774 const monotonic_clock::duration channel_storage_duration =
2775 std::chrono::nanoseconds(
2776 event_loop->configuration()->channel_storage_duration());
2777 const int queue_size = TestChannelQueueSize(event_loop.get());
2778
2779 int msgs_sent = 0;
2780 SendFailureCounter counter;
2781 auto start = monotonic_clock::min_time;
2782
2783 event_loop->AddPhasedLoop(
2784 [&](int) {
2785 const auto actual_err = SendTestMessage(sender);
2786 const bool done_waiting = (start != monotonic_clock::min_time &&
2787 sender.monotonic_sent_time() >=
2788 (start + channel_storage_duration));
2789 const auto expected_err =
2790 (msgs_sent < queue_size || done_waiting
2791 ? RawSender::Error::kOk
2792 : RawSender::Error::kMessagesSentTooFast);
2793
2794 if (start == monotonic_clock::min_time) {
2795 start = sender.monotonic_sent_time();
2796 }
2797
2798 ASSERT_EQ(actual_err, expected_err);
2799 counter.Count(actual_err);
2800 msgs_sent++;
2801
2802 EXPECT_EQ(counter.failures(),
2803 msgs_sent <= queue_size
2804 ? 0
2805 : (msgs_sent - queue_size) -
2806 (actual_err == RawSender::Error::kOk ? 1 : 0));
2807 EXPECT_EQ(counter.just_failed(), actual_err != RawSender::Error::kOk);
2808
2809 if (done_waiting) {
2810 Exit();
2811 }
2812 },
2813 kInterval);
2814 Run();
2815}
2816
2817// Tests that RawSender::Error::kMessagesSentTooFast is returned
2818// when messages are sent too fast from senders in different loops
2819TEST_P(AbstractEventLoopTest, SendingTooFastWithMultipleLoops) {
2820 auto loop1 = MakePrimary();
2821 auto loop2 = Make();
2822
2823 auto sender1 = loop1->MakeSender<TestMessage>("/test");
2824 auto sender2 = loop2->MakeSender<TestMessage>("/test");
2825
2826 // Send queue_size messages split between the senders.
2827 const int queue_size = TestChannelQueueSize(loop1.get());
2828 for (int i = 0; i < queue_size / 2; i++) {
2829 ASSERT_EQ(SendTestMessage(sender1), RawSender::Error::kOk);
2830 ASSERT_EQ(SendTestMessage(sender2), RawSender::Error::kOk);
2831 }
2832
2833 // Since queue_size messages have been sent, this should return an error
2834 EXPECT_EQ(SendTestMessage(sender2), RawSender::Error::kMessagesSentTooFast);
2835}
2836
Parker Schuhe4a70d62017-12-27 20:10:20 -08002837} // namespace testing
2838} // namespace aos