Ajout de l'ensemble du workspace.
[GPU.git] / WCudaMSE / API_CppTest / SRC / core / htmloutput.cpp
1 // ---
2 //
3 // $Id: htmloutput.cpp,v 1.7 2008/07/15 20:33:31 hartwork Exp $
4 //
5 // CppTest - A C++ Unit Testing Framework
6 // Copyright (c) 2003 Niklas Lundell
7 //
8 // ---
9 //
10 // This library is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU Lesser General Public
12 // License as published by the Free Software Foundation; either
13 // version 2 of the License, or (at your option) any later version.
14 //
15 // This library is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the
22 // Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 // Boston, MA 02111-1307, USA.
24 //
25 // ---
26
27 #include <algorithm>
28 #include <sstream>
29
30 #if (defined(__WIN32__) || defined(WIN32))
31 # include "winconfig.h"
32 #else
33 # include "config.h"
34 #endif
35
36 #include "cpptest-htmloutput.h"
37 #include "utils.h"
38
39 using namespace std;
40
41 namespace Test
42 {
43 namespace
44 {
45 void
46 strreplace(string &value, char search, const string &replace)
47 {
48 string::size_type idx = 0;
49 while((idx = value.find(search, idx)) != string::npos)
50 {
51 value.replace(idx, 1, replace);
52 idx += replace.size();
53 }
54 }
55
56 string
57 escape(string value)
58 {
59 strreplace(value, '&', "&amp;");
60 strreplace(value, '<', "&lt;");
61 strreplace(value, '>', "&gt;");
62 strreplace(value, '"', "&quot;");
63 strreplace(value, '\'', "&#39;");
64 return value;
65 }
66
67 void
68 header(ostream& os, string name)
69 {
70 if (!name.empty())
71 name += " ";
72 name = escape(name);
73 os <<
74 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
75 "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
76 "<head>\n"
77 " <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n"
78 " <meta name=\"generator\" content=\"CppTest - http://cpptest.sourceforge.net\" />\n"
79 " \n"
80 " <title>" << name << "Unit Tests Results</title>\n"
81 " \n"
82 " <style type=\"text/css\" media=\"screen\">\n"
83 " <!--\n"
84 " hr {\n"
85 " width: 100%;\n"
86 " border-width: 0px;\n"
87 " height: 1px;\n"
88 " color: #cccccc;\n"
89 " background-color: #cccccc;\n"
90 " padding: 0px;\n"
91 " }\n"
92 " \n"
93 " table {\n"
94 " width:100%;\n"
95 " border-collapse:separate;\n"
96 " border-spacing: 2px;\n"
97 " border:0px;\n"
98 " }\n"
99 " tr {\n"
100 " margin:0px;\n"
101 " padding:0px;\n"
102 " }\n"
103 " td {\n"
104 " margin:0px;\n"
105 " padding:1px;\n"
106 " }\n"
107 " .table_summary {\n"
108 " }\n"
109 " .table_suites {\n"
110 " }\n"
111 " .table_suite {\n"
112 " }\n"
113 " .table_result {\n"
114 " margin: 0px 0px 1em 0px;\n"
115 " }\n"
116 " .tablecell_title {\n"
117 " background-color: #a5cef7;\n"
118 " font-weight: bold;\n"
119 " }\n"
120 " \n"
121 " .tablecell_success {\n"
122 " background-color: #efefe7;\n"
123 " }\n"
124 " \n"
125 " .tablecell_error {\n"
126 " color: #ff0808;\n"
127 " background-color: #efefe7;\n"
128 " font-weight: bold;\n"
129 " }\n"
130 " p.spaced {\n"
131 " margin: 0px;\n"
132 " padding: 1em 0px 2em 0px;\n"
133 " }\n"
134 " p.unspaced {\n"
135 " margin: 0px;\n"
136 " padding: 0px 0px 2em 0px;\n"
137 " }\n"
138 " -->\n"
139 " </style>\n"
140 "</head>\n"
141 "\n"
142 "<body>\n"
143 "\n"
144 "<h1><a name=\"top\"></a>" << name << "Unit Tests Results</h1>\n"
145 "\n"
146 "<div style=\"text-align:right\">\n"
147 "Designed by <a href=\"http://cpptest.sourceforge.net\">CppTest</a>\n"
148 "</div>\n"
149 "<hr />\n"
150 "\n";
151 }
152
153 void
154 footer(ostream& os)
155 {
156 os <<
157 "\n"
158 "<p>\n"
159 " <a href=\"http://validator.w3.org/#validate-by-upload\">\n"
160 " Valid XHTML 1.0 Strict\n"
161 " </a>\n"
162 "</p>\n"
163 "</body>\n</html>\n";
164 }
165
166 void
167 back_ref(ostream& os, const string& ref, bool prepend_newline = true)
168 {
169
170 os << "<p class=\"" << (prepend_newline ? "spaced" : "unspaced") << "\"><a href=\"#" << ref
171 << "\">Back to " << escape(ref) << "</a>\n</p>\n";
172 }
173
174 void
175 sub_title(ostream& os, const string& title, int size)
176 {
177 ostringstream h;
178 h << "h" << size;
179 os << "<" << h.str() << ">" << escape(title) << "</" << h.str() << ">\n";
180 }
181
182 void
183 sub_title(ostream& os, const string& title, int size, const string& mark)
184 {
185 ostringstream h;
186 h << "h" << size;
187 os << "<" << h.str() << "><a name=\"" << mark << "\"></a>" << escape(title) << "</" << h.str() << ">\n";
188 }
189
190 enum ClassTableType { TableClass_Summary, TableClass_Suites, TableClass_Suite, TableClass_Result };
191
192 void
193 table_header(ostream& os, ClassTableType type, const string &summary = "")
194 {
195 static const char* class_tabletypes[] = { "summary", "suites", "suite", "result" };
196
197 os << "<table summary=\"" << escape(summary) << "\" class=\"table_" << class_tabletypes[type] << "\">\n";
198 }
199
200 void
201 table_footer(ostream& os)
202 {
203 os << "</table>\n";
204 }
205
206 void
207 table_tr_header(ostream& os)
208 {
209 os << " <tr>\n";
210 }
211
212 void
213 table_tr_footer(ostream& os)
214 {
215 os << " </tr>\n";
216 }
217
218 enum ClassType { Title, Success, Error };
219
220 void
221 table_entry(ostream& os, ClassType type, const string& s,
222 int width = 0, const string& link = "")
223 {
224 static const char* class_types[] = { "title", "success", "error" };
225
226 os << " <td";
227 if (width)
228 os << " style=\"width:" << width << "%\"";
229 if (!link.empty())
230 os << " class=\"tablecell_" << class_types[type] << "\"><a href=\"#" << link << "\">" << escape(s) << "</a>";
231 else
232 os << " class=\"tablecell_" << class_types[type] << "\">" << escape(s);
233 os << "</td>\n";
234 }
235
236 } // anonymous namespace
237
238 // Test suite table
239 //
240 struct HtmlOutput::SuiteRow
241 {
242 ostream& _os;
243 SuiteRow(ostream& os) : _os(os) {}
244 void operator()(const SuiteInfo& si)
245 {
246 ClassType type(si._errors > 0 ? Error : Success);
247 ostringstream ss;
248
249 table_tr_header(_os);
250 table_entry(_os, type, si._name, 0, si._name);
251 ss.str(""), ss << si._tests.size();
252 table_entry(_os, type, ss.str(), 10);
253 ss.str(""), ss << si._errors;
254 table_entry(_os, type, ss.str(), 10);
255 ss.str(""), ss << correct(si._tests.size(), si._errors) << "%";
256 table_entry(_os, type, ss.str(), 10);
257 ss.str(""), ss << si._time;
258 table_entry(_os, type, ss.str(), 10);
259 table_tr_footer(_os);
260 }
261 };
262
263 // Individual tests tables, tests
264 //
265 struct HtmlOutput::TestRow
266 {
267 bool _incl_ok_tests;
268 ostream& _os;
269 TestRow(ostream& os, bool incl_ok_tests)
270 : _incl_ok_tests(incl_ok_tests), _os(os) {}
271 void operator()(const TestInfo& ti)
272 {
273 if (!ti._success || _incl_ok_tests)
274 {
275 string link = ti._success ? string(""):
276 ti._sources.front().suite() + "_" + ti._name;
277 ClassType type(ti._success ? Success : Error);
278 ostringstream ss;
279
280 table_tr_header(_os);
281 table_entry(_os, type, ti._name, 0, link);
282 ss.str(""), ss << ti._sources.size();
283 table_entry(_os, type, ss.str());
284 table_entry(_os, type, ti._success ? "true" : "false");
285 ss.str(""), ss << ti._time;
286 table_entry(_os, type, ss.str());
287 table_tr_footer(_os);
288 }
289 }
290 };
291
292 // Individual tests tables, header
293 //
294 struct HtmlOutput::TestSuiteRow
295 {
296 bool _incl_ok_tests;
297 ostream& _os;
298 TestSuiteRow(ostream& os, bool incl_ok_tests)
299 : _incl_ok_tests(incl_ok_tests), _os(os) {}
300 void operator()(const SuiteInfo& si)
301 {
302 ostringstream ss;
303
304 sub_title(_os, "Suite: " + si._name, 3, si._name);
305 table_header(_os, TableClass_Suite, "Details for suite " + si._name);
306 table_tr_header(_os);
307 table_entry(_os, Title, "Name");
308 table_entry(_os, Title, "Errors", 10);
309 table_entry(_os, Title, "Success", 10);
310 table_entry(_os, Title, "Time (s)", 10);
311 table_tr_footer(_os);
312 for_each(si._tests.begin(), si._tests.end(),
313 TestRow(_os, _incl_ok_tests));
314 table_footer(_os);
315 back_ref(_os, "top");
316 }
317 };
318
319 // Individual tests result tables
320 //
321 struct HtmlOutput::TestResult
322 {
323 ostream& _os;
324 TestResult(ostream& os) : _os(os) {}
325 void operator()(const Source& s)
326 {
327 const int TitleSize = 15;
328
329 ostringstream ss;
330
331 table_header(_os, TableClass_Result, "Test Failure");
332 table_tr_header(_os);
333 table_entry(_os, Title, "Test", TitleSize);
334 table_entry(_os, Success, s.suite() + "::" + s.test());
335 table_tr_footer(_os);
336 table_tr_header(_os);
337 table_entry(_os, Title, "File", TitleSize);
338 ss << s.file() << ":" << s.line();
339 table_entry(_os, Success, ss.str());
340 table_tr_footer(_os);
341 table_tr_header(_os);
342 table_entry(_os, Title, "Message", TitleSize);
343 table_entry(_os, Success, s.message());
344 table_tr_footer(_os);
345 table_footer(_os);
346 }
347 };
348
349 // All tests result tables
350 //
351 struct HtmlOutput::TestResultAll
352 {
353 ostream& _os;
354 TestResultAll(ostream& os) : _os(os) {}
355 void operator()(const TestInfo& ti)
356 {
357 if (!ti._success)
358 {
359 const string& suite = ti._sources.front().suite();
360
361 sub_title(_os, suite + "::" + ti._name, 3, suite + "_" + ti._name);
362 for_each(ti._sources.begin(), ti._sources.end(), TestResult(_os));
363 back_ref(_os, suite, false);
364 }
365 }
366 };
367
368 // Individual tests result tables, iterator
369 //
370 struct HtmlOutput::SuiteTestResult
371 {
372 ostream& _os;
373 SuiteTestResult(ostream& os) : _os(os) {}
374 void operator()(const SuiteInfo& si)
375 {
376 for_each(si._tests.begin(), si._tests.end(), TestResultAll(_os));
377 }
378 };
379
380 /// Generates the HTML table. This function should only be called after
381 /// run(), when all tests have been executed.
382 ///
383 /// \param os Output stream.
384 /// \param incl_ok_tests Set if successful tests should be shown;
385 /// false otherwise.
386 /// \param name Name of generated report.
387 ///
388 void
389 HtmlOutput::generate(ostream& os, bool incl_ok_tests, const string& name)
390 {
391 ClassType type(_total_errors > 0 ? Error : Success);
392 ostringstream ss;
393
394 header(os, name);
395
396 // Table: Summary
397 //
398 sub_title(os, "Summary", 2);
399 table_header(os, TableClass_Summary, "Summary of test results");
400 table_tr_header(os);
401 table_entry(os, Title, "Tests", 30);
402 table_entry(os, Title, "Errors", 30);
403 table_entry(os, Title, "Success", 30);
404 table_entry(os, Title, "Time (s)", 10);
405 table_tr_footer(os);
406 table_tr_header(os);
407 ss.str(""), ss << _total_tests;
408 table_entry(os, type, ss.str(), 30);
409 ss.str(""), ss << _total_errors;
410 table_entry(os, type, ss.str(), 30);
411 ss.str(""), ss << correct(_total_tests, _total_errors) << "%";
412 table_entry(os, type, ss.str(), 30);
413 ss.str(""), ss << _total_time;
414 table_entry(os, type, ss.str(), 10);
415 table_tr_footer(os);
416 table_footer(os);
417 os << "<hr />\n\n";
418
419 // Table: Test suites
420 //
421 sub_title(os, "Test suites", 2);
422 table_header(os, TableClass_Suites, "Test Suites");
423 table_tr_header(os);
424 table_entry(os, Title, "Name");
425 table_entry(os, Title, "Tests", 10);
426 table_entry(os, Title, "Errors", 10);
427 table_entry(os, Title, "Success", 10);
428 table_entry(os, Title, "Time (s)", 10);
429 table_tr_footer(os);
430 for_each(_suites.begin(), _suites.end(), SuiteRow(os));
431 table_footer(os);
432 os << "<hr />\n\n";
433
434 // Individual tests tables
435 //
436 for_each(_suites.begin(), _suites.end(), TestSuiteRow(os, incl_ok_tests));
437 os << "<hr />\n\n";
438
439 // Individual tests result tables
440 //
441 if(_total_errors != 0)
442 {
443 sub_title(os, "Test results", 2);
444 for_each(_suites.begin(), _suites.end(), SuiteTestResult(os));
445 os << "<hr />\n\n";
446 }
447 // EOF
448 //
449 footer(os);
450 }
451
452 } // namespace Test
453