SolidUtils
UnitTest.hpp
Go to the documentation of this file.
1 
32 #ifndef SOLIDUTILS_INCLUDE_UNITTEST_HPP
33 #define SOLIDUTILS_INCLUDE_UNITTEST_HPP
34 
35 
36 #include <stdexcept>
37 #include <exception>
38 #include <string>
39 #include <iostream>
40 #include <sstream>
41 
42 #include <cmath>
43 
44 
45 /******************************************************************************
46 * CLASSES AND TYPES ***********************************************************
47 ******************************************************************************/
48 
49 namespace sl
50 {
51 
52 
53 volatile int _unittest_numberFailed = 0;
54 volatile int _unittest_numberPassed = 0;
55 
56 
57 namespace
58 {
59 
60 
61 class TestFailed : public std::logic_error
62 {
63  public:
64  TestFailed(std::string const & str) :
65  std::logic_error(str)
66  {
67  // do nothing
68  }
69 };
70 
71 
72 class TestStream
73 {
74  public:
75  TestStream() :
76  m_stream(),
77  m_fail(false)
78  {
79  // do nothing
80  }
81 
82 
83  ~TestStream() noexcept(false)
84  {
85  if (m_fail) {
86  // write new line
87  std::cerr << std::endl;
88  // throw our error
89  throw TestFailed("Unit test failed.");
90  }
91  }
92 
93 
94  std::ostream & test()
95  {
96  if (m_fail) {
97  return std::cerr << "Test Failed: ";
98  } else {
99  return m_stream;
100  }
101  }
102 
103 
104  std::ostream & testFail()
105  {
106  m_fail = true;
107 
108  return test();
109  }
110 
111 
112  std::ostream & testEqual(
113  std::string const & a,
114  std::string const & b)
115  {
116  if (!m_fail) {
117  m_fail = !(a.compare(b) == 0);
118  }
119 
120  return test();
121  }
122 
123 
124  template<typename A, typename B>
125  std::ostream & testEqual(
126  A const & a,
127  B const & b)
128  {
129  if (!m_fail) {
130  m_fail = !(a == b);
131  }
132 
133  return test();
134  }
135 
136 
137  std::ostream & testNearEqual(
138  double const a,
139  double const b,
140  double const ratio = 1e-6,
141  double const buffer = 1e-9)
142  {
143  if (std::abs(a - b) <= buffer) {
144  m_fail = false;
145  } else if (-a == b) {
146  m_fail = true;
147  } else {
148  m_fail = std::abs((a-b)/(a+b)) >= ratio;
149  }
150 
151  return test();
152  }
153 
154 
155  template<typename A, typename B>
156  std::ostream & testNotEqual(
157  A const & a,
158  B const & b)
159  {
160  if (!m_fail) {
161  m_fail = (a == b);
162  }
163 
164  return test();
165  }
166 
167 
168  std::ostream & testTrue(
169  bool const pass)
170  {
171  if (!m_fail) {
172  m_fail = !pass;
173  }
174 
175  return test();
176  }
177 
178 
179  std::ostream & testFalse(
180  bool const fail)
181  {
182  if (!m_fail) {
183  m_fail = fail;
184  }
185 
186  return test();
187  }
188 
189 
190  template<typename A, typename B>
191  std::ostream & testGreater(
192  A const & a,
193  B const & b)
194  {
195  if (!m_fail) {
196  m_fail = !(a > b);
197  }
198 
199  return test();
200  }
201 
202 
203  template<typename A, typename B>
204  std::ostream & testGreaterOrEqual(
205  A const & a,
206  B const & b)
207  {
208  if (!m_fail) {
209  m_fail = !(a >= b);
210  }
211 
212  return test();
213  }
214 
215 
216  template<typename A, typename B>
217  std::ostream & testLess(
218  A const & a,
219  B const & b)
220  {
221  if (!m_fail) {
222  m_fail = !(a < b);
223  }
224 
225  return test();
226  }
227 
228 
229  template<typename A, typename B>
230  std::ostream & testLessOrEqual(
231  A const & a,
232  B const & b)
233  {
234  if (!m_fail) {
235  m_fail = !(a <= b);
236  }
237 
238  return test();
239  }
240 
241 
242 
243  private:
244  std::ostringstream m_stream;
245  bool m_fail;
246 };
247 
248 
249 bool UnitTest(
250  char const * name,
251  void (*test)(void))
252 {
253  try {
254  test();
255  std::cerr << "Test " << name << " PASSED." << std::endl;
256  ++_unittest_numberPassed;
257  return true;
258  } catch (TestFailed const &) {
259  std::cerr << "Test " << name << " FAILED." << std::endl;
260  ++_unittest_numberFailed;
261  return false;
262  }
263 }
264 
265 }
266 
267 
268 }
269 
270 
271 /******************************************************************************
272 * TESTS ***********************************************************************
273 ******************************************************************************/
274 
275 
276 #define testFail() \
277  sl::TestStream().testFail() << "testFail() called at " << __LINE__ << \
278  std::endl
279 
280 
281 #define testEqual(a,b) \
282  sl::TestStream().testEqual(a,b) << #a << ":'" << (a) \
283  << "' != " << #b << ":'" << (b) << "' at " << __LINE__ << std::endl
284 
285 
286 #define testNotEqual(a,b) \
287  sl::TestStream().testNotEqual(a,b) << #a << ":'" << (a) \
288  << "' == " << #b << ":'" << (b) << "' at " << __LINE__ << std::endl
289 
290 
291 #define testTrue(a) \
292  sl::TestStream().testTrue(a) << #a << "' is false at: " << __LINE__ \
293  << std::endl
294 
295 
296 #define testFalse(a) \
297  sl::TestStream().testFalse(a) << #a << "' is true at: " << __LINE__ \
298  << std::endl
299 
300 
301 #define testGreater(a,b) \
302  sl::TestStream().testGreater(a,b) << #a << ":'" << (a) << "' <= " << #b \
303  << ":'" << (b) << "' at " << __LINE__ << std::endl
304 
305 
306 #define testGreaterOrEqual(a,b) \
307  sl::TestStream().testGreaterOrEqual(a,b) << #a << ":'" << (a) << "' < " << \
308  #b << ":'" << (b) << "' at " << __LINE__ << std::endl
309 
310 
311 #define testLess(a,b) \
312  sl::TestStream().testLess(a,b) << #a << ":'" << (a) << "' >= " << #b << \
313  ":'" << (b) << "' at " << __LINE__ << std::endl
314 
315 
316 #define testLessOrEqual(a,b) \
317  sl::TestStream().testLessOrEqual(a,b) << #a << ":'" << (a) << "' > " << #b \
318  << ":'" << (b) << "' at " << __LINE__ << std::endl
319 
320 
321 #define testNearEqual(a, b, c, d) \
322  sl::TestStream().testNearEqual(a, b, c, d) << #a << ":'" << (a) \
323  << "' != " << #b << ":'" << (b) << "' at " << __LINE__ << std::endl
324 
325 
326 #define UNITTEST(CLASS, TEST) \
327  void _unittest_ ## CLASS ## _ ## TEST ## _func(void); \
328  bool _unittest_ ## CLASS ## _ ## TEST ## _result = \
329  sl::UnitTest( \
330  __FILE__":"#CLASS"->"#TEST, \
331  _unittest_ ## CLASS ## _ ## TEST ## _func); \
332  void _unittest_ ## CLASS ## _ ## TEST ## _func(void) \
333 
334 
335 
336 
337 /******************************************************************************
338 * MAIN ************************************************************************
339 ******************************************************************************/
340 
341 
342 int main(
343  int argc,
344  char ** argv)
345 {
346  // make sure we don't have any useless arguments
347  if (argc > 1) {
348  for (int i=1; i<argc; ++i) {
349  std::cerr << "Unused parameter: " << argv[i] << std::endl;
350  }
351  return 2;
352  }
353 
354 
355 
356  if (sl::_unittest_numberPassed == 0 && \
357  sl::_unittest_numberFailed == 0) {
358  std::cerr << "No tests run." << std::endl;
359  return 3;
360  }
361 
362  std::cout << sl::_unittest_numberPassed << " tests passed." << \
363  std::endl;
364  std::cout << sl::_unittest_numberFailed << " tests failed." << \
365  std::endl;
366 
367  if (sl::_unittest_numberFailed == 0) {
368  return 0;
369  } else {
370  return 1;
371  }
372 }
373 
374 
375 
376 
377 #endif
Definition: Alloc.hpp:40