blob: 7f0a2aa68c74c30553b3896b07b71f85a40a9609 [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 <chrono>
William A. Kennington IIId1331082018-02-27 18:47:05 -08004#include <memory>
William A. Kennington III287105c2021-04-22 15:19:02 -07005#include <sdbusplus/bus.hpp>
6#include <sdeventplus/event.hpp>
William A. Kennington IIIf505fc02018-09-12 18:30:09 -07007#include <thread>
William A. Kennington IIId1331082018-02-27 18:47:05 -08008#include <utility>
William A. Kennington III99c69de2018-03-01 10:59:22 -08009
William A. Kennington III287105c2021-04-22 15:19:02 -070010#include <gtest/gtest.h>
11
Ofer Yehiellic35135d2019-06-14 11:30:25 -070012namespace phosphor
13{
14namespace watchdog
15{
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +053016
William A. Kennington III287105c2021-04-22 15:19:02 -070017using namespace std::chrono;
18using namespace std::chrono_literals;
William A. Kennington III99c69de2018-03-01 10:59:22 -080019
William A. Kennington III287105c2021-04-22 15:19:02 -070020constexpr auto TEST_MIN_INTERVAL = duration<uint64_t, std::deci>(2);
21
22// Test Watchdog functionality
23class WdogTest : public ::testing::Test
24{
25 public:
26 // The unit time used to measure the timer
27 // This should be large enough to accomodate drift
28 using Quantum = duration<uint64_t, std::deci>;
29
30 // Gets called as part of each TEST_F construction
31 WdogTest() :
32 event(sdeventplus::Event::get_default()),
33 bus(sdbusplus::bus::new_default()),
34 wdog(std::make_unique<Watchdog>(
35 bus, TEST_PATH, event, Watchdog::ActionTargetMap(), std::nullopt,
36 milliseconds(TEST_MIN_INTERVAL).count())),
37
38 defaultInterval(Quantum(3))
39
40 {
41 wdog->interval(milliseconds(defaultInterval).count());
42 // Initially the watchdog would be disabled
43 EXPECT_FALSE(wdog->enabled());
William A. Kennington III99c69de2018-03-01 10:59:22 -080044 }
45
William A. Kennington III287105c2021-04-22 15:19:02 -070046 // sdevent Event handle
47 sdeventplus::Event event;
48
49 // sdbusplus handle
50 sdbusplus::bus::bus bus;
51
52 // Watchdog object
53 std::unique_ptr<Watchdog> wdog;
54
55 // This is the default interval as given in Interface definition
56 Quantum defaultInterval;
57
58 protected:
59 // Dummy name for object path
60 // This is just to satisfy the constructor. Does not have
61 // a need to check if the objects paths have been created.
62 static constexpr auto TEST_PATH = "/test/path";
63
64 // Returns how long it took for the current watchdog timer to be
65 // disabled or have its timeRemaining reset.
66 Quantum waitForWatchdog(Quantum timeLimit)
67 {
68 auto previousTimeRemaining = wdog->timeRemaining();
69 auto ret = Quantum(0);
70 while (ret < timeLimit &&
71 previousTimeRemaining >= wdog->timeRemaining() &&
72 wdog->timerEnabled())
73 {
74 previousTimeRemaining = wdog->timeRemaining();
75
76 constexpr auto sleepTime = Quantum(1);
77 if (event.run(sleepTime) == 0)
78 {
79 ret += sleepTime;
80 }
81 }
82
83 return ret;
84 }
85};
William A. Kennington III99c69de2018-03-01 10:59:22 -080086
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +053087/** @brief Make sure that watchdog is started and not enabled */
88TEST_F(WdogTest, createWdogAndDontEnable)
89{
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -080090 EXPECT_FALSE(wdog->enabled());
91 EXPECT_EQ(0, wdog->timeRemaining());
92 EXPECT_FALSE(wdog->timerExpired());
William A. Kennington III0650a3f2018-03-01 10:53:25 -080093 EXPECT_FALSE(wdog->timerEnabled());
William A. Kennington III25c1b202018-03-01 11:00:19 -080094
95 // We should be able to configure persistent properties
96 // while disabled
97 auto newAction = Watchdog::Action::PowerOff;
98 EXPECT_EQ(newAction, wdog->expireAction(newAction));
99 auto newIntervalMs = milliseconds(defaultInterval * 2).count();
100 EXPECT_EQ(newIntervalMs, wdog->interval(newIntervalMs));
101
102 EXPECT_EQ(newAction, wdog->expireAction());
103 EXPECT_EQ(newIntervalMs, wdog->interval());
104
105 // We won't be able to configure timeRemaining
106 EXPECT_EQ(0, wdog->timeRemaining(1000));
107 EXPECT_EQ(0, wdog->timeRemaining());
108
109 // Timer should not have become enabled
110 EXPECT_FALSE(wdog->enabled());
111 EXPECT_EQ(0, wdog->timeRemaining());
112 EXPECT_FALSE(wdog->timerExpired());
113 EXPECT_FALSE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530114}
115
116/** @brief Make sure that watchdog is started and enabled */
117TEST_F(WdogTest, createWdogAndEnable)
118{
119 // Enable and then verify
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800120 EXPECT_TRUE(wdog->enabled(true));
121 EXPECT_FALSE(wdog->timerExpired());
William A. Kennington III0650a3f2018-03-01 10:53:25 -0800122 EXPECT_TRUE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530123
124 // Get the configured interval
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800125 auto remaining = milliseconds(wdog->timeRemaining());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530126
127 // Its possible that we are off by few msecs depending on
128 // how we get scheduled. So checking a range here.
William A. Kennington III3964f002019-01-16 15:43:43 -0800129 EXPECT_TRUE((remaining >= defaultInterval - Quantum(1)) &&
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530130 (remaining <= defaultInterval));
131
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800132 EXPECT_FALSE(wdog->timerExpired());
William A. Kennington III0650a3f2018-03-01 10:53:25 -0800133 EXPECT_TRUE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530134}
135
136/** @brief Make sure that watchdog is started and enabled.
137 * Later, disable watchdog
138 */
139TEST_F(WdogTest, createWdogAndEnableThenDisable)
140{
141 // Enable and then verify
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800142 EXPECT_TRUE(wdog->enabled(true));
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530143
144 // Disable and then verify
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800145 EXPECT_FALSE(wdog->enabled(false));
146 EXPECT_FALSE(wdog->enabled());
147 EXPECT_EQ(0, wdog->timeRemaining());
William A. Kennington III0650a3f2018-03-01 10:53:25 -0800148 EXPECT_FALSE(wdog->timerExpired());
149 EXPECT_FALSE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530150}
151
152/** @brief Make sure that watchdog is started and enabled.
William A. Kennington III3964f002019-01-16 15:43:43 -0800153 * Wait for 5 quantums and make sure that the remaining
154 * time shows 5 fewer quantums.
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530155 */
William A. Kennington III3964f002019-01-16 15:43:43 -0800156TEST_F(WdogTest, enableWdogAndWait5Quantums)
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530157{
158 // Enable and then verify
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800159 EXPECT_TRUE(wdog->enabled(true));
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530160
William A. Kennington III3964f002019-01-16 15:43:43 -0800161 // Sleep for 5 quantums
162 auto sleepTime = Quantum(2);
163 ASSERT_LT(sleepTime, defaultInterval);
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530164 std::this_thread::sleep_for(sleepTime);
165
William A. Kennington III3964f002019-01-16 15:43:43 -0800166 // Get the remaining time again and expectation is that we get fewer
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800167 auto remaining = milliseconds(wdog->timeRemaining());
William A. Kennington III8cd38392018-03-01 11:07:36 -0800168 auto expected = defaultInterval - sleepTime;
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530169
170 // Its possible that we are off by few msecs depending on
171 // how we get scheduled. So checking a range here.
William A. Kennington III3964f002019-01-16 15:43:43 -0800172 EXPECT_TRUE((remaining >= expected - Quantum(1)) &&
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530173 (remaining <= expected));
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800174 EXPECT_FALSE(wdog->timerExpired());
William A. Kennington III0650a3f2018-03-01 10:53:25 -0800175 EXPECT_TRUE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530176}
177
178/** @brief Make sure that watchdog is started and enabled.
William A. Kennington III3964f002019-01-16 15:43:43 -0800179 * Wait 1 quantum and then reset the timer to 5 quantums
180 * and then expect the watchdog to expire in 5 quantums
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530181 */
William A. Kennington III3964f002019-01-16 15:43:43 -0800182TEST_F(WdogTest, enableWdogAndResetTo5Quantums)
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530183{
184 // Enable and then verify
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800185 EXPECT_TRUE(wdog->enabled(true));
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530186
187 // Sleep for 1 second
William A. Kennington III3964f002019-01-16 15:43:43 -0800188 std::this_thread::sleep_for(Quantum(1));
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530189
William A. Kennington IIIf505fc02018-09-12 18:30:09 -0700190 // Timer should still be running unexpired
191 EXPECT_FALSE(wdog->timerExpired());
192 EXPECT_TRUE(wdog->timerEnabled());
193
William A. Kennington III3964f002019-01-16 15:43:43 -0800194 // Next timer will expire in 5 quantums from now.
195 auto expireTime = Quantum(5);
William A. Kennington III8cd38392018-03-01 11:07:36 -0800196 auto expireTimeMs = milliseconds(expireTime).count();
197 EXPECT_EQ(expireTimeMs, wdog->timeRemaining(expireTimeMs));
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530198
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530199 // Waiting for expiration
William A. Kennington III3964f002019-01-16 15:43:43 -0800200 EXPECT_EQ(expireTime - Quantum(1), waitForWatchdog(expireTime));
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800201 EXPECT_TRUE(wdog->timerExpired());
William A. Kennington III0650a3f2018-03-01 10:53:25 -0800202 EXPECT_FALSE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530203}
204
Gunnar Millsbfe5cb82017-10-25 20:48:50 -0500205/** @brief Make sure the Interval can be updated directly.
Patrick Venture96816342017-08-17 12:32:22 -0700206 */
207TEST_F(WdogTest, verifyIntervalUpdateReceived)
208{
William A. Kennington III3964f002019-01-16 15:43:43 -0800209 auto expireTime = Quantum(5);
William A. Kennington III8cd38392018-03-01 11:07:36 -0800210 auto expireTimeMs = milliseconds(expireTime).count();
211 EXPECT_EQ(expireTimeMs, wdog->interval(expireTimeMs));
Patrick Venture96816342017-08-17 12:32:22 -0700212
213 // Expect an update in the Interval
William A. Kennington III8cd38392018-03-01 11:07:36 -0800214 EXPECT_EQ(expireTimeMs, wdog->interval());
Patrick Venture96816342017-08-17 12:32:22 -0700215}
216
William A. Kennington IIId4cbc5a2018-09-24 14:23:05 -0700217/** @brief Make sure the Interval can be updated while the timer is running.
218 */
219TEST_F(WdogTest, verifyIntervalUpdateRunning)
220{
221 const auto oldInterval = milliseconds(wdog->interval());
222 const auto newInterval = 5s;
223
224 EXPECT_TRUE(wdog->enabled(true));
225 auto remaining = milliseconds(wdog->timeRemaining());
226 EXPECT_GE(oldInterval, remaining);
William A. Kennington III3964f002019-01-16 15:43:43 -0800227 EXPECT_LE(oldInterval - Quantum(1), remaining);
William A. Kennington IIId4cbc5a2018-09-24 14:23:05 -0700228 EXPECT_EQ(newInterval,
229 milliseconds(wdog->interval(milliseconds(newInterval).count())));
230
231 // Expect only the interval to update
232 remaining = milliseconds(wdog->timeRemaining());
233 EXPECT_GE(oldInterval, remaining);
William A. Kennington III3964f002019-01-16 15:43:43 -0800234 EXPECT_LE(oldInterval - Quantum(1), remaining);
William A. Kennington IIId4cbc5a2018-09-24 14:23:05 -0700235 EXPECT_EQ(newInterval, milliseconds(wdog->interval()));
236
237 // Expect reset to use the new interval
238 wdog->resetTimeRemaining(false);
239 remaining = milliseconds(wdog->timeRemaining());
240 EXPECT_GE(newInterval, remaining);
William A. Kennington III3964f002019-01-16 15:43:43 -0800241 EXPECT_LE(newInterval - Quantum(1), remaining);
William A. Kennington IIId4cbc5a2018-09-24 14:23:05 -0700242}
243
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530244/** @brief Make sure that watchdog is started and enabled.
William A. Kennington III3964f002019-01-16 15:43:43 -0800245 * Wait default interval quantums and make sure that wdog has died
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530246 */
247TEST_F(WdogTest, enableWdogAndWaitTillEnd)
248{
249 // Enable and then verify
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800250 EXPECT_TRUE(wdog->enabled(true));
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530251
252 // Waiting default expiration
William A. Kennington III3964f002019-01-16 15:43:43 -0800253 EXPECT_EQ(defaultInterval - Quantum(1), waitForWatchdog(defaultInterval));
William A. Kennington III99c69de2018-03-01 10:59:22 -0800254
William A. Kennington III825f4982018-02-27 19:10:56 -0800255 EXPECT_FALSE(wdog->enabled());
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800256 EXPECT_EQ(0, wdog->timeRemaining());
257 EXPECT_TRUE(wdog->timerExpired());
William A. Kennington III0650a3f2018-03-01 10:53:25 -0800258 EXPECT_FALSE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530259}
William A. Kennington IIId1331082018-02-27 18:47:05 -0800260
261/** @brief Make sure the watchdog is started and enabled with a fallback
262 * Wait through the initial trip and ensure the fallback is observed
263 * Make sure that fallback runs to completion and ensure the watchdog
264 * is disabled
265 */
266TEST_F(WdogTest, enableWdogWithFallbackTillEnd)
267{
William A. Kennington III3964f002019-01-16 15:43:43 -0800268 auto primaryInterval = Quantum(5);
William A. Kennington IIId1331082018-02-27 18:47:05 -0800269 auto primaryIntervalMs = milliseconds(primaryInterval).count();
270 auto fallbackInterval = primaryInterval * 2;
271 auto fallbackIntervalMs = milliseconds(fallbackInterval).count();
272
273 // We need to make a wdog with the right fallback options
274 // The interval is set to be noticeably different from the default
275 // so we can always tell the difference
William A. Kennington III8cf5f642019-01-16 16:58:14 -0800276 Watchdog::Fallback fallback;
277 fallback.action = Watchdog::Action::PowerOff;
278 fallback.interval = static_cast<uint64_t>(fallbackIntervalMs);
279 fallback.always = false;
William A. Kennington III1859eeb2021-04-20 16:08:57 -0700280 wdog.reset();
William A. Kennington IIIf505fc02018-09-12 18:30:09 -0700281 wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
William A. Kennington III3bb2f402018-09-13 00:35:47 -0700282 Watchdog::ActionTargetMap(),
Patrick Venture8f6c5152018-09-11 17:45:33 -0700283 std::move(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,
William A. Kennington III3bb2f402018-09-13 00:35:47 -0700365 Watchdog::ActionTargetMap(),
Patrick Venture8f6c5152018-09-11 17:45:33 -0700366 std::move(fallback));
William A. Kennington IIId1331082018-02-27 18:47:05 -0800367 EXPECT_EQ(primaryInterval, milliseconds(wdog->interval(primaryIntervalMs)));
368 EXPECT_FALSE(wdog->enabled());
369 EXPECT_EQ(0, wdog->timeRemaining());
370 EXPECT_FALSE(wdog->timerExpired());
371 EXPECT_FALSE(wdog->timerEnabled());
372
373 // Enable and then verify
374 EXPECT_TRUE(wdog->enabled(true));
375
376 // Waiting default expiration
William A. Kennington III3964f002019-01-16 15:43:43 -0800377 EXPECT_EQ(primaryInterval - Quantum(1), waitForWatchdog(primaryInterval));
William A. Kennington IIId1331082018-02-27 18:47:05 -0800378
379 // We should now have entered the fallback once the primary expires
380 EXPECT_FALSE(wdog->enabled());
381 auto remaining = milliseconds(wdog->timeRemaining());
382 EXPECT_GE(fallbackInterval, remaining);
383 EXPECT_LT(primaryInterval, remaining);
384 EXPECT_FALSE(wdog->timerExpired());
385 EXPECT_TRUE(wdog->timerEnabled());
386
387 EXPECT_TRUE(wdog->enabled(true));
388
389 // We should have re-entered the primary
390 EXPECT_TRUE(wdog->enabled());
391 EXPECT_GE(primaryInterval, milliseconds(wdog->timeRemaining()));
392 EXPECT_FALSE(wdog->timerExpired());
393 EXPECT_TRUE(wdog->timerEnabled());
394}
William A. Kennington III22352192018-02-27 18:51:44 -0800395
Kun Yi50cc9562019-12-04 11:46:59 -0800396/** @brief Make sure the watchdog is started and enabled with a fallback
397 * Wait through the initial trip and ensure the fallback is observed
398 * Make sure that changing the primary interval and calling reset timer
399 * will enable the primary watchdog with primary interval.
400 */
401TEST_F(WdogTest, enableWdogWithFallbackResetTimerEnable)
402{
403 auto primaryInterval = Quantum(5);
404 auto primaryIntervalMs = milliseconds(primaryInterval).count();
405 auto fallbackInterval = primaryInterval * 2;
406 auto fallbackIntervalMs = milliseconds(fallbackInterval).count();
407 auto newInterval = fallbackInterval * 2;
408 auto newIntervalMs = milliseconds(newInterval).count();
409
410 // We need to make a wdog with the right fallback options
411 // The interval is set to be noticeably different from the default
412 // so we can always tell the difference
413 Watchdog::Fallback fallback;
414 fallback.action = Watchdog::Action::PowerOff;
415 fallback.interval = static_cast<uint64_t>(fallbackIntervalMs);
416 fallback.always = false;
William A. Kennington III1859eeb2021-04-20 16:08:57 -0700417 wdog.reset();
Kun Yi50cc9562019-12-04 11:46:59 -0800418 wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
419 Watchdog::ActionTargetMap(),
420 std::move(fallback));
421 EXPECT_EQ(primaryInterval, milliseconds(wdog->interval(primaryIntervalMs)));
422 EXPECT_FALSE(wdog->enabled());
423 EXPECT_EQ(0, wdog->timeRemaining());
424 EXPECT_FALSE(wdog->timerExpired());
425 EXPECT_FALSE(wdog->timerEnabled());
426
427 // Enable and then verify
428 EXPECT_TRUE(wdog->enabled(true));
429
430 // Waiting default expiration
431 EXPECT_EQ(primaryInterval - Quantum(1), waitForWatchdog(primaryInterval));
432
433 // We should now have entered the fallback once the primary expires
434 EXPECT_FALSE(wdog->enabled());
435 auto remaining = milliseconds(wdog->timeRemaining());
436 EXPECT_GE(fallbackInterval, remaining);
437 EXPECT_LT(primaryInterval, remaining);
438 EXPECT_FALSE(wdog->timerExpired());
439 EXPECT_TRUE(wdog->timerEnabled());
440
441 // Setting the interval should take effect once resetTimer re-enables wdog
442 EXPECT_EQ(newIntervalMs, wdog->interval(newIntervalMs));
443 wdog->resetTimeRemaining(true);
444
445 // We should have re-entered the primary
446 EXPECT_TRUE(wdog->enabled());
447 remaining = milliseconds(wdog->timeRemaining());
448 EXPECT_GE(newInterval, remaining);
449 EXPECT_LE(newInterval - Quantum(1), remaining);
450 EXPECT_FALSE(wdog->timerExpired());
451 EXPECT_TRUE(wdog->timerEnabled());
452}
453
William A. Kennington III22352192018-02-27 18:51:44 -0800454/** @brief Make sure the watchdog is started and with a fallback without
455 * sending an enable
456 * Then enable the watchdog
457 * Wait through the initial trip and ensure the fallback is observed
458 * Make sure that fallback runs to completion and ensure the watchdog
459 * is in the fallback state again
460 */
461TEST_F(WdogTest, enableWdogWithFallbackAlways)
462{
William A. Kennington III3964f002019-01-16 15:43:43 -0800463 auto primaryInterval = Quantum(5);
William A. Kennington III22352192018-02-27 18:51:44 -0800464 auto primaryIntervalMs = milliseconds(primaryInterval).count();
465 auto fallbackInterval = primaryInterval * 2;
466 auto fallbackIntervalMs = milliseconds(fallbackInterval).count();
467
468 // We need to make a wdog with the right fallback options
469 // The interval is set to be noticeably different from the default
470 // so we can always tell the difference
William A. Kennington III8cf5f642019-01-16 16:58:14 -0800471 Watchdog::Fallback fallback;
472 fallback.action = Watchdog::Action::PowerOff;
473 fallback.interval = static_cast<uint64_t>(fallbackIntervalMs);
474 fallback.always = true;
William A. Kennington III1859eeb2021-04-20 16:08:57 -0700475 wdog.reset();
William A. Kennington IIIf505fc02018-09-12 18:30:09 -0700476 wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700477 Watchdog::ActionTargetMap(), fallback,
478 milliseconds(TEST_MIN_INTERVAL).count());
479
480 // Make sure defualt interval is biggger than min interval
481 EXPECT_LT(milliseconds((TEST_MIN_INTERVAL).count()),
482 milliseconds(wdog->interval()));
483
William A. Kennington III22352192018-02-27 18:51:44 -0800484 EXPECT_EQ(primaryInterval, milliseconds(wdog->interval(primaryIntervalMs)));
485 EXPECT_FALSE(wdog->enabled());
486 auto remaining = milliseconds(wdog->timeRemaining());
487 EXPECT_GE(fallbackInterval, remaining);
488 EXPECT_LT(primaryInterval, remaining);
489 EXPECT_FALSE(wdog->timerExpired());
490 EXPECT_TRUE(wdog->timerEnabled());
491
492 // Enable and then verify
493 EXPECT_TRUE(wdog->enabled(true));
494 EXPECT_GE(primaryInterval, milliseconds(wdog->timeRemaining()));
495
496 // Waiting default expiration
William A. Kennington III3964f002019-01-16 15:43:43 -0800497 EXPECT_EQ(primaryInterval - Quantum(1), waitForWatchdog(primaryInterval));
William A. Kennington III22352192018-02-27 18:51:44 -0800498
499 // We should now have entered the fallback once the primary expires
500 EXPECT_FALSE(wdog->enabled());
501 remaining = milliseconds(wdog->timeRemaining());
502 EXPECT_GE(fallbackInterval, remaining);
503 EXPECT_LT(primaryInterval, remaining);
504 EXPECT_FALSE(wdog->timerExpired());
505 EXPECT_TRUE(wdog->timerEnabled());
506
507 // Waiting fallback expiration
William A. Kennington III3964f002019-01-16 15:43:43 -0800508 EXPECT_EQ(fallbackInterval - Quantum(1), waitForWatchdog(fallbackInterval));
William A. Kennington III22352192018-02-27 18:51:44 -0800509
510 // We should now enter the fallback again
511 EXPECT_FALSE(wdog->enabled());
512 remaining = milliseconds(wdog->timeRemaining());
513 EXPECT_GE(fallbackInterval, remaining);
514 EXPECT_LT(primaryInterval, remaining);
515 EXPECT_FALSE(wdog->timerExpired());
516 EXPECT_TRUE(wdog->timerEnabled());
517}
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700518
519/** @brief Test minimal interval
520 * The minimal interval was set 2 seconds
521 * Test that when setting interval to 1s , it is still returning 2s
522 */
523TEST_F(WdogTest, verifyMinIntervalSetting)
524{
525 auto newInterval = Quantum(1);
526 auto newIntervalMs = milliseconds(newInterval).count();
527 auto minIntervalMs = milliseconds(TEST_MIN_INTERVAL).count();
528
529 // Check first that the current interval is greater than minInterval
530 EXPECT_LT(minIntervalMs, wdog->interval());
531 // Check that the interval was not set to smaller value than minInterval
532 EXPECT_EQ(minIntervalMs, wdog->interval(newIntervalMs));
533 // Check that the interval was not set to smaller value than minInterval
534 EXPECT_EQ(minIntervalMs, wdog->interval());
535}
536
537/** @brief Test minimal interval
538 * Initiate default Watchdog in order to get the default
539 * interval.
540 * Initiate watchdog with minInterval greater than default
541 * interval, and make sure the default interval was set to the
542 * minInterval.
543 */
544TEST_F(WdogTest, verifyConstructorMinIntervalSetting)
545{
546 // Initiate default Watchdog and get the default interval value.
William A. Kennington III1859eeb2021-04-20 16:08:57 -0700547 wdog.reset();
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700548 wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event);
Kun Yie8e11c62019-12-04 16:35:47 -0800549 auto defaultIntervalMs = wdog->interval();
550 auto defaultInterval = milliseconds(defaultIntervalMs);
551 auto minInterval = defaultInterval + Quantum(30);
552 auto minIntervalMs = milliseconds(minInterval).count();
553
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700554 // We initiate a new Watchdog with min interval greater than the default
555 // intrval
William A. Kennington III1859eeb2021-04-20 16:08:57 -0700556 wdog.reset();
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700557 wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
558 Watchdog::ActionTargetMap(), std::nullopt,
Kun Yie8e11c62019-12-04 16:35:47 -0800559 minIntervalMs);
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700560 // Check that the interval was set to the minInterval
Kun Yie8e11c62019-12-04 16:35:47 -0800561 EXPECT_EQ(minIntervalMs, wdog->interval());
562
563 // Enable and then verify
564 EXPECT_TRUE(wdog->enabled(true));
565 EXPECT_FALSE(wdog->timerExpired());
566 EXPECT_TRUE(wdog->timerEnabled());
567
568 // Set remaining time shorter than minInterval will actually set it to
569 // minInterval
570 auto remaining = milliseconds(wdog->timeRemaining(defaultIntervalMs));
571
572 // Its possible that we are off by few msecs depending on
573 // how we get scheduled. So checking a range here.
574 EXPECT_TRUE((remaining >= minInterval - Quantum(1)) &&
575 (remaining <= minInterval));
576
577 EXPECT_FALSE(wdog->timerExpired());
578 EXPECT_TRUE(wdog->timerEnabled());
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700579}
580
581} // namespace watchdog
582} // namespace phosphor