#include #include #include #include "timer.hpp" using namespace phosphor::ipmi; 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 = 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 func(std::bind( &TimerTestCallBack::callBack, this)); timer = std::make_unique(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(seconds(2)); EXPECT_GE(timer.startTimer(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(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(seconds(2)); EXPECT_GE(timer.startTimer(time), 0); // Now turn off the timer post a 1 second sleep sleep(1); EXPECT_GE(timer.setTimer(SD_EVENT_OFF), 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(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(seconds(2)); EXPECT_GE(timer.startTimer(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(seconds(3)); EXPECT_GE(timer.startTimer(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(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(seconds(2)); EXPECT_GE(timer.startTimer(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(seconds(2)); EXPECT_GE(timer.startTimer(time), 0); // Now turn off the timer post a 1 second sleep sleep(1); EXPECT_GE(timer.setTimer(SD_EVENT_OFF), 0); // Wait 2 seconds and see that timer is expired int count = 0; while(count < 2) { // Returns -0- on timeout auto sleepTime = duration_cast(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(seconds(2)); EXPECT_GE(timer->startTimer(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(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(seconds(2)); EXPECT_GE(timer->startTimer(time), 0); // Now turn off the timer post a 1 second sleep sleep(1); EXPECT_GE(timer->setTimer(SD_EVENT_OFF), 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(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); }