blob: 48152b0bbd86182a54eca05450a07fbded3dffa0 [file] [log] [blame]
Patrick Williams127b8ab2020-05-21 15:24:19 -05001#include <sdbusplus/timer.hpp>
2
Vernon Mauery7efcdae2018-09-06 06:34:39 -07003#include <chrono>
4#include <iostream>
Vernon Mauery7efcdae2018-09-06 06:34:39 -07005
6#include <gtest/gtest.h>
7
8using namespace phosphor;
9
10class TimerTest : public ::testing::Test
11{
12 public:
13 // systemd event handler
Patrick Williams4dcf7552020-09-18 08:27:16 -050014 sd_event* events = nullptr;
Vernon Mauery7efcdae2018-09-06 06:34:39 -070015
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()
35 {
36 events = sd_event_unref(events);
37 }
38};
39
40class 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()
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 */
86TEST_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 */
111TEST_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 */
142TEST_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 */
174TEST_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 */
210TEST_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 */
236TEST_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}