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 |