From: Jan Nieuwenhuizen Date: Sat, 30 Dec 2006 21:33:50 +0000 (+0100) Subject: Make test-file-name and test-file-path more unit-testy. X-Git-Tag: release/2.11.7-1~23^2~2 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=2558df9ea472e4c520dd5bbfd35241bce9c0c560;p=lilypond.git Make test-file-name and test-file-path more unit-testy. --- diff --git a/flower/include/yaffut-parameters.hh b/flower/include/yaffut-parameters.hh new file mode 100644 index 0000000000..9a569f903c --- /dev/null +++ b/flower/include/yaffut-parameters.hh @@ -0,0 +1,30 @@ +#ifndef __YAFFUT_PARAMETERS_H__ +#define __YAFFUT_PARAMETERS_H__ + +#include "yaffut.hh" + +namespace yaffut { +template +struct TestOne: public ITest, public Suite +{ + ParameterOne const parameter_one_; + //static Registrator s_Registrator; + TestOne(ParameterOne p) + : Suite(p) + , parameter_one_ (p) + { + Registrator* r = &Test::s_Registrator; + r = 0; + } +}; + +#define TEST_STRING(Suite, Case, String)\ + namespace { \ + struct Case: public yaffut::TestOne{ Case(); }; \ + } \ + template struct yaffut::TestOne; Case::Case() \ + : yaffut::TestOne (String) + +} + +#endif // __YAFFUT_PARAMETERS_H__ diff --git a/flower/include/yaffut.hh b/flower/include/yaffut.hh new file mode 100644 index 0000000000..91a3521493 --- /dev/null +++ b/flower/include/yaffut.hh @@ -0,0 +1,359 @@ +// Copyright 2006 Rutger E.W. van Beusekom. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef __YAFFUT_H__ +#define __YAFFUT_H__ + +#include + +#include +#include +#include +#include +#include +#include + +#define YAFFUT_STRINGIZE(x) YAFFUT_STRINGIZE_(x) +#define YAFFUT_STRINGIZE_(x) #x + +#define __YAFFUT_AT__ __FILE__ ":" YAFFUT_STRINGIZE(__LINE__)": " +#ifndef __AT__ +#define __AT__ __YAFFUT_AT__ +#endif + +#define YAFFUT_EQUAL(e,a) \ + yaffut::equal (e ,a , __YAFFUT_AT__, "EQUAL(" #e " == " #a ") failed ") +#ifndef EQUAL +#define EQUAL YAFFUT_EQUAL +#endif + +#define YAFFUT_UNEQUAL(e,a) \ + yaffut::unequal (e, a, __YAFFUT_AT__, "UNEQUAL(" #e " != " #a ") failed ") +#ifndef UNEQUAL +#define UNEQUAL YAFFUT_UNEQUAL +#endif + +#define YAFFUT_CHECK(e) \ + yaffut::check (e, __YAFFUT_AT__, "CHECK(" #e ") failed ") +#ifndef CHECK +#define CHECK YAFFUT_CHECK +#endif + +#define YAFFUT_FAIL(s) yaffut::fail (s, __YAFFUT_AT__); +#ifndef FAIL +#define FAIL YAFFUT_FAIL +#endif + +#define YAFFUT_ASSERT_THROW(s, e) \ + try \ + { \ + s; \ + throw yaffut::failure (__YAFFUT_AT__, #s " failed to throw"); \ + } \ + catch(const e&){} +#ifndef ASSERT_THROW +#define ASSERT_THROW YAFFUT_ASSERT_THROW +#endif + +namespace yaffut { + +template +std::string demangle() +{ + size_t sz; + int status; + char* ptr = abi::__cxa_demangle(typeid(T).name(), 0, &sz, &status); + std::string name(ptr ? ptr : "", ptr ? strlen(ptr) : 0); + if(ptr){ free(ptr); } + std::string::size_type pos = name.rfind("::"); + if(pos != std::string::npos) + { + name = name.substr(pos + 2); + } + return name; +} + +struct ITest +{ + virtual ~ITest(){} +}; + +class Factory +{ +public: + typedef ITest* (*Create_t) (); +private: + typedef std::map Tests_t; + Tests_t m_Tests; + size_t m_fail; + size_t m_pass; +private: + Factory(){} + ~Factory(){} + static bool EqualsSuiteName (std::string const &name, std::string const& s) + { + return name.find (':') >= name.length () - 2 + && s.substr (0, name.length ()) == name; + } +public: + static Factory& Instance() + { + static Factory instance; + return instance; + } + void Register(const std::string& name, Create_t create) + { + m_Tests[name] = create; + } + size_t Fail () { return m_fail; } + void List(const std::string& name) + { + for(Tests_t::const_iterator it = m_Tests.begin(); it != m_Tests.end(); ++it) + { + if(name.empty () || it->first == name + || EqualsSuiteName (name, it->first)) + std::cout << it->first << std::endl; + } + } + void Run(const std::string& name) + { + for(Tests_t::const_iterator it = m_Tests.begin(); it != m_Tests.end(); ++it) + { + if("All" == name || it->first == name + || EqualsSuiteName (name, it->first)) + { + try + { + std::cout << std::endl << it->first << ' ' << std::flush; + { + std::auto_ptr test(it->second()); + } + std::cout << "[OK]" << std::flush; + ++m_pass; + } + catch(const std::exception& e) + { + std::cout << "[FAIL]\n" << e.what() << std::flush; + ++m_fail; + } + catch(...) + { + std::cout << "[FAIL]\nunknown exception" << std::flush; + ++m_fail; + } + } + } + } + void Report () + { + const size_t size = m_Tests.size(); + std::cout << std::endl; + std::cout << "[TOTAL](" << m_pass + m_fail << '/' << size << ")" << std::endl; + std::cout << "[OK](" << m_pass << '/' << size << ")" << std::endl; + if (m_fail) + std::cout << "[FAIL](" << m_fail << '/' << size << ")" << std::endl; + } + int Main (int argc, const char* argv[]) + { + if(argc > 1 + && (std::string(argv[1]) == "-h" || std::string(argv[1]) == "--help")) + { + std::cout << "Yaffut - Yet Another Framework For Unit Testing.\n\n" + "Usage: yaffut [OPTION] [Suite:|Suite::Test]...\n\n" + "Options:\n" + " -h, --help show this help\n" + " -l, --list list test cases" << std::endl; + return 0; + } + if(argc > 1 + && (std::string(argv[1]) == "-l" || std::string(argv[1]) == "--list")) + { + Factory::Instance().List(argc > 2 ? argv[2] : ""); + return 0; + } + + const char* all[] = {"All"}; + const char** test = all; + int num = 1; + if(1 < argc) + { + test = argv; + num = argc; + } + + for(int i = 0; i < num; ++i) + { + try + { + Factory::Instance().Run(test[i]); + } + catch(const std::exception& e) + { + std::clog << e.what() << std::endl; + } + } + + Factory::Instance().Report (); + return Factory::Instance().Fail (); + } +}; + +class failure: public std::exception +{ + std::string failure_; +public: + template + failure(const Expected& e, Actual& a, const char* at = "", const char* expr = "") + { + std::ostringstream os; + os << at << expr << "\nexpected: " + << "(" << demangle() << ") " << e + << " != actual: " << "(" << demangle() << ") " << a; + failure_ = os.str(); + } + failure(const char* at = "", const char* expr = "") + { + std::ostringstream os; + os << at << expr; + failure_ = os.str(); + } + virtual ~failure() throw() {} + virtual const char* what() const throw() { return failure_.c_str(); } +}; + +template +struct Registrator +{ + Registrator() + { + Factory::Instance().Register(TestName(), Create); + } + const std::string& TestName() + { + static const std::string name(demangle() + "::" + demangle()); + return name; + } + static ITest* Create() + { + return new Case; + } +}; + +template +struct Test: public ITest, public Suite +{ + static Registrator s_Registrator; + Test() + : Suite() + { + Registrator* r = &s_Registrator; + r = 0; + } + template + void assert_throw(void(T::*mf)(), const char* at) + { + try + { + (dynamic_cast (this)->*mf)(); + throw yaffut::failure (at, "statement failed to throw"); + } + catch(const E&){} + } +}; + +template +Registrator Test::s_Registrator; + +template +void equal(const Expected& e, const Actual& a, const char* at = "", const char* expr = "") +{ + if(e != a) + { + throw failure(e, a, at, expr); + } +} +inline void equal(double e, double a, const char* at = "", const char* expr = "") +{ + double max = std::abs(std::max(e, a)); + max = max < 1.0 ? 1.0 : max; + if(std::abs(e - a) > std::numeric_limits::epsilon() * max) + { + throw failure(e, a, at, expr); + } +} +inline void check(bool b, const char* at = "", const char* expr = "") +{ + if(!b) + { + throw failure(at, expr); + } +} + +template +void unequal(const Expected& e, const Actual& a, const char* at = "", const char* expr = "") +{ + if(e == a) + { + throw failure(e, a, at, expr); + } +} +inline void unequal(double e, double a, const char* at = "", const char* expr = "") +{ + double max = std::abs(std::max(e, a)); + max = max < 1.0 ? 1.0 : max; + if(std::abs(e - a) <= std::numeric_limits::epsilon() * max) + { + throw failure(e, a, at, expr); + } +} + +template +void fail(const T& expr, const char* at = "") +{ + std::ostringstream os; + os << expr; + throw failure(at, os.str().c_str()); +} + +template +void assert_throw(void(*pf)(), const char* at = "") +{ + try + { + (*pf)(); + throw failure (at, " statement failed to throw"); + } + catch(const E&){} +} + +//define catch-all suite +struct Suite {}; + +} + +//and for those who prefer macro obscurity over more typing +#define TEST(Suite, Case)\ + namespace { struct Case: public yaffut::Test{ Case(); }; } \ + template struct yaffut::Test; Case::Case() + +#define FUNC(Case)\ + namespace { struct Case: public yaffut::Test{ Case(); }; } \ + template struct yaffut::Test; Case::Case() + +#ifdef YAFFUT_MAIN + +#include + +int main(int argc, const char* argv[]) +{ + std::cout << "pid(" << getpid() << ")" << std::endl; + return yaffut::Factory::Instance().Main (argc, argv); +}; + +#endif /* YAFFUT_MAIN */ + +#define yaffut_main(argc, argv) yaffut::Factory::Instance().Main (argc, argv) + +#endif diff --git a/flower/test-file-name.cc b/flower/test-file-name.cc new file mode 100644 index 0000000000..0bd427bda8 --- /dev/null +++ b/flower/test-file-name.cc @@ -0,0 +1,31 @@ +#include "file-name.hh" + +#include "yaffut-parameters.hh" + +using namespace std; + +string slashify (string file_name); + +TEST_STRING (File_name, Mingw_slashify, "foe.ly") +{ + string s = slashify (to_string ()); + EQUAL (parameter_one_, s); +} + +TEST_STRING (File_name, Mingw_slashify_2, "/tmp/x.ly") +{ + string s = slashify (to_string ()); + EQUAL (parameter_one_, s); +} + +TEST_STRING (File_name, Mingw_slashify_3, "c:/tmp/x.ly") +{ + string s = slashify (to_string ()); + EQUAL (parameter_one_, s); +} + +TEST_STRING (File_name, Mingw_slashify_4, "\\tmp\\x.ly") +{ + string s = slashify (to_string ()); + EQUAL ("/tmp/x.ly", s); +} diff --git a/flower/test-file-path.cc b/flower/test-file-path.cc new file mode 100644 index 0000000000..053d237b66 --- /dev/null +++ b/flower/test-file-path.cc @@ -0,0 +1,19 @@ +#include "file-path.hh" + +#include "yaffut.hh" +#include "config.hh" + +TEST (File_path, Find) +{ + char const *extensions[] = {"ly", "", 0}; + string file = "init"; + char cwd[PATH_MAX]; + getcwd (cwd, PATH_MAX); + string ly_dir = string (getenv ("top-src-dir")) + "/ly"; + parse_path (string (1, PATHSEP) + ly_dir); + string file_name = find (file, extensions); + EQUAL (file_name.substr (file_name.rfind ('/')), "/init.ly"); + file = "init.ly"; + file_name = find (file, extensions); + EQUAL (file_name, ly_dir + "/init.ly"); +} diff --git a/flower/test-file.cc b/flower/test-file.cc deleted file mode 100644 index c7335171a9..0000000000 --- a/flower/test-file.cc +++ /dev/null @@ -1,55 +0,0 @@ -#include "std-vector.hh" - -#include -#include - -using namespace std; - -#include "file-name.hh" -string slashify (string file_name); - -#include "yaffut.hh" - -// FIXME: split into file-name, file-path unit fixture tests -FUNC (mingw_slashify) -{ - File_name f = string ("foe.ly"); - string s = slashify (f.to_string ()); - cout << s << endl; - EQUAL ("foe.ly", s); - f = string ("/tmp/x.ly"); - s = slashify (f.to_string ()); - cout << s << endl; - EQUAL ("/tmp/x.ly", s); - f = string ("c:/tmp/x.ly"); - s = slashify (f.to_string ()); - cout << s << endl; - EQUAL ("c:/tmp/x.ly", s); - f = string ("\\tmp\\x.ly"); - s = slashify (f.to_string ()); - cout << s << endl; - EQUAL ("/tmp/x.ly", s); -} - -#include "config.hh" -#include "file-path.hh" - -FUNC (file_find) -{ - char const *extensions[] = {"ly", "", 0}; - string file = "init"; - File_path path; - char cwd[PATH_MAX]; - getcwd (cwd, PATH_MAX); - string ly_dir = string (getenv ("top-src-dir")) + "/ly"; - cout << ly_dir << endl; - path.parse_path (string (1, PATHSEP) + ly_dir); - string file_name = path.find (file, extensions); - cout << file_name << endl; - EQUAL (file_name.substr (file_name.rfind ('/')), "/init.ly"); - file = "init.ly"; - file_name = path.find (file, extensions); - cout << file_name << endl; - EQUAL (file_name, ly_dir + "/init.ly"); - -}