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)
149 Name: Controller_InitSimple
150 Description: tests initialization of simple int controller
151 Expected: no exceptions
153 RUNNER_TEST(Controller_InitSimple)
155 IntController controller;
157 RUNNER_ASSERT(controller.Value() == -1);
161 Name: Controller_InitStrange
162 Description: tests initialization of struct controller
163 Expected: no exceptions
165 RUNNER_TEST(Controller_InitStrange)
167 StrangeController controller;
172 Name: Controller_PostEventToThread
173 Description: tests post events to other thread
174 Expected: thread id gathered in event handling method should match id of created thread
176 RUNNER_TEST(Controller_PostEventToThread)
178 ThreadController controller;
184 controller.SwitchToThread(&thread);
186 DPL::WaitableEvent waitHandle;
188 controller.PostEvent(DoneSignalEvent(&waitHandle));
190 DPL::WaitForSingleHandle(waitHandle.GetHandle());
192 controller.SwitchToThread(NULL);
194 RUNNER_ASSERT(controller.Value() == &thread);
198 Name: Controller_PostTimedEventToThread
199 Description: tests post events to other thread with time delay
200 Expected: thread id gathered in event handling method should match id of created thread
202 RUNNER_TEST(Controller_PostTimedEventToThread)
204 ThreadController controller;
210 controller.SwitchToThread(&thread);
212 DPL::WaitableEvent waitHandle;
214 controller.PostTimedEvent(DoneSignalEvent(&waitHandle), 0.5);
216 DPL::WaitForSingleHandle(waitHandle.GetHandle());
218 controller.SwitchToThread(NULL);
220 RUNNER_ASSERT(controller.Value() == &thread);
223 DECLARE_GENERIC_EVENT_2(TouchInThread, DPL::WaitableEvent *, DPL::Thread * *)
224 DECLARE_GENERIC_EVENT_2(TouchedControllerSignal,
225 DPL::WaitableEvent *,
228 class TouchInThreadController :
229 public DPL::Event::Controller<DPL::TypeListDecl<TouchInThread>::Type>,
230 private DPL::Event::Controller<DPL::TypeListDecl<TouchedControllerSignal>::
234 typedef DPL::Event::Controller<DPL::TypeListDecl<TouchInThread>::Type>
236 typedef DPL::Event::Controller<DPL::TypeListDecl<TouchedControllerSignal>::
237 Type> PrivateController;
239 virtual void OnEventReceived(const TouchInThread &event)
241 // Touch controller in thread
242 PrivateController::Touch();
245 PrivateController::PostEvent(TouchedControllerSignal(event.GetArg0(),
249 virtual void OnEventReceived(const TouchedControllerSignal &event)
251 // Return touched thread
252 *event.GetArg1() = DPL::Thread::GetCurrentThread();
254 // Signal waitable event
255 event.GetArg0()->Signal();
260 Name: Controller_TouchInThread
261 Description: tests ability to touch (initizilize / set destination thread) in creatd thread
262 other than thread were controlelr object was created
263 Expected: thread id gathered in event handling method should match id of created thread
265 RUNNER_TEST(Controller_TouchInThread)
267 TouchInThreadController controller;
268 controller.PublicController::Touch();
273 controller.PublicController::SwitchToThread(&thread);
275 DPL::WaitableEvent waitHandle;
276 DPL::Thread *touchedThread = NULL;
278 controller.PublicController::PostEvent(TouchInThread(&waitHandle,
281 DPL::WaitForSingleHandle(waitHandle.GetHandle());
283 controller.PublicController::SwitchToThread(NULL);
285 RUNNER_ASSERT(touchedThread == &thread);
289 Name: Controller_SynchronizedEvent
290 Description: tests ability to post synchronized events to ther thread
291 Expected: correct value should be saved when event was handled
293 RUNNER_TEST(Controller_SynchronizedEvent)
295 IntController controller;
301 controller.SwitchToThread(&thread);
302 controller.PostSyncEvent(12345);
303 controller.SwitchToThread(NULL);
305 RUNNER_ASSERT(controller.Value() == 12345);
308 const int ControllersNumber = 5;
309 const int MaxEventsPerController = 1;
310 const int MaxEvents = ControllersNumber * MaxEventsPerController;
311 const int ControllersPerThread = 1;
313 class TestController; //Forward Declaration
315 typedef std::shared_ptr<TestController> ControllerPtr;
316 typedef std::shared_ptr<DPL::Thread> ThreadPtr;
317 typedef std::vector<ControllerPtr> ControllerList;
318 typedef std::list<ThreadPtr> ThreadList;
320 DECLARE_GENERIC_EVENT_0(QuitEvent)
321 class QuitController :
322 public DPL::Event::Controller<DPL::TypeListDecl<QuitEvent>::Type>,
323 public DPL::ApplicationExt
326 explicit QuitController() : DPL::ApplicationExt(1, NULL, "test-app")
332 virtual void OnEventReceived(const QuitEvent &)
340 ControllerList controllers;
342 QuitController quitter;
343 DPL::Atomic g_ReceivedCounter;
344 DPL::Atomic g_SentCounter;
346 typedef std::unique_ptr<TestContext> TestContextPtr;
347 TestContextPtr testContextPtr;
349 DECLARE_GENERIC_EVENT_0(StartSendEvent)
350 DECLARE_GENERIC_EVENT_0(RandomEvent)
351 class TestController :
352 public DPL::Event::Controller<DPL::TypeListDecl<RandomEvent,
353 StartSendEvent>::Type>
356 explicit TestController()
362 virtual void OnEventReceived(const RandomEvent &)
364 ++testContextPtr->g_ReceivedCounter;
365 if (testContextPtr->g_ReceivedCounter == MaxEvents) {
366 testContextPtr->quitter.DPL::Event::ControllerEventHandler<
367 QuitEvent>::PostEvent(QuitEvent());
371 virtual void OnEventReceived(const StartSendEvent &)
373 for (int i = 0; i < MaxEventsPerController; ++i) {
374 if (testContextPtr->g_SentCounter > MaxEvents) {
377 ++testContextPtr->g_SentCounter;
378 int id = rand() % static_cast<int>(testContextPtr->controllers.size());
379 testContextPtr->controllers.at(id)->DPL::Event::
380 ControllerEventHandler<RandomEvent>::PostEvent(RandomEvent());
386 Name: Controllers_MultipleEvents
387 Description: tests controller coooperation.
388 This runs many controllers in many threads. Each controller sends
389 to other randomly chosen controller events.
390 Expected: Test is supposed to be ended when all limits of sent event will be reach
391 -> all scheduled event will be sent and received.
393 RUNNER_TEST(Controllers_MultipleEvents)
397 testContextPtr.reset(new TestContext());
398 testContextPtr->controllers.reserve(ControllersNumber);
400 for (int i = 0; i < ControllersNumber; ++i) {
401 if (testContextPtr->controllers.size() % ControllersPerThread == 0) {
402 ThreadPtr thread = ThreadPtr(new DPL::Thread());
403 testContextPtr->threads.push_back(thread);
407 ControllerPtr controller = ControllerPtr(new TestController());
408 testContextPtr->controllers.push_back(controller);
409 if (testContextPtr->controllers.size() % 2 == 0) {
410 //This controller is being switched to thread (otherwise it is
411 // touched to main thread)
412 ThreadPtr thread = testContextPtr->threads.back();
413 controller->SwitchToThread(thread.get());
415 controller->DPL::Event::ControllerEventHandler<StartSendEvent>::
416 PostEvent(StartSendEvent());
418 testContextPtr->quitter.Exec();
420 testContextPtr->g_SentCounter == testContextPtr->g_ReceivedCounter);
421 testContextPtr.reset();