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)
20 #define YAFFUT_STRINGIZE(x) YAFFUT_STRINGIZE_(x)
21 #define YAFFUT_STRINGIZE_(x) #x
23 #define __YAFFUT_AT__ __FILE__ ":" YAFFUT_STRINGIZE(__LINE__)": "
25 #define __AT__ __YAFFUT_AT__
28 #define YAFFUT_EQUAL(e,a) \
29 yaffut::equal (e ,a , __YAFFUT_AT__, "EQUAL(" #e " == " #a ") failed ")
31 #define EQUAL YAFFUT_EQUAL
34 #define YAFFUT_UNEQUAL(e,a) \
35 yaffut::unequal (e, a, __YAFFUT_AT__, "UNEQUAL(" #e " != " #a ") failed ")
37 #define UNEQUAL YAFFUT_UNEQUAL
40 #define YAFFUT_CHECK(e) \
41 yaffut::check (e, __YAFFUT_AT__, "CHECK(" #e ") failed ")
43 #define CHECK YAFFUT_CHECK
46 #define YAFFUT_FAIL(s) yaffut::fail (s, __YAFFUT_AT__);
48 #define FAIL YAFFUT_FAIL
51 #define YAFFUT_ASSERT_THROW(s, e) \
55 throw yaffut::failure (__YAFFUT_AT__, #s " failed to throw"); \
59 #define ASSERT_THROW YAFFUT_ASSERT_THROW
65 std::string
demangle()
69 char* ptr
= abi::__cxa_demangle(typeid(T
).name(), 0, &sz
, &status
);
70 std::string
name(ptr
? ptr
: "", ptr
? strlen(ptr
) : 0);
72 std::string::size_type pos
= name
.rfind("::");
73 if(pos
!= std::string::npos
)
75 name
= name
.substr(pos
+ 2);
88 typedef ITest
* (*Create_t
) ();
90 typedef std::map
<std::string
, Create_t
> Tests_t
;
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
;
103 static Factory
& Instance()
105 static Factory 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
;
138 catch(const std::exception
& e
)
140 std::cout
<< "[FAIL]\n " << e
.what() << std::flush
;
145 std::cout
<< "[FAIL]\n unknown exception" << std::flush
;
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
;
158 std::cout
<< "[FAIL](" << m_fail
<< '/' << size
<< ")" << std::endl
;
160 int Main (int argc
, const char* argv
[])
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"
168 " -h, --help show this help\n"
169 " -l, --list list test cases" << std::endl
;
173 && (std::string(argv
[1]) == "-l" || std::string(argv
[1]) == "--list"))
175 Factory::Instance().List(argc
> 2 ? argv
[2] : "");
179 const char* all
[] = {"All"};
180 const char** test
= all
;
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_
;
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
;
218 failure(const char* at
= "", const char* expr
= "")
220 std::ostringstream os
;
224 virtual ~failure() throw() {}
225 virtual const char* what() const throw() { return failure_
.c_str(); }
228 template <typename Suite
, typename Case
>
233 Factory::Instance().Register(TestName(), Create
);
235 const std::string
& TestName()
237 static const std::string
name(demangle
<Suite
>() + "::" + demangle
<Case
>());
240 static ITest
* Create()
246 template <typename Case
>
247 struct Registrator
<Case
, void>
251 Factory::Instance().Register(TestName(), Create
);
253 const std::string
& TestName()
255 static const std::string
name ("::" + demangle
<Case
>());
258 static ITest
* Create()
265 template <typename Suite
, typename Case
= void>
266 struct Test
: public ITest
, public virtual Suite
268 static Registrator
<Suite
, Case
> s_Registrator
;
271 Registrator
<Suite
, Case
>* r
= &s_Registrator
;
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");
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
;
296 Registrator
<Case
, void>* r
= &s_Registrator
;
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");
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
= "")
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
= "")
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
= "")
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
;
364 throw failure(at
, os
.str().c_str());
367 template <typename E
>
368 void assert_throw(void(*pf
)(), const char* at
= "")
373 throw failure (at
, " statement failed to throw");
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()
386 namespace { struct Case: public yaffut::Test<Case>{ Case(); }; } \
387 template struct yaffut::Test<Case>; Case::Case()
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)