Mercurial > thymian
comparison 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 |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:a4671277546c |
|---|---|
| 1 // | |
| 2 // VMime library (http://www.vmime.org) | |
| 3 // Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> | |
| 4 // | |
| 5 // This program is free software; you can redistribute it and/or | |
| 6 // modify it under the terms of the GNU General Public License as | |
| 7 // published by the Free Software Foundation; either version 3 of | |
| 8 // the License, or (at your option) any later version. | |
| 9 // | |
| 10 // This program is distributed in the hope that it will be useful, | |
| 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 13 // General Public License for more details. | |
| 14 // | |
| 15 // You should have received a copy of the GNU General Public License along | |
| 16 // with this program; if not, write to the Free Software Foundation, Inc., | |
| 17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 18 // | |
| 19 // Linking this library statically or dynamically with other modules is making | |
| 20 // a combined work based on this library. Thus, the terms and conditions of | |
| 21 // the GNU General Public License cover the whole combination. | |
| 22 // | |
| 23 | |
| 24 #include <sys/time.h> | |
| 25 #include <time.h> | |
| 26 | |
| 27 #include <iostream> | |
| 28 #include <vector> | |
| 29 #include <algorithm> | |
| 30 #include <memory> | |
| 31 | |
| 32 #include <cppunit/XmlOutputter.h> | |
| 33 #include <cppunit/extensions/TestFactoryRegistry.h> | |
| 34 #include <cppunit/ui/text/TestRunner.h> | |
| 35 #include <cppunit/TestListener.h> | |
| 36 #include <cppunit/TestResult.h> | |
| 37 #include <cppunit/TestResultCollector.h> | |
| 38 #include <cppunit/TestFailure.h> | |
| 39 #include <cppunit/SourceLine.h> | |
| 40 #include <cppunit/Exception.h> | |
| 41 #include <cppunit/tools/XmlDocument.h> | |
| 42 #include <cppunit/tools/XmlElement.h> | |
| 43 | |
| 44 #include "vmime/vmime.hpp" | |
| 45 #include "vmime/platforms/posix/posixHandler.hpp" | |
| 46 | |
| 47 | |
| 48 class Clock | |
| 49 { | |
| 50 public: | |
| 51 | |
| 52 void reset() | |
| 53 { | |
| 54 struct timezone tz; | |
| 55 | |
| 56 gettimeofday(&m_start, &tz); | |
| 57 } | |
| 58 | |
| 59 double getDuration() const | |
| 60 { | |
| 61 struct timeval tv; | |
| 62 struct timezone tz; | |
| 63 | |
| 64 gettimeofday(&tv, &tz); | |
| 65 | |
| 66 return static_cast <double>(tv.tv_sec - m_start.tv_sec) | |
| 67 + static_cast <double>(tv.tv_usec - m_start.tv_usec) / 1000000.0; | |
| 68 } | |
| 69 | |
| 70 private: | |
| 71 | |
| 72 struct timeval m_start; | |
| 73 }; | |
| 74 | |
| 75 | |
| 76 class XmlTestListener : public CppUnit::TestListener | |
| 77 { | |
| 78 public: | |
| 79 | |
| 80 XmlTestListener() | |
| 81 : m_doc("utf-8"), m_testElt(NULL) | |
| 82 { | |
| 83 m_doc.setRootElement(new CppUnit::XmlElement("TestRun")); | |
| 84 } | |
| 85 | |
| 86 void startTest(CppUnit::Test* test) | |
| 87 { | |
| 88 m_testElt = new CppUnit::XmlElement("Test"); | |
| 89 m_suiteElt.back()->addElement(m_testElt); | |
| 90 | |
| 91 m_testElt->addElement(new CppUnit::XmlElement("Name", test->getName())); | |
| 92 | |
| 93 m_chrono.reset(); | |
| 94 } | |
| 95 | |
| 96 void addFailure(const CppUnit::TestFailure& failure) | |
| 97 { | |
| 98 CppUnit::XmlElement* failElt = new CppUnit::XmlElement("Failure"); | |
| 99 m_testElt->addElement(failElt); | |
| 100 | |
| 101 failElt->addElement(new CppUnit::XmlElement("FailureType", | |
| 102 failure.isError() ? "Error" : "Assertion")); | |
| 103 | |
| 104 if (failure.sourceLine().isValid()) | |
| 105 { | |
| 106 CppUnit::XmlElement* locElt = new CppUnit::XmlElement("Location"); | |
| 107 failElt->addElement(locElt); | |
| 108 | |
| 109 locElt->addElement(new CppUnit::XmlElement("File", failure.sourceLine().fileName())); | |
| 110 locElt->addElement(new CppUnit::XmlElement("Line", failure.sourceLine().lineNumber())); | |
| 111 } | |
| 112 | |
| 113 CppUnit::XmlElement* exElt = new CppUnit::XmlElement("Exception"); | |
| 114 failElt->addElement(exElt); | |
| 115 | |
| 116 exElt->addElement(new CppUnit::XmlElement("Message", failure.thrownException()->what())); | |
| 117 } | |
| 118 | |
| 119 void endTest(CppUnit::Test* /* test */) | |
| 120 { | |
| 121 std::ostringstream ossTime; | |
| 122 ossTime << (m_chrono.getDuration() * 1000.0); | |
| 123 | |
| 124 m_testElt->addElement(new CppUnit::XmlElement("Time", ossTime.str())); | |
| 125 | |
| 126 m_testElt = NULL; | |
| 127 } | |
| 128 | |
| 129 void startSuite(CppUnit::Test* suite) | |
| 130 { | |
| 131 if (suite->getName() == "All Tests") | |
| 132 return; | |
| 133 | |
| 134 CppUnit::XmlElement* suiteElt = new CppUnit::XmlElement("Suite"); | |
| 135 | |
| 136 if (m_suiteElt.size() == 0) | |
| 137 m_doc.rootElement().addElement(suiteElt); | |
| 138 else | |
| 139 m_suiteElt.back()->addElement(suiteElt); | |
| 140 | |
| 141 m_suiteElt.push_back(suiteElt); | |
| 142 | |
| 143 suiteElt->addElement(new CppUnit::XmlElement("Name", suite->getName())); | |
| 144 } | |
| 145 | |
| 146 void endSuite(CppUnit::Test* /* suite */) | |
| 147 { | |
| 148 if (m_suiteElt.size()) | |
| 149 m_suiteElt.pop_back(); | |
| 150 } | |
| 151 | |
| 152 void startTestRun(CppUnit::Test* /* test */, CppUnit::TestResult* /* eventManager */) | |
| 153 { | |
| 154 } | |
| 155 | |
| 156 void endTestRun(CppUnit::Test* /* test */, CppUnit::TestResult* /* eventManager */) | |
| 157 { | |
| 158 } | |
| 159 | |
| 160 void output(std::ostream& os) | |
| 161 { | |
| 162 os << m_doc.toString(); | |
| 163 } | |
| 164 | |
| 165 private: | |
| 166 | |
| 167 Clock m_chrono; | |
| 168 | |
| 169 CppUnit::XmlDocument m_doc; | |
| 170 std::vector <CppUnit::XmlElement*> m_suiteElt; | |
| 171 CppUnit::XmlElement* m_testElt; | |
| 172 }; | |
| 173 | |
| 174 | |
| 175 | |
| 176 // see testUtils.hpp | |
| 177 | |
| 178 std::vector <std::string>& getTestModules() | |
| 179 { | |
| 180 static std::vector <std::string> allModules; | |
| 181 return allModules; | |
| 182 } | |
| 183 | |
| 184 | |
| 185 void registerTestModule(const char* name_) | |
| 186 { | |
| 187 std::vector <std::string>& testModules = getTestModules(); | |
| 188 std::string name(name_); | |
| 189 | |
| 190 if (std::find(testModules.begin(), testModules.end(), name) == testModules.end()) | |
| 191 testModules.push_back(name); | |
| 192 } | |
| 193 | |
| 194 | |
| 195 const std::string getNormalizedPath(const std::string& path) | |
| 196 { | |
| 197 std::string res = path; | |
| 198 | |
| 199 for (std::size_t i = 0, n = res.length() ; i < n ; ++i) | |
| 200 { | |
| 201 if (res[i] == '\\') | |
| 202 res[i] = '/'; | |
| 203 } | |
| 204 | |
| 205 return res; | |
| 206 } | |
| 207 | |
| 208 | |
| 209 const std::string getFileNameFromPath(const std::string& path) | |
| 210 { | |
| 211 const std::size_t pos = path.find_last_of('/'); | |
| 212 | |
| 213 if (pos == std::string::npos) | |
| 214 return ""; | |
| 215 | |
| 216 return path.substr(pos + 1); | |
| 217 } | |
| 218 | |
| 219 | |
| 220 static char g_moduleNameBuffer[2048]; | |
| 221 | |
| 222 | |
| 223 const char* getTestModuleNameFromSourceFile(const char *path_) | |
| 224 { | |
| 225 static const std::string testRunnerPath(getNormalizedPath(__FILE__)); | |
| 226 static const std::string testRunnerFileName(getFileNameFromPath(testRunnerPath)); | |
| 227 | |
| 228 const std::string path = getNormalizedPath(path_); | |
| 229 | |
| 230 // "/path/to/testRunner.cpp" --> "/path/to/" | |
| 231 const std::string basePath | |
| 232 (testRunnerPath.begin(), testRunnerPath.end() - testRunnerFileName.length()); | |
| 233 | |
| 234 // "/path/to/module/testFile.cpp" --> "module/testFile.cpp" | |
| 235 const std::string testFileName(getFileNameFromPath(path)); | |
| 236 const std::string testPath(path.begin() + basePath.length(), path.end()); | |
| 237 | |
| 238 // "module/testFile.cpp" --> "module" | |
| 239 const std::string moduleName(testPath.substr(0, testPath.length() - testFileName.length() - 1)); | |
| 240 std::copy(moduleName.begin(), moduleName.end(), g_moduleNameBuffer); | |
| 241 g_moduleNameBuffer[moduleName.length()] = 0; | |
| 242 | |
| 243 return g_moduleNameBuffer; | |
| 244 } | |
| 245 | |
| 246 | |
| 247 int main(int argc, char* argv[]) | |
| 248 { | |
| 249 // Parse arguments | |
| 250 bool xmlOutput = false; | |
| 251 | |
| 252 for (int c = 1 ; c < argc ; ++c) | |
| 253 { | |
| 254 const std::string arg = argv[c]; | |
| 255 | |
| 256 if (arg == "--xml") | |
| 257 xmlOutput = true; | |
| 258 } | |
| 259 | |
| 260 // Run the tests | |
| 261 if (xmlOutput) | |
| 262 { | |
| 263 // Get the test suites from the registry and add them to the list of tests to run | |
| 264 CppUnit::TestRunner runner; | |
| 265 | |
| 266 for (unsigned int i = 0 ; i < getTestModules().size() ; ++i) | |
| 267 { | |
| 268 runner.addTest(CppUnit::TestFactoryRegistry:: | |
| 269 getRegistry(getTestModules()[i]).makeTest()); | |
| 270 } | |
| 271 | |
| 272 std::auto_ptr <XmlTestListener> xmlListener(new XmlTestListener); | |
| 273 | |
| 274 CppUnit::TestResult controller; | |
| 275 controller.addListener(xmlListener.get()); | |
| 276 | |
| 277 CppUnit::TestResultCollector result; | |
| 278 controller.addListener(&result); | |
| 279 | |
| 280 runner.run(controller); | |
| 281 | |
| 282 xmlListener->output(std::cout); | |
| 283 | |
| 284 // Return error code 1 if a test failed | |
| 285 return result.wasSuccessful() ? 0 : 1; | |
| 286 } | |
| 287 else | |
| 288 { | |
| 289 // Get the top level suite from the registry | |
| 290 CppUnit::TextUi::TestRunner runner; | |
| 291 runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest()); | |
| 292 | |
| 293 return runner.run() ? 0 : 1; | |
| 294 } | |
| 295 } | |
| 296 |
