Source code formating unification
[framework/web/wrt-commons.git] / tests / dpl / event / test_controller.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 /*
17  * @file        test_controller.cpp
18  * @author      Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
19  * @version     1.0
20  * @brief       This file is the implementation file of test controller
21  */
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>
31 #include <list>
32 #include <vector>
33 #include <memory>
34
35 RUNNER_TEST_GROUP_INIT(DPL)
36
37 class IntController :
38     public DPL::Event::Controller<DPL::TypeListDecl<int>::Type>
39 {
40   private:
41     int m_value;
42
43   protected:
44     virtual void OnEventReceived(const int &event)
45     {
46         m_value = event;
47     }
48
49   public:
50     IntController() :
51         m_value(-1)
52     {}
53
54     int Value() const
55     {
56         return m_value;
57     }
58 };
59
60 DECLARE_GENERIC_EVENT_1(DoneSignalEvent, DPL::WaitableEvent *)
61
62 class ThreadController :
63     public DPL::Event::Controller<DPL::TypeListDecl<DoneSignalEvent>::Type>
64 {
65   private:
66     DPL::Thread *m_value;
67
68   protected:
69     virtual void OnEventReceived(const DoneSignalEvent &event)
70     {
71         m_value = DPL::Thread::GetCurrentThread();
72         event.GetArg0()->Signal();
73     }
74
75   public:
76     ThreadController() :
77         m_value(NULL)
78     {}
79
80     DPL::Thread *Value() const
81     {
82         return m_value;
83     }
84 };
85
86 struct StrangeStruct
87 {
88     int a;
89     float b;
90     double c;
91 };
92
93 class StrangeController :
94     public DPL::Event::Controller<DPL::TypeListDecl<char, short, int, long,
95                                                     unsigned char,
96                                                     unsigned short,
97                                                     unsigned int, unsigned long,
98                                                     float, double,
99                                                     StrangeStruct>::Type>
100 {
101   protected:
102     virtual void OnEventReceived(const char &event)
103     {
104         (void)event;
105     }
106     virtual void OnEventReceived(const short &event)
107     {
108         (void)event;
109     }
110     virtual void OnEventReceived(const int &event)
111     {
112         (void)event;
113     }
114     virtual void OnEventReceived(const long &event)
115     {
116         (void)event;
117     }
118     virtual void OnEventReceived(const unsigned char &event)
119     {
120         (void)event;
121     }
122     virtual void OnEventReceived(const unsigned short &event)
123     {
124         (void)event;
125     }
126     virtual void OnEventReceived(const unsigned int &event)
127     {
128         (void)event;
129     }
130     virtual void OnEventReceived(const unsigned long &event)
131     {
132         (void)event;
133     }
134     virtual void OnEventReceived(const float &event)
135     {
136         (void)event;
137     }
138     virtual void OnEventReceived(const double &event)
139     {
140         (void)event;
141     }
142     virtual void OnEventReceived(const StrangeStruct &event)
143     {
144         (void)event;
145     }
146 };
147
148 RUNNER_TEST(Controller_InitSimple)
149 {
150     IntController controller;
151     controller.Touch();
152     RUNNER_ASSERT(controller.Value() == -1);
153 }
154
155 RUNNER_TEST(Controller_InitStrange)
156 {
157     StrangeController controller;
158     controller.Touch();
159 }
160
161 RUNNER_TEST(Controller_PostEventToThread)
162 {
163     ThreadController controller;
164     controller.Touch();
165
166     DPL::Thread thread;
167     thread.Run();
168
169     controller.SwitchToThread(&thread);
170
171     DPL::WaitableEvent waitHandle;
172
173     controller.PostEvent(DoneSignalEvent(&waitHandle));
174
175     DPL::WaitForSingleHandle(waitHandle.GetHandle());
176
177     controller.SwitchToThread(NULL);
178
179     RUNNER_ASSERT(controller.Value() == &thread);
180 }
181
182 RUNNER_TEST(Controller_PostTimedEventToThread)
183 {
184     ThreadController controller;
185     controller.Touch();
186
187     DPL::Thread thread;
188     thread.Run();
189
190     controller.SwitchToThread(&thread);
191
192     DPL::WaitableEvent waitHandle;
193
194     controller.PostTimedEvent(DoneSignalEvent(&waitHandle), 0.5);
195
196     DPL::WaitForSingleHandle(waitHandle.GetHandle());
197
198     controller.SwitchToThread(NULL);
199
200     RUNNER_ASSERT(controller.Value() == &thread);
201 }
202
203 DECLARE_GENERIC_EVENT_2(TouchInThread, DPL::WaitableEvent *, DPL::Thread * *)
204 DECLARE_GENERIC_EVENT_2(TouchedControllerSignal,
205                         DPL::WaitableEvent *,
206                         DPL::Thread * *)
207
208 class TouchInThreadController :
209     public DPL::Event::Controller<DPL::TypeListDecl<TouchInThread>::Type>,
210     private DPL::Event::Controller<DPL::TypeListDecl<TouchedControllerSignal>::
211                                        Type>
212 {
213   public:
214     typedef DPL::Event::Controller<DPL::TypeListDecl<TouchInThread>::Type>
215     PublicController;
216     typedef DPL::Event::Controller<DPL::TypeListDecl<TouchedControllerSignal>::
217                                        Type> PrivateController;
218
219     virtual void OnEventReceived(const TouchInThread &event)
220     {
221         // Touch controller in thread
222         PrivateController::Touch();
223
224         // Post signal
225         PrivateController::PostEvent(TouchedControllerSignal(event.GetArg0(),
226                                                              event.GetArg1()));
227     }
228
229     virtual void OnEventReceived(const TouchedControllerSignal &event)
230     {
231         // Return touched thread
232         *event.GetArg1() = DPL::Thread::GetCurrentThread();
233
234         // Signal waitable event
235         event.GetArg0()->Signal();
236     }
237 };
238
239 RUNNER_TEST(Controller_TouchInThread)
240 {
241     TouchInThreadController controller;
242     controller.PublicController::Touch();
243
244     DPL::Thread thread;
245     thread.Run();
246
247     controller.PublicController::SwitchToThread(&thread);
248
249     DPL::WaitableEvent waitHandle;
250     DPL::Thread *touchedThread = NULL;
251
252     controller.PublicController::PostEvent(TouchInThread(&waitHandle,
253                                                          &touchedThread));
254
255     DPL::WaitForSingleHandle(waitHandle.GetHandle());
256
257     controller.PublicController::SwitchToThread(NULL);
258
259     RUNNER_ASSERT(touchedThread == &thread);
260 }
261
262 RUNNER_TEST(Controller_SynchronizedEvent)
263 {
264     IntController controller;
265     controller.Touch();
266
267     DPL::Thread thread;
268     thread.Run();
269
270     controller.SwitchToThread(&thread);
271     controller.PostSyncEvent(12345);
272     controller.SwitchToThread(NULL);
273
274     RUNNER_ASSERT(controller.Value() == 12345);
275 }
276
277 const int ControllersNumber = 5;
278 const int MaxEventsPerController = 1;
279 const int MaxEvents = ControllersNumber * MaxEventsPerController;
280 const int ControllersPerThread = 1;
281
282 class TestController; //Forward Declaration
283
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;
288
289 DECLARE_GENERIC_EVENT_0(QuitEvent)
290 class QuitController :
291     public DPL::Event::Controller<DPL::TypeListDecl<QuitEvent>::Type>,
292     public DPL::ApplicationExt
293 {
294   public:
295     explicit QuitController() : DPL::ApplicationExt(1, NULL, "test-app")
296     {
297         Touch();
298     }
299
300   protected:
301     virtual void OnEventReceived(const QuitEvent &)
302     {
303         Quit();
304     }
305 };
306
307 struct TestContext
308 {
309     ControllerList controllers;
310     ThreadList threads;
311     QuitController quitter;
312     DPL::Atomic g_ReceivedCounter;
313     DPL::Atomic g_SentCounter;
314 };
315 typedef std::unique_ptr<TestContext> TestContextPtr;
316 TestContextPtr testContextPtr;
317
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>
323 {
324   public:
325     explicit TestController()
326     {
327         Touch();
328     }
329
330   protected:
331     virtual void OnEventReceived(const RandomEvent &)
332     {
333         ++testContextPtr->g_ReceivedCounter;
334         if (testContextPtr->g_ReceivedCounter == MaxEvents) {
335             testContextPtr->quitter.DPL::Event::ControllerEventHandler<
336                 QuitEvent>::PostEvent(QuitEvent());
337             return;
338         }
339     }
340     virtual void OnEventReceived(const StartSendEvent &)
341     {
342         for (int i = 0; i < MaxEventsPerController; ++i) {
343             if (testContextPtr->g_SentCounter > MaxEvents) {
344                 return;
345             }
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());
350         }
351     }
352 };
353
354 RUNNER_TEST(Controllers_MultipleEvents)
355 {
356     srand(time(NULL) );
357
358     testContextPtr.reset(new TestContext());
359     testContextPtr->controllers.reserve(ControllersNumber);
360
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);
365             thread->Run();
366         }
367
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());
375         }
376         controller->DPL::Event::ControllerEventHandler<StartSendEvent>::
377             PostEvent(StartSendEvent());
378     }
379     testContextPtr->quitter.Exec();
380     RUNNER_ASSERT(
381         testContextPtr->g_SentCounter == testContextPtr->g_ReceivedCounter);
382     testContextPtr.reset();
383 }