diff --git a/tests/testRunner.cpp b/tests/testRunner.cpp index fb8d9108..883869a0 100644 --- a/tests/testRunner.cpp +++ b/tests/testRunner.cpp @@ -17,38 +17,201 @@ // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // +#include +#include + +#include + #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include #include "vmime/vmime.hpp" #include "vmime/platforms/posix/posixHandler.hpp" +class Clock +{ +public: + + void reset() + { + struct timezone tz; + + gettimeofday(&m_start, &tz); + } + + const double getDuration() const + { + struct timeval tv; + struct timezone tz; + + gettimeofday(&tv, &tz); + + return static_cast (tv.tv_sec - m_start.tv_sec) + + static_cast (tv.tv_usec - m_start.tv_usec) / 1000000.0; + } + +private: + + struct timeval m_start; +}; + + +class XmlTestListener : public CppUnit::TestListener +{ +public: + + XmlTestListener() + : m_doc("utf-8"), m_testElt(NULL) + { + m_doc.setRootElement(new CppUnit::XmlElement("TestRun")); + } + + void startTest(CppUnit::Test* test) + { + m_testElt = new CppUnit::XmlElement("Test"); + m_suiteElt.back()->addElement(m_testElt); + + m_testElt->addElement(new CppUnit::XmlElement("Name", test->getName())); + + m_chrono.reset(); + } + + void addFailure(const CppUnit::TestFailure& failure) + { + CppUnit::XmlElement* failElt = new CppUnit::XmlElement("Failure"); + m_testElt->addElement(failElt); + + failElt->addElement(new CppUnit::XmlElement("FailureType", + failure.isError() ? "Error" : "Assertion")); + + if (failure.sourceLine().isValid()) + { + CppUnit::XmlElement* locElt = new CppUnit::XmlElement("Location"); + failElt->addElement(locElt); + + locElt->addElement(new CppUnit::XmlElement("File", failure.sourceLine().fileName())); + locElt->addElement(new CppUnit::XmlElement("Line", failure.sourceLine().lineNumber())); + } + + CppUnit::XmlElement* exElt = new CppUnit::XmlElement("Exception"); + failElt->addElement(exElt); + + exElt->addElement(new CppUnit::XmlElement("Message", failure.thrownException()->what())); + } + + void endTest(CppUnit::Test* /* test */) + { + std::ostringstream ossTime; + ossTime << (m_chrono.getDuration() * 1000.0); + + m_testElt->addElement(new CppUnit::XmlElement("Time", ossTime.str())); + + m_testElt = NULL; + } + + void startSuite(CppUnit::Test* suite) + { + if (suite->getName() == "All Tests") + return; + + CppUnit::XmlElement* suiteElt = new CppUnit::XmlElement("Suite"); + + if (m_suiteElt.size() == 0) + m_doc.rootElement().addElement(suiteElt); + else + m_suiteElt.back()->addElement(suiteElt); + + m_suiteElt.push_back(suiteElt); + + suiteElt->addElement(new CppUnit::XmlElement("Name", suite->getName())); + } + + void endSuite(CppUnit::Test* /* suite */) + { + if (m_suiteElt.size()) + m_suiteElt.pop_back(); + } + + void startTestRun(CppUnit::Test* /* test */, CppUnit::TestResult* /* eventManager */) + { + } + + void endTestRun(CppUnit::Test* /* test */, CppUnit::TestResult* /* eventManager */) + { + } + + void output(std::ostream& os) + { + os << m_doc.toString(); + } + +private: + + Clock m_chrono; + + CppUnit::XmlDocument m_doc; + std::vector m_suiteElt; + CppUnit::XmlElement* m_testElt; +}; + + int main(int argc, char* argv[]) { // VMime initialization vmime::platformDependant::setHandler(); - // Get the top level suite from the registry - CppUnit::Test* suite = NULL; + // Parse arguments + bool xmlOutput = false; - if (argc > 1) - suite = CppUnit::TestFactoryRegistry::getRegistry(argv[1]).makeTest(); - else - suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest(); + for (int c = 1 ; c < argc ; ++c) + { + const std::string arg = argv[c]; - // Adds the test to the list of test to run - CppUnit::TextUi::TestRunner runner; - runner.addTest(suite); - - // Change the default outputter to a compiler error format outputter -// runner.setOutputter(new CppUnit::XmlOutputter(&runner.result(), std::cerr)); + if (arg == "--xml") + xmlOutput = true; + } // Run the tests - const bool wasSucessful = runner.run(); + if (xmlOutput) + { + // Get the test suites from the registry and add them to the list of test to run + CppUnit::TestRunner runner; + runner.addTest(CppUnit::TestFactoryRegistry::getRegistry("Parser").makeTest()); + runner.addTest(CppUnit::TestFactoryRegistry::getRegistry("Utility").makeTest()); + runner.addTest(CppUnit::TestFactoryRegistry::getRegistry("Misc").makeTest()); - // Return error code 1 if the one of test failed - return wasSucessful ? 0 : 1; + std::auto_ptr xmlListener(new XmlTestListener); + + CppUnit::TestResult controller; + controller.addListener(xmlListener.get()); + + CppUnit::TestResultCollector result; + controller.addListener(&result); + + runner.run(controller); + + xmlListener->output(std::cout); + + // Return error code 1 if the one of test failed + return result.wasSuccessful() ? 0 : 1; + } + else + { + // Get the top level suite from the registry + CppUnit::TextUi::TestRunner runner; + runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest()); + + return runner.run() ? 0 : 1; + } }