1127b8abeSPatrick Williams #include <sdbusplus/timer.hpp>
2127b8abeSPatrick Williams
37efcdaebSVernon Mauery #include <chrono>
47efcdaebSVernon Mauery #include <iostream>
57efcdaebSVernon Mauery
67efcdaebSVernon Mauery #include <gtest/gtest.h>
77efcdaebSVernon Mauery
8*2bf0bb29SPatrick Williams using sdbusplus::Timer;
97efcdaebSVernon Mauery
107efcdaebSVernon Mauery class TimerTest : public ::testing::Test
117efcdaebSVernon Mauery {
127efcdaebSVernon Mauery public:
137efcdaebSVernon Mauery // systemd event handler
144dcf755bSPatrick Williams sd_event* events = nullptr;
157efcdaebSVernon Mauery
167efcdaebSVernon Mauery // Need this so that events can be initialized.
177efcdaebSVernon Mauery int rc;
187efcdaebSVernon Mauery
197efcdaebSVernon Mauery // Source of event
207efcdaebSVernon Mauery sd_event_source* eventSource = nullptr;
217efcdaebSVernon Mauery
227efcdaebSVernon Mauery // Add a Timer Object
237efcdaebSVernon Mauery Timer timer;
247efcdaebSVernon Mauery
257efcdaebSVernon Mauery // Gets called as part of each TEST_F construction
TimerTest()267efcdaebSVernon Mauery TimerTest() : rc(sd_event_default(&events)), timer(events)
277efcdaebSVernon Mauery {
287efcdaebSVernon Mauery // Check for successful creation of
297efcdaebSVernon Mauery // event handler and timer object.
307efcdaebSVernon Mauery EXPECT_GE(rc, 0);
317efcdaebSVernon Mauery }
327efcdaebSVernon Mauery
337efcdaebSVernon Mauery // Gets called as part of each TEST_F destruction
~TimerTest()349688ed68SEd Tanous ~TimerTest() override
357efcdaebSVernon Mauery {
367efcdaebSVernon Mauery events = sd_event_unref(events);
377efcdaebSVernon Mauery }
387efcdaebSVernon Mauery };
397efcdaebSVernon Mauery
407efcdaebSVernon Mauery class TimerTestCallBack : public ::testing::Test
417efcdaebSVernon Mauery {
427efcdaebSVernon Mauery public:
437efcdaebSVernon Mauery // systemd event handler
447efcdaebSVernon Mauery sd_event* events;
457efcdaebSVernon Mauery
467efcdaebSVernon Mauery // Need this so that events can be initialized.
477efcdaebSVernon Mauery int rc;
487efcdaebSVernon Mauery
497efcdaebSVernon Mauery // Source of event
507efcdaebSVernon Mauery sd_event_source* eventSource = nullptr;
517efcdaebSVernon Mauery
527efcdaebSVernon Mauery // Add a Timer Object
537efcdaebSVernon Mauery std::unique_ptr<Timer> timer = nullptr;
547efcdaebSVernon Mauery
557efcdaebSVernon Mauery // Indicates optional call back fun was called
567efcdaebSVernon Mauery bool callBackDone = false;
577efcdaebSVernon Mauery
callBack()587efcdaebSVernon Mauery void callBack()
597efcdaebSVernon Mauery {
607efcdaebSVernon Mauery callBackDone = true;
617efcdaebSVernon Mauery }
627efcdaebSVernon Mauery
637efcdaebSVernon Mauery // Gets called as part of each TEST_F construction
TimerTestCallBack()647efcdaebSVernon Mauery TimerTestCallBack() : rc(sd_event_default(&events))
657efcdaebSVernon Mauery
667efcdaebSVernon Mauery {
677efcdaebSVernon Mauery // Check for successful creation of
687efcdaebSVernon Mauery // event handler and timer object.
697efcdaebSVernon Mauery EXPECT_GE(rc, 0);
707efcdaebSVernon Mauery
717efcdaebSVernon Mauery std::function<void()> func(
727efcdaebSVernon Mauery std::bind(&TimerTestCallBack::callBack, this));
737efcdaebSVernon Mauery timer = std::make_unique<Timer>(events, func);
747efcdaebSVernon Mauery }
757efcdaebSVernon Mauery
767efcdaebSVernon Mauery // Gets called as part of each TEST_F destruction
~TimerTestCallBack()779688ed68SEd Tanous ~TimerTestCallBack() override
787efcdaebSVernon Mauery {
797efcdaebSVernon Mauery events = sd_event_unref(events);
807efcdaebSVernon Mauery }
817efcdaebSVernon Mauery };
827efcdaebSVernon Mauery
837efcdaebSVernon Mauery /** @brief Makes sure that timer is expired and the
847efcdaebSVernon Mauery * callback handler gets invoked post 2 seconds
857efcdaebSVernon Mauery */
TEST_F(TimerTest,timerExpiresAfter2seconds)867efcdaebSVernon Mauery TEST_F(TimerTest, timerExpiresAfter2seconds)
877efcdaebSVernon Mauery {
887efcdaebSVernon Mauery using namespace std::chrono;
897efcdaebSVernon Mauery
907efcdaebSVernon Mauery auto time = duration_cast<microseconds>(seconds(2));
917efcdaebSVernon Mauery EXPECT_GE(timer.start(time), 0);
927efcdaebSVernon Mauery
937efcdaebSVernon Mauery // Waiting 2 seconds is enough here since we have
947efcdaebSVernon Mauery // already spent some usec now
957efcdaebSVernon Mauery int count = 0;
967efcdaebSVernon Mauery while (count < 2 && !timer.isExpired())
977efcdaebSVernon Mauery {
987efcdaebSVernon Mauery // Returns -0- on timeout and positive number on dispatch
997efcdaebSVernon Mauery auto sleepTime = duration_cast<microseconds>(seconds(1));
1007efcdaebSVernon Mauery if (!sd_event_run(events, sleepTime.count()))
1017efcdaebSVernon Mauery {
1027efcdaebSVernon Mauery count++;
1037efcdaebSVernon Mauery }
1047efcdaebSVernon Mauery }
1057efcdaebSVernon Mauery EXPECT_EQ(true, timer.isExpired());
1067efcdaebSVernon Mauery EXPECT_EQ(1, count);
1077efcdaebSVernon Mauery }
1087efcdaebSVernon Mauery
1097efcdaebSVernon Mauery /** @brief Makes sure that timer is not expired
1107efcdaebSVernon Mauery */
TEST_F(TimerTest,timerNotExpiredAfter2Seconds)1117efcdaebSVernon Mauery TEST_F(TimerTest, timerNotExpiredAfter2Seconds)
1127efcdaebSVernon Mauery {
1137efcdaebSVernon Mauery using namespace std::chrono;
1147efcdaebSVernon Mauery
1157efcdaebSVernon Mauery auto time = duration_cast<microseconds>(seconds(2));
1167efcdaebSVernon Mauery EXPECT_GE(timer.start(time), 0);
1177efcdaebSVernon Mauery
1187efcdaebSVernon Mauery // Now turn off the timer post a 1 second sleep
1197efcdaebSVernon Mauery sleep(1);
1207efcdaebSVernon Mauery EXPECT_GE(timer.stop(), 0);
1217efcdaebSVernon Mauery
1227efcdaebSVernon Mauery // Wait 2 seconds and see that timer is not expired
1237efcdaebSVernon Mauery int count = 0;
1247efcdaebSVernon Mauery while (count < 2)
1257efcdaebSVernon Mauery {
1267efcdaebSVernon Mauery // Returns -0- on timeout
1277efcdaebSVernon Mauery auto sleepTime = duration_cast<microseconds>(seconds(1));
1287efcdaebSVernon Mauery if (!sd_event_run(events, sleepTime.count()))
1297efcdaebSVernon Mauery {
1307efcdaebSVernon Mauery count++;
1317efcdaebSVernon Mauery }
1327efcdaebSVernon Mauery }
1337efcdaebSVernon Mauery EXPECT_EQ(false, timer.isExpired());
1347efcdaebSVernon Mauery
1357efcdaebSVernon Mauery // 2 because of one more count that happens prior to exiting
1367efcdaebSVernon Mauery EXPECT_EQ(2, count);
1377efcdaebSVernon Mauery }
1387efcdaebSVernon Mauery
1397efcdaebSVernon Mauery /** @brief Makes sure that timer value is changed in between
1407efcdaebSVernon Mauery * and that the new timer expires
1417efcdaebSVernon Mauery */
TEST_F(TimerTest,updateTimerAndExpectExpire)1427efcdaebSVernon Mauery TEST_F(TimerTest, updateTimerAndExpectExpire)
1437efcdaebSVernon Mauery {
1447efcdaebSVernon Mauery using namespace std::chrono;
1457efcdaebSVernon Mauery
1467efcdaebSVernon Mauery auto time = duration_cast<microseconds>(seconds(2));
1477efcdaebSVernon Mauery EXPECT_GE(timer.start(time), 0);
1487efcdaebSVernon Mauery
1497efcdaebSVernon Mauery // Now sleep for a second and then set the new timeout value
1507efcdaebSVernon Mauery sleep(1);
1517efcdaebSVernon Mauery
1527efcdaebSVernon Mauery // New timeout is 3 seconds from THIS point.
1537efcdaebSVernon Mauery time = duration_cast<microseconds>(seconds(3));
1547efcdaebSVernon Mauery EXPECT_GE(timer.start(time), 0);
1557efcdaebSVernon Mauery
1567efcdaebSVernon Mauery // Wait 3 seconds and see that timer is expired
1577efcdaebSVernon Mauery int count = 0;
1587efcdaebSVernon Mauery while (count < 3 && !timer.isExpired())
1597efcdaebSVernon Mauery {
1607efcdaebSVernon Mauery // Returns -0- on timeout
1617efcdaebSVernon Mauery auto sleepTime = duration_cast<microseconds>(seconds(1));
1627efcdaebSVernon Mauery if (!sd_event_run(events, sleepTime.count()))
1637efcdaebSVernon Mauery {
1647efcdaebSVernon Mauery count++;
1657efcdaebSVernon Mauery }
1667efcdaebSVernon Mauery }
1677efcdaebSVernon Mauery EXPECT_EQ(true, timer.isExpired());
1687efcdaebSVernon Mauery EXPECT_EQ(2, count);
1697efcdaebSVernon Mauery }
1707efcdaebSVernon Mauery
1717efcdaebSVernon Mauery /** @brief Makes sure that timer value is changed in between
1727efcdaebSVernon Mauery * and turn off and make sure that timer does not expire
1737efcdaebSVernon Mauery */
TEST_F(TimerTest,updateTimerAndNeverExpire)1747efcdaebSVernon Mauery TEST_F(TimerTest, updateTimerAndNeverExpire)
1757efcdaebSVernon Mauery {
1767efcdaebSVernon Mauery using namespace std::chrono;
1777efcdaebSVernon Mauery
1787efcdaebSVernon Mauery auto time = duration_cast<microseconds>(seconds(2));
1797efcdaebSVernon Mauery EXPECT_GE(timer.start(time), 0);
1807efcdaebSVernon Mauery
1817efcdaebSVernon Mauery // Now sleep for a second and then set the new timeout value
1827efcdaebSVernon Mauery sleep(1);
1837efcdaebSVernon Mauery
1847efcdaebSVernon Mauery // New timeout is 2 seconds from THIS point.
1857efcdaebSVernon Mauery time = duration_cast<microseconds>(seconds(2));
1867efcdaebSVernon Mauery EXPECT_GE(timer.start(time), 0);
1877efcdaebSVernon Mauery
1887efcdaebSVernon Mauery // Now turn off the timer post a 1 second sleep
1897efcdaebSVernon Mauery sleep(1);
1907efcdaebSVernon Mauery EXPECT_GE(timer.stop(), 0);
1917efcdaebSVernon Mauery
1927efcdaebSVernon Mauery // Wait 2 seconds and see that timer is expired
1937efcdaebSVernon Mauery int count = 0;
1947efcdaebSVernon Mauery while (count < 2)
1957efcdaebSVernon Mauery {
1967efcdaebSVernon Mauery // Returns -0- on timeout
1977efcdaebSVernon Mauery auto sleepTime = duration_cast<microseconds>(seconds(1));
1987efcdaebSVernon Mauery if (!sd_event_run(events, sleepTime.count()))
1997efcdaebSVernon Mauery {
2007efcdaebSVernon Mauery count++;
2017efcdaebSVernon Mauery }
2027efcdaebSVernon Mauery }
2037efcdaebSVernon Mauery EXPECT_EQ(false, timer.isExpired());
2047efcdaebSVernon Mauery
2057efcdaebSVernon Mauery // 2 because of one more count that happens prior to exiting
2067efcdaebSVernon Mauery EXPECT_EQ(2, count);
2077efcdaebSVernon Mauery }
2087efcdaebSVernon Mauery
2097efcdaebSVernon Mauery /** @brief Makes sure that optional callback is called */
TEST_F(TimerTestCallBack,optionalFuncCallBackDone)2107efcdaebSVernon Mauery TEST_F(TimerTestCallBack, optionalFuncCallBackDone)
2117efcdaebSVernon Mauery {
2127efcdaebSVernon Mauery using namespace std::chrono;
2137efcdaebSVernon Mauery
2147efcdaebSVernon Mauery auto time = duration_cast<microseconds>(seconds(2));
2157efcdaebSVernon Mauery EXPECT_GE(timer->start(time), 0);
2167efcdaebSVernon Mauery
2177efcdaebSVernon Mauery // Waiting 2 seconds is enough here since we have
2187efcdaebSVernon Mauery // already spent some usec now
2197efcdaebSVernon Mauery int count = 0;
2207efcdaebSVernon Mauery while (count < 2 && !timer->isExpired())
2217efcdaebSVernon Mauery {
2227efcdaebSVernon Mauery // Returns -0- on timeout and positive number on dispatch
2237efcdaebSVernon Mauery auto sleepTime = duration_cast<microseconds>(seconds(1));
2247efcdaebSVernon Mauery if (!sd_event_run(events, sleepTime.count()))
2257efcdaebSVernon Mauery {
2267efcdaebSVernon Mauery count++;
2277efcdaebSVernon Mauery }
2287efcdaebSVernon Mauery }
2297efcdaebSVernon Mauery EXPECT_EQ(true, timer->isExpired());
2307efcdaebSVernon Mauery EXPECT_EQ(true, callBackDone);
2317efcdaebSVernon Mauery EXPECT_EQ(1, count);
2327efcdaebSVernon Mauery }
2337efcdaebSVernon Mauery
2347efcdaebSVernon Mauery /** @brief Makes sure that timer is not expired
2357efcdaebSVernon Mauery */
TEST_F(TimerTestCallBack,timerNotExpiredAfter2SecondsNoOptionalCallBack)2367efcdaebSVernon Mauery TEST_F(TimerTestCallBack, timerNotExpiredAfter2SecondsNoOptionalCallBack)
2377efcdaebSVernon Mauery {
2387efcdaebSVernon Mauery using namespace std::chrono;
2397efcdaebSVernon Mauery
2407efcdaebSVernon Mauery auto time = duration_cast<microseconds>(seconds(2));
2417efcdaebSVernon Mauery EXPECT_GE(timer->start(time), 0);
2427efcdaebSVernon Mauery
2437efcdaebSVernon Mauery // Now turn off the timer post a 1 second sleep
2447efcdaebSVernon Mauery sleep(1);
2457efcdaebSVernon Mauery EXPECT_GE(timer->stop(), 0);
2467efcdaebSVernon Mauery
2477efcdaebSVernon Mauery // Wait 2 seconds and see that timer is not expired
2487efcdaebSVernon Mauery int count = 0;
2497efcdaebSVernon Mauery while (count < 2)
2507efcdaebSVernon Mauery {
2517efcdaebSVernon Mauery // Returns -0- on timeout
2527efcdaebSVernon Mauery auto sleepTime = duration_cast<microseconds>(seconds(1));
2537efcdaebSVernon Mauery if (!sd_event_run(events, sleepTime.count()))
2547efcdaebSVernon Mauery {
2557efcdaebSVernon Mauery count++;
2567efcdaebSVernon Mauery }
2577efcdaebSVernon Mauery }
2587efcdaebSVernon Mauery EXPECT_EQ(false, timer->isExpired());
2597efcdaebSVernon Mauery EXPECT_EQ(false, callBackDone);
2607efcdaebSVernon Mauery
2617efcdaebSVernon Mauery // 2 because of one more count that happens prior to exiting
2627efcdaebSVernon Mauery EXPECT_EQ(2, count);
2637efcdaebSVernon Mauery }
264