test: Rename watchdog_test to watchdog

Tested:
    Ran through build and unit test suite.

Change-Id: I3a906ac26c43ac419eef8a98b20a498fe22f942b
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/test/watchdog.cpp b/test/watchdog.cpp
new file mode 100644
index 0000000..66cca7e
--- /dev/null
+++ b/test/watchdog.cpp
@@ -0,0 +1,394 @@
+#include "watchdog.hpp"
+
+#include <memory>
+#include <thread>
+#include <utility>
+
+using namespace phosphor::watchdog;
+
+seconds WdogTest::waitForWatchdog(seconds timeLimit)
+{
+    auto previousTimeRemaining = wdog->timeRemaining();
+    auto ret = 0s;
+    while (ret < timeLimit && previousTimeRemaining >= wdog->timeRemaining() &&
+           wdog->timerEnabled())
+    {
+        previousTimeRemaining = wdog->timeRemaining();
+
+        constexpr auto sleepTime = 1s;
+        if (event.run(sleepTime) == 0)
+        {
+            ret += sleepTime;
+        }
+    }
+
+    return ret;
+}
+
+/** @brief Make sure that watchdog is started and not enabled */
+TEST_F(WdogTest, createWdogAndDontEnable)
+{
+    EXPECT_FALSE(wdog->enabled());
+    EXPECT_EQ(0, wdog->timeRemaining());
+    EXPECT_FALSE(wdog->timerExpired());
+    EXPECT_FALSE(wdog->timerEnabled());
+
+    // We should be able to configure persistent properties
+    // while disabled
+    auto newAction = Watchdog::Action::PowerOff;
+    EXPECT_EQ(newAction, wdog->expireAction(newAction));
+    auto newIntervalMs = milliseconds(defaultInterval * 2).count();
+    EXPECT_EQ(newIntervalMs, wdog->interval(newIntervalMs));
+
+    EXPECT_EQ(newAction, wdog->expireAction());
+    EXPECT_EQ(newIntervalMs, wdog->interval());
+
+    // We won't be able to configure timeRemaining
+    EXPECT_EQ(0, wdog->timeRemaining(1000));
+    EXPECT_EQ(0, wdog->timeRemaining());
+
+    // Timer should not have become enabled
+    EXPECT_FALSE(wdog->enabled());
+    EXPECT_EQ(0, wdog->timeRemaining());
+    EXPECT_FALSE(wdog->timerExpired());
+    EXPECT_FALSE(wdog->timerEnabled());
+}
+
+/** @brief Make sure that watchdog is started and enabled */
+TEST_F(WdogTest, createWdogAndEnable)
+{
+    // Enable and then verify
+    EXPECT_TRUE(wdog->enabled(true));
+    EXPECT_FALSE(wdog->timerExpired());
+    EXPECT_TRUE(wdog->timerEnabled());
+
+    // Get the configured interval
+    auto remaining = milliseconds(wdog->timeRemaining());
+
+    // Its possible that we are off by few msecs depending on
+    // how we get scheduled. So checking a range here.
+    EXPECT_TRUE((remaining >= defaultInterval - defaultDrift) &&
+                (remaining <= defaultInterval));
+
+    EXPECT_FALSE(wdog->timerExpired());
+    EXPECT_TRUE(wdog->timerEnabled());
+}
+
+/** @brief Make sure that watchdog is started and enabled.
+ *         Later, disable watchdog
+ */
+TEST_F(WdogTest, createWdogAndEnableThenDisable)
+{
+    // Enable and then verify
+    EXPECT_TRUE(wdog->enabled(true));
+
+    // Disable and then verify
+    EXPECT_FALSE(wdog->enabled(false));
+    EXPECT_FALSE(wdog->enabled());
+    EXPECT_EQ(0, wdog->timeRemaining());
+    EXPECT_FALSE(wdog->timerExpired());
+    EXPECT_FALSE(wdog->timerEnabled());
+}
+
+/** @brief Make sure that watchdog is started and enabled.
+ *         Wait for 5 seconds and make sure that the remaining
+ *         time shows 25 seconds.
+ */
+TEST_F(WdogTest, enableWdogAndWait5Seconds)
+{
+    // Enable and then verify
+    EXPECT_TRUE(wdog->enabled(true));
+
+    // Sleep for 5 seconds
+    auto sleepTime = 5s;
+    std::this_thread::sleep_for(sleepTime);
+
+    // Get the remaining time again and expectation is that we get 25s
+    auto remaining = milliseconds(wdog->timeRemaining());
+    auto expected = defaultInterval - sleepTime;
+
+    // Its possible that we are off by few msecs depending on
+    // how we get scheduled. So checking a range here.
+    EXPECT_TRUE((remaining >= expected - defaultDrift) &&
+                (remaining <= expected));
+    EXPECT_FALSE(wdog->timerExpired());
+    EXPECT_TRUE(wdog->timerEnabled());
+}
+
+/** @brief Make sure that watchdog is started and enabled.
+ *         Wait 1 second and then reset the timer to 5 seconds
+ *         and then expect the watchdog to expire in 5 seconds
+ */
+TEST_F(WdogTest, enableWdogAndResetTo5Seconds)
+{
+    // Enable and then verify
+    EXPECT_TRUE(wdog->enabled(true));
+
+    // Sleep for 1 second
+    std::this_thread::sleep_for(1s);
+
+    // Timer should still be running unexpired
+    EXPECT_FALSE(wdog->timerExpired());
+    EXPECT_TRUE(wdog->timerEnabled());
+
+    // Next timer will expire in 5 seconds from now.
+    auto expireTime = 5s;
+    auto expireTimeMs = milliseconds(expireTime).count();
+    EXPECT_EQ(expireTimeMs, wdog->timeRemaining(expireTimeMs));
+
+    // Waiting for expiration
+    EXPECT_EQ(expireTime - 1s, waitForWatchdog(expireTime));
+    EXPECT_TRUE(wdog->timerExpired());
+    EXPECT_FALSE(wdog->timerEnabled());
+}
+
+/** @brief Make sure the Interval can be updated directly.
+ */
+TEST_F(WdogTest, verifyIntervalUpdateReceived)
+{
+    auto expireTime = 5s;
+    auto expireTimeMs = milliseconds(expireTime).count();
+    EXPECT_EQ(expireTimeMs, wdog->interval(expireTimeMs));
+
+    // Expect an update in the Interval
+    EXPECT_EQ(expireTimeMs, wdog->interval());
+}
+
+/** @brief Make sure the Interval can be updated while the timer is running.
+ */
+TEST_F(WdogTest, verifyIntervalUpdateRunning)
+{
+    const auto oldInterval = milliseconds(wdog->interval());
+    const auto newInterval = 5s;
+
+    EXPECT_TRUE(wdog->enabled(true));
+    auto remaining = milliseconds(wdog->timeRemaining());
+    EXPECT_GE(oldInterval, remaining);
+    EXPECT_LE(oldInterval - defaultDrift, remaining);
+    EXPECT_EQ(newInterval,
+              milliseconds(wdog->interval(milliseconds(newInterval).count())));
+
+    // Expect only the interval to update
+    remaining = milliseconds(wdog->timeRemaining());
+    EXPECT_GE(oldInterval, remaining);
+    EXPECT_LE(oldInterval - defaultDrift, remaining);
+    EXPECT_EQ(newInterval, milliseconds(wdog->interval()));
+
+    // Expect reset to use the new interval
+    wdog->resetTimeRemaining(false);
+    remaining = milliseconds(wdog->timeRemaining());
+    EXPECT_GE(newInterval, remaining);
+    EXPECT_LE(newInterval - defaultDrift, remaining);
+}
+
+/** @brief Make sure that watchdog is started and enabled.
+ *         Wait default interval seconds and make sure that wdog has died
+ */
+TEST_F(WdogTest, enableWdogAndWaitTillEnd)
+{
+    // Enable and then verify
+    EXPECT_TRUE(wdog->enabled(true));
+    auto expireTime = duration_cast<seconds>(defaultInterval);
+
+    // Waiting default expiration
+    EXPECT_EQ(expireTime - 1s, waitForWatchdog(expireTime));
+
+    EXPECT_FALSE(wdog->enabled());
+    EXPECT_EQ(0, wdog->timeRemaining());
+    EXPECT_TRUE(wdog->timerExpired());
+    EXPECT_FALSE(wdog->timerEnabled());
+}
+
+/** @brief Make sure the watchdog is started and enabled with a fallback
+ *         Wait through the initial trip and ensure the fallback is observed
+ *         Make sure that fallback runs to completion and ensure the watchdog
+ *         is disabled
+ */
+TEST_F(WdogTest, enableWdogWithFallbackTillEnd)
+{
+    auto primaryInterval = 5s;
+    auto primaryIntervalMs = milliseconds(primaryInterval).count();
+    auto fallbackInterval = primaryInterval * 2;
+    auto fallbackIntervalMs = milliseconds(fallbackInterval).count();
+
+    // We need to make a wdog with the right fallback options
+    // The interval is set to be noticeably different from the default
+    // so we can always tell the difference
+    Watchdog::Fallback fallback{
+        .action = Watchdog::Action::PowerOff,
+        .interval = static_cast<uint64_t>(fallbackIntervalMs),
+    };
+    wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
+                                      Watchdog::ActionTargetMap(),
+                                      std::move(fallback));
+    EXPECT_EQ(primaryInterval, milliseconds(wdog->interval(primaryIntervalMs)));
+    EXPECT_FALSE(wdog->enabled());
+    EXPECT_EQ(0, wdog->timeRemaining());
+
+    // Enable and then verify
+    EXPECT_TRUE(wdog->enabled(true));
+
+    // Waiting default expiration
+    EXPECT_EQ(primaryInterval - 1s, waitForWatchdog(primaryInterval));
+
+    // We should now have entered the fallback once the primary expires
+    EXPECT_FALSE(wdog->enabled());
+    auto remaining = milliseconds(wdog->timeRemaining());
+    EXPECT_GE(fallbackInterval, remaining);
+    EXPECT_LT(primaryInterval, remaining);
+    EXPECT_FALSE(wdog->timerExpired());
+    EXPECT_TRUE(wdog->timerEnabled());
+
+    // We should still be ticking in fallback when setting action or interval
+    auto newInterval = primaryInterval - 1s;
+    auto newIntervalMs = milliseconds(newInterval).count();
+    EXPECT_EQ(newInterval, milliseconds(wdog->interval(newIntervalMs)));
+    EXPECT_EQ(Watchdog::Action::None,
+              wdog->expireAction(Watchdog::Action::None));
+
+    EXPECT_FALSE(wdog->enabled());
+    EXPECT_GE(remaining, milliseconds(wdog->timeRemaining()));
+    EXPECT_LT(primaryInterval, milliseconds(wdog->timeRemaining()));
+    EXPECT_FALSE(wdog->timerExpired());
+    EXPECT_TRUE(wdog->timerEnabled());
+
+    // Test that setting the timeRemaining always resets the timer to the
+    // fallback interval
+    EXPECT_EQ(fallback.interval, wdog->timeRemaining(primaryInterval.count()));
+    EXPECT_FALSE(wdog->enabled());
+
+    remaining = milliseconds(wdog->timeRemaining());
+    EXPECT_GE(fallbackInterval, remaining);
+    EXPECT_LE(fallbackInterval - defaultDrift, remaining);
+    EXPECT_FALSE(wdog->timerExpired());
+    EXPECT_TRUE(wdog->timerEnabled());
+
+    // Waiting fallback expiration
+    EXPECT_EQ(fallbackInterval - 1s, waitForWatchdog(fallbackInterval));
+
+    // We should now have disabled the watchdog after the fallback expires
+    EXPECT_FALSE(wdog->enabled());
+    EXPECT_EQ(0, wdog->timeRemaining());
+    EXPECT_TRUE(wdog->timerExpired());
+    EXPECT_FALSE(wdog->timerEnabled());
+
+    // Make sure enabling the watchdog again works
+    EXPECT_TRUE(wdog->enabled(true));
+
+    // We should have re-entered the primary
+    EXPECT_TRUE(wdog->enabled());
+    EXPECT_GE(primaryInterval, milliseconds(wdog->timeRemaining()));
+    EXPECT_FALSE(wdog->timerExpired());
+    EXPECT_TRUE(wdog->timerEnabled());
+}
+
+/** @brief Make sure the watchdog is started and enabled with a fallback
+ *         Wait through the initial trip and ensure the fallback is observed
+ *         Make sure that we can re-enable the watchdog during fallback
+ */
+TEST_F(WdogTest, enableWdogWithFallbackReEnable)
+{
+    auto primaryInterval = 5s;
+    auto primaryIntervalMs = milliseconds(primaryInterval).count();
+    auto fallbackInterval = primaryInterval * 2;
+    auto fallbackIntervalMs = milliseconds(fallbackInterval).count();
+
+    // We need to make a wdog with the right fallback options
+    // The interval is set to be noticeably different from the default
+    // so we can always tell the difference
+    Watchdog::Fallback fallback{
+        .action = Watchdog::Action::PowerOff,
+        .interval = static_cast<uint64_t>(fallbackIntervalMs),
+        .always = false,
+    };
+    wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
+                                      Watchdog::ActionTargetMap(),
+                                      std::move(fallback));
+    EXPECT_EQ(primaryInterval, milliseconds(wdog->interval(primaryIntervalMs)));
+    EXPECT_FALSE(wdog->enabled());
+    EXPECT_EQ(0, wdog->timeRemaining());
+    EXPECT_FALSE(wdog->timerExpired());
+    EXPECT_FALSE(wdog->timerEnabled());
+
+    // Enable and then verify
+    EXPECT_TRUE(wdog->enabled(true));
+
+    // Waiting default expiration
+    EXPECT_EQ(primaryInterval - 1s, waitForWatchdog(primaryInterval));
+
+    // We should now have entered the fallback once the primary expires
+    EXPECT_FALSE(wdog->enabled());
+    auto remaining = milliseconds(wdog->timeRemaining());
+    EXPECT_GE(fallbackInterval, remaining);
+    EXPECT_LT(primaryInterval, remaining);
+    EXPECT_FALSE(wdog->timerExpired());
+    EXPECT_TRUE(wdog->timerEnabled());
+
+    EXPECT_TRUE(wdog->enabled(true));
+
+    // We should have re-entered the primary
+    EXPECT_TRUE(wdog->enabled());
+    EXPECT_GE(primaryInterval, milliseconds(wdog->timeRemaining()));
+    EXPECT_FALSE(wdog->timerExpired());
+    EXPECT_TRUE(wdog->timerEnabled());
+}
+
+/** @brief Make sure the watchdog is started and with a fallback without
+ *         sending an enable
+ *         Then enable the watchdog
+ *         Wait through the initial trip and ensure the fallback is observed
+ *         Make sure that fallback runs to completion and ensure the watchdog
+ *         is in the fallback state again
+ */
+TEST_F(WdogTest, enableWdogWithFallbackAlways)
+{
+    auto primaryInterval = 5s;
+    auto primaryIntervalMs = milliseconds(primaryInterval).count();
+    auto fallbackInterval = primaryInterval * 2;
+    auto fallbackIntervalMs = milliseconds(fallbackInterval).count();
+
+    // We need to make a wdog with the right fallback options
+    // The interval is set to be noticeably different from the default
+    // so we can always tell the difference
+    Watchdog::Fallback fallback{
+        .action = Watchdog::Action::PowerOff,
+        .interval = static_cast<uint64_t>(fallbackIntervalMs),
+        .always = true,
+    };
+    wdog = std::make_unique<Watchdog>(bus, TEST_PATH, event,
+                                      Watchdog::ActionTargetMap(),
+                                      std::move(fallback));
+    EXPECT_EQ(primaryInterval, milliseconds(wdog->interval(primaryIntervalMs)));
+    EXPECT_FALSE(wdog->enabled());
+    auto remaining = milliseconds(wdog->timeRemaining());
+    EXPECT_GE(fallbackInterval, remaining);
+    EXPECT_LT(primaryInterval, remaining);
+    EXPECT_FALSE(wdog->timerExpired());
+    EXPECT_TRUE(wdog->timerEnabled());
+
+    // Enable and then verify
+    EXPECT_TRUE(wdog->enabled(true));
+    EXPECT_GE(primaryInterval, milliseconds(wdog->timeRemaining()));
+
+    // Waiting default expiration
+    EXPECT_EQ(primaryInterval - 1s, waitForWatchdog(primaryInterval));
+
+    // We should now have entered the fallback once the primary expires
+    EXPECT_FALSE(wdog->enabled());
+    remaining = milliseconds(wdog->timeRemaining());
+    EXPECT_GE(fallbackInterval, remaining);
+    EXPECT_LT(primaryInterval, remaining);
+    EXPECT_FALSE(wdog->timerExpired());
+    EXPECT_TRUE(wdog->timerEnabled());
+
+    // Waiting fallback expiration
+    EXPECT_EQ(fallbackInterval - 1s, waitForWatchdog(fallbackInterval));
+
+    // We should now enter the fallback again
+    EXPECT_FALSE(wdog->enabled());
+    remaining = milliseconds(wdog->timeRemaining());
+    EXPECT_GE(fallbackInterval, remaining);
+    EXPECT_LT(primaryInterval, remaining);
+    EXPECT_FALSE(wdog->timerExpired());
+    EXPECT_TRUE(wdog->timerEnabled());
+}