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