Source code formating unification
[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     virtual ~CBaseClass()
58     {}
59
60     void SimpleMemberFunction(int num, const char *str)
61     {
62         LogDebug("In SimpleMemberFunction in " << m_name << ". Num="
63                                                << num << ", str = " << str);
64     }
65
66     int SimpleMemberFunctionReturnsInt(int num, const char *str)
67     {
68         LogDebug(
69             "In SimpleMemberFunctionReturnsInt in " << m_name << ". Num="
70                                                     << num <<
71             ", 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     virtual void UnusedVirtualFunction(void)
103     {}
104     virtual void TrickyVirtualFunction(int num, const char *str) = 0;
105 };
106
107 class VeryBigClass
108 {
109     int letsMakeThingsComplicated[400];
110 };
111
112 // This declaration ensures that we get a convoluted class heirarchy.
113 class CDerivedClass :
114     public VeryBigClass,
115     virtual public COtherClass,
116     virtual public CBaseClass
117 {
118     double m_somemember[8];
119
120   public:
121     CDerivedClass() :
122         CBaseClass("Base of Derived")
123     {
124         m_somemember[0] = 1.2345;
125     }
126
127     void SimpleDerivedFunction(int num, const char *str)
128     {
129         LogDebug("In SimpleDerivedFunction Num="
130                  << num << ", str = " << str);
131     }
132
133     virtual void AnotherUnusedVirtualFunction(int num, const char *str)
134     {
135         LogDebug(
136             "In AnotherUnusedVirtualFunction in " << m_name << ". Num="
137                                                   << num << ", str = " <<
138             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     MyDelegate funclist[12]; // delegates are initialized to empty
167     CBaseClass a("Base A");
168     CBaseClass b("Base B");
169     CDerivedClass d;
170     CDerivedClass c;
171
172     IntMyDelegate newdeleg;
173     newdeleg = DPL::MakeDelegate(&a,
174                                  &CBaseClass::SimpleMemberFunctionReturnsInt);
175
176     // Binding a simple member function
177     funclist[0].bind(&a, &CBaseClass::SimpleMemberFunction);
178
179     // You can also bind static (free) functions
180     funclist[1].bind(&SimpleStaticFunction);
181
182     // and static member functions
183     funclist[2].bind(&CBaseClass::StaticMemberFunction);
184
185     // and const member functions (these only need a const class pointer).
186     funclist[3].bind((const CBaseClass *) &a,
187                      &CBaseClass::ConstMemberFunction);
188
189     funclist[4].bind(&a, &CBaseClass::ConstMemberFunction);
190
191     // and virtual member functions
192     funclist[5].bind(&b, &CBaseClass::SimpleVirtualFunction);
193
194     // You can also use the = operator. For static functions, a fastdelegate
195     // looks identical to a simple function pointer.
196     funclist[6] = &CBaseClass::StaticMemberFunction;
197
198     // The weird rule about the class of derived member function pointers
199     // is avoided. For MSVC, you can use &CDerivedClass::SimpleVirtualFunction
200     // here, but DMC will complain. Note that as well as .bind(), you can also
201     // use the MakeDelegate() global function.
202     funclist[7] = DPL::MakeDelegate(&d, &CBaseClass::SimpleVirtualFunction);
203
204     // The worst case is an abstract virtual function of a virtually-derived
205     // class with at least one non-virtual base class. This is a VERY obscure
206     // situation, which you're unlikely to encounter in the real world.
207     // FastDelegate versions prior to 1.3 had problems with this case on VC6.
208     // Now, it works without problems on all compilers.
209     funclist[8].bind(&c, &CDerivedClass::TrickyVirtualFunction);
210
211     // BUT... in such cases you should be using the base class as an
212     // interface, anyway.
213     funclist[9].bind(&c, &COtherClass::TrickyVirtualFunction);
214
215     // Calling a function that was first declared in the derived class is
216     // straightforward
217     funclist[10] = DPL::MakeDelegate(&c, &CDerivedClass::SimpleDerivedFunction);
218
219     // You can also bind directly using the constructor
220     MyDelegate dg(&b, &CBaseClass::SimpleVirtualFunction);
221
222     const char *msg = "Looking for equal delegate";
223
224     for (int i = 0; i < 12; i++) {
225         LogDebug(i << ":");
226
227         // The == and != operators are provided
228         // Note that they work even for inline functions.
229         if (funclist[i] == dg) {
230             msg = "Found equal delegate";
231         }
232
233         // operator ! can be used to test for an empty delegate
234         // You can also use the .empty() member function.
235         if (!funclist[i]) {
236             LogDebug("Delegate is empty");
237         } else {
238             // Invocation generates optimal assembly code.
239             funclist[i](i, msg);
240         }
241     }
242 }