blob: 49890dad3295682c2cf88c95e639e212e3b02f32 [file] [log] [blame]
Patrick Venture8f6c5152018-09-11 17:45:33 -07001#include "watchdog_test.hpp"
2
William A. Kennington III99c69de2018-03-01 10:59:22 -08003#include <chrono>
William A. Kennington IIId1331082018-02-27 18:47:05 -08004#include <memory>
5#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
18 // Returns -0- on timeout and positive number on dispatch
19 auto sleepTime = 1s;
Patrick Venture8f6c5152018-09-11 17:45:33 -070020 if (!sd_event_run(eventP.get(), microseconds(sleepTime).count()))
William A. Kennington III99c69de2018-03-01 10:59:22 -080021 {
22 ret += sleepTime;
23 }
24 }
25
26 return ret;
27}
28
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +053029/** @brief Make sure that watchdog is started and not enabled */
30TEST_F(WdogTest, createWdogAndDontEnable)
31{
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -080032 EXPECT_FALSE(wdog->enabled());
33 EXPECT_EQ(0, wdog->timeRemaining());
34 EXPECT_FALSE(wdog->timerExpired());
William A. Kennington III0650a3f2018-03-01 10:53:25 -080035 EXPECT_FALSE(wdog->timerEnabled());
William A. Kennington III25c1b202018-03-01 11:00:19 -080036
37 // We should be able to configure persistent properties
38 // while disabled
39 auto newAction = Watchdog::Action::PowerOff;
40 EXPECT_EQ(newAction, wdog->expireAction(newAction));
41 auto newIntervalMs = milliseconds(defaultInterval * 2).count();
42 EXPECT_EQ(newIntervalMs, wdog->interval(newIntervalMs));
43
44 EXPECT_EQ(newAction, wdog->expireAction());
45 EXPECT_EQ(newIntervalMs, wdog->interval());
46
47 // We won't be able to configure timeRemaining
48 EXPECT_EQ(0, wdog->timeRemaining(1000));
49 EXPECT_EQ(0, wdog->timeRemaining());
50
51 // Timer should not have become enabled
52 EXPECT_FALSE(wdog->enabled());
53 EXPECT_EQ(0, wdog->timeRemaining());
54 EXPECT_FALSE(wdog->timerExpired());
55 EXPECT_FALSE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +053056}
57
58/** @brief Make sure that watchdog is started and enabled */
59TEST_F(WdogTest, createWdogAndEnable)
60{
61 // Enable and then verify
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -080062 EXPECT_TRUE(wdog->enabled(true));
63 EXPECT_FALSE(wdog->timerExpired());
William A. Kennington III0650a3f2018-03-01 10:53:25 -080064 EXPECT_TRUE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +053065
66 // Get the configured interval
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -080067 auto remaining = milliseconds(wdog->timeRemaining());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +053068
69 // Its possible that we are off by few msecs depending on
70 // how we get scheduled. So checking a range here.
71 EXPECT_TRUE((remaining >= defaultInterval - defaultDrift) &&
72 (remaining <= defaultInterval));
73
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -080074 EXPECT_FALSE(wdog->timerExpired());
William A. Kennington III0650a3f2018-03-01 10:53:25 -080075 EXPECT_TRUE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +053076}
77
78/** @brief Make sure that watchdog is started and enabled.
79 * Later, disable watchdog
80 */
81TEST_F(WdogTest, createWdogAndEnableThenDisable)
82{
83 // Enable and then verify
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -080084 EXPECT_TRUE(wdog->enabled(true));
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +053085
86 // Disable and then verify
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -080087 EXPECT_FALSE(wdog->enabled(false));
88 EXPECT_FALSE(wdog->enabled());
89 EXPECT_EQ(0, wdog->timeRemaining());
William A. Kennington III0650a3f2018-03-01 10:53:25 -080090 EXPECT_FALSE(wdog->timerExpired());
91 EXPECT_FALSE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +053092}
93
94/** @brief Make sure that watchdog is started and enabled.
95 * Wait for 5 seconds and make sure that the remaining
96 * time shows 25 seconds.
97 */
98TEST_F(WdogTest, enableWdogAndWait5Seconds)
99{
100 // Enable and then verify
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800101 EXPECT_TRUE(wdog->enabled(true));
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530102
103 // Sleep for 5 seconds
William A. Kennington III8cd38392018-03-01 11:07:36 -0800104 auto sleepTime = 5s;
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530105 std::this_thread::sleep_for(sleepTime);
106
107 // Get the remaining time again and expectation is that we get 25s
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800108 auto remaining = milliseconds(wdog->timeRemaining());
William A. Kennington III8cd38392018-03-01 11:07:36 -0800109 auto expected = defaultInterval - sleepTime;
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530110
111 // Its possible that we are off by few msecs depending on
112 // how we get scheduled. So checking a range here.
113 EXPECT_TRUE((remaining >= expected - defaultDrift) &&
114 (remaining <= expected));
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800115 EXPECT_FALSE(wdog->timerExpired());
William A. Kennington III0650a3f2018-03-01 10:53:25 -0800116 EXPECT_TRUE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530117}
118
119/** @brief Make sure that watchdog is started and enabled.
120 * Wait 1 second and then reset the timer to 5 seconds
121 * and then expect the watchdog to expire in 5 seconds
122 */
123TEST_F(WdogTest, enableWdogAndResetTo5Seconds)
124{
125 // Enable and then verify
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800126 EXPECT_TRUE(wdog->enabled(true));
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530127
128 // Sleep for 1 second
129 std::this_thread::sleep_for(1s);
130
131 // Next timer will expire in 5 seconds from now.
William A. Kennington III8cd38392018-03-01 11:07:36 -0800132 auto expireTime = 5s;
133 auto expireTimeMs = milliseconds(expireTime).count();
134 EXPECT_EQ(expireTimeMs, wdog->timeRemaining(expireTimeMs));
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530135
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530136 // Waiting for expiration
William A. Kennington III99c69de2018-03-01 10:59:22 -0800137 EXPECT_EQ(expireTime - 1s, waitForWatchdog(expireTime));
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800138 EXPECT_TRUE(wdog->timerExpired());
William A. Kennington III0650a3f2018-03-01 10:53:25 -0800139 EXPECT_FALSE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530140
141 // Make sure secondary callback was not called.
William A. Kennington IIId5d14832018-02-28 09:54:08 -0800142 EXPECT_FALSE(expired);
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
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530157/** @brief Make sure that watchdog is started and enabled.
158 * Wait default interval seconds and make sure that wdog has died
159 */
160TEST_F(WdogTest, enableWdogAndWaitTillEnd)
161{
162 // Enable and then verify
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800163 EXPECT_TRUE(wdog->enabled(true));
William A. Kennington III8cd38392018-03-01 11:07:36 -0800164 auto expireTime = duration_cast<seconds>(defaultInterval);
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530165
166 // Waiting default expiration
William A. Kennington III99c69de2018-03-01 10:59:22 -0800167 EXPECT_EQ(expireTime - 1s, waitForWatchdog(expireTime));
168
William A. Kennington III825f4982018-02-27 19:10:56 -0800169 EXPECT_FALSE(wdog->enabled());
William A. Kennington IIIf0fe2d62018-02-28 15:20:16 -0800170 EXPECT_EQ(0, wdog->timeRemaining());
171 EXPECT_TRUE(wdog->timerExpired());
William A. Kennington III0650a3f2018-03-01 10:53:25 -0800172 EXPECT_FALSE(wdog->timerEnabled());
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530173}
William A. Kennington IIId1331082018-02-27 18:47:05 -0800174
175/** @brief Make sure the watchdog is started and enabled with a fallback
176 * Wait through the initial trip and ensure the fallback is observed
177 * Make sure that fallback runs to completion and ensure the watchdog
178 * is disabled
179 */
180TEST_F(WdogTest, enableWdogWithFallbackTillEnd)
181{
182 auto primaryInterval = 5s;
183 auto primaryIntervalMs = milliseconds(primaryInterval).count();
184 auto fallbackInterval = primaryInterval * 2;
185 auto fallbackIntervalMs = milliseconds(fallbackInterval).count();
186
187 // We need to make a wdog with the right fallback options
188 // The interval is set to be noticeably different from the default
189 // so we can always tell the difference
190 Watchdog::Fallback fallback{
191 .action = Watchdog::Action::PowerOff,
192 .interval = static_cast<uint64_t>(fallbackIntervalMs),
193 };
William A. Kennington IIId1331082018-02-27 18:47:05 -0800194 wdog = std::make_unique<Watchdog>(bus, TEST_PATH, eventP,
William A. Kennington III3bb2f402018-09-13 00:35:47 -0700195 Watchdog::ActionTargetMap(),
Patrick Venture8f6c5152018-09-11 17:45:33 -0700196 std::move(fallback));
William A. Kennington IIId1331082018-02-27 18:47:05 -0800197 EXPECT_EQ(primaryInterval, milliseconds(wdog->interval(primaryIntervalMs)));
198 EXPECT_FALSE(wdog->enabled());
199 EXPECT_EQ(0, wdog->timeRemaining());
200
201 // Enable and then verify
202 EXPECT_TRUE(wdog->enabled(true));
203
204 // Waiting default expiration
205 EXPECT_EQ(primaryInterval - 1s, waitForWatchdog(primaryInterval));
206
207 // We should now have entered the fallback once the primary expires
208 EXPECT_FALSE(wdog->enabled());
209 auto remaining = milliseconds(wdog->timeRemaining());
210 EXPECT_GE(fallbackInterval, remaining);
211 EXPECT_LT(primaryInterval, remaining);
212 EXPECT_FALSE(wdog->timerExpired());
213 EXPECT_TRUE(wdog->timerEnabled());
214
215 // We should still be ticking in fallback when setting action or interval
216 auto newInterval = primaryInterval - 1s;
217 auto newIntervalMs = milliseconds(newInterval).count();
218 EXPECT_EQ(newInterval, milliseconds(wdog->interval(newIntervalMs)));
219 EXPECT_EQ(Watchdog::Action::None,
Patrick Venture8f6c5152018-09-11 17:45:33 -0700220 wdog->expireAction(Watchdog::Action::None));
William A. Kennington IIId1331082018-02-27 18:47:05 -0800221
222 EXPECT_FALSE(wdog->enabled());
223 EXPECT_GE(remaining, milliseconds(wdog->timeRemaining()));
224 EXPECT_LT(primaryInterval, milliseconds(wdog->timeRemaining()));
225 EXPECT_FALSE(wdog->timerExpired());
226 EXPECT_TRUE(wdog->timerEnabled());
227
228 // Test that setting the timeRemaining always resets the timer to the
229 // fallback interval
230 EXPECT_EQ(fallback.interval, wdog->timeRemaining(primaryInterval.count()));
231 EXPECT_FALSE(wdog->enabled());
232
233 remaining = milliseconds(wdog->timeRemaining());
234 EXPECT_GE(fallbackInterval, remaining);
235 EXPECT_LE(fallbackInterval - defaultDrift, remaining);
236 EXPECT_FALSE(wdog->timerExpired());
237 EXPECT_TRUE(wdog->timerEnabled());
238
239 // Waiting fallback expiration
240 EXPECT_EQ(fallbackInterval - 1s, waitForWatchdog(fallbackInterval));
241
242 // We should now have disabled the watchdog after the fallback expires
243 EXPECT_FALSE(wdog->enabled());
244 EXPECT_EQ(0, wdog->timeRemaining());
245 EXPECT_TRUE(wdog->timerExpired());
246 EXPECT_FALSE(wdog->timerEnabled());
247
248 // Make sure enabling the watchdog again works
249 EXPECT_TRUE(wdog->enabled(true));
250
251 // We should have re-entered the primary
252 EXPECT_TRUE(wdog->enabled());
253 EXPECT_GE(primaryInterval, milliseconds(wdog->timeRemaining()));
254 EXPECT_FALSE(wdog->timerExpired());
255 EXPECT_TRUE(wdog->timerEnabled());
256}
257
258/** @brief Make sure the watchdog is started and enabled with a fallback
259 * Wait through the initial trip and ensure the fallback is observed
260 * Make sure that we can re-enable the watchdog during fallback
261 */
262TEST_F(WdogTest, enableWdogWithFallbackReEnable)
263{
264 auto primaryInterval = 5s;
265 auto primaryIntervalMs = milliseconds(primaryInterval).count();
266 auto fallbackInterval = primaryInterval * 2;
267 auto fallbackIntervalMs = milliseconds(fallbackInterval).count();
268
269 // We need to make a wdog with the right fallback options
270 // The interval is set to be noticeably different from the default
271 // so we can always tell the difference
272 Watchdog::Fallback fallback{
273 .action = Watchdog::Action::PowerOff,
274 .interval = static_cast<uint64_t>(fallbackIntervalMs),
William A. Kennington III22352192018-02-27 18:51:44 -0800275 .always = false,
William A. Kennington IIId1331082018-02-27 18:47:05 -0800276 };
William A. Kennington IIId1331082018-02-27 18:47:05 -0800277 wdog = std::make_unique<Watchdog>(bus, TEST_PATH, eventP,
William A. Kennington III3bb2f402018-09-13 00:35:47 -0700278 Watchdog::ActionTargetMap(),
Patrick Venture8f6c5152018-09-11 17:45:33 -0700279 std::move(fallback));
William A. Kennington IIId1331082018-02-27 18:47:05 -0800280 EXPECT_EQ(primaryInterval, milliseconds(wdog->interval(primaryIntervalMs)));
281 EXPECT_FALSE(wdog->enabled());
282 EXPECT_EQ(0, wdog->timeRemaining());
283 EXPECT_FALSE(wdog->timerExpired());
284 EXPECT_FALSE(wdog->timerEnabled());
285
286 // Enable and then verify
287 EXPECT_TRUE(wdog->enabled(true));
288
289 // Waiting default expiration
290 EXPECT_EQ(primaryInterval - 1s, waitForWatchdog(primaryInterval));
291
292 // We should now have entered the fallback once the primary expires
293 EXPECT_FALSE(wdog->enabled());
294 auto remaining = milliseconds(wdog->timeRemaining());
295 EXPECT_GE(fallbackInterval, remaining);
296 EXPECT_LT(primaryInterval, remaining);
297 EXPECT_FALSE(wdog->timerExpired());
298 EXPECT_TRUE(wdog->timerEnabled());
299
300 EXPECT_TRUE(wdog->enabled(true));
301
302 // We should have re-entered the primary
303 EXPECT_TRUE(wdog->enabled());
304 EXPECT_GE(primaryInterval, milliseconds(wdog->timeRemaining()));
305 EXPECT_FALSE(wdog->timerExpired());
306 EXPECT_TRUE(wdog->timerEnabled());
307}
William A. Kennington III22352192018-02-27 18:51:44 -0800308
309/** @brief Make sure the watchdog is started and with a fallback without
310 * sending an enable
311 * Then enable the watchdog
312 * Wait through the initial trip and ensure the fallback is observed
313 * Make sure that fallback runs to completion and ensure the watchdog
314 * is in the fallback state again
315 */
316TEST_F(WdogTest, enableWdogWithFallbackAlways)
317{
318 auto primaryInterval = 5s;
319 auto primaryIntervalMs = milliseconds(primaryInterval).count();
320 auto fallbackInterval = primaryInterval * 2;
321 auto fallbackIntervalMs = milliseconds(fallbackInterval).count();
322
323 // We need to make a wdog with the right fallback options
324 // The interval is set to be noticeably different from the default
325 // so we can always tell the difference
326 Watchdog::Fallback fallback{
327 .action = Watchdog::Action::PowerOff,
328 .interval = static_cast<uint64_t>(fallbackIntervalMs),
329 .always = true,
330 };
William A. Kennington III22352192018-02-27 18:51:44 -0800331 wdog = std::make_unique<Watchdog>(bus, TEST_PATH, eventP,
William A. Kennington III3bb2f402018-09-13 00:35:47 -0700332 Watchdog::ActionTargetMap(),
Patrick Venture8f6c5152018-09-11 17:45:33 -0700333 std::move(fallback));
William A. Kennington III22352192018-02-27 18:51:44 -0800334 EXPECT_EQ(primaryInterval, milliseconds(wdog->interval(primaryIntervalMs)));
335 EXPECT_FALSE(wdog->enabled());
336 auto remaining = milliseconds(wdog->timeRemaining());
337 EXPECT_GE(fallbackInterval, remaining);
338 EXPECT_LT(primaryInterval, remaining);
339 EXPECT_FALSE(wdog->timerExpired());
340 EXPECT_TRUE(wdog->timerEnabled());
341
342 // Enable and then verify
343 EXPECT_TRUE(wdog->enabled(true));
344 EXPECT_GE(primaryInterval, milliseconds(wdog->timeRemaining()));
345
346 // Waiting default expiration
347 EXPECT_EQ(primaryInterval - 1s, waitForWatchdog(primaryInterval));
348
349 // We should now have entered the fallback once the primary expires
350 EXPECT_FALSE(wdog->enabled());
351 remaining = milliseconds(wdog->timeRemaining());
352 EXPECT_GE(fallbackInterval, remaining);
353 EXPECT_LT(primaryInterval, remaining);
354 EXPECT_FALSE(wdog->timerExpired());
355 EXPECT_TRUE(wdog->timerEnabled());
356
357 // Waiting fallback expiration
358 EXPECT_EQ(fallbackInterval - 1s, waitForWatchdog(fallbackInterval));
359
360 // We should now enter the fallback again
361 EXPECT_FALSE(wdog->enabled());
362 remaining = milliseconds(wdog->timeRemaining());
363 EXPECT_GE(fallbackInterval, remaining);
364 EXPECT_LT(primaryInterval, remaining);
365 EXPECT_FALSE(wdog->timerExpired());
366 EXPECT_TRUE(wdog->timerEnabled());
367}