blob: aae8f1588ff32a3a813616910c5c6784b922c2e0 [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() {
Alex Perrycb7da4b2019-08-28 19:35:56 -070020 // Clean up anything left there before.
Austin Schuhac6d89e2024-03-27 14:56:09 -070021 unlink((FLAGS_shm_base + "/test/aos.TestMessage.v7").c_str());
22 unlink((FLAGS_shm_base + "/test1/aos.TestMessage.v7").c_str());
23 unlink((FLAGS_shm_base + "/test2/aos.TestMessage.v7").c_str());
24 unlink((FLAGS_shm_base + "/test2/aos.TestMessage.v7").c_str());
25 unlink((FLAGS_shm_base + "/aos/aos.timing.Report.v7").c_str());
26 unlink((FLAGS_shm_base + "/aos/aos.logging.LogMessageFbs.v7").c_str());
Alex Perrycb7da4b2019-08-28 19:35:56 -070027 }
28
Austin Schuh217a9782019-12-21 23:02:50 -080029 ~ShmEventLoopTestFactory() { FLAGS_override_hostname = ""; }
30
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080031 ::std::unique_ptr<EventLoop> Make(std::string_view name) override {
Austin Schuh217a9782019-12-21 23:02:50 -080032 if (configuration()->has_nodes()) {
Austin Schuh898f4972020-01-11 17:21:25 -080033 FLAGS_override_hostname =
34 std::string(my_node()->hostname()->string_view());
Austin Schuh217a9782019-12-21 23:02:50 -080035 }
36 ::std::unique_ptr<ShmEventLoop> loop(new ShmEventLoop(configuration()));
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080037 loop->set_name(name);
James Kuszmaul9776b392023-01-14 14:08:08 -080038 return loop;
Parker Schuhe4a70d62017-12-27 20:10:20 -080039 }
40
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080041 ::std::unique_ptr<EventLoop> MakePrimary(std::string_view name) override {
Austin Schuh217a9782019-12-21 23:02:50 -080042 if (configuration()->has_nodes()) {
Austin Schuh898f4972020-01-11 17:21:25 -080043 FLAGS_override_hostname =
44 std::string(my_node()->hostname()->string_view());
Austin Schuh217a9782019-12-21 23:02:50 -080045 }
Austin Schuh44019f92019-05-19 19:58:27 -070046 ::std::unique_ptr<ShmEventLoop> loop =
Alex Perrycb7da4b2019-08-28 19:35:56 -070047 ::std::unique_ptr<ShmEventLoop>(new ShmEventLoop(configuration()));
Austin Schuh44019f92019-05-19 19:58:27 -070048 primary_event_loop_ = loop.get();
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080049 loop->set_name(name);
James Kuszmaul9776b392023-01-14 14:08:08 -080050 return loop;
Austin Schuh44019f92019-05-19 19:58:27 -070051 }
52
James Kuszmaul9f998082024-05-23 15:37:35 -070053 Result<void> Run() override {
Austin Schuh6bdcc372024-06-27 14:49:11 -070054 CHECK(primary_event_loop_ != nullptr);
55 return primary_event_loop_->Run();
James Kuszmaul9f998082024-05-23 15:37:35 -070056 }
57
58 std::unique_ptr<ExitHandle> MakeExitHandle() override {
Austin Schuh6bdcc372024-06-27 14:49:11 -070059 CHECK(primary_event_loop_ != nullptr);
60 return primary_event_loop_->MakeExitHandle();
James Kuszmaul9f998082024-05-23 15:37:35 -070061 }
Austin Schuh44019f92019-05-19 19:58:27 -070062
Austin Schuh6bdcc372024-06-27 14:49:11 -070063 void Exit() override {
64 CHECK(primary_event_loop_ != nullptr);
65 primary_event_loop_->Exit();
66 }
Austin Schuh9fe68f72019-08-10 19:32:03 -070067
Austin Schuh52d325c2019-06-23 18:59:06 -070068 void SleepFor(::std::chrono::nanoseconds duration) override {
69 ::std::this_thread::sleep_for(duration);
70 }
71
Austin Schuh44019f92019-05-19 19:58:27 -070072 private:
James Kuszmaul9f998082024-05-23 15:37:35 -070073 ::aos::ShmEventLoop *primary_event_loop_ = nullptr;
Parker Schuhe4a70d62017-12-27 20:10:20 -080074};
75
Austin Schuh6bae8252021-02-07 22:01:49 -080076auto CommonParameters() {
77 return ::testing::Combine(
78 ::testing::Values([]() { return new ShmEventLoopTestFactory(); }),
79 ::testing::Values(ReadMethod::COPY, ReadMethod::PIN),
80 ::testing::Values(DoTimingReports::kYes, DoTimingReports::kNo));
81}
Parker Schuhe4a70d62017-12-27 20:10:20 -080082
James Kuszmaulf4bf9fe2021-05-10 22:58:24 -070083INSTANTIATE_TEST_SUITE_P(ShmEventLoopCommonTest, AbstractEventLoopTest,
Brian Silvermance418d02021-11-03 11:25:52 -070084 CommonParameters());
Brian Silverman77162972020-08-12 19:52:40 -070085
Brian Silvermance418d02021-11-03 11:25:52 -070086INSTANTIATE_TEST_SUITE_P(ShmEventLoopCommonDeathTest,
87 AbstractEventLoopDeathTest, CommonParameters());
Austin Schuh6b6dfa52019-06-12 20:16:20 -070088
Parker Schuhe4a70d62017-12-27 20:10:20 -080089} // namespace
James Kuszmaulc79768b2019-02-18 15:08:44 -080090
Austin Schuh3115a202019-05-27 21:02:14 -070091bool IsRealtime() {
92 int scheduler;
Alex Perrycb7da4b2019-08-28 19:35:56 -070093 PCHECK((scheduler = sched_getscheduler(0)) != -1);
94
Austin Schuh62288252020-11-18 23:26:04 -080095 {
96 // If we are RT, logging the scheduler will crash us. Mark that we just
97 // don't care.
98 aos::ScopedNotRealtime nrt;
99 LOG(INFO) << "scheduler is " << scheduler;
100 }
101
102 const bool result = scheduler == SCHED_FIFO || scheduler == SCHED_RR;
103 // Confirm that the scheduler matches AOS' interpretation of if we are
104 // realtime or not.
105 if (result) {
106 aos::CheckRealtime();
107 } else {
108 aos::CheckNotRealtime();
109 }
110 return result;
Austin Schuh3115a202019-05-27 21:02:14 -0700111}
James Kuszmaulc79768b2019-02-18 15:08:44 -0800112
Brian Silvermana5450a92020-08-12 19:59:57 -0700113class ShmEventLoopTest : public ::testing::TestWithParam<ReadMethod> {
114 public:
115 ShmEventLoopTest() {
116 if (GetParam() == ReadMethod::PIN) {
117 factory_.PinReads();
118 }
119 }
120
121 ShmEventLoopTestFactory *factory() { return &factory_; }
122
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -0700123 // Helper functions for testing when a fetcher cannot fetch the next message
124 // because it was overwritten
125 void TestNextMessageNotAvailable(const bool skip_timing_report) {
126 auto loop1 = factory()->MakePrimary("loop1");
127 if (skip_timing_report) {
128 loop1->SkipTimingReport();
129 }
130 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
131 auto loop2 = factory()->Make("loop2");
132 auto sender = loop2->MakeSender<TestMessage>("/test");
133 bool ran = false;
134 loop1->AddPhasedLoop(
135 [&sender](int) {
136 auto builder = sender.MakeBuilder();
137 TestMessage::Builder test_builder(*builder.fbb());
138 test_builder.add_value(0);
139 builder.CheckOk(builder.Send(test_builder.Finish()));
140 },
141 std::chrono::milliseconds(2));
142 loop1
143 ->AddTimer([this, &fetcher, &ran]() {
144 EXPECT_DEATH(fetcher.FetchNext(),
145 "The next message is no longer "
146 "available.*\"/test\".*\"aos\\.TestMessage\"");
147 factory()->Exit();
148 ran = true;
149 })
Philipp Schradera6712522023-07-05 20:25:11 -0700150 ->Schedule(loop1->monotonic_now() + std::chrono::seconds(4));
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -0700151 factory()->Run();
152 EXPECT_TRUE(ran);
153 }
154 void TestNextMessageNotAvailableNoRun(const bool skip_timing_report) {
155 auto loop1 = factory()->MakePrimary("loop1");
156 if (skip_timing_report) {
157 loop1->SkipTimingReport();
158 }
159 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
160 auto loop2 = factory()->Make("loop2");
161 auto sender = loop2->MakeSender<TestMessage>("/test");
162 time::PhasedLoop phased_loop(std::chrono::milliseconds(2),
163 loop2->monotonic_now());
164 for (int i = 0; i < 2000; ++i) {
165 auto builder = sender.MakeBuilder();
166 TestMessage::Builder test_builder(*builder.fbb());
167 test_builder.add_value(0);
168 builder.CheckOk(builder.Send(test_builder.Finish()));
169 phased_loop.SleepUntilNext();
170 }
171 EXPECT_DEATH(fetcher.FetchNext(),
172 "The next message is no longer "
173 "available.*\"/test\".*\"aos\\.TestMessage\"");
174 }
175
Brian Silvermana5450a92020-08-12 19:59:57 -0700176 private:
177 ShmEventLoopTestFactory factory_;
178};
179
180using ShmEventLoopDeathTest = ShmEventLoopTest;
181
Austin Schuha94e1002021-07-21 15:45:21 -0700182// Tests that we don't leave the calling thread realtime when calling Send
183// before Run.
184TEST_P(ShmEventLoopTest, SendBeforeRun) {
185 auto loop = factory()->MakePrimary("primary");
186 loop->SetRuntimeRealtimePriority(1);
187
188 auto loop2 = factory()->Make("loop2");
189 loop2->SetRuntimeRealtimePriority(2);
190 loop2->MakeWatcher("/test", [](const TestMessage &) {});
191 // Need the other one running for its watcher to record in SHM that it wants
192 // wakers to boost their priority, so leave it running in a thread for this
193 // test.
194 std::thread loop2_thread(
195 [&loop2]() { static_cast<ShmEventLoop *>(loop2.get())->Run(); });
196 std::this_thread::sleep_for(std::chrono::milliseconds(100));
197
198 auto sender = loop->MakeSender<TestMessage>("/test");
199 EXPECT_FALSE(IsRealtime());
200 {
201 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
202 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
203 builder.add_value(200);
milind1f1dca32021-07-03 13:50:07 -0700204 msg.CheckOk(msg.Send(builder.Finish()));
Austin Schuha94e1002021-07-21 15:45:21 -0700205 }
206 EXPECT_FALSE(IsRealtime());
207
208 static_cast<ShmEventLoop *>(loop2.get())->Exit();
209 loop2_thread.join();
210}
211
Austin Schuh3115a202019-05-27 21:02:14 -0700212// Tests that every handler type is realtime and runs. There are threads
213// involved and it's easy to miss one.
Brian Silvermana5450a92020-08-12 19:59:57 -0700214TEST_P(ShmEventLoopTest, AllHandlersAreRealtime) {
215 auto loop = factory()->MakePrimary("primary");
216 auto loop2 = factory()->Make("loop2");
Austin Schuh3115a202019-05-27 21:02:14 -0700217
218 loop->SetRuntimeRealtimePriority(1);
219
220 auto sender = loop2->MakeSender<TestMessage>("/test");
221
222 bool did_onrun = false;
223 bool did_timer = false;
224 bool did_watcher = false;
225
Brian Silvermana5450a92020-08-12 19:59:57 -0700226 auto timer = loop->AddTimer([this, &did_timer]() {
Austin Schuh3115a202019-05-27 21:02:14 -0700227 EXPECT_TRUE(IsRealtime());
228 did_timer = true;
Brian Silvermana5450a92020-08-12 19:59:57 -0700229 factory()->Exit();
Austin Schuh3115a202019-05-27 21:02:14 -0700230 });
231
232 loop->MakeWatcher("/test", [&did_watcher](const TestMessage &) {
233 EXPECT_TRUE(IsRealtime());
234 did_watcher = true;
235 });
236
237 loop->OnRun([&loop, &did_onrun, &sender, timer]() {
238 EXPECT_TRUE(IsRealtime());
239 did_onrun = true;
Philipp Schradera6712522023-07-05 20:25:11 -0700240 timer->Schedule(loop->monotonic_now() + chrono::milliseconds(100));
Alex Perrycb7da4b2019-08-28 19:35:56 -0700241
242 aos::Sender<TestMessage>::Builder msg = sender.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()));
Austin Schuh3115a202019-05-27 21:02:14 -0700246 });
James Kuszmaulc79768b2019-02-18 15:08:44 -0800247
Brian Silvermana5450a92020-08-12 19:59:57 -0700248 factory()->Run();
James Kuszmaulc79768b2019-02-18 15:08:44 -0800249
Austin Schuh3115a202019-05-27 21:02:14 -0700250 EXPECT_TRUE(did_onrun);
251 EXPECT_TRUE(did_timer);
252 EXPECT_TRUE(did_watcher);
James Kuszmaulc79768b2019-02-18 15:08:44 -0800253}
Austin Schuh52d325c2019-06-23 18:59:06 -0700254
255// Tests that missing a deadline inside the function still results in PhasedLoop
256// running at the right offset.
Brian Silvermana5450a92020-08-12 19:59:57 -0700257TEST_P(ShmEventLoopTest, DelayedPhasedLoop) {
258 auto loop1 = factory()->MakePrimary("primary");
Austin Schuh52d325c2019-06-23 18:59:06 -0700259
260 ::std::vector<::aos::monotonic_clock::time_point> times;
261
262 constexpr chrono::milliseconds kOffset = chrono::milliseconds(400);
263
264 loop1->AddPhasedLoop(
Brian Silvermana5450a92020-08-12 19:59:57 -0700265 [this, &times, &loop1, &kOffset](int count) {
Austin Schuh52d325c2019-06-23 18:59:06 -0700266 const ::aos::monotonic_clock::time_point monotonic_now =
267 loop1->monotonic_now();
268
269 // Compute our offset.
270 const ::aos::monotonic_clock::duration remainder =
271 monotonic_now.time_since_epoch() -
272 chrono::duration_cast<chrono::seconds>(
273 monotonic_now.time_since_epoch());
274
275 // Make sure we we are called near where we should be even when we
276 // delay.
277 constexpr chrono::milliseconds kEpsilon(200);
278 EXPECT_LT(remainder, kOffset + kEpsilon);
279 EXPECT_GT(remainder, kOffset - kEpsilon);
280
281 // Confirm that we see the missed count when we sleep.
282 if (times.size() == 0) {
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800283 CHECK_EQ(count, 1);
Austin Schuh52d325c2019-06-23 18:59:06 -0700284 } else {
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800285 CHECK_EQ(count, 3);
Austin Schuh52d325c2019-06-23 18:59:06 -0700286 }
287
288 times.push_back(loop1->monotonic_now());
289 if (times.size() == 2) {
Brian Silvermana5450a92020-08-12 19:59:57 -0700290 factory()->Exit();
Austin Schuh52d325c2019-06-23 18:59:06 -0700291 }
292
293 // Now, add a large delay. This should push us up to 3 cycles.
294 ::std::this_thread::sleep_for(chrono::milliseconds(2500));
295 },
296 chrono::seconds(1), kOffset);
297
Brian Silvermana5450a92020-08-12 19:59:57 -0700298 factory()->Run();
Austin Schuh52d325c2019-06-23 18:59:06 -0700299
300 EXPECT_EQ(times.size(), 2u);
301}
302
James Kuszmaul9f998082024-05-23 15:37:35 -0700303// Tests that the ShmEventLoop::Exit() method causes the ShmEventLoop to return
304// with a successful status.
305TEST_P(ShmEventLoopTest, SuccessfulExitTest) {
306 auto loop1 = factory()->MakePrimary("primary");
307 auto exit_handle = factory()->MakeExitHandle();
308
309 loop1->OnRun([this, &exit_handle]() {
310 factory()->Exit();
311 // The second Exit() call should get ignored.
312 exit_handle->Exit(aos::Error::MakeUnexpectedError("Hello, World!"));
313 });
314
315 EXPECT_TRUE(factory()->Run().has_value());
316}
317
Brian Silverman5120afb2020-01-31 17:44:35 -0800318// Test GetWatcherSharedMemory in a few basic scenarios.
Brian Silvermana5450a92020-08-12 19:59:57 -0700319TEST_P(ShmEventLoopDeathTest, GetWatcherSharedMemory) {
320 auto generic_loop1 = factory()->MakePrimary("primary");
Brian Silverman5120afb2020-01-31 17:44:35 -0800321 ShmEventLoop *const loop1 = static_cast<ShmEventLoop *>(generic_loop1.get());
322 const auto channel = configuration::GetChannel(
323 loop1->configuration(), "/test", TestMessage::GetFullyQualifiedName(),
324 loop1->name(), loop1->node());
325
326 // First verify it handles an invalid channel reasonably.
327 EXPECT_DEATH(loop1->GetWatcherSharedMemory(channel),
328 "No watcher found for channel");
329
330 // Then, actually create a watcher, and verify it returns something sane.
Brian Silvermana5450a92020-08-12 19:59:57 -0700331 absl::Span<const char> shared_memory;
332 bool ran = false;
333 loop1->MakeWatcher("/test", [this, &shared_memory,
334 &ran](const TestMessage &message) {
335 EXPECT_FALSE(ran);
336 ran = true;
337 // If we're using pinning, then we can verify that the message is actually
338 // in the specified region.
339 if (GetParam() == ReadMethod::PIN) {
340 EXPECT_GE(reinterpret_cast<const char *>(&message),
341 shared_memory.begin());
342 EXPECT_LT(reinterpret_cast<const char *>(&message), shared_memory.end());
343 }
344 factory()->Exit();
345 });
346 shared_memory = loop1->GetWatcherSharedMemory(channel);
347 EXPECT_FALSE(shared_memory.empty());
348
349 auto loop2 = factory()->Make("sender");
350 auto sender = loop2->MakeSender<TestMessage>("/test");
351 generic_loop1->OnRun([&sender]() {
352 auto builder = sender.MakeBuilder();
353 TestMessage::Builder test_builder(*builder.fbb());
354 test_builder.add_value(1);
milind1f1dca32021-07-03 13:50:07 -0700355 builder.CheckOk(builder.Send(test_builder.Finish()));
Brian Silvermana5450a92020-08-12 19:59:57 -0700356 });
357 factory()->Run();
358 EXPECT_TRUE(ran);
Brian Silverman5120afb2020-01-31 17:44:35 -0800359}
360
Brian Silvermana5450a92020-08-12 19:59:57 -0700361TEST_P(ShmEventLoopTest, GetSenderSharedMemory) {
362 auto generic_loop1 = factory()->MakePrimary("primary");
Brian Silverman5120afb2020-01-31 17:44:35 -0800363 ShmEventLoop *const loop1 = static_cast<ShmEventLoop *>(generic_loop1.get());
364
Brian Silvermana5450a92020-08-12 19:59:57 -0700365 // Check that GetSenderSharedMemory returns non-null/non-empty memory span.
Brian Silverman5120afb2020-01-31 17:44:35 -0800366 auto sender = loop1->MakeSender<TestMessage>("/test");
Brian Silvermana5450a92020-08-12 19:59:57 -0700367 const absl::Span<char> shared_memory = loop1->GetSenderSharedMemory(&sender);
368 EXPECT_FALSE(shared_memory.empty());
369
370 auto builder = sender.MakeBuilder();
371 uint8_t *buffer;
James Kuszmaul65541cb2022-11-08 14:53:47 -0800372 builder.fbb()->CreateUninitializedVector(5, &buffer);
Brian Silvermana5450a92020-08-12 19:59:57 -0700373 EXPECT_GE(reinterpret_cast<char *>(buffer), shared_memory.begin());
374 EXPECT_LT(reinterpret_cast<char *>(buffer), shared_memory.end());
Brian Silverman5120afb2020-01-31 17:44:35 -0800375}
376
Brian Silvermana5450a92020-08-12 19:59:57 -0700377TEST_P(ShmEventLoopTest, GetFetcherPrivateMemory) {
378 auto generic_loop1 = factory()->MakePrimary("primary");
Brian Silverman6d2b3592020-06-18 14:40:15 -0700379 ShmEventLoop *const loop1 = static_cast<ShmEventLoop *>(generic_loop1.get());
380
Brian Silvermana5450a92020-08-12 19:59:57 -0700381 // Check that GetFetcherPrivateMemory returns non-null/non-empty memory span.
Brian Silverman6d2b3592020-06-18 14:40:15 -0700382 auto fetcher = loop1->MakeFetcher<TestMessage>("/test");
Brian Silvermana5450a92020-08-12 19:59:57 -0700383 const auto private_memory = loop1->GetFetcherPrivateMemory(&fetcher);
384 EXPECT_FALSE(private_memory.empty());
385
386 auto loop2 = factory()->Make("sender");
387 auto sender = loop2->MakeSender<TestMessage>("/test");
388 {
389 auto builder = sender.MakeBuilder();
390 TestMessage::Builder test_builder(*builder.fbb());
391 test_builder.add_value(1);
milind1f1dca32021-07-03 13:50:07 -0700392 builder.CheckOk(builder.Send(test_builder.Finish()));
Brian Silvermana5450a92020-08-12 19:59:57 -0700393 }
394
395 ASSERT_TRUE(fetcher.Fetch());
396 EXPECT_GE(fetcher.context().data, private_memory.begin());
397 EXPECT_LT(fetcher.context().data, private_memory.end());
Brian Silverman6d2b3592020-06-18 14:40:15 -0700398}
399
Brian Silverman0eaa1da2020-08-12 20:03:52 -0700400// Tests that corrupting the bytes around the data buffer results in a crash.
401TEST_P(ShmEventLoopDeathTest, OutOfBoundsWrite) {
402 auto loop1 = factory()->Make("loop1");
403 std::unique_ptr<aos::RawSender> sender =
404 loop1->MakeRawSender(configuration::GetChannel(
405 loop1->configuration(), "/test", "aos.TestMessage", "", nullptr));
406 for (size_t i = 0; i < kChannelDataRedzone; ++i) {
407 SCOPED_TRACE(std::to_string(i));
408 EXPECT_DEATH(
409 {
Philipp Schrader4473d2c2023-12-01 13:43:09 -0800410 // Can't use `data()[-1 -i]` here because that's undefined behaviour.
411 // We do manual pointer arithmetic to work around that.
412 ++(*(static_cast<char *>(sender->data()) - 1 - i));
milind1f1dca32021-07-03 13:50:07 -0700413 sender->CheckOk(sender->Send(0));
Brian Silverman0eaa1da2020-08-12 20:03:52 -0700414 },
415 "Somebody wrote outside the buffer of their message");
416 EXPECT_DEATH(
417 {
418 ++static_cast<char *>(sender->data())[sender->size() + i];
milind1f1dca32021-07-03 13:50:07 -0700419 sender->CheckOk(sender->Send(0));
Brian Silverman0eaa1da2020-08-12 20:03:52 -0700420 },
421 "Somebody wrote outside the buffer of their message");
422 }
423}
424
Brian Silvermance418d02021-11-03 11:25:52 -0700425// Tests that the next message not being available prints a helpful error in the
426// normal case.
427TEST_P(ShmEventLoopDeathTest, NextMessageNotAvailable) {
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -0700428 TestNextMessageNotAvailable(false);
Brian Silvermance418d02021-11-03 11:25:52 -0700429}
430
431// Tests that the next message not being available prints a helpful error with
432// timing reports disabled.
433TEST_P(ShmEventLoopDeathTest, NextMessageNotAvailableNoTimingReports) {
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -0700434 TestNextMessageNotAvailable(true);
Brian Silvermance418d02021-11-03 11:25:52 -0700435}
436
437// Tests that the next message not being available prints a helpful error even
438// when Run is never called.
439TEST_P(ShmEventLoopDeathTest, NextMessageNotAvailableNoRun) {
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -0700440 TestNextMessageNotAvailableNoRun(false);
Brian Silvermance418d02021-11-03 11:25:52 -0700441}
442
443// Tests that the next message not being available prints a helpful error even
444// when Run is never called without timing reports.
445TEST_P(ShmEventLoopDeathTest, NextMessageNotAvailableNoRunNoTimingReports) {
Eric Schmiedebergef44b8a2022-02-28 17:30:38 -0700446 TestNextMessageNotAvailableNoRun(true);
Brian Silvermance418d02021-11-03 11:25:52 -0700447}
448
Brian Silvermane1fe2512022-08-14 23:18:50 -0700449// Test that an ExitHandle outliving its EventLoop is caught.
450TEST_P(ShmEventLoopDeathTest, ExitHandleOutlivesEventLoop) {
451 auto loop1 = factory()->MakePrimary("loop1");
452 auto exit_handle = static_cast<ShmEventLoop *>(loop1.get())->MakeExitHandle();
453 EXPECT_DEATH(loop1.reset(),
454 "All ExitHandles must be destroyed before the ShmEventLoop");
455}
456
Austin Schuh39788ff2019-12-01 18:22:57 -0800457// TODO(austin): Test that missing a deadline with a timer recovers as expected.
458
James Kuszmaulf4bf9fe2021-05-10 22:58:24 -0700459INSTANTIATE_TEST_SUITE_P(ShmEventLoopCopyTest, ShmEventLoopTest,
Brian Silvermance418d02021-11-03 11:25:52 -0700460 ::testing::Values(ReadMethod::COPY));
James Kuszmaulf4bf9fe2021-05-10 22:58:24 -0700461INSTANTIATE_TEST_SUITE_P(ShmEventLoopPinTest, ShmEventLoopTest,
Brian Silvermance418d02021-11-03 11:25:52 -0700462 ::testing::Values(ReadMethod::PIN));
James Kuszmaulf4bf9fe2021-05-10 22:58:24 -0700463INSTANTIATE_TEST_SUITE_P(ShmEventLoopCopyDeathTest, ShmEventLoopDeathTest,
Brian Silvermance418d02021-11-03 11:25:52 -0700464 ::testing::Values(ReadMethod::COPY));
James Kuszmaulf4bf9fe2021-05-10 22:58:24 -0700465INSTANTIATE_TEST_SUITE_P(ShmEventLoopPinDeathTest, ShmEventLoopDeathTest,
Brian Silvermance418d02021-11-03 11:25:52 -0700466 ::testing::Values(ReadMethod::PIN));
Brian Silvermana5450a92020-08-12 19:59:57 -0700467
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800468} // namespace aos::testing