blob: 39ada29f9adfddf3b8c1480060b173505a467874 [file] [log] [blame]
William A. Kennington IIIaf60e632019-01-16 15:00:18 -08001#include "watchdog.hpp"
Patrick Venture8f6c5152018-09-11 17:45:33 -07002
William A. Kennington III287105c2021-04-22 15:19:02 -07003#include <sdbusplus/bus.hpp>
4#include <sdeventplus/event.hpp>
Patrick Williams6ac6a342023-05-10 07:51:12 -05005
6#include <chrono>
7#include <memory>
William A. Kennington IIIf505fc02018-09-12 18:30:09 -07008#include <thread>
William A. Kennington IIId1331082018-02-27 18:47:05 -08009#include <utility>
William A. Kennington III99c69de2018-03-01 10:59:22 -080010
William A. Kennington III287105c2021-04-22 15:19:02 -070011#include <gtest/gtest.h>
12
Ofer Yehiellic35135d2019-06-14 11:30:25 -070013namespace phosphor
14{
15namespace watchdog
16{
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +053017
William A. Kennington III287105c2021-04-22 15:19:02 -070018using namespace std::chrono;
19using namespace std::chrono_literals;
William A. Kennington III99c69de2018-03-01 10:59:22 -080020
William A. Kennington III287105c2021-04-22 15:19:02 -070021constexpr auto TEST_MIN_INTERVAL = duration<uint64_t, std::deci>(2);
22
23// Test Watchdog functionality
24class WdogTest : public ::testing::Test
25{
26 public:
27 // The unit time used to measure the timer
28 // This should be large enough to accomodate drift
29 using Quantum = duration<uint64_t, std::deci>;
30
31 // Gets called as part of each TEST_F construction
32 WdogTest() :
33 event(sdeventplus::Event::get_default()),
34 bus(sdbusplus::bus::new_default()),
35 wdog(std::make_unique<Watchdog>(
36 bus, TEST_PATH, event, Watchdog::ActionTargetMap(), std::nullopt,
37 milliseconds(TEST_MIN_INTERVAL).count())),
38
39 defaultInterval(Quantum(3))
40
41 {
42 wdog->interval(milliseconds(defaultInterval).count());
43 // Initially the watchdog would be disabled
44 EXPECT_FALSE(wdog->enabled());
William A. Kennington III99c69de2018-03-01 10:59:22 -080045 }
46
William A. Kennington III287105c2021-04-22 15:19:02 -070047 // sdevent Event handle
48 sdeventplus::Event event;
49
50 // sdbusplus handle
Patrick Williams73bd5272022-07-22 19:26:57 -050051 sdbusplus::bus_t bus;
William A. Kennington III287105c2021-04-22 15:19:02 -070052
53 // Watchdog object
54 std::unique_ptr<Watchdog> wdog;
55
56 // This is the default interval as given in Interface definition
57 Quantum defaultInterval;
58
59 protected:
60 // Dummy name for object path
61 // This is just to satisfy the constructor. Does not have
62 // a need to check if the objects paths have been created.
63 static constexpr auto TEST_PATH = "/test/path";
64
65 // Returns how long it took for the current watchdog timer to be
66 // disabled or have its timeRemaining reset.
67 Quantum waitForWatchdog(Quantum timeLimit)
68 {
69 auto previousTimeRemaining = wdog->timeRemaining();
70 auto ret = Quantum(0);
71 while (ret < timeLimit &&
72 previousTimeRemaining >= wdog->timeRemaining() &&
73 wdog->timerEnabled())
74 {
75 previousTimeRemaining = wdog->timeRemaining();
76
77 constexpr auto sleepTime = Quantum(1);
78 if (event.run(sleepTime) == 0)
79 {
80 ret += sleepTime;
81 }
82 }
83
84 return ret;
85 }
86};
William A. Kennington III99c69de2018-03-01 10:59:22 -080087
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +053088/** @brief Make sure that watchdog is started and not enabled */
89TEST_F(WdogTest, createWdogAndDontEnable)
90{
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -080091 EXPECT_FALSE(wdog->enabled());
92 EXPECT_EQ(0, wdog->timeRemaining());
93 EXPECT_FALSE(wdog->timerExpired());
William A. Kennington III0650a3f2018-03-01 10:53:25 -080094 EXPECT_FALSE(wdog->timerEnabled());
William A. Kennington III25c1b202018-03-01 11:00:19 -080095
96 // We should be able to configure persistent properties
97 // while disabled
98 auto newAction = Watchdog::Action::PowerOff;
99 EXPECT_EQ(newAction, wdog->expireAction(newAction));
100 auto newIntervalMs = milliseconds(defaultInterval * 2).count();
101 EXPECT_EQ(newIntervalMs, wdog->interval(newIntervalMs));
102
103 EXPECT_EQ(newAction, wdog->expireAction());
104 EXPECT_EQ(newIntervalMs, wdog->interval());
105
106 // We won't be able to configure timeRemaining
107 EXPECT_EQ(0, wdog->timeRemaining(1000));
108 EXPECT_EQ(0, wdog->timeRemaining());
109
110 // Timer should not have become enabled
111 EXPECT_FALSE(wdog->enabled());
112 EXPECT_EQ(0, wdog->timeRemaining());
113 EXPECT_FALSE(wdog->timerExpired());
114 EXPECT_FALSE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530115}
116
117/** @brief Make sure that watchdog is started and enabled */
118TEST_F(WdogTest, createWdogAndEnable)
119{
120 // Enable and then verify
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800121 EXPECT_TRUE(wdog->enabled(true));
122 EXPECT_FALSE(wdog->timerExpired());
William A. Kennington III0650a3f2018-03-01 10:53:25 -0800123 EXPECT_TRUE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530124
125 // Get the configured interval
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800126 auto remaining = milliseconds(wdog->timeRemaining());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530127
128 // Its possible that we are off by few msecs depending on
129 // how we get scheduled. So checking a range here.
William A. Kennington III3964f002019-01-16 15:43:43 -0800130 EXPECT_TRUE((remaining >= defaultInterval - Quantum(1)) &&
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530131 (remaining <= defaultInterval));
132
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800133 EXPECT_FALSE(wdog->timerExpired());
William A. Kennington III0650a3f2018-03-01 10:53:25 -0800134 EXPECT_TRUE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530135}
136
137/** @brief Make sure that watchdog is started and enabled.
138 * Later, disable watchdog
139 */
140TEST_F(WdogTest, createWdogAndEnableThenDisable)
141{
142 // Enable and then verify
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800143 EXPECT_TRUE(wdog->enabled(true));
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530144
145 // Disable and then verify
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800146 EXPECT_FALSE(wdog->enabled(false));
147 EXPECT_FALSE(wdog->enabled());
148 EXPECT_EQ(0, wdog->timeRemaining());
William A. Kennington III0650a3f2018-03-01 10:53:25 -0800149 EXPECT_FALSE(wdog->timerExpired());
150 EXPECT_FALSE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530151}
152
153/** @brief Make sure that watchdog is started and enabled.
William A. Kennington III3964f002019-01-16 15:43:43 -0800154 * Wait for 5 quantums and make sure that the remaining
155 * time shows 5 fewer quantums.
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530156 */
William A. Kennington III3964f002019-01-16 15:43:43 -0800157TEST_F(WdogTest, enableWdogAndWait5Quantums)
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530158{
159 // Enable and then verify
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800160 EXPECT_TRUE(wdog->enabled(true));
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530161
William A. Kennington III3964f002019-01-16 15:43:43 -0800162 // Sleep for 5 quantums
163 auto sleepTime = Quantum(2);
164 ASSERT_LT(sleepTime, defaultInterval);
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530165 std::this_thread::sleep_for(sleepTime);
166
William A. Kennington III3964f002019-01-16 15:43:43 -0800167 // Get the remaining time again and expectation is that we get fewer
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800168 auto remaining = milliseconds(wdog->timeRemaining());
William A. Kennington III8cd38392018-03-01 11:07:36 -0800169 auto expected = defaultInterval - sleepTime;
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530170
171 // Its possible that we are off by few msecs depending on
172 // how we get scheduled. So checking a range here.
William A. Kennington III3964f002019-01-16 15:43:43 -0800173 EXPECT_TRUE((remaining >= expected - Quantum(1)) &&
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530174 (remaining <= expected));
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800175 EXPECT_FALSE(wdog->timerExpired());
William A. Kennington III0650a3f2018-03-01 10:53:25 -0800176 EXPECT_TRUE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530177}
178
179/** @brief Make sure that watchdog is started and enabled.
William A. Kennington III3964f002019-01-16 15:43:43 -0800180 * Wait 1 quantum and then reset the timer to 5 quantums
181 * and then expect the watchdog to expire in 5 quantums
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530182 */
William A. Kennington III3964f002019-01-16 15:43:43 -0800183TEST_F(WdogTest, enableWdogAndResetTo5Quantums)
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530184{
185 // Enable and then verify
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800186 EXPECT_TRUE(wdog->enabled(true));
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530187
188 // Sleep for 1 second
William A. Kennington III3964f002019-01-16 15:43:43 -0800189 std::this_thread::sleep_for(Quantum(1));
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530190
William A. Kennington IIIf505fc02018-09-12 18:30:09 -0700191 // Timer should still be running unexpired
192 EXPECT_FALSE(wdog->timerExpired());
193 EXPECT_TRUE(wdog->timerEnabled());
194
William A. Kennington III3964f002019-01-16 15:43:43 -0800195 // Next timer will expire in 5 quantums from now.
196 auto expireTime = Quantum(5);
William A. Kennington III8cd38392018-03-01 11:07:36 -0800197 auto expireTimeMs = milliseconds(expireTime).count();
198 EXPECT_EQ(expireTimeMs, wdog->timeRemaining(expireTimeMs));
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530199
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530200 // Waiting for expiration
William A. Kennington III3964f002019-01-16 15:43:43 -0800201 EXPECT_EQ(expireTime - Quantum(1), waitForWatchdog(expireTime));
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800202 EXPECT_TRUE(wdog->timerExpired());
William A. Kennington III0650a3f2018-03-01 10:53:25 -0800203 EXPECT_FALSE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530204}
205
Gunnar Millsbfe5cb82017-10-25 20:48:50 -0500206/** @brief Make sure the Interval can be updated directly.
Patrick Venture96816342017-08-17 12:32:22 -0700207 */
208TEST_F(WdogTest, verifyIntervalUpdateReceived)
209{
William A. Kennington III3964f002019-01-16 15:43:43 -0800210 auto expireTime = Quantum(5);
William A. Kennington III8cd38392018-03-01 11:07:36 -0800211 auto expireTimeMs = milliseconds(expireTime).count();
212 EXPECT_EQ(expireTimeMs, wdog->interval(expireTimeMs));
Patrick Venture96816342017-08-17 12:32:22 -0700213
214 // Expect an update in the Interval
William A. Kennington III8cd38392018-03-01 11:07:36 -0800215 EXPECT_EQ(expireTimeMs, wdog->interval());
Patrick Venture96816342017-08-17 12:32:22 -0700216}
217
William A. Kennington IIId4cbc5a2018-09-24 14:23:05 -0700218/** @brief Make sure the Interval can be updated while the timer is running.
219 */
220TEST_F(WdogTest, verifyIntervalUpdateRunning)
221{
222 const auto oldInterval = milliseconds(wdog->interval());
223 const auto newInterval = 5s;
224
225 EXPECT_TRUE(wdog->enabled(true));
226 auto remaining = milliseconds(wdog->timeRemaining());
227 EXPECT_GE(oldInterval, remaining);
William A. Kennington III3964f002019-01-16 15:43:43 -0800228 EXPECT_LE(oldInterval - Quantum(1), remaining);
William A. Kennington IIId4cbc5a2018-09-24 14:23:05 -0700229 EXPECT_EQ(newInterval,
230 milliseconds(wdog->interval(milliseconds(newInterval).count())));
231
232 // Expect only the interval to update
233 remaining = milliseconds(wdog->timeRemaining());
234 EXPECT_GE(oldInterval, remaining);
William A. Kennington III3964f002019-01-16 15:43:43 -0800235 EXPECT_LE(oldInterval - Quantum(1), remaining);
William A. Kennington IIId4cbc5a2018-09-24 14:23:05 -0700236 EXPECT_EQ(newInterval, milliseconds(wdog->interval()));
237
238 // Expect reset to use the new interval
239 wdog->resetTimeRemaining(false);
240 remaining = milliseconds(wdog->timeRemaining());
241 EXPECT_GE(newInterval, remaining);
William A. Kennington III3964f002019-01-16 15:43:43 -0800242 EXPECT_LE(newInterval - Quantum(1), remaining);
William A. Kennington IIId4cbc5a2018-09-24 14:23:05 -0700243}
244
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530245/** @brief Make sure that watchdog is started and enabled.
William A. Kennington III3964f002019-01-16 15:43:43 -0800246 * Wait default interval quantums and make sure that wdog has died
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530247 */
248TEST_F(WdogTest, enableWdogAndWaitTillEnd)
249{
250 // Enable and then verify
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800251 EXPECT_TRUE(wdog->enabled(true));
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530252
253 // Waiting default expiration
William A. Kennington III3964f002019-01-16 15:43:43 -0800254 EXPECT_EQ(defaultInterval - Quantum(1), waitForWatchdog(defaultInterval));
William A. Kennington III99c69de2018-03-01 10:59:22 -0800255
William A. Kennington III825f4982018-02-27 19:10:56 -0800256 EXPECT_FALSE(wdog->enabled());
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800257 EXPECT_EQ(0, wdog->timeRemaining());
258 EXPECT_TRUE(wdog->timerExpired());
William A. Kennington III0650a3f2018-03-01 10:53:25 -0800259 EXPECT_FALSE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530260}
William A. Kennington IIId1331082018-02-27 18:47:05 -0800261
262/** @brief Make sure the watchdog is started and enabled with a fallback
263 * Wait through the initial trip and ensure the fallback is observed
264 * Make sure that fallback runs to completion and ensure the watchdog
265 * is disabled
266 */
267TEST_F(WdogTest, enableWdogWithFallbackTillEnd)
268{
William A. Kennington III3964f002019-01-16 15:43:43 -0800269 auto primaryInterval = Quantum(5);
William A. Kennington IIId1331082018-02-27 18:47:05 -0800270 auto primaryIntervalMs = milliseconds(primaryInterval).count();
271 auto fallbackInterval = primaryInterval * 2;
272 auto fallbackIntervalMs = milliseconds(fallbackInterval).count();
273
274 // We need to make a wdog with the right fallback options
275 // The interval is set to be noticeably different from the default
276 // so we can always tell the difference
William A. Kennington III8cf5f642019-01-16 16:58:14 -0800277 Watchdog::Fallback fallback;
278 fallback.action = Watchdog::Action::PowerOff;
279 fallback.interval = static_cast<uint64_t>(fallbackIntervalMs);
280 fallback.always = false;
William A. Kennington III1859eeb2021-04-20 16:08:57 -0700281 wdog.reset();
William A. Kennington IIIf505fc02018-09-12 18:30:09 -0700282 wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
Willy Tucf4ce3c2021-12-09 20:39:37 -0800283 Watchdog::ActionTargetMap(), fallback);
William A. Kennington IIId1331082018-02-27 18:47:05 -0800284 EXPECT_EQ(primaryInterval, milliseconds(wdog->interval(primaryIntervalMs)));
285 EXPECT_FALSE(wdog->enabled());
286 EXPECT_EQ(0, wdog->timeRemaining());
287
288 // Enable and then verify
289 EXPECT_TRUE(wdog->enabled(true));
290
291 // Waiting default expiration
William A. Kennington III3964f002019-01-16 15:43:43 -0800292 EXPECT_EQ(primaryInterval - Quantum(1), waitForWatchdog(primaryInterval));
William A. Kennington IIId1331082018-02-27 18:47:05 -0800293
294 // We should now have entered the fallback once the primary expires
295 EXPECT_FALSE(wdog->enabled());
296 auto remaining = milliseconds(wdog->timeRemaining());
297 EXPECT_GE(fallbackInterval, remaining);
298 EXPECT_LT(primaryInterval, remaining);
299 EXPECT_FALSE(wdog->timerExpired());
300 EXPECT_TRUE(wdog->timerEnabled());
301
302 // We should still be ticking in fallback when setting action or interval
William A. Kennington III3964f002019-01-16 15:43:43 -0800303 auto newInterval = primaryInterval - Quantum(1);
William A. Kennington IIId1331082018-02-27 18:47:05 -0800304 auto newIntervalMs = milliseconds(newInterval).count();
305 EXPECT_EQ(newInterval, milliseconds(wdog->interval(newIntervalMs)));
306 EXPECT_EQ(Watchdog::Action::None,
Patrick Venture8f6c5152018-09-11 17:45:33 -0700307 wdog->expireAction(Watchdog::Action::None));
William A. Kennington IIId1331082018-02-27 18:47:05 -0800308
309 EXPECT_FALSE(wdog->enabled());
310 EXPECT_GE(remaining, milliseconds(wdog->timeRemaining()));
311 EXPECT_LT(primaryInterval, milliseconds(wdog->timeRemaining()));
312 EXPECT_FALSE(wdog->timerExpired());
313 EXPECT_TRUE(wdog->timerEnabled());
314
315 // Test that setting the timeRemaining always resets the timer to the
316 // fallback interval
317 EXPECT_EQ(fallback.interval, wdog->timeRemaining(primaryInterval.count()));
318 EXPECT_FALSE(wdog->enabled());
319
320 remaining = milliseconds(wdog->timeRemaining());
321 EXPECT_GE(fallbackInterval, remaining);
William A. Kennington III3964f002019-01-16 15:43:43 -0800322 EXPECT_LE(fallbackInterval - Quantum(1), remaining);
William A. Kennington IIId1331082018-02-27 18:47:05 -0800323 EXPECT_FALSE(wdog->timerExpired());
324 EXPECT_TRUE(wdog->timerEnabled());
325
326 // Waiting fallback expiration
William A. Kennington III3964f002019-01-16 15:43:43 -0800327 EXPECT_EQ(fallbackInterval - Quantum(1), waitForWatchdog(fallbackInterval));
William A. Kennington IIId1331082018-02-27 18:47:05 -0800328
329 // We should now have disabled the watchdog after the fallback expires
330 EXPECT_FALSE(wdog->enabled());
331 EXPECT_EQ(0, wdog->timeRemaining());
332 EXPECT_TRUE(wdog->timerExpired());
333 EXPECT_FALSE(wdog->timerEnabled());
334
335 // Make sure enabling the watchdog again works
336 EXPECT_TRUE(wdog->enabled(true));
337
338 // We should have re-entered the primary
339 EXPECT_TRUE(wdog->enabled());
340 EXPECT_GE(primaryInterval, milliseconds(wdog->timeRemaining()));
341 EXPECT_FALSE(wdog->timerExpired());
342 EXPECT_TRUE(wdog->timerEnabled());
343}
344
345/** @brief Make sure the watchdog is started and enabled with a fallback
346 * Wait through the initial trip and ensure the fallback is observed
347 * Make sure that we can re-enable the watchdog during fallback
348 */
349TEST_F(WdogTest, enableWdogWithFallbackReEnable)
350{
William A. Kennington III3964f002019-01-16 15:43:43 -0800351 auto primaryInterval = Quantum(5);
William A. Kennington IIId1331082018-02-27 18:47:05 -0800352 auto primaryIntervalMs = milliseconds(primaryInterval).count();
353 auto fallbackInterval = primaryInterval * 2;
354 auto fallbackIntervalMs = milliseconds(fallbackInterval).count();
355
356 // We need to make a wdog with the right fallback options
357 // The interval is set to be noticeably different from the default
358 // so we can always tell the difference
William A. Kennington III8cf5f642019-01-16 16:58:14 -0800359 Watchdog::Fallback fallback;
360 fallback.action = Watchdog::Action::PowerOff;
361 fallback.interval = static_cast<uint64_t>(fallbackIntervalMs);
362 fallback.always = false;
William A. Kennington III1859eeb2021-04-20 16:08:57 -0700363 wdog.reset();
William A. Kennington IIIf505fc02018-09-12 18:30:09 -0700364 wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
Willy Tucf4ce3c2021-12-09 20:39:37 -0800365 Watchdog::ActionTargetMap(), fallback);
William A. Kennington IIId1331082018-02-27 18:47:05 -0800366 EXPECT_EQ(primaryInterval, milliseconds(wdog->interval(primaryIntervalMs)));
367 EXPECT_FALSE(wdog->enabled());
368 EXPECT_EQ(0, wdog->timeRemaining());
369 EXPECT_FALSE(wdog->timerExpired());
370 EXPECT_FALSE(wdog->timerEnabled());
371
372 // Enable and then verify
373 EXPECT_TRUE(wdog->enabled(true));
374
375 // Waiting default expiration
William A. Kennington III3964f002019-01-16 15:43:43 -0800376 EXPECT_EQ(primaryInterval - Quantum(1), waitForWatchdog(primaryInterval));
William A. Kennington IIId1331082018-02-27 18:47:05 -0800377
378 // We should now have entered the fallback once the primary expires
379 EXPECT_FALSE(wdog->enabled());
380 auto remaining = milliseconds(wdog->timeRemaining());
381 EXPECT_GE(fallbackInterval, remaining);
382 EXPECT_LT(primaryInterval, remaining);
383 EXPECT_FALSE(wdog->timerExpired());
384 EXPECT_TRUE(wdog->timerEnabled());
385
386 EXPECT_TRUE(wdog->enabled(true));
387
388 // We should have re-entered the primary
389 EXPECT_TRUE(wdog->enabled());
390 EXPECT_GE(primaryInterval, milliseconds(wdog->timeRemaining()));
391 EXPECT_FALSE(wdog->timerExpired());
392 EXPECT_TRUE(wdog->timerEnabled());
393}
William A. Kennington III22352192018-02-27 18:51:44 -0800394
Kun Yi50cc9562019-12-04 11:46:59 -0800395/** @brief Make sure the watchdog is started and enabled with a fallback
396 * Wait through the initial trip and ensure the fallback is observed
397 * Make sure that changing the primary interval and calling reset timer
398 * will enable the primary watchdog with primary interval.
399 */
400TEST_F(WdogTest, enableWdogWithFallbackResetTimerEnable)
401{
402 auto primaryInterval = Quantum(5);
403 auto primaryIntervalMs = milliseconds(primaryInterval).count();
404 auto fallbackInterval = primaryInterval * 2;
405 auto fallbackIntervalMs = milliseconds(fallbackInterval).count();
406 auto newInterval = fallbackInterval * 2;
407 auto newIntervalMs = milliseconds(newInterval).count();
408
409 // We need to make a wdog with the right fallback options
410 // The interval is set to be noticeably different from the default
411 // so we can always tell the difference
412 Watchdog::Fallback fallback;
413 fallback.action = Watchdog::Action::PowerOff;
414 fallback.interval = static_cast<uint64_t>(fallbackIntervalMs);
415 fallback.always = false;
William A. Kennington III1859eeb2021-04-20 16:08:57 -0700416 wdog.reset();
Kun Yi50cc9562019-12-04 11:46:59 -0800417 wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
Willy Tucf4ce3c2021-12-09 20:39:37 -0800418 Watchdog::ActionTargetMap(), fallback);
Kun Yi50cc9562019-12-04 11:46:59 -0800419 EXPECT_EQ(primaryInterval, milliseconds(wdog->interval(primaryIntervalMs)));
420 EXPECT_FALSE(wdog->enabled());
421 EXPECT_EQ(0, wdog->timeRemaining());
422 EXPECT_FALSE(wdog->timerExpired());
423 EXPECT_FALSE(wdog->timerEnabled());
424
425 // Enable and then verify
426 EXPECT_TRUE(wdog->enabled(true));
427
428 // Waiting default expiration
429 EXPECT_EQ(primaryInterval - Quantum(1), waitForWatchdog(primaryInterval));
430
431 // We should now have entered the fallback once the primary expires
432 EXPECT_FALSE(wdog->enabled());
433 auto remaining = milliseconds(wdog->timeRemaining());
434 EXPECT_GE(fallbackInterval, remaining);
435 EXPECT_LT(primaryInterval, remaining);
436 EXPECT_FALSE(wdog->timerExpired());
437 EXPECT_TRUE(wdog->timerEnabled());
438
439 // Setting the interval should take effect once resetTimer re-enables wdog
440 EXPECT_EQ(newIntervalMs, wdog->interval(newIntervalMs));
441 wdog->resetTimeRemaining(true);
442
443 // We should have re-entered the primary
444 EXPECT_TRUE(wdog->enabled());
445 remaining = milliseconds(wdog->timeRemaining());
446 EXPECT_GE(newInterval, remaining);
447 EXPECT_LE(newInterval - Quantum(1), remaining);
448 EXPECT_FALSE(wdog->timerExpired());
449 EXPECT_TRUE(wdog->timerEnabled());
450}
451
William A. Kennington III22352192018-02-27 18:51:44 -0800452/** @brief Make sure the watchdog is started and with a fallback without
453 * sending an enable
454 * Then enable the watchdog
455 * Wait through the initial trip and ensure the fallback is observed
456 * Make sure that fallback runs to completion and ensure the watchdog
457 * is in the fallback state again
458 */
459TEST_F(WdogTest, enableWdogWithFallbackAlways)
460{
William A. Kennington III3964f002019-01-16 15:43:43 -0800461 auto primaryInterval = Quantum(5);
William A. Kennington III22352192018-02-27 18:51:44 -0800462 auto primaryIntervalMs = milliseconds(primaryInterval).count();
463 auto fallbackInterval = primaryInterval * 2;
464 auto fallbackIntervalMs = milliseconds(fallbackInterval).count();
465
466 // We need to make a wdog with the right fallback options
467 // The interval is set to be noticeably different from the default
468 // so we can always tell the difference
William A. Kennington III8cf5f642019-01-16 16:58:14 -0800469 Watchdog::Fallback fallback;
470 fallback.action = Watchdog::Action::PowerOff;
471 fallback.interval = static_cast<uint64_t>(fallbackIntervalMs);
472 fallback.always = true;
William A. Kennington III1859eeb2021-04-20 16:08:57 -0700473 wdog.reset();
William A. Kennington IIIf505fc02018-09-12 18:30:09 -0700474 wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700475 Watchdog::ActionTargetMap(), fallback,
476 milliseconds(TEST_MIN_INTERVAL).count());
477
478 // Make sure defualt interval is biggger than min interval
479 EXPECT_LT(milliseconds((TEST_MIN_INTERVAL).count()),
480 milliseconds(wdog->interval()));
481
William A. Kennington III22352192018-02-27 18:51:44 -0800482 EXPECT_EQ(primaryInterval, milliseconds(wdog->interval(primaryIntervalMs)));
483 EXPECT_FALSE(wdog->enabled());
484 auto remaining = milliseconds(wdog->timeRemaining());
485 EXPECT_GE(fallbackInterval, remaining);
486 EXPECT_LT(primaryInterval, remaining);
487 EXPECT_FALSE(wdog->timerExpired());
488 EXPECT_TRUE(wdog->timerEnabled());
489
490 // Enable and then verify
491 EXPECT_TRUE(wdog->enabled(true));
492 EXPECT_GE(primaryInterval, milliseconds(wdog->timeRemaining()));
493
494 // Waiting default expiration
William A. Kennington III3964f002019-01-16 15:43:43 -0800495 EXPECT_EQ(primaryInterval - Quantum(1), waitForWatchdog(primaryInterval));
William A. Kennington III22352192018-02-27 18:51:44 -0800496
497 // We should now have entered the fallback once the primary expires
498 EXPECT_FALSE(wdog->enabled());
499 remaining = milliseconds(wdog->timeRemaining());
500 EXPECT_GE(fallbackInterval, remaining);
501 EXPECT_LT(primaryInterval, remaining);
502 EXPECT_FALSE(wdog->timerExpired());
503 EXPECT_TRUE(wdog->timerEnabled());
504
505 // Waiting fallback expiration
William A. Kennington III3964f002019-01-16 15:43:43 -0800506 EXPECT_EQ(fallbackInterval - Quantum(1), waitForWatchdog(fallbackInterval));
William A. Kennington III22352192018-02-27 18:51:44 -0800507
508 // We should now enter the fallback again
509 EXPECT_FALSE(wdog->enabled());
510 remaining = milliseconds(wdog->timeRemaining());
511 EXPECT_GE(fallbackInterval, remaining);
512 EXPECT_LT(primaryInterval, remaining);
513 EXPECT_FALSE(wdog->timerExpired());
514 EXPECT_TRUE(wdog->timerEnabled());
515}
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700516
517/** @brief Test minimal interval
518 * The minimal interval was set 2 seconds
519 * Test that when setting interval to 1s , it is still returning 2s
520 */
521TEST_F(WdogTest, verifyMinIntervalSetting)
522{
523 auto newInterval = Quantum(1);
524 auto newIntervalMs = milliseconds(newInterval).count();
525 auto minIntervalMs = milliseconds(TEST_MIN_INTERVAL).count();
526
527 // Check first that the current interval is greater than minInterval
528 EXPECT_LT(minIntervalMs, wdog->interval());
529 // Check that the interval was not set to smaller value than minInterval
530 EXPECT_EQ(minIntervalMs, wdog->interval(newIntervalMs));
531 // Check that the interval was not set to smaller value than minInterval
532 EXPECT_EQ(minIntervalMs, wdog->interval());
533}
534
535/** @brief Test minimal interval
536 * Initiate default Watchdog in order to get the default
537 * interval.
538 * Initiate watchdog with minInterval greater than default
539 * interval, and make sure the default interval was set to the
540 * minInterval.
541 */
542TEST_F(WdogTest, verifyConstructorMinIntervalSetting)
543{
544 // Initiate default Watchdog and get the default interval value.
William A. Kennington III1859eeb2021-04-20 16:08:57 -0700545 wdog.reset();
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700546 wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event);
Kun Yie8e11c62019-12-04 16:35:47 -0800547 auto defaultIntervalMs = wdog->interval();
548 auto defaultInterval = milliseconds(defaultIntervalMs);
549 auto minInterval = defaultInterval + Quantum(30);
550 auto minIntervalMs = milliseconds(minInterval).count();
551
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700552 // We initiate a new Watchdog with min interval greater than the default
553 // intrval
William A. Kennington III1859eeb2021-04-20 16:08:57 -0700554 wdog.reset();
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700555 wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
556 Watchdog::ActionTargetMap(), std::nullopt,
Kun Yie8e11c62019-12-04 16:35:47 -0800557 minIntervalMs);
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700558 // Check that the interval was set to the minInterval
Kun Yie8e11c62019-12-04 16:35:47 -0800559 EXPECT_EQ(minIntervalMs, wdog->interval());
560
561 // Enable and then verify
562 EXPECT_TRUE(wdog->enabled(true));
563 EXPECT_FALSE(wdog->timerExpired());
564 EXPECT_TRUE(wdog->timerEnabled());
565
566 // Set remaining time shorter than minInterval will actually set it to
567 // minInterval
568 auto remaining = milliseconds(wdog->timeRemaining(defaultIntervalMs));
569
570 // Its possible that we are off by few msecs depending on
571 // how we get scheduled. So checking a range here.
572 EXPECT_TRUE((remaining >= minInterval - Quantum(1)) &&
573 (remaining <= minInterval));
574
575 EXPECT_FALSE(wdog->timerExpired());
576 EXPECT_TRUE(wdog->timerEnabled());
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700577}
578
579} // namespace watchdog
580} // namespace phosphor