summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVishwanatha Subbanna <vishwa@linux.vnet.ibm.com>2017-05-31 14:53:42 +0530
committerVishwanatha Subbanna <vishwa@linux.vnet.ibm.com>2017-06-06 13:12:02 +0530
commit00bd377e612a646b43e0186f84e1343f160daa0f (patch)
tree706ee56ea6618500025bb06cb839efbb4043c43d
parent3473d70d3ffc0d3e0079f07050e2bcfb175fa606 (diff)
downloadphosphor-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.am2
-rw-r--r--configure.ac23
-rw-r--r--test/Makefile.am39
-rw-r--r--test/timer_test.cpp72
-rw-r--r--test/timer_test.hpp40
-rw-r--r--test/watchdog_test.cpp130
-rw-r--r--test/watchdog_test.hpp46
-rw-r--r--watchdog.cpp6
-rw-r--r--watchdog.hpp10
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
OpenPOWER on IntegriCloud