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