add common timer.hpp unit tests
Add unit tests for timer.hpp class. These are the unit tests copied from
the phosphor-host-ipmid/softoff/test directory.
Change-Id: I9d74c6eb528f652965f43a3a4b973368ed782bf0
Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
diff --git a/test/Makefile.am b/test/Makefile.am
index 5848c67..a2ea724 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -10,7 +10,7 @@
AM_CXXFLAGS = $(CODE_COVERAGE_CXXFLAGS)
test_ldadd = $(top_builddir)/libsdbusplus.la $(SYSTEMD_LIBS) \
$(OESDK_TESTCASE_FLAGS) $(CODE_COVERAGE_LIBS)
-gtest_ldadd = $(test_ldadd) $(GTEST_LIBS) $(GMOCK_LIBS) -lgmock_main
+gtest_ldadd = $(test_ldadd) $(GTEST_LIBS) $(GMOCK_LIBS) -lgmock_main -lpthread
check_PROGRAMS =
TESTS = $(check_PROGRAMS)
@@ -55,4 +55,8 @@
vtable_vtable_SOURCES = vtable/vtable.cpp vtable/vtable_c.c
vtable_vtable_LDADD = $(gtest_ldadd)
+check_PROGRAMS += timer
+timer_SOURCES = timer.cpp
+timer_LDADD = $(gtest_ldadd)
+
endif
diff --git a/test/timer.cpp b/test/timer.cpp
new file mode 100644
index 0000000..f27fc6e
--- /dev/null
+++ b/test/timer.cpp
@@ -0,0 +1,262 @@
+#include <chrono>
+#include <iostream>
+#include <sdbusplus/timer.hpp>
+
+#include <gtest/gtest.h>
+
+using namespace phosphor;
+
+class TimerTest : public ::testing::Test
+{
+ public:
+ // systemd event handler
+ sd_event* events;
+
+ // Need this so that events can be initialized.
+ int rc;
+
+ // Source of event
+ sd_event_source* eventSource = nullptr;
+
+ // Add a Timer Object
+ Timer timer;
+
+ // Gets called as part of each TEST_F construction
+ TimerTest() : rc(sd_event_default(&events)), timer(events)
+ {
+ // Check for successful creation of
+ // event handler and timer object.
+ EXPECT_GE(rc, 0);
+ }
+
+ // Gets called as part of each TEST_F destruction
+ ~TimerTest()
+ {
+ events = sd_event_unref(events);
+ }
+};
+
+class TimerTestCallBack : public ::testing::Test
+{
+ public:
+ // systemd event handler
+ sd_event* events;
+
+ // Need this so that events can be initialized.
+ int rc;
+
+ // Source of event
+ sd_event_source* eventSource = nullptr;
+
+ // Add a Timer Object
+ std::unique_ptr<Timer> timer = nullptr;
+
+ // Indicates optional call back fun was called
+ bool callBackDone = false;
+
+ void callBack()
+ {
+ callBackDone = true;
+ }
+
+ // Gets called as part of each TEST_F construction
+ TimerTestCallBack() : rc(sd_event_default(&events))
+
+ {
+ // Check for successful creation of
+ // event handler and timer object.
+ EXPECT_GE(rc, 0);
+
+ std::function<void()> func(
+ std::bind(&TimerTestCallBack::callBack, this));
+ timer = std::make_unique<Timer>(events, func);
+ }
+
+ // Gets called as part of each TEST_F destruction
+ ~TimerTestCallBack()
+ {
+ events = sd_event_unref(events);
+ }
+};
+
+/** @brief Makes sure that timer is expired and the
+ * callback handler gets invoked post 2 seconds
+ */
+TEST_F(TimerTest, timerExpiresAfter2seconds)
+{
+ using namespace std::chrono;
+
+ auto time = duration_cast<microseconds>(seconds(2));
+ EXPECT_GE(timer.start(time), 0);
+
+ // Waiting 2 seconds is enough here since we have
+ // already spent some usec now
+ int count = 0;
+ while (count < 2 && !timer.isExpired())
+ {
+ // Returns -0- on timeout and positive number on dispatch
+ auto sleepTime = duration_cast<microseconds>(seconds(1));
+ if (!sd_event_run(events, sleepTime.count()))
+ {
+ count++;
+ }
+ }
+ EXPECT_EQ(true, timer.isExpired());
+ EXPECT_EQ(1, count);
+}
+
+/** @brief Makes sure that timer is not expired
+ */
+TEST_F(TimerTest, timerNotExpiredAfter2Seconds)
+{
+ using namespace std::chrono;
+
+ auto time = duration_cast<microseconds>(seconds(2));
+ EXPECT_GE(timer.start(time), 0);
+
+ // Now turn off the timer post a 1 second sleep
+ sleep(1);
+ EXPECT_GE(timer.stop(), 0);
+
+ // Wait 2 seconds and see that timer is not expired
+ int count = 0;
+ while (count < 2)
+ {
+ // Returns -0- on timeout
+ auto sleepTime = duration_cast<microseconds>(seconds(1));
+ if (!sd_event_run(events, sleepTime.count()))
+ {
+ count++;
+ }
+ }
+ EXPECT_EQ(false, timer.isExpired());
+
+ // 2 because of one more count that happens prior to exiting
+ EXPECT_EQ(2, count);
+}
+
+/** @brief Makes sure that timer value is changed in between
+ * and that the new timer expires
+ */
+TEST_F(TimerTest, updateTimerAndExpectExpire)
+{
+ using namespace std::chrono;
+
+ auto time = duration_cast<microseconds>(seconds(2));
+ EXPECT_GE(timer.start(time), 0);
+
+ // Now sleep for a second and then set the new timeout value
+ sleep(1);
+
+ // New timeout is 3 seconds from THIS point.
+ time = duration_cast<microseconds>(seconds(3));
+ EXPECT_GE(timer.start(time), 0);
+
+ // Wait 3 seconds and see that timer is expired
+ int count = 0;
+ while (count < 3 && !timer.isExpired())
+ {
+ // Returns -0- on timeout
+ auto sleepTime = duration_cast<microseconds>(seconds(1));
+ if (!sd_event_run(events, sleepTime.count()))
+ {
+ count++;
+ }
+ }
+ EXPECT_EQ(true, timer.isExpired());
+ EXPECT_EQ(2, count);
+}
+
+/** @brief Makes sure that timer value is changed in between
+ * and turn off and make sure that timer does not expire
+ */
+TEST_F(TimerTest, updateTimerAndNeverExpire)
+{
+ using namespace std::chrono;
+
+ auto time = duration_cast<microseconds>(seconds(2));
+ EXPECT_GE(timer.start(time), 0);
+
+ // Now sleep for a second and then set the new timeout value
+ sleep(1);
+
+ // New timeout is 2 seconds from THIS point.
+ time = duration_cast<microseconds>(seconds(2));
+ EXPECT_GE(timer.start(time), 0);
+
+ // Now turn off the timer post a 1 second sleep
+ sleep(1);
+ EXPECT_GE(timer.stop(), 0);
+
+ // Wait 2 seconds and see that timer is expired
+ int count = 0;
+ while (count < 2)
+ {
+ // Returns -0- on timeout
+ auto sleepTime = duration_cast<microseconds>(seconds(1));
+ if (!sd_event_run(events, sleepTime.count()))
+ {
+ count++;
+ }
+ }
+ EXPECT_EQ(false, timer.isExpired());
+
+ // 2 because of one more count that happens prior to exiting
+ EXPECT_EQ(2, count);
+}
+
+/** @brief Makes sure that optional callback is called */
+TEST_F(TimerTestCallBack, optionalFuncCallBackDone)
+{
+ using namespace std::chrono;
+
+ auto time = duration_cast<microseconds>(seconds(2));
+ EXPECT_GE(timer->start(time), 0);
+
+ // Waiting 2 seconds is enough here since we have
+ // already spent some usec now
+ int count = 0;
+ while (count < 2 && !timer->isExpired())
+ {
+ // Returns -0- on timeout and positive number on dispatch
+ auto sleepTime = duration_cast<microseconds>(seconds(1));
+ if (!sd_event_run(events, sleepTime.count()))
+ {
+ count++;
+ }
+ }
+ EXPECT_EQ(true, timer->isExpired());
+ EXPECT_EQ(true, callBackDone);
+ EXPECT_EQ(1, count);
+}
+
+/** @brief Makes sure that timer is not expired
+ */
+TEST_F(TimerTestCallBack, timerNotExpiredAfter2SecondsNoOptionalCallBack)
+{
+ using namespace std::chrono;
+
+ auto time = duration_cast<microseconds>(seconds(2));
+ EXPECT_GE(timer->start(time), 0);
+
+ // Now turn off the timer post a 1 second sleep
+ sleep(1);
+ EXPECT_GE(timer->stop(), 0);
+
+ // Wait 2 seconds and see that timer is not expired
+ int count = 0;
+ while (count < 2)
+ {
+ // Returns -0- on timeout
+ auto sleepTime = duration_cast<microseconds>(seconds(1));
+ if (!sd_event_run(events, sleepTime.count()))
+ {
+ count++;
+ }
+ }
+ EXPECT_EQ(false, timer->isExpired());
+ EXPECT_EQ(false, callBackDone);
+
+ // 2 because of one more count that happens prior to exiting
+ EXPECT_EQ(2, count);
+}