blob: 2382f0785463cd31e7ed31a8f15a45b70ac58487 [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
13namespace aos {
14namespace testing {
15namespace {
Austin Schuh3115a202019-05-27 21:02:14 -070016namespace chrono = ::std::chrono;
Parker Schuhe4a70d62017-12-27 20:10:20 -080017
18class ShmEventLoopTestFactory : public EventLoopTestFactory {
19 public:
Alex Perrycb7da4b2019-08-28 19:35:56 -070020 ShmEventLoopTestFactory() {
21 // Put all the queue files in ${TEST_TMPDIR} if it is set, otherwise
22 // everything will be reusing /dev/shm when sharded.
23 char *test_tmpdir = getenv("TEST_TMPDIR");
24 if (test_tmpdir != nullptr) {
25 FLAGS_shm_base = std::string(test_tmpdir) + "/aos";
26 }
27
28 // Clean up anything left there before.
Philipp Schrader81fa3fb2023-09-17 18:58:35 -070029 unlink((FLAGS_shm_base + "/test/aos.TestMessage.v6").c_str());
30 unlink((FLAGS_shm_base + "/test1/aos.TestMessage.v6").c_str());
31 unlink((FLAGS_shm_base + "/test2/aos.TestMessage.v6").c_str());
32 unlink((FLAGS_shm_base + "/test2/aos.TestMessage.v6").c_str());
33 unlink((FLAGS_shm_base + "/aos/aos.timing.Report.v6").c_str());
34 unlink((FLAGS_shm_base + "/aos/aos.logging.LogMessageFbs.v6").c_str());
Alex Perrycb7da4b2019-08-28 19:35:56 -070035 }
36
Austin Schuh217a9782019-12-21 23:02:50 -080037 ~ShmEventLoopTestFactory() { FLAGS_override_hostname = ""; }
38
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080039 ::std::unique_ptr<EventLoop> Make(std::string_view name) override {
Austin Schuh217a9782019-12-21 23:02:50 -080040 if (configuration()->has_nodes()) {
Austin Schuh898f4972020-01-11 17:21:25 -080041 FLAGS_override_hostname =
42 std::string(my_node()->hostname()->string_view());
Austin Schuh217a9782019-12-21 23:02:50 -080043 }
44 ::std::unique_ptr<ShmEventLoop> loop(new ShmEventLoop(configuration()));
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080045 loop->set_name(name);
James Kuszmaul9776b392023-01-14 14:08:08 -080046 return loop;
Parker Schuhe4a70d62017-12-27 20:10:20 -080047 }
48
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080049 ::std::unique_ptr<EventLoop> MakePrimary(std::string_view name) override {
Austin Schuh217a9782019-12-21 23:02:50 -080050 if (configuration()->has_nodes()) {
Austin Schuh898f4972020-01-11 17:21:25 -080051 FLAGS_override_hostname =
52 std::string(my_node()->hostname()->string_view());
Austin Schuh217a9782019-12-21 23:02:50 -080053 }
Austin Schuh44019f92019-05-19 19:58:27 -070054 ::std::unique_ptr<ShmEventLoop> loop =
Alex Perrycb7da4b2019-08-28 19:35:56 -070055 ::std::unique_ptr<ShmEventLoop>(new ShmEventLoop(configuration()));
Austin Schuh44019f92019-05-19 19:58:27 -070056 primary_event_loop_ = loop.get();
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080057 loop->set_name(name);
James Kuszmaul9776b392023-01-14 14:08:08 -080058 return loop;
Austin Schuh44019f92019-05-19 19:58:27 -070059 }
60
Alex Perrycb7da4b2019-08-28 19:35:56 -070061 void Run() override { CHECK_NOTNULL(primary_event_loop_)->Run(); }
Austin Schuh44019f92019-05-19 19:58:27 -070062
Alex Perrycb7da4b2019-08-28 19:35:56 -070063 void Exit() override { CHECK_NOTNULL(primary_event_loop_)->Exit(); }
Austin Schuh9fe68f72019-08-10 19:32:03 -070064
Austin Schuh52d325c2019-06-23 18:59:06 -070065 void SleepFor(::std::chrono::nanoseconds duration) override {
66 ::std::this_thread::sleep_for(duration);
67 }
68
Austin Schuh44019f92019-05-19 19:58:27 -070069 private:
Austin Schuh44019f92019-05-19 19:58:27 -070070 ::aos::ShmEventLoop *primary_event_loop_;
Parker Schuhe4a70d62017-12-27 20:10:20 -080071};
72
Austin Schuh6bae8252021-02-07 22:01:49 -080073auto CommonParameters() {
74 return ::testing::Combine(
75 ::testing::Values([]() { return new ShmEventLoopTestFactory(); }),
76 ::testing::Values(ReadMethod::COPY, ReadMethod::PIN),
77 ::testing::Values(DoTimingReports::kYes, DoTimingReports::kNo));
78}
Parker Schuhe4a70d62017-12-27 20:10:20 -080079
James Kuszmaulf4bf9fe2021-05-10 22:58:24 -070080INSTANTIATE_TEST_SUITE_P(ShmEventLoopCommonTest, AbstractEventLoopTest,
Brian Silvermance418d02021-11-03 11:25:52 -070081 CommonParameters());
Brian Silverman77162972020-08-12 19:52:40 -070082
Brian Silvermance418d02021-11-03 11:25:52 -070083INSTANTIATE_TEST_SUITE_P(ShmEventLoopCommonDeathTest,
84 AbstractEventLoopDeathTest, CommonParameters());
Austin Schuh6b6dfa52019-06-12 20:16:20 -070085
Parker Schuhe4a70d62017-12-27 20:10:20 -080086} // namespace
James Kuszmaulc79768b2019-02-18 15:08:44 -080087
Austin Schuh3115a202019-05-27 21:02:14 -070088bool IsRealtime() {
89 int scheduler;
Alex Perrycb7da4b2019-08-28 19:35:56 -070090 PCHECK((scheduler = sched_getscheduler(0)) != -1);
91
Austin Schuh62288252020-11-18 23:26:04 -080092 {
93 // If we are RT, logging the scheduler will crash us. Mark that we just
94 // don't care.
95 aos::ScopedNotRealtime nrt;
96 LOG(INFO) << "scheduler is " << scheduler;
97 }
98
99 const bool result = scheduler == SCHED_FIFO || scheduler == SCHED_RR;
100 // Confirm that the scheduler matches AOS' interpretation of if we are
101 // realtime or not.
102 if (result) {
103 aos::CheckRealtime();
104 } else {
105 aos::CheckNotRealtime();
106 }
107 return result;
Austin Schuh3115a202019-05-27 21:02:14 -0700108}
James Kuszmaulc79768b2019-02-18 15:08:44 -0800109
Brian Silvermana5450a92020-08-12 19:59:57 -0700110class ShmEventLoopTest : public ::testing::TestWithParam<ReadMethod> {
111 public:
112 ShmEventLoopTest() {
113 if (GetParam() == ReadMethod::PIN) {
114 factory_.PinReads();
115 }
116 }
117
118 ShmEventLoopTestFactory *factory() { return &factory_; }
119
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -0700120 // Helper functions for testing when a fetcher cannot fetch the next message
121 // because it was overwritten
122 void TestNextMessageNotAvailable(const bool skip_timing_report) {
123 auto loop1 = factory()->MakePrimary("loop1");
124 if (skip_timing_report) {
125 loop1->SkipTimingReport();
126 }
127 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
128 auto loop2 = factory()->Make("loop2");
129 auto sender = loop2->MakeSender<TestMessage>("/test");
130 bool ran = false;
131 loop1->AddPhasedLoop(
132 [&sender](int) {
133 auto builder = sender.MakeBuilder();
134 TestMessage::Builder test_builder(*builder.fbb());
135 test_builder.add_value(0);
136 builder.CheckOk(builder.Send(test_builder.Finish()));
137 },
138 std::chrono::milliseconds(2));
139 loop1
140 ->AddTimer([this, &fetcher, &ran]() {
141 EXPECT_DEATH(fetcher.FetchNext(),
142 "The next message is no longer "
143 "available.*\"/test\".*\"aos\\.TestMessage\"");
144 factory()->Exit();
145 ran = true;
146 })
Philipp Schradera6712522023-07-05 20:25:11 -0700147 ->Schedule(loop1->monotonic_now() + std::chrono::seconds(4));
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -0700148 factory()->Run();
149 EXPECT_TRUE(ran);
150 }
151 void TestNextMessageNotAvailableNoRun(const bool skip_timing_report) {
152 auto loop1 = factory()->MakePrimary("loop1");
153 if (skip_timing_report) {
154 loop1->SkipTimingReport();
155 }
156 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
157 auto loop2 = factory()->Make("loop2");
158 auto sender = loop2->MakeSender<TestMessage>("/test");
159 time::PhasedLoop phased_loop(std::chrono::milliseconds(2),
160 loop2->monotonic_now());
161 for (int i = 0; i < 2000; ++i) {
162 auto builder = sender.MakeBuilder();
163 TestMessage::Builder test_builder(*builder.fbb());
164 test_builder.add_value(0);
165 builder.CheckOk(builder.Send(test_builder.Finish()));
166 phased_loop.SleepUntilNext();
167 }
168 EXPECT_DEATH(fetcher.FetchNext(),
169 "The next message is no longer "
170 "available.*\"/test\".*\"aos\\.TestMessage\"");
171 }
172
Brian Silvermana5450a92020-08-12 19:59:57 -0700173 private:
174 ShmEventLoopTestFactory factory_;
175};
176
177using ShmEventLoopDeathTest = ShmEventLoopTest;
178
Austin Schuha94e1002021-07-21 15:45:21 -0700179// Tests that we don't leave the calling thread realtime when calling Send
180// before Run.
181TEST_P(ShmEventLoopTest, SendBeforeRun) {
182 auto loop = factory()->MakePrimary("primary");
183 loop->SetRuntimeRealtimePriority(1);
184
185 auto loop2 = factory()->Make("loop2");
186 loop2->SetRuntimeRealtimePriority(2);
187 loop2->MakeWatcher("/test", [](const TestMessage &) {});
188 // Need the other one running for its watcher to record in SHM that it wants
189 // wakers to boost their priority, so leave it running in a thread for this
190 // test.
191 std::thread loop2_thread(
192 [&loop2]() { static_cast<ShmEventLoop *>(loop2.get())->Run(); });
193 std::this_thread::sleep_for(std::chrono::milliseconds(100));
194
195 auto sender = loop->MakeSender<TestMessage>("/test");
196 EXPECT_FALSE(IsRealtime());
197 {
198 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
199 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
200 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700201 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuha94e1002021-07-21 15:45:21 -0700202 }
203 EXPECT_FALSE(IsRealtime());
204
205 static_cast<ShmEventLoop *>(loop2.get())->Exit();
206 loop2_thread.join();
207}
208
Austin Schuh3115a202019-05-27 21:02:14 -0700209// Tests that every handler type is realtime and runs. There are threads
210// involved and it's easy to miss one.
Brian Silvermana5450a92020-08-12 19:59:57 -0700211TEST_P(ShmEventLoopTest, AllHandlersAreRealtime) {
212 auto loop = factory()->MakePrimary("primary");
213 auto loop2 = factory()->Make("loop2");
Austin Schuh3115a202019-05-27 21:02:14 -0700214
215 loop->SetRuntimeRealtimePriority(1);
216
217 auto sender = loop2->MakeSender<TestMessage>("/test");
218
219 bool did_onrun = false;
220 bool did_timer = false;
221 bool did_watcher = false;
222
Brian Silvermana5450a92020-08-12 19:59:57 -0700223 auto timer = loop->AddTimer([this, &did_timer]() {
Austin Schuh3115a202019-05-27 21:02:14 -0700224 EXPECT_TRUE(IsRealtime());
225 did_timer = true;
Brian Silvermana5450a92020-08-12 19:59:57 -0700226 factory()->Exit();
Austin Schuh3115a202019-05-27 21:02:14 -0700227 });
228
229 loop->MakeWatcher("/test", [&did_watcher](const TestMessage &) {
230 EXPECT_TRUE(IsRealtime());
231 did_watcher = true;
232 });
233
234 loop->OnRun([&loop, &did_onrun, &sender, timer]() {
235 EXPECT_TRUE(IsRealtime());
236 did_onrun = true;
Philipp Schradera6712522023-07-05 20:25:11 -0700237 timer->Schedule(loop->monotonic_now() + chrono::milliseconds(100));
Alex Perrycb7da4b2019-08-28 19:35:56 -0700238
239 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
240 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
241 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700242 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700243 });
James Kuszmaulc79768b2019-02-18 15:08:44 -0800244
Brian Silvermana5450a92020-08-12 19:59:57 -0700245 factory()->Run();
James Kuszmaulc79768b2019-02-18 15:08:44 -0800246
Austin Schuh3115a202019-05-27 21:02:14 -0700247 EXPECT_TRUE(did_onrun);
248 EXPECT_TRUE(did_timer);
249 EXPECT_TRUE(did_watcher);
James Kuszmaulc79768b2019-02-18 15:08:44 -0800250}
Austin Schuh52d325c2019-06-23 18:59:06 -0700251
252// Tests that missing a deadline inside the function still results in PhasedLoop
253// running at the right offset.
Brian Silvermana5450a92020-08-12 19:59:57 -0700254TEST_P(ShmEventLoopTest, DelayedPhasedLoop) {
255 auto loop1 = factory()->MakePrimary("primary");
Austin Schuh52d325c2019-06-23 18:59:06 -0700256
257 ::std::vector<::aos::monotonic_clock::time_point> times;
258
259 constexpr chrono::milliseconds kOffset = chrono::milliseconds(400);
260
261 loop1->AddPhasedLoop(
Brian Silvermana5450a92020-08-12 19:59:57 -0700262 [this, &times, &loop1, &kOffset](int count) {
Austin Schuh52d325c2019-06-23 18:59:06 -0700263 const ::aos::monotonic_clock::time_point monotonic_now =
264 loop1->monotonic_now();
265
266 // Compute our offset.
267 const ::aos::monotonic_clock::duration remainder =
268 monotonic_now.time_since_epoch() -
269 chrono::duration_cast<chrono::seconds>(
270 monotonic_now.time_since_epoch());
271
272 // Make sure we we are called near where we should be even when we
273 // delay.
274 constexpr chrono::milliseconds kEpsilon(200);
275 EXPECT_LT(remainder, kOffset + kEpsilon);
276 EXPECT_GT(remainder, kOffset - kEpsilon);
277
278 // Confirm that we see the missed count when we sleep.
279 if (times.size() == 0) {
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800280 CHECK_EQ(count, 1);
Austin Schuh52d325c2019-06-23 18:59:06 -0700281 } else {
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800282 CHECK_EQ(count, 3);
Austin Schuh52d325c2019-06-23 18:59:06 -0700283 }
284
285 times.push_back(loop1->monotonic_now());
286 if (times.size() == 2) {
Brian Silvermana5450a92020-08-12 19:59:57 -0700287 factory()->Exit();
Austin Schuh52d325c2019-06-23 18:59:06 -0700288 }
289
290 // Now, add a large delay. This should push us up to 3 cycles.
291 ::std::this_thread::sleep_for(chrono::milliseconds(2500));
292 },
293 chrono::seconds(1), kOffset);
294
Brian Silvermana5450a92020-08-12 19:59:57 -0700295 factory()->Run();
Austin Schuh52d325c2019-06-23 18:59:06 -0700296
297 EXPECT_EQ(times.size(), 2u);
298}
299
Brian Silverman5120afb2020-01-31 17:44:35 -0800300// Test GetWatcherSharedMemory in a few basic scenarios.
Brian Silvermana5450a92020-08-12 19:59:57 -0700301TEST_P(ShmEventLoopDeathTest, GetWatcherSharedMemory) {
302 auto generic_loop1 = factory()->MakePrimary("primary");
Brian Silverman5120afb2020-01-31 17:44:35 -0800303 ShmEventLoop *const loop1 = static_cast<ShmEventLoop *>(generic_loop1.get());
304 const auto channel = configuration::GetChannel(
305 loop1->configuration(), "/test", TestMessage::GetFullyQualifiedName(),
306 loop1->name(), loop1->node());
307
308 // First verify it handles an invalid channel reasonably.
309 EXPECT_DEATH(loop1->GetWatcherSharedMemory(channel),
310 "No watcher found for channel");
311
312 // Then, actually create a watcher, and verify it returns something sane.
Brian Silvermana5450a92020-08-12 19:59:57 -0700313 absl::Span<const char> shared_memory;
314 bool ran = false;
315 loop1->MakeWatcher("/test", [this, &shared_memory,
316 &ran](const TestMessage &message) {
317 EXPECT_FALSE(ran);
318 ran = true;
319 // If we're using pinning, then we can verify that the message is actually
320 // in the specified region.
321 if (GetParam() == ReadMethod::PIN) {
322 EXPECT_GE(reinterpret_cast<const char *>(&message),
323 shared_memory.begin());
324 EXPECT_LT(reinterpret_cast<const char *>(&message), shared_memory.end());
325 }
326 factory()->Exit();
327 });
328 shared_memory = loop1->GetWatcherSharedMemory(channel);
329 EXPECT_FALSE(shared_memory.empty());
330
331 auto loop2 = factory()->Make("sender");
332 auto sender = loop2->MakeSender<TestMessage>("/test");
333 generic_loop1->OnRun([&sender]() {
334 auto builder = sender.MakeBuilder();
335 TestMessage::Builder test_builder(*builder.fbb());
336 test_builder.add_value(1);
milind1f1dca32021-07-03 13:50:07 -0700337 builder.CheckOk(builder.Send(test_builder.Finish()));
Brian Silvermana5450a92020-08-12 19:59:57 -0700338 });
339 factory()->Run();
340 EXPECT_TRUE(ran);
Brian Silverman5120afb2020-01-31 17:44:35 -0800341}
342
Brian Silvermana5450a92020-08-12 19:59:57 -0700343TEST_P(ShmEventLoopTest, GetSenderSharedMemory) {
344 auto generic_loop1 = factory()->MakePrimary("primary");
Brian Silverman5120afb2020-01-31 17:44:35 -0800345 ShmEventLoop *const loop1 = static_cast<ShmEventLoop *>(generic_loop1.get());
346
Brian Silvermana5450a92020-08-12 19:59:57 -0700347 // Check that GetSenderSharedMemory returns non-null/non-empty memory span.
Brian Silverman5120afb2020-01-31 17:44:35 -0800348 auto sender = loop1->MakeSender<TestMessage>("/test");
Brian Silvermana5450a92020-08-12 19:59:57 -0700349 const absl::Span<char> shared_memory = loop1->GetSenderSharedMemory(&sender);
350 EXPECT_FALSE(shared_memory.empty());
351
352 auto builder = sender.MakeBuilder();
353 uint8_t *buffer;
James Kuszmaul65541cb2022-11-08 14:53:47 -0800354 builder.fbb()->CreateUninitializedVector(5, &buffer);
Brian Silvermana5450a92020-08-12 19:59:57 -0700355 EXPECT_GE(reinterpret_cast<char *>(buffer), shared_memory.begin());
356 EXPECT_LT(reinterpret_cast<char *>(buffer), shared_memory.end());
Brian Silverman5120afb2020-01-31 17:44:35 -0800357}
358
Brian Silvermana5450a92020-08-12 19:59:57 -0700359TEST_P(ShmEventLoopTest, GetFetcherPrivateMemory) {
360 auto generic_loop1 = factory()->MakePrimary("primary");
Brian Silverman6d2b3592020-06-18 14:40:15 -0700361 ShmEventLoop *const loop1 = static_cast<ShmEventLoop *>(generic_loop1.get());
362
Brian Silvermana5450a92020-08-12 19:59:57 -0700363 // Check that GetFetcherPrivateMemory returns non-null/non-empty memory span.
Brian Silverman6d2b3592020-06-18 14:40:15 -0700364 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
Brian Silvermana5450a92020-08-12 19:59:57 -0700365 const auto private_memory = loop1->GetFetcherPrivateMemory(&fetcher);
366 EXPECT_FALSE(private_memory.empty());
367
368 auto loop2 = factory()->Make("sender");
369 auto sender = loop2->MakeSender<TestMessage>("/test");
370 {
371 auto builder = sender.MakeBuilder();
372 TestMessage::Builder test_builder(*builder.fbb());
373 test_builder.add_value(1);
milind1f1dca32021-07-03 13:50:07 -0700374 builder.CheckOk(builder.Send(test_builder.Finish()));
Brian Silvermana5450a92020-08-12 19:59:57 -0700375 }
376
377 ASSERT_TRUE(fetcher.Fetch());
378 EXPECT_GE(fetcher.context().data, private_memory.begin());
379 EXPECT_LT(fetcher.context().data, private_memory.end());
Brian Silverman6d2b3592020-06-18 14:40:15 -0700380}
381
Brian Silverman0eaa1da2020-08-12 20:03:52 -0700382// Tests that corrupting the bytes around the data buffer results in a crash.
383TEST_P(ShmEventLoopDeathTest, OutOfBoundsWrite) {
384 auto loop1 = factory()->Make("loop1");
385 std::unique_ptr<aos::RawSender> sender =
386 loop1->MakeRawSender(configuration::GetChannel(
387 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
388 for (size_t i = 0; i < kChannelDataRedzone; ++i) {
389 SCOPED_TRACE(std::to_string(i));
390 EXPECT_DEATH(
391 {
392 ++static_cast<char *>(sender->data())[-1 - i];
milind1f1dca32021-07-03 13:50:07 -0700393 sender->CheckOk(sender->Send(0));
Brian Silverman0eaa1da2020-08-12 20:03:52 -0700394 },
395 "Somebody wrote outside the buffer of their message");
396 EXPECT_DEATH(
397 {
398 ++static_cast<char *>(sender->data())[sender->size() + i];
milind1f1dca32021-07-03 13:50:07 -0700399 sender->CheckOk(sender->Send(0));
Brian Silverman0eaa1da2020-08-12 20:03:52 -0700400 },
401 "Somebody wrote outside the buffer of their message");
402 }
403}
404
Brian Silvermance418d02021-11-03 11:25:52 -0700405// Tests that the next message not being available prints a helpful error in the
406// normal case.
407TEST_P(ShmEventLoopDeathTest, NextMessageNotAvailable) {
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -0700408 TestNextMessageNotAvailable(false);
Brian Silvermance418d02021-11-03 11:25:52 -0700409}
410
411// Tests that the next message not being available prints a helpful error with
412// timing reports disabled.
413TEST_P(ShmEventLoopDeathTest, NextMessageNotAvailableNoTimingReports) {
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -0700414 TestNextMessageNotAvailable(true);
Brian Silvermance418d02021-11-03 11:25:52 -0700415}
416
417// Tests that the next message not being available prints a helpful error even
418// when Run is never called.
419TEST_P(ShmEventLoopDeathTest, NextMessageNotAvailableNoRun) {
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -0700420 TestNextMessageNotAvailableNoRun(false);
Brian Silvermance418d02021-11-03 11:25:52 -0700421}
422
423// Tests that the next message not being available prints a helpful error even
424// when Run is never called without timing reports.
425TEST_P(ShmEventLoopDeathTest, NextMessageNotAvailableNoRunNoTimingReports) {
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -0700426 TestNextMessageNotAvailableNoRun(true);
Brian Silvermance418d02021-11-03 11:25:52 -0700427}
428
Brian Silvermane1fe2512022-08-14 23:18:50 -0700429// Test that an ExitHandle outliving its EventLoop is caught.
430TEST_P(ShmEventLoopDeathTest, ExitHandleOutlivesEventLoop) {
431 auto loop1 = factory()->MakePrimary("loop1");
432 auto exit_handle = static_cast<ShmEventLoop *>(loop1.get())->MakeExitHandle();
433 EXPECT_DEATH(loop1.reset(),
434 "All ExitHandles must be destroyed before the ShmEventLoop");
435}
436
Austin Schuh39788ff2019-12-01 18:22:57 -0800437// TODO(austin): Test that missing a deadline with a timer recovers as expected.
438
James Kuszmaulf4bf9fe2021-05-10 22:58:24 -0700439INSTANTIATE_TEST_SUITE_P(ShmEventLoopCopyTest, ShmEventLoopTest,
Brian Silvermance418d02021-11-03 11:25:52 -0700440 ::testing::Values(ReadMethod::COPY));
James Kuszmaulf4bf9fe2021-05-10 22:58:24 -0700441INSTANTIATE_TEST_SUITE_P(ShmEventLoopPinTest, ShmEventLoopTest,
Brian Silvermance418d02021-11-03 11:25:52 -0700442 ::testing::Values(ReadMethod::PIN));
James Kuszmaulf4bf9fe2021-05-10 22:58:24 -0700443INSTANTIATE_TEST_SUITE_P(ShmEventLoopCopyDeathTest, ShmEventLoopDeathTest,
Brian Silvermance418d02021-11-03 11:25:52 -0700444 ::testing::Values(ReadMethod::COPY));
James Kuszmaulf4bf9fe2021-05-10 22:58:24 -0700445INSTANTIATE_TEST_SUITE_P(ShmEventLoopPinDeathTest, ShmEventLoopDeathTest,
Brian Silvermance418d02021-11-03 11:25:52 -0700446 ::testing::Values(ReadMethod::PIN));
Brian Silvermana5450a92020-08-12 19:59:57 -0700447
Parker Schuhe4a70d62017-12-27 20:10:20 -0800448} // namespace testing
449} // namespace aos