xref: /openbmc/sdbusplus/test/async/watchdog.cpp (revision bc1399744a317307a3f9061de32b27681721248b)
1*bc139974SPatrick Williams #include <sdbusplus/async.hpp>
2*bc139974SPatrick Williams #include <sdbusplus/bus.hpp>
3*bc139974SPatrick Williams #include <sdbusplus/test/sdbus_mock.hpp>
4*bc139974SPatrick Williams 
5*bc139974SPatrick Williams #include <gmock/gmock.h>
6*bc139974SPatrick Williams #include <gtest/gtest.h>
7*bc139974SPatrick Williams 
8*bc139974SPatrick Williams namespace sdbusplus::async
9*bc139974SPatrick Williams {
10*bc139974SPatrick Williams struct WatchdogMock : public sdbusplus::SdBusImpl
11*bc139974SPatrick Williams {
WatchdogMocksdbusplus::async::WatchdogMock12*bc139974SPatrick Williams     WatchdogMock() : sdbusplus::SdBusImpl()
13*bc139974SPatrick Williams     {
14*bc139974SPatrick Williams         sd_bus_open(&busp);
15*bc139974SPatrick Williams     }
16*bc139974SPatrick Williams 
~WatchdogMocksdbusplus::async::WatchdogMock17*bc139974SPatrick Williams     ~WatchdogMock()
18*bc139974SPatrick Williams     {
19*bc139974SPatrick Williams         sd_bus_unref(busp);
20*bc139974SPatrick Williams     }
21*bc139974SPatrick Williams 
22*bc139974SPatrick Williams     MOCK_METHOD(int, sd_notify, (int, const char*), (override));
23*bc139974SPatrick Williams 
24*bc139974SPatrick Williams     MOCK_METHOD(int, sd_watchdog_enabled, (int, uint64_t* usec), (override));
25*bc139974SPatrick Williams 
26*bc139974SPatrick Williams     sdbusplus::bus::busp_t busp = nullptr;
27*bc139974SPatrick Williams };
28*bc139974SPatrick Williams 
29*bc139974SPatrick Williams struct WatchdogContext : public testing::Test
30*bc139974SPatrick Williams {
31*bc139974SPatrick Williams     WatchdogMock sdbusMock;
32*bc139974SPatrick Williams     sdbusplus::async::context ctx;
33*bc139974SPatrick Williams 
WatchdogContextsdbusplus::async::WatchdogContext34*bc139974SPatrick Williams     WatchdogContext() : ctx(sdbusplus::bus_t(sdbusMock.busp, &sdbusMock)) {}
35*bc139974SPatrick Williams 
36*bc139974SPatrick Williams     ~WatchdogContext() noexcept override = default;
37*bc139974SPatrick Williams 
TearDownsdbusplus::async::WatchdogContext38*bc139974SPatrick Williams     void TearDown() override {}
39*bc139974SPatrick Williams 
spawnStopsdbusplus::async::WatchdogContext40*bc139974SPatrick Williams     void spawnStop()
41*bc139974SPatrick Williams     {
42*bc139974SPatrick Williams         ctx.spawn(stdexec::just() |
43*bc139974SPatrick Williams                   stdexec::then([this]() { ctx.request_stop(); }));
44*bc139974SPatrick Williams     }
45*bc139974SPatrick Williams 
runToStopsdbusplus::async::WatchdogContext46*bc139974SPatrick Williams     void runToStop()
47*bc139974SPatrick Williams     {
48*bc139974SPatrick Williams         spawnStop();
49*bc139974SPatrick Williams         ctx.run();
50*bc139974SPatrick Williams     }
51*bc139974SPatrick Williams };
52*bc139974SPatrick Williams 
TEST_F(WatchdogContext,WatchdogEnabledAndHeartbeat)53*bc139974SPatrick Williams TEST_F(WatchdogContext, WatchdogEnabledAndHeartbeat)
54*bc139974SPatrick Williams {
55*bc139974SPatrick Williams     using namespace testing;
56*bc139974SPatrick Williams     using namespace std::literals;
57*bc139974SPatrick Williams 
58*bc139974SPatrick Williams     // Expect sd_watchdog_enabled to be called once and return .1 second
59*bc139974SPatrick Williams     EXPECT_CALL(sdbusMock, sd_watchdog_enabled(_, _))
60*bc139974SPatrick Williams         .WillOnce([](int, uint64_t* usec) {
61*bc139974SPatrick Williams             *usec = 100000; // .1 second
62*bc139974SPatrick Williams             return 0;
63*bc139974SPatrick Williams         });
64*bc139974SPatrick Williams 
65*bc139974SPatrick Williams     // Expect sd_notify to be called at least once for heartbeat
66*bc139974SPatrick Williams     // The watchdog_loop divides the time by 2, so it should be
67*bc139974SPatrick Williams     // called every 0.05 seconds.
68*bc139974SPatrick Williams     EXPECT_CALL(sdbusMock, sd_notify(_, StrEq("WATCHDOG=1")))
69*bc139974SPatrick Williams         .WillRepeatedly(Return(0));
70*bc139974SPatrick Williams 
71*bc139974SPatrick Williams     // Run the context for a short period to allow watchdog_loop to execute
72*bc139974SPatrick Williams     // and send a handful of heartbeats.
73*bc139974SPatrick Williams     ctx.spawn(sdbusplus::async::sleep_for(ctx, 1s));
74*bc139974SPatrick Williams     runToStop();
75*bc139974SPatrick Williams 
76*bc139974SPatrick Williams     // The EXPECT_CALL for sd_notify will verify if it was called as expected.
77*bc139974SPatrick Williams     // If the test passes, it means sd_watchdog_enabled was called,
78*bc139974SPatrick Williams     // and sd_notify was called for heartbeats.
79*bc139974SPatrick Williams }
80*bc139974SPatrick Williams 
TEST_F(WatchdogContext,WatchdogDisabled)81*bc139974SPatrick Williams TEST_F(WatchdogContext, WatchdogDisabled)
82*bc139974SPatrick Williams {
83*bc139974SPatrick Williams     using namespace testing;
84*bc139974SPatrick Williams     using namespace std::literals;
85*bc139974SPatrick Williams 
86*bc139974SPatrick Williams     // Expect sd_watchdog_enabled to be called once and return 0 (disabled)
87*bc139974SPatrick Williams     EXPECT_CALL(sdbusMock, sd_watchdog_enabled(_, _))
88*bc139974SPatrick Williams         .WillOnce([](int, uint64_t* usec) {
89*bc139974SPatrick Williams             *usec = 0; // Watchdog disabled
90*bc139974SPatrick Williams             return 0;
91*bc139974SPatrick Williams         });
92*bc139974SPatrick Williams 
93*bc139974SPatrick Williams     // Expect sd_notify will NOT be called
94*bc139974SPatrick Williams     EXPECT_CALL(sdbusMock, sd_notify(_, _)).Times(0);
95*bc139974SPatrick Williams 
96*bc139974SPatrick Williams     // Run the context. No sleep is needed as watchdog should exit immediately.
97*bc139974SPatrick Williams     runToStop();
98*bc139974SPatrick Williams }
99*bc139974SPatrick Williams 
100*bc139974SPatrick Williams } // namespace sdbusplus::async
101