1 #include "watchdog.hpp"
2 
3 #include <chrono>
4 #include <memory>
5 #include <sdbusplus/bus.hpp>
6 #include <sdeventplus/event.hpp>
7 #include <thread>
8 #include <utility>
9 
10 #include <gtest/gtest.h>
11 
12 namespace phosphor
13 {
14 namespace watchdog
15 {
16 
17 using namespace std::chrono;
18 using namespace std::chrono_literals;
19 
20 constexpr auto TEST_MIN_INTERVAL = duration<uint64_t, std::deci>(2);
21 
22 // Test Watchdog functionality
23 class 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());
44     }
45 
46     // 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 };
86 
87 /** @brief Make sure that watchdog is started and not enabled */
88 TEST_F(WdogTest, createWdogAndDontEnable)
89 {
90     EXPECT_FALSE(wdog->enabled());
91     EXPECT_EQ(0, wdog->timeRemaining());
92     EXPECT_FALSE(wdog->timerExpired());
93     EXPECT_FALSE(wdog->timerEnabled());
94 
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());
114 }
115 
116 /** @brief Make sure that watchdog is started and enabled */
117 TEST_F(WdogTest, createWdogAndEnable)
118 {
119     // Enable and then verify
120     EXPECT_TRUE(wdog->enabled(true));
121     EXPECT_FALSE(wdog->timerExpired());
122     EXPECT_TRUE(wdog->timerEnabled());
123 
124     // Get the configured interval
125     auto remaining = milliseconds(wdog->timeRemaining());
126 
127     // Its possible that we are off by few msecs depending on
128     // how we get scheduled. So checking a range here.
129     EXPECT_TRUE((remaining >= defaultInterval - Quantum(1)) &&
130                 (remaining <= defaultInterval));
131 
132     EXPECT_FALSE(wdog->timerExpired());
133     EXPECT_TRUE(wdog->timerEnabled());
134 }
135 
136 /** @brief Make sure that watchdog is started and enabled.
137  *         Later, disable watchdog
138  */
139 TEST_F(WdogTest, createWdogAndEnableThenDisable)
140 {
141     // Enable and then verify
142     EXPECT_TRUE(wdog->enabled(true));
143 
144     // Disable and then verify
145     EXPECT_FALSE(wdog->enabled(false));
146     EXPECT_FALSE(wdog->enabled());
147     EXPECT_EQ(0, wdog->timeRemaining());
148     EXPECT_FALSE(wdog->timerExpired());
149     EXPECT_FALSE(wdog->timerEnabled());
150 }
151 
152 /** @brief Make sure that watchdog is started and enabled.
153  *         Wait for 5 quantums and make sure that the remaining
154  *         time shows 5 fewer quantums.
155  */
156 TEST_F(WdogTest, enableWdogAndWait5Quantums)
157 {
158     // Enable and then verify
159     EXPECT_TRUE(wdog->enabled(true));
160 
161     // Sleep for 5 quantums
162     auto sleepTime = Quantum(2);
163     ASSERT_LT(sleepTime, defaultInterval);
164     std::this_thread::sleep_for(sleepTime);
165 
166     // Get the remaining time again and expectation is that we get fewer
167     auto remaining = milliseconds(wdog->timeRemaining());
168     auto expected = defaultInterval - sleepTime;
169 
170     // Its possible that we are off by few msecs depending on
171     // how we get scheduled. So checking a range here.
172     EXPECT_TRUE((remaining >= expected - Quantum(1)) &&
173                 (remaining <= expected));
174     EXPECT_FALSE(wdog->timerExpired());
175     EXPECT_TRUE(wdog->timerEnabled());
176 }
177 
178 /** @brief Make sure that watchdog is started and enabled.
179  *         Wait 1 quantum and then reset the timer to 5 quantums
180  *         and then expect the watchdog to expire in 5 quantums
181  */
182 TEST_F(WdogTest, enableWdogAndResetTo5Quantums)
183 {
184     // Enable and then verify
185     EXPECT_TRUE(wdog->enabled(true));
186 
187     // Sleep for 1 second
188     std::this_thread::sleep_for(Quantum(1));
189 
190     // Timer should still be running unexpired
191     EXPECT_FALSE(wdog->timerExpired());
192     EXPECT_TRUE(wdog->timerEnabled());
193 
194     // Next timer will expire in 5 quantums from now.
195     auto expireTime = Quantum(5);
196     auto expireTimeMs = milliseconds(expireTime).count();
197     EXPECT_EQ(expireTimeMs, wdog->timeRemaining(expireTimeMs));
198 
199     // Waiting for expiration
200     EXPECT_EQ(expireTime - Quantum(1), waitForWatchdog(expireTime));
201     EXPECT_TRUE(wdog->timerExpired());
202     EXPECT_FALSE(wdog->timerEnabled());
203 }
204 
205 /** @brief Make sure the Interval can be updated directly.
206  */
207 TEST_F(WdogTest, verifyIntervalUpdateReceived)
208 {
209     auto expireTime = Quantum(5);
210     auto expireTimeMs = milliseconds(expireTime).count();
211     EXPECT_EQ(expireTimeMs, wdog->interval(expireTimeMs));
212 
213     // Expect an update in the Interval
214     EXPECT_EQ(expireTimeMs, wdog->interval());
215 }
216 
217 /** @brief Make sure the Interval can be updated while the timer is running.
218  */
219 TEST_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);
227     EXPECT_LE(oldInterval - Quantum(1), remaining);
228     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);
234     EXPECT_LE(oldInterval - Quantum(1), remaining);
235     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);
241     EXPECT_LE(newInterval - Quantum(1), remaining);
242 }
243 
244 /** @brief Make sure that watchdog is started and enabled.
245  *         Wait default interval quantums and make sure that wdog has died
246  */
247 TEST_F(WdogTest, enableWdogAndWaitTillEnd)
248 {
249     // Enable and then verify
250     EXPECT_TRUE(wdog->enabled(true));
251 
252     // Waiting default expiration
253     EXPECT_EQ(defaultInterval - Quantum(1), waitForWatchdog(defaultInterval));
254 
255     EXPECT_FALSE(wdog->enabled());
256     EXPECT_EQ(0, wdog->timeRemaining());
257     EXPECT_TRUE(wdog->timerExpired());
258     EXPECT_FALSE(wdog->timerEnabled());
259 }
260 
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  */
266 TEST_F(WdogTest, enableWdogWithFallbackTillEnd)
267 {
268     auto primaryInterval = Quantum(5);
269     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
276     Watchdog::Fallback fallback;
277     fallback.action = Watchdog::Action::PowerOff;
278     fallback.interval = static_cast<uint64_t>(fallbackIntervalMs);
279     fallback.always = false;
280     wdog.reset();
281     wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
282                                       Watchdog::ActionTargetMap(),
283                                       std::move(fallback));
284     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
292     EXPECT_EQ(primaryInterval - Quantum(1), waitForWatchdog(primaryInterval));
293 
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
303     auto newInterval = primaryInterval - Quantum(1);
304     auto newIntervalMs = milliseconds(newInterval).count();
305     EXPECT_EQ(newInterval, milliseconds(wdog->interval(newIntervalMs)));
306     EXPECT_EQ(Watchdog::Action::None,
307               wdog->expireAction(Watchdog::Action::None));
308 
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);
322     EXPECT_LE(fallbackInterval - Quantum(1), remaining);
323     EXPECT_FALSE(wdog->timerExpired());
324     EXPECT_TRUE(wdog->timerEnabled());
325 
326     // Waiting fallback expiration
327     EXPECT_EQ(fallbackInterval - Quantum(1), waitForWatchdog(fallbackInterval));
328 
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  */
349 TEST_F(WdogTest, enableWdogWithFallbackReEnable)
350 {
351     auto primaryInterval = Quantum(5);
352     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
359     Watchdog::Fallback fallback;
360     fallback.action = Watchdog::Action::PowerOff;
361     fallback.interval = static_cast<uint64_t>(fallbackIntervalMs);
362     fallback.always = false;
363     wdog.reset();
364     wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
365                                       Watchdog::ActionTargetMap(),
366                                       std::move(fallback));
367     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
377     EXPECT_EQ(primaryInterval - Quantum(1), waitForWatchdog(primaryInterval));
378 
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 }
395 
396 /** @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  */
401 TEST_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;
417     wdog.reset();
418     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 
454 /** @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  */
461 TEST_F(WdogTest, enableWdogWithFallbackAlways)
462 {
463     auto primaryInterval = Quantum(5);
464     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
471     Watchdog::Fallback fallback;
472     fallback.action = Watchdog::Action::PowerOff;
473     fallback.interval = static_cast<uint64_t>(fallbackIntervalMs);
474     fallback.always = true;
475     wdog.reset();
476     wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
477                                       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 
484     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
497     EXPECT_EQ(primaryInterval - Quantum(1), waitForWatchdog(primaryInterval));
498 
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
508     EXPECT_EQ(fallbackInterval - Quantum(1), waitForWatchdog(fallbackInterval));
509 
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 }
518 
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  */
523 TEST_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  */
544 TEST_F(WdogTest, verifyConstructorMinIntervalSetting)
545 {
546     // Initiate default Watchdog and get the default interval value.
547     wdog.reset();
548     wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event);
549     auto defaultIntervalMs = wdog->interval();
550     auto defaultInterval = milliseconds(defaultIntervalMs);
551     auto minInterval = defaultInterval + Quantum(30);
552     auto minIntervalMs = milliseconds(minInterval).count();
553 
554     // We initiate a new Watchdog with min interval greater than the default
555     // intrval
556     wdog.reset();
557     wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
558                                       Watchdog::ActionTargetMap(), std::nullopt,
559                                       minIntervalMs);
560     // Check that the interval was set to the minInterval
561     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());
579 }
580 
581 } // namespace watchdog
582 } // namespace phosphor
583