blob: 862196742a5d444ba6681663d7ca4e6630963c23 [file] [log] [blame]
#include <sdbusplus/timer.hpp>
#include <chrono>
#include <iostream>
#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);
}