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)
18 #define YAFFUT_STRINGIZE(x) YAFFUT_STRINGIZE_(x)
19 #define YAFFUT_STRINGIZE_(x) #x
21 #define __YAFFUT_AT__ __FILE__ ":" YAFFUT_STRINGIZE(__LINE__)": "
23 #define __AT__ __YAFFUT_AT__
26 #define YAFFUT_EQUAL(e,a) \
27 yaffut::equal (e ,a , __YAFFUT_AT__, "EQUAL(" #e " == " #a ") failed ")
29 #define EQUAL YAFFUT_EQUAL
32 #define YAFFUT_UNEQUAL(e,a) \
33 yaffut::unequal (e, a, __YAFFUT_AT__, "UNEQUAL(" #e " != " #a ") failed ")
35 #define UNEQUAL YAFFUT_UNEQUAL
38 #define YAFFUT_CHECK(e) \
39 yaffut::check (e, __YAFFUT_AT__, "CHECK(" #e ") failed ")
41 #define CHECK YAFFUT_CHECK
44 #define YAFFUT_FAIL(s) yaffut::fail (s, __YAFFUT_AT__);
46 #define FAIL YAFFUT_FAIL
49 #define YAFFUT_ASSERT_THROW(s, e) \
53 throw yaffut::failure (__YAFFUT_AT__, #s " failed to throw"); \
57 #define ASSERT_THROW YAFFUT_ASSERT_THROW
63 std::string demangle()
67 char* ptr = abi::__cxa_demangle(typeid(T).name(), 0, &sz, &status);
68 std::string name(ptr ? ptr : "", ptr ? strlen(ptr) : 0);
70 std::string::size_type pos = name.rfind("::");
71 if(pos != std::string::npos)
73 name = name.substr(pos + 2);
86 typedef ITest* (*Create_t) ();
88 typedef std::map<std::string, Create_t> Tests_t;
95 static bool EqualsSuiteName (std::string const &name, std::string const& s)
97 return name.find (':') >= name.length () - 2
98 && s.substr (0, name.length ()) == name;
101 static Factory& Instance()
103 static Factory instance;
106 void Register(const std::string& name, Create_t create)
108 m_Tests[name] = create;
110 size_t Fail () { return m_fail; }
111 void List(const std::string& name)
113 for(Tests_t::const_iterator it = m_Tests.begin(); it != m_Tests.end(); ++it)
115 if(name.empty () || it->first == name
116 || EqualsSuiteName (name, it->first))
117 std::cout << it->first << std::endl;
120 void Run(const std::string& name)
122 for(Tests_t::const_iterator it = m_Tests.begin(); it != m_Tests.end(); ++it)
124 if("All" == name || it->first == name
125 || EqualsSuiteName (name, it->first))
129 std::cout << std::endl << it->first << ' ' << std::flush;
131 std::auto_ptr<ITest> test(it->second());
133 std::cout << "[OK]" << std::flush;
136 catch(const std::exception& e)
138 std::cout << "[FAIL]\n" << e.what() << std::flush;
143 std::cout << "[FAIL]\nunknown exception" << std::flush;
151 const size_t size = m_Tests.size();
152 std::cout << std::endl;
153 std::cout << "[TOTAL](" << m_pass + m_fail << '/' << size << ")" << std::endl;
154 std::cout << "[OK](" << m_pass << '/' << size << ")" << std::endl;
156 std::cout << "[FAIL](" << m_fail << '/' << size << ")" << std::endl;
158 int Main (int argc, const char* argv[])
161 && (std::string(argv[1]) == "-h" || std::string(argv[1]) == "--help"))
163 std::cout << "Yaffut - Yet Another Framework For Unit Testing.\n\n"
164 "Usage: yaffut [OPTION] [Suite:|Suite::Test]...\n\n"
166 " -h, --help show this help\n"
167 " -l, --list list test cases" << std::endl;
171 && (std::string(argv[1]) == "-l" || std::string(argv[1]) == "--list"))
173 Factory::Instance().List(argc > 2 ? argv[2] : "");
177 const char* all[] = {"All"};
178 const char** test = all;
186 for(int i = 0; i < num; ++i)
190 Factory::Instance().Run(test[i]);
192 catch(const std::exception& e)
194 std::clog << e.what() << std::endl;
198 Factory::Instance().Report ();
199 return Factory::Instance().Fail ();
203 class failure: public std::exception
205 std::string failure_;
207 template <typename Expected, typename Actual>
208 failure(const Expected& e, Actual& a, const char* at = "", const char* expr = "")
210 std::ostringstream os;
211 os << at << expr << "\nexpected: "
212 << "(" << demangle<Expected>() << ") " << e
213 << " != actual: " << "(" << demangle<Actual>() << ") " << a;
216 failure(const char* at = "", const char* expr = "")
218 std::ostringstream os;
222 virtual ~failure() throw() {}
223 virtual const char* what() const throw() { return failure_.c_str(); }
226 template <typename Suite, typename Case>
231 Factory::Instance().Register(TestName(), Create);
233 const std::string& TestName()
235 static const std::string name(demangle<Suite>() + "::" + demangle<Case>());
238 static ITest* Create()
244 template <typename Suite, typename Case>
245 struct Test: public ITest, public Suite
247 static Registrator<Suite, Case> s_Registrator;
251 Registrator<Suite, Case>* r = &s_Registrator;
254 template <typename E, typename T>
255 void assert_throw(void(T::*mf)(), const char* at)
259 (dynamic_cast<T*> (this)->*mf)();
260 throw yaffut::failure (at, "statement failed to throw");
266 template <typename Suite, typename Case>
267 Registrator<Suite, Case> Test<Suite, Case>::s_Registrator;
269 template <typename Expected, typename Actual>
270 void equal(const Expected& e, const Actual& a, const char* at = "", const char* expr = "")
274 throw failure(e, a, at, expr);
277 inline void equal(double e, double a, const char* at = "", const char* expr = "")
279 double max = std::abs(std::max(e, a));
280 max = max < 1.0 ? 1.0 : max;
281 if(std::abs(e - a) > std::numeric_limits<double>::epsilon() * max)
283 throw failure(e, a, at, expr);
286 inline void check(bool b, const char* at = "", const char* expr = "")
290 throw failure(at, expr);
294 template <typename Expected, typename Actual>
295 void unequal(const Expected& e, const Actual& a, const char* at = "", const char* expr = "")
299 throw failure(e, a, at, expr);
302 inline void unequal(double e, double a, const char* at = "", const char* expr = "")
304 double max = std::abs(std::max(e, a));
305 max = max < 1.0 ? 1.0 : max;
306 if(std::abs(e - a) <= std::numeric_limits<double>::epsilon() * max)
308 throw failure(e, a, at, expr);
312 template <typename T>
313 void fail(const T& expr, const char* at = "")
315 std::ostringstream os;
317 throw failure(at, os.str().c_str());
320 template <typename E>
321 void assert_throw(void(*pf)(), const char* at = "")
326 throw failure (at, " statement failed to throw");
331 //define catch-all suite
336 //and for those who prefer macro obscurity over more typing
337 #define TEST(Suite, Case)\
338 namespace { struct Case: public yaffut::Test<Suite, Case>{ Case(); }; } \
339 template struct yaffut::Test<Suite, Case>; Case::Case()
342 namespace { struct Case: public yaffut::Test<yaffut::Suite, Case>{ Case(); }; } \
343 template struct yaffut::Test<yaffut::Suite, Case>; Case::Case()
349 int main(int argc, const char* argv[])
351 std::cout << "pid(" << getpid() << ")" << std::endl;
352 return yaffut::Factory::Instance().Main (argc, argv);
355 #endif /* YAFFUT_MAIN */
357 #define yaffut_main(argc, argv) yaffut::Factory::Instance().Main (argc, argv)