blob: 4f4a4cc3f329329295bf68cd19b12222651c4481 [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
Patrick Williams73bd5272022-07-22 19:26:57 -050050 sdbusplus::bus_t bus;
William A. Kennington III287105c2021-04-22 15:19:02 -070051
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,
Willy Tucf4ce3c2021-12-09 20:39:37 -0800282 Watchdog::ActionTargetMap(), fallback);
William A. Kennington IIId1331082018-02-27 18:47:05 -0800283 EXPECT_EQ(primaryInterval, milliseconds(wdog->interval(primaryIntervalMs)));
284 EXPECT_FALSE(wdog->enabled());
285 EXPECT_EQ(0, wdog->timeRemaining());
286
287 // Enable and then verify
288 EXPECT_TRUE(wdog->enabled(true));
289
290 // Waiting default expiration
William A. Kennington III3964f002019-01-16 15:43:43 -0800291 EXPECT_EQ(primaryInterval - Quantum(1), waitForWatchdog(primaryInterval));
William A. Kennington IIId1331082018-02-27 18:47:05 -0800292
293 // We should now have entered the fallback once the primary expires
294 EXPECT_FALSE(wdog->enabled());
295 auto remaining = milliseconds(wdog->timeRemaining());
296 EXPECT_GE(fallbackInterval, remaining);
297 EXPECT_LT(primaryInterval, remaining);
298 EXPECT_FALSE(wdog->timerExpired());
299 EXPECT_TRUE(wdog->timerEnabled());
300
301 // We should still be ticking in fallback when setting action or interval
William A. Kennington III3964f002019-01-16 15:43:43 -0800302 auto newInterval = primaryInterval - Quantum(1);
William A. Kennington IIId1331082018-02-27 18:47:05 -0800303 auto newIntervalMs = milliseconds(newInterval).count();
304 EXPECT_EQ(newInterval, milliseconds(wdog->interval(newIntervalMs)));
305 EXPECT_EQ(Watchdog::Action::None,
Patrick Venture8f6c5152018-09-11 17:45:33 -0700306 wdog->expireAction(Watchdog::Action::None));
William A. Kennington IIId1331082018-02-27 18:47:05 -0800307
308 EXPECT_FALSE(wdog->enabled());
309 EXPECT_GE(remaining, milliseconds(wdog->timeRemaining()));
310 EXPECT_LT(primaryInterval, milliseconds(wdog->timeRemaining()));
311 EXPECT_FALSE(wdog->timerExpired());
312 EXPECT_TRUE(wdog->timerEnabled());
313
314 // Test that setting the timeRemaining always resets the timer to the
315 // fallback interval
316 EXPECT_EQ(fallback.interval, wdog->timeRemaining(primaryInterval.count()));
317 EXPECT_FALSE(wdog->enabled());
318
319 remaining = milliseconds(wdog->timeRemaining());
320 EXPECT_GE(fallbackInterval, remaining);
William A. Kennington III3964f002019-01-16 15:43:43 -0800321 EXPECT_LE(fallbackInterval - Quantum(1), remaining);
William A. Kennington IIId1331082018-02-27 18:47:05 -0800322 EXPECT_FALSE(wdog->timerExpired());
323 EXPECT_TRUE(wdog->timerEnabled());
324
325 // Waiting fallback expiration
William A. Kennington III3964f002019-01-16 15:43:43 -0800326 EXPECT_EQ(fallbackInterval - Quantum(1), waitForWatchdog(fallbackInterval));
William A. Kennington IIId1331082018-02-27 18:47:05 -0800327
328 // We should now have disabled the watchdog after the fallback expires
329 EXPECT_FALSE(wdog->enabled());
330 EXPECT_EQ(0, wdog->timeRemaining());
331 EXPECT_TRUE(wdog->timerExpired());
332 EXPECT_FALSE(wdog->timerEnabled());
333
334 // Make sure enabling the watchdog again works
335 EXPECT_TRUE(wdog->enabled(true));
336
337 // We should have re-entered the primary
338 EXPECT_TRUE(wdog->enabled());
339 EXPECT_GE(primaryInterval, milliseconds(wdog->timeRemaining()));
340 EXPECT_FALSE(wdog->timerExpired());
341 EXPECT_TRUE(wdog->timerEnabled());
342}
343
344/** @brief Make sure the watchdog is started and enabled with a fallback
345 * Wait through the initial trip and ensure the fallback is observed
346 * Make sure that we can re-enable the watchdog during fallback
347 */
348TEST_F(WdogTest, enableWdogWithFallbackReEnable)
349{
William A. Kennington III3964f002019-01-16 15:43:43 -0800350 auto primaryInterval = Quantum(5);
William A. Kennington IIId1331082018-02-27 18:47:05 -0800351 auto primaryIntervalMs = milliseconds(primaryInterval).count();
352 auto fallbackInterval = primaryInterval * 2;
353 auto fallbackIntervalMs = milliseconds(fallbackInterval).count();
354
355 // We need to make a wdog with the right fallback options
356 // The interval is set to be noticeably different from the default
357 // so we can always tell the difference
William A. Kennington III8cf5f642019-01-16 16:58:14 -0800358 Watchdog::Fallback fallback;
359 fallback.action = Watchdog::Action::PowerOff;
360 fallback.interval = static_cast<uint64_t>(fallbackIntervalMs);
361 fallback.always = false;
William A. Kennington III1859eeb2021-04-20 16:08:57 -0700362 wdog.reset();
William A. Kennington IIIf505fc02018-09-12 18:30:09 -0700363 wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
Willy Tucf4ce3c2021-12-09 20:39:37 -0800364 Watchdog::ActionTargetMap(), fallback);
William A. Kennington IIId1331082018-02-27 18:47:05 -0800365 EXPECT_EQ(primaryInterval, milliseconds(wdog->interval(primaryIntervalMs)));
366 EXPECT_FALSE(wdog->enabled());
367 EXPECT_EQ(0, wdog->timeRemaining());
368 EXPECT_FALSE(wdog->timerExpired());
369 EXPECT_FALSE(wdog->timerEnabled());
370
371 // Enable and then verify
372 EXPECT_TRUE(wdog->enabled(true));
373
374 // Waiting default expiration
William A. Kennington III3964f002019-01-16 15:43:43 -0800375 EXPECT_EQ(primaryInterval - Quantum(1), waitForWatchdog(primaryInterval));
William A. Kennington IIId1331082018-02-27 18:47:05 -0800376
377 // We should now have entered the fallback once the primary expires
378 EXPECT_FALSE(wdog->enabled());
379 auto remaining = milliseconds(wdog->timeRemaining());
380 EXPECT_GE(fallbackInterval, remaining);
381 EXPECT_LT(primaryInterval, remaining);
382 EXPECT_FALSE(wdog->timerExpired());
383 EXPECT_TRUE(wdog->timerEnabled());
384
385 EXPECT_TRUE(wdog->enabled(true));
386
387 // We should have re-entered the primary
388 EXPECT_TRUE(wdog->enabled());
389 EXPECT_GE(primaryInterval, milliseconds(wdog->timeRemaining()));
390 EXPECT_FALSE(wdog->timerExpired());
391 EXPECT_TRUE(wdog->timerEnabled());
392}
William A. Kennington III22352192018-02-27 18:51:44 -0800393
Kun Yi50cc9562019-12-04 11:46:59 -0800394/** @brief Make sure the watchdog is started and enabled with a fallback
395 * Wait through the initial trip and ensure the fallback is observed
396 * Make sure that changing the primary interval and calling reset timer
397 * will enable the primary watchdog with primary interval.
398 */
399TEST_F(WdogTest, enableWdogWithFallbackResetTimerEnable)
400{
401 auto primaryInterval = Quantum(5);
402 auto primaryIntervalMs = milliseconds(primaryInterval).count();
403 auto fallbackInterval = primaryInterval * 2;
404 auto fallbackIntervalMs = milliseconds(fallbackInterval).count();
405 auto newInterval = fallbackInterval * 2;
406 auto newIntervalMs = milliseconds(newInterval).count();
407
408 // We need to make a wdog with the right fallback options
409 // The interval is set to be noticeably different from the default
410 // so we can always tell the difference
411 Watchdog::Fallback fallback;
412 fallback.action = Watchdog::Action::PowerOff;
413 fallback.interval = static_cast<uint64_t>(fallbackIntervalMs);
414 fallback.always = false;
William A. Kennington III1859eeb2021-04-20 16:08:57 -0700415 wdog.reset();
Kun Yi50cc9562019-12-04 11:46:59 -0800416 wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
Willy Tucf4ce3c2021-12-09 20:39:37 -0800417 Watchdog::ActionTargetMap(), fallback);
Kun Yi50cc9562019-12-04 11:46:59 -0800418 EXPECT_EQ(primaryInterval, milliseconds(wdog->interval(primaryIntervalMs)));
419 EXPECT_FALSE(wdog->enabled());
420 EXPECT_EQ(0, wdog->timeRemaining());
421 EXPECT_FALSE(wdog->timerExpired());
422 EXPECT_FALSE(wdog->timerEnabled());
423
424 // Enable and then verify
425 EXPECT_TRUE(wdog->enabled(true));
426
427 // Waiting default expiration
428 EXPECT_EQ(primaryInterval - Quantum(1), waitForWatchdog(primaryInterval));
429
430 // We should now have entered the fallback once the primary expires
431 EXPECT_FALSE(wdog->enabled());
432 auto remaining = milliseconds(wdog->timeRemaining());
433 EXPECT_GE(fallbackInterval, remaining);
434 EXPECT_LT(primaryInterval, remaining);
435 EXPECT_FALSE(wdog->timerExpired());
436 EXPECT_TRUE(wdog->timerEnabled());
437
438 // Setting the interval should take effect once resetTimer re-enables wdog
439 EXPECT_EQ(newIntervalMs, wdog->interval(newIntervalMs));
440 wdog->resetTimeRemaining(true);
441
442 // We should have re-entered the primary
443 EXPECT_TRUE(wdog->enabled());
444 remaining = milliseconds(wdog->timeRemaining());
445 EXPECT_GE(newInterval, remaining);
446 EXPECT_LE(newInterval - Quantum(1), remaining);
447 EXPECT_FALSE(wdog->timerExpired());
448 EXPECT_TRUE(wdog->timerEnabled());
449}
450
William A. Kennington III22352192018-02-27 18:51:44 -0800451/** @brief Make sure the watchdog is started and with a fallback without
452 * sending an enable
453 * Then enable the watchdog
454 * Wait through the initial trip and ensure the fallback is observed
455 * Make sure that fallback runs to completion and ensure the watchdog
456 * is in the fallback state again
457 */
458TEST_F(WdogTest, enableWdogWithFallbackAlways)
459{
William A. Kennington III3964f002019-01-16 15:43:43 -0800460 auto primaryInterval = Quantum(5);
William A. Kennington III22352192018-02-27 18:51:44 -0800461 auto primaryIntervalMs = milliseconds(primaryInterval).count();
462 auto fallbackInterval = primaryInterval * 2;
463 auto fallbackIntervalMs = milliseconds(fallbackInterval).count();
464
465 // We need to make a wdog with the right fallback options
466 // The interval is set to be noticeably different from the default
467 // so we can always tell the difference
William A. Kennington III8cf5f642019-01-16 16:58:14 -0800468 Watchdog::Fallback fallback;
469 fallback.action = Watchdog::Action::PowerOff;
470 fallback.interval = static_cast<uint64_t>(fallbackIntervalMs);
471 fallback.always = true;
William A. Kennington III1859eeb2021-04-20 16:08:57 -0700472 wdog.reset();
William A. Kennington IIIf505fc02018-09-12 18:30:09 -0700473 wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700474 Watchdog::ActionTargetMap(), fallback,
475 milliseconds(TEST_MIN_INTERVAL).count());
476
477 // Make sure defualt interval is biggger than min interval
478 EXPECT_LT(milliseconds((TEST_MIN_INTERVAL).count()),
479 milliseconds(wdog->interval()));
480
William A. Kennington III22352192018-02-27 18:51:44 -0800481 EXPECT_EQ(primaryInterval, milliseconds(wdog->interval(primaryIntervalMs)));
482 EXPECT_FALSE(wdog->enabled());
483 auto remaining = milliseconds(wdog->timeRemaining());
484 EXPECT_GE(fallbackInterval, remaining);
485 EXPECT_LT(primaryInterval, remaining);
486 EXPECT_FALSE(wdog->timerExpired());
487 EXPECT_TRUE(wdog->timerEnabled());
488
489 // Enable and then verify
490 EXPECT_TRUE(wdog->enabled(true));
491 EXPECT_GE(primaryInterval, milliseconds(wdog->timeRemaining()));
492
493 // Waiting default expiration
William A. Kennington III3964f002019-01-16 15:43:43 -0800494 EXPECT_EQ(primaryInterval - Quantum(1), waitForWatchdog(primaryInterval));
William A. Kennington III22352192018-02-27 18:51:44 -0800495
496 // We should now have entered the fallback once the primary expires
497 EXPECT_FALSE(wdog->enabled());
498 remaining = milliseconds(wdog->timeRemaining());
499 EXPECT_GE(fallbackInterval, remaining);
500 EXPECT_LT(primaryInterval, remaining);
501 EXPECT_FALSE(wdog->timerExpired());
502 EXPECT_TRUE(wdog->timerEnabled());
503
504 // Waiting fallback expiration
William A. Kennington III3964f002019-01-16 15:43:43 -0800505 EXPECT_EQ(fallbackInterval - Quantum(1), waitForWatchdog(fallbackInterval));
William A. Kennington III22352192018-02-27 18:51:44 -0800506
507 // We should now enter the fallback again
508 EXPECT_FALSE(wdog->enabled());
509 remaining = milliseconds(wdog->timeRemaining());
510 EXPECT_GE(fallbackInterval, remaining);
511 EXPECT_LT(primaryInterval, remaining);
512 EXPECT_FALSE(wdog->timerExpired());
513 EXPECT_TRUE(wdog->timerEnabled());
514}
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700515
516/** @brief Test minimal interval
517 * The minimal interval was set 2 seconds
518 * Test that when setting interval to 1s , it is still returning 2s
519 */
520TEST_F(WdogTest, verifyMinIntervalSetting)
521{
522 auto newInterval = Quantum(1);
523 auto newIntervalMs = milliseconds(newInterval).count();
524 auto minIntervalMs = milliseconds(TEST_MIN_INTERVAL).count();
525
526 // Check first that the current interval is greater than minInterval
527 EXPECT_LT(minIntervalMs, wdog->interval());
528 // Check that the interval was not set to smaller value than minInterval
529 EXPECT_EQ(minIntervalMs, wdog->interval(newIntervalMs));
530 // Check that the interval was not set to smaller value than minInterval
531 EXPECT_EQ(minIntervalMs, wdog->interval());
532}
533
534/** @brief Test minimal interval
535 * Initiate default Watchdog in order to get the default
536 * interval.
537 * Initiate watchdog with minInterval greater than default
538 * interval, and make sure the default interval was set to the
539 * minInterval.
540 */
541TEST_F(WdogTest, verifyConstructorMinIntervalSetting)
542{
543 // Initiate default Watchdog and get the default interval value.
William A. Kennington III1859eeb2021-04-20 16:08:57 -0700544 wdog.reset();
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700545 wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event);
Kun Yie8e11c62019-12-04 16:35:47 -0800546 auto defaultIntervalMs = wdog->interval();
547 auto defaultInterval = milliseconds(defaultIntervalMs);
548 auto minInterval = defaultInterval + Quantum(30);
549 auto minIntervalMs = milliseconds(minInterval).count();
550
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700551 // We initiate a new Watchdog with min interval greater than the default
552 // intrval
William A. Kennington III1859eeb2021-04-20 16:08:57 -0700553 wdog.reset();
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700554 wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
555 Watchdog::ActionTargetMap(), std::nullopt,
Kun Yie8e11c62019-12-04 16:35:47 -0800556 minIntervalMs);
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700557 // Check that the interval was set to the minInterval
Kun Yie8e11c62019-12-04 16:35:47 -0800558 EXPECT_EQ(minIntervalMs, wdog->interval());
559
560 // Enable and then verify
561 EXPECT_TRUE(wdog->enabled(true));
562 EXPECT_FALSE(wdog->timerExpired());
563 EXPECT_TRUE(wdog->timerEnabled());
564
565 // Set remaining time shorter than minInterval will actually set it to
566 // minInterval
567 auto remaining = milliseconds(wdog->timeRemaining(defaultIntervalMs));
568
569 // Its possible that we are off by few msecs depending on
570 // how we get scheduled. So checking a range here.
571 EXPECT_TRUE((remaining >= minInterval - Quantum(1)) &&
572 (remaining <= minInterval));
573
574 EXPECT_FALSE(wdog->timerExpired());
575 EXPECT_TRUE(wdog->timerEnabled());
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700576}
577
578} // namespace watchdog
579} // namespace phosphor