Lumiera  0.pre.03
»edit your freedom«
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 
51  typedef FunErasure<StoreFunction> Efun;
52  typedef FunErasure<StoreFunPtr> Efp;
53  typedef FunErasure<StoreUncheckedFunPtr> Evoid;
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  detect_unboundFunctor(Efun(testFunc), Efun(getterFunc), Efun(membFunc));
92  detect_unboundFunctor(Efp(testFunc),Efp(&testFunc), Efp(returnIt));
93  detect_unboundFunctor(Evoid(testFunc),Evoid(&testFunc),Evoid(returnIt));
94  }
95 
96  void
98  {
99  return testFunc('a'-'A', c);
100  }
101 
102 
103  void
104  check_FunctorContainer (Efun f1, Efun f2, Efun f3, Efun f4, Efun f5)
105  {
106  typedef void (Sig1) (int,char);
107  typedef void (Sig2) (int);
108  typedef void (Sig3) (char);
109  typedef int (Sig4) ();
110 
111  _sum_ = 0;
112  f1.getFun<Sig1>() (-11,'M'); // invoke stored std::function...
113  CHECK (_sum_ == 'M'-11);
114 
115  _sum_ = 0;
116  f2.getFun<Sig1>() (-22,'M');
117  CHECK (_sum_ == 'M'-22);
118 
119  _sum_ = 0;
120  f3.getFun<Sig2>() (-33);
121  CHECK (_sum_ == 'x'-33);
122 
123  _sum_ = 0;
124  f4.getFun<Sig3>() ('U');
125  CHECK (_sum_ == 'u');
126 
127  CHECK ( 'u' == f5.getFun<Sig4>() () );
128  CHECK (INSTANCEOF (function<Sig4>, &f5.getFun<Sig4>()));
129 
130 
131 #if false
132  VERIFY_ERROR (ASSERTION, f1.getFun<Sig2>() );
133  VERIFY_ERROR (ASSERTION, f1.getFun<Sig3>() );
134  VERIFY_ERROR (ASSERTION, f1.getFun<Sig4>() );
135 
136  VERIFY_ERROR (ASSERTION, f2.getFun<Sig2>() );
137  VERIFY_ERROR (ASSERTION, f3.getFun<Sig3>() );
138  VERIFY_ERROR (ASSERTION, f2.getFun<Sig4>() );
139 
140  VERIFY_ERROR (ASSERTION, f3.getFun<Sig1>() );
141  VERIFY_ERROR (ASSERTION, f3.getFun<Sig3>() );
142  VERIFY_ERROR (ASSERTION, f3.getFun<Sig4>() );
143 
144  VERIFY_ERROR (ASSERTION, f4.getFun<Sig1>() );
145  VERIFY_ERROR (ASSERTION, f4.getFun<Sig2>() );
146  VERIFY_ERROR (ASSERTION, f4.getFun<Sig4>() );
147 
148  VERIFY_ERROR (ASSERTION, f5.getFun<Sig1>() );
149  VERIFY_ERROR (ASSERTION, f5.getFun<Sig2>() );
150  VERIFY_ERROR (ASSERTION, f5.getFun<Sig3>() );
151 #endif
152  }
153 
154 
155  void
156  check_FunctPtrHolder (Efp f1, Efp f2, Efp f3)
157  {
158  typedef void (*FP)(int,char);
159  typedef void (&FR)(int,char);
160 
161  FP fun1 = &f1.getFun<void(int,char)>();
162  FP fun2 = &f2.getFun<void(int,char)>();
163  FR fun2r = f2.getFun<void(int,char)>();
164 
165  _sum_ = 0;
166  (*fun1) (10, 'a'); // invoke retrieved function pointer
167  CHECK (_sum_ == 10+'a');
168 
169  (*fun2) (20, 'b');
170  CHECK (_sum_ == 10+'a'+20+'b');
171 
172  fun2r (30, 'c');
173  CHECK (_sum_ == 10+'a'+20+'b'+30+'c');
174 
175  CHECK (_sum_ == (f3.getFun<int(void)>()) () );
176  }
177 
178 
179  void
180  check_VoidPtrHolder (Evoid f1, Evoid f2, Evoid f3)
181  {
182  typedef void (*FP)(int,char);
183  typedef void (&FR)(int,char);
184 
185  FP fun1 = &f1.getFun<void(int,char)>();
186  FP fun2 = &f2.getFun<void(int,char)>();
187  FR fun2r = f2.getFun<void(int,char)>();
188 
189  _sum_ = 0;
190  (*fun1) (10, 'a');
191  CHECK (_sum_ == 10+'a');
192 
193  (*fun2) (20, 'b');
194  CHECK (_sum_ == 10+'a'+20+'b');
195 
196  fun2r (30, 'c');
197  CHECK (_sum_ == 10+'a'+20+'b'+30+'c');
198 
199  CHECK (_sum_ == (f3.getFun<int(void)>()) () );
200 
201  FP bad_fun = &f3.getFun<void(int,char)>();
202  CHECK ((void*)bad_fun == &returnIt); // got wrong function!
203 
204  //(*bad_fun) (11, 'x'); // The compiler would accept this line!
205  } // likely to result in heap corruption or SEGV
206 
207 
208  template<class HOL>
209  void
210  detect_unboundFunctor (HOL h1, HOL h2, HOL h3)
211  {
212  // fabricate a suitable, unbound functor to wrap...
213  typedef typename BuildEmptyFunctor<HOL>::Type NoFunc;
214  NoFunc noFunction = NoFunc();
215 
216  // wrap this (actually empty) functor into the holder type
217  HOL emptyHolder (noFunction);
218 
219  // verify the older detects that the wrapped functor is empty
220  CHECK (!emptyHolder);
221 
222  // cross-verify that non-empty functors are not flagged as empty
223  CHECK ( h1 );
224  CHECK ( h2 );
225  CHECK ( h3 );
226  }
227 
228 
229  };
230 
231 
233  LAUNCHER (FunctionErasure_test, "unit common");
234 
235 
236 
237 }}} // namespace lib::meta::test
Definition: run.hpp:49
#define INSTANCEOF(CLASS, EXPR)
shortcut for subclass test, intended for assertions only.
Definition: util.hpp:492
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
Implementation namespace for support and library code.
Simple test class runner.
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).
int _sum_
used to verify the effect of testFunc