blob: 4db0c7dad62642f8a84ab8b79d4a4e10d53c0994 [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
Philipp Schrader790cb542023-07-05 21:06:52 -07005#include "glog/logging.h"
6#include "gtest/gtest.h"
7
Alex Perrycb7da4b2019-08-28 19:35:56 -07008#include "aos/events/event_loop_param_test.h"
Austin Schuha94e1002021-07-21 15:45:21 -07009#include "aos/events/test_message_generated.h"
10#include "aos/network/team_number.h"
Austin Schuh62288252020-11-18 23:26:04 -080011#include "aos/realtime.h"
Parker Schuhe4a70d62017-12-27 20:10:20 -080012
Stephan Pleinesf63bde82024-01-13 15:59:33 -080013namespace aos::testing {
Parker Schuhe4a70d62017-12-27 20:10:20 -080014namespace {
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.
Philipp Schrader81fa3fb2023-09-17 18:58:35 -070028 unlink((FLAGS_shm_base + "/test/aos.TestMessage.v6").c_str());
29 unlink((FLAGS_shm_base + "/test1/aos.TestMessage.v6").c_str());
30 unlink((FLAGS_shm_base + "/test2/aos.TestMessage.v6").c_str());
31 unlink((FLAGS_shm_base + "/test2/aos.TestMessage.v6").c_str());
32 unlink((FLAGS_shm_base + "/aos/aos.timing.Report.v6").c_str());
33 unlink((FLAGS_shm_base + "/aos/aos.logging.LogMessageFbs.v6").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);
James Kuszmaul9776b392023-01-14 14:08:08 -080045 return 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);
James Kuszmaul9776b392023-01-14 14:08:08 -080057 return 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
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -0700119 // Helper functions for testing when a fetcher cannot fetch the next message
120 // because it was overwritten
121 void TestNextMessageNotAvailable(const bool skip_timing_report) {
122 auto loop1 = factory()->MakePrimary("loop1");
123 if (skip_timing_report) {
124 loop1->SkipTimingReport();
125 }
126 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
127 auto loop2 = factory()->Make("loop2");
128 auto sender = loop2->MakeSender<TestMessage>("/test");
129 bool ran = false;
130 loop1->AddPhasedLoop(
131 [&sender](int) {
132 auto builder = sender.MakeBuilder();
133 TestMessage::Builder test_builder(*builder.fbb());
134 test_builder.add_value(0);
135 builder.CheckOk(builder.Send(test_builder.Finish()));
136 },
137 std::chrono::milliseconds(2));
138 loop1
139 ->AddTimer([this, &fetcher, &ran]() {
140 EXPECT_DEATH(fetcher.FetchNext(),
141 "The next message is no longer "
142 "available.*\"/test\".*\"aos\\.TestMessage\"");
143 factory()->Exit();
144 ran = true;
145 })
Philipp Schradera6712522023-07-05 20:25:11 -0700146 ->Schedule(loop1->monotonic_now() + std::chrono::seconds(4));
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -0700147 factory()->Run();
148 EXPECT_TRUE(ran);
149 }
150 void TestNextMessageNotAvailableNoRun(const bool skip_timing_report) {
151 auto loop1 = factory()->MakePrimary("loop1");
152 if (skip_timing_report) {
153 loop1->SkipTimingReport();
154 }
155 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
156 auto loop2 = factory()->Make("loop2");
157 auto sender = loop2->MakeSender<TestMessage>("/test");
158 time::PhasedLoop phased_loop(std::chrono::milliseconds(2),
159 loop2->monotonic_now());
160 for (int i = 0; i < 2000; ++i) {
161 auto builder = sender.MakeBuilder();
162 TestMessage::Builder test_builder(*builder.fbb());
163 test_builder.add_value(0);
164 builder.CheckOk(builder.Send(test_builder.Finish()));
165 phased_loop.SleepUntilNext();
166 }
167 EXPECT_DEATH(fetcher.FetchNext(),
168 "The next message is no longer "
169 "available.*\"/test\".*\"aos\\.TestMessage\"");
170 }
171
Brian Silvermana5450a92020-08-12 19:59:57 -0700172 private:
173 ShmEventLoopTestFactory factory_;
174};
175
176using ShmEventLoopDeathTest = ShmEventLoopTest;
177
Austin Schuha94e1002021-07-21 15:45:21 -0700178// Tests that we don't leave the calling thread realtime when calling Send
179// before Run.
180TEST_P(ShmEventLoopTest, SendBeforeRun) {
181 auto loop = factory()->MakePrimary("primary");
182 loop->SetRuntimeRealtimePriority(1);
183
184 auto loop2 = factory()->Make("loop2");
185 loop2->SetRuntimeRealtimePriority(2);
186 loop2->MakeWatcher("/test", [](const TestMessage &) {});
187 // Need the other one running for its watcher to record in SHM that it wants
188 // wakers to boost their priority, so leave it running in a thread for this
189 // test.
190 std::thread loop2_thread(
191 [&loop2]() { static_cast<ShmEventLoop *>(loop2.get())->Run(); });
192 std::this_thread::sleep_for(std::chrono::milliseconds(100));
193
194 auto sender = loop->MakeSender<TestMessage>("/test");
195 EXPECT_FALSE(IsRealtime());
196 {
197 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
198 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
199 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700200 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuha94e1002021-07-21 15:45:21 -0700201 }
202 EXPECT_FALSE(IsRealtime());
203
204 static_cast<ShmEventLoop *>(loop2.get())->Exit();
205 loop2_thread.join();
206}
207
Austin Schuh3115a202019-05-27 21:02:14 -0700208// Tests that every handler type is realtime and runs. There are threads
209// involved and it's easy to miss one.
Brian Silvermana5450a92020-08-12 19:59:57 -0700210TEST_P(ShmEventLoopTest, AllHandlersAreRealtime) {
211 auto loop = factory()->MakePrimary("primary");
212 auto loop2 = factory()->Make("loop2");
Austin Schuh3115a202019-05-27 21:02:14 -0700213
214 loop->SetRuntimeRealtimePriority(1);
215
216 auto sender = loop2->MakeSender<TestMessage>("/test");
217
218 bool did_onrun = false;
219 bool did_timer = false;
220 bool did_watcher = false;
221
Brian Silvermana5450a92020-08-12 19:59:57 -0700222 auto timer = loop->AddTimer([this, &did_timer]() {
Austin Schuh3115a202019-05-27 21:02:14 -0700223 EXPECT_TRUE(IsRealtime());
224 did_timer = true;
Brian Silvermana5450a92020-08-12 19:59:57 -0700225 factory()->Exit();
Austin Schuh3115a202019-05-27 21:02:14 -0700226 });
227
228 loop->MakeWatcher("/test", [&did_watcher](const TestMessage &) {
229 EXPECT_TRUE(IsRealtime());
230 did_watcher = true;
231 });
232
233 loop->OnRun([&loop, &did_onrun, &sender, timer]() {
234 EXPECT_TRUE(IsRealtime());
235 did_onrun = true;
Philipp Schradera6712522023-07-05 20:25:11 -0700236 timer->Schedule(loop->monotonic_now() + chrono::milliseconds(100));
Alex Perrycb7da4b2019-08-28 19:35:56 -0700237
238 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
239 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
240 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700241 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700242 });
James Kuszmaulc79768b2019-02-18 15:08:44 -0800243
Brian Silvermana5450a92020-08-12 19:59:57 -0700244 factory()->Run();
James Kuszmaulc79768b2019-02-18 15:08:44 -0800245
Austin Schuh3115a202019-05-27 21:02:14 -0700246 EXPECT_TRUE(did_onrun);
247 EXPECT_TRUE(did_timer);
248 EXPECT_TRUE(did_watcher);
James Kuszmaulc79768b2019-02-18 15:08:44 -0800249}
Austin Schuh52d325c2019-06-23 18:59:06 -0700250
251// Tests that missing a deadline inside the function still results in PhasedLoop
252// running at the right offset.
Brian Silvermana5450a92020-08-12 19:59:57 -0700253TEST_P(ShmEventLoopTest, DelayedPhasedLoop) {
254 auto loop1 = factory()->MakePrimary("primary");
Austin Schuh52d325c2019-06-23 18:59:06 -0700255
256 ::std::vector<::aos::monotonic_clock::time_point> times;
257
258 constexpr chrono::milliseconds kOffset = chrono::milliseconds(400);
259
260 loop1->AddPhasedLoop(
Brian Silvermana5450a92020-08-12 19:59:57 -0700261 [this, &times, &loop1, &kOffset](int count) {
Austin Schuh52d325c2019-06-23 18:59:06 -0700262 const ::aos::monotonic_clock::time_point monotonic_now =
263 loop1->monotonic_now();
264
265 // Compute our offset.
266 const ::aos::monotonic_clock::duration remainder =
267 monotonic_now.time_since_epoch() -
268 chrono::duration_cast<chrono::seconds>(
269 monotonic_now.time_since_epoch());
270
271 // Make sure we we are called near where we should be even when we
272 // delay.
273 constexpr chrono::milliseconds kEpsilon(200);
274 EXPECT_LT(remainder, kOffset + kEpsilon);
275 EXPECT_GT(remainder, kOffset - kEpsilon);
276
277 // Confirm that we see the missed count when we sleep.
278 if (times.size() == 0) {
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800279 CHECK_EQ(count, 1);
Austin Schuh52d325c2019-06-23 18:59:06 -0700280 } else {
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800281 CHECK_EQ(count, 3);
Austin Schuh52d325c2019-06-23 18:59:06 -0700282 }
283
284 times.push_back(loop1->monotonic_now());
285 if (times.size() == 2) {
Brian Silvermana5450a92020-08-12 19:59:57 -0700286 factory()->Exit();
Austin Schuh52d325c2019-06-23 18:59:06 -0700287 }
288
289 // Now, add a large delay. This should push us up to 3 cycles.
290 ::std::this_thread::sleep_for(chrono::milliseconds(2500));
291 },
292 chrono::seconds(1), kOffset);
293
Brian Silvermana5450a92020-08-12 19:59:57 -0700294 factory()->Run();
Austin Schuh52d325c2019-06-23 18:59:06 -0700295
296 EXPECT_EQ(times.size(), 2u);
297}
298
Brian Silverman5120afb2020-01-31 17:44:35 -0800299// Test GetWatcherSharedMemory in a few basic scenarios.
Brian Silvermana5450a92020-08-12 19:59:57 -0700300TEST_P(ShmEventLoopDeathTest, GetWatcherSharedMemory) {
301 auto generic_loop1 = factory()->MakePrimary("primary");
Brian Silverman5120afb2020-01-31 17:44:35 -0800302 ShmEventLoop *const loop1 = static_cast<ShmEventLoop *>(generic_loop1.get());
303 const auto channel = configuration::GetChannel(
304 loop1->configuration(), "/test", TestMessage::GetFullyQualifiedName(),
305 loop1->name(), loop1->node());
306
307 // First verify it handles an invalid channel reasonably.
308 EXPECT_DEATH(loop1->GetWatcherSharedMemory(channel),
309 "No watcher found for channel");
310
311 // Then, actually create a watcher, and verify it returns something sane.
Brian Silvermana5450a92020-08-12 19:59:57 -0700312 absl::Span<const char> shared_memory;
313 bool ran = false;
314 loop1->MakeWatcher("/test", [this, &shared_memory,
315 &ran](const TestMessage &message) {
316 EXPECT_FALSE(ran);
317 ran = true;
318 // If we're using pinning, then we can verify that the message is actually
319 // in the specified region.
320 if (GetParam() == ReadMethod::PIN) {
321 EXPECT_GE(reinterpret_cast<const char *>(&message),
322 shared_memory.begin());
323 EXPECT_LT(reinterpret_cast<const char *>(&message), shared_memory.end());
324 }
325 factory()->Exit();
326 });
327 shared_memory = loop1->GetWatcherSharedMemory(channel);
328 EXPECT_FALSE(shared_memory.empty());
329
330 auto loop2 = factory()->Make("sender");
331 auto sender = loop2->MakeSender<TestMessage>("/test");
332 generic_loop1->OnRun([&sender]() {
333 auto builder = sender.MakeBuilder();
334 TestMessage::Builder test_builder(*builder.fbb());
335 test_builder.add_value(1);
milind1f1dca32021-07-03 13:50:07 -0700336 builder.CheckOk(builder.Send(test_builder.Finish()));
Brian Silvermana5450a92020-08-12 19:59:57 -0700337 });
338 factory()->Run();
339 EXPECT_TRUE(ran);
Brian Silverman5120afb2020-01-31 17:44:35 -0800340}
341
Brian Silvermana5450a92020-08-12 19:59:57 -0700342TEST_P(ShmEventLoopTest, GetSenderSharedMemory) {
343 auto generic_loop1 = factory()->MakePrimary("primary");
Brian Silverman5120afb2020-01-31 17:44:35 -0800344 ShmEventLoop *const loop1 = static_cast<ShmEventLoop *>(generic_loop1.get());
345
Brian Silvermana5450a92020-08-12 19:59:57 -0700346 // Check that GetSenderSharedMemory returns non-null/non-empty memory span.
Brian Silverman5120afb2020-01-31 17:44:35 -0800347 auto sender = loop1->MakeSender<TestMessage>("/test");
Brian Silvermana5450a92020-08-12 19:59:57 -0700348 const absl::Span<char> shared_memory = loop1->GetSenderSharedMemory(&sender);
349 EXPECT_FALSE(shared_memory.empty());
350
351 auto builder = sender.MakeBuilder();
352 uint8_t *buffer;
James Kuszmaul65541cb2022-11-08 14:53:47 -0800353 builder.fbb()->CreateUninitializedVector(5, &buffer);
Brian Silvermana5450a92020-08-12 19:59:57 -0700354 EXPECT_GE(reinterpret_cast<char *>(buffer), shared_memory.begin());
355 EXPECT_LT(reinterpret_cast<char *>(buffer), shared_memory.end());
Brian Silverman5120afb2020-01-31 17:44:35 -0800356}
357
Brian Silvermana5450a92020-08-12 19:59:57 -0700358TEST_P(ShmEventLoopTest, GetFetcherPrivateMemory) {
359 auto generic_loop1 = factory()->MakePrimary("primary");
Brian Silverman6d2b3592020-06-18 14:40:15 -0700360 ShmEventLoop *const loop1 = static_cast<ShmEventLoop *>(generic_loop1.get());
361
Brian Silvermana5450a92020-08-12 19:59:57 -0700362 // Check that GetFetcherPrivateMemory returns non-null/non-empty memory span.
Brian Silverman6d2b3592020-06-18 14:40:15 -0700363 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
Brian Silvermana5450a92020-08-12 19:59:57 -0700364 const auto private_memory = loop1->GetFetcherPrivateMemory(&fetcher);
365 EXPECT_FALSE(private_memory.empty());
366
367 auto loop2 = factory()->Make("sender");
368 auto sender = loop2->MakeSender<TestMessage>("/test");
369 {
370 auto builder = sender.MakeBuilder();
371 TestMessage::Builder test_builder(*builder.fbb());
372 test_builder.add_value(1);
milind1f1dca32021-07-03 13:50:07 -0700373 builder.CheckOk(builder.Send(test_builder.Finish()));
Brian Silvermana5450a92020-08-12 19:59:57 -0700374 }
375
376 ASSERT_TRUE(fetcher.Fetch());
377 EXPECT_GE(fetcher.context().data, private_memory.begin());
378 EXPECT_LT(fetcher.context().data, private_memory.end());
Brian Silverman6d2b3592020-06-18 14:40:15 -0700379}
380
Brian Silverman0eaa1da2020-08-12 20:03:52 -0700381// Tests that corrupting the bytes around the data buffer results in a crash.
382TEST_P(ShmEventLoopDeathTest, OutOfBoundsWrite) {
383 auto loop1 = factory()->Make("loop1");
384 std::unique_ptr<aos::RawSender> sender =
385 loop1->MakeRawSender(configuration::GetChannel(
386 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
387 for (size_t i = 0; i < kChannelDataRedzone; ++i) {
388 SCOPED_TRACE(std::to_string(i));
389 EXPECT_DEATH(
390 {
Philipp Schrader4473d2c2023-12-01 13:43:09 -0800391 // Can't use `data()[-1 -i]` here because that's undefined behaviour.
392 // We do manual pointer arithmetic to work around that.
393 ++(*(static_cast<char *>(sender->data()) - 1 - i));
milind1f1dca32021-07-03 13:50:07 -0700394 sender->CheckOk(sender->Send(0));
Brian Silverman0eaa1da2020-08-12 20:03:52 -0700395 },
396 "Somebody wrote outside the buffer of their message");
397 EXPECT_DEATH(
398 {
399 ++static_cast<char *>(sender->data())[sender->size() + i];
milind1f1dca32021-07-03 13:50:07 -0700400 sender->CheckOk(sender->Send(0));
Brian Silverman0eaa1da2020-08-12 20:03:52 -0700401 },
402 "Somebody wrote outside the buffer of their message");
403 }
404}
405
Brian Silvermance418d02021-11-03 11:25:52 -0700406// Tests that the next message not being available prints a helpful error in the
407// normal case.
408TEST_P(ShmEventLoopDeathTest, NextMessageNotAvailable) {
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -0700409 TestNextMessageNotAvailable(false);
Brian Silvermance418d02021-11-03 11:25:52 -0700410}
411
412// Tests that the next message not being available prints a helpful error with
413// timing reports disabled.
414TEST_P(ShmEventLoopDeathTest, NextMessageNotAvailableNoTimingReports) {
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -0700415 TestNextMessageNotAvailable(true);
Brian Silvermance418d02021-11-03 11:25:52 -0700416}
417
418// Tests that the next message not being available prints a helpful error even
419// when Run is never called.
420TEST_P(ShmEventLoopDeathTest, NextMessageNotAvailableNoRun) {
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -0700421 TestNextMessageNotAvailableNoRun(false);
Brian Silvermance418d02021-11-03 11:25:52 -0700422}
423
424// Tests that the next message not being available prints a helpful error even
425// when Run is never called without timing reports.
426TEST_P(ShmEventLoopDeathTest, NextMessageNotAvailableNoRunNoTimingReports) {
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -0700427 TestNextMessageNotAvailableNoRun(true);
Brian Silvermance418d02021-11-03 11:25:52 -0700428}
429
Brian Silvermane1fe2512022-08-14 23:18:50 -0700430// Test that an ExitHandle outliving its EventLoop is caught.
431TEST_P(ShmEventLoopDeathTest, ExitHandleOutlivesEventLoop) {
432 auto loop1 = factory()->MakePrimary("loop1");
433 auto exit_handle = static_cast<ShmEventLoop *>(loop1.get())->MakeExitHandle();
434 EXPECT_DEATH(loop1.reset(),
435 "All ExitHandles must be destroyed before the ShmEventLoop");
436}
437
Austin Schuh39788ff2019-12-01 18:22:57 -0800438// TODO(austin): Test that missing a deadline with a timer recovers as expected.
439
James Kuszmaulf4bf9fe2021-05-10 22:58:24 -0700440INSTANTIATE_TEST_SUITE_P(ShmEventLoopCopyTest, ShmEventLoopTest,
Brian Silvermance418d02021-11-03 11:25:52 -0700441 ::testing::Values(ReadMethod::COPY));
James Kuszmaulf4bf9fe2021-05-10 22:58:24 -0700442INSTANTIATE_TEST_SUITE_P(ShmEventLoopPinTest, ShmEventLoopTest,
Brian Silvermance418d02021-11-03 11:25:52 -0700443 ::testing::Values(ReadMethod::PIN));
James Kuszmaulf4bf9fe2021-05-10 22:58:24 -0700444INSTANTIATE_TEST_SUITE_P(ShmEventLoopCopyDeathTest, ShmEventLoopDeathTest,
Brian Silvermance418d02021-11-03 11:25:52 -0700445 ::testing::Values(ReadMethod::COPY));
James Kuszmaulf4bf9fe2021-05-10 22:58:24 -0700446INSTANTIATE_TEST_SUITE_P(ShmEventLoopPinDeathTest, ShmEventLoopDeathTest,
Brian Silvermance418d02021-11-03 11:25:52 -0700447 ::testing::Values(ReadMethod::PIN));
Brian Silvermana5450a92020-08-12 19:59:57 -0700448
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800449} // namespace aos::testing