xref: /openbmc/sdeventplus/test/utility/timer.cpp (revision a8c11e3ca342b090aec615c832b85686bd4655f6)
1*a8c11e3cSPatrick Williams #include <systemd/sd-event.h>
2*a8c11e3cSPatrick Williams 
381282e1aSWilliam A. Kennington III #include <sdeventplus/clock.hpp>
481282e1aSWilliam A. Kennington III #include <sdeventplus/event.hpp>
581282e1aSWilliam A. Kennington III #include <sdeventplus/test/sdevent.hpp>
681282e1aSWilliam A. Kennington III #include <sdeventplus/utility/timer.hpp>
7*a8c11e3cSPatrick Williams 
8*a8c11e3cSPatrick Williams #include <chrono>
9*a8c11e3cSPatrick Williams #include <memory>
10*a8c11e3cSPatrick Williams #include <optional>
1181282e1aSWilliam A. Kennington III #include <stdexcept>
12*a8c11e3cSPatrick Williams 
13*a8c11e3cSPatrick Williams #include <gmock/gmock.h>
14*a8c11e3cSPatrick Williams #include <gtest/gtest.h>
1581282e1aSWilliam A. Kennington III 
1681282e1aSWilliam A. Kennington III namespace sdeventplus
1781282e1aSWilliam A. Kennington III {
1881282e1aSWilliam A. Kennington III namespace utility
1981282e1aSWilliam A. Kennington III {
2081282e1aSWilliam A. Kennington III namespace
2181282e1aSWilliam A. Kennington III {
2281282e1aSWilliam A. Kennington III 
2381282e1aSWilliam A. Kennington III constexpr ClockId testClock = ClockId::Monotonic;
2481282e1aSWilliam A. Kennington III 
2581282e1aSWilliam A. Kennington III using std::chrono::microseconds;
2681282e1aSWilliam A. Kennington III using std::chrono::milliseconds;
2781282e1aSWilliam A. Kennington III using testing::DoAll;
2881282e1aSWilliam A. Kennington III using testing::Return;
295320b1f5SWilliam A. Kennington III using testing::ReturnPointee;
3081282e1aSWilliam A. Kennington III using testing::SaveArg;
3181282e1aSWilliam A. Kennington III using testing::SetArgPointee;
3281282e1aSWilliam A. Kennington III using TestTimer = Timer<testClock>;
3381282e1aSWilliam A. Kennington III 
3481282e1aSWilliam A. Kennington III ssize_t event_ref_times = 0;
3581282e1aSWilliam A. Kennington III 
ACTION(EventRef)3681282e1aSWilliam A. Kennington III ACTION(EventRef)
3781282e1aSWilliam A. Kennington III {
3881282e1aSWilliam A. Kennington III     event_ref_times++;
3981282e1aSWilliam A. Kennington III }
4081282e1aSWilliam A. Kennington III 
ACTION(EventUnref)4181282e1aSWilliam A. Kennington III ACTION(EventUnref)
4281282e1aSWilliam A. Kennington III {
4381282e1aSWilliam A. Kennington III     ASSERT_LT(0, event_ref_times);
4481282e1aSWilliam A. Kennington III     event_ref_times--;
4581282e1aSWilliam A. Kennington III }
4681282e1aSWilliam A. Kennington III 
4781282e1aSWilliam A. Kennington III class TimerTest : public testing::Test
4881282e1aSWilliam A. Kennington III {
4981282e1aSWilliam A. Kennington III   protected:
5081282e1aSWilliam A. Kennington III     testing::StrictMock<test::SdEventMock> mock;
5181282e1aSWilliam A. Kennington III     sd_event* const expected_event = reinterpret_cast<sd_event*>(1234);
5281282e1aSWilliam A. Kennington III     sd_event_source* const expected_source =
5381282e1aSWilliam A. Kennington III         reinterpret_cast<sd_event_source*>(2345);
54a5f8596aSWilliam A. Kennington III     sd_event_source* const expected_source2 =
55a5f8596aSWilliam A. Kennington III         reinterpret_cast<sd_event_source*>(3456);
5681282e1aSWilliam A. Kennington III     const milliseconds interval{134};
5781282e1aSWilliam A. Kennington III     const milliseconds starting_time{10};
58a5f8596aSWilliam A. Kennington III     const milliseconds starting_time2{30};
5981282e1aSWilliam A. Kennington III     sd_event_time_handler_t handler = nullptr;
6081282e1aSWilliam A. Kennington III     void* handler_userdata;
615320b1f5SWilliam A. Kennington III     sd_event_destroy_t handler_destroy;
62ba04ffb5SWilliam A. Kennington III     std::unique_ptr<Event> event;
6381282e1aSWilliam A. Kennington III     std::unique_ptr<TestTimer> timer;
6481282e1aSWilliam A. Kennington III     std::function<void()> callback;
6581282e1aSWilliam A. Kennington III 
expectNow(microseconds ret)6681282e1aSWilliam A. Kennington III     void expectNow(microseconds ret)
6781282e1aSWilliam A. Kennington III     {
6881282e1aSWilliam A. Kennington III         EXPECT_CALL(mock,
6981282e1aSWilliam A. Kennington III                     sd_event_now(expected_event,
7081282e1aSWilliam A. Kennington III                                  static_cast<clockid_t>(testClock), testing::_))
7181282e1aSWilliam A. Kennington III             .WillOnce(DoAll(SetArgPointee<2>(ret.count()), Return(0)));
7281282e1aSWilliam A. Kennington III     }
7381282e1aSWilliam A. Kennington III 
expectSetTime(microseconds time)7481282e1aSWilliam A. Kennington III     void expectSetTime(microseconds time)
7581282e1aSWilliam A. Kennington III     {
7681282e1aSWilliam A. Kennington III         EXPECT_CALL(mock,
7781282e1aSWilliam A. Kennington III                     sd_event_source_set_time(expected_source, time.count()))
7881282e1aSWilliam A. Kennington III             .WillOnce(Return(0));
7981282e1aSWilliam A. Kennington III     }
8081282e1aSWilliam A. Kennington III 
expectSetEnabled(source::Enabled enabled)8181282e1aSWilliam A. Kennington III     void expectSetEnabled(source::Enabled enabled)
8281282e1aSWilliam A. Kennington III     {
8381282e1aSWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_source_set_enabled(
8481282e1aSWilliam A. Kennington III                               expected_source, static_cast<int>(enabled)))
8581282e1aSWilliam A. Kennington III             .WillOnce(Return(0));
8681282e1aSWilliam A. Kennington III     }
8781282e1aSWilliam A. Kennington III 
expectGetEnabled(source::Enabled enabled)8881282e1aSWilliam A. Kennington III     void expectGetEnabled(source::Enabled enabled)
8981282e1aSWilliam A. Kennington III     {
9081282e1aSWilliam A. Kennington III         EXPECT_CALL(mock,
9181282e1aSWilliam A. Kennington III                     sd_event_source_get_enabled(expected_source, testing::_))
9281282e1aSWilliam A. Kennington III             .WillOnce(
9381282e1aSWilliam A. Kennington III                 DoAll(SetArgPointee<1>(static_cast<int>(enabled)), Return(0)));
9481282e1aSWilliam A. Kennington III     }
9581282e1aSWilliam A. Kennington III 
resetTimer()96ba04ffb5SWilliam A. Kennington III     void resetTimer()
97ba04ffb5SWilliam A. Kennington III     {
98ba04ffb5SWilliam A. Kennington III         if (timer)
99ba04ffb5SWilliam A. Kennington III         {
100ba04ffb5SWilliam A. Kennington III             timer.reset();
1015320b1f5SWilliam A. Kennington III             handler_destroy(handler_userdata);
102ba04ffb5SWilliam A. Kennington III         }
103ba04ffb5SWilliam A. Kennington III     }
104ba04ffb5SWilliam A. Kennington III 
expireTimer()105ba04ffb5SWilliam A. Kennington III     void expireTimer()
106ba04ffb5SWilliam A. Kennington III     {
107ba04ffb5SWilliam A. Kennington III         const milliseconds new_time(90);
108ba04ffb5SWilliam A. Kennington III         expectNow(new_time);
109ba04ffb5SWilliam A. Kennington III         expectSetTime(new_time + interval);
110ba04ffb5SWilliam A. Kennington III         EXPECT_EQ(0, handler(nullptr, 0, handler_userdata));
111ba04ffb5SWilliam A. Kennington III         EXPECT_TRUE(timer->hasExpired());
112ba04ffb5SWilliam A. Kennington III         EXPECT_EQ(interval, timer->getInterval());
113ba04ffb5SWilliam A. Kennington III     }
114ba04ffb5SWilliam A. Kennington III 
SetUp()11581282e1aSWilliam A. Kennington III     void SetUp()
11681282e1aSWilliam A. Kennington III     {
11781282e1aSWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_ref(expected_event))
11881282e1aSWilliam A. Kennington III             .WillRepeatedly(DoAll(EventRef(), Return(expected_event)));
11981282e1aSWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_unref(expected_event))
12081282e1aSWilliam A. Kennington III             .WillRepeatedly(DoAll(EventUnref(), Return(nullptr)));
121ba04ffb5SWilliam A. Kennington III         event = std::make_unique<Event>(expected_event, &mock);
122ba04ffb5SWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_source_unref(expected_source))
123ba04ffb5SWilliam A. Kennington III             .WillRepeatedly(Return(nullptr));
1245320b1f5SWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_source_set_destroy_callback(expected_source,
1255320b1f5SWilliam A. Kennington III                                                                testing::_))
1265320b1f5SWilliam A. Kennington III             .WillRepeatedly(DoAll(SaveArg<1>(&handler_destroy), Return(0)));
127ba04ffb5SWilliam A. Kennington III         EXPECT_CALL(mock,
128ba04ffb5SWilliam A. Kennington III                     sd_event_source_set_userdata(expected_source, testing::_))
129ba04ffb5SWilliam A. Kennington III             .WillRepeatedly(
130ba04ffb5SWilliam A. Kennington III                 DoAll(SaveArg<1>(&handler_userdata), Return(nullptr)));
1315320b1f5SWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_source_get_userdata(expected_source))
1325320b1f5SWilliam A. Kennington III             .WillRepeatedly(ReturnPointee(&handler_userdata));
13381282e1aSWilliam A. Kennington III 
134ba04ffb5SWilliam A. Kennington III         // Having a callback proxy allows us to update the test callback
135ba04ffb5SWilliam A. Kennington III         // dynamically, without changing it inside the timer
1364755818eSWilliam A. Kennington III         auto runCallback = [&](TestTimer&) {
13781282e1aSWilliam A. Kennington III             if (callback)
13881282e1aSWilliam A. Kennington III             {
13981282e1aSWilliam A. Kennington III                 callback();
14081282e1aSWilliam A. Kennington III             }
14181282e1aSWilliam A. Kennington III         };
14281282e1aSWilliam A. Kennington III         expectNow(starting_time);
14381282e1aSWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_add_time(
14481282e1aSWilliam A. Kennington III                               expected_event, testing::_,
14581282e1aSWilliam A. Kennington III                               static_cast<clockid_t>(testClock),
14681282e1aSWilliam A. Kennington III                               microseconds(starting_time + interval).count(),
14781282e1aSWilliam A. Kennington III                               1000, testing::_, nullptr))
14881282e1aSWilliam A. Kennington III             .WillOnce(DoAll(SetArgPointee<1>(expected_source),
14981282e1aSWilliam A. Kennington III                             SaveArg<5>(&handler), Return(0)));
15081282e1aSWilliam A. Kennington III         expectSetEnabled(source::Enabled::On);
151ba04ffb5SWilliam A. Kennington III         timer = std::make_unique<TestTimer>(*event, runCallback, interval);
15227b7301aSWilliam A. Kennington III         EXPECT_EQ(expected_event, timer->get_event().get());
15381282e1aSWilliam A. Kennington III     }
15481282e1aSWilliam A. Kennington III 
TearDown()15581282e1aSWilliam A. Kennington III     void TearDown()
15681282e1aSWilliam A. Kennington III     {
157ba04ffb5SWilliam A. Kennington III         resetTimer();
158ba04ffb5SWilliam A. Kennington III         event.reset();
15981282e1aSWilliam A. Kennington III         EXPECT_EQ(0, event_ref_times);
16081282e1aSWilliam A. Kennington III     }
16181282e1aSWilliam A. Kennington III };
16281282e1aSWilliam A. Kennington III 
TEST_F(TimerTest,NoCallback)163ba04ffb5SWilliam A. Kennington III TEST_F(TimerTest, NoCallback)
164ba04ffb5SWilliam A. Kennington III {
165ba04ffb5SWilliam A. Kennington III     resetTimer();
166ba04ffb5SWilliam A. Kennington III     expectNow(starting_time);
167ba04ffb5SWilliam A. Kennington III     EXPECT_CALL(
168ba04ffb5SWilliam A. Kennington III         mock, sd_event_add_time(expected_event, testing::_,
169ba04ffb5SWilliam A. Kennington III                                 static_cast<clockid_t>(testClock),
170ba04ffb5SWilliam A. Kennington III                                 microseconds(starting_time + interval).count(),
171ba04ffb5SWilliam A. Kennington III                                 1000, testing::_, nullptr))
172ba04ffb5SWilliam A. Kennington III         .WillOnce(DoAll(SetArgPointee<1>(expected_source), SaveArg<5>(&handler),
173ba04ffb5SWilliam A. Kennington III                         Return(0)));
174ba04ffb5SWilliam A. Kennington III     expectSetEnabled(source::Enabled::On);
175ba04ffb5SWilliam A. Kennington III     timer = std::make_unique<TestTimer>(*event, nullptr, interval);
176ba04ffb5SWilliam A. Kennington III 
177ba04ffb5SWilliam A. Kennington III     expectNow(starting_time);
178ba04ffb5SWilliam A. Kennington III     expectSetTime(starting_time + interval);
179ba04ffb5SWilliam A. Kennington III     EXPECT_EQ(0, handler(nullptr, 0, handler_userdata));
180ba04ffb5SWilliam A. Kennington III }
181ba04ffb5SWilliam A. Kennington III 
TEST_F(TimerTest,NoInterval)182ba04ffb5SWilliam A. Kennington III TEST_F(TimerTest, NoInterval)
183ba04ffb5SWilliam A. Kennington III {
184ba04ffb5SWilliam A. Kennington III     resetTimer();
185ba04ffb5SWilliam A. Kennington III     expectNow(starting_time);
186ba04ffb5SWilliam A. Kennington III     EXPECT_CALL(mock, sd_event_add_time(expected_event, testing::_,
187ba04ffb5SWilliam A. Kennington III                                         static_cast<clockid_t>(testClock),
188ba04ffb5SWilliam A. Kennington III                                         microseconds(starting_time).count(),
189ba04ffb5SWilliam A. Kennington III                                         1000, testing::_, nullptr))
190ba04ffb5SWilliam A. Kennington III         .WillOnce(DoAll(SetArgPointee<1>(expected_source), SaveArg<5>(&handler),
191ba04ffb5SWilliam A. Kennington III                         Return(0)));
192ba04ffb5SWilliam A. Kennington III     expectSetEnabled(source::Enabled::Off);
193ba04ffb5SWilliam A. Kennington III     timer = std::make_unique<TestTimer>(*event, nullptr);
194ba04ffb5SWilliam A. Kennington III 
195ba04ffb5SWilliam A. Kennington III     EXPECT_EQ(std::nullopt, timer->getInterval());
196ba04ffb5SWilliam A. Kennington III     EXPECT_THROW(timer->setEnabled(true), std::runtime_error);
197ba04ffb5SWilliam A. Kennington III }
198ba04ffb5SWilliam A. Kennington III 
TEST_F(TimerTest,NewTimer)19981282e1aSWilliam A. Kennington III TEST_F(TimerTest, NewTimer)
20081282e1aSWilliam A. Kennington III {
20181282e1aSWilliam A. Kennington III     EXPECT_FALSE(timer->hasExpired());
20281282e1aSWilliam A. Kennington III     EXPECT_EQ(interval, timer->getInterval());
20381282e1aSWilliam A. Kennington III }
20481282e1aSWilliam A. Kennington III 
TEST_F(TimerTest,IsEnabled)20581282e1aSWilliam A. Kennington III TEST_F(TimerTest, IsEnabled)
20681282e1aSWilliam A. Kennington III {
20781282e1aSWilliam A. Kennington III     expectGetEnabled(source::Enabled::On);
20881282e1aSWilliam A. Kennington III     EXPECT_TRUE(timer->isEnabled());
20981282e1aSWilliam A. Kennington III     expectGetEnabled(source::Enabled::Off);
21081282e1aSWilliam A. Kennington III     EXPECT_FALSE(timer->isEnabled());
21181282e1aSWilliam A. Kennington III }
21281282e1aSWilliam A. Kennington III 
TEST_F(TimerTest,GetRemainingDisabled)21381282e1aSWilliam A. Kennington III TEST_F(TimerTest, GetRemainingDisabled)
21481282e1aSWilliam A. Kennington III {
21581282e1aSWilliam A. Kennington III     expectGetEnabled(source::Enabled::Off);
21681282e1aSWilliam A. Kennington III     EXPECT_THROW(timer->getRemaining(), std::runtime_error);
21781282e1aSWilliam A. Kennington III }
21881282e1aSWilliam A. Kennington III 
TEST_F(TimerTest,GetRemainingNegative)21981282e1aSWilliam A. Kennington III TEST_F(TimerTest, GetRemainingNegative)
22081282e1aSWilliam A. Kennington III {
22181282e1aSWilliam A. Kennington III     milliseconds now(675), end(453);
22281282e1aSWilliam A. Kennington III     expectGetEnabled(source::Enabled::On);
22381282e1aSWilliam A. Kennington III     EXPECT_CALL(mock, sd_event_source_get_time(expected_source, testing::_))
22481282e1aSWilliam A. Kennington III         .WillOnce(
22581282e1aSWilliam A. Kennington III             DoAll(SetArgPointee<1>(microseconds(end).count()), Return(0)));
22681282e1aSWilliam A. Kennington III     expectNow(now);
22781282e1aSWilliam A. Kennington III     EXPECT_EQ(milliseconds(0), timer->getRemaining());
22881282e1aSWilliam A. Kennington III }
22981282e1aSWilliam A. Kennington III 
TEST_F(TimerTest,GetRemainingPositive)23081282e1aSWilliam A. Kennington III TEST_F(TimerTest, GetRemainingPositive)
23181282e1aSWilliam A. Kennington III {
23281282e1aSWilliam A. Kennington III     milliseconds now(453), end(675);
23381282e1aSWilliam A. Kennington III     expectGetEnabled(source::Enabled::On);
23481282e1aSWilliam A. Kennington III     EXPECT_CALL(mock, sd_event_source_get_time(expected_source, testing::_))
23581282e1aSWilliam A. Kennington III         .WillOnce(
23681282e1aSWilliam A. Kennington III             DoAll(SetArgPointee<1>(microseconds(end).count()), Return(0)));
23781282e1aSWilliam A. Kennington III     expectNow(now);
23881282e1aSWilliam A. Kennington III     EXPECT_EQ(end - now, timer->getRemaining());
23981282e1aSWilliam A. Kennington III }
24081282e1aSWilliam A. Kennington III 
TEST_F(TimerTest,SetEnabled)24181282e1aSWilliam A. Kennington III TEST_F(TimerTest, SetEnabled)
24281282e1aSWilliam A. Kennington III {
24381282e1aSWilliam A. Kennington III     expectSetEnabled(source::Enabled::On);
24481282e1aSWilliam A. Kennington III     timer->setEnabled(true);
24581282e1aSWilliam A. Kennington III     EXPECT_FALSE(timer->hasExpired());
24681282e1aSWilliam A. Kennington III     // Value should always be passed through regardless of current state
24781282e1aSWilliam A. Kennington III     expectSetEnabled(source::Enabled::On);
24881282e1aSWilliam A. Kennington III     timer->setEnabled(true);
24981282e1aSWilliam A. Kennington III     EXPECT_FALSE(timer->hasExpired());
25081282e1aSWilliam A. Kennington III 
25181282e1aSWilliam A. Kennington III     expectSetEnabled(source::Enabled::Off);
25281282e1aSWilliam A. Kennington III     timer->setEnabled(false);
25381282e1aSWilliam A. Kennington III     EXPECT_FALSE(timer->hasExpired());
25481282e1aSWilliam A. Kennington III     // Value should always be passed through regardless of current state
25581282e1aSWilliam A. Kennington III     expectSetEnabled(source::Enabled::Off);
25681282e1aSWilliam A. Kennington III     timer->setEnabled(false);
25781282e1aSWilliam A. Kennington III     EXPECT_FALSE(timer->hasExpired());
25881282e1aSWilliam A. Kennington III }
25981282e1aSWilliam A. Kennington III 
TEST_F(TimerTest,SetEnabledUnsetTimer)260ba04ffb5SWilliam A. Kennington III TEST_F(TimerTest, SetEnabledUnsetTimer)
261ba04ffb5SWilliam A. Kennington III {
262ba04ffb5SWilliam A. Kennington III     // Force the timer to become unset
263ba04ffb5SWilliam A. Kennington III     expectSetEnabled(source::Enabled::Off);
264ba04ffb5SWilliam A. Kennington III     timer->restart(std::nullopt);
265ba04ffb5SWilliam A. Kennington III 
266ba04ffb5SWilliam A. Kennington III     // Setting an interval should not update the timer directly
267ba04ffb5SWilliam A. Kennington III     timer->setInterval(milliseconds(90));
268ba04ffb5SWilliam A. Kennington III 
269ba04ffb5SWilliam A. Kennington III     expectSetEnabled(source::Enabled::Off);
270ba04ffb5SWilliam A. Kennington III     timer->setEnabled(false);
271ba04ffb5SWilliam A. Kennington III     EXPECT_THROW(timer->setEnabled(true), std::runtime_error);
272ba04ffb5SWilliam A. Kennington III }
273ba04ffb5SWilliam A. Kennington III 
TEST_F(TimerTest,SetEnabledOneshot)274ba04ffb5SWilliam A. Kennington III TEST_F(TimerTest, SetEnabledOneshot)
275ba04ffb5SWilliam A. Kennington III {
276ba04ffb5SWilliam A. Kennington III     // Timer effectively becomes oneshot if it gets initialized but has
277ba04ffb5SWilliam A. Kennington III     // the interval removed
278ba04ffb5SWilliam A. Kennington III     timer->setInterval(std::nullopt);
279ba04ffb5SWilliam A. Kennington III 
280ba04ffb5SWilliam A. Kennington III     expectSetEnabled(source::Enabled::Off);
281ba04ffb5SWilliam A. Kennington III     timer->setEnabled(false);
282ba04ffb5SWilliam A. Kennington III     expectSetEnabled(source::Enabled::On);
283ba04ffb5SWilliam A. Kennington III     timer->setEnabled(true);
284ba04ffb5SWilliam A. Kennington III }
285ba04ffb5SWilliam A. Kennington III 
TEST_F(TimerTest,SetRemaining)28681282e1aSWilliam A. Kennington III TEST_F(TimerTest, SetRemaining)
28781282e1aSWilliam A. Kennington III {
28881282e1aSWilliam A. Kennington III     const milliseconds now(90), remaining(30);
28981282e1aSWilliam A. Kennington III     expectNow(now);
29081282e1aSWilliam A. Kennington III     expectSetTime(now + remaining);
29181282e1aSWilliam A. Kennington III     timer->setRemaining(remaining);
29281282e1aSWilliam A. Kennington III     EXPECT_EQ(interval, timer->getInterval());
29381282e1aSWilliam A. Kennington III     EXPECT_FALSE(timer->hasExpired());
29481282e1aSWilliam A. Kennington III }
29581282e1aSWilliam A. Kennington III 
TEST_F(TimerTest,ResetRemaining)29681282e1aSWilliam A. Kennington III TEST_F(TimerTest, ResetRemaining)
29781282e1aSWilliam A. Kennington III {
29881282e1aSWilliam A. Kennington III     const milliseconds now(90);
29981282e1aSWilliam A. Kennington III     expectNow(now);
30081282e1aSWilliam A. Kennington III     expectSetTime(now + interval);
30181282e1aSWilliam A. Kennington III     timer->resetRemaining();
30281282e1aSWilliam A. Kennington III     EXPECT_EQ(interval, timer->getInterval());
30381282e1aSWilliam A. Kennington III     EXPECT_FALSE(timer->hasExpired());
30481282e1aSWilliam A. Kennington III }
30581282e1aSWilliam A. Kennington III 
TEST_F(TimerTest,SetInterval)30681282e1aSWilliam A. Kennington III TEST_F(TimerTest, SetInterval)
30781282e1aSWilliam A. Kennington III {
30881282e1aSWilliam A. Kennington III     const milliseconds new_interval(40);
30981282e1aSWilliam A. Kennington III     timer->setInterval(new_interval);
31081282e1aSWilliam A. Kennington III     EXPECT_EQ(new_interval, timer->getInterval());
31181282e1aSWilliam A. Kennington III     EXPECT_FALSE(timer->hasExpired());
31281282e1aSWilliam A. Kennington III }
31381282e1aSWilliam A. Kennington III 
TEST_F(TimerTest,SetIntervalEmpty)314ba04ffb5SWilliam A. Kennington III TEST_F(TimerTest, SetIntervalEmpty)
315ba04ffb5SWilliam A. Kennington III {
316ba04ffb5SWilliam A. Kennington III     timer->setInterval(std::nullopt);
317ba04ffb5SWilliam A. Kennington III     EXPECT_EQ(std::nullopt, timer->getInterval());
318ba04ffb5SWilliam A. Kennington III     EXPECT_FALSE(timer->hasExpired());
319ba04ffb5SWilliam A. Kennington III }
320ba04ffb5SWilliam A. Kennington III 
TEST_F(TimerTest,CallbackHappensLast)321ba04ffb5SWilliam A. Kennington III TEST_F(TimerTest, CallbackHappensLast)
322ba04ffb5SWilliam A. Kennington III {
323ba04ffb5SWilliam A. Kennington III     const milliseconds new_time(90);
324ba04ffb5SWilliam A. Kennington III     expectNow(new_time);
325ba04ffb5SWilliam A. Kennington III     expectSetTime(new_time + interval);
326ba04ffb5SWilliam A. Kennington III     callback = [&]() {
327ba04ffb5SWilliam A. Kennington III         EXPECT_TRUE(timer->hasExpired());
328ba04ffb5SWilliam A. Kennington III         expectSetEnabled(source::Enabled::On);
329ba04ffb5SWilliam A. Kennington III         timer->setEnabled(true);
330ba04ffb5SWilliam A. Kennington III         timer->clearExpired();
331ba04ffb5SWilliam A. Kennington III         timer->setInterval(std::nullopt);
332ba04ffb5SWilliam A. Kennington III     };
333ba04ffb5SWilliam A. Kennington III     EXPECT_EQ(0, handler(nullptr, 0, handler_userdata));
334ba04ffb5SWilliam A. Kennington III     EXPECT_FALSE(timer->hasExpired());
335ba04ffb5SWilliam A. Kennington III     EXPECT_EQ(std::nullopt, timer->getInterval());
336ba04ffb5SWilliam A. Kennington III     expectSetEnabled(source::Enabled::On);
337ba04ffb5SWilliam A. Kennington III     timer->setEnabled(true);
338ba04ffb5SWilliam A. Kennington III }
339ba04ffb5SWilliam A. Kennington III 
TEST_F(TimerTest,CallbackOneshot)340ba04ffb5SWilliam A. Kennington III TEST_F(TimerTest, CallbackOneshot)
341ba04ffb5SWilliam A. Kennington III {
342ba04ffb5SWilliam A. Kennington III     // Make sure we try a one shot so we can test the callback
343ba04ffb5SWilliam A. Kennington III     // correctly
344ba04ffb5SWilliam A. Kennington III     timer->setInterval(std::nullopt);
345ba04ffb5SWilliam A. Kennington III 
346ba04ffb5SWilliam A. Kennington III     expectSetEnabled(source::Enabled::Off);
347ba04ffb5SWilliam A. Kennington III     callback = [&]() {
348ba04ffb5SWilliam A. Kennington III         EXPECT_TRUE(timer->hasExpired());
349ba04ffb5SWilliam A. Kennington III         EXPECT_THROW(timer->setEnabled(true), std::runtime_error);
350ba04ffb5SWilliam A. Kennington III         timer->setInterval(interval);
351ba04ffb5SWilliam A. Kennington III     };
352ba04ffb5SWilliam A. Kennington III     EXPECT_EQ(0, handler(nullptr, 0, handler_userdata));
353ba04ffb5SWilliam A. Kennington III     EXPECT_THROW(timer->setEnabled(true), std::runtime_error);
354ba04ffb5SWilliam A. Kennington III }
355ba04ffb5SWilliam A. Kennington III 
TEST_F(TimerTest,CallbackMove)356a5f8596aSWilliam A. Kennington III TEST_F(TimerTest, CallbackMove)
357a5f8596aSWilliam A. Kennington III {
358a5f8596aSWilliam A. Kennington III     size_t called = 0;
359a5f8596aSWilliam A. Kennington III     callback = [&]() { ++called; };
360a5f8596aSWilliam A. Kennington III 
361a5f8596aSWilliam A. Kennington III     expectNow(starting_time2);
3625320b1f5SWilliam A. Kennington III     sd_event_destroy_t local_destroy;
3635320b1f5SWilliam A. Kennington III     EXPECT_CALL(mock, sd_event_source_set_destroy_callback(expected_source2,
3645320b1f5SWilliam A. Kennington III                                                            testing::_))
3655320b1f5SWilliam A. Kennington III         .WillOnce(DoAll(SaveArg<1>(&local_destroy), Return(0)));
3665320b1f5SWilliam A. Kennington III     void* local_userdata;
367a5f8596aSWilliam A. Kennington III     EXPECT_CALL(mock,
368a5f8596aSWilliam A. Kennington III                 sd_event_source_set_userdata(expected_source2, testing::_))
3695320b1f5SWilliam A. Kennington III         .WillOnce(DoAll(SaveArg<1>(&local_userdata), Return(nullptr)));
3705320b1f5SWilliam A. Kennington III     EXPECT_CALL(mock, sd_event_source_get_userdata(expected_source2))
3715320b1f5SWilliam A. Kennington III         .WillRepeatedly(ReturnPointee(&local_userdata));
372a5f8596aSWilliam A. Kennington III     EXPECT_CALL(mock, sd_event_add_time(expected_event, testing::_,
373a5f8596aSWilliam A. Kennington III                                         static_cast<clockid_t>(testClock),
374a5f8596aSWilliam A. Kennington III                                         microseconds(starting_time2).count(),
375a5f8596aSWilliam A. Kennington III                                         1000, testing::_, nullptr))
376a5f8596aSWilliam A. Kennington III         .WillOnce(DoAll(SetArgPointee<1>(expected_source2), Return(0)));
377a5f8596aSWilliam A. Kennington III     EXPECT_CALL(mock, sd_event_source_unref(expected_source2))
378a5f8596aSWilliam A. Kennington III         .WillOnce(Return(nullptr));
379a5f8596aSWilliam A. Kennington III     EXPECT_CALL(mock,
380a5f8596aSWilliam A. Kennington III                 sd_event_source_set_enabled(
381a5f8596aSWilliam A. Kennington III                     expected_source2, static_cast<int>(source::Enabled::Off)))
382a5f8596aSWilliam A. Kennington III         .WillOnce(Return(0));
383a5f8596aSWilliam A. Kennington III     TestTimer local_timer(*event, nullptr);
384a5f8596aSWilliam A. Kennington III 
385a5f8596aSWilliam A. Kennington III     // Move assign
386a5f8596aSWilliam A. Kennington III     local_timer = std::move(*timer);
3875320b1f5SWilliam A. Kennington III     local_destroy(local_userdata);
388a5f8596aSWilliam A. Kennington III     timer.reset();
389a5f8596aSWilliam A. Kennington III 
390a5f8596aSWilliam A. Kennington III     // Move construct
391a5f8596aSWilliam A. Kennington III     timer = std::make_unique<TestTimer>(std::move(local_timer));
392a5f8596aSWilliam A. Kennington III 
393a5f8596aSWilliam A. Kennington III     // handler_userdata should have been updated and the callback should work
394a5f8596aSWilliam A. Kennington III     const milliseconds new_time(90);
395a5f8596aSWilliam A. Kennington III     expectNow(new_time);
396a5f8596aSWilliam A. Kennington III     expectSetTime(new_time + interval);
397a5f8596aSWilliam A. Kennington III     EXPECT_EQ(0, handler(nullptr, 0, handler_userdata));
398a5f8596aSWilliam A. Kennington III     EXPECT_EQ(1, called);
39908ebb399SWilliam A. Kennington III 
40008ebb399SWilliam A. Kennington III     // update the callback and make sure it still works
40108ebb399SWilliam A. Kennington III     timer->set_callback(std::bind([]() {}));
40208ebb399SWilliam A. Kennington III     expectNow(new_time);
40308ebb399SWilliam A. Kennington III     expectSetTime(new_time + interval);
40408ebb399SWilliam A. Kennington III     EXPECT_EQ(0, handler(nullptr, 0, handler_userdata));
40508ebb399SWilliam A. Kennington III     EXPECT_EQ(1, called);
406a5f8596aSWilliam A. Kennington III }
407a5f8596aSWilliam A. Kennington III 
TEST_F(TimerTest,SetValuesExpiredTimer)40881282e1aSWilliam A. Kennington III TEST_F(TimerTest, SetValuesExpiredTimer)
40981282e1aSWilliam A. Kennington III {
41081282e1aSWilliam A. Kennington III     const milliseconds new_time(90);
41181282e1aSWilliam A. Kennington III     expectNow(new_time);
41281282e1aSWilliam A. Kennington III     expectSetTime(new_time + interval);
41381282e1aSWilliam A. Kennington III     EXPECT_EQ(0, handler(nullptr, 0, handler_userdata));
41481282e1aSWilliam A. Kennington III     EXPECT_TRUE(timer->hasExpired());
41581282e1aSWilliam A. Kennington III     EXPECT_EQ(interval, timer->getInterval());
41681282e1aSWilliam A. Kennington III 
41781282e1aSWilliam A. Kennington III     // Timer should remain expired unless clearExpired() or reset()
41881282e1aSWilliam A. Kennington III     expectSetEnabled(source::Enabled::On);
41981282e1aSWilliam A. Kennington III     timer->setEnabled(true);
42081282e1aSWilliam A. Kennington III     EXPECT_TRUE(timer->hasExpired());
42181282e1aSWilliam A. Kennington III     expectNow(milliseconds(20));
42281282e1aSWilliam A. Kennington III     expectSetTime(milliseconds(50));
42381282e1aSWilliam A. Kennington III     timer->setRemaining(milliseconds(30));
42481282e1aSWilliam A. Kennington III     EXPECT_TRUE(timer->hasExpired());
42581282e1aSWilliam A. Kennington III     timer->setInterval(milliseconds(10));
42681282e1aSWilliam A. Kennington III     EXPECT_TRUE(timer->hasExpired());
42781282e1aSWilliam A. Kennington III     expectNow(milliseconds(20));
42881282e1aSWilliam A. Kennington III     expectSetTime(milliseconds(30));
42981282e1aSWilliam A. Kennington III     timer->resetRemaining();
43081282e1aSWilliam A. Kennington III     EXPECT_TRUE(timer->hasExpired());
43181282e1aSWilliam A. Kennington III 
43281282e1aSWilliam A. Kennington III     timer->clearExpired();
43381282e1aSWilliam A. Kennington III     EXPECT_FALSE(timer->hasExpired());
43481282e1aSWilliam A. Kennington III }
43581282e1aSWilliam A. Kennington III 
TEST_F(TimerTest,Restart)43681282e1aSWilliam A. Kennington III TEST_F(TimerTest, Restart)
43781282e1aSWilliam A. Kennington III {
438ba04ffb5SWilliam A. Kennington III     expireTimer();
43981282e1aSWilliam A. Kennington III 
44081282e1aSWilliam A. Kennington III     const milliseconds new_interval(471);
44181282e1aSWilliam A. Kennington III     expectNow(starting_time);
44281282e1aSWilliam A. Kennington III     expectSetTime(starting_time + new_interval);
44381282e1aSWilliam A. Kennington III     expectSetEnabled(source::Enabled::On);
44481282e1aSWilliam A. Kennington III     timer->restart(new_interval);
44581282e1aSWilliam A. Kennington III     EXPECT_FALSE(timer->hasExpired());
44681282e1aSWilliam A. Kennington III     EXPECT_EQ(new_interval, timer->getInterval());
447ba04ffb5SWilliam A. Kennington III     expectSetEnabled(source::Enabled::On);
448ba04ffb5SWilliam A. Kennington III     timer->setEnabled(true);
449ba04ffb5SWilliam A. Kennington III }
450ba04ffb5SWilliam A. Kennington III 
TEST_F(TimerTest,RestartEmpty)451ba04ffb5SWilliam A. Kennington III TEST_F(TimerTest, RestartEmpty)
452ba04ffb5SWilliam A. Kennington III {
453ba04ffb5SWilliam A. Kennington III     expireTimer();
454ba04ffb5SWilliam A. Kennington III 
455ba04ffb5SWilliam A. Kennington III     expectSetEnabled(source::Enabled::Off);
456ba04ffb5SWilliam A. Kennington III     timer->restart(std::nullopt);
457ba04ffb5SWilliam A. Kennington III     EXPECT_FALSE(timer->hasExpired());
458ba04ffb5SWilliam A. Kennington III     EXPECT_EQ(std::nullopt, timer->getInterval());
459ba04ffb5SWilliam A. Kennington III     EXPECT_THROW(timer->setEnabled(true), std::runtime_error);
460ba04ffb5SWilliam A. Kennington III }
461ba04ffb5SWilliam A. Kennington III 
TEST_F(TimerTest,RestartOnce)462ba04ffb5SWilliam A. Kennington III TEST_F(TimerTest, RestartOnce)
463ba04ffb5SWilliam A. Kennington III {
464ba04ffb5SWilliam A. Kennington III     expireTimer();
465ba04ffb5SWilliam A. Kennington III 
466ba04ffb5SWilliam A. Kennington III     const milliseconds remaining(471);
467ba04ffb5SWilliam A. Kennington III     expectNow(starting_time);
468ba04ffb5SWilliam A. Kennington III     expectSetTime(starting_time + remaining);
469ba04ffb5SWilliam A. Kennington III     expectSetEnabled(source::Enabled::On);
470ba04ffb5SWilliam A. Kennington III     timer->restartOnce(remaining);
471ba04ffb5SWilliam A. Kennington III     EXPECT_FALSE(timer->hasExpired());
472ba04ffb5SWilliam A. Kennington III     EXPECT_EQ(std::nullopt, timer->getInterval());
473ba04ffb5SWilliam A. Kennington III     expectSetEnabled(source::Enabled::On);
474ba04ffb5SWilliam A. Kennington III     timer->setEnabled(true);
47581282e1aSWilliam A. Kennington III }
47681282e1aSWilliam A. Kennington III 
47781282e1aSWilliam A. Kennington III } // namespace
47881282e1aSWilliam A. Kennington III } // namespace utility
47981282e1aSWilliam A. Kennington III } // namespace sdeventplus
480