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