| Patrick Williams | 127b8ab | 2020-05-21 15:24:19 -0500 | [diff] [blame] | 1 | #include <sdbusplus/timer.hpp> | 
 | 2 |  | 
| Vernon Mauery | 7efcdae | 2018-09-06 06:34:39 -0700 | [diff] [blame] | 3 | #include <chrono> | 
 | 4 | #include <iostream> | 
| Vernon Mauery | 7efcdae | 2018-09-06 06:34:39 -0700 | [diff] [blame] | 5 |  | 
 | 6 | #include <gtest/gtest.h> | 
 | 7 |  | 
| Patrick Williams | 2bf0bb2 | 2023-12-05 12:24:34 -0600 | [diff] [blame] | 8 | using sdbusplus::Timer; | 
| Vernon Mauery | 7efcdae | 2018-09-06 06:34:39 -0700 | [diff] [blame] | 9 |  | 
 | 10 | class TimerTest : public ::testing::Test | 
 | 11 | { | 
 | 12 |   public: | 
 | 13 |     // systemd event handler | 
| Patrick Williams | 4dcf755 | 2020-09-18 08:27:16 -0500 | [diff] [blame] | 14 |     sd_event* events = nullptr; | 
| Vernon Mauery | 7efcdae | 2018-09-06 06:34:39 -0700 | [diff] [blame] | 15 |  | 
 | 16 |     // Need this so that events can be initialized. | 
 | 17 |     int rc; | 
 | 18 |  | 
 | 19 |     // Source of event | 
 | 20 |     sd_event_source* eventSource = nullptr; | 
 | 21 |  | 
 | 22 |     // Add a Timer Object | 
 | 23 |     Timer timer; | 
 | 24 |  | 
 | 25 |     // Gets called as part of each TEST_F construction | 
 | 26 |     TimerTest() : rc(sd_event_default(&events)), timer(events) | 
 | 27 |     { | 
 | 28 |         // Check for successful creation of | 
 | 29 |         // event handler and timer object. | 
 | 30 |         EXPECT_GE(rc, 0); | 
 | 31 |     } | 
 | 32 |  | 
 | 33 |     // Gets called as part of each TEST_F destruction | 
| Ed Tanous | 9688ed6 | 2023-01-06 13:17:25 -0800 | [diff] [blame] | 34 |     ~TimerTest() override | 
| Vernon Mauery | 7efcdae | 2018-09-06 06:34:39 -0700 | [diff] [blame] | 35 |     { | 
 | 36 |         events = sd_event_unref(events); | 
 | 37 |     } | 
 | 38 | }; | 
 | 39 |  | 
 | 40 | class TimerTestCallBack : public ::testing::Test | 
 | 41 | { | 
 | 42 |   public: | 
 | 43 |     // systemd event handler | 
 | 44 |     sd_event* events; | 
 | 45 |  | 
 | 46 |     // Need this so that events can be initialized. | 
 | 47 |     int rc; | 
 | 48 |  | 
 | 49 |     // Source of event | 
 | 50 |     sd_event_source* eventSource = nullptr; | 
 | 51 |  | 
 | 52 |     // Add a Timer Object | 
 | 53 |     std::unique_ptr<Timer> timer = nullptr; | 
 | 54 |  | 
 | 55 |     // Indicates optional call back fun was called | 
 | 56 |     bool callBackDone = false; | 
 | 57 |  | 
 | 58 |     void callBack() | 
 | 59 |     { | 
 | 60 |         callBackDone = true; | 
 | 61 |     } | 
 | 62 |  | 
 | 63 |     // Gets called as part of each TEST_F construction | 
 | 64 |     TimerTestCallBack() : rc(sd_event_default(&events)) | 
 | 65 |  | 
 | 66 |     { | 
 | 67 |         // Check for successful creation of | 
 | 68 |         // event handler and timer object. | 
 | 69 |         EXPECT_GE(rc, 0); | 
 | 70 |  | 
 | 71 |         std::function<void()> func( | 
 | 72 |             std::bind(&TimerTestCallBack::callBack, this)); | 
 | 73 |         timer = std::make_unique<Timer>(events, func); | 
 | 74 |     } | 
 | 75 |  | 
 | 76 |     // Gets called as part of each TEST_F destruction | 
| Ed Tanous | 9688ed6 | 2023-01-06 13:17:25 -0800 | [diff] [blame] | 77 |     ~TimerTestCallBack() override | 
| Vernon Mauery | 7efcdae | 2018-09-06 06:34:39 -0700 | [diff] [blame] | 78 |     { | 
 | 79 |         events = sd_event_unref(events); | 
 | 80 |     } | 
 | 81 | }; | 
 | 82 |  | 
 | 83 | /** @brief Makes sure that timer is expired and the | 
 | 84 |  *  callback handler gets invoked post 2 seconds | 
 | 85 |  */ | 
 | 86 | TEST_F(TimerTest, timerExpiresAfter2seconds) | 
 | 87 | { | 
 | 88 |     using namespace std::chrono; | 
 | 89 |  | 
 | 90 |     auto time = duration_cast<microseconds>(seconds(2)); | 
 | 91 |     EXPECT_GE(timer.start(time), 0); | 
 | 92 |  | 
 | 93 |     // Waiting 2 seconds is enough here since we have | 
 | 94 |     // already spent some usec now | 
 | 95 |     int count = 0; | 
 | 96 |     while (count < 2 && !timer.isExpired()) | 
 | 97 |     { | 
 | 98 |         // Returns -0- on timeout and positive number on dispatch | 
 | 99 |         auto sleepTime = duration_cast<microseconds>(seconds(1)); | 
 | 100 |         if (!sd_event_run(events, sleepTime.count())) | 
 | 101 |         { | 
 | 102 |             count++; | 
 | 103 |         } | 
 | 104 |     } | 
 | 105 |     EXPECT_EQ(true, timer.isExpired()); | 
 | 106 |     EXPECT_EQ(1, count); | 
 | 107 | } | 
 | 108 |  | 
 | 109 | /** @brief Makes sure that timer is not expired | 
 | 110 |  */ | 
 | 111 | TEST_F(TimerTest, timerNotExpiredAfter2Seconds) | 
 | 112 | { | 
 | 113 |     using namespace std::chrono; | 
 | 114 |  | 
 | 115 |     auto time = duration_cast<microseconds>(seconds(2)); | 
 | 116 |     EXPECT_GE(timer.start(time), 0); | 
 | 117 |  | 
 | 118 |     // Now turn off the timer post a 1 second sleep | 
 | 119 |     sleep(1); | 
 | 120 |     EXPECT_GE(timer.stop(), 0); | 
 | 121 |  | 
 | 122 |     // Wait 2 seconds and see that timer is not expired | 
 | 123 |     int count = 0; | 
 | 124 |     while (count < 2) | 
 | 125 |     { | 
 | 126 |         // Returns -0- on timeout | 
 | 127 |         auto sleepTime = duration_cast<microseconds>(seconds(1)); | 
 | 128 |         if (!sd_event_run(events, sleepTime.count())) | 
 | 129 |         { | 
 | 130 |             count++; | 
 | 131 |         } | 
 | 132 |     } | 
 | 133 |     EXPECT_EQ(false, timer.isExpired()); | 
 | 134 |  | 
 | 135 |     // 2 because of one more count that happens prior to exiting | 
 | 136 |     EXPECT_EQ(2, count); | 
 | 137 | } | 
 | 138 |  | 
 | 139 | /** @brief Makes sure that timer value is changed in between | 
 | 140 |  *  and that the new timer expires | 
 | 141 |  */ | 
 | 142 | TEST_F(TimerTest, updateTimerAndExpectExpire) | 
 | 143 | { | 
 | 144 |     using namespace std::chrono; | 
 | 145 |  | 
 | 146 |     auto time = duration_cast<microseconds>(seconds(2)); | 
 | 147 |     EXPECT_GE(timer.start(time), 0); | 
 | 148 |  | 
 | 149 |     // Now sleep for a second and then set the new timeout value | 
 | 150 |     sleep(1); | 
 | 151 |  | 
 | 152 |     // New timeout is 3 seconds from THIS point. | 
 | 153 |     time = duration_cast<microseconds>(seconds(3)); | 
 | 154 |     EXPECT_GE(timer.start(time), 0); | 
 | 155 |  | 
 | 156 |     // Wait 3 seconds and see that timer is expired | 
 | 157 |     int count = 0; | 
 | 158 |     while (count < 3 && !timer.isExpired()) | 
 | 159 |     { | 
 | 160 |         // Returns -0- on timeout | 
 | 161 |         auto sleepTime = duration_cast<microseconds>(seconds(1)); | 
 | 162 |         if (!sd_event_run(events, sleepTime.count())) | 
 | 163 |         { | 
 | 164 |             count++; | 
 | 165 |         } | 
 | 166 |     } | 
 | 167 |     EXPECT_EQ(true, timer.isExpired()); | 
 | 168 |     EXPECT_EQ(2, count); | 
 | 169 | } | 
 | 170 |  | 
 | 171 | /** @brief Makes sure that timer value is changed in between | 
 | 172 |  *  and turn off and make sure that timer does not expire | 
 | 173 |  */ | 
 | 174 | TEST_F(TimerTest, updateTimerAndNeverExpire) | 
 | 175 | { | 
 | 176 |     using namespace std::chrono; | 
 | 177 |  | 
 | 178 |     auto time = duration_cast<microseconds>(seconds(2)); | 
 | 179 |     EXPECT_GE(timer.start(time), 0); | 
 | 180 |  | 
 | 181 |     // Now sleep for a second and then set the new timeout value | 
 | 182 |     sleep(1); | 
 | 183 |  | 
 | 184 |     // New timeout is 2 seconds from THIS point. | 
 | 185 |     time = duration_cast<microseconds>(seconds(2)); | 
 | 186 |     EXPECT_GE(timer.start(time), 0); | 
 | 187 |  | 
 | 188 |     // Now turn off the timer post a 1 second sleep | 
 | 189 |     sleep(1); | 
 | 190 |     EXPECT_GE(timer.stop(), 0); | 
 | 191 |  | 
 | 192 |     // Wait 2 seconds and see that timer is expired | 
 | 193 |     int count = 0; | 
 | 194 |     while (count < 2) | 
 | 195 |     { | 
 | 196 |         // Returns -0- on timeout | 
 | 197 |         auto sleepTime = duration_cast<microseconds>(seconds(1)); | 
 | 198 |         if (!sd_event_run(events, sleepTime.count())) | 
 | 199 |         { | 
 | 200 |             count++; | 
 | 201 |         } | 
 | 202 |     } | 
 | 203 |     EXPECT_EQ(false, timer.isExpired()); | 
 | 204 |  | 
 | 205 |     // 2 because of one more count that happens prior to exiting | 
 | 206 |     EXPECT_EQ(2, count); | 
 | 207 | } | 
 | 208 |  | 
 | 209 | /** @brief Makes sure that optional callback is called */ | 
 | 210 | TEST_F(TimerTestCallBack, optionalFuncCallBackDone) | 
 | 211 | { | 
 | 212 |     using namespace std::chrono; | 
 | 213 |  | 
 | 214 |     auto time = duration_cast<microseconds>(seconds(2)); | 
 | 215 |     EXPECT_GE(timer->start(time), 0); | 
 | 216 |  | 
 | 217 |     // Waiting 2 seconds is enough here since we have | 
 | 218 |     // already spent some usec now | 
 | 219 |     int count = 0; | 
 | 220 |     while (count < 2 && !timer->isExpired()) | 
 | 221 |     { | 
 | 222 |         // Returns -0- on timeout and positive number on dispatch | 
 | 223 |         auto sleepTime = duration_cast<microseconds>(seconds(1)); | 
 | 224 |         if (!sd_event_run(events, sleepTime.count())) | 
 | 225 |         { | 
 | 226 |             count++; | 
 | 227 |         } | 
 | 228 |     } | 
 | 229 |     EXPECT_EQ(true, timer->isExpired()); | 
 | 230 |     EXPECT_EQ(true, callBackDone); | 
 | 231 |     EXPECT_EQ(1, count); | 
 | 232 | } | 
 | 233 |  | 
 | 234 | /** @brief Makes sure that timer is not expired | 
 | 235 |  */ | 
 | 236 | TEST_F(TimerTestCallBack, timerNotExpiredAfter2SecondsNoOptionalCallBack) | 
 | 237 | { | 
 | 238 |     using namespace std::chrono; | 
 | 239 |  | 
 | 240 |     auto time = duration_cast<microseconds>(seconds(2)); | 
 | 241 |     EXPECT_GE(timer->start(time), 0); | 
 | 242 |  | 
 | 243 |     // Now turn off the timer post a 1 second sleep | 
 | 244 |     sleep(1); | 
 | 245 |     EXPECT_GE(timer->stop(), 0); | 
 | 246 |  | 
 | 247 |     // Wait 2 seconds and see that timer is not expired | 
 | 248 |     int count = 0; | 
 | 249 |     while (count < 2) | 
 | 250 |     { | 
 | 251 |         // Returns -0- on timeout | 
 | 252 |         auto sleepTime = duration_cast<microseconds>(seconds(1)); | 
 | 253 |         if (!sd_event_run(events, sleepTime.count())) | 
 | 254 |         { | 
 | 255 |             count++; | 
 | 256 |         } | 
 | 257 |     } | 
 | 258 |     EXPECT_EQ(false, timer->isExpired()); | 
 | 259 |     EXPECT_EQ(false, callBackDone); | 
 | 260 |  | 
 | 261 |     // 2 because of one more count that happens prior to exiting | 
 | 262 |     EXPECT_EQ(2, count); | 
 | 263 | } |