1 #include <sdbusplus/timer.hpp> 2 3 #include <chrono> 4 #include <iostream> 5 6 #include <gtest/gtest.h> 7 8 using namespace phosphor; 9 10 class TimerTest : public ::testing::Test 11 { 12 public: 13 // systemd event handler 14 sd_event* events = nullptr; 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 34 ~TimerTest() override 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 77 ~TimerTestCallBack() override 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 } 264