blob: 01ca92b2af1e226883c75d751020bbb5535ce638 [file] [log] [blame]
Alex Perrycb7da4b2019-08-28 19:35:56 -07001#include "aos/events/shm_event_loop.h"
Parker Schuhe4a70d62017-12-27 20:10:20 -08002
Austin Schuh5f1cc5c2019-12-01 18:01:11 -08003#include <string_view>
4
Alex Perrycb7da4b2019-08-28 19:35:56 -07005#include "aos/events/event_loop_param_test.h"
Austin Schuha94e1002021-07-21 15:45:21 -07006#include "aos/events/test_message_generated.h"
7#include "aos/network/team_number.h"
Austin Schuh62288252020-11-18 23:26:04 -08008#include "aos/realtime.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -07009#include "glog/logging.h"
Parker Schuhe4a70d62017-12-27 20:10:20 -080010#include "gtest/gtest.h"
11
12namespace aos {
13namespace testing {
14namespace {
Austin Schuh3115a202019-05-27 21:02:14 -070015namespace chrono = ::std::chrono;
Parker Schuhe4a70d62017-12-27 20:10:20 -080016
17class ShmEventLoopTestFactory : public EventLoopTestFactory {
18 public:
Alex Perrycb7da4b2019-08-28 19:35:56 -070019 ShmEventLoopTestFactory() {
20 // Put all the queue files in ${TEST_TMPDIR} if it is set, otherwise
21 // everything will be reusing /dev/shm when sharded.
22 char *test_tmpdir = getenv("TEST_TMPDIR");
23 if (test_tmpdir != nullptr) {
24 FLAGS_shm_base = std::string(test_tmpdir) + "/aos";
25 }
26
27 // Clean up anything left there before.
Austin Schuh8902fa52021-03-14 22:39:24 -070028 unlink((FLAGS_shm_base + "/test/aos.TestMessage.v4").c_str());
29 unlink((FLAGS_shm_base + "/test1/aos.TestMessage.v4").c_str());
30 unlink((FLAGS_shm_base + "/test2/aos.TestMessage.v4").c_str());
31 unlink((FLAGS_shm_base + "/test2/aos.TestMessage.v4").c_str());
32 unlink((FLAGS_shm_base + "/aos/aos.timing.Report.v4").c_str());
33 unlink((FLAGS_shm_base + "/aos/aos.logging.LogMessageFbs.v4").c_str());
Alex Perrycb7da4b2019-08-28 19:35:56 -070034 }
35
Austin Schuh217a9782019-12-21 23:02:50 -080036 ~ShmEventLoopTestFactory() { FLAGS_override_hostname = ""; }
37
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080038 ::std::unique_ptr<EventLoop> Make(std::string_view name) override {
Austin Schuh217a9782019-12-21 23:02:50 -080039 if (configuration()->has_nodes()) {
Austin Schuh898f4972020-01-11 17:21:25 -080040 FLAGS_override_hostname =
41 std::string(my_node()->hostname()->string_view());
Austin Schuh217a9782019-12-21 23:02:50 -080042 }
43 ::std::unique_ptr<ShmEventLoop> loop(new ShmEventLoop(configuration()));
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080044 loop->set_name(name);
Austin Schuh217a9782019-12-21 23:02:50 -080045 return std::move(loop);
Parker Schuhe4a70d62017-12-27 20:10:20 -080046 }
47
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080048 ::std::unique_ptr<EventLoop> MakePrimary(std::string_view name) override {
Austin Schuh217a9782019-12-21 23:02:50 -080049 if (configuration()->has_nodes()) {
Austin Schuh898f4972020-01-11 17:21:25 -080050 FLAGS_override_hostname =
51 std::string(my_node()->hostname()->string_view());
Austin Schuh217a9782019-12-21 23:02:50 -080052 }
Austin Schuh44019f92019-05-19 19:58:27 -070053 ::std::unique_ptr<ShmEventLoop> loop =
Alex Perrycb7da4b2019-08-28 19:35:56 -070054 ::std::unique_ptr<ShmEventLoop>(new ShmEventLoop(configuration()));
Austin Schuh44019f92019-05-19 19:58:27 -070055 primary_event_loop_ = loop.get();
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080056 loop->set_name(name);
57 return std::move(loop);
Austin Schuh44019f92019-05-19 19:58:27 -070058 }
59
Alex Perrycb7da4b2019-08-28 19:35:56 -070060 void Run() override { CHECK_NOTNULL(primary_event_loop_)->Run(); }
Austin Schuh44019f92019-05-19 19:58:27 -070061
Alex Perrycb7da4b2019-08-28 19:35:56 -070062 void Exit() override { CHECK_NOTNULL(primary_event_loop_)->Exit(); }
Austin Schuh9fe68f72019-08-10 19:32:03 -070063
Austin Schuh52d325c2019-06-23 18:59:06 -070064 void SleepFor(::std::chrono::nanoseconds duration) override {
65 ::std::this_thread::sleep_for(duration);
66 }
67
Austin Schuh44019f92019-05-19 19:58:27 -070068 private:
Austin Schuh44019f92019-05-19 19:58:27 -070069 ::aos::ShmEventLoop *primary_event_loop_;
Parker Schuhe4a70d62017-12-27 20:10:20 -080070};
71
Austin Schuh6bae8252021-02-07 22:01:49 -080072auto CommonParameters() {
73 return ::testing::Combine(
74 ::testing::Values([]() { return new ShmEventLoopTestFactory(); }),
75 ::testing::Values(ReadMethod::COPY, ReadMethod::PIN),
76 ::testing::Values(DoTimingReports::kYes, DoTimingReports::kNo));
77}
Parker Schuhe4a70d62017-12-27 20:10:20 -080078
James Kuszmaulf4bf9fe2021-05-10 22:58:24 -070079INSTANTIATE_TEST_SUITE_P(ShmEventLoopCommonTest, AbstractEventLoopTest,
Brian Silvermance418d02021-11-03 11:25:52 -070080 CommonParameters());
Brian Silverman77162972020-08-12 19:52:40 -070081
Brian Silvermance418d02021-11-03 11:25:52 -070082INSTANTIATE_TEST_SUITE_P(ShmEventLoopCommonDeathTest,
83 AbstractEventLoopDeathTest, CommonParameters());
Austin Schuh6b6dfa52019-06-12 20:16:20 -070084
Parker Schuhe4a70d62017-12-27 20:10:20 -080085} // namespace
James Kuszmaulc79768b2019-02-18 15:08:44 -080086
Austin Schuh3115a202019-05-27 21:02:14 -070087bool IsRealtime() {
88 int scheduler;
Alex Perrycb7da4b2019-08-28 19:35:56 -070089 PCHECK((scheduler = sched_getscheduler(0)) != -1);
90
Austin Schuh62288252020-11-18 23:26:04 -080091 {
92 // If we are RT, logging the scheduler will crash us. Mark that we just
93 // don't care.
94 aos::ScopedNotRealtime nrt;
95 LOG(INFO) << "scheduler is " << scheduler;
96 }
97
98 const bool result = scheduler == SCHED_FIFO || scheduler == SCHED_RR;
99 // Confirm that the scheduler matches AOS' interpretation of if we are
100 // realtime or not.
101 if (result) {
102 aos::CheckRealtime();
103 } else {
104 aos::CheckNotRealtime();
105 }
106 return result;
Austin Schuh3115a202019-05-27 21:02:14 -0700107}
James Kuszmaulc79768b2019-02-18 15:08:44 -0800108
Brian Silvermana5450a92020-08-12 19:59:57 -0700109class ShmEventLoopTest : public ::testing::TestWithParam<ReadMethod> {
110 public:
111 ShmEventLoopTest() {
112 if (GetParam() == ReadMethod::PIN) {
113 factory_.PinReads();
114 }
115 }
116
117 ShmEventLoopTestFactory *factory() { return &factory_; }
118
119 private:
120 ShmEventLoopTestFactory factory_;
121};
122
123using ShmEventLoopDeathTest = ShmEventLoopTest;
124
Austin Schuha94e1002021-07-21 15:45:21 -0700125// Tests that we don't leave the calling thread realtime when calling Send
126// before Run.
127TEST_P(ShmEventLoopTest, SendBeforeRun) {
128 auto loop = factory()->MakePrimary("primary");
129 loop->SetRuntimeRealtimePriority(1);
130
131 auto loop2 = factory()->Make("loop2");
132 loop2->SetRuntimeRealtimePriority(2);
133 loop2->MakeWatcher("/test", [](const TestMessage &) {});
134 // Need the other one running for its watcher to record in SHM that it wants
135 // wakers to boost their priority, so leave it running in a thread for this
136 // test.
137 std::thread loop2_thread(
138 [&loop2]() { static_cast<ShmEventLoop *>(loop2.get())->Run(); });
139 std::this_thread::sleep_for(std::chrono::milliseconds(100));
140
141 auto sender = loop->MakeSender<TestMessage>("/test");
142 EXPECT_FALSE(IsRealtime());
143 {
144 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
145 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
146 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700147 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuha94e1002021-07-21 15:45:21 -0700148 }
149 EXPECT_FALSE(IsRealtime());
150
151 static_cast<ShmEventLoop *>(loop2.get())->Exit();
152 loop2_thread.join();
153}
154
Austin Schuh3115a202019-05-27 21:02:14 -0700155// Tests that every handler type is realtime and runs. There are threads
156// involved and it's easy to miss one.
Brian Silvermana5450a92020-08-12 19:59:57 -0700157TEST_P(ShmEventLoopTest, AllHandlersAreRealtime) {
158 auto loop = factory()->MakePrimary("primary");
159 auto loop2 = factory()->Make("loop2");
Austin Schuh3115a202019-05-27 21:02:14 -0700160
161 loop->SetRuntimeRealtimePriority(1);
162
163 auto sender = loop2->MakeSender<TestMessage>("/test");
164
165 bool did_onrun = false;
166 bool did_timer = false;
167 bool did_watcher = false;
168
Brian Silvermana5450a92020-08-12 19:59:57 -0700169 auto timer = loop->AddTimer([this, &did_timer]() {
Austin Schuh3115a202019-05-27 21:02:14 -0700170 EXPECT_TRUE(IsRealtime());
171 did_timer = true;
Brian Silvermana5450a92020-08-12 19:59:57 -0700172 factory()->Exit();
Austin Schuh3115a202019-05-27 21:02:14 -0700173 });
174
175 loop->MakeWatcher("/test", [&did_watcher](const TestMessage &) {
176 EXPECT_TRUE(IsRealtime());
177 did_watcher = true;
178 });
179
180 loop->OnRun([&loop, &did_onrun, &sender, timer]() {
181 EXPECT_TRUE(IsRealtime());
182 did_onrun = true;
183 timer->Setup(loop->monotonic_now() + chrono::milliseconds(100));
Alex Perrycb7da4b2019-08-28 19:35:56 -0700184
185 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
186 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
187 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700188 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700189 });
James Kuszmaulc79768b2019-02-18 15:08:44 -0800190
Brian Silvermana5450a92020-08-12 19:59:57 -0700191 factory()->Run();
James Kuszmaulc79768b2019-02-18 15:08:44 -0800192
Austin Schuh3115a202019-05-27 21:02:14 -0700193 EXPECT_TRUE(did_onrun);
194 EXPECT_TRUE(did_timer);
195 EXPECT_TRUE(did_watcher);
James Kuszmaulc79768b2019-02-18 15:08:44 -0800196}
Austin Schuh52d325c2019-06-23 18:59:06 -0700197
198// Tests that missing a deadline inside the function still results in PhasedLoop
199// running at the right offset.
Brian Silvermana5450a92020-08-12 19:59:57 -0700200TEST_P(ShmEventLoopTest, DelayedPhasedLoop) {
201 auto loop1 = factory()->MakePrimary("primary");
Austin Schuh52d325c2019-06-23 18:59:06 -0700202
203 ::std::vector<::aos::monotonic_clock::time_point> times;
204
205 constexpr chrono::milliseconds kOffset = chrono::milliseconds(400);
206
207 loop1->AddPhasedLoop(
Brian Silvermana5450a92020-08-12 19:59:57 -0700208 [this, &times, &loop1, &kOffset](int count) {
Austin Schuh52d325c2019-06-23 18:59:06 -0700209 const ::aos::monotonic_clock::time_point monotonic_now =
210 loop1->monotonic_now();
211
212 // Compute our offset.
213 const ::aos::monotonic_clock::duration remainder =
214 monotonic_now.time_since_epoch() -
215 chrono::duration_cast<chrono::seconds>(
216 monotonic_now.time_since_epoch());
217
218 // Make sure we we are called near where we should be even when we
219 // delay.
220 constexpr chrono::milliseconds kEpsilon(200);
221 EXPECT_LT(remainder, kOffset + kEpsilon);
222 EXPECT_GT(remainder, kOffset - kEpsilon);
223
224 // Confirm that we see the missed count when we sleep.
225 if (times.size() == 0) {
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800226 CHECK_EQ(count, 1);
Austin Schuh52d325c2019-06-23 18:59:06 -0700227 } else {
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800228 CHECK_EQ(count, 3);
Austin Schuh52d325c2019-06-23 18:59:06 -0700229 }
230
231 times.push_back(loop1->monotonic_now());
232 if (times.size() == 2) {
Brian Silvermana5450a92020-08-12 19:59:57 -0700233 factory()->Exit();
Austin Schuh52d325c2019-06-23 18:59:06 -0700234 }
235
236 // Now, add a large delay. This should push us up to 3 cycles.
237 ::std::this_thread::sleep_for(chrono::milliseconds(2500));
238 },
239 chrono::seconds(1), kOffset);
240
Brian Silvermana5450a92020-08-12 19:59:57 -0700241 factory()->Run();
Austin Schuh52d325c2019-06-23 18:59:06 -0700242
243 EXPECT_EQ(times.size(), 2u);
244}
245
Brian Silverman5120afb2020-01-31 17:44:35 -0800246// Test GetWatcherSharedMemory in a few basic scenarios.
Brian Silvermana5450a92020-08-12 19:59:57 -0700247TEST_P(ShmEventLoopDeathTest, GetWatcherSharedMemory) {
248 auto generic_loop1 = factory()->MakePrimary("primary");
Brian Silverman5120afb2020-01-31 17:44:35 -0800249 ShmEventLoop *const loop1 = static_cast<ShmEventLoop *>(generic_loop1.get());
250 const auto channel = configuration::GetChannel(
251 loop1->configuration(), "/test", TestMessage::GetFullyQualifiedName(),
252 loop1->name(), loop1->node());
253
254 // First verify it handles an invalid channel reasonably.
255 EXPECT_DEATH(loop1->GetWatcherSharedMemory(channel),
256 "No watcher found for channel");
257
258 // Then, actually create a watcher, and verify it returns something sane.
Brian Silvermana5450a92020-08-12 19:59:57 -0700259 absl::Span<const char> shared_memory;
260 bool ran = false;
261 loop1->MakeWatcher("/test", [this, &shared_memory,
262 &ran](const TestMessage &message) {
263 EXPECT_FALSE(ran);
264 ran = true;
265 // If we're using pinning, then we can verify that the message is actually
266 // in the specified region.
267 if (GetParam() == ReadMethod::PIN) {
268 EXPECT_GE(reinterpret_cast<const char *>(&message),
269 shared_memory.begin());
270 EXPECT_LT(reinterpret_cast<const char *>(&message), shared_memory.end());
271 }
272 factory()->Exit();
273 });
274 shared_memory = loop1->GetWatcherSharedMemory(channel);
275 EXPECT_FALSE(shared_memory.empty());
276
277 auto loop2 = factory()->Make("sender");
278 auto sender = loop2->MakeSender<TestMessage>("/test");
279 generic_loop1->OnRun([&sender]() {
280 auto builder = sender.MakeBuilder();
281 TestMessage::Builder test_builder(*builder.fbb());
282 test_builder.add_value(1);
milind1f1dca32021-07-03 13:50:07 -0700283 builder.CheckOk(builder.Send(test_builder.Finish()));
Brian Silvermana5450a92020-08-12 19:59:57 -0700284 });
285 factory()->Run();
286 EXPECT_TRUE(ran);
Brian Silverman5120afb2020-01-31 17:44:35 -0800287}
288
Brian Silvermana5450a92020-08-12 19:59:57 -0700289TEST_P(ShmEventLoopTest, GetSenderSharedMemory) {
290 auto generic_loop1 = factory()->MakePrimary("primary");
Brian Silverman5120afb2020-01-31 17:44:35 -0800291 ShmEventLoop *const loop1 = static_cast<ShmEventLoop *>(generic_loop1.get());
292
Brian Silvermana5450a92020-08-12 19:59:57 -0700293 // Check that GetSenderSharedMemory returns non-null/non-empty memory span.
Brian Silverman5120afb2020-01-31 17:44:35 -0800294 auto sender = loop1->MakeSender<TestMessage>("/test");
Brian Silvermana5450a92020-08-12 19:59:57 -0700295 const absl::Span<char> shared_memory = loop1->GetSenderSharedMemory(&sender);
296 EXPECT_FALSE(shared_memory.empty());
297
298 auto builder = sender.MakeBuilder();
299 uint8_t *buffer;
300 builder.fbb()->CreateUninitializedVector(5, 1, &buffer);
301 EXPECT_GE(reinterpret_cast<char *>(buffer), shared_memory.begin());
302 EXPECT_LT(reinterpret_cast<char *>(buffer), shared_memory.end());
Brian Silverman5120afb2020-01-31 17:44:35 -0800303}
304
Brian Silvermana5450a92020-08-12 19:59:57 -0700305TEST_P(ShmEventLoopTest, GetFetcherPrivateMemory) {
306 auto generic_loop1 = factory()->MakePrimary("primary");
Brian Silverman6d2b3592020-06-18 14:40:15 -0700307 ShmEventLoop *const loop1 = static_cast<ShmEventLoop *>(generic_loop1.get());
308
Brian Silvermana5450a92020-08-12 19:59:57 -0700309 // Check that GetFetcherPrivateMemory returns non-null/non-empty memory span.
Brian Silverman6d2b3592020-06-18 14:40:15 -0700310 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
Brian Silvermana5450a92020-08-12 19:59:57 -0700311 const auto private_memory = loop1->GetFetcherPrivateMemory(&fetcher);
312 EXPECT_FALSE(private_memory.empty());
313
314 auto loop2 = factory()->Make("sender");
315 auto sender = loop2->MakeSender<TestMessage>("/test");
316 {
317 auto builder = sender.MakeBuilder();
318 TestMessage::Builder test_builder(*builder.fbb());
319 test_builder.add_value(1);
milind1f1dca32021-07-03 13:50:07 -0700320 builder.CheckOk(builder.Send(test_builder.Finish()));
Brian Silvermana5450a92020-08-12 19:59:57 -0700321 }
322
323 ASSERT_TRUE(fetcher.Fetch());
324 EXPECT_GE(fetcher.context().data, private_memory.begin());
325 EXPECT_LT(fetcher.context().data, private_memory.end());
Brian Silverman6d2b3592020-06-18 14:40:15 -0700326}
327
Brian Silverman0eaa1da2020-08-12 20:03:52 -0700328// Tests that corrupting the bytes around the data buffer results in a crash.
329TEST_P(ShmEventLoopDeathTest, OutOfBoundsWrite) {
330 auto loop1 = factory()->Make("loop1");
331 std::unique_ptr<aos::RawSender> sender =
332 loop1->MakeRawSender(configuration::GetChannel(
333 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
334 for (size_t i = 0; i < kChannelDataRedzone; ++i) {
335 SCOPED_TRACE(std::to_string(i));
336 EXPECT_DEATH(
337 {
338 ++static_cast<char *>(sender->data())[-1 - i];
milind1f1dca32021-07-03 13:50:07 -0700339 sender->CheckOk(sender->Send(0));
Brian Silverman0eaa1da2020-08-12 20:03:52 -0700340 },
341 "Somebody wrote outside the buffer of their message");
342 EXPECT_DEATH(
343 {
344 ++static_cast<char *>(sender->data())[sender->size() + i];
milind1f1dca32021-07-03 13:50:07 -0700345 sender->CheckOk(sender->Send(0));
Brian Silverman0eaa1da2020-08-12 20:03:52 -0700346 },
347 "Somebody wrote outside the buffer of their message");
348 }
349}
350
Brian Silvermance418d02021-11-03 11:25:52 -0700351// Tests that the next message not being available prints a helpful error in the
352// normal case.
353TEST_P(ShmEventLoopDeathTest, NextMessageNotAvailable) {
354 auto loop1 = factory()->MakePrimary("loop1");
355 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
356 auto loop2 = factory()->Make("loop2");
357 auto sender = loop2->MakeSender<TestMessage>("/test");
358 bool ran = false;
359 loop1->OnRun([this, &sender, &fetcher, &ran]() {
360 for (int i = 0; i < 2000; ++i) {
361 auto builder = sender.MakeBuilder();
362 TestMessage::Builder test_builder(*builder.fbb());
363 test_builder.add_value(0);
milind1f1dca32021-07-03 13:50:07 -0700364 builder.CheckOk(builder.Send(test_builder.Finish()));
Brian Silvermance418d02021-11-03 11:25:52 -0700365 }
366 EXPECT_DEATH(fetcher.FetchNext(),
367 "The next message is no longer "
368 "available.*\"/test\".*\"aos\\.TestMessage\"");
369 factory()->Exit();
370 ran = true;
371 });
372 factory()->Run();
373 EXPECT_TRUE(ran);
374}
375
376// Tests that the next message not being available prints a helpful error with
377// timing reports disabled.
378TEST_P(ShmEventLoopDeathTest, NextMessageNotAvailableNoTimingReports) {
379 auto loop1 = factory()->MakePrimary("loop1");
380 loop1->SkipTimingReport();
381 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
382 auto loop2 = factory()->Make("loop2");
383 auto sender = loop2->MakeSender<TestMessage>("/test");
384 bool ran = false;
385 loop1->OnRun([this, &sender, &fetcher, &ran]() {
386 for (int i = 0; i < 2000; ++i) {
387 auto builder = sender.MakeBuilder();
388 TestMessage::Builder test_builder(*builder.fbb());
389 test_builder.add_value(0);
milind1f1dca32021-07-03 13:50:07 -0700390 builder.CheckOk(builder.Send(test_builder.Finish()));
Brian Silvermance418d02021-11-03 11:25:52 -0700391 }
392 EXPECT_DEATH(fetcher.FetchNext(),
393 "The next message is no longer "
394 "available.*\"/test\".*\"aos\\.TestMessage\"");
395 factory()->Exit();
396 ran = true;
397 });
398 factory()->Run();
399 EXPECT_TRUE(ran);
400}
401
402// Tests that the next message not being available prints a helpful error even
403// when Run is never called.
404TEST_P(ShmEventLoopDeathTest, NextMessageNotAvailableNoRun) {
405 auto loop1 = factory()->MakePrimary("loop1");
406 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
407 auto loop2 = factory()->Make("loop2");
408 auto sender = loop2->MakeSender<TestMessage>("/test");
409 for (int i = 0; i < 2000; ++i) {
410 auto builder = sender.MakeBuilder();
411 TestMessage::Builder test_builder(*builder.fbb());
412 test_builder.add_value(0);
milind1f1dca32021-07-03 13:50:07 -0700413 builder.CheckOk(builder.Send(test_builder.Finish()));
Brian Silvermance418d02021-11-03 11:25:52 -0700414 }
415 EXPECT_DEATH(fetcher.FetchNext(),
416 "The next message is no longer "
417 "available.*\"/test\".*\"aos\\.TestMessage\"");
418}
419
420// Tests that the next message not being available prints a helpful error even
421// when Run is never called without timing reports.
422TEST_P(ShmEventLoopDeathTest, NextMessageNotAvailableNoRunNoTimingReports) {
423 auto loop1 = factory()->MakePrimary("loop1");
424 loop1->SkipTimingReport();
425 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
426 auto loop2 = factory()->Make("loop2");
427 auto sender = loop2->MakeSender<TestMessage>("/test");
428 for (int i = 0; i < 2000; ++i) {
429 auto builder = sender.MakeBuilder();
430 TestMessage::Builder test_builder(*builder.fbb());
431 test_builder.add_value(0);
milind1f1dca32021-07-03 13:50:07 -0700432 builder.CheckOk(builder.Send(test_builder.Finish()));
Brian Silvermance418d02021-11-03 11:25:52 -0700433 }
434 EXPECT_DEATH(fetcher.FetchNext(),
435 "The next message is no longer "
436 "available.*\"/test\".*\"aos\\.TestMessage\"");
437}
438
Austin Schuh39788ff2019-12-01 18:22:57 -0800439// TODO(austin): Test that missing a deadline with a timer recovers as expected.
440
James Kuszmaulf4bf9fe2021-05-10 22:58:24 -0700441INSTANTIATE_TEST_SUITE_P(ShmEventLoopCopyTest, ShmEventLoopTest,
Brian Silvermance418d02021-11-03 11:25:52 -0700442 ::testing::Values(ReadMethod::COPY));
James Kuszmaulf4bf9fe2021-05-10 22:58:24 -0700443INSTANTIATE_TEST_SUITE_P(ShmEventLoopPinTest, ShmEventLoopTest,
Brian Silvermance418d02021-11-03 11:25:52 -0700444 ::testing::Values(ReadMethod::PIN));
James Kuszmaulf4bf9fe2021-05-10 22:58:24 -0700445INSTANTIATE_TEST_SUITE_P(ShmEventLoopCopyDeathTest, ShmEventLoopDeathTest,
Brian Silvermance418d02021-11-03 11:25:52 -0700446 ::testing::Values(ReadMethod::COPY));
James Kuszmaulf4bf9fe2021-05-10 22:58:24 -0700447INSTANTIATE_TEST_SUITE_P(ShmEventLoopPinDeathTest, ShmEventLoopDeathTest,
Brian Silvermance418d02021-11-03 11:25:52 -0700448 ::testing::Values(ReadMethod::PIN));
Brian Silvermana5450a92020-08-12 19:59:57 -0700449
Parker Schuhe4a70d62017-12-27 20:10:20 -0800450} // namespace testing
451} // namespace aos