Doc -- compile fix
[lilypond/mpolesky.git] / flower / include / yaffut.hh
blobe324922b69738c60abbc17c7ab88b46ef3b789b8
1 // Copyright 2006 Rutger E.W. van Beusekom.
2 // Distributed under the Boost Software License, Version 1.0. (See
3 // accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
6 #ifndef __YAFFUT_H__
7 #define __YAFFUT_H__
9 #include <cxxabi.h>
11 #include <cmath>
12 #include <cstring>
13 #include <iostream>
14 #include <limits>
15 #include <map>
16 #include <memory>
17 #include <sstream>
18 #include <stdexcept>
20 #define YAFFUT_STRINGIZE(x) YAFFUT_STRINGIZE_(x)
21 #define YAFFUT_STRINGIZE_(x) #x
23 #define __YAFFUT_AT__ __FILE__ ":" YAFFUT_STRINGIZE(__LINE__)": "
24 #ifndef __AT__
25 #define __AT__ __YAFFUT_AT__
26 #endif
28 #define YAFFUT_EQUAL(e,a) \
29 yaffut::equal (e ,a , __YAFFUT_AT__, "EQUAL(" #e " == " #a ") failed ")
30 #ifndef EQUAL
31 #define EQUAL YAFFUT_EQUAL
32 #endif
34 #define YAFFUT_UNEQUAL(e,a) \
35 yaffut::unequal (e, a, __YAFFUT_AT__, "UNEQUAL(" #e " != " #a ") failed ")
36 #ifndef UNEQUAL
37 #define UNEQUAL YAFFUT_UNEQUAL
38 #endif
40 #define YAFFUT_CHECK(e) \
41 yaffut::check (e, __YAFFUT_AT__, "CHECK(" #e ") failed ")
42 #ifndef CHECK
43 #define CHECK YAFFUT_CHECK
44 #endif
46 #define YAFFUT_FAIL(s) yaffut::fail (s, __YAFFUT_AT__);
47 #ifndef FAIL
48 #define FAIL YAFFUT_FAIL
49 #endif
51 #define YAFFUT_ASSERT_THROW(s, e) \
52 try \
53 { \
54 s; \
55 throw yaffut::failure (__YAFFUT_AT__, #s " failed to throw"); \
56 } \
57 catch(const e&){}
58 #ifndef ASSERT_THROW
59 #define ASSERT_THROW YAFFUT_ASSERT_THROW
60 #endif
62 namespace yaffut {
64 template <typename T>
65 std::string demangle()
67 size_t sz;
68 int status;
69 char* ptr = abi::__cxa_demangle(typeid(T).name(), 0, &sz, &status);
70 std::string name(ptr ? ptr : "", ptr ? strlen(ptr) : 0);
71 if(ptr){ free(ptr); }
72 std::string::size_type pos = name.rfind("::");
73 if(pos != std::string::npos)
75 name = name.substr(pos + 2);
77 return name;
80 struct ITest
82 virtual ~ITest(){}
85 class Factory
87 public:
88 typedef ITest* (*Create_t) ();
89 private:
90 typedef std::map<std::string, Create_t> Tests_t;
91 Tests_t m_Tests;
92 size_t m_fail;
93 size_t m_pass;
94 private:
95 Factory(){}
96 ~Factory(){}
97 static bool EqualsSuiteName (std::string const &name, std::string const& s)
99 return name.find (':') >= name.length () - 2
100 && s.substr (0, name.length ()) == name;
102 public:
103 static Factory& Instance()
105 static Factory instance;
106 return instance;
108 void Register(const std::string& name, Create_t create)
110 m_Tests[name] = create;
112 size_t Fail () { return m_fail; }
113 void List(const std::string& name)
115 for(Tests_t::const_iterator it = m_Tests.begin(); it != m_Tests.end(); ++it)
117 if(name.empty () || it->first == name
118 || EqualsSuiteName (name, it->first))
119 std::cout << it->first << std::endl;
122 void Run(const std::string& name)
124 for(Tests_t::const_iterator it = m_Tests.begin(); it != m_Tests.end(); ++it)
126 if("All" == name || it->first == name
127 || EqualsSuiteName (name, it->first))
131 std::cout << std::endl << it->first << ' ' << std::flush;
133 std::auto_ptr<ITest> test(it->second());
135 std::cout << "[OK]" << std::flush;
136 ++m_pass;
138 catch(const std::exception& e)
140 std::cout << "[FAIL]\n " << e.what() << std::flush;
141 ++m_fail;
143 catch(...)
145 std::cout << "[FAIL]\n unknown exception" << std::flush;
146 ++m_fail;
151 void Report ()
153 const size_t size = m_Tests.size();
154 std::cout << std::endl;
155 std::cout << "[TOTAL](" << m_pass + m_fail << '/' << size << ")" << std::endl;
156 std::cout << "[OK](" << m_pass << '/' << size << ")" << std::endl;
157 if (m_fail)
158 std::cout << "[FAIL](" << m_fail << '/' << size << ")" << std::endl;
160 int Main (int argc, const char* argv[])
162 if(argc > 1
163 && (std::string(argv[1]) == "-h" || std::string(argv[1]) == "--help"))
165 std::cout << "Yaffut - Yet Another Framework For Unit Testing.\n\n"
166 "Usage: yaffut [OPTION] [Suite:|Suite::Test]...\n\n"
167 "Options:\n"
168 " -h, --help show this help\n"
169 " -l, --list list test cases" << std::endl;
170 return 0;
172 if(argc > 1
173 && (std::string(argv[1]) == "-l" || std::string(argv[1]) == "--list"))
175 Factory::Instance().List(argc > 2 ? argv[2] : "");
176 return 0;
179 const char* all[] = {"All"};
180 const char** test = all;
181 int num = 1;
182 if(1 < argc)
184 test = argv;
185 num = argc;
188 for(int i = 0; i < num; ++i)
192 Factory::Instance().Run(test[i]);
194 catch(const std::exception& e)
196 std::clog << e.what() << std::endl;
200 Factory::Instance().Report ();
201 return Factory::Instance().Fail ();
205 class failure: public std::exception
207 std::string failure_;
208 public:
209 template <typename Expected, typename Actual>
210 failure(const Expected& e, Actual& a, const char* at = "", const char* expr = "")
212 std::ostringstream os;
213 os << at << expr << "\nexpected: "
214 << "(" << demangle<Expected>() << ") " << e
215 << " != actual: " << "(" << demangle<Actual>() << ") " << a;
216 failure_ = os.str();
218 failure(const char* at = "", const char* expr = "")
220 std::ostringstream os;
221 os << at << expr;
222 failure_ = os.str();
224 virtual ~failure() throw() {}
225 virtual const char* what() const throw() { return failure_.c_str(); }
228 template <typename Suite, typename Case>
229 struct Registrator
231 Registrator()
233 Factory::Instance().Register(TestName(), Create);
235 const std::string& TestName()
237 static const std::string name(demangle<Suite>() + "::" + demangle<Case>());
238 return name;
240 static ITest* Create()
242 return new Case;
246 template <typename Case>
247 struct Registrator<Case, void>
249 Registrator()
251 Factory::Instance().Register(TestName(), Create);
253 const std::string& TestName()
255 static const std::string name ("::" + demangle<Case>());
256 return name;
258 static ITest* Create()
260 return new Case;
265 template <typename Suite, typename Case = void>
266 struct Test: public ITest, public virtual Suite
268 static Registrator<Suite, Case> s_Registrator;
269 Test(): Suite()
271 Registrator<Suite, Case>* r = &s_Registrator;
272 r = 0;
274 template <typename E, typename T>
275 void assert_throw(void(T::*mf)(), const char* at)
279 (dynamic_cast<T*> (this)->*mf)();
280 throw yaffut::failure (at, "statement failed to throw");
282 catch(const E&){}
286 template <typename Suite, typename Case>
287 Registrator<Suite, Case> Test<Suite, Case>::s_Registrator;
290 template <typename Case>
291 struct Test<Case, void>: public ITest
293 static Registrator<Case, void> s_Registrator;
294 Test()
296 Registrator<Case, void>* r = &s_Registrator;
297 r = 0;
299 template <typename E, typename T>
300 void assert_throw(void(T::*mf)(), const char* at)
304 (dynamic_cast<T*> (this)->*mf)();
305 throw yaffut::failure (at, "statement failed to throw");
307 catch(const E&){}
311 template <typename Case>
312 Registrator<Case, void> Test<Case, void>::s_Registrator;
316 template <typename Expected, typename Actual>
317 void equal(const Expected& e, const Actual& a, const char* at = "", const char* expr = "")
319 if(e != a)
321 throw failure(e, a, at, expr);
324 inline void equal(double e, double a, const char* at = "", const char* expr = "")
326 double max = std::abs(std::max(e, a));
327 max = max < 1.0 ? 1.0 : max;
328 if(std::abs(e - a) > std::numeric_limits<double>::epsilon() * max)
330 throw failure(e, a, at, expr);
333 inline void check(bool b, const char* at = "", const char* expr = "")
335 if(!b)
337 throw failure(at, expr);
341 template <typename Expected, typename Actual>
342 void unequal(const Expected& e, const Actual& a, const char* at = "", const char* expr = "")
344 if(e == a)
346 throw failure(e, a, at, expr);
349 inline void unequal(double e, double a, const char* at = "", const char* expr = "")
351 double max = std::abs(std::max(e, a));
352 max = max < 1.0 ? 1.0 : max;
353 if(std::abs(e - a) <= std::numeric_limits<double>::epsilon() * max)
355 throw failure(e, a, at, expr);
359 template <typename T>
360 void fail(const T& expr, const char* at = "")
362 std::ostringstream os;
363 os << expr;
364 throw failure(at, os.str().c_str());
367 template <typename E>
368 void assert_throw(void(*pf)(), const char* at = "")
372 (*pf)();
373 throw failure (at, " statement failed to throw");
375 catch(const E&){}
380 //and for those who prefer macro obscurity over typing
381 #define TEST(Suite, Case)\
382 namespace { struct Case: public yaffut::Test<Suite, Case>{ Case(); }; } \
383 template struct yaffut::Test<Suite, Case>; Case::Case()
385 #define FUNC(Case)\
386 namespace { struct Case: public yaffut::Test<Case>{ Case(); }; } \
387 template struct yaffut::Test<Case>; Case::Case()
389 #ifdef YAFFUT_MAIN
391 #include <iostream>
393 int main(int argc, const char* argv[])
395 std::cout << "pid(" << getpid() << ")" << std::endl;
396 return yaffut::Factory::Instance().Main (argc, argv);
399 #endif /* YAFFUT_MAIN */
401 #define yaffut_main(argc, argv) yaffut::Factory::Instance().Main (argc, argv)
403 #endif