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)
5  2009, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 * *****************************************************************/
13 
19 #include "lib/test/run.hpp"
20 #include "lib/test/test-helper.hpp"
22 #include "lib/error.hpp"
23 #include "meta/dummy-functions.hpp"
24 
25 #include <functional>
26 
27 using ::test::Test;
28 using lumiera::error::LUMIERA_ERROR_ASSERTION;
29 
30 
31 
32 namespace lib {
33 namespace meta {
34 namespace test {
35 
36  using std::function;
37  using std::placeholders::_1;
38  using std::placeholders::_2;
39  using std::bind;
40 
41 
42  typedef FunErasure<StoreFunction> Efun;
43  typedef FunErasure<StoreFunPtr> Efp;
44  typedef FunErasure<StoreUncheckedFunPtr> Evoid;
45 
46  template<class HOL>
47  struct BuildEmptyFunctor { typedef long (*Type)(int,char); };
48  template<>
49  struct BuildEmptyFunctor<Efun> { typedef function<long(int,char)> Type; };
50 
51 
52  /*******************************************************************/
61  class FunctionErasure_test : public Test
62  {
63  virtual void
64  run (Arg)
65  {
66  function<void(int,char)> bindFunc = bind (testFunc,_1,_2);
67  function<void(int )> pAplFunc = bind (testFunc,_1,'x');
68  function<void( char)> membFunc = bind (&FunctionErasure_test::testMemberFunction,this, _1);
69 
70  function<int(void)> getterFunc = &returnIt;
71 
72  check_FunctorContainer( Efun (testFunc)
73  , Efun (bindFunc)
74  , Efun (pAplFunc)
75  , Efun (membFunc)
76  , Efun (getterFunc)
77  );
78 
79  check_FunctPtrHolder(Efp(testFunc),Efp(&testFunc), Efp(returnIt));
80  check_VoidPtrHolder(Evoid(testFunc),Evoid(&testFunc),Evoid(returnIt));
81 
82  detect_unboundFunctor(Efun(testFunc), Efun(getterFunc), Efun(membFunc));
83  detect_unboundFunctor(Efp(testFunc),Efp(&testFunc), Efp(returnIt));
84  detect_unboundFunctor(Evoid(testFunc),Evoid(&testFunc),Evoid(returnIt));
85  }
86 
87  void
89  {
90  return testFunc('a'-'A', c);
91  }
92 
93 
94  void
95  check_FunctorContainer (Efun f1, Efun f2, Efun f3, Efun f4, Efun f5)
96  {
97  typedef void (Sig1) (int,char);
98  typedef void (Sig2) (int);
99  typedef void (Sig3) (char);
100  typedef int (Sig4) ();
101 
102  _sum_ = 0;
103  f1.getFun<Sig1>() (-11,'M'); // invoke stored std::function...
104  CHECK (_sum_ == 'M'-11);
105 
106  _sum_ = 0;
107  f2.getFun<Sig1>() (-22,'M');
108  CHECK (_sum_ == 'M'-22);
109 
110  _sum_ = 0;
111  f3.getFun<Sig2>() (-33);
112  CHECK (_sum_ == 'x'-33);
113 
114  _sum_ = 0;
115  f4.getFun<Sig3>() ('U');
116  CHECK (_sum_ == 'u');
117 
118  CHECK ( 'u' == f5.getFun<Sig4>() () );
119  CHECK (INSTANCEOF (function<Sig4>, &f5.getFun<Sig4>()));
120 
121 
122 #if false
123  VERIFY_ERROR (ASSERTION, f1.getFun<Sig2>() );
124  VERIFY_ERROR (ASSERTION, f1.getFun<Sig3>() );
125  VERIFY_ERROR (ASSERTION, f1.getFun<Sig4>() );
126 
127  VERIFY_ERROR (ASSERTION, f2.getFun<Sig2>() );
128  VERIFY_ERROR (ASSERTION, f3.getFun<Sig3>() );
129  VERIFY_ERROR (ASSERTION, f2.getFun<Sig4>() );
130 
131  VERIFY_ERROR (ASSERTION, f3.getFun<Sig1>() );
132  VERIFY_ERROR (ASSERTION, f3.getFun<Sig3>() );
133  VERIFY_ERROR (ASSERTION, f3.getFun<Sig4>() );
134 
135  VERIFY_ERROR (ASSERTION, f4.getFun<Sig1>() );
136  VERIFY_ERROR (ASSERTION, f4.getFun<Sig2>() );
137  VERIFY_ERROR (ASSERTION, f4.getFun<Sig4>() );
138 
139  VERIFY_ERROR (ASSERTION, f5.getFun<Sig1>() );
140  VERIFY_ERROR (ASSERTION, f5.getFun<Sig2>() );
141  VERIFY_ERROR (ASSERTION, f5.getFun<Sig3>() );
142 #endif
143  }
144 
145 
146  void
147  check_FunctPtrHolder (Efp f1, Efp f2, Efp f3)
148  {
149  typedef void (*FP)(int,char);
150  typedef void (&FR)(int,char);
151 
152  FP fun1 = &f1.getFun<void(int,char)>();
153  FP fun2 = &f2.getFun<void(int,char)>();
154  FR fun2r = f2.getFun<void(int,char)>();
155 
156  _sum_ = 0;
157  (*fun1) (10, 'a'); // invoke retrieved function pointer
158  CHECK (_sum_ == 10+'a');
159 
160  (*fun2) (20, 'b');
161  CHECK (_sum_ == 10+'a'+20+'b');
162 
163  fun2r (30, 'c');
164  CHECK (_sum_ == 10+'a'+20+'b'+30+'c');
165 
166  CHECK (_sum_ == (f3.getFun<int(void)>()) () );
167  }
168 
169 
170  void
171  check_VoidPtrHolder (Evoid f1, Evoid f2, Evoid f3)
172  {
173  typedef void (*FP)(int,char);
174  typedef void (&FR)(int,char);
175 
176  FP fun1 = &f1.getFun<void(int,char)>();
177  FP fun2 = &f2.getFun<void(int,char)>();
178  FR fun2r = f2.getFun<void(int,char)>();
179 
180  _sum_ = 0;
181  (*fun1) (10, 'a');
182  CHECK (_sum_ == 10+'a');
183 
184  (*fun2) (20, 'b');
185  CHECK (_sum_ == 10+'a'+20+'b');
186 
187  fun2r (30, 'c');
188  CHECK (_sum_ == 10+'a'+20+'b'+30+'c');
189 
190  CHECK (_sum_ == (f3.getFun<int(void)>()) () );
191 
192  FP bad_fun = &f3.getFun<void(int,char)>();
193  CHECK ((void*)bad_fun == &returnIt); // got wrong function!
194 
195  //(*bad_fun) (11, 'x'); // The compiler would accept this line!
196  } // likely to result in heap corruption or SEGV
197 
198 
199  template<class HOL>
200  void
201  detect_unboundFunctor (HOL h1, HOL h2, HOL h3)
202  {
203  // fabricate a suitable, unbound functor to wrap...
204  typedef typename BuildEmptyFunctor<HOL>::Type NoFunc;
205  NoFunc noFunction = NoFunc();
206 
207  // wrap this (actually empty) functor into the holder type
208  HOL emptyHolder (noFunction);
209 
210  // verify the older detects that the wrapped functor is empty
211  CHECK (!emptyHolder);
212 
213  // cross-verify that non-empty functors are not flagged as empty
214  CHECK ( h1 );
215  CHECK ( h2 );
216  CHECK ( h3 );
217  }
218 
219 
220  };
221 
222 
224  LAUNCHER (FunctionErasure_test, "unit common");
225 
226 
227 
228 }}} // namespace lib::meta::test
Definition: run.hpp:40
#define INSTANCEOF(CLASS, EXPR)
shortcut for subclass test, intended for assertions only.
Definition: util.hpp:514
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
Implementation namespace for support and library code.
Simplistic 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