diff options
| author | Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com> | 2017-05-31 14:53:42 +0530 | 
|---|---|---|
| committer | Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com> | 2017-06-06 13:12:02 +0530 | 
| commit | 00bd377e612a646b43e0186f84e1343f160daa0f (patch) | |
| tree | 706ee56ea6618500025bb06cb839efbb4043c43d | |
| parent | 3473d70d3ffc0d3e0079f07050e2bcfb175fa606 (diff) | |
| download | phosphor-watchdog-00bd377e612a646b43e0186f84e1343f160daa0f.tar.gz phosphor-watchdog-00bd377e612a646b43e0186f84e1343f160daa0f.zip  | |
Add Gtest to test watchdog
Change-Id: Ia0268b6b18999b6dd6cfd26bcadcff25734306f0
Signed-off-by: Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com>
| -rw-r--r-- | Makefile.am | 2 | ||||
| -rw-r--r-- | configure.ac | 23 | ||||
| -rw-r--r-- | test/Makefile.am | 39 | ||||
| -rw-r--r-- | test/timer_test.cpp | 72 | ||||
| -rw-r--r-- | test/timer_test.hpp | 40 | ||||
| -rw-r--r-- | test/watchdog_test.cpp | 130 | ||||
| -rw-r--r-- | test/watchdog_test.hpp | 46 | ||||
| -rw-r--r-- | watchdog.cpp | 6 | ||||
| -rw-r--r-- | watchdog.hpp | 10 | 
9 files changed, 362 insertions, 6 deletions
diff --git a/Makefile.am b/Makefile.am index cd58d99..2e9a4f1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,3 +18,5 @@ phosphor_watchdog_CXXFLAGS = $(SYSTEMD_CFLAGS)\                               ${PHOSPHOR_LOGGING_CFLAGS} \                               ${SDBUSPLUS_CFLAGS} \                               ${PHOSPHOR_DBUS_INTERFACES_CFLAGS} + +SUBDIRS = test diff --git a/configure.ac b/configure.ac index 878b30d..49b300e 100644 --- a/configure.ac +++ b/configure.ac @@ -24,6 +24,27 @@ PKG_CHECK_MODULES([PHOSPHOR_LOGGING], [phosphor-logging],, [AC_MSG_ERROR([Could  PKG_CHECK_MODULES([SDBUSPLUS], [sdbusplus],, [AC_MSG_ERROR([Could not find sdbusplus...openbmc/sdbusplus package required])])  PKG_CHECK_MODULES([PHOSPHOR_DBUS_INTERFACES], [phosphor-dbus-interfaces],, [AC_MSG_ERROR([Could not find phosphor-dbus-interfaces...openbmc/phosphor-dbus-interfaces package required])]) +# Check/set gtest specific functions. +AX_PTHREAD([GTEST_CPPFLAGS="-DGTEST_HAS_PTHREAD=1"],[GTEST_CPPFLAGS="-DGTEST_HAS_PTHREAD=0"]) +AC_SUBST(GTEST_CPPFLAGS) +AC_ARG_ENABLE([oe-sdk], +    AS_HELP_STRING([--enable-oe-sdk], [Link testcases absolutely against OE SDK so they can be ran within it.]) +) +AC_ARG_VAR(OECORE_TARGET_SYSROOT, +    [Path to the OE SDK SYSROOT]) +AS_IF([test "x$enable_oe_sdk" == "xyes"], +    AS_IF([test "x$OECORE_TARGET_SYSROOT" == "x"], +          AC_MSG_ERROR([OECORE_TARGET_SYSROOT must be set with --enable-oe-sdk]) +    ) +    AC_MSG_NOTICE([Enabling OE-SDK at $OECORE_TARGET_SYSROOT]) +    [ +        testcase_flags="-Wl,-rpath,\${OECORE_TARGET_SYSROOT}/lib" +        testcase_flags="${testcase_flags} -Wl,-rpath,\${OECORE_TARGET_SYSROOT}/usr/lib" +        testcase_flags="${testcase_flags} -Wl,-dynamic-linker,`find \${OECORE_TARGET_SYSROOT}/lib/ld-*.so | sort -r -n | head -n1`" +    ] +    AC_SUBST([OESDK_TESTCASE_FLAGS], [$testcase_flags]) +) +  # Create configured output -AC_CONFIG_FILES([Makefile]) +AC_CONFIG_FILES([Makefile test/Makefile])  AC_OUTPUT diff --git a/test/Makefile.am b/test/Makefile.am new file mode 100644 index 0000000..654f0f1 --- /dev/null +++ b/test/Makefile.am @@ -0,0 +1,39 @@ +AM_CPPFLAGS = -I$(top_srcdir) + +# Run all 'check' test programs +TESTS = $(check_PROGRAMS) + +# Build/add utest to test suite +check_PROGRAMS = timer_test \ +                 watchdog_test + +utestCPPFLAGS = -Igtest \ +                 $(GTEST_CPPFLAGS) \ +                 $(AM_CPPFLAGS) \ +                 $(SDBUSPLUS_CFLAGS) \ +                 $(PHOSPHOR_LOGGING_CFLAGS) \ +                 $(PHOSPHOR_DBUS_INTERFACES_CFLAGS) + +utestCXXFLAGS = $(PTHREAD_CFLAGS) + +utestLDFLAGS = -lgtest_main -lgtest \ +                $(PTHREAD_LIBS) \ +                $(OESDK_TESTCASE_FLAGS) \ +                $(SDBUSPLUS_LIBS) \ +                $(PHOSPHOR_LOGGING_LIBS) \ +                $(PHOSPHOR_DBUS_INTERFACES_LIBS) + +timer_test_CPPFLAGS = ${utestCPPFLAGS} +timer_test_CXXFLAGS = ${utestCXXFLAGS} +timer_test_LDFLAGS = ${utestLDFLAGS} + +watchdog_test_CPPFLAGS = ${utestCPPFLAGS} +watchdog_test_CXXFLAGS = ${utestCXXFLAGS} +watchdog_test_LDFLAGS = ${utestLDFLAGS} + +timer_test_SOURCES = timer_test.cpp +watchdog_test_SOURCES = watchdog_test.cpp + +timer_test_LDADD = $(top_builddir)/timer.o +watchdog_test_LDADD = $(top_builddir)/timer.o \ +                      $(top_builddir)/watchdog.o diff --git a/test/timer_test.cpp b/test/timer_test.cpp new file mode 100644 index 0000000..e9f323b --- /dev/null +++ b/test/timer_test.cpp @@ -0,0 +1,72 @@ +#include <chrono> +#include <timer_test.hpp> + +using namespace std::chrono; +using namespace std::chrono_literals; + +/** @brief Starts the timer and expects it to + *         expire in configured time and expects the + *         deault callback handler to kick-in + */ +TEST_F(TimerTest, testTimerForExpirationDefaultTimeoutHandler) +{ +    // Expect timer to expire in 2 seconds +    auto expireTime = seconds(2s); + +    phosphor::watchdog::Timer timer(eventP); + +    // Set the expiration and enable the timer +    timer.start(duration_cast<milliseconds>(expireTime)); +    timer.setEnabled<std::true_type>(); + +    // Waiting 2 seconds to expect expiration +    int count = 0; +    while(count < expireTime.count() && !timer.expired()) +    { +        // Returns -0- on timeout and positive number on dispatch +        auto sleepTime = duration_cast<microseconds>(seconds(1)); +        if(!sd_event_run(eventP.get(), sleepTime.count())) +        { +            count++; +        } +    } +    EXPECT_EQ(true, timer.expired()); +    EXPECT_EQ(expireTime.count() - 1, count); + +    // Make sure secondary callback was not called. +    EXPECT_EQ(false, expired); +} + +/** @brief Starts the timer and expects it to expire + *         in configured time and expects the secondary + *         callback to be called into along with default. + */ +TEST_F(TimerTest, testTimerForExpirationSecondCallBack) +{ +    // Expect timer to expire in 2 seconds +    auto expireTime = seconds(2s); + +    phosphor::watchdog::Timer timer(eventP, +                    std::bind(&TimerTest::timeOutHandler, this)); + +    // Set the expiration and enable the timer +    timer.start(duration_cast<milliseconds>(expireTime)); +    timer.setEnabled<std::true_type>(); + +    // Waiting 2 seconds to expect expiration +    int count = 0; +    while(count < expireTime.count() && !timer.expired()) +    { +        // Returns -0- on timeout and positive number on dispatch +        auto sleepTime = duration_cast<microseconds>(seconds(1)); +        if(!sd_event_run(eventP.get(), sleepTime.count())) +        { +            count++; +        } +    } +    EXPECT_EQ(true, timer.expired()); +    EXPECT_EQ(expireTime.count() - 1, count); + +    // This gets set as part of secondary callback +    EXPECT_EQ(true, expired); +} diff --git a/test/timer_test.hpp b/test/timer_test.hpp new file mode 100644 index 0000000..3f6ffea --- /dev/null +++ b/test/timer_test.hpp @@ -0,0 +1,40 @@ +#include <iostream> +#include <gtest/gtest.h> +#include <timer.hpp> + +// Base class for testing Timer +class TimerTest : public testing::Test +{ +    public: +        // systemd event handler +        sd_event* events; + +        // Need this so that events can be initialized. +        int rc; + +        // Tells if the watchdog timer expired. +        bool expired = false; + +        // Gets called as part of each TEST_F construction +        TimerTest() +            : rc(sd_event_default(&events)), +              eventP(events) +        { +            // Check for successful creation of +            // event handler and bus handler +            EXPECT_GE(rc, 0); + +            // Its already wrapped in eventP +            events = nullptr; +        } + +        // unique_ptr for sd_event +        phosphor::watchdog::EventPtr eventP; + +        // Handler called by timer expiration +        inline void timeOutHandler() +        { +            std::cout << "Time out handler called" << std::endl; +            expired = true; +        } +}; diff --git a/test/watchdog_test.cpp b/test/watchdog_test.cpp new file mode 100644 index 0000000..4e77528 --- /dev/null +++ b/test/watchdog_test.cpp @@ -0,0 +1,130 @@ +#include <watchdog_test.hpp> + +using namespace phosphor::watchdog; + +/** @brief Make sure that watchdog is started and not enabled */ +TEST_F(WdogTest, createWdogAndDontEnable) +{ +    EXPECT_EQ(false, wdog.enabled()); +    EXPECT_EQ(0, wdog.timeRemaining()); +    EXPECT_EQ(false, wdog.timerExpired()); +} + +/** @brief Make sure that watchdog is started and enabled */ +TEST_F(WdogTest, createWdogAndEnable) +{ +    // Enable and then verify +    EXPECT_EQ(true, wdog.enabled(true)); +    EXPECT_EQ(false, wdog.timerExpired()); + +    // 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_EQ(false, wdog.timerExpired()); +} + +/** @brief Make sure that watchdog is started and enabled. + *         Later, disable watchdog + */ +TEST_F(WdogTest, createWdogAndEnableThenDisable) +{ +    // Enable and then verify +    EXPECT_EQ(true, wdog.enabled(true)); + +    // Disable and then verify +    EXPECT_EQ(false, wdog.enabled(false)); +    EXPECT_EQ(false, wdog.enabled()); +    EXPECT_EQ(0, wdog.timeRemaining()); +} + +/** @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_EQ(true, wdog.enabled(true)); + +    // Sleep for 5 seconds +    auto sleepTime = seconds(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 - +                    duration_cast<milliseconds>(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_EQ(false, wdog.timerExpired()); +} + +/** @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_EQ(true, wdog.enabled(true)); + +    // Sleep for 1 second +    std::this_thread::sleep_for(1s); + +    // Next timer will expire in 5 seconds from now. +    auto expireTime = seconds(5s); +    auto newTime = duration_cast<milliseconds>(expireTime); +    wdog.timeRemaining(newTime.count()); + +    // Waiting for expiration +    int count = 0; +    while(count < expireTime.count() && !wdog.timerExpired()) +    { +        // Returns -0- on timeout and positive number on dispatch +        auto sleepTime = duration_cast<microseconds>(seconds(1s)); +        if(!sd_event_run(eventP.get(), sleepTime.count())) +        { +            count++; +        } +    } +    EXPECT_EQ(true, wdog.timerExpired()); +    EXPECT_EQ(expireTime.count() - 1 , count); + +    // Make sure secondary callback was not called. +    EXPECT_EQ(false, expired); +} + +/** @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_EQ(true, wdog.enabled(true)); +    auto expireTime = duration_cast<seconds>( +                        milliseconds(defaultInterval)); + +    // Waiting default expiration +    int count = 0; +    while(count < expireTime.count() && !wdog.timerExpired()) +    { +        // Returns -0- on timeout and positive number on dispatch +        auto sleepTime = duration_cast<microseconds>(seconds(1s)); +        if(!sd_event_run(eventP.get(), sleepTime.count())) +        { +            count++; +        } +    } +    EXPECT_EQ(true, wdog.enabled()); +    EXPECT_EQ(0, wdog.timeRemaining()); +    EXPECT_EQ(true, wdog.timerExpired()); +    EXPECT_EQ(expireTime.count() - 1, count); +} diff --git a/test/watchdog_test.hpp b/test/watchdog_test.hpp new file mode 100644 index 0000000..0d1d628 --- /dev/null +++ b/test/watchdog_test.hpp @@ -0,0 +1,46 @@ +#include <timer_test.hpp> +#include <chrono> +#include <watchdog.hpp> + +using namespace std::chrono; +using namespace std::chrono_literals; + +// Test Watchdog functionality +class WdogTest : public TimerTest +{ +    public: +        // Gets called as part of each TEST_F construction +        WdogTest() +            : bus(sdbusplus::bus::new_default()), +              wdog(bus, TEST_PATH, eventP), +              defaultInterval(milliseconds(wdog.interval())), +              defaultDrift(30) +        { +            // Check for successful creation of +            // event handler and bus handler +            EXPECT_GE(rc, 0); + +            // Initially the watchdog would be disabled +            EXPECT_EQ(false, wdog.enabled()); +        } + +        //sdbusplus handle +        sdbusplus::bus::bus bus; + +        // Watchdog object +        phosphor::watchdog::Watchdog wdog; + +        // This is the default interval as given in Interface definition +        milliseconds defaultInterval; + +        // Acceptable drift when we compare the interval to timeRemaining. +        // This is needed since it depends on when do we get scheduled and it +        // has happened that remaining time was off by few msecs. +        milliseconds defaultDrift; + +    private: +        // Dummy name for object path +        // This is just to satisfy the constructor. Does not have +        // a need to check if the objects paths have been created. +        static constexpr auto TEST_PATH = "/test/path"; +}; diff --git a/watchdog.cpp b/watchdog.cpp index 99ef679..0c82df1 100644 --- a/watchdog.cpp +++ b/watchdog.cpp @@ -17,7 +17,7 @@ constexpr auto SYSTEMD_INTERFACE  = "org.freedesktop.systemd1.Manager";  // Enable or disable watchdog  bool Watchdog::enabled(bool value)  { -    if (WatchdogInherits::enabled() != value) +    if (this->enabled() != value)      {          if (value)          { @@ -48,7 +48,7 @@ uint64_t Watchdog::timeRemaining() const  {      uint64_t timeRemain = 0; -    if (WatchdogInherits::enabled()) +    if (this->enabled())      {          // timer may have already expired and disabled          if (timer.getEnabled() != SD_EVENT_OFF) @@ -73,7 +73,7 @@ uint64_t Watchdog::timeRemaining() const  // Reset the timer to a new expiration value  uint64_t Watchdog::timeRemaining(uint64_t value)  { -    if (WatchdogInherits::enabled()) +    if (this->enabled())      {          // Disable the timer          timer.setEnabled<std::false_type>(); diff --git a/watchdog.hpp b/watchdog.hpp index 79df438..cb26b7e 100644 --- a/watchdog.hpp +++ b/watchdog.hpp @@ -9,8 +9,8 @@ namespace phosphor  {  namespace watchdog  { -using WatchdogInherits = sdbusplus::server::object::object< -        sdbusplus::xyz::openbmc_project::State::server::Watchdog>; +namespace Base = sdbusplus::xyz::openbmc_project::State::server; +using WatchdogInherits = sdbusplus::server::object::object<Base::Watchdog>;  /** @class Watchdog   *  @brief OpenBMC watchdog implementation. @@ -46,6 +46,12 @@ class Watchdog : public WatchdogInherits              // Nothing          } +        /** @brief Since we are overriding the setter-enabled but not the +         *         getter-enabled, we need to have this using in order to +         *         allow passthrough usage of the getter-enabled. +         */ +        using Base::Watchdog::enabled; +          /** @brief Enable or disable watchdog           *         If a watchdog state is changed from disable to enable,           *         the watchdog timer is set with the default expiration  | 

