2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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 * @file test_controller.cpp
18 * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
20 * @brief This file is the implementation file of test controller
22 #include <dpl/test/test_runner.h>
23 #include <dpl/event/controller.h>
24 #include <dpl/thread.h>
25 #include <dpl/generic_event.h>
26 #include <dpl/waitable_handle.h>
27 #include <dpl/waitable_event.h>
28 #include <dpl/type_list.h>
29 #include <dpl/application.h>
30 #include <dpl/atomic.h>
35 RUNNER_TEST_GROUP_INIT(DPL)
38 public DPL::Event::Controller<DPL::TypeListDecl<int>::Type>
44 virtual void OnEventReceived(const int &event)
60 DECLARE_GENERIC_EVENT_1(DoneSignalEvent, DPL::WaitableEvent *)
62 class ThreadController :
63 public DPL::Event::Controller<DPL::TypeListDecl<DoneSignalEvent>::Type>
69 virtual void OnEventReceived(const DoneSignalEvent &event)
71 m_value = DPL::Thread::GetCurrentThread();
72 event.GetArg0()->Signal();
80 DPL::Thread *Value() const
93 class StrangeController :
94 public DPL::Event::Controller<DPL::TypeListDecl<char, short, int, long,
97 unsigned int, unsigned long,
102 virtual void OnEventReceived(const char &event)
106 virtual void OnEventReceived(const short &event)
110 virtual void OnEventReceived(const int &event)
114 virtual void OnEventReceived(const long &event)
118 virtual void OnEventReceived(const unsigned char &event)
122 virtual void OnEventReceived(const unsigned short &event)
126 virtual void OnEventReceived(const unsigned int &event)
130 virtual void OnEventReceived(const unsigned long &event)
134 virtual void OnEventReceived(const float &event)
138 virtual void OnEventReceived(const double &event)
142 virtual void OnEventReceived(const StrangeStruct &event)
148 RUNNER_TEST(Controller_InitSimple)
150 IntController controller;
152 RUNNER_ASSERT(controller.Value() == -1);
155 RUNNER_TEST(Controller_InitStrange)
157 StrangeController controller;
161 RUNNER_TEST(Controller_PostEventToThread)
163 ThreadController controller;
169 controller.SwitchToThread(&thread);
171 DPL::WaitableEvent waitHandle;
173 controller.PostEvent(DoneSignalEvent(&waitHandle));
175 DPL::WaitForSingleHandle(waitHandle.GetHandle());
177 controller.SwitchToThread(NULL);
179 RUNNER_ASSERT(controller.Value() == &thread);
182 RUNNER_TEST(Controller_PostTimedEventToThread)
184 ThreadController controller;
190 controller.SwitchToThread(&thread);
192 DPL::WaitableEvent waitHandle;
194 controller.PostTimedEvent(DoneSignalEvent(&waitHandle), 0.5);
196 DPL::WaitForSingleHandle(waitHandle.GetHandle());
198 controller.SwitchToThread(NULL);
200 RUNNER_ASSERT(controller.Value() == &thread);
203 DECLARE_GENERIC_EVENT_2(TouchInThread, DPL::WaitableEvent *, DPL::Thread * *)
204 DECLARE_GENERIC_EVENT_2(TouchedControllerSignal,
205 DPL::WaitableEvent *,
208 class TouchInThreadController :
209 public DPL::Event::Controller<DPL::TypeListDecl<TouchInThread>::Type>,
210 private DPL::Event::Controller<DPL::TypeListDecl<TouchedControllerSignal>::
214 typedef DPL::Event::Controller<DPL::TypeListDecl<TouchInThread>::Type>
216 typedef DPL::Event::Controller<DPL::TypeListDecl<TouchedControllerSignal>::
217 Type> PrivateController;
219 virtual void OnEventReceived(const TouchInThread &event)
221 // Touch controller in thread
222 PrivateController::Touch();
225 PrivateController::PostEvent(TouchedControllerSignal(event.GetArg0(),
229 virtual void OnEventReceived(const TouchedControllerSignal &event)
231 // Return touched thread
232 *event.GetArg1() = DPL::Thread::GetCurrentThread();
234 // Signal waitable event
235 event.GetArg0()->Signal();
239 RUNNER_TEST(Controller_TouchInThread)
241 TouchInThreadController controller;
242 controller.PublicController::Touch();
247 controller.PublicController::SwitchToThread(&thread);
249 DPL::WaitableEvent waitHandle;
250 DPL::Thread *touchedThread = NULL;
252 controller.PublicController::PostEvent(TouchInThread(&waitHandle,
255 DPL::WaitForSingleHandle(waitHandle.GetHandle());
257 controller.PublicController::SwitchToThread(NULL);
259 RUNNER_ASSERT(touchedThread == &thread);
262 RUNNER_TEST(Controller_SynchronizedEvent)
264 IntController controller;
270 controller.SwitchToThread(&thread);
271 controller.PostSyncEvent(12345);
272 controller.SwitchToThread(NULL);
274 RUNNER_ASSERT(controller.Value() == 12345);
277 const int ControllersNumber = 5;
278 const int MaxEventsPerController = 1;
279 const int MaxEvents = ControllersNumber * MaxEventsPerController;
280 const int ControllersPerThread = 1;
282 class TestController; //Forward Declaration
284 typedef std::shared_ptr<TestController> ControllerPtr;
285 typedef std::shared_ptr<DPL::Thread> ThreadPtr;
286 typedef std::vector<ControllerPtr> ControllerList;
287 typedef std::list<ThreadPtr> ThreadList;
289 DECLARE_GENERIC_EVENT_0(QuitEvent)
290 class QuitController :
291 public DPL::Event::Controller<DPL::TypeListDecl<QuitEvent>::Type>,
292 public DPL::ApplicationExt
295 explicit QuitController() : DPL::ApplicationExt(1, NULL, "test-app")
301 virtual void OnEventReceived(const QuitEvent &)
309 ControllerList controllers;
311 QuitController quitter;
312 DPL::Atomic g_ReceivedCounter;
313 DPL::Atomic g_SentCounter;
315 typedef std::unique_ptr<TestContext> TestContextPtr;
316 TestContextPtr testContextPtr;
318 DECLARE_GENERIC_EVENT_0(StartSendEvent)
319 DECLARE_GENERIC_EVENT_0(RandomEvent)
320 class TestController :
321 public DPL::Event::Controller<DPL::TypeListDecl<RandomEvent,
322 StartSendEvent>::Type>
325 explicit TestController()
331 virtual void OnEventReceived(const RandomEvent &)
333 ++testContextPtr->g_ReceivedCounter;
334 if (testContextPtr->g_ReceivedCounter == MaxEvents) {
335 testContextPtr->quitter.DPL::Event::ControllerEventHandler<
336 QuitEvent>::PostEvent(QuitEvent());
340 virtual void OnEventReceived(const StartSendEvent &)
342 for (int i = 0; i < MaxEventsPerController; ++i) {
343 if (testContextPtr->g_SentCounter > MaxEvents) {
346 ++testContextPtr->g_SentCounter;
347 int id = rand() % static_cast<int>(testContextPtr->controllers.size());
348 testContextPtr->controllers.at(id)->DPL::Event::
349 ControllerEventHandler<RandomEvent>::PostEvent(RandomEvent());
354 RUNNER_TEST(Controllers_MultipleEvents)
358 testContextPtr.reset(new TestContext());
359 testContextPtr->controllers.reserve(ControllersNumber);
361 for (int i = 0; i < ControllersNumber; ++i) {
362 if (testContextPtr->controllers.size() % ControllersPerThread == 0) {
363 ThreadPtr thread = ThreadPtr(new DPL::Thread());
364 testContextPtr->threads.push_back(thread);
368 ControllerPtr controller = ControllerPtr(new TestController());
369 testContextPtr->controllers.push_back(controller);
370 if (testContextPtr->controllers.size() % 2 == 0) {
371 //This controller is being switched to thread (otherwise it is
372 // touched to main thread)
373 ThreadPtr thread = testContextPtr->threads.back();
374 controller->SwitchToThread(thread.get());
376 controller->DPL::Event::ControllerEventHandler<StartSendEvent>::
377 PostEvent(StartSendEvent());
379 testContextPtr->quitter.Exec();
381 testContextPtr->g_SentCounter == testContextPtr->g_ReceivedCounter);
382 testContextPtr.reset();