blob: f27fc6ec8808f3ebc14c1279e8b9ecab82e622d9 [file] [log] [blame]
Vernon Mauery7efcdae2018-09-06 06:34:39 -07001#include <chrono>
2#include <iostream>
3#include <sdbusplus/timer.hpp>
4
5#include <gtest/gtest.h>
6
7using namespace phosphor;
8
9class 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
39class 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 */
85TEST_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 */
110TEST_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 */
141TEST_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 */
173TEST_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 */
209TEST_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 */
235TEST_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}