upload tizen1.0 source
[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/shared_ptr.h>
31 #include <dpl/waitable_event.h>
32 #include <dpl/assert.h>
33 #include <dpl/mutex.h>
34 #include <dpl/type_list.h>
35
36 RUNNER_TEST_GROUP_INIT(DPL)
37
38 const int IntVal = 123;
39 const std::string StringVal = "someString";
40
41 typedef DPL::Event::ICDelegate<> GetNothingDlpType;
42 typedef DPL::Event::ICDelegate<int> GetIntDlgType;
43 typedef DPL::Event::ICDelegate<int, std::string> GetIntAndStringDlgType;
44 DECLARE_GENERIC_EVENT_1(GetNothingEvent, GetNothingDlpType)
45 DECLARE_GENERIC_EVENT_1(GetIntEvent, GetIntDlgType)
46 DECLARE_GENERIC_EVENT_1(GetIntAndStringEvent, GetIntAndStringDlgType)
47
48 class ICTestController
49 : public DPL::Event::Controller<DPL::TypeListDecl<GetNothingEvent,
50                                                   GetIntEvent,
51                                                   GetIntAndStringEvent>::Type>
52 {
53   public:
54     ICTestController() { }
55
56   protected:
57     virtual void OnEventReceived(const GetNothingEvent& event)
58     {
59         event.GetArg0()(); //calling intercontext delegate
60     }
61     virtual void OnEventReceived(const GetIntEvent& event)
62     {
63         event.GetArg0()(IntVal); //calling intercontext delegate
64     }
65
66     virtual void OnEventReceived(const GetIntAndStringEvent& event)
67     {
68         event.GetArg0()(IntVal, StringVal); //calling intercontext delegate
69     }
70 };
71
72 struct TestResult
73 {
74     TestResult() :
75         m_correctThread0(false),
76         m_correctThread1(false),
77         m_correctThread2(false),
78         m_int(-1),
79         m_int2(-1),
80         m_string("")
81     {
82     }
83
84     void TestEventsPassed()
85     {
86         RUNNER_ASSERT(m_correctThread0);
87         RUNNER_ASSERT(m_correctThread1);
88         RUNNER_ASSERT(m_int == IntVal);
89         RUNNER_ASSERT(m_correctThread2);
90         RUNNER_ASSERT(m_int2 == IntVal);
91         RUNNER_ASSERT(m_string == StringVal);
92     }
93
94     void TestEventsDidNotPass()
95     {
96         RUNNER_ASSERT(!m_correctThread0);
97         RUNNER_ASSERT(!m_correctThread1);
98         RUNNER_ASSERT(m_int == -1);
99         RUNNER_ASSERT(!m_correctThread2);
100         RUNNER_ASSERT(m_int2 == -1);
101         RUNNER_ASSERT(m_string == "");
102     }
103
104     bool m_correctThread0;
105     bool m_correctThread1;
106     bool m_correctThread2;
107     int m_int;
108     int m_int2;
109     std::string m_string;
110 };
111
112 class TestContextFreeClass :
113     protected DPL::Thread,
114     public DPL::Event::ICDelegateSupport<TestContextFreeClass>
115 {
116   public:
117     TestContextFreeClass(ICTestController* controller, TestResult* result) :
118         Thread(),
119         m_testResult(result),
120         m_controller(controller)
121     {
122         LogDebug("Context thread id = " << this);
123     }
124
125     void Run()
126     {
127         LogDebug("Running Context Free thread");
128         Thread::Run();
129     }
130
131     void Quit()
132     {
133         LogDebug("Exiting Context Free thread");
134         Thread::Quit();
135     }
136
137
138     void Wait()
139     {
140         LogDebug("Waiting for thread");
141         DPL::WaitForSingleHandle(m_waitable.GetHandle());
142     }
143
144   protected:
145     void OnNothing()
146     {
147         LogDebug("Received nothing in thread = " << GetCurrentThread());
148         m_testResult->m_correctThread0 = (GetCurrentThread() == this);
149     }
150
151     void OnIntReceive(int val)
152     {
153         LogDebug("Received int in thread = " << GetCurrentThread());
154         m_testResult->m_correctThread1 = (GetCurrentThread() == this);
155         m_testResult->m_int = val;
156     }
157
158     void OnIntAndStringReceive(int val, std::string stringval)
159     {
160         LogDebug("Received int and string in thread = " << 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>::PostEvent(
173             getNothingEvent);
174
175         GetIntEvent getIntEvent(
176             makeICDelegate(
177                 &TestContextFreeClass::OnIntReceive));
178         m_controller->DPL::Event::ControllerEventHandler<GetIntEvent>::PostEvent(
179             getIntEvent);
180
181         GetIntAndStringEvent getIntAndStringEvent(
182             makeICDelegate(
183                 &TestContextFreeClass::OnIntAndStringReceive));
184         m_controller->DPL::Event::ControllerEventHandler<GetIntAndStringEvent>::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 {
250 const int ControllersPerThread = 40;
251 const int ContextFreePerThread = 180;
252 const int TestsPerController = 110;
253 const int TestThreads = 23;
254 const int TestsPerThread = 100;
255 const int NumberOfEvents = 230;
256
257 typedef DPL::SharedPtr<ICTestController> ICTestControllerPtr;
258 typedef DPL::SharedPtr<TestContextFree> TestContextFreePtr;
259 typedef DPL::SharedPtr<TestRunnerInThread> TestRunnerInThreadPtr;
260 typedef DPL::SharedPtr<DPL::Thread> ThreadPtr;
261
262 DPL::Mutex mutex;
263 std::list<TestContextFreePtr> frees;
264 std::list<ICTestControllerPtr> ctrls;
265 std::list<TestRunnerInThreadPtr> frees_threads;
266 std::list<ThreadPtr> ctrls_threads;
267
268 }
269
270 class TestContextFree : public DPL::Event::ICDelegateSupport<TestContextFree>
271 {
272   public:
273     TestContextFree(ICTestController* controller,
274                     int eventsCount) :
275         m_controller(controller),
276         m_eventsCount(eventsCount)
277     {
278     }
279
280     void Wait()
281     {
282         LogDebug("Waiting for thread");
283         DPL::WaitForSingleHandle(m_waitable.GetHandle());
284     }
285
286
287     void OnNothing()
288     {
289         LogDebug("Got");
290         m_eventsCount--;
291         if (m_eventsCount > 0) {
292             LogDebug("posting next event");
293             GetIntAndStringEvent getIntAndStringEvent(
294                 makeICDelegate(
295                     &TestContextFree::OnIntAndStringReceive));
296             LogDebug("posting next event ...");
297             m_controller->DPL::Event::ControllerEventHandler<GetIntAndStringEvent>::PostEvent(
298                 getIntAndStringEvent);
299             LogDebug("posting next event done");
300         } else {
301             LogDebug("test finished");
302             m_waitable.Signal();
303         }
304     }
305
306     void OnIntReceive(int)
307     {
308         LogDebug("Got");
309         m_eventsCount--;
310         if (m_eventsCount > 0) {
311             LogDebug("posting next event");
312             GetNothingEvent getNothingEvent(
313                 makeICDelegate(
314                     &TestContextFree::OnNothing));
315             LogDebug("posting next event ...");
316             m_controller->DPL::Event::ControllerEventHandler<GetNothingEvent>::PostEvent(
317                 getNothingEvent);
318             LogDebug("posting next event done");
319         } else {
320             LogDebug("test finished");
321             m_waitable.Signal();
322         }
323     }
324
325     void OnIntAndStringReceive(int, std::string)
326     {
327         LogDebug("Got");
328         m_eventsCount--;
329         if (m_eventsCount > 0) {
330             LogDebug("posting next event");
331
332             GetIntEvent getIntEvent(
333                 makeICDelegate(
334                     &TestContextFree::OnIntReceive));
335             LogDebug("posting next event ...");
336             m_controller->DPL::Event::ControllerEventHandler<GetIntEvent>::PostEvent(
337                 getIntEvent);
338             LogDebug("posting next event done");
339         } else {
340             LogDebug("test finished");
341             m_waitable.Signal();
342         }
343     }
344
345     void StartTestOnNothing()
346     {
347         GetNothingEvent getNothingEvent(
348             makeICDelegate(
349                 &TestContextFree::OnNothing));
350         m_controller->DPL::Event::ControllerEventHandler<GetNothingEvent>::PostEvent(
351             getNothingEvent);
352     }
353
354     void StartTestOnInt()
355     {
356         GetIntEvent getIntEvent(
357             makeICDelegate(
358                 &TestContextFree::OnIntReceive));
359         m_controller->DPL::Event::ControllerEventHandler<GetIntEvent>::PostEvent(
360             getIntEvent);
361     }
362
363     void StartTestOnIntAndString()
364     {
365         GetIntAndStringEvent getIntAndStringEvent(
366             makeICDelegate(
367                 &TestContextFree::OnIntAndStringReceive));
368         m_controller->DPL::Event::ControllerEventHandler<GetIntAndStringEvent>::PostEvent(
369             getIntAndStringEvent);
370     }
371
372     bool CheckTest()
373     {
374         LogDebug("Checking test result");
375         return m_eventsCount == 0;
376     }
377
378   private:
379     ICTestController* m_controller;
380     int m_eventsCount;
381     DPL::WaitableEvent m_waitable;
382 };
383
384 class TestRunnerInThread : public DPL::Thread
385 {
386   public:
387     TestRunnerInThread(int events, int tests) :
388         m_eventsCount(events),
389         m_tests(tests) {}
390
391     void WaitForInit()
392     {
393         LogDebug("Waiting for thread");
394         DPL::WaitForSingleHandle(m_init.GetHandle());
395     }
396
397   protected:
398     virtual int ThreadEntry()
399     {
400         LogDebug("Thread starts");
401         {
402             DPL::Mutex::ScopedLock lock(&mutex);
403             for (int i = 0; i < m_tests; ++i)
404             {
405                 if (i % TestsPerController == 0) {
406                     if (ctrls.size() % ControllersPerThread == 0) {
407                         ThreadPtr thread(new DPL::Thread());
408                         thread->Run();
409                         ctrls_threads.push_back(thread);
410                     }
411                     ICTestControllerPtr ptr(new ICTestController());
412                     ptr->Touch();
413                     ptr->SwitchToThread(ctrls_threads.back().Get());
414                     ctrls.push_back(ptr);
415
416                     TestContextFreePtr t(new TestContextFree(ctrls.back().Get(),
417                                                              m_eventsCount));
418                     t->StartTestOnNothing();
419                     LogDebug("");
420                     frees.push_back(t);
421                 }
422             }
423         }
424         m_init.Signal();
425         LogDebug("Thread starts loop");
426         return DPL::Thread::ThreadEntry();
427     }
428
429   private:
430     DPL::WaitableEvent m_init;
431     int m_eventsCount;
432     int m_tests;
433 };
434
435 RUNNER_TEST(ICDelegate_2)
436 {
437     LogDebug("Creating test threads");
438     for (int i = 0; i < TestThreads; ++i)
439     {
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() { m_reuseCount = 0; }
490
491   protected:
492     virtual void OnEventReceived(const ReuseCountEvent& event)
493     {
494         event.GetArg0()(); //calling intercontext delegate
495         if(++m_reuseCount < ReuseCount){
496             LogInfo("[Send] Reuse: " << m_reuseCount);
497             DPL::Event::ControllerEventHandler<ReuseCountEvent>::PostEvent(event);
498         }
499     }
500
501     int m_reuseCount;
502 };
503
504 class ReuseTestContextFreeClass :
505     protected DPL::Thread,
506     public DPL::Event::ICDelegateSupport<ReuseTestContextFreeClass>
507 {
508   public:
509     ReuseTestContextFreeClass(ICReuseTestController* controller) :
510         Thread(),
511         m_controller(controller),
512         m_reuseCount(0)
513     { }
514
515     void Run() { Thread::Run(); }
516     void Quit() { Thread::Quit(); }
517     void Wait() { DPL::WaitForSingleHandle(m_waitable.GetHandle()); }
518
519   protected:
520     void OnReuseReceive()
521     {
522         LogDebug("[Received] : " << ++m_reuseCount);
523         if(m_reuseCount == ReuseCount)
524             m_waitable.Signal();
525     }
526
527     virtual int ThreadEntry()
528     {
529         ReuseCountEvent reuseEvent(
530             makeICDelegate(
531                 &ReuseTestContextFreeClass::OnReuseReceive,
532                 DPL::Event::ICD::Reuse::Yes));
533         m_controller->DPL::Event::ControllerEventHandler<ReuseCountEvent>::PostEvent(
534             reuseEvent);
535
536         return Thread::ThreadEntry();
537     }
538
539   private:
540     DPL::WaitableEvent m_waitable;
541     ICReuseTestController* m_controller;
542     int m_reuseCount;
543 };
544
545 RUNNER_TEST(ICDelegate_3)
546 {
547     DPL::Thread thread;
548     thread.Run();
549     LogDebug("Controller thread id = " << &thread);
550
551     ICReuseTestController testController;
552     testController.Touch();
553     testController.SwitchToThread(&thread);
554
555     ReuseTestContextFreeClass* contextFree =
556         new ReuseTestContextFreeClass(&testController);
557
558     thread.Run();
559     contextFree->Run();
560     contextFree->Wait();
561     contextFree->Quit();
562     thread.Quit();
563
564     delete contextFree;
565
566     RUNNER_ASSERT(true);
567 }
568 } //namespace ReuseCheck