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 unsigned int seed = time(NULL);
42 public DPL::Event::Controller<DPL::TypeListDecl<int>::Type>
48 virtual void OnEventReceived(const int &event)
64 DECLARE_GENERIC_EVENT_1(DoneSignalEvent, DPL::WaitableEvent *)
66 class ThreadController :
67 public DPL::Event::Controller<DPL::TypeListDecl<DoneSignalEvent>::Type>
73 virtual void OnEventReceived(const DoneSignalEvent &event)
75 m_value = DPL::Thread::GetCurrentThread();
76 event.GetArg0()->Signal();
84 DPL::Thread *Value() const
97 class StrangeController :
98 public DPL::Event::Controller<DPL::TypeListDecl<char, short, int, long,
101 unsigned int, unsigned long,
103 StrangeStruct>::Type>
106 virtual void OnEventReceived(const char &event)
110 virtual void OnEventReceived(const short &event)
114 virtual void OnEventReceived(const int &event)
118 virtual void OnEventReceived(const long &event)
122 virtual void OnEventReceived(const unsigned char &event)
126 virtual void OnEventReceived(const unsigned short &event)
130 virtual void OnEventReceived(const unsigned int &event)
134 virtual void OnEventReceived(const unsigned long &event)
138 virtual void OnEventReceived(const float &event)
142 virtual void OnEventReceived(const double &event)
146 virtual void OnEventReceived(const StrangeStruct &event)
153 Name: Controller_InitSimple
154 Description: tests initialization of simple int controller
155 Expected: no exceptions
157 RUNNER_TEST(Controller_InitSimple)
159 IntController controller;
161 RUNNER_ASSERT(controller.Value() == -1);
165 Name: Controller_InitStrange
166 Description: tests initialization of struct controller
167 Expected: no exceptions
169 RUNNER_TEST(Controller_InitStrange)
171 StrangeController controller;
176 Name: Controller_PostEventToThread
177 Description: tests post events to other thread
178 Expected: thread id gathered in event handling method should match id of created thread
180 RUNNER_TEST(Controller_PostEventToThread)
182 ThreadController controller;
188 controller.SwitchToThread(&thread);
190 DPL::WaitableEvent waitHandle;
192 controller.PostEvent(DoneSignalEvent(&waitHandle));
194 DPL::WaitForSingleHandle(waitHandle.GetHandle());
196 controller.SwitchToThread(NULL);
198 RUNNER_ASSERT(controller.Value() == &thread);
202 Name: Controller_PostTimedEventToThread
203 Description: tests post events to other thread with time delay
204 Expected: thread id gathered in event handling method should match id of created thread
206 RUNNER_TEST(Controller_PostTimedEventToThread)
208 ThreadController controller;
214 controller.SwitchToThread(&thread);
216 DPL::WaitableEvent waitHandle;
218 controller.PostTimedEvent(DoneSignalEvent(&waitHandle), 0.5);
220 DPL::WaitForSingleHandle(waitHandle.GetHandle());
222 controller.SwitchToThread(NULL);
224 RUNNER_ASSERT(controller.Value() == &thread);
227 DECLARE_GENERIC_EVENT_2(TouchInThread, DPL::WaitableEvent *, DPL::Thread * *)
228 DECLARE_GENERIC_EVENT_2(TouchedControllerSignal,
229 DPL::WaitableEvent *,
232 class TouchInThreadController :
233 public DPL::Event::Controller<DPL::TypeListDecl<TouchInThread>::Type>,
234 private DPL::Event::Controller<DPL::TypeListDecl<TouchedControllerSignal>::
238 typedef DPL::Event::Controller<DPL::TypeListDecl<TouchInThread>::Type>
240 typedef DPL::Event::Controller<DPL::TypeListDecl<TouchedControllerSignal>::
241 Type> PrivateController;
243 virtual void OnEventReceived(const TouchInThread &event)
245 // Touch controller in thread
246 PrivateController::Touch();
249 PrivateController::PostEvent(TouchedControllerSignal(event.GetArg0(),
253 virtual void OnEventReceived(const TouchedControllerSignal &event)
255 // Return touched thread
256 *event.GetArg1() = DPL::Thread::GetCurrentThread();
258 // Signal waitable event
259 event.GetArg0()->Signal();
264 Name: Controller_TouchInThread
265 Description: tests ability to touch (initizilize / set destination thread) in creatd thread
266 other than thread were controlelr object was created
267 Expected: thread id gathered in event handling method should match id of created thread
269 RUNNER_TEST(Controller_TouchInThread)
271 TouchInThreadController controller;
272 controller.PublicController::Touch();
277 controller.PublicController::SwitchToThread(&thread);
279 DPL::WaitableEvent waitHandle;
280 DPL::Thread *touchedThread = NULL;
282 controller.PublicController::PostEvent(TouchInThread(&waitHandle,
285 DPL::WaitForSingleHandle(waitHandle.GetHandle());
287 controller.PublicController::SwitchToThread(NULL);
289 RUNNER_ASSERT(touchedThread == &thread);
293 Name: Controller_SynchronizedEvent
294 Description: tests ability to post synchronized events to ther thread
295 Expected: correct value should be saved when event was handled
297 RUNNER_TEST(Controller_SynchronizedEvent)
299 IntController controller;
305 controller.SwitchToThread(&thread);
306 controller.PostSyncEvent(12345);
307 controller.SwitchToThread(NULL);
309 RUNNER_ASSERT(controller.Value() == 12345);
312 const int ControllersNumber = 5;
313 const int MaxEventsPerController = 1;
314 const int MaxEvents = ControllersNumber * MaxEventsPerController;
315 const int ControllersPerThread = 1;
317 class TestController; //Forward Declaration
319 typedef std::shared_ptr<TestController> ControllerPtr;
320 typedef std::shared_ptr<DPL::Thread> ThreadPtr;
321 typedef std::vector<ControllerPtr> ControllerList;
322 typedef std::list<ThreadPtr> ThreadList;
324 DECLARE_GENERIC_EVENT_0(QuitEvent)
325 class QuitController :
326 public DPL::Event::Controller<DPL::TypeListDecl<QuitEvent>::Type>,
327 public DPL::ApplicationExt
330 explicit QuitController() : DPL::ApplicationExt(1, NULL, "test-app")
336 virtual void OnEventReceived(const QuitEvent &)
344 ControllerList controllers;
346 QuitController quitter;
347 DPL::Atomic g_ReceivedCounter;
348 DPL::Atomic g_SentCounter;
350 typedef std::unique_ptr<TestContext> TestContextPtr;
351 TestContextPtr testContextPtr;
353 DECLARE_GENERIC_EVENT_0(StartSendEvent)
354 DECLARE_GENERIC_EVENT_0(RandomEvent)
355 class TestController :
356 public DPL::Event::Controller<DPL::TypeListDecl<RandomEvent,
357 StartSendEvent>::Type>
360 explicit TestController()
366 virtual void OnEventReceived(const RandomEvent &)
368 ++testContextPtr->g_ReceivedCounter;
369 if (testContextPtr->g_ReceivedCounter == MaxEvents) {
370 testContextPtr->quitter.DPL::Event::ControllerEventHandler<
371 QuitEvent>::PostEvent(QuitEvent());
375 virtual void OnEventReceived(const StartSendEvent &)
377 for (int i = 0; i < MaxEventsPerController; ++i) {
378 if (testContextPtr->g_SentCounter > MaxEvents) {
381 ++testContextPtr->g_SentCounter;
382 int id = rand_r(&seed) % static_cast<int>(testContextPtr->controllers.size());
383 testContextPtr->controllers.at(id)->DPL::Event::
384 ControllerEventHandler<RandomEvent>::PostEvent(RandomEvent());
390 Name: Controllers_MultipleEvents
391 Description: tests controller coooperation.
392 This runs many controllers in many threads. Each controller sends
393 to other randomly chosen controller events.
394 Expected: Test is supposed to be ended when all limits of sent event will be reach
395 -> all scheduled event will be sent and received.
397 RUNNER_TEST(Controllers_MultipleEvents)
401 testContextPtr.reset(new TestContext());
402 testContextPtr->controllers.reserve(ControllersNumber);
404 for (int i = 0; i < ControllersNumber; ++i) {
405 if (testContextPtr->controllers.size() % ControllersPerThread == 0) {
406 ThreadPtr thread = ThreadPtr(new DPL::Thread());
407 testContextPtr->threads.push_back(thread);
411 ControllerPtr controller = ControllerPtr(new TestController());
412 testContextPtr->controllers.push_back(controller);
413 if (testContextPtr->controllers.size() % 2 == 0) {
414 //This controller is being switched to thread (otherwise it is
415 // touched to main thread)
416 ThreadPtr thread = testContextPtr->threads.back();
417 controller->SwitchToThread(thread.get());
419 controller->DPL::Event::ControllerEventHandler<StartSendEvent>::
420 PostEvent(StartSendEvent());
422 testContextPtr->quitter.Exec();
424 testContextPtr->g_SentCounter == testContextPtr->g_ReceivedCounter);
425 testContextPtr.reset();