xref: /openbmc/sdbusplus/test/timer.cpp (revision 2bf0bb29)
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