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)
61 DECLARE_GENERIC_EVENT_1(DoneSignalEvent, DPL::WaitableEvent *)
63 class ThreadController
64 : public DPL::Event::Controller<DPL::TypeListDecl<DoneSignalEvent>::Type>
70 virtual void OnEventReceived(const DoneSignalEvent &event)
72 m_value = DPL::Thread::GetCurrentThread();
73 event.GetArg0()->Signal();
82 DPL::Thread *Value() const
95 class StrangeController
96 : public DPL::Event::Controller<DPL::TypeListDecl<char, short, int, long,
97 unsigned char, unsigned short, unsigned int, unsigned long,
98 float, double, StrangeStruct>::Type>
101 virtual void OnEventReceived(const char &event) { (void)event; }
102 virtual void OnEventReceived(const short &event) { (void)event; }
103 virtual void OnEventReceived(const int &event) { (void)event; }
104 virtual void OnEventReceived(const long &event) { (void)event; }
105 virtual void OnEventReceived(const unsigned char &event) { (void)event; }
106 virtual void OnEventReceived(const unsigned short &event) { (void)event; }
107 virtual void OnEventReceived(const unsigned int &event) { (void)event; }
108 virtual void OnEventReceived(const unsigned long &event) { (void)event; }
109 virtual void OnEventReceived(const float &event) { (void)event; }
110 virtual void OnEventReceived(const double &event) { (void)event; }
111 virtual void OnEventReceived(const StrangeStruct &event) { (void)event; }
114 RUNNER_TEST(Controller_InitSimple)
116 IntController controller;
118 RUNNER_ASSERT(controller.Value() == -1);
121 RUNNER_TEST(Controller_InitStrange)
123 StrangeController controller;
127 RUNNER_TEST(Controller_PostEventToThread)
129 ThreadController controller;
135 controller.SwitchToThread(&thread);
137 DPL::WaitableEvent waitHandle;
139 controller.PostEvent(DoneSignalEvent(&waitHandle));
141 DPL::WaitForSingleHandle(waitHandle.GetHandle());
143 controller.SwitchToThread(NULL);
145 RUNNER_ASSERT(controller.Value() == &thread);
148 RUNNER_TEST(Controller_PostTimedEventToThread)
150 ThreadController controller;
156 controller.SwitchToThread(&thread);
158 DPL::WaitableEvent waitHandle;
160 controller.PostTimedEvent(DoneSignalEvent(&waitHandle), 0.5);
162 DPL::WaitForSingleHandle(waitHandle.GetHandle());
164 controller.SwitchToThread(NULL);
166 RUNNER_ASSERT(controller.Value() == &thread);
169 DECLARE_GENERIC_EVENT_2(TouchInThread, DPL::WaitableEvent *, DPL::Thread **)
170 DECLARE_GENERIC_EVENT_2(TouchedControllerSignal, DPL::WaitableEvent *, DPL::Thread **)
172 class TouchInThreadController
173 : public DPL::Event::Controller<DPL::TypeListDecl<TouchInThread>::Type>,
174 private DPL::Event::Controller<DPL::TypeListDecl<TouchedControllerSignal>::Type>
177 typedef DPL::Event::Controller<DPL::TypeListDecl<TouchInThread>::Type> PublicController;
178 typedef DPL::Event::Controller<DPL::TypeListDecl<TouchedControllerSignal>::Type> PrivateController;
180 virtual void OnEventReceived(const TouchInThread &event)
182 // Touch controller in thread
183 PrivateController::Touch();
186 PrivateController::PostEvent(TouchedControllerSignal(event.GetArg0(), event.GetArg1()));
189 virtual void OnEventReceived(const TouchedControllerSignal &event)
191 // Return touched thread
192 *event.GetArg1() = DPL::Thread::GetCurrentThread();
194 // Signal waitable event
195 event.GetArg0()->Signal();
199 RUNNER_TEST(Controller_TouchInThread)
201 TouchInThreadController controller;
202 controller.PublicController::Touch();
207 controller.PublicController::SwitchToThread(&thread);
209 DPL::WaitableEvent waitHandle;
210 DPL::Thread *touchedThread = NULL;
212 controller.PublicController::PostEvent(TouchInThread(&waitHandle, &touchedThread));
214 DPL::WaitForSingleHandle(waitHandle.GetHandle());
216 controller.PublicController::SwitchToThread(NULL);
218 RUNNER_ASSERT(touchedThread == &thread);
221 RUNNER_TEST(Controller_SynchronizedEvent)
223 IntController controller;
229 controller.SwitchToThread(&thread);
230 controller.PostSyncEvent(12345);
231 controller.SwitchToThread(NULL);
233 RUNNER_ASSERT(controller.Value() == 12345);
236 const int ControllersNumber = 5;
237 const int MaxEventsPerController = 1;
238 const int MaxEvents = ControllersNumber * MaxEventsPerController;
239 const int ControllersPerThread = 1;
241 class TestController; //Forward Declaration
243 typedef std::shared_ptr<TestController> ControllerPtr;
244 typedef std::shared_ptr<DPL::Thread> ThreadPtr;
245 typedef std::vector<ControllerPtr> ControllerList;
246 typedef std::list<ThreadPtr> ThreadList;
248 DECLARE_GENERIC_EVENT_0(QuitEvent)
250 : public DPL::Event::Controller<DPL::TypeListDecl<QuitEvent>::Type>,
251 public DPL::ApplicationExt
254 explicit QuitController( ) : DPL::ApplicationExt(1, NULL, "test-app") { Touch(); }
256 virtual void OnEventReceived(const QuitEvent &) { Quit(); }
261 ControllerList controllers;
263 QuitController quitter;
264 DPL::Atomic g_ReceivedCounter;
265 DPL::Atomic g_SentCounter;
267 typedef std::unique_ptr<TestContext> TestContextPtr;
268 TestContextPtr testContextPtr;
270 DECLARE_GENERIC_EVENT_0(StartSendEvent)
271 DECLARE_GENERIC_EVENT_0(RandomEvent)
273 : public DPL::Event::Controller<DPL::TypeListDecl<RandomEvent, StartSendEvent>::Type>
276 explicit TestController() { Touch(); }
278 virtual void OnEventReceived(const RandomEvent &)
280 ++testContextPtr->g_ReceivedCounter;
281 if(testContextPtr->g_ReceivedCounter == MaxEvents)
283 testContextPtr->quitter.DPL::Event::ControllerEventHandler<QuitEvent>::PostEvent(QuitEvent());
287 virtual void OnEventReceived(const StartSendEvent &)
289 for (int i=0 ; i<MaxEventsPerController ;++i)
291 if(testContextPtr->g_SentCounter > MaxEvents)
295 ++testContextPtr->g_SentCounter;
296 int id = rand() % static_cast<int>(testContextPtr->controllers.size());
297 testContextPtr->controllers.at(id)->DPL::Event::ControllerEventHandler<RandomEvent>::PostEvent(RandomEvent());
302 RUNNER_TEST(Controllers_MultipleEvents)
304 srand ( time(NULL) );
306 testContextPtr.reset(new TestContext());
307 testContextPtr->controllers.reserve(ControllersNumber);
309 for (int i = 0; i < ControllersNumber ; ++i)
311 if(testContextPtr->controllers.size() % ControllersPerThread ==0)
313 ThreadPtr thread = ThreadPtr(new DPL::Thread());
314 testContextPtr->threads.push_back(thread);
318 ControllerPtr controller = ControllerPtr(new TestController());
319 testContextPtr->controllers.push_back(controller);
320 if(testContextPtr->controllers.size() % 2 == 0)
322 //This controller is being switched to thread (otherwise it is touched to main thread)
323 ThreadPtr thread = testContextPtr->threads.back();
324 controller->SwitchToThread(thread.get());
326 controller->DPL::Event::ControllerEventHandler<StartSendEvent>::PostEvent(StartSendEvent());
328 testContextPtr->quitter.Exec();
329 RUNNER_ASSERT(testContextPtr->g_SentCounter == testContextPtr->g_ReceivedCounter);
330 testContextPtr.reset();