Source code formating unification
[framework/web/wrt-commons.git] / tests / dpl / event / test_ic_delegate.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_ic_delegate.cpp
18  * @author      Pawel Sikorski (p.sikorski@samsung.com)
19  * @author      Lukasz Wrzosek (l.wrzosek@samsung.com)
20  * @version     1.0
21  * @brief       This file is the implementation file of fast delegate tests.
22  */
23 #include <dpl/test/test_runner.h>
24 #include <dpl/application.h>
25 #include <dpl/event/controller.h>
26 #include <dpl/log/log.h>
27 #include <dpl/fast_delegate.h>
28 #include <dpl/event/inter_context_delegate.h>
29 #include <dpl/thread.h>
30 #include <dpl/waitable_event.h>
31 #include <dpl/assert.h>
32 #include <dpl/mutex.h>
33 #include <dpl/type_list.h>
34 #include <memory>
35 RUNNER_TEST_GROUP_INIT(DPL)
36
37 const int IntVal = 123;
38 const std::string StringVal = "someString";
39
40 typedef DPL::Event::ICDelegate<> GetNothingDlpType;
41 typedef DPL::Event::ICDelegate<int> GetIntDlgType;
42 typedef DPL::Event::ICDelegate<int, std::string> GetIntAndStringDlgType;
43 DECLARE_GENERIC_EVENT_1(GetNothingEvent, GetNothingDlpType)
44 DECLARE_GENERIC_EVENT_1(GetIntEvent, GetIntDlgType)
45 DECLARE_GENERIC_EVENT_1(GetIntAndStringEvent, GetIntAndStringDlgType)
46
47 class ICTestController :
48     public DPL::Event::Controller<DPL::TypeListDecl<GetNothingEvent,
49                                                     GetIntEvent,
50                                                     GetIntAndStringEvent>::Type>
51 {
52   public:
53     ICTestController() { }
54
55   protected:
56     virtual void OnEventReceived(const GetNothingEvent& event)
57     {
58         event.GetArg0() (); //calling intercontext delegate
59     }
60     virtual void OnEventReceived(const GetIntEvent& event)
61     {
62         event.GetArg0() (IntVal); //calling intercontext delegate
63     }
64
65     virtual void OnEventReceived(const GetIntAndStringEvent& event)
66     {
67         event.GetArg0() (IntVal, StringVal); //calling intercontext delegate
68     }
69 };
70
71 struct TestResult
72 {
73     TestResult() :
74         m_correctThread0(false),
75         m_correctThread1(false),
76         m_correctThread2(false),
77         m_int(-1),
78         m_int2(-1),
79         m_string("")
80     {}
81
82     void TestEventsPassed()
83     {
84         RUNNER_ASSERT(m_correctThread0);
85         RUNNER_ASSERT(m_correctThread1);
86         RUNNER_ASSERT(m_int == IntVal);
87         RUNNER_ASSERT(m_correctThread2);
88         RUNNER_ASSERT(m_int2 == IntVal);
89         RUNNER_ASSERT(m_string == StringVal);
90     }
91
92     void TestEventsDidNotPass()
93     {
94         RUNNER_ASSERT(!m_correctThread0);
95         RUNNER_ASSERT(!m_correctThread1);
96         RUNNER_ASSERT(m_int == -1);
97         RUNNER_ASSERT(!m_correctThread2);
98         RUNNER_ASSERT(m_int2 == -1);
99         RUNNER_ASSERT(m_string == "");
100     }
101
102     bool m_correctThread0;
103     bool m_correctThread1;
104     bool m_correctThread2;
105     int m_int;
106     int m_int2;
107     std::string m_string;
108 };
109
110 class TestContextFreeClass :
111     protected DPL::Thread,
112     public DPL::Event::ICDelegateSupport<TestContextFreeClass>
113 {
114   public:
115     TestContextFreeClass(ICTestController* controller, TestResult* result) :
116         Thread(),
117         m_testResult(result),
118         m_controller(controller)
119     {
120         LogDebug("Context thread id = " << this);
121     }
122
123     void Run()
124     {
125         LogDebug("Running Context Free thread");
126         Thread::Run();
127     }
128
129     void Quit()
130     {
131         LogDebug("Exiting Context Free thread");
132         Thread::Quit();
133     }
134
135     void Wait()
136     {
137         LogDebug("Waiting for thread");
138         DPL::WaitForSingleHandle(m_waitable.GetHandle());
139     }
140
141   protected:
142     void OnNothing()
143     {
144         LogDebug("Received nothing in thread = " << GetCurrentThread());
145         m_testResult->m_correctThread0 = (GetCurrentThread() == this);
146     }
147
148     void OnIntReceive(int val)
149     {
150         LogDebug("Received int in thread = " << GetCurrentThread());
151         m_testResult->m_correctThread1 = (GetCurrentThread() == this);
152         m_testResult->m_int = val;
153     }
154
155     void OnIntAndStringReceive(int val, std::string stringval)
156     {
157         LogDebug("Received int and string in thread = " << GetCurrentThread());
158         m_testResult->m_correctThread2 = (GetCurrentThread() == this);
159         m_testResult->m_int2 = val;
160         m_testResult->m_string = stringval;
161         m_waitable.Signal();
162     }
163
164     virtual int ThreadEntry()
165     {
166         GetNothingEvent getNothingEvent(
167             makeICDelegate(
168                 &TestContextFreeClass::OnNothing));
169         m_controller->DPL::Event::ControllerEventHandler<GetNothingEvent>::
170             PostEvent(
171             getNothingEvent);
172
173         GetIntEvent getIntEvent(
174             makeICDelegate(
175                 &TestContextFreeClass::OnIntReceive));
176         m_controller->DPL::Event::ControllerEventHandler<GetIntEvent>::
177             PostEvent(
178             getIntEvent);
179
180         GetIntAndStringEvent getIntAndStringEvent(
181             makeICDelegate(
182                 &TestContextFreeClass::OnIntAndStringReceive));
183         m_controller->DPL::Event::ControllerEventHandler<GetIntAndStringEvent>
184             ::PostEvent(
185             getIntAndStringEvent);
186
187         return Thread::ThreadEntry();
188     }
189
190   private:
191     TestResult* m_testResult;
192     DPL::WaitableEvent m_waitable;
193     ICTestController* m_controller;
194 };
195
196 RUNNER_TEST(ICDelegate_0)
197 {
198     DPL::Thread thread;
199     thread.Run();
200     LogDebug("Controller thread id = " << &thread);
201
202     ICTestController testController;
203     testController.Touch();
204     testController.SwitchToThread(&thread);
205
206     TestResult result;
207     TestContextFreeClass* contextFree =
208         new TestContextFreeClass(&testController, &result);
209     result.TestEventsDidNotPass();
210
211     thread.Run();
212     contextFree->Run();
213     contextFree->Wait();
214     contextFree->Quit();
215     thread.Quit();
216
217     delete contextFree;
218
219     result.TestEventsPassed();
220 }
221
222 RUNNER_TEST(ICDelegate_1)
223 {
224     DPL::Thread thread;
225     LogDebug("Controller thread id = " << &thread);
226
227     ICTestController testController;
228     testController.Touch();
229     testController.SwitchToThread(&thread);
230
231     TestResult result;
232     TestContextFreeClass* contextFree =
233         new TestContextFreeClass(&testController, &result);
234     result.TestEventsDidNotPass();
235
236     contextFree->Run();
237     contextFree->Quit();
238     delete contextFree; //deleting Delegates before actual Events are worked out
239     thread.Run();
240     thread.Quit();
241
242     result.TestEventsDidNotPass();
243 }
244
245 class TestContextFree;
246 class TestRunnerInThread;
247
248 namespace {
249 const int ControllersPerThread = 40;
250 const int ContextFreePerThread = 180;
251 const int TestsPerController = 110;
252 const int TestThreads = 23;
253 const int TestsPerThread = 100;
254 const int NumberOfEvents = 230;
255
256 typedef std::shared_ptr<ICTestController> ICTestControllerPtr;
257 typedef std::shared_ptr<TestContextFree> TestContextFreePtr;
258 typedef std::shared_ptr<TestRunnerInThread> TestRunnerInThreadPtr;
259 typedef std::shared_ptr<DPL::Thread> ThreadPtr;
260
261 DPL::Mutex mutex;
262 std::list<TestContextFreePtr> frees;
263 std::list<ICTestControllerPtr> ctrls;
264 std::list<TestRunnerInThreadPtr> frees_threads;
265 std::list<ThreadPtr> ctrls_threads;
266 }
267
268 class TestContextFree : public DPL::Event::ICDelegateSupport<TestContextFree>
269 {
270   public:
271     TestContextFree(ICTestController* controller,
272                     int eventsCount) :
273         m_controller(controller),
274         m_eventsCount(eventsCount)
275     {}
276
277     void Wait()
278     {
279         LogDebug("Waiting for thread");
280         DPL::WaitForSingleHandle(m_waitable.GetHandle());
281     }
282
283     void OnNothing()
284     {
285         LogDebug("Got");
286         m_eventsCount--;
287         if (m_eventsCount > 0) {
288             LogDebug("posting next event");
289             GetIntAndStringEvent getIntAndStringEvent(
290                 makeICDelegate(
291                     &TestContextFree::OnIntAndStringReceive));
292             LogDebug("posting next event ...");
293             m_controller->DPL::Event::ControllerEventHandler<
294                 GetIntAndStringEvent>::PostEvent(
295                 getIntAndStringEvent);
296             LogDebug("posting next event done");
297         } else {
298             LogDebug("test finished");
299             m_waitable.Signal();
300         }
301     }
302
303     void OnIntReceive(int)
304     {
305         LogDebug("Got");
306         m_eventsCount--;
307         if (m_eventsCount > 0) {
308             LogDebug("posting next event");
309             GetNothingEvent getNothingEvent(
310                 makeICDelegate(
311                     &TestContextFree::OnNothing));
312             LogDebug("posting next event ...");
313             m_controller->DPL::Event::ControllerEventHandler<GetNothingEvent>::
314                 PostEvent(
315                 getNothingEvent);
316             LogDebug("posting next event done");
317         } else {
318             LogDebug("test finished");
319             m_waitable.Signal();
320         }
321     }
322
323     void OnIntAndStringReceive(int, std::string)
324     {
325         LogDebug("Got");
326         m_eventsCount--;
327         if (m_eventsCount > 0) {
328             LogDebug("posting next event");
329
330             GetIntEvent getIntEvent(
331                 makeICDelegate(
332                     &TestContextFree::OnIntReceive));
333             LogDebug("posting next event ...");
334             m_controller->DPL::Event::ControllerEventHandler<GetIntEvent>::
335                 PostEvent(
336                 getIntEvent);
337             LogDebug("posting next event done");
338         } else {
339             LogDebug("test finished");
340             m_waitable.Signal();
341         }
342     }
343
344     void StartTestOnNothing()
345     {
346         GetNothingEvent getNothingEvent(
347             makeICDelegate(
348                 &TestContextFree::OnNothing));
349         m_controller->DPL::Event::ControllerEventHandler<GetNothingEvent>::
350             PostEvent(
351             getNothingEvent);
352     }
353
354     void StartTestOnInt()
355     {
356         GetIntEvent getIntEvent(
357             makeICDelegate(
358                 &TestContextFree::OnIntReceive));
359         m_controller->DPL::Event::ControllerEventHandler<GetIntEvent>::
360             PostEvent(
361             getIntEvent);
362     }
363
364     void StartTestOnIntAndString()
365     {
366         GetIntAndStringEvent getIntAndStringEvent(
367             makeICDelegate(
368                 &TestContextFree::OnIntAndStringReceive));
369         m_controller->DPL::Event::ControllerEventHandler<GetIntAndStringEvent>
370             ::PostEvent(
371             getIntAndStringEvent);
372     }
373
374     bool CheckTest()
375     {
376         LogDebug("Checking test result");
377         return m_eventsCount == 0;
378     }
379
380   private:
381     ICTestController* m_controller;
382     int m_eventsCount;
383     DPL::WaitableEvent m_waitable;
384 };
385
386 class TestRunnerInThread : public DPL::Thread
387 {
388   public:
389     TestRunnerInThread(int events, int tests) :
390         m_eventsCount(events),
391         m_tests(tests) {}
392
393     void WaitForInit()
394     {
395         LogDebug("Waiting for thread");
396         DPL::WaitForSingleHandle(m_init.GetHandle());
397     }
398
399   protected:
400     virtual int ThreadEntry()
401     {
402         LogDebug("Thread starts");
403         {
404             DPL::Mutex::ScopedLock lock(&mutex);
405             for (int i = 0; i < m_tests; ++i) {
406                 if (i % TestsPerController == 0) {
407                     if (ctrls.size() % ControllersPerThread == 0) {
408                         ThreadPtr thread(new DPL::Thread());
409                         thread->Run();
410                         ctrls_threads.push_back(thread);
411                     }
412                     ICTestControllerPtr ptr(new ICTestController());
413                     ptr->Touch();
414                     ptr->SwitchToThread(ctrls_threads.back().get());
415                     ctrls.push_back(ptr);
416
417                     TestContextFreePtr t(new TestContextFree(ctrls.back().get(),
418                                                              m_eventsCount));
419                     t->StartTestOnNothing();
420                     LogDebug("");
421                     frees.push_back(t);
422                 }
423             }
424         }
425         m_init.Signal();
426         LogDebug("Thread starts loop");
427         return DPL::Thread::ThreadEntry();
428     }
429
430   private:
431     DPL::WaitableEvent m_init;
432     int m_eventsCount;
433     int m_tests;
434 };
435
436 RUNNER_TEST(ICDelegate_2)
437 {
438     LogDebug("Creating test threads");
439     for (int i = 0; i < TestThreads; ++i) {
440         TestRunnerInThreadPtr ptr(
441             new TestRunnerInThread(NumberOfEvents, TestsPerThread));
442         frees_threads.push_back(ptr);
443         frees_threads.back()->Run();
444     }
445
446     FOREACH(it, frees_threads) {
447         (*it)->WaitForInit();
448     }
449     LogDebug("Creating test threads done");
450
451     FOREACH(it, frees) {
452         LogDebug("...");
453         (*it)->Wait();
454     }
455
456     FOREACH(it, frees) {
457         RUNNER_ASSERT((*it)->CheckTest());
458     }
459
460     frees.clear();
461
462     FOREACH(it, frees_threads) {
463         (*it)->Quit();
464     }
465
466     frees_threads.clear();
467
468     FOREACH(it, ctrls) {
469         (*it)->SwitchToThread(NULL);
470     }
471
472     FOREACH(it, ctrls_threads) {
473         (*it)->Quit();
474     }
475
476     ctrls.clear();
477     ctrls_threads.clear();
478 }
479
480 namespace ReuseCheck {
481 const int ReuseCount = 5;
482 typedef DPL::Event::ICDelegate<> GetNothingDlpType;
483 DECLARE_GENERIC_EVENT_1(ReuseCountEvent, GetNothingDlpType)
484
485 class ICReuseTestController :
486     public DPL::Event::Controller<DPL::TypeListDecl<ReuseCountEvent>::Type>
487 {
488   public:
489     ICReuseTestController()
490     {
491         m_reuseCount = 0;
492     }
493
494   protected:
495     virtual void OnEventReceived(const ReuseCountEvent& event)
496     {
497         event.GetArg0() (); //calling intercontext delegate
498         if (++m_reuseCount < ReuseCount) {
499             LogInfo("[Send] Reuse: " << m_reuseCount);
500             DPL::Event::ControllerEventHandler<ReuseCountEvent>::PostEvent(
501                 event);
502         }
503     }
504
505     int m_reuseCount;
506 };
507
508 class ReuseTestContextFreeClass :
509     protected DPL::Thread,
510     public DPL::Event::ICDelegateSupport<ReuseTestContextFreeClass>
511 {
512   public:
513     ReuseTestContextFreeClass(ICReuseTestController* controller) :
514         Thread(),
515         m_controller(controller),
516         m_reuseCount(0)
517     { }
518
519     void Run()
520     {
521         Thread::Run();
522     }
523     void Quit()
524     {
525         Thread::Quit();
526     }
527     void Wait()
528     {
529         DPL::WaitForSingleHandle(m_waitable.GetHandle());
530     }
531
532   protected:
533     void OnReuseReceive()
534     {
535         LogDebug("[Received] : " << ++m_reuseCount);
536         if (m_reuseCount == ReuseCount) {
537             m_waitable.Signal();
538         }
539     }
540
541     virtual int ThreadEntry()
542     {
543         ReuseCountEvent reuseEvent(
544             makeICDelegate(
545                 &ReuseTestContextFreeClass::OnReuseReceive,
546                 DPL::Event::ICD::Reuse::Yes));
547         m_controller->DPL::Event::ControllerEventHandler<ReuseCountEvent>::
548             PostEvent(
549             reuseEvent);
550
551         return Thread::ThreadEntry();
552     }
553
554   private:
555     DPL::WaitableEvent m_waitable;
556     ICReuseTestController* m_controller;
557     int m_reuseCount;
558 };
559
560 RUNNER_TEST(ICDelegate_3)
561 {
562     DPL::Thread thread;
563     thread.Run();
564     LogDebug("Controller thread id = " << &thread);
565
566     ICReuseTestController testController;
567     testController.Touch();
568     testController.SwitchToThread(&thread);
569
570     ReuseTestContextFreeClass* contextFree =
571         new ReuseTestContextFreeClass(&testController);
572
573     thread.Run();
574     contextFree->Run();
575     contextFree->Wait();
576     contextFree->Quit();
577     thread.Quit();
578
579     delete contextFree;
580
581     RUNNER_ASSERT(true);
582 }
583 } //namespace ReuseCheck