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>
36 RUNNER_TEST_GROUP_INIT(DPL)
39 unsigned int seed = time(NULL);
43 public DPL::Event::Controller<DPL::TypeListDecl<int>::Type>
49 virtual void OnEventReceived(const int &event)
65 DECLARE_GENERIC_EVENT_1(DoneSignalEvent, DPL::WaitableEvent *)
67 class ThreadController :
68 public DPL::Event::Controller<DPL::TypeListDecl<DoneSignalEvent>::Type>
74 virtual void OnEventReceived(const DoneSignalEvent &event)
76 m_value = DPL::Thread::GetCurrentThread();
77 event.GetArg0()->Signal();
85 DPL::Thread *Value() const
98 class StrangeController :
99 public DPL::Event::Controller<DPL::TypeListDecl<char, short, int, long,
102 unsigned int, unsigned long,
104 StrangeStruct>::Type>
107 virtual void OnEventReceived(const char &event)
111 virtual void OnEventReceived(const short &event)
115 virtual void OnEventReceived(const int &event)
119 virtual void OnEventReceived(const long &event)
123 virtual void OnEventReceived(const unsigned char &event)
127 virtual void OnEventReceived(const unsigned short &event)
131 virtual void OnEventReceived(const unsigned int &event)
135 virtual void OnEventReceived(const unsigned long &event)
139 virtual void OnEventReceived(const float &event)
143 virtual void OnEventReceived(const double &event)
147 virtual void OnEventReceived(const StrangeStruct &event)
154 Name: Controller_InitSimple
155 Description: tests initialization of simple int controller
156 Expected: no exceptions
158 RUNNER_TEST(Controller_InitSimple)
160 IntController controller;
162 RUNNER_ASSERT(controller.Value() == -1);
166 Name: Controller_InitStrange
167 Description: tests initialization of struct controller
168 Expected: no exceptions
170 RUNNER_TEST(Controller_InitStrange)
172 StrangeController controller;
177 Name: Controller_PostEventToThread
178 Description: tests post events to other thread
179 Expected: thread id gathered in event handling method should match id of created thread
181 RUNNER_TEST(Controller_PostEventToThread)
183 ThreadController controller;
189 controller.SwitchToThread(&thread);
191 DPL::WaitableEvent waitHandle;
193 controller.PostEvent(DoneSignalEvent(&waitHandle));
195 DPL::WaitForSingleHandle(waitHandle.GetHandle());
197 controller.SwitchToThread(NULL);
199 RUNNER_ASSERT(controller.Value() == &thread);
203 Name: Controller_PostTimedEventToThread
204 Description: tests post events to other thread with time delay
205 Expected: thread id gathered in event handling method should match id of created thread
207 RUNNER_TEST(Controller_PostTimedEventToThread)
209 ThreadController controller;
215 controller.SwitchToThread(&thread);
217 DPL::WaitableEvent waitHandle;
219 controller.PostTimedEvent(DoneSignalEvent(&waitHandle), 0.5);
221 DPL::WaitForSingleHandle(waitHandle.GetHandle());
223 controller.SwitchToThread(NULL);
225 RUNNER_ASSERT(controller.Value() == &thread);
228 DECLARE_GENERIC_EVENT_2(TouchInThread, DPL::WaitableEvent *, DPL::Thread * *)
229 DECLARE_GENERIC_EVENT_2(TouchedControllerSignal,
230 DPL::WaitableEvent *,
233 class TouchInThreadController :
234 public DPL::Event::Controller<DPL::TypeListDecl<TouchInThread>::Type>,
235 private DPL::Event::Controller<DPL::TypeListDecl<TouchedControllerSignal>::
239 typedef DPL::Event::Controller<DPL::TypeListDecl<TouchInThread>::Type>
241 typedef DPL::Event::Controller<DPL::TypeListDecl<TouchedControllerSignal>::
242 Type> PrivateController;
244 virtual void OnEventReceived(const TouchInThread &event)
246 // Touch controller in thread
247 PrivateController::Touch();
250 PrivateController::PostEvent(TouchedControllerSignal(event.GetArg0(),
254 virtual void OnEventReceived(const TouchedControllerSignal &event)
256 // Return touched thread
257 *event.GetArg1() = DPL::Thread::GetCurrentThread();
259 // Signal waitable event
260 event.GetArg0()->Signal();
265 Name: Controller_TouchInThread
266 Description: tests ability to touch (initizilize / set destination thread) in creatd thread
267 other than thread were controlelr object was created
268 Expected: thread id gathered in event handling method should match id of created thread
270 RUNNER_TEST(Controller_TouchInThread)
272 TouchInThreadController controller;
273 controller.PublicController::Touch();
278 controller.PublicController::SwitchToThread(&thread);
280 DPL::WaitableEvent waitHandle;
281 DPL::Thread *touchedThread = NULL;
283 controller.PublicController::PostEvent(TouchInThread(&waitHandle,
286 DPL::WaitForSingleHandle(waitHandle.GetHandle());
288 controller.PublicController::SwitchToThread(NULL);
290 RUNNER_ASSERT(touchedThread == &thread);
294 Name: Controller_SynchronizedEvent
295 Description: tests ability to post synchronized events to ther thread
296 Expected: correct value should be saved when event was handled
298 RUNNER_TEST(Controller_SynchronizedEvent)
300 IntController controller;
306 controller.SwitchToThread(&thread);
307 controller.PostSyncEvent(12345);
308 controller.SwitchToThread(NULL);
310 RUNNER_ASSERT(controller.Value() == 12345);
313 const int ControllersNumber = 5;
314 const int MaxEventsPerController = 1;
315 const int MaxEvents = ControllersNumber * MaxEventsPerController;
316 const int ControllersPerThread = 1;
318 class TestController; //Forward Declaration
320 typedef std::shared_ptr<TestController> ControllerPtr;
321 typedef std::shared_ptr<DPL::Thread> ThreadPtr;
322 typedef std::vector<ControllerPtr> ControllerList;
323 typedef std::list<ThreadPtr> ThreadList;
325 DECLARE_GENERIC_EVENT_0(QuitEvent)
326 class QuitController :
327 public DPL::Event::Controller<DPL::TypeListDecl<QuitEvent>::Type>,
328 public DPL::ApplicationExt
331 explicit QuitController() : DPL::ApplicationExt(1, NULL, "test-app")
337 virtual void OnEventReceived(const QuitEvent &)
345 ControllerList controllers;
347 QuitController quitter;
348 std::atomic<int> g_ReceivedCounter;
349 std::atomic<int> g_SentCounter;
352 : g_ReceivedCounter(0)
357 typedef std::unique_ptr<TestContext> TestContextPtr;
358 TestContextPtr testContextPtr;
360 DECLARE_GENERIC_EVENT_0(StartSendEvent)
361 DECLARE_GENERIC_EVENT_0(RandomEvent)
362 class TestController :
363 public DPL::Event::Controller<DPL::TypeListDecl<RandomEvent,
364 StartSendEvent>::Type>
367 explicit TestController()
373 virtual void OnEventReceived(const RandomEvent &)
375 ++testContextPtr->g_ReceivedCounter;
376 if (testContextPtr->g_ReceivedCounter == MaxEvents) {
377 testContextPtr->quitter.DPL::Event::ControllerEventHandler<
378 QuitEvent>::PostEvent(QuitEvent());
382 virtual void OnEventReceived(const StartSendEvent &)
384 for (int i = 0; i < MaxEventsPerController; ++i) {
385 if (testContextPtr->g_SentCounter > MaxEvents) {
388 ++testContextPtr->g_SentCounter;
389 int id = rand_r(&seed) % static_cast<int>(testContextPtr->controllers.size());
390 testContextPtr->controllers.at(id)->DPL::Event::
391 ControllerEventHandler<RandomEvent>::PostEvent(RandomEvent());
397 Name: Controllers_MultipleEvents
398 Description: tests controller coooperation.
399 This runs many controllers in many threads. Each controller sends
400 to other randomly chosen controller events.
401 Expected: Test is supposed to be ended when all limits of sent event will be reach
402 -> all scheduled event will be sent and received.
404 RUNNER_TEST(Controllers_MultipleEvents)
408 testContextPtr.reset(new TestContext());
409 testContextPtr->controllers.reserve(ControllersNumber);
411 for (int i = 0; i < ControllersNumber; ++i) {
412 if (testContextPtr->controllers.size() % ControllersPerThread == 0) {
413 ThreadPtr thread = ThreadPtr(new DPL::Thread());
414 testContextPtr->threads.push_back(thread);
418 ControllerPtr controller = ControllerPtr(new TestController());
419 testContextPtr->controllers.push_back(controller);
420 if (testContextPtr->controllers.size() % 2 == 0) {
421 //This controller is being switched to thread (otherwise it is
422 // touched to main thread)
423 ThreadPtr thread = testContextPtr->threads.back();
424 controller->SwitchToThread(thread.get());
426 controller->DPL::Event::ControllerEventHandler<StartSendEvent>::
427 PostEvent(StartSendEvent());
429 testContextPtr->quitter.Exec();
431 testContextPtr->g_SentCounter == testContextPtr->g_ReceivedCounter);
432 testContextPtr.reset();