xref: /openbmc/sdbusplus/test/timer.cpp (revision 2bf0bb29cf5c44da8fc94cee8ef87e23def03dba)
1  #include <sdbusplus/timer.hpp>
2  
3  #include <chrono>
4  #include <iostream>
5  
6  #include <gtest/gtest.h>
7  
8  using sdbusplus::Timer;
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
TimerTest()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
~TimerTest()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  
callBack()58      void callBack()
59      {
60          callBackDone = true;
61      }
62  
63      // Gets called as part of each TEST_F construction
TimerTestCallBack()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
~TimerTestCallBack()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   */
TEST_F(TimerTest,timerExpiresAfter2seconds)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   */
TEST_F(TimerTest,timerNotExpiredAfter2Seconds)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   */
TEST_F(TimerTest,updateTimerAndExpectExpire)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   */
TEST_F(TimerTest,updateTimerAndNeverExpire)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 */
TEST_F(TimerTestCallBack,optionalFuncCallBackDone)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   */
TEST_F(TimerTestCallBack,timerNotExpiredAfter2SecondsNoOptionalCallBack)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