Tizen 2.0 Release
[framework/web/wrt-commons.git] / tests / dpl / core / test_fast_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_fast_delegate.cpp
18  * @author      Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
19  * @version     1.0
20  * @brief       This file is the implementation file of fast delegate tests.
21  */
22 #include <dpl/test/test_runner.h>
23 #include <dpl/fast_delegate.h>
24 #include <dpl/log/log.h>
25
26 RUNNER_TEST_GROUP_INIT(DPL)
27
28 // Sample copied and adopted from
29 // http://www.codeproject.com/KB/cpp/FastDelegate.aspx
30 //
31 // Demonstrate the syntax for FastDelegates.
32 //                -Don Clugston, May 2004.
33 // It's a really boring example, but it shows the most important cases.
34 // Declare some functions of varying complexity...
35 void SimpleStaticFunction(int num, const char *str);
36 void SimpleStaticFunction(int num, const char *str)
37 {
38     LogDebug("In SimpleStaticFunction. Num=" << num << ", str =" << str);
39 }
40
41 void SimpleVoidFunction();
42 void SimpleVoidFunction()
43 {
44     LogDebug("In SimpleVoidFunction with no parameters.");
45 }
46
47 class CBaseClass
48 {
49 protected:
50     const char *m_name;
51
52 public:
53     CBaseClass(const char *name)
54         : m_name(name)
55     {
56     }
57
58     virtual ~CBaseClass()
59     {
60     }
61
62     void SimpleMemberFunction(int num, const char *str)
63     {
64         LogDebug("In SimpleMemberFunction in " << m_name << ". Num="
65                  << num << ", str = " << str);
66     }
67
68     int SimpleMemberFunctionReturnsInt(int num, const char *str)
69     {
70         LogDebug("In SimpleMemberFunctionReturnsInt in " << m_name << ". Num="
71                  << num << ", str = " << str);
72         return -1;
73     }
74
75     void ConstMemberFunction(int num, const char *str) const
76     {
77         LogDebug("In ConstMemberFunction in " << m_name << ". Num="
78                  << num << ", str = " << str);
79     }
80
81     virtual void SimpleVirtualFunction(int num, const char *str)
82     {
83         LogDebug("In SimpleVirtualFunction in " << m_name << ". Num="
84                  << num << ", str = " << str);
85     }
86
87     static void StaticMemberFunction(int num, const char *str)
88     {
89         LogDebug("In StaticMemberFunction Num="
90                  << num << ", str = " << str);
91     }
92 };
93
94 class COtherClass
95 {
96     double rubbish; // to ensure this class has non-zero size.
97
98 public:
99     virtual ~COtherClass()
100     {
101     }
102
103     virtual void UnusedVirtualFunction(void)
104     {
105     }
106     virtual void TrickyVirtualFunction(int num, const char *str) = 0;
107 };
108
109 class VeryBigClass
110 {
111     int letsMakeThingsComplicated[400];
112 };
113
114 // This declaration ensures that we get a convoluted class heirarchy.
115 class CDerivedClass
116     : public VeryBigClass,
117       virtual public COtherClass,
118       virtual public CBaseClass
119 {
120     double m_somemember[8];
121
122 public:
123     CDerivedClass()
124         : CBaseClass("Base of Derived")
125     {
126         m_somemember[0] = 1.2345;
127     }
128
129     void SimpleDerivedFunction(int num, const char *str)
130     {
131         LogDebug("In SimpleDerivedFunction Num="
132                  << num << ", str = " << str);
133     }
134
135     virtual void AnotherUnusedVirtualFunction(int num, const char *str)
136     {
137         LogDebug("In AnotherUnusedVirtualFunction in " << m_name << ". Num="
138                  << num << ", str = " << str);
139     }
140
141     virtual void TrickyVirtualFunction(int num, const char *str)
142     {
143         LogDebug("In TrickyVirtualFunction in " << m_name << ". Num="
144                  << num << ", str = " << str);
145     }
146 };
147
148 RUNNER_TEST(FastDelegate_Test)
149 {
150     // Delegates with up to 8 parameters are supported.
151     // Here's the case for a void function.
152     // We declare a delegate and attach it to SimpleVoidFunction()
153     DPL::FastDelegate0<> noparameterdelegate(&SimpleVoidFunction);
154
155     // invoke the delegate - this calls SimpleVoidFunction()
156     noparameterdelegate();
157
158     LogDebug("-- Examples using two-parameter delegates (int, char *) --");
159
160     // By default, the return value is void.
161     typedef DPL::FastDelegate2<int, const char *> MyDelegate;
162
163     // If you want to have a non-void return value, put it at the end.
164     typedef DPL::FastDelegate2<int, const char *, int> IntMyDelegate;
165
166
167     MyDelegate funclist[12]; // delegates are initialized to empty
168     CBaseClass a("Base A");
169     CBaseClass b("Base B");
170     CDerivedClass d;
171     CDerivedClass c;
172
173     IntMyDelegate newdeleg;
174     newdeleg = DPL::MakeDelegate(&a,
175                                  &CBaseClass::SimpleMemberFunctionReturnsInt);
176
177     // Binding a simple member function
178     funclist[0].bind(&a, &CBaseClass::SimpleMemberFunction);
179
180     // You can also bind static (free) functions
181     funclist[1].bind(&SimpleStaticFunction);
182
183     // and static member functions
184     funclist[2].bind(&CBaseClass::StaticMemberFunction);
185
186     // and const member functions (these only need a const class pointer).
187     funclist[3].bind((const CBaseClass *) &a,
188                       &CBaseClass::ConstMemberFunction);
189
190     funclist[4].bind(&a, &CBaseClass::ConstMemberFunction);
191
192     // and virtual member functions
193     funclist[5].bind(&b, &CBaseClass::SimpleVirtualFunction);
194
195     // You can also use the = operator. For static functions, a fastdelegate
196     // looks identical to a simple function pointer.
197     funclist[6] = &CBaseClass::StaticMemberFunction;
198
199     // The weird rule about the class of derived member function pointers
200     // is avoided. For MSVC, you can use &CDerivedClass::SimpleVirtualFunction
201     // here, but DMC will complain. Note that as well as .bind(), you can also
202     // use the MakeDelegate() global function.
203     funclist[7] = DPL::MakeDelegate(&d, &CBaseClass::SimpleVirtualFunction);
204
205     // The worst case is an abstract virtual function of a virtually-derived
206     // class with at least one non-virtual base class. This is a VERY obscure
207     // situation, which you're unlikely to encounter in the real world.
208     // FastDelegate versions prior to 1.3 had problems with this case on VC6.
209     // Now, it works without problems on all compilers.
210     funclist[8].bind(&c, &CDerivedClass::TrickyVirtualFunction);
211
212     // BUT... in such cases you should be using the base class as an
213     // interface, anyway.
214     funclist[9].bind(&c, &COtherClass::TrickyVirtualFunction);
215
216     // Calling a function that was first declared in the derived class is
217     // straightforward
218     funclist[10] = DPL::MakeDelegate(&c, &CDerivedClass::SimpleDerivedFunction);
219
220     // You can also bind directly using the constructor
221     MyDelegate dg(&b, &CBaseClass::SimpleVirtualFunction);
222
223     const char *msg = "Looking for equal delegate";
224
225     for (int i = 0; i < 12; i++)
226     {
227         LogDebug(i << ":");
228
229         // The == and != operators are provided
230         // Note that they work even for inline functions.
231         if (funclist[i] == dg)
232         {
233             msg = "Found equal delegate";
234         }
235
236         // operator ! can be used to test for an empty delegate
237         // You can also use the .empty() member function.
238         if (!funclist[i])
239         {
240             LogDebug("Delegate is empty");
241         }
242         else
243         {
244             // Invocation generates optimal assembly code.
245             funclist[i](i, msg);
246         }
247     }
248 }