sync
[platform/framework/web/wrt-commons.git] / tests / 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 /*
197 Name: ICDelegate_0
198 Description: checks if delegetes are correctly called
199 Expected: delegates should be called from right context
200 */
201 RUNNER_TEST(ICDelegate_0)
202 {
203     DPL::Thread thread;
204     thread.Run();
205     LogDebug("Controller thread id = " << &thread);
206
207     ICTestController testController;
208     testController.Touch();
209     testController.SwitchToThread(&thread);
210
211     TestResult result;
212     TestContextFreeClass* contextFree =
213         new TestContextFreeClass(&testController, &result);
214     result.TestEventsDidNotPass();
215
216     thread.Run();
217     contextFree->Run();
218     contextFree->Wait();
219     contextFree->Quit();
220     thread.Quit();
221
222     delete contextFree;
223
224     result.TestEventsPassed();
225 }
226
227 /*
228 Name: ICDelegate_1
229 Description: checks if delegetes are correctly called
230 Expected: delegates should be called from right context
231 */
232 RUNNER_TEST(ICDelegate_1)
233 {
234     DPL::Thread thread;
235     LogDebug("Controller thread id = " << &thread);
236
237     ICTestController testController;
238     testController.Touch();
239     testController.SwitchToThread(&thread);
240
241     TestResult result;
242     TestContextFreeClass* contextFree =
243         new TestContextFreeClass(&testController, &result);
244     result.TestEventsDidNotPass();
245
246     contextFree->Run();
247     contextFree->Quit();
248     delete contextFree; //deleting Delegates before actual Events are worked out
249     thread.Run();
250     thread.Quit();
251
252     result.TestEventsDidNotPass();
253 }
254
255 class TestContextFree;
256 class TestRunnerInThread;
257
258 namespace {
259 const int ControllersPerThread = 40;
260 const int ContextFreePerThread = 180;
261 const int TestsPerController = 110;
262 const int TestThreads = 23;
263 const int TestsPerThread = 100;
264 const int NumberOfEvents = 230;
265
266 typedef std::shared_ptr<ICTestController> ICTestControllerPtr;
267 typedef std::shared_ptr<TestContextFree> TestContextFreePtr;
268 typedef std::shared_ptr<TestRunnerInThread> TestRunnerInThreadPtr;
269 typedef std::shared_ptr<DPL::Thread> ThreadPtr;
270
271 DPL::Mutex mutex;
272 std::list<TestContextFreePtr> frees;
273 std::list<ICTestControllerPtr> ctrls;
274 std::list<TestRunnerInThreadPtr> frees_threads;
275 std::list<ThreadPtr> ctrls_threads;
276 }
277
278 class TestContextFree : public DPL::Event::ICDelegateSupport<TestContextFree>
279 {
280   public:
281     TestContextFree(ICTestController* controller,
282                     int eventsCount) :
283         m_controller(controller),
284         m_eventsCount(eventsCount)
285     {}
286
287     void Wait()
288     {
289         LogDebug("Waiting for thread");
290         DPL::WaitForSingleHandle(m_waitable.GetHandle());
291     }
292
293     void OnNothing()
294     {
295         LogDebug("Got");
296         m_eventsCount--;
297         if (m_eventsCount > 0) {
298             LogDebug("posting next event");
299             GetIntAndStringEvent getIntAndStringEvent(
300                 makeICDelegate(
301                     &TestContextFree::OnIntAndStringReceive));
302             LogDebug("posting next event ...");
303             m_controller->DPL::Event::ControllerEventHandler<
304                 GetIntAndStringEvent>::PostEvent(
305                 getIntAndStringEvent);
306             LogDebug("posting next event done");
307         } else {
308             LogDebug("test finished");
309             m_waitable.Signal();
310         }
311     }
312
313     void OnIntReceive(int)
314     {
315         LogDebug("Got");
316         m_eventsCount--;
317         if (m_eventsCount > 0) {
318             LogDebug("posting next event");
319             GetNothingEvent getNothingEvent(
320                 makeICDelegate(
321                     &TestContextFree::OnNothing));
322             LogDebug("posting next event ...");
323             m_controller->DPL::Event::ControllerEventHandler<GetNothingEvent>::
324                 PostEvent(
325                 getNothingEvent);
326             LogDebug("posting next event done");
327         } else {
328             LogDebug("test finished");
329             m_waitable.Signal();
330         }
331     }
332
333     void OnIntAndStringReceive(int, std::string)
334     {
335         LogDebug("Got");
336         m_eventsCount--;
337         if (m_eventsCount > 0) {
338             LogDebug("posting next event");
339
340             GetIntEvent getIntEvent(
341                 makeICDelegate(
342                     &TestContextFree::OnIntReceive));
343             LogDebug("posting next event ...");
344             m_controller->DPL::Event::ControllerEventHandler<GetIntEvent>::
345                 PostEvent(
346                 getIntEvent);
347             LogDebug("posting next event done");
348         } else {
349             LogDebug("test finished");
350             m_waitable.Signal();
351         }
352     }
353
354     void StartTestOnNothing()
355     {
356         GetNothingEvent getNothingEvent(
357             makeICDelegate(
358                 &TestContextFree::OnNothing));
359         m_controller->DPL::Event::ControllerEventHandler<GetNothingEvent>::
360             PostEvent(
361             getNothingEvent);
362     }
363
364     void StartTestOnInt()
365     {
366         GetIntEvent getIntEvent(
367             makeICDelegate(
368                 &TestContextFree::OnIntReceive));
369         m_controller->DPL::Event::ControllerEventHandler<GetIntEvent>::
370             PostEvent(
371             getIntEvent);
372     }
373
374     void StartTestOnIntAndString()
375     {
376         GetIntAndStringEvent getIntAndStringEvent(
377             makeICDelegate(
378                 &TestContextFree::OnIntAndStringReceive));
379         m_controller->DPL::Event::ControllerEventHandler<GetIntAndStringEvent>
380             ::PostEvent(
381             getIntAndStringEvent);
382     }
383
384     bool CheckTest()
385     {
386         LogDebug("Checking test result");
387         return m_eventsCount == 0;
388     }
389
390   private:
391     ICTestController* m_controller;
392     int m_eventsCount;
393     DPL::WaitableEvent m_waitable;
394 };
395
396 class TestRunnerInThread : public DPL::Thread
397 {
398   public:
399     TestRunnerInThread(int events, int tests) :
400         m_eventsCount(events),
401         m_tests(tests) {}
402
403     void WaitForInit()
404     {
405         LogDebug("Waiting for thread");
406         DPL::WaitForSingleHandle(m_init.GetHandle());
407     }
408
409   protected:
410     virtual int ThreadEntry()
411     {
412         LogDebug("Thread starts");
413         {
414             DPL::Mutex::ScopedLock lock(&mutex);
415             for (int i = 0; i < m_tests; ++i) {
416                 if (i % TestsPerController == 0) {
417                     if (ctrls.size() % ControllersPerThread == 0) {
418                         ThreadPtr thread(new DPL::Thread());
419                         thread->Run();
420                         ctrls_threads.push_back(thread);
421                     }
422                     ICTestControllerPtr ptr(new ICTestController());
423                     ptr->Touch();
424                     ptr->SwitchToThread(ctrls_threads.back().get());
425                     ctrls.push_back(ptr);
426
427                     TestContextFreePtr t(new TestContextFree(ctrls.back().get(),
428                                                              m_eventsCount));
429                     t->StartTestOnNothing();
430                     LogDebug("");
431                     frees.push_back(t);
432                 }
433             }
434         }
435         m_init.Signal();
436         LogDebug("Thread starts loop");
437         return DPL::Thread::ThreadEntry();
438     }
439
440   private:
441     DPL::WaitableEvent m_init;
442     int m_eventsCount;
443     int m_tests;
444 };
445
446 /*
447 Name: ICDelegate_2
448 Description: checks if delegetes are correctly called
449 Expected: delegates should be called from right context
450 */
451 RUNNER_TEST(ICDelegate_2)
452 {
453     LogDebug("Creating test threads");
454     for (int i = 0; i < TestThreads; ++i) {
455         TestRunnerInThreadPtr ptr(
456             new TestRunnerInThread(NumberOfEvents, TestsPerThread));
457         frees_threads.push_back(ptr);
458         frees_threads.back()->Run();
459     }
460
461     FOREACH(it, frees_threads) {
462         (*it)->WaitForInit();
463     }
464     LogDebug("Creating test threads done");
465
466     FOREACH(it, frees) {
467         LogDebug("...");
468         (*it)->Wait();
469     }
470
471     FOREACH(it, frees) {
472         RUNNER_ASSERT((*it)->CheckTest());
473     }
474
475     frees.clear();
476
477     FOREACH(it, frees_threads) {
478         (*it)->Quit();
479     }
480
481     frees_threads.clear();
482
483     FOREACH(it, ctrls) {
484         (*it)->SwitchToThread(NULL);
485     }
486
487     FOREACH(it, ctrls_threads) {
488         (*it)->Quit();
489     }
490
491     ctrls.clear();
492     ctrls_threads.clear();
493 }
494
495 namespace ReuseCheck {
496 const int ReuseCount = 5;
497 typedef DPL::Event::ICDelegate<> GetNothingDlpType;
498 DECLARE_GENERIC_EVENT_1(ReuseCountEvent, GetNothingDlpType)
499
500 class ICReuseTestController :
501     public DPL::Event::Controller<DPL::TypeListDecl<ReuseCountEvent>::Type>
502 {
503   public:
504     ICReuseTestController()
505     {
506         m_reuseCount = 0;
507     }
508
509   protected:
510     virtual void OnEventReceived(const ReuseCountEvent& event)
511     {
512         event.GetArg0() (); //calling intercontext delegate
513         if (++m_reuseCount < ReuseCount) {
514             LogInfo("[Send] Reuse: " << m_reuseCount);
515             DPL::Event::ControllerEventHandler<ReuseCountEvent>::PostEvent(
516                 event);
517         }
518     }
519
520     int m_reuseCount;
521 };
522
523 class ReuseTestContextFreeClass :
524     protected DPL::Thread,
525     public DPL::Event::ICDelegateSupport<ReuseTestContextFreeClass>
526 {
527   public:
528     ReuseTestContextFreeClass(ICReuseTestController* controller) :
529         Thread(),
530         m_controller(controller),
531         m_reuseCount(0)
532     { }
533
534     void Run()
535     {
536         Thread::Run();
537     }
538     void Quit()
539     {
540         Thread::Quit();
541     }
542     void Wait()
543     {
544         DPL::WaitForSingleHandle(m_waitable.GetHandle());
545     }
546
547   protected:
548     void OnReuseReceive()
549     {
550         LogDebug("[Received] : " << ++m_reuseCount);
551         if (m_reuseCount == ReuseCount) {
552             m_waitable.Signal();
553         }
554     }
555
556     virtual int ThreadEntry()
557     {
558         ReuseCountEvent reuseEvent(
559             makeICDelegate(
560                 &ReuseTestContextFreeClass::OnReuseReceive,
561                 DPL::Event::ICD::Reuse::Yes));
562         m_controller->DPL::Event::ControllerEventHandler<ReuseCountEvent>::
563             PostEvent(
564             reuseEvent);
565
566         return Thread::ThreadEntry();
567     }
568
569   private:
570     DPL::WaitableEvent m_waitable;
571     ICReuseTestController* m_controller;
572     int m_reuseCount;
573 };
574
575 /*
576 Name: ICDelegate_3
577 Description: checks if delegetes are correctly called
578 Expected: delegates should be called from right context
579 */
580 RUNNER_TEST(ICDelegate_3)
581 {
582     DPL::Thread thread;
583     thread.Run();
584     LogDebug("Controller thread id = " << &thread);
585
586     ICReuseTestController testController;
587     testController.Touch();
588     testController.SwitchToThread(&thread);
589
590     ReuseTestContextFreeClass* contextFree =
591         new ReuseTestContextFreeClass(&testController);
592
593     thread.Run();
594     contextFree->Run();
595     contextFree->Wait();
596     contextFree->Quit();
597     thread.Quit();
598
599     delete contextFree;
600
601     RUNNER_ASSERT(true);
602 }
603 } //namespace ReuseCheck