1 //******************************************************************
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 #include <UnitTestHelper.h>
26 #include "RCSException.h"
27 #include "ExpiryTimer.h"
28 #include "ExpiryTimerImpl.h"
30 using namespace OIC::Service;
32 constexpr int TOLERANCE_IN_MILLIS{ 50 };
37 virtual ~FunctionObject()
42 virtual void execute(ExpiryTimerImpl::Id)
48 class ExpiryTimerImplTest: public TestWithMock
56 void Wait(int waitingTime = TOLERANCE_IN_MILLIS)
58 std::unique_lock< std::mutex > lock{ mutex };
59 cond.wait_for(lock, std::chrono::milliseconds{ waitingTime });
63 std::condition_variable cond;
68 TEST_F(ExpiryTimerImplTest, PostThrowsIfDelayIsNegative)
70 ASSERT_THROW(ExpiryTimerImpl::getInstance()->post(-1,
71 [](ExpiryTimerImpl::Id)
76 TEST_F(ExpiryTimerImplTest, PostThrowsIfCallbackIsEmpty)
78 ASSERT_THROW(ExpiryTimerImpl::getInstance()->post(1, { }), RCSException);
81 TEST_F(ExpiryTimerImplTest, CallbackBeInvokedWithinTolerance)
83 FunctionObject* functor = mocks.Mock< FunctionObject >();
85 mocks.ExpectCall(functor, FunctionObject::execute).Do(
86 [this](ExpiryTimerImpl::Id)
92 ExpiryTimerImpl::getInstance()->post(10,
93 std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
98 TEST_F(ExpiryTimerImplTest, CallbackBeInvokedWithTimerId)
100 ExpiryTimerImpl::Id returnedId = 0;
101 FunctionObject* functor = mocks.Mock< FunctionObject >();
103 mocks.ExpectCall(functor, FunctionObject::execute).Match(
104 [this, &returnedId](ExpiryTimerImpl::Id id)
106 return returnedId == id;
109 [this](ExpiryTimerImpl::Id)
115 returnedId = ExpiryTimerImpl::getInstance()->post(1,
116 std::bind(&FunctionObject::execute, functor, std::placeholders::_1))->getId();
121 TEST_F(ExpiryTimerImplTest, CanceledTaskBeNotCalled)
123 FunctionObject* functor = mocks.Mock< FunctionObject >();
125 mocks.NeverCall(functor, FunctionObject::execute);
127 ExpiryTimerImpl::Id id = ExpiryTimerImpl::getInstance()->post(10,
128 std::bind(&FunctionObject::execute, functor, std::placeholders::_1))->getId();
129 ExpiryTimerImpl::getInstance()->cancel(id);
133 TEST_F(ExpiryTimerImplTest, CancelReturnsTrueIfCanceledCorrectly)
135 FunctionObject* functor = mocks.Mock< FunctionObject >();
137 ExpiryTimerImpl::Id id = ExpiryTimerImpl::getInstance()->post(10,
138 std::bind(&FunctionObject::execute, functor, std::placeholders::_1))->getId();
140 ASSERT_TRUE(ExpiryTimerImpl::getInstance()->cancel(id));
143 TEST_F(ExpiryTimerImplTest, CancelReturnsFalseIfAlreadyExecuted)
145 FunctionObject* functor = mocks.Mock< FunctionObject >();
147 mocks.ExpectCall(functor, FunctionObject::execute).Do(
148 [this](ExpiryTimerImpl::Id)
154 ExpiryTimerImpl::Id id = ExpiryTimerImpl::getInstance()->post(1,
155 std::bind(&FunctionObject::execute, functor, std::placeholders::_1))->getId();
158 ASSERT_FALSE(ExpiryTimerImpl::getInstance()->cancel(id));
161 TEST_F(ExpiryTimerImplTest, CallbackBeInvokedWithinToleranceWithMultiplePost)
163 constexpr int NUM_OF_POST{ 10000 };
164 std::atomic_int called{ 0 };
166 for (int i=0; i<NUM_OF_POST; ++i)
168 FunctionObject* functor = mocks.Mock< FunctionObject >();
169 mocks.OnCall(functor, FunctionObject::execute).Do(
170 [&called](ExpiryTimerImpl::Id)
176 ExpiryTimerImpl::getInstance()->post(rand() % 20 + 5,
177 std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
180 Wait(TOLERANCE_IN_MILLIS + 25);
182 ASSERT_EQ(NUM_OF_POST, called);
185 class ExpiryTimerTest: public TestWithMock
196 void Wait(int waitingTime = TOLERANCE_IN_MILLIS)
198 std::unique_lock< std::mutex > lock{ mutex };
199 cond.wait_for(lock, std::chrono::milliseconds{ waitingTime });
203 std::condition_variable cond;
207 TEST_F(ExpiryTimerTest, PostThrowsIfDelayIsNegative)
209 ASSERT_THROW(timer.post(-1,
215 TEST_F(ExpiryTimerTest, PostThrowsIfCallbackIsEmpty)
217 ASSERT_THROW(timer.post(1, { }), RCSException);
220 TEST_F(ExpiryTimerTest, CallbackBeInvokedWithinTolerance)
222 FunctionObject* functor = mocks.Mock< FunctionObject >();
224 mocks.ExpectCall(functor, FunctionObject::execute).Do(
225 [this](ExpiryTimer::Id)
232 std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
237 TEST_F(ExpiryTimerTest, CallbackBeInvokedWithTimerId)
239 ExpiryTimer::Id returnedId = 0;
240 FunctionObject* functor = mocks.Mock< FunctionObject >();
242 mocks.ExpectCall(functor, FunctionObject::execute).Match(
243 [this, &returnedId](ExpiryTimer::Id id)
245 return returnedId == id;
248 [this](ExpiryTimer::Id)
254 returnedId = timer.post(1, std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
259 TEST_F(ExpiryTimerTest, CanceledTaskBeNotCalled)
261 FunctionObject* functor = mocks.Mock< FunctionObject >();
263 mocks.NeverCall(functor, FunctionObject::execute);
265 auto id = timer.post(10, std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
270 TEST_F(ExpiryTimerTest, CancelReturnsTrueIfCanceledCorrectly)
272 FunctionObject* functor = mocks.Mock< FunctionObject >();
274 auto id = timer.post(10, std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
276 ASSERT_TRUE(timer.cancel(id));
279 TEST_F(ExpiryTimerTest, CancelReturnsFalseIfAlreadyExecuted)
281 FunctionObject* functor = mocks.Mock< FunctionObject >();
283 mocks.ExpectCall(functor, FunctionObject::execute).Do(
284 [this](ExpiryTimer::Id)
290 auto id = timer.post(1, std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
293 ASSERT_FALSE(timer.cancel(id));
296 TEST_F(ExpiryTimerTest, NumOfPendingReturnsNumberOfNotExecuted)
298 constexpr size_t numOfFutureTask{ 100 };
299 constexpr size_t numOfShortDelayTask{ 100 };
301 for (size_t i=0; i<numOfFutureTask; ++i)
303 FunctionObject* functor = mocks.Mock< FunctionObject >();
304 mocks.OnCall(functor, FunctionObject::execute);
306 timer.post(1000, std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
309 for (size_t i=0; i<numOfShortDelayTask; ++i)
311 FunctionObject* functor = mocks.Mock< FunctionObject >();
312 mocks.OnCall(functor, FunctionObject::execute);
314 timer.post(i, std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
317 Wait(numOfShortDelayTask + TOLERANCE_IN_MILLIS);
319 ASSERT_EQ(timer.getNumOfPending(), numOfFutureTask);
322 TEST_F(ExpiryTimerTest, CancelAllCancelsAllTasks)
324 constexpr size_t numOfTask{ 100 };
326 for (size_t i=0; i<numOfTask; ++i)
328 FunctionObject* functor = mocks.Mock< FunctionObject >();
329 mocks.NeverCall(functor, FunctionObject::execute);
331 timer.post(50 + i, std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
339 TEST_F(ExpiryTimerTest, AllTasksAreCancelledAfterTimerDestroyed)
342 ExpiryTimer localTimer;
343 FunctionObject* functor = mocks.Mock< FunctionObject >();
345 mocks.NeverCall(functor, FunctionObject::execute);
348 std::bind(&FunctionObject::execute, functor, std::placeholders::_1));