xref: /openbmc/phosphor-watchdog/test/watchdog.cpp (revision 6d12acf23caf73be581e2c48f17be55a368af681)
1af60e630SWilliam A. Kennington III #include "watchdog.hpp"
2af60e630SWilliam A. Kennington III 
3287105ceSWilliam A. Kennington III #include <sdbusplus/bus.hpp>
4287105ceSWilliam A. Kennington III #include <sdeventplus/event.hpp>
56ac6a347SPatrick Williams 
66ac6a347SPatrick Williams #include <chrono>
76ac6a347SPatrick Williams #include <memory>
8af60e630SWilliam A. Kennington III #include <thread>
9af60e630SWilliam A. Kennington III #include <utility>
10af60e630SWilliam A. Kennington III 
11287105ceSWilliam A. Kennington III #include <gtest/gtest.h>
12287105ceSWilliam A. Kennington III 
13c35135d3SOfer Yehielli namespace phosphor
14c35135d3SOfer Yehielli {
15c35135d3SOfer Yehielli namespace watchdog
16c35135d3SOfer Yehielli {
17af60e630SWilliam A. Kennington III 
18287105ceSWilliam A. Kennington III using namespace std::chrono;
19287105ceSWilliam A. Kennington III using namespace std::chrono_literals;
20287105ceSWilliam A. Kennington III 
21287105ceSWilliam A. Kennington III constexpr auto TEST_MIN_INTERVAL = duration<uint64_t, std::deci>(2);
22287105ceSWilliam A. Kennington III 
23287105ceSWilliam A. Kennington III // Test Watchdog functionality
24287105ceSWilliam A. Kennington III class WdogTest : public ::testing::Test
25287105ceSWilliam A. Kennington III {
26287105ceSWilliam A. Kennington III   public:
27287105ceSWilliam A. Kennington III     // The unit time used to measure the timer
28*6d12acf2SManojkiran Eda     // This should be large enough to accommodate drift
29287105ceSWilliam A. Kennington III     using Quantum = duration<uint64_t, std::deci>;
30287105ceSWilliam A. Kennington III 
31287105ceSWilliam A. Kennington III     // Gets called as part of each TEST_F construction
WdogTest()32287105ceSWilliam A. Kennington III     WdogTest() :
33287105ceSWilliam A. Kennington III         event(sdeventplus::Event::get_default()),
34287105ceSWilliam A. Kennington III         bus(sdbusplus::bus::new_default()),
35287105ceSWilliam A. Kennington III         wdog(std::make_unique<Watchdog>(
36287105ceSWilliam A. Kennington III             bus, TEST_PATH, event, Watchdog::ActionTargetMap(), std::nullopt,
37287105ceSWilliam A. Kennington III             milliseconds(TEST_MIN_INTERVAL).count())),
38287105ceSWilliam A. Kennington III 
39287105ceSWilliam A. Kennington III         defaultInterval(Quantum(3))
40287105ceSWilliam A. Kennington III 
41287105ceSWilliam A. Kennington III     {
42287105ceSWilliam A. Kennington III         wdog->interval(milliseconds(defaultInterval).count());
43287105ceSWilliam A. Kennington III         // Initially the watchdog would be disabled
44287105ceSWilliam A. Kennington III         EXPECT_FALSE(wdog->enabled());
45287105ceSWilliam A. Kennington III     }
46287105ceSWilliam A. Kennington III 
47287105ceSWilliam A. Kennington III     // sdevent Event handle
48287105ceSWilliam A. Kennington III     sdeventplus::Event event;
49287105ceSWilliam A. Kennington III 
50287105ceSWilliam A. Kennington III     // sdbusplus handle
5173bd5277SPatrick Williams     sdbusplus::bus_t bus;
52287105ceSWilliam A. Kennington III 
53287105ceSWilliam A. Kennington III     // Watchdog object
54287105ceSWilliam A. Kennington III     std::unique_ptr<Watchdog> wdog;
55287105ceSWilliam A. Kennington III 
56287105ceSWilliam A. Kennington III     // This is the default interval as given in Interface definition
57287105ceSWilliam A. Kennington III     Quantum defaultInterval;
58287105ceSWilliam A. Kennington III 
59287105ceSWilliam A. Kennington III   protected:
60287105ceSWilliam A. Kennington III     // Dummy name for object path
61287105ceSWilliam A. Kennington III     // This is just to satisfy the constructor. Does not have
62287105ceSWilliam A. Kennington III     // a need to check if the objects paths have been created.
63287105ceSWilliam A. Kennington III     static constexpr auto TEST_PATH = "/test/path";
64287105ceSWilliam A. Kennington III 
65287105ceSWilliam A. Kennington III     // Returns how long it took for the current watchdog timer to be
66287105ceSWilliam A. Kennington III     // disabled or have its timeRemaining reset.
waitForWatchdog(Quantum timeLimit)67287105ceSWilliam A. Kennington III     Quantum waitForWatchdog(Quantum timeLimit)
68af60e630SWilliam A. Kennington III     {
69af60e630SWilliam A. Kennington III         auto previousTimeRemaining = wdog->timeRemaining();
703964f001SWilliam A. Kennington III         auto ret = Quantum(0);
71287105ceSWilliam A. Kennington III         while (ret < timeLimit &&
72287105ceSWilliam A. Kennington III                previousTimeRemaining >= wdog->timeRemaining() &&
73af60e630SWilliam A. Kennington III                wdog->timerEnabled())
74af60e630SWilliam A. Kennington III         {
75af60e630SWilliam A. Kennington III             previousTimeRemaining = wdog->timeRemaining();
76af60e630SWilliam A. Kennington III 
773964f001SWilliam A. Kennington III             constexpr auto sleepTime = Quantum(1);
78af60e630SWilliam A. Kennington III             if (event.run(sleepTime) == 0)
79af60e630SWilliam A. Kennington III             {
80af60e630SWilliam A. Kennington III                 ret += sleepTime;
81af60e630SWilliam A. Kennington III             }
82af60e630SWilliam A. Kennington III         }
83af60e630SWilliam A. Kennington III 
84af60e630SWilliam A. Kennington III         return ret;
85af60e630SWilliam A. Kennington III     }
86287105ceSWilliam A. Kennington III };
87af60e630SWilliam A. Kennington III 
88af60e630SWilliam A. Kennington III /** @brief Make sure that watchdog is started and not enabled */
TEST_F(WdogTest,createWdogAndDontEnable)89af60e630SWilliam A. Kennington III TEST_F(WdogTest, createWdogAndDontEnable)
90af60e630SWilliam A. Kennington III {
91af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->enabled());
92af60e630SWilliam A. Kennington III     EXPECT_EQ(0, wdog->timeRemaining());
93af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->timerExpired());
94af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->timerEnabled());
95af60e630SWilliam A. Kennington III 
96af60e630SWilliam A. Kennington III     // We should be able to configure persistent properties
97af60e630SWilliam A. Kennington III     // while disabled
98af60e630SWilliam A. Kennington III     auto newAction = Watchdog::Action::PowerOff;
99af60e630SWilliam A. Kennington III     EXPECT_EQ(newAction, wdog->expireAction(newAction));
100af60e630SWilliam A. Kennington III     auto newIntervalMs = milliseconds(defaultInterval * 2).count();
101af60e630SWilliam A. Kennington III     EXPECT_EQ(newIntervalMs, wdog->interval(newIntervalMs));
102af60e630SWilliam A. Kennington III 
103af60e630SWilliam A. Kennington III     EXPECT_EQ(newAction, wdog->expireAction());
104af60e630SWilliam A. Kennington III     EXPECT_EQ(newIntervalMs, wdog->interval());
105af60e630SWilliam A. Kennington III 
106af60e630SWilliam A. Kennington III     // We won't be able to configure timeRemaining
107af60e630SWilliam A. Kennington III     EXPECT_EQ(0, wdog->timeRemaining(1000));
108af60e630SWilliam A. Kennington III     EXPECT_EQ(0, wdog->timeRemaining());
109af60e630SWilliam A. Kennington III 
110af60e630SWilliam A. Kennington III     // Timer should not have become enabled
111af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->enabled());
112af60e630SWilliam A. Kennington III     EXPECT_EQ(0, wdog->timeRemaining());
113af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->timerExpired());
114af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->timerEnabled());
115af60e630SWilliam A. Kennington III }
116af60e630SWilliam A. Kennington III 
117af60e630SWilliam A. Kennington III /** @brief Make sure that watchdog is started and enabled */
TEST_F(WdogTest,createWdogAndEnable)118af60e630SWilliam A. Kennington III TEST_F(WdogTest, createWdogAndEnable)
119af60e630SWilliam A. Kennington III {
120af60e630SWilliam A. Kennington III     // Enable and then verify
121af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->enabled(true));
122af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->timerExpired());
123af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->timerEnabled());
124af60e630SWilliam A. Kennington III 
125af60e630SWilliam A. Kennington III     // Get the configured interval
126af60e630SWilliam A. Kennington III     auto remaining = milliseconds(wdog->timeRemaining());
127af60e630SWilliam A. Kennington III 
128af60e630SWilliam A. Kennington III     // Its possible that we are off by few msecs depending on
129af60e630SWilliam A. Kennington III     // how we get scheduled. So checking a range here.
1303964f001SWilliam A. Kennington III     EXPECT_TRUE((remaining >= defaultInterval - Quantum(1)) &&
131af60e630SWilliam A. Kennington III                 (remaining <= defaultInterval));
132af60e630SWilliam A. Kennington III 
133af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->timerExpired());
134af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->timerEnabled());
135af60e630SWilliam A. Kennington III }
136af60e630SWilliam A. Kennington III 
137af60e630SWilliam A. Kennington III /** @brief Make sure that watchdog is started and enabled.
138af60e630SWilliam A. Kennington III  *         Later, disable watchdog
139af60e630SWilliam A. Kennington III  */
TEST_F(WdogTest,createWdogAndEnableThenDisable)140af60e630SWilliam A. Kennington III TEST_F(WdogTest, createWdogAndEnableThenDisable)
141af60e630SWilliam A. Kennington III {
142af60e630SWilliam A. Kennington III     // Enable and then verify
143af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->enabled(true));
144af60e630SWilliam A. Kennington III 
145af60e630SWilliam A. Kennington III     // Disable and then verify
146af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->enabled(false));
147af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->enabled());
148af60e630SWilliam A. Kennington III     EXPECT_EQ(0, wdog->timeRemaining());
149af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->timerExpired());
150af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->timerEnabled());
151af60e630SWilliam A. Kennington III }
152af60e630SWilliam A. Kennington III 
153af60e630SWilliam A. Kennington III /** @brief Make sure that watchdog is started and enabled.
1543964f001SWilliam A. Kennington III  *         Wait for 5 quantums and make sure that the remaining
1553964f001SWilliam A. Kennington III  *         time shows 5 fewer quantums.
156af60e630SWilliam A. Kennington III  */
TEST_F(WdogTest,enableWdogAndWait5Quantums)1573964f001SWilliam A. Kennington III TEST_F(WdogTest, enableWdogAndWait5Quantums)
158af60e630SWilliam A. Kennington III {
159af60e630SWilliam A. Kennington III     // Enable and then verify
160af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->enabled(true));
161af60e630SWilliam A. Kennington III 
1623964f001SWilliam A. Kennington III     // Sleep for 5 quantums
1633964f001SWilliam A. Kennington III     auto sleepTime = Quantum(2);
1643964f001SWilliam A. Kennington III     ASSERT_LT(sleepTime, defaultInterval);
165af60e630SWilliam A. Kennington III     std::this_thread::sleep_for(sleepTime);
166af60e630SWilliam A. Kennington III 
1673964f001SWilliam A. Kennington III     // Get the remaining time again and expectation is that we get fewer
168af60e630SWilliam A. Kennington III     auto remaining = milliseconds(wdog->timeRemaining());
169af60e630SWilliam A. Kennington III     auto expected = defaultInterval - sleepTime;
170af60e630SWilliam A. Kennington III 
171af60e630SWilliam A. Kennington III     // Its possible that we are off by few msecs depending on
172af60e630SWilliam A. Kennington III     // how we get scheduled. So checking a range here.
1733964f001SWilliam A. Kennington III     EXPECT_TRUE((remaining >= expected - Quantum(1)) &&
174af60e630SWilliam A. Kennington III                 (remaining <= expected));
175af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->timerExpired());
176af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->timerEnabled());
177af60e630SWilliam A. Kennington III }
178af60e630SWilliam A. Kennington III 
179af60e630SWilliam A. Kennington III /** @brief Make sure that watchdog is started and enabled.
1803964f001SWilliam A. Kennington III  *         Wait 1 quantum and then reset the timer to 5 quantums
1813964f001SWilliam A. Kennington III  *         and then expect the watchdog to expire in 5 quantums
182af60e630SWilliam A. Kennington III  */
TEST_F(WdogTest,enableWdogAndResetTo5Quantums)1833964f001SWilliam A. Kennington III TEST_F(WdogTest, enableWdogAndResetTo5Quantums)
184af60e630SWilliam A. Kennington III {
185af60e630SWilliam A. Kennington III     // Enable and then verify
186af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->enabled(true));
187af60e630SWilliam A. Kennington III 
188af60e630SWilliam A. Kennington III     // Sleep for 1 second
1893964f001SWilliam A. Kennington III     std::this_thread::sleep_for(Quantum(1));
190af60e630SWilliam A. Kennington III 
191af60e630SWilliam A. Kennington III     // Timer should still be running unexpired
192af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->timerExpired());
193af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->timerEnabled());
194af60e630SWilliam A. Kennington III 
1953964f001SWilliam A. Kennington III     // Next timer will expire in 5 quantums from now.
1963964f001SWilliam A. Kennington III     auto expireTime = Quantum(5);
197af60e630SWilliam A. Kennington III     auto expireTimeMs = milliseconds(expireTime).count();
198af60e630SWilliam A. Kennington III     EXPECT_EQ(expireTimeMs, wdog->timeRemaining(expireTimeMs));
199af60e630SWilliam A. Kennington III 
200af60e630SWilliam A. Kennington III     // Waiting for expiration
2013964f001SWilliam A. Kennington III     EXPECT_EQ(expireTime - Quantum(1), waitForWatchdog(expireTime));
202af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->timerExpired());
203af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->timerEnabled());
204af60e630SWilliam A. Kennington III }
205af60e630SWilliam A. Kennington III 
206af60e630SWilliam A. Kennington III /** @brief Make sure the Interval can be updated directly.
207af60e630SWilliam A. Kennington III  */
TEST_F(WdogTest,verifyIntervalUpdateReceived)208af60e630SWilliam A. Kennington III TEST_F(WdogTest, verifyIntervalUpdateReceived)
209af60e630SWilliam A. Kennington III {
2103964f001SWilliam A. Kennington III     auto expireTime = Quantum(5);
211af60e630SWilliam A. Kennington III     auto expireTimeMs = milliseconds(expireTime).count();
212af60e630SWilliam A. Kennington III     EXPECT_EQ(expireTimeMs, wdog->interval(expireTimeMs));
213af60e630SWilliam A. Kennington III 
214af60e630SWilliam A. Kennington III     // Expect an update in the Interval
215af60e630SWilliam A. Kennington III     EXPECT_EQ(expireTimeMs, wdog->interval());
216af60e630SWilliam A. Kennington III }
217af60e630SWilliam A. Kennington III 
218af60e630SWilliam A. Kennington III /** @brief Make sure the Interval can be updated while the timer is running.
219af60e630SWilliam A. Kennington III  */
TEST_F(WdogTest,verifyIntervalUpdateRunning)220af60e630SWilliam A. Kennington III TEST_F(WdogTest, verifyIntervalUpdateRunning)
221af60e630SWilliam A. Kennington III {
222af60e630SWilliam A. Kennington III     const auto oldInterval = milliseconds(wdog->interval());
223af60e630SWilliam A. Kennington III     const auto newInterval = 5s;
224af60e630SWilliam A. Kennington III 
225af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->enabled(true));
226af60e630SWilliam A. Kennington III     auto remaining = milliseconds(wdog->timeRemaining());
227af60e630SWilliam A. Kennington III     EXPECT_GE(oldInterval, remaining);
2283964f001SWilliam A. Kennington III     EXPECT_LE(oldInterval - Quantum(1), remaining);
229af60e630SWilliam A. Kennington III     EXPECT_EQ(newInterval,
230af60e630SWilliam A. Kennington III               milliseconds(wdog->interval(milliseconds(newInterval).count())));
231af60e630SWilliam A. Kennington III 
232af60e630SWilliam A. Kennington III     // Expect only the interval to update
233af60e630SWilliam A. Kennington III     remaining = milliseconds(wdog->timeRemaining());
234af60e630SWilliam A. Kennington III     EXPECT_GE(oldInterval, remaining);
2353964f001SWilliam A. Kennington III     EXPECT_LE(oldInterval - Quantum(1), remaining);
236af60e630SWilliam A. Kennington III     EXPECT_EQ(newInterval, milliseconds(wdog->interval()));
237af60e630SWilliam A. Kennington III 
238af60e630SWilliam A. Kennington III     // Expect reset to use the new interval
239af60e630SWilliam A. Kennington III     wdog->resetTimeRemaining(false);
240af60e630SWilliam A. Kennington III     remaining = milliseconds(wdog->timeRemaining());
241af60e630SWilliam A. Kennington III     EXPECT_GE(newInterval, remaining);
2423964f001SWilliam A. Kennington III     EXPECT_LE(newInterval - Quantum(1), remaining);
243af60e630SWilliam A. Kennington III }
244af60e630SWilliam A. Kennington III 
245af60e630SWilliam A. Kennington III /** @brief Make sure that watchdog is started and enabled.
2463964f001SWilliam A. Kennington III  *         Wait default interval quantums and make sure that wdog has died
247af60e630SWilliam A. Kennington III  */
TEST_F(WdogTest,enableWdogAndWaitTillEnd)248af60e630SWilliam A. Kennington III TEST_F(WdogTest, enableWdogAndWaitTillEnd)
249af60e630SWilliam A. Kennington III {
250af60e630SWilliam A. Kennington III     // Enable and then verify
251af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->enabled(true));
252af60e630SWilliam A. Kennington III 
253af60e630SWilliam A. Kennington III     // Waiting default expiration
2543964f001SWilliam A. Kennington III     EXPECT_EQ(defaultInterval - Quantum(1), waitForWatchdog(defaultInterval));
255af60e630SWilliam A. Kennington III 
256af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->enabled());
257af60e630SWilliam A. Kennington III     EXPECT_EQ(0, wdog->timeRemaining());
258af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->timerExpired());
259af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->timerEnabled());
260af60e630SWilliam A. Kennington III }
261af60e630SWilliam A. Kennington III 
262af60e630SWilliam A. Kennington III /** @brief Make sure the watchdog is started and enabled with a fallback
263af60e630SWilliam A. Kennington III  *         Wait through the initial trip and ensure the fallback is observed
264af60e630SWilliam A. Kennington III  *         Make sure that fallback runs to completion and ensure the watchdog
265af60e630SWilliam A. Kennington III  *         is disabled
266af60e630SWilliam A. Kennington III  */
TEST_F(WdogTest,enableWdogWithFallbackTillEnd)267af60e630SWilliam A. Kennington III TEST_F(WdogTest, enableWdogWithFallbackTillEnd)
268af60e630SWilliam A. Kennington III {
2693964f001SWilliam A. Kennington III     auto primaryInterval = Quantum(5);
270af60e630SWilliam A. Kennington III     auto primaryIntervalMs = milliseconds(primaryInterval).count();
271af60e630SWilliam A. Kennington III     auto fallbackInterval = primaryInterval * 2;
272af60e630SWilliam A. Kennington III     auto fallbackIntervalMs = milliseconds(fallbackInterval).count();
273af60e630SWilliam A. Kennington III 
274af60e630SWilliam A. Kennington III     // We need to make a wdog with the right fallback options
275af60e630SWilliam A. Kennington III     // The interval is set to be noticeably different from the default
276af60e630SWilliam A. Kennington III     // so we can always tell the difference
2778cf5f64cSWilliam A. Kennington III     Watchdog::Fallback fallback;
2788cf5f64cSWilliam A. Kennington III     fallback.action = Watchdog::Action::PowerOff;
2798cf5f64cSWilliam A. Kennington III     fallback.interval = static_cast<uint64_t>(fallbackIntervalMs);
2808cf5f64cSWilliam A. Kennington III     fallback.always = false;
2811859eeb2SWilliam A. Kennington III     wdog.reset();
282af60e630SWilliam A. Kennington III     wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
283cf4ce3c1SWilly Tu                                       Watchdog::ActionTargetMap(), fallback);
284af60e630SWilliam A. Kennington III     EXPECT_EQ(primaryInterval, milliseconds(wdog->interval(primaryIntervalMs)));
285af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->enabled());
286af60e630SWilliam A. Kennington III     EXPECT_EQ(0, wdog->timeRemaining());
287af60e630SWilliam A. Kennington III 
288af60e630SWilliam A. Kennington III     // Enable and then verify
289af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->enabled(true));
290af60e630SWilliam A. Kennington III 
291af60e630SWilliam A. Kennington III     // Waiting default expiration
2923964f001SWilliam A. Kennington III     EXPECT_EQ(primaryInterval - Quantum(1), waitForWatchdog(primaryInterval));
293af60e630SWilliam A. Kennington III 
294af60e630SWilliam A. Kennington III     // We should now have entered the fallback once the primary expires
295af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->enabled());
296af60e630SWilliam A. Kennington III     auto remaining = milliseconds(wdog->timeRemaining());
297af60e630SWilliam A. Kennington III     EXPECT_GE(fallbackInterval, remaining);
298af60e630SWilliam A. Kennington III     EXPECT_LT(primaryInterval, remaining);
299af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->timerExpired());
300af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->timerEnabled());
301af60e630SWilliam A. Kennington III 
302af60e630SWilliam A. Kennington III     // We should still be ticking in fallback when setting action or interval
3033964f001SWilliam A. Kennington III     auto newInterval = primaryInterval - Quantum(1);
304af60e630SWilliam A. Kennington III     auto newIntervalMs = milliseconds(newInterval).count();
305af60e630SWilliam A. Kennington III     EXPECT_EQ(newInterval, milliseconds(wdog->interval(newIntervalMs)));
306af60e630SWilliam A. Kennington III     EXPECT_EQ(Watchdog::Action::None,
307af60e630SWilliam A. Kennington III               wdog->expireAction(Watchdog::Action::None));
308af60e630SWilliam A. Kennington III 
309af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->enabled());
310af60e630SWilliam A. Kennington III     EXPECT_GE(remaining, milliseconds(wdog->timeRemaining()));
311af60e630SWilliam A. Kennington III     EXPECT_LT(primaryInterval, milliseconds(wdog->timeRemaining()));
312af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->timerExpired());
313af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->timerEnabled());
314af60e630SWilliam A. Kennington III 
315af60e630SWilliam A. Kennington III     // Test that setting the timeRemaining always resets the timer to the
316af60e630SWilliam A. Kennington III     // fallback interval
317af60e630SWilliam A. Kennington III     EXPECT_EQ(fallback.interval, wdog->timeRemaining(primaryInterval.count()));
318af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->enabled());
319af60e630SWilliam A. Kennington III 
320af60e630SWilliam A. Kennington III     remaining = milliseconds(wdog->timeRemaining());
321af60e630SWilliam A. Kennington III     EXPECT_GE(fallbackInterval, remaining);
3223964f001SWilliam A. Kennington III     EXPECT_LE(fallbackInterval - Quantum(1), remaining);
323af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->timerExpired());
324af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->timerEnabled());
325af60e630SWilliam A. Kennington III 
326af60e630SWilliam A. Kennington III     // Waiting fallback expiration
3273964f001SWilliam A. Kennington III     EXPECT_EQ(fallbackInterval - Quantum(1), waitForWatchdog(fallbackInterval));
328af60e630SWilliam A. Kennington III 
329af60e630SWilliam A. Kennington III     // We should now have disabled the watchdog after the fallback expires
330af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->enabled());
331af60e630SWilliam A. Kennington III     EXPECT_EQ(0, wdog->timeRemaining());
332af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->timerExpired());
333af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->timerEnabled());
334af60e630SWilliam A. Kennington III 
335af60e630SWilliam A. Kennington III     // Make sure enabling the watchdog again works
336af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->enabled(true));
337af60e630SWilliam A. Kennington III 
338af60e630SWilliam A. Kennington III     // We should have re-entered the primary
339af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->enabled());
340af60e630SWilliam A. Kennington III     EXPECT_GE(primaryInterval, milliseconds(wdog->timeRemaining()));
341af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->timerExpired());
342af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->timerEnabled());
343af60e630SWilliam A. Kennington III }
344af60e630SWilliam A. Kennington III 
345af60e630SWilliam A. Kennington III /** @brief Make sure the watchdog is started and enabled with a fallback
346af60e630SWilliam A. Kennington III  *         Wait through the initial trip and ensure the fallback is observed
347af60e630SWilliam A. Kennington III  *         Make sure that we can re-enable the watchdog during fallback
348af60e630SWilliam A. Kennington III  */
TEST_F(WdogTest,enableWdogWithFallbackReEnable)349af60e630SWilliam A. Kennington III TEST_F(WdogTest, enableWdogWithFallbackReEnable)
350af60e630SWilliam A. Kennington III {
3513964f001SWilliam A. Kennington III     auto primaryInterval = Quantum(5);
352af60e630SWilliam A. Kennington III     auto primaryIntervalMs = milliseconds(primaryInterval).count();
353af60e630SWilliam A. Kennington III     auto fallbackInterval = primaryInterval * 2;
354af60e630SWilliam A. Kennington III     auto fallbackIntervalMs = milliseconds(fallbackInterval).count();
355af60e630SWilliam A. Kennington III 
356af60e630SWilliam A. Kennington III     // We need to make a wdog with the right fallback options
357af60e630SWilliam A. Kennington III     // The interval is set to be noticeably different from the default
358af60e630SWilliam A. Kennington III     // so we can always tell the difference
3598cf5f64cSWilliam A. Kennington III     Watchdog::Fallback fallback;
3608cf5f64cSWilliam A. Kennington III     fallback.action = Watchdog::Action::PowerOff;
3618cf5f64cSWilliam A. Kennington III     fallback.interval = static_cast<uint64_t>(fallbackIntervalMs);
3628cf5f64cSWilliam A. Kennington III     fallback.always = false;
3631859eeb2SWilliam A. Kennington III     wdog.reset();
364af60e630SWilliam A. Kennington III     wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
365cf4ce3c1SWilly Tu                                       Watchdog::ActionTargetMap(), fallback);
366af60e630SWilliam A. Kennington III     EXPECT_EQ(primaryInterval, milliseconds(wdog->interval(primaryIntervalMs)));
367af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->enabled());
368af60e630SWilliam A. Kennington III     EXPECT_EQ(0, wdog->timeRemaining());
369af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->timerExpired());
370af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->timerEnabled());
371af60e630SWilliam A. Kennington III 
372af60e630SWilliam A. Kennington III     // Enable and then verify
373af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->enabled(true));
374af60e630SWilliam A. Kennington III 
375af60e630SWilliam A. Kennington III     // Waiting default expiration
3763964f001SWilliam A. Kennington III     EXPECT_EQ(primaryInterval - Quantum(1), waitForWatchdog(primaryInterval));
377af60e630SWilliam A. Kennington III 
378af60e630SWilliam A. Kennington III     // We should now have entered the fallback once the primary expires
379af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->enabled());
380af60e630SWilliam A. Kennington III     auto remaining = milliseconds(wdog->timeRemaining());
381af60e630SWilliam A. Kennington III     EXPECT_GE(fallbackInterval, remaining);
382af60e630SWilliam A. Kennington III     EXPECT_LT(primaryInterval, remaining);
383af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->timerExpired());
384af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->timerEnabled());
385af60e630SWilliam A. Kennington III 
386af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->enabled(true));
387af60e630SWilliam A. Kennington III 
388af60e630SWilliam A. Kennington III     // We should have re-entered the primary
389af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->enabled());
390af60e630SWilliam A. Kennington III     EXPECT_GE(primaryInterval, milliseconds(wdog->timeRemaining()));
391af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->timerExpired());
392af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->timerEnabled());
393af60e630SWilliam A. Kennington III }
394af60e630SWilliam A. Kennington III 
39550cc9563SKun Yi /** @brief Make sure the watchdog is started and enabled with a fallback
39650cc9563SKun Yi  *         Wait through the initial trip and ensure the fallback is observed
39750cc9563SKun Yi  *         Make sure that changing the primary interval and calling reset timer
39850cc9563SKun Yi  *         will enable the primary watchdog with primary interval.
39950cc9563SKun Yi  */
TEST_F(WdogTest,enableWdogWithFallbackResetTimerEnable)40050cc9563SKun Yi TEST_F(WdogTest, enableWdogWithFallbackResetTimerEnable)
40150cc9563SKun Yi {
40250cc9563SKun Yi     auto primaryInterval = Quantum(5);
40350cc9563SKun Yi     auto primaryIntervalMs = milliseconds(primaryInterval).count();
40450cc9563SKun Yi     auto fallbackInterval = primaryInterval * 2;
40550cc9563SKun Yi     auto fallbackIntervalMs = milliseconds(fallbackInterval).count();
40650cc9563SKun Yi     auto newInterval = fallbackInterval * 2;
40750cc9563SKun Yi     auto newIntervalMs = milliseconds(newInterval).count();
40850cc9563SKun Yi 
40950cc9563SKun Yi     // We need to make a wdog with the right fallback options
41050cc9563SKun Yi     // The interval is set to be noticeably different from the default
41150cc9563SKun Yi     // so we can always tell the difference
41250cc9563SKun Yi     Watchdog::Fallback fallback;
41350cc9563SKun Yi     fallback.action = Watchdog::Action::PowerOff;
41450cc9563SKun Yi     fallback.interval = static_cast<uint64_t>(fallbackIntervalMs);
41550cc9563SKun Yi     fallback.always = false;
4161859eeb2SWilliam A. Kennington III     wdog.reset();
41750cc9563SKun Yi     wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
418cf4ce3c1SWilly Tu                                       Watchdog::ActionTargetMap(), fallback);
41950cc9563SKun Yi     EXPECT_EQ(primaryInterval, milliseconds(wdog->interval(primaryIntervalMs)));
42050cc9563SKun Yi     EXPECT_FALSE(wdog->enabled());
42150cc9563SKun Yi     EXPECT_EQ(0, wdog->timeRemaining());
42250cc9563SKun Yi     EXPECT_FALSE(wdog->timerExpired());
42350cc9563SKun Yi     EXPECT_FALSE(wdog->timerEnabled());
42450cc9563SKun Yi 
42550cc9563SKun Yi     // Enable and then verify
42650cc9563SKun Yi     EXPECT_TRUE(wdog->enabled(true));
42750cc9563SKun Yi 
42850cc9563SKun Yi     // Waiting default expiration
42950cc9563SKun Yi     EXPECT_EQ(primaryInterval - Quantum(1), waitForWatchdog(primaryInterval));
43050cc9563SKun Yi 
43150cc9563SKun Yi     // We should now have entered the fallback once the primary expires
43250cc9563SKun Yi     EXPECT_FALSE(wdog->enabled());
43350cc9563SKun Yi     auto remaining = milliseconds(wdog->timeRemaining());
43450cc9563SKun Yi     EXPECT_GE(fallbackInterval, remaining);
43550cc9563SKun Yi     EXPECT_LT(primaryInterval, remaining);
43650cc9563SKun Yi     EXPECT_FALSE(wdog->timerExpired());
43750cc9563SKun Yi     EXPECT_TRUE(wdog->timerEnabled());
43850cc9563SKun Yi 
43950cc9563SKun Yi     // Setting the interval should take effect once resetTimer re-enables wdog
44050cc9563SKun Yi     EXPECT_EQ(newIntervalMs, wdog->interval(newIntervalMs));
44150cc9563SKun Yi     wdog->resetTimeRemaining(true);
44250cc9563SKun Yi 
44350cc9563SKun Yi     // We should have re-entered the primary
44450cc9563SKun Yi     EXPECT_TRUE(wdog->enabled());
44550cc9563SKun Yi     remaining = milliseconds(wdog->timeRemaining());
44650cc9563SKun Yi     EXPECT_GE(newInterval, remaining);
44750cc9563SKun Yi     EXPECT_LE(newInterval - Quantum(1), remaining);
44850cc9563SKun Yi     EXPECT_FALSE(wdog->timerExpired());
44950cc9563SKun Yi     EXPECT_TRUE(wdog->timerEnabled());
45050cc9563SKun Yi }
45150cc9563SKun Yi 
452af60e630SWilliam A. Kennington III /** @brief Make sure the watchdog is started and with a fallback without
453af60e630SWilliam A. Kennington III  *         sending an enable
454af60e630SWilliam A. Kennington III  *         Then enable the watchdog
455af60e630SWilliam A. Kennington III  *         Wait through the initial trip and ensure the fallback is observed
456af60e630SWilliam A. Kennington III  *         Make sure that fallback runs to completion and ensure the watchdog
457af60e630SWilliam A. Kennington III  *         is in the fallback state again
458af60e630SWilliam A. Kennington III  */
TEST_F(WdogTest,enableWdogWithFallbackAlways)459af60e630SWilliam A. Kennington III TEST_F(WdogTest, enableWdogWithFallbackAlways)
460af60e630SWilliam A. Kennington III {
4613964f001SWilliam A. Kennington III     auto primaryInterval = Quantum(5);
462af60e630SWilliam A. Kennington III     auto primaryIntervalMs = milliseconds(primaryInterval).count();
463af60e630SWilliam A. Kennington III     auto fallbackInterval = primaryInterval * 2;
464af60e630SWilliam A. Kennington III     auto fallbackIntervalMs = milliseconds(fallbackInterval).count();
465af60e630SWilliam A. Kennington III 
466af60e630SWilliam A. Kennington III     // We need to make a wdog with the right fallback options
467af60e630SWilliam A. Kennington III     // The interval is set to be noticeably different from the default
468af60e630SWilliam A. Kennington III     // so we can always tell the difference
4698cf5f64cSWilliam A. Kennington III     Watchdog::Fallback fallback;
4708cf5f64cSWilliam A. Kennington III     fallback.action = Watchdog::Action::PowerOff;
4718cf5f64cSWilliam A. Kennington III     fallback.interval = static_cast<uint64_t>(fallbackIntervalMs);
4728cf5f64cSWilliam A. Kennington III     fallback.always = true;
4731859eeb2SWilliam A. Kennington III     wdog.reset();
474af60e630SWilliam A. Kennington III     wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
475c35135d3SOfer Yehielli                                       Watchdog::ActionTargetMap(), fallback,
476c35135d3SOfer Yehielli                                       milliseconds(TEST_MIN_INTERVAL).count());
477c35135d3SOfer Yehielli 
478*6d12acf2SManojkiran Eda     // Make sure default interval is biggger than min interval
479c35135d3SOfer Yehielli     EXPECT_LT(milliseconds((TEST_MIN_INTERVAL).count()),
480c35135d3SOfer Yehielli               milliseconds(wdog->interval()));
481c35135d3SOfer Yehielli 
482af60e630SWilliam A. Kennington III     EXPECT_EQ(primaryInterval, milliseconds(wdog->interval(primaryIntervalMs)));
483af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->enabled());
484af60e630SWilliam A. Kennington III     auto remaining = milliseconds(wdog->timeRemaining());
485af60e630SWilliam A. Kennington III     EXPECT_GE(fallbackInterval, remaining);
486af60e630SWilliam A. Kennington III     EXPECT_LT(primaryInterval, remaining);
487af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->timerExpired());
488af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->timerEnabled());
489af60e630SWilliam A. Kennington III 
490af60e630SWilliam A. Kennington III     // Enable and then verify
491af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->enabled(true));
492af60e630SWilliam A. Kennington III     EXPECT_GE(primaryInterval, milliseconds(wdog->timeRemaining()));
493af60e630SWilliam A. Kennington III 
494af60e630SWilliam A. Kennington III     // Waiting default expiration
4953964f001SWilliam A. Kennington III     EXPECT_EQ(primaryInterval - Quantum(1), waitForWatchdog(primaryInterval));
496af60e630SWilliam A. Kennington III 
497af60e630SWilliam A. Kennington III     // We should now have entered the fallback once the primary expires
498af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->enabled());
499af60e630SWilliam A. Kennington III     remaining = milliseconds(wdog->timeRemaining());
500af60e630SWilliam A. Kennington III     EXPECT_GE(fallbackInterval, remaining);
501af60e630SWilliam A. Kennington III     EXPECT_LT(primaryInterval, remaining);
502af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->timerExpired());
503af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->timerEnabled());
504af60e630SWilliam A. Kennington III 
505af60e630SWilliam A. Kennington III     // Waiting fallback expiration
5063964f001SWilliam A. Kennington III     EXPECT_EQ(fallbackInterval - Quantum(1), waitForWatchdog(fallbackInterval));
507af60e630SWilliam A. Kennington III 
508af60e630SWilliam A. Kennington III     // We should now enter the fallback again
509af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->enabled());
510af60e630SWilliam A. Kennington III     remaining = milliseconds(wdog->timeRemaining());
511af60e630SWilliam A. Kennington III     EXPECT_GE(fallbackInterval, remaining);
512af60e630SWilliam A. Kennington III     EXPECT_LT(primaryInterval, remaining);
513af60e630SWilliam A. Kennington III     EXPECT_FALSE(wdog->timerExpired());
514af60e630SWilliam A. Kennington III     EXPECT_TRUE(wdog->timerEnabled());
515af60e630SWilliam A. Kennington III }
516c35135d3SOfer Yehielli 
517c35135d3SOfer Yehielli /** @brief Test minimal interval
518c35135d3SOfer Yehielli  *  The minimal interval was set 2 seconds
519c35135d3SOfer Yehielli  *  Test that when setting interval to 1s , it is still returning 2s
520c35135d3SOfer Yehielli  */
TEST_F(WdogTest,verifyMinIntervalSetting)521c35135d3SOfer Yehielli TEST_F(WdogTest, verifyMinIntervalSetting)
522c35135d3SOfer Yehielli {
523c35135d3SOfer Yehielli     auto newInterval = Quantum(1);
524c35135d3SOfer Yehielli     auto newIntervalMs = milliseconds(newInterval).count();
525c35135d3SOfer Yehielli     auto minIntervalMs = milliseconds(TEST_MIN_INTERVAL).count();
526c35135d3SOfer Yehielli 
527c35135d3SOfer Yehielli     // Check first that the current interval is greater than minInterval
528c35135d3SOfer Yehielli     EXPECT_LT(minIntervalMs, wdog->interval());
529c35135d3SOfer Yehielli     // Check that the interval was not set to smaller value than minInterval
530c35135d3SOfer Yehielli     EXPECT_EQ(minIntervalMs, wdog->interval(newIntervalMs));
531c35135d3SOfer Yehielli     // Check that the interval was not set to smaller value than minInterval
532c35135d3SOfer Yehielli     EXPECT_EQ(minIntervalMs, wdog->interval());
533c35135d3SOfer Yehielli }
534c35135d3SOfer Yehielli 
535c35135d3SOfer Yehielli /** @brief Test minimal interval
536c35135d3SOfer Yehielli  *  Initiate default Watchdog in order to get the default
537c35135d3SOfer Yehielli  *  interval.
538c35135d3SOfer Yehielli  *  Initiate watchdog with minInterval greater than default
539c35135d3SOfer Yehielli  *  interval, and make sure the default interval was set to the
540c35135d3SOfer Yehielli  *  minInterval.
541c35135d3SOfer Yehielli  */
TEST_F(WdogTest,verifyConstructorMinIntervalSetting)542c35135d3SOfer Yehielli TEST_F(WdogTest, verifyConstructorMinIntervalSetting)
543c35135d3SOfer Yehielli {
544c35135d3SOfer Yehielli     // Initiate default Watchdog and get the default interval value.
5451859eeb2SWilliam A. Kennington III     wdog.reset();
546c35135d3SOfer Yehielli     wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event);
547e8e11c63SKun Yi     auto defaultIntervalMs = wdog->interval();
548e8e11c63SKun Yi     auto defaultInterval = milliseconds(defaultIntervalMs);
549e8e11c63SKun Yi     auto minInterval = defaultInterval + Quantum(30);
550e8e11c63SKun Yi     auto minIntervalMs = milliseconds(minInterval).count();
551e8e11c63SKun Yi 
552c35135d3SOfer Yehielli     // We initiate a new Watchdog with min interval greater than the default
553c35135d3SOfer Yehielli     // intrval
5541859eeb2SWilliam A. Kennington III     wdog.reset();
555c35135d3SOfer Yehielli     wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
556c35135d3SOfer Yehielli                                       Watchdog::ActionTargetMap(), std::nullopt,
557e8e11c63SKun Yi                                       minIntervalMs);
558c35135d3SOfer Yehielli     // Check that the interval was set to the minInterval
559e8e11c63SKun Yi     EXPECT_EQ(minIntervalMs, wdog->interval());
560e8e11c63SKun Yi 
561e8e11c63SKun Yi     // Enable and then verify
562e8e11c63SKun Yi     EXPECT_TRUE(wdog->enabled(true));
563e8e11c63SKun Yi     EXPECT_FALSE(wdog->timerExpired());
564e8e11c63SKun Yi     EXPECT_TRUE(wdog->timerEnabled());
565e8e11c63SKun Yi 
566e8e11c63SKun Yi     // Set remaining time shorter than minInterval will actually set it to
567e8e11c63SKun Yi     // minInterval
568e8e11c63SKun Yi     auto remaining = milliseconds(wdog->timeRemaining(defaultIntervalMs));
569e8e11c63SKun Yi 
570e8e11c63SKun Yi     // Its possible that we are off by few msecs depending on
571e8e11c63SKun Yi     // how we get scheduled. So checking a range here.
572e8e11c63SKun Yi     EXPECT_TRUE((remaining >= minInterval - Quantum(1)) &&
573e8e11c63SKun Yi                 (remaining <= minInterval));
574e8e11c63SKun Yi 
575e8e11c63SKun Yi     EXPECT_FALSE(wdog->timerExpired());
576e8e11c63SKun Yi     EXPECT_TRUE(wdog->timerEnabled());
577c35135d3SOfer Yehielli }
578c35135d3SOfer Yehielli 
579c35135d3SOfer Yehielli } // namespace watchdog
580c35135d3SOfer Yehielli } // namespace phosphor
581