blob: 06b43b8980cdf095fa2a56502b0c9b23934b8c93 [file] [log] [blame]
Patrick Venture8f6c5152018-09-11 17:45:33 -07001#include "watchdog_test.hpp"
2
William A. Kennington IIId1331082018-02-27 18:47:05 -08003#include <memory>
William A. Kennington IIIf505fc02018-09-12 18:30:09 -07004#include <thread>
William A. Kennington IIId1331082018-02-27 18:47:05 -08005#include <utility>
William A. Kennington III99c69de2018-03-01 10:59:22 -08006
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +05307using namespace phosphor::watchdog;
8
William A. Kennington III99c69de2018-03-01 10:59:22 -08009seconds WdogTest::waitForWatchdog(seconds timeLimit)
10{
11 auto previousTimeRemaining = wdog->timeRemaining();
12 auto ret = 0s;
Patrick Venture8f6c5152018-09-11 17:45:33 -070013 while (ret < timeLimit && previousTimeRemaining >= wdog->timeRemaining() &&
William A. Kennington III99c69de2018-03-01 10:59:22 -080014 wdog->timerEnabled())
15 {
16 previousTimeRemaining = wdog->timeRemaining();
17
William A. Kennington IIIf505fc02018-09-12 18:30:09 -070018 constexpr auto sleepTime = 1s;
19 if (event.run(sleepTime) == 0)
William A. Kennington III99c69de2018-03-01 10:59:22 -080020 {
21 ret += sleepTime;
22 }
23 }
24
25 return ret;
26}
27
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +053028/** @brief Make sure that watchdog is started and not enabled */
29TEST_F(WdogTest, createWdogAndDontEnable)
30{
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -080031 EXPECT_FALSE(wdog->enabled());
32 EXPECT_EQ(0, wdog->timeRemaining());
33 EXPECT_FALSE(wdog->timerExpired());
William A. Kennington III0650a3f2018-03-01 10:53:25 -080034 EXPECT_FALSE(wdog->timerEnabled());
William A. Kennington III25c1b202018-03-01 11:00:19 -080035
36 // We should be able to configure persistent properties
37 // while disabled
38 auto newAction = Watchdog::Action::PowerOff;
39 EXPECT_EQ(newAction, wdog->expireAction(newAction));
40 auto newIntervalMs = milliseconds(defaultInterval * 2).count();
41 EXPECT_EQ(newIntervalMs, wdog->interval(newIntervalMs));
42
43 EXPECT_EQ(newAction, wdog->expireAction());
44 EXPECT_EQ(newIntervalMs, wdog->interval());
45
46 // We won't be able to configure timeRemaining
47 EXPECT_EQ(0, wdog->timeRemaining(1000));
48 EXPECT_EQ(0, wdog->timeRemaining());
49
50 // Timer should not have become enabled
51 EXPECT_FALSE(wdog->enabled());
52 EXPECT_EQ(0, wdog->timeRemaining());
53 EXPECT_FALSE(wdog->timerExpired());
54 EXPECT_FALSE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +053055}
56
57/** @brief Make sure that watchdog is started and enabled */
58TEST_F(WdogTest, createWdogAndEnable)
59{
60 // Enable and then verify
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -080061 EXPECT_TRUE(wdog->enabled(true));
62 EXPECT_FALSE(wdog->timerExpired());
William A. Kennington III0650a3f2018-03-01 10:53:25 -080063 EXPECT_TRUE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +053064
65 // Get the configured interval
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -080066 auto remaining = milliseconds(wdog->timeRemaining());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +053067
68 // Its possible that we are off by few msecs depending on
69 // how we get scheduled. So checking a range here.
70 EXPECT_TRUE((remaining >= defaultInterval - defaultDrift) &&
71 (remaining <= defaultInterval));
72
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -080073 EXPECT_FALSE(wdog->timerExpired());
William A. Kennington III0650a3f2018-03-01 10:53:25 -080074 EXPECT_TRUE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +053075}
76
77/** @brief Make sure that watchdog is started and enabled.
78 * Later, disable watchdog
79 */
80TEST_F(WdogTest, createWdogAndEnableThenDisable)
81{
82 // Enable and then verify
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -080083 EXPECT_TRUE(wdog->enabled(true));
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +053084
85 // Disable and then verify
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -080086 EXPECT_FALSE(wdog->enabled(false));
87 EXPECT_FALSE(wdog->enabled());
88 EXPECT_EQ(0, wdog->timeRemaining());
William A. Kennington III0650a3f2018-03-01 10:53:25 -080089 EXPECT_FALSE(wdog->timerExpired());
90 EXPECT_FALSE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +053091}
92
93/** @brief Make sure that watchdog is started and enabled.
94 * Wait for 5 seconds and make sure that the remaining
95 * time shows 25 seconds.
96 */
97TEST_F(WdogTest, enableWdogAndWait5Seconds)
98{
99 // Enable and then verify
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800100 EXPECT_TRUE(wdog->enabled(true));
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530101
102 // Sleep for 5 seconds
William A. Kennington III8cd38392018-03-01 11:07:36 -0800103 auto sleepTime = 5s;
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530104 std::this_thread::sleep_for(sleepTime);
105
106 // Get the remaining time again and expectation is that we get 25s
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800107 auto remaining = milliseconds(wdog->timeRemaining());
William A. Kennington III8cd38392018-03-01 11:07:36 -0800108 auto expected = defaultInterval - sleepTime;
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530109
110 // Its possible that we are off by few msecs depending on
111 // how we get scheduled. So checking a range here.
112 EXPECT_TRUE((remaining >= expected - defaultDrift) &&
113 (remaining <= expected));
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800114 EXPECT_FALSE(wdog->timerExpired());
William A. Kennington III0650a3f2018-03-01 10:53:25 -0800115 EXPECT_TRUE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530116}
117
118/** @brief Make sure that watchdog is started and enabled.
119 * Wait 1 second and then reset the timer to 5 seconds
120 * and then expect the watchdog to expire in 5 seconds
121 */
122TEST_F(WdogTest, enableWdogAndResetTo5Seconds)
123{
124 // Enable and then verify
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800125 EXPECT_TRUE(wdog->enabled(true));
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530126
127 // Sleep for 1 second
128 std::this_thread::sleep_for(1s);
129
William A. Kennington IIIf505fc02018-09-12 18:30:09 -0700130 // Timer should still be running unexpired
131 EXPECT_FALSE(wdog->timerExpired());
132 EXPECT_TRUE(wdog->timerEnabled());
133
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530134 // Next timer will expire in 5 seconds from now.
William A. Kennington III8cd38392018-03-01 11:07:36 -0800135 auto expireTime = 5s;
136 auto expireTimeMs = milliseconds(expireTime).count();
137 EXPECT_EQ(expireTimeMs, wdog->timeRemaining(expireTimeMs));
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530138
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530139 // Waiting for expiration
William A. Kennington III99c69de2018-03-01 10:59:22 -0800140 EXPECT_EQ(expireTime - 1s, waitForWatchdog(expireTime));
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800141 EXPECT_TRUE(wdog->timerExpired());
William A. Kennington III0650a3f2018-03-01 10:53:25 -0800142 EXPECT_FALSE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530143}
144
Gunnar Millsbfe5cb82017-10-25 20:48:50 -0500145/** @brief Make sure the Interval can be updated directly.
Patrick Venture96816342017-08-17 12:32:22 -0700146 */
147TEST_F(WdogTest, verifyIntervalUpdateReceived)
148{
William A. Kennington III8cd38392018-03-01 11:07:36 -0800149 auto expireTime = 5s;
150 auto expireTimeMs = milliseconds(expireTime).count();
151 EXPECT_EQ(expireTimeMs, wdog->interval(expireTimeMs));
Patrick Venture96816342017-08-17 12:32:22 -0700152
153 // Expect an update in the Interval
William A. Kennington III8cd38392018-03-01 11:07:36 -0800154 EXPECT_EQ(expireTimeMs, wdog->interval());
Patrick Venture96816342017-08-17 12:32:22 -0700155}
156
William A. Kennington IIId4cbc5a2018-09-24 14:23:05 -0700157/** @brief Make sure the Interval can be updated while the timer is running.
158 */
159TEST_F(WdogTest, verifyIntervalUpdateRunning)
160{
161 const auto oldInterval = milliseconds(wdog->interval());
162 const auto newInterval = 5s;
163
164 EXPECT_TRUE(wdog->enabled(true));
165 auto remaining = milliseconds(wdog->timeRemaining());
166 EXPECT_GE(oldInterval, remaining);
167 EXPECT_LE(oldInterval - defaultDrift, remaining);
168 EXPECT_EQ(newInterval,
169 milliseconds(wdog->interval(milliseconds(newInterval).count())));
170
171 // Expect only the interval to update
172 remaining = milliseconds(wdog->timeRemaining());
173 EXPECT_GE(oldInterval, remaining);
174 EXPECT_LE(oldInterval - defaultDrift, remaining);
175 EXPECT_EQ(newInterval, milliseconds(wdog->interval()));
176
177 // Expect reset to use the new interval
178 wdog->resetTimeRemaining(false);
179 remaining = milliseconds(wdog->timeRemaining());
180 EXPECT_GE(newInterval, remaining);
181 EXPECT_LE(newInterval - defaultDrift, remaining);
182}
183
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530184/** @brief Make sure that watchdog is started and enabled.
185 * Wait default interval seconds and make sure that wdog has died
186 */
187TEST_F(WdogTest, enableWdogAndWaitTillEnd)
188{
189 // Enable and then verify
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800190 EXPECT_TRUE(wdog->enabled(true));
William A. Kennington III8cd38392018-03-01 11:07:36 -0800191 auto expireTime = duration_cast<seconds>(defaultInterval);
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530192
193 // Waiting default expiration
William A. Kennington III99c69de2018-03-01 10:59:22 -0800194 EXPECT_EQ(expireTime - 1s, waitForWatchdog(expireTime));
195
William A. Kennington III825f4982018-02-27 19:10:56 -0800196 EXPECT_FALSE(wdog->enabled());
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800197 EXPECT_EQ(0, wdog->timeRemaining());
198 EXPECT_TRUE(wdog->timerExpired());
William A. Kennington III0650a3f2018-03-01 10:53:25 -0800199 EXPECT_FALSE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530200}
William A. Kennington IIId1331082018-02-27 18:47:05 -0800201
202/** @brief Make sure the watchdog is started and enabled with a fallback
203 * Wait through the initial trip and ensure the fallback is observed
204 * Make sure that fallback runs to completion and ensure the watchdog
205 * is disabled
206 */
207TEST_F(WdogTest, enableWdogWithFallbackTillEnd)
208{
209 auto primaryInterval = 5s;
210 auto primaryIntervalMs = milliseconds(primaryInterval).count();
211 auto fallbackInterval = primaryInterval * 2;
212 auto fallbackIntervalMs = milliseconds(fallbackInterval).count();
213
214 // We need to make a wdog with the right fallback options
215 // The interval is set to be noticeably different from the default
216 // so we can always tell the difference
217 Watchdog::Fallback fallback{
218 .action = Watchdog::Action::PowerOff,
219 .interval = static_cast<uint64_t>(fallbackIntervalMs),
220 };
William A. Kennington IIIf505fc02018-09-12 18:30:09 -0700221 wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
William A. Kennington III3bb2f402018-09-13 00:35:47 -0700222 Watchdog::ActionTargetMap(),
Patrick Venture8f6c5152018-09-11 17:45:33 -0700223 std::move(fallback));
William A. Kennington IIId1331082018-02-27 18:47:05 -0800224 EXPECT_EQ(primaryInterval, milliseconds(wdog->interval(primaryIntervalMs)));
225 EXPECT_FALSE(wdog->enabled());
226 EXPECT_EQ(0, wdog->timeRemaining());
227
228 // Enable and then verify
229 EXPECT_TRUE(wdog->enabled(true));
230
231 // Waiting default expiration
232 EXPECT_EQ(primaryInterval - 1s, waitForWatchdog(primaryInterval));
233
234 // We should now have entered the fallback once the primary expires
235 EXPECT_FALSE(wdog->enabled());
236 auto remaining = milliseconds(wdog->timeRemaining());
237 EXPECT_GE(fallbackInterval, remaining);
238 EXPECT_LT(primaryInterval, remaining);
239 EXPECT_FALSE(wdog->timerExpired());
240 EXPECT_TRUE(wdog->timerEnabled());
241
242 // We should still be ticking in fallback when setting action or interval
243 auto newInterval = primaryInterval - 1s;
244 auto newIntervalMs = milliseconds(newInterval).count();
245 EXPECT_EQ(newInterval, milliseconds(wdog->interval(newIntervalMs)));
246 EXPECT_EQ(Watchdog::Action::None,
Patrick Venture8f6c5152018-09-11 17:45:33 -0700247 wdog->expireAction(Watchdog::Action::None));
William A. Kennington IIId1331082018-02-27 18:47:05 -0800248
249 EXPECT_FALSE(wdog->enabled());
250 EXPECT_GE(remaining, milliseconds(wdog->timeRemaining()));
251 EXPECT_LT(primaryInterval, milliseconds(wdog->timeRemaining()));
252 EXPECT_FALSE(wdog->timerExpired());
253 EXPECT_TRUE(wdog->timerEnabled());
254
255 // Test that setting the timeRemaining always resets the timer to the
256 // fallback interval
257 EXPECT_EQ(fallback.interval, wdog->timeRemaining(primaryInterval.count()));
258 EXPECT_FALSE(wdog->enabled());
259
260 remaining = milliseconds(wdog->timeRemaining());
261 EXPECT_GE(fallbackInterval, remaining);
262 EXPECT_LE(fallbackInterval - defaultDrift, remaining);
263 EXPECT_FALSE(wdog->timerExpired());
264 EXPECT_TRUE(wdog->timerEnabled());
265
266 // Waiting fallback expiration
267 EXPECT_EQ(fallbackInterval - 1s, waitForWatchdog(fallbackInterval));
268
269 // We should now have disabled the watchdog after the fallback expires
270 EXPECT_FALSE(wdog->enabled());
271 EXPECT_EQ(0, wdog->timeRemaining());
272 EXPECT_TRUE(wdog->timerExpired());
273 EXPECT_FALSE(wdog->timerEnabled());
274
275 // Make sure enabling the watchdog again works
276 EXPECT_TRUE(wdog->enabled(true));
277
278 // We should have re-entered the primary
279 EXPECT_TRUE(wdog->enabled());
280 EXPECT_GE(primaryInterval, milliseconds(wdog->timeRemaining()));
281 EXPECT_FALSE(wdog->timerExpired());
282 EXPECT_TRUE(wdog->timerEnabled());
283}
284
285/** @brief Make sure the watchdog is started and enabled with a fallback
286 * Wait through the initial trip and ensure the fallback is observed
287 * Make sure that we can re-enable the watchdog during fallback
288 */
289TEST_F(WdogTest, enableWdogWithFallbackReEnable)
290{
291 auto primaryInterval = 5s;
292 auto primaryIntervalMs = milliseconds(primaryInterval).count();
293 auto fallbackInterval = primaryInterval * 2;
294 auto fallbackIntervalMs = milliseconds(fallbackInterval).count();
295
296 // We need to make a wdog with the right fallback options
297 // The interval is set to be noticeably different from the default
298 // so we can always tell the difference
299 Watchdog::Fallback fallback{
300 .action = Watchdog::Action::PowerOff,
301 .interval = static_cast<uint64_t>(fallbackIntervalMs),
William A. Kennington III22352192018-02-27 18:51:44 -0800302 .always = false,
William A. Kennington IIId1331082018-02-27 18:47:05 -0800303 };
William A. Kennington IIIf505fc02018-09-12 18:30:09 -0700304 wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
William A. Kennington III3bb2f402018-09-13 00:35:47 -0700305 Watchdog::ActionTargetMap(),
Patrick Venture8f6c5152018-09-11 17:45:33 -0700306 std::move(fallback));
William A. Kennington IIId1331082018-02-27 18:47:05 -0800307 EXPECT_EQ(primaryInterval, milliseconds(wdog->interval(primaryIntervalMs)));
308 EXPECT_FALSE(wdog->enabled());
309 EXPECT_EQ(0, wdog->timeRemaining());
310 EXPECT_FALSE(wdog->timerExpired());
311 EXPECT_FALSE(wdog->timerEnabled());
312
313 // Enable and then verify
314 EXPECT_TRUE(wdog->enabled(true));
315
316 // Waiting default expiration
317 EXPECT_EQ(primaryInterval - 1s, waitForWatchdog(primaryInterval));
318
319 // We should now have entered the fallback once the primary expires
320 EXPECT_FALSE(wdog->enabled());
321 auto remaining = milliseconds(wdog->timeRemaining());
322 EXPECT_GE(fallbackInterval, remaining);
323 EXPECT_LT(primaryInterval, remaining);
324 EXPECT_FALSE(wdog->timerExpired());
325 EXPECT_TRUE(wdog->timerEnabled());
326
327 EXPECT_TRUE(wdog->enabled(true));
328
329 // We should have re-entered the primary
330 EXPECT_TRUE(wdog->enabled());
331 EXPECT_GE(primaryInterval, milliseconds(wdog->timeRemaining()));
332 EXPECT_FALSE(wdog->timerExpired());
333 EXPECT_TRUE(wdog->timerEnabled());
334}
William A. Kennington III22352192018-02-27 18:51:44 -0800335
336/** @brief Make sure the watchdog is started and with a fallback without
337 * sending an enable
338 * Then enable the watchdog
339 * Wait through the initial trip and ensure the fallback is observed
340 * Make sure that fallback runs to completion and ensure the watchdog
341 * is in the fallback state again
342 */
343TEST_F(WdogTest, enableWdogWithFallbackAlways)
344{
345 auto primaryInterval = 5s;
346 auto primaryIntervalMs = milliseconds(primaryInterval).count();
347 auto fallbackInterval = primaryInterval * 2;
348 auto fallbackIntervalMs = milliseconds(fallbackInterval).count();
349
350 // We need to make a wdog with the right fallback options
351 // The interval is set to be noticeably different from the default
352 // so we can always tell the difference
353 Watchdog::Fallback fallback{
354 .action = Watchdog::Action::PowerOff,
355 .interval = static_cast<uint64_t>(fallbackIntervalMs),
356 .always = true,
357 };
William A. Kennington IIIf505fc02018-09-12 18:30:09 -0700358 wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
William A. Kennington III3bb2f402018-09-13 00:35:47 -0700359 Watchdog::ActionTargetMap(),
Patrick Venture8f6c5152018-09-11 17:45:33 -0700360 std::move(fallback));
William A. Kennington III22352192018-02-27 18:51:44 -0800361 EXPECT_EQ(primaryInterval, milliseconds(wdog->interval(primaryIntervalMs)));
362 EXPECT_FALSE(wdog->enabled());
363 auto remaining = milliseconds(wdog->timeRemaining());
364 EXPECT_GE(fallbackInterval, remaining);
365 EXPECT_LT(primaryInterval, remaining);
366 EXPECT_FALSE(wdog->timerExpired());
367 EXPECT_TRUE(wdog->timerEnabled());
368
369 // Enable and then verify
370 EXPECT_TRUE(wdog->enabled(true));
371 EXPECT_GE(primaryInterval, milliseconds(wdog->timeRemaining()));
372
373 // Waiting default expiration
374 EXPECT_EQ(primaryInterval - 1s, waitForWatchdog(primaryInterval));
375
376 // We should now have entered the fallback once the primary expires
377 EXPECT_FALSE(wdog->enabled());
378 remaining = milliseconds(wdog->timeRemaining());
379 EXPECT_GE(fallbackInterval, remaining);
380 EXPECT_LT(primaryInterval, remaining);
381 EXPECT_FALSE(wdog->timerExpired());
382 EXPECT_TRUE(wdog->timerEnabled());
383
384 // Waiting fallback expiration
385 EXPECT_EQ(fallbackInterval - 1s, waitForWatchdog(fallbackInterval));
386
387 // We should now enter the fallback again
388 EXPECT_FALSE(wdog->enabled());
389 remaining = milliseconds(wdog->timeRemaining());
390 EXPECT_GE(fallbackInterval, remaining);
391 EXPECT_LT(primaryInterval, remaining);
392 EXPECT_FALSE(wdog->timerExpired());
393 EXPECT_TRUE(wdog->timerEnabled());
394}