Mercurial > thymian
diff 3rdparty/vmime/tests/testRunner.cpp @ 0:a4671277546c tip
created the repository for the thymian project
| author | ferencd |
|---|---|
| date | Tue, 17 Aug 2021 11:19:54 +0200 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/3rdparty/vmime/tests/testRunner.cpp Tue Aug 17 11:19:54 2021 +0200 @@ -0,0 +1,296 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 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()); + } + + std::auto_ptr <XmlTestListener> 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 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; + } +} +
