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