Lumiera  0.pre.03
»edityourfreedom«
function-erasure-test.cpp
Go to the documentation of this file.
1 /*
2  FunctionErasure(Test) - verify the wrapping of functor object with type erasure
3 
4  Copyright (C) Lumiera.org
5  2009, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
28 #include "lib/test/run.hpp"
29 #include "lib/test/test-helper.hpp"
31 #include "lib/error.hpp"
32 #include "meta/dummy-functions.hpp"
33 
34 #include <functional>
35 
36 using ::test::Test;
37 using lumiera::error::LUMIERA_ERROR_ASSERTION;
38 
39 
40 
41 namespace lib {
42 namespace meta {
43 namespace test {
44 
45  using std::function;
46  using std::placeholders::_1;
47  using std::placeholders::_2;
48  using std::bind;
49 
50 
54 
55  template<class HOL>
56  struct BuildEmptyFunctor { typedef long (*Type)(int,char); };
57  template<>
58  struct BuildEmptyFunctor<Efun> { typedef function<long(int,char)> Type; };
59 
60 
61  /*******************************************************************/
70  class FunctionErasure_test : public Test
71  {
72  virtual void
73  run (Arg)
74  {
75  function<void(int,char)> bindFunc = bind (testFunc,_1,_2);
76  function<void(int )> pAplFunc = bind (testFunc,_1,'x');
77  function<void( char)> membFunc = bind (&FunctionErasure_test::testMemberFunction,this, _1);
78 
79  function<int(void)> getterFunc = &returnIt;
80 
81  check_FunctorContainer( Efun (testFunc)
82  , Efun (bindFunc)
83  , Efun (pAplFunc)
84  , Efun (membFunc)
85  , Efun (getterFunc)
86  );
87 
88  check_FunctPtrHolder(Efp(testFunc),Efp(&testFunc), Efp(returnIt));
89  check_VoidPtrHolder(Evoid(testFunc),Evoid(&testFunc),Evoid(returnIt));
90 
91  check_Comparisons (Efun(testFunc), Efun(bindFunc));
92  check_Comparisons (Efun(testFunc), Efun(pAplFunc));
93  check_Comparisons (Efun(testFunc), Efun(membFunc));
94  check_Comparisons (Efun(testFunc), Efun(getterFunc));
95  check_Comparisons (Efun(bindFunc), Efun(pAplFunc));
96  check_Comparisons (Efun(bindFunc), Efun(membFunc));
97  check_Comparisons (Efun(bindFunc), Efun(getterFunc));
98  check_Comparisons (Efun(pAplFunc), Efun(membFunc));
99  check_Comparisons (Efun(pAplFunc), Efun(getterFunc));
100  check_Comparisons (Efun(membFunc), Efun(getterFunc));
101 
102  check_Comparisons (Efp(testFunc), Efp(returnIt));
103  check_Comparisons (Evoid(testFunc), Evoid(returnIt));
104 
105  CHECK ( detect_Clone (Efun(testFunc)));
106  CHECK (!detect_Clone (Efun(bindFunc))); //note equality not detected when cloning a bind term
107  CHECK (!detect_Clone (Efun(pAplFunc))); //similarly
108  CHECK (!detect_Clone (Efun(membFunc))); //analogous for bound member function
109  CHECK ( detect_Clone (Efp(testFunc) ));
110  CHECK ( detect_Clone (Evoid(testFunc)));
111 
112  detect_unboundFunctor(Efun(testFunc), Efun(getterFunc), Efun(membFunc));
113  detect_unboundFunctor(Efp(testFunc),Efp(&testFunc), Efp(returnIt));
114  detect_unboundFunctor(Evoid(testFunc),Evoid(&testFunc),Evoid(returnIt));
115  }
116 
117  void
119  {
120  return testFunc('a'-'A', c);
121  }
122 
123 
124  void
125  check_FunctorContainer (Efun f1, Efun f2, Efun f3, Efun f4, Efun f5)
126  {
127  typedef void (Sig1) (int,char);
128  typedef void (Sig2) (int);
129  typedef void (Sig3) (char);
130  typedef int (Sig4) ();
131 
132  _sum_ = 0;
133  f1.getFun<Sig1>() (-11,'M'); // invoke stored std::function...
134  CHECK (_sum_ == 'M'-11);
135 
136  _sum_ = 0;
137  f2.getFun<Sig1>() (-22,'M');
138  CHECK (_sum_ == 'M'-22);
139 
140  _sum_ = 0;
141  f3.getFun<Sig2>() (-33);
142  CHECK (_sum_ == 'x'-33);
143 
144  _sum_ = 0;
145  f4.getFun<Sig3>() ('U');
146  CHECK (_sum_ == 'u');
147 
148  CHECK ( 'u' == f5.getFun<Sig4>() () );
149  CHECK (INSTANCEOF (function<Sig4>, &f5.getFun<Sig4>()));
150 
151 
152 #if false
153  VERIFY_ERROR (ASSERTION, f1.getFun<Sig2>() );
154  VERIFY_ERROR (ASSERTION, f1.getFun<Sig3>() );
155  VERIFY_ERROR (ASSERTION, f1.getFun<Sig4>() );
156 
157  VERIFY_ERROR (ASSERTION, f2.getFun<Sig2>() );
158  VERIFY_ERROR (ASSERTION, f3.getFun<Sig3>() );
159  VERIFY_ERROR (ASSERTION, f2.getFun<Sig4>() );
160 
161  VERIFY_ERROR (ASSERTION, f3.getFun<Sig1>() );
162  VERIFY_ERROR (ASSERTION, f3.getFun<Sig3>() );
163  VERIFY_ERROR (ASSERTION, f3.getFun<Sig4>() );
164 
165  VERIFY_ERROR (ASSERTION, f4.getFun<Sig1>() );
166  VERIFY_ERROR (ASSERTION, f4.getFun<Sig2>() );
167  VERIFY_ERROR (ASSERTION, f4.getFun<Sig4>() );
168 
169  VERIFY_ERROR (ASSERTION, f5.getFun<Sig1>() );
170  VERIFY_ERROR (ASSERTION, f5.getFun<Sig2>() );
171  VERIFY_ERROR (ASSERTION, f5.getFun<Sig3>() );
172 #endif
173  }
174 
175 
176  void
177  check_FunctPtrHolder (Efp f1, Efp f2, Efp f3)
178  {
179  typedef void (*FP)(int,char);
180  typedef void (&FR)(int,char);
181 
182  FP fun1 = &f1.getFun<void(int,char)>();
183  FP fun2 = &f2.getFun<void(int,char)>();
184  FR fun2r = f2.getFun<void(int,char)>();
185 
186  _sum_ = 0;
187  (*fun1) (10, 'a'); // invoke retrieved function pointer
188  CHECK (_sum_ == 10+'a');
189 
190  (*fun2) (20, 'b');
191  CHECK (_sum_ == 10+'a'+20+'b');
192 
193  fun2r (30, 'c');
194  CHECK (_sum_ == 10+'a'+20+'b'+30+'c');
195 
196  CHECK (_sum_ == (f3.getFun<int(void)>()) () );
197 
198 #if false
199  VERIFY_ERROR (ASSERTION, f1.getFun<int(int)>() );
200 #endif
201 
202  }
203 
204 
205  void
206  check_VoidPtrHolder (Evoid f1, Evoid f2, Evoid f3)
207  {
208  typedef void (*FP)(int,char);
209  typedef void (&FR)(int,char);
210 
211  FP fun1 = &f1.getFun<void(int,char)>();
212  FP fun2 = &f2.getFun<void(int,char)>();
213  FR fun2r = f2.getFun<void(int,char)>();
214 
215  _sum_ = 0;
216  (*fun1) (10, 'a');
217  CHECK (_sum_ == 10+'a');
218 
219  (*fun2) (20, 'b');
220  CHECK (_sum_ == 10+'a'+20+'b');
221 
222  fun2r (30, 'c');
223  CHECK (_sum_ == 10+'a'+20+'b'+30+'c');
224 
225  CHECK (_sum_ == (f3.getFun<int(void)>()) () );
226 
227  FP bad_fun = &f3.getFun<void(int,char)>();
228  CHECK ((void*)bad_fun == &returnIt); // got wrong function!
229 
230  //(*bad_fun) (11, 'x'); // The compiler would accept this line!
231  } // likely to result in heap corruption or SEGV
232 
233 
234  template<class HOL>
235  void
236  check_Comparisons (HOL h1, HOL h2)
237  {
238  CHECK (h1 == h1); CHECK (!(h1 != h1));
239  CHECK (h2 == h2); CHECK (!(h2 != h2));
240 
241  CHECK (h1 != h2);
242  CHECK (h2 != h1);
243  }
244 
245 
246  template<class HOL>
247  bool
248  detect_Clone (HOL const& h1)
249  {
250  HOL clone (h1);
251  return (clone == h1);
252  }
253 
254 
255  template<class HOL>
256  void
257  detect_unboundFunctor (HOL h1, HOL h2, HOL h3)
258  {
259  // fabricate a suitable, unbound functor to wrap...
260  typedef typename BuildEmptyFunctor<HOL>::Type NoFunc;
261  NoFunc noFunction = NoFunc();
262 
263  // wrap this (actually empty) functor into the holder type
264  HOL emptyHolder (noFunction);
265 
266  // verify the older detects that the wrapped functor is empty
267  CHECK (!emptyHolder);
268 
269  // cross-verify that non-empty functors are not flagged as empty
270  CHECK ( h1 );
271  CHECK ( h2 );
272  CHECK ( h3 );
273  }
274 
275 
276  };
277 
278 
280  LAUNCHER (FunctionErasure_test, "unit common");
281 
282 
283 
284 }}} // namespace lib::meta::test
void detect_unboundFunctor(HOL h1, HOL h2, HOL h3)
FunErasure< StoreUncheckedFunPtr > Evoid
Definition: run.hpp:49
#define INSTANCEOF(CLASS, EXPR)
shortcut for subclass test, intended for assertions only.
Definition: util.hpp:404
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify a statement indeed raises an exception.
Implementation namespace for support and library code.
LAUNCHER(ConfigFlags_test, "unit common")
Register this test class...
std::vector< string > & Arg
Definition: run.hpp:54
Generic wrapper carrying a function object while hiding the actual function signature.
Simple test class runner.
FunErasure< StoreFunction > Efun
dummy functions to support unit testing of function metaprogramming helpers
A collection of frequently used helper functions to support unit testing.
Generic holder for functor objects, concealing the concrete function type.
Lumiera error handling (C++ interface).
void check_VoidPtrHolder(Evoid f1, Evoid f2, Evoid f3)
void check_FunctorContainer(Efun f1, Efun f2, Efun f3, Efun f4, Efun f5)
FunErasure< StoreFunPtr > Efp
void check_FunctPtrHolder(Efp f1, Efp f2, Efp f3)