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() { }
39 virtual void execute(ExpiryTimerImpl::Id) { }
42 class ExpiryTimerImplTest: public TestWithMock
50 void Wait(int waitingTime = TOLERANCE_IN_MILLIS)
52 std::unique_lock< std::mutex > lock{ mutex };
53 cond.wait_for(lock, std::chrono::milliseconds{ waitingTime });
57 std::condition_variable cond;
62 TEST_F(ExpiryTimerImplTest, PostThrowsIfDelayIsNegative)
64 ASSERT_THROW(ExpiryTimerImpl::getInstance()->post(-1, [](ExpiryTimerImpl::Id){}), RCSException);
67 TEST_F(ExpiryTimerImplTest, PostThrowsIfCallbackIsEmpty)
69 ASSERT_THROW(ExpiryTimerImpl::getInstance()->post(1, { }), RCSException);
72 TEST_F(ExpiryTimerImplTest, CallbackBeInvokedWithinTolerance)
74 FunctionObject* functor = mocks.Mock< FunctionObject >();
76 mocks.ExpectCall(functor, FunctionObject::execute).Do(
77 [this](ExpiryTimerImpl::Id){
82 ExpiryTimerImpl::getInstance()->post(10,
83 std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
88 TEST_F(ExpiryTimerImplTest, CallbackBeInvokedWithTimerId)
90 ExpiryTimerImpl::Id returnedId;
91 FunctionObject* functor = mocks.Mock< FunctionObject >();
93 mocks.ExpectCall(functor, FunctionObject::execute).Match(
94 [this, &returnedId](ExpiryTimerImpl::Id id){
95 return returnedId == id;
98 [this](ExpiryTimerImpl::Id){
103 returnedId = ExpiryTimerImpl::getInstance()->post(1,
104 std::bind(&FunctionObject::execute, functor, std::placeholders::_1))->getId();
109 TEST_F(ExpiryTimerImplTest, CanceledTaskBeNotCalled)
111 FunctionObject* functor = mocks.Mock< FunctionObject >();
113 mocks.NeverCall(functor, FunctionObject::execute);
115 ExpiryTimerImpl::Id id = ExpiryTimerImpl::getInstance()->post(10,
116 std::bind(&FunctionObject::execute, functor, std::placeholders::_1))->getId();
117 ExpiryTimerImpl::getInstance()->cancel(id);
121 TEST_F(ExpiryTimerImplTest, CancelReturnsTrueIfCanceledCorrectly)
123 FunctionObject* functor = mocks.Mock< FunctionObject >();
125 ExpiryTimerImpl::Id id = ExpiryTimerImpl::getInstance()->post(10,
126 std::bind(&FunctionObject::execute, functor, std::placeholders::_1))->getId();
128 ASSERT_TRUE(ExpiryTimerImpl::getInstance()->cancel(id));
131 TEST_F(ExpiryTimerImplTest, CancelReturnsFalseIfAlreadyExecuted)
133 FunctionObject* functor = mocks.Mock< FunctionObject >();
135 mocks.ExpectCall(functor, FunctionObject::execute).Do(
136 [this](ExpiryTimerImpl::Id){
141 ExpiryTimerImpl::Id id = ExpiryTimerImpl::getInstance()->post(1,
142 std::bind(&FunctionObject::execute, functor, std::placeholders::_1))->getId();
145 ASSERT_FALSE(ExpiryTimerImpl::getInstance()->cancel(id));
148 TEST_F(ExpiryTimerImplTest, CallbackBeInvokedWithinToleranceWithMultiplePost)
150 constexpr int NUM_OF_POST{ 10000 };
151 std::atomic_int called{ 0 };
153 for (int i=0; i<NUM_OF_POST; ++i)
155 FunctionObject* functor = mocks.Mock< FunctionObject >();
156 mocks.OnCall(functor, FunctionObject::execute).Do(
157 [&called](ExpiryTimerImpl::Id)
163 ExpiryTimerImpl::getInstance()->post(rand() % 20 + 5,
164 std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
167 Wait(TOLERANCE_IN_MILLIS + 25);
169 ASSERT_EQ(NUM_OF_POST, called);
172 class ExpiryTimerTest: public TestWithMock
183 void Wait(int waitingTime = TOLERANCE_IN_MILLIS)
185 std::unique_lock< std::mutex > lock{ mutex };
186 cond.wait_for(lock, std::chrono::milliseconds{ waitingTime });
190 std::condition_variable cond;
194 TEST_F(ExpiryTimerTest, PostThrowsIfDelayIsNegative)
196 ASSERT_THROW(timer.post(-1, [](ExpiryTimer::Id){}), RCSException);
199 TEST_F(ExpiryTimerTest, PostThrowsIfCallbackIsEmpty)
201 ASSERT_THROW(timer.post(1, { }), RCSException);
204 TEST_F(ExpiryTimerTest, CallbackBeInvokedWithinTolerance)
206 FunctionObject* functor = mocks.Mock< FunctionObject >();
208 mocks.ExpectCall(functor, FunctionObject::execute).Do(
209 [this](ExpiryTimer::Id){
215 std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
220 TEST_F(ExpiryTimerTest, CallbackBeInvokedWithTimerId)
222 ExpiryTimer::Id returnedId;
223 FunctionObject* functor = mocks.Mock< FunctionObject >();
225 mocks.ExpectCall(functor, FunctionObject::execute).Match(
226 [this, &returnedId](ExpiryTimer::Id id){
227 return returnedId == id;
230 [this](ExpiryTimer::Id){
235 returnedId = timer.post(1, std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
240 TEST_F(ExpiryTimerTest, CanceledTaskBeNotCalled)
242 FunctionObject* functor = mocks.Mock< FunctionObject >();
244 mocks.NeverCall(functor, FunctionObject::execute);
246 auto id = timer.post(10, std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
251 TEST_F(ExpiryTimerTest, CancelReturnsTrueIfCanceledCorrectly)
253 FunctionObject* functor = mocks.Mock< FunctionObject >();
255 auto id = timer.post(10, std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
257 ASSERT_TRUE(timer.cancel(id));
260 TEST_F(ExpiryTimerTest, CancelReturnsFalseIfAlreadyExecuted)
262 FunctionObject* functor = mocks.Mock< FunctionObject >();
264 mocks.ExpectCall(functor, FunctionObject::execute).Do(
265 [this](ExpiryTimer::Id){
270 auto id = timer.post(1, std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
273 ASSERT_FALSE(timer.cancel(id));
276 TEST_F(ExpiryTimerTest, NumOfPendingReturnsNumberOfNotExecuted)
278 constexpr size_t numOfFutureTask{ 100 };
279 constexpr size_t numOfShortDelayTask{ 100 };
281 for (size_t i=0; i<numOfFutureTask; ++i)
283 FunctionObject* functor = mocks.Mock< FunctionObject >();
284 mocks.OnCall(functor, FunctionObject::execute);
286 timer.post(1000, std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
289 for (size_t i=0; i<numOfShortDelayTask; ++i)
291 FunctionObject* functor = mocks.Mock< FunctionObject >();
292 mocks.OnCall(functor, FunctionObject::execute);
294 timer.post(i, std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
297 Wait(numOfShortDelayTask + TOLERANCE_IN_MILLIS);
299 ASSERT_EQ(timer.getNumOfPending(), numOfFutureTask);
302 TEST_F(ExpiryTimerTest, CancelAllCancelsAllTasks)
304 constexpr size_t numOfTask{ 100 };
306 for (size_t i=0; i<numOfTask; ++i)
308 FunctionObject* functor = mocks.Mock< FunctionObject >();
309 mocks.NeverCall(functor, FunctionObject::execute);
311 timer.post(50 + i, std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
319 TEST_F(ExpiryTimerTest, AllTasksAreCancelledAfterTimerDestroyed)
322 ExpiryTimer localTimer;
323 FunctionObject* functor = mocks.Mock< FunctionObject >();
325 mocks.NeverCall(functor, FunctionObject::execute);
328 std::bind(&FunctionObject::execute, functor, std::placeholders::_1));