diff options
Diffstat (limited to 'vmime-master/tests/testRunner.cpp')
-rw-r--r-- | vmime-master/tests/testRunner.cpp | 305 |
1 files changed, 305 insertions, 0 deletions
diff --git a/vmime-master/tests/testRunner.cpp b/vmime-master/tests/testRunner.cpp new file mode 100644 index 0000000..f1f13b2 --- /dev/null +++ b/vmime-master/tests/testRunner.cpp @@ -0,0 +1,305 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <vincent@vmime.org> +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#include <sys/time.h> +#include <time.h> + +#include <iostream> +#include <vector> +#include <algorithm> +#include <memory> + +#include <cppunit/XmlOutputter.h> +#include <cppunit/extensions/TestFactoryRegistry.h> +#include <cppunit/ui/text/TestRunner.h> +#include <cppunit/TestListener.h> +#include <cppunit/TestResult.h> +#include <cppunit/TestResultCollector.h> +#include <cppunit/TestFailure.h> +#include <cppunit/SourceLine.h> +#include <cppunit/Exception.h> +#include <cppunit/tools/XmlDocument.h> +#include <cppunit/tools/XmlElement.h> + +#include "vmime/vmime.hpp" +#include "vmime/platforms/posix/posixHandler.hpp" + + +class Clock { + +public: + + void reset() { + + struct timezone tz; + + gettimeofday(&m_start, &tz); + } + + double getDuration() const { + + struct timeval tv; + struct timezone tz; + + gettimeofday(&tv, &tz); + + return static_cast <double>(tv.tv_sec - m_start.tv_sec) + + static_cast <double>(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 <CppUnit::XmlElement*> m_suiteElt; + CppUnit::XmlElement* m_testElt; +}; + + + +// see testUtils.hpp + +std::vector <std::string>& getTestModules() { + + static std::vector <std::string> allModules; + return allModules; +} + + +void registerTestModule(const char* name_) { + + std::vector <std::string>& testModules = getTestModules(); + std::string name(name_); + + if (std::find(testModules.begin(), testModules.end(), name) == testModules.end()) { + testModules.push_back(name); + } +} + + +const std::string getNormalizedPath(const std::string& path) { + + std::string res = path; + + for (std::size_t i = 0, n = res.length() ; i < n ; ++i) { + + if (res[i] == '\\') { + res[i] = '/'; + } + } + + return res; +} + + +const std::string getFileNameFromPath(const std::string& path) { + + const std::size_t pos = path.find_last_of('/'); + + if (pos == std::string::npos) { + return ""; + } + + return path.substr(pos + 1); +} + + +static char g_moduleNameBuffer[2048]; + + +const char* getTestModuleNameFromSourceFile(const char *path_) { + + static const std::string testRunnerPath(getNormalizedPath(__FILE__)); + static const std::string testRunnerFileName(getFileNameFromPath(testRunnerPath)); + + const std::string path = getNormalizedPath(path_); + + // "/path/to/testRunner.cpp" --> "/path/to/" + const std::string basePath + (testRunnerPath.begin(), testRunnerPath.end() - testRunnerFileName.length()); + + // "/path/to/module/testFile.cpp" --> "module/testFile.cpp" + const std::string testFileName(getFileNameFromPath(path)); + const std::string testPath(path.begin() + basePath.length(), path.end()); + + // "module/testFile.cpp" --> "module" + const std::string moduleName(testPath.substr(0, testPath.length() - testFileName.length() - 1)); + std::copy(moduleName.begin(), moduleName.end(), g_moduleNameBuffer); + g_moduleNameBuffer[moduleName.length()] = 0; + + return g_moduleNameBuffer; +} + + +int main(int argc, char* argv[]) { + + // Parse arguments + bool xmlOutput = false; + + for (int c = 1 ; c < argc ; ++c) { + + const std::string arg = argv[c]; + + if (arg == "--xml") { + xmlOutput = true; + } + } + + // Run the tests + if (xmlOutput) { + + // Get the test suites from the registry and add them to the list of tests to run + CppUnit::TestRunner runner; + + for (unsigned int i = 0 ; i < getTestModules().size() ; ++i) { + + runner.addTest( + CppUnit::TestFactoryRegistry::getRegistry(getTestModules()[i]).makeTest() + ); + } + + XmlTestListener xmlListener; + + CppUnit::TestResult controller; + controller.addListener(&xmlListener); + + CppUnit::TestResultCollector result; + controller.addListener(&result); + + runner.run(controller); + + xmlListener.output(std::cout); + + // Return error code 1 if a 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; + } +} |