2 Copyright (c) 2018-2019 Nokia.
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
8 http://www.apache.org/licenses/LICENSE-2.0
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
17 #include <type_traits>
19 #include <boost/optional.hpp>
20 #include <sys/timerfd.h>
21 #include <gmock/gmock.h>
22 #include "private/timerfd.hpp"
23 #include "private/tst/systemmock.hpp"
24 #include "private/tst/enginemock.hpp"
26 using namespace shareddatalayer;
27 using namespace shareddatalayer::tst;
28 using namespace testing;
32 class TimerFDTest: public testing::Test
36 NiceMock<SystemMock> systemMock;
37 EngineMock engineMock;
38 std::unique_ptr<TimerFD> timerFD;
39 std::unique_ptr<Timer> timer1;
40 std::unique_ptr<Timer> timer2;
41 Engine::EventHandler savedEventHandler;
43 TimerFDTest(): tfd(123)
46 EXPECT_CALL(systemMock, timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC))
48 .WillOnce(Return(tfd));
49 EXPECT_CALL(engineMock, addMonitoredFD(Matcher<FileDescriptor&>(_), Engine::EVENT_IN, _))
51 .WillOnce(Invoke([this] (FileDescriptor& fd, unsigned int, const Engine::EventHandler& eh)
53 EXPECT_EQ(tfd, static_cast<int>(fd));
54 savedEventHandler = eh;
56 timerFD.reset(new TimerFD(systemMock, engineMock));
58 Mock::VerifyAndClear(&systemMock);
59 Mock::VerifyAndClear(&engineMock);
61 EXPECT_CALL(engineMock, armTimer(_, _, _))
63 .WillRepeatedly(Invoke([this] (Timer& timer, const Timer::Duration& duration, const Timer::Callback& cb)
65 timerFD.get()->arm(timer, duration, cb);
68 EXPECT_CALL(engineMock, disarmTimer(_))
70 .WillRepeatedly(Invoke([this](const Timer& timer)
72 timerFD.get()->disarm(timer);
75 ON_CALL(systemMock, time_since_epoch())
76 .WillByDefault(Return(std::chrono::steady_clock::duration(0)));
78 timer1.reset(new Timer(engineMock));
79 timer2.reset(new Timer(engineMock));
82 void expectSetTime(int seconds, int nanoseconds)
84 EXPECT_CALL(systemMock, timerfd_settime(tfd, TFD_TIMER_ABSTIME, NotNull(), nullptr))
86 .WillOnce(Invoke([seconds, nanoseconds] (int, int, const itimerspec* new_value, itimerspec*)
88 EXPECT_EQ(0, new_value->it_interval.tv_sec);
89 EXPECT_EQ(0, new_value->it_interval.tv_nsec);
90 EXPECT_EQ(seconds, new_value->it_value.tv_sec);
91 EXPECT_EQ(nanoseconds, new_value->it_value.tv_nsec);
95 void expectRead(const boost::optional<uint64_t>& count)
97 EXPECT_CALL(systemMock, read(tfd, NotNull(), sizeof(uint64_t)))
99 .WillOnce(Invoke([count] (int, void* buf, size_t) -> ssize_t
103 *static_cast<uint64_t *>(buf) = *count;
104 return sizeof(uint64_t);
110 void expectTimeSinceEpoch(const std::chrono::steady_clock::duration& ret)
112 EXPECT_CALL(systemMock, time_since_epoch())
114 .WillOnce(Return(ret));
117 void arm(Timer& timer, int seconds, int nanoseconds, const std::string& param = std::string())
119 timer.arm(std::chrono::duration_cast<Timer::Duration>(std::chrono::seconds(seconds) + std::chrono::nanoseconds(nanoseconds)),
120 std::bind(&TimerFDTest::callback, this, param));
123 void arm(int seconds, int nanoseconds, const std::string& param = std::string())
125 arm(*timer1, seconds, nanoseconds, param);
128 void disarm(Timer& timer)
138 MOCK_METHOD1(callback, void(const std::string& param));
142 TEST_F(TimerFDTest, IsNotCopyableAndIsNotMovable)
144 EXPECT_FALSE(std::is_copy_assignable<TimerFD>::value);
145 EXPECT_FALSE(std::is_move_assignable<TimerFD>::value);
146 EXPECT_FALSE(std::is_copy_constructible<TimerFD>::value);
147 EXPECT_FALSE(std::is_move_constructible<TimerFD>::value);
150 TEST_F(TimerFDTest, ArmingTheFirstTimerCallsSetTimeWithProperValues)
152 expectSetTime(3, 4000);
154 Mock::VerifyAndClear(&systemMock);
157 TEST_F(TimerFDTest, ArmingAnotherTimerWithLongerTimeoutDoesntCallSetTime)
162 Mock::VerifyAndClear(&systemMock);
165 TEST_F(TimerFDTest, DisarminTheOnlyTimerCallsSetTimeWithZeroValues)
172 TEST_F(TimerFDTest, DisarminTheFirstTimerCallsSetTimeWithProperValues)
178 Mock::VerifyAndClear(&systemMock);
181 TEST_F(TimerFDTest, AfterExecutingTheFirstTimerSetTimeIsCalledWithProperValues)
184 arm(*timer1, 1, 0, "first");
185 arm(*timer2, 2, 0, "second");
187 EXPECT_CALL(*this, callback("first"))
190 savedEventHandler(Engine::EVENT_IN);
191 Mock::VerifyAndClear(&systemMock);
194 TEST_F(TimerFDTest, AfterExecutingTheLastTimerSetTimeIsCalledWithZeroValues)
197 arm(*timer1, 1, 0, "first");
199 EXPECT_CALL(*this, callback("first"))
202 savedEventHandler(Engine::EVENT_IN);
203 Mock::VerifyAndClear(&systemMock);
206 TEST_F(TimerFDTest, IfReadReturnsNegativeOnHandleEventsNothingIsDone)
209 expectRead(boost::none);
210 EXPECT_CALL(*this, callback(_))
212 EXPECT_CALL(systemMock, timerfd_settime(_, _, _, _))
214 savedEventHandler(Engine::EVENT_IN);
215 Mock::VerifyAndClear(&systemMock);
218 TEST_F(TimerFDTest, IfReadReturnsNoEventsOnHandleEventsNothingIsDone)
221 expectRead(static_cast<uint64_t>(0U));
222 EXPECT_CALL(*this, callback(_))
224 EXPECT_CALL(systemMock, timerfd_settime(_, _, _, _))
226 savedEventHandler(Engine::EVENT_IN);
227 Mock::VerifyAndClear(&systemMock);
230 TEST_F(TimerFDTest, AllTimersThatHaveExpiredDuringTheEventLoopAreExecutedWithTheSameTimerFdExpiration)
234 /* The first timer is armed to expire after 10 seconds */
235 expectTimeSinceEpoch(std::chrono::seconds(0));
236 arm(*timer1, 10, 0, "first");
238 /* Time has passed 2 seconds, the second timer is armed to expire after 8 seconds */
239 expectTimeSinceEpoch(std::chrono::seconds(2));
240 arm(*timer2, 8, 0, "second");
242 /* Time has passed 8 more seconds, both timers expire at once */
244 expectTimeSinceEpoch(std::chrono::seconds(10));
245 EXPECT_CALL(*this, callback("first"))
247 EXPECT_CALL(*this, callback("second"))
249 savedEventHandler(Engine::EVENT_IN);