2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 * @file test_results_collector.h
18 * @author Lukasz Wrzosek (l.wrzosek@samsung.com)
20 * @brief Implementation file some concrete TestResulstsCollector
23 #include <dpl/test/test_results_collector.h>
24 #include <dpl/colors.h>
25 #include <dpl/assert.h>
26 #include <dpl/foreach.h>
27 #include <dpl/scoped_fclose.h>
41 const char *DEFAULT_HTML_FILE_NAME = "index.html";
42 const char *DEFAULT_TAP_FILE_NAME = "results.tap";
56 void AddTest(TestResultsCollectorBase::FailStatus::Type type)
60 case TestResultsCollectorBase::FailStatus::INTERNAL:
61 case TestResultsCollectorBase::FailStatus::FAILED: ++m_failed; break;
62 case TestResultsCollectorBase::FailStatus::IGNORED: ++m_ignored; break;
63 case TestResultsCollectorBase::FailStatus::TODO: ++m_todo; break;
64 case TestResultsCollectorBase::FailStatus::NONE: ++m_passed; break;
66 Assert(false && "Bad FailStatus");
70 size_t GetTotal() const { return m_count; }
71 size_t GetPassed() const { return m_passed; }
72 size_t GetSuccesed() const { return m_passed; }
73 size_t GetFailed() const { return m_failed; }
74 size_t GetTODO() const { return m_todo; }
75 size_t GetIgnored() const { return m_ignored; }
76 float GetPassedOrIgnoredPercend() const
78 float passIgnoredPercent =
79 100.0f * (static_cast<float>(m_passed)
80 + static_cast<float>(m_ignored))
81 / static_cast<float>(m_count);
82 return passIgnoredPercent;
93 class ConsoleCollector
94 : public TestResultsCollectorBase
97 static TestResultsCollectorBase* Constructor();
100 ConsoleCollector() {}
102 virtual void CollectCurrentTestGroupName(const std::string& name)
104 printf("Starting group %s\n", name.c_str());
105 m_currentGroup = name;
108 virtual void Finish()
110 using namespace DPL::Colors::Text;
113 FOREACH(group, m_groupsStats) {
114 PrintStats(group->first, group->second);
116 PrintStats("All tests together", m_stats);
119 virtual void CollectResult(const std::string& id,
120 const std::string& /*description*/,
121 const FailStatus::Type status = FailStatus::NONE,
122 const std::string& reason = "")
124 using namespace DPL::Colors::Text;
125 std::string tmp = "'" + id + "' ...";
127 printf("Running test case %-60s", tmp.c_str());
129 case TestResultsCollectorBase::FailStatus::NONE:
130 printf("[%s%s%s]\n", BOLD_GREEN_BEGIN, " OK ", BOLD_GREEN_END); break;
131 case TestResultsCollectorBase::FailStatus::FAILED:
132 PrintfErrorMessage( " FAILED ", reason, true); break;
133 case TestResultsCollectorBase::FailStatus::IGNORED:
134 PrintfIgnoredMessage("Ignored ", reason, true); break;
135 case TestResultsCollectorBase::FailStatus::TODO:
136 PrintfTODOMessage( " TODO ", reason, true); break;
137 case TestResultsCollectorBase::FailStatus::INTERNAL:
138 PrintfErrorMessage( "INTERNAL", reason, true); break;
140 Assert(false && "Bad status");
142 m_stats.AddTest(status);
143 m_groupsStats[m_currentGroup].AddTest(status);
146 void PrintfErrorMessage(const char* type,
147 const std::string& message,
150 using namespace DPL::Colors::Text;
152 printf("[%s%s%s] %s%s%s\n",
167 void PrintfTODOMessage(const char* type,
168 const std::string& message,
171 using namespace DPL::Colors::Text;
173 printf("[%s%s%s] %s%s%s\n",
188 void PrintfIgnoredMessage(const char* type,
189 const std::string& message,
192 using namespace DPL::Colors::Text;
194 printf("[%s%s%s] %s%s%s\n",
209 void PrintStats(const std::string& title, const Statistic& stats)
211 using namespace DPL::Colors::Text;
212 printf("\n%sResults [%s]: %s\n", BOLD_GREEN_BEGIN, title.c_str(), BOLD_GREEN_END);
213 printf("%s%s%3d%s\n", CYAN_BEGIN, "Total tests: ", stats.GetTotal(), CYAN_END);
214 printf("%s%s%3d%s\n", CYAN_BEGIN, "Succeeded or ignored: ", stats.GetPassed() + stats.GetIgnored(), CYAN_END);
215 printf(" %s%s%3d%s\n", CYAN_BEGIN, "Succeeded: ", stats.GetPassed(), CYAN_END);
216 printf(" %s%s%3d%s\n", CYAN_BEGIN, "Ignored: ", stats.GetIgnored(), CYAN_END);
217 printf("%s%s%3d%s\n", CYAN_BEGIN, "Failed: ", stats.GetFailed(), CYAN_END);
218 printf("%s%s%3d%s\n", CYAN_BEGIN, "Todo: ", stats.GetTODO(), CYAN_END);
219 printf("%s%s%3.0f%%%s\n", CYAN_BEGIN, "Succeeded or ignored %: ", stats.GetPassedOrIgnoredPercend(), CYAN_END);
223 std::map<std::string, Statistic> m_groupsStats;
224 std::string m_currentGroup;
228 TestResultsCollectorBase* ConsoleCollector::Constructor()
230 return new ConsoleCollector();
235 : public TestResultsCollectorBase
238 static TestResultsCollectorBase* Constructor();
241 HtmlCollector() : m_filename(DEFAULT_HTML_FILE_NAME) {}
243 virtual void CollectCurrentTestGroupName(const std::string& name)
245 fprintf(m_fp.Get(),"<b>Starting group %s", name.c_str());
246 m_currentGroup = name;
249 virtual bool Configure()
251 m_fp.Reset(fopen (m_filename.c_str(), "w"));
253 LogPedantic("Could not open file " << m_filename << " for writing");
258 virtual std::string CollectorSpecificHelp() const
260 return "--file=<filename> - name of file for output\n"
261 " default - index.html\n";
266 Assert(!!m_fp && "File handle must not be null");
268 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0"
269 "Transitional//EN\" "
270 "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\""
273 "<html xmlns=\"http://www.w3.org/1999/xhtml\" "
274 "lang=\"en\" dir=\"ltr\">\n");
275 fprintf(m_fp.Get(), "<body style=\"background-color: black;\">\n");
276 fprintf(m_fp.Get(), "<pre>\n");
277 fprintf(m_fp.Get(), "<font color=\"white\">\n");
280 virtual void Finish()
282 using namespace DPL::Colors::Html;
284 FOREACH(group, m_groupsStats) {
285 PrintStats(group->first, group->second);
287 PrintStats("All tests together", m_stats);
288 fprintf(m_fp.Get(), "</font>\n");
289 fprintf(m_fp.Get(), "</pre>\n");
290 fprintf(m_fp.Get(), "</body>\n");
291 fprintf(m_fp.Get(), "</html>\n");
294 virtual bool ParseCollectorSpecificArg(const std::string& arg)
296 const std::string argname = "--file=";
297 if (0 == arg.find(argname)) {
298 m_filename = arg.substr(argname.size());
305 virtual void CollectResult(const std::string& id,
306 const std::string& /*description*/,
307 const FailStatus::Type status = FailStatus::NONE,
308 const std::string& reason = "")
310 using namespace DPL::Colors::Html;
311 std::string tmp = "'" + id + "' ...";
313 fprintf(m_fp.Get(), "Running test case %-100s", tmp.c_str());
315 case TestResultsCollectorBase::FailStatus::NONE:
316 fprintf(m_fp.Get(), "[%s%s%s]\n", BOLD_GREEN_BEGIN, " OK ", BOLD_GREEN_END); break;
317 case TestResultsCollectorBase::FailStatus::FAILED:
318 PrintfErrorMessage( " FAILED ", reason, true); break;
319 case TestResultsCollectorBase::FailStatus::IGNORED:
320 PrintfIgnoredMessage("Ignored ", reason, true); break;
321 case TestResultsCollectorBase::FailStatus::TODO:
322 PrintfTODOMessage( " TODO ", reason, true); break;
323 case TestResultsCollectorBase::FailStatus::INTERNAL:
324 PrintfErrorMessage( "INTERNAL", reason, true); break;
326 Assert(false && "Bad status");
328 m_groupsStats[m_currentGroup].AddTest(status);
329 m_stats.AddTest(status);
332 void PrintfErrorMessage(const char* type,
333 const std::string& message,
336 using namespace DPL::Colors::Html;
355 void PrintfTODOMessage(const char* type,
356 const std::string& message,
359 using namespace DPL::Colors::Html;
378 void PrintfIgnoredMessage(const char* type,
379 const std::string& message,
382 using namespace DPL::Colors::Html;
402 void PrintStats(const std::string& name, const Statistic& stats)
404 using namespace DPL::Colors::Html;
405 fprintf(m_fp.Get(), "\n%sResults [%s]:%s\n", BOLD_GREEN_BEGIN, name.c_str(), BOLD_GREEN_END);
406 fprintf(m_fp.Get(), "%s%s%3d%s\n", CYAN_BEGIN, "Total tests: ", stats.GetTotal(), CYAN_END);
407 fprintf(m_fp.Get(), "%s%s%3d%s\n", CYAN_BEGIN, "Succeeded or ignored: ", stats.GetPassed() + stats.GetIgnored(), CYAN_END);
408 fprintf(m_fp.Get(), " %s%s%3d%s\n", CYAN_BEGIN, "Succeeded: ", stats.GetPassed(), CYAN_END);
409 fprintf(m_fp.Get(), " %s%s%3d%s\n", CYAN_BEGIN, "Ignored: ", stats.GetIgnored(), CYAN_END);
410 fprintf(m_fp.Get(), "%s%s%3d%s\n", CYAN_BEGIN, "Failed: ", stats.GetFailed(), CYAN_END);
411 fprintf(m_fp.Get(), "%s%s%3d%s\n", CYAN_BEGIN, "Todo: ", stats.GetTODO(), CYAN_END);
412 fprintf(m_fp.Get(), "%s%s%3.0f%%%s\n", CYAN_BEGIN, "Succeeded or ignored %: ", stats.GetPassedOrIgnoredPercend(), CYAN_END);
415 std::string m_filename;
418 std::string m_currentGroup;
419 std::map<std::string, Statistic> m_groupsStats;
422 TestResultsCollectorBase* HtmlCollector::Constructor()
424 return new HtmlCollector();
428 : public TestResultsCollectorBase
431 static TestResultsCollectorBase* Constructor();
436 virtual void Start() {
437 printf("GROUP;ID;RESULT;REASON\n");
440 virtual void CollectCurrentTestGroupName(const std::string& name)
442 m_currentGroup = name;
445 virtual void CollectResult(const std::string& id,
446 const std::string& /*description*/,
447 const FailStatus::Type status = FailStatus::NONE,
448 const std::string& reason = "")
450 std::string statusMsg = "";
452 case TestResultsCollectorBase::FailStatus::NONE: statusMsg = "OK"; break;
453 case TestResultsCollectorBase::FailStatus::FAILED: statusMsg = "FAILED"; break;
454 case TestResultsCollectorBase::FailStatus::IGNORED: statusMsg = "IGNORED"; break;
455 case TestResultsCollectorBase::FailStatus::TODO: statusMsg = "TODO"; break;
456 case TestResultsCollectorBase::FailStatus::INTERNAL: statusMsg = "FAILED"; break;
458 Assert(false && "Bad status");
460 printf("%s;%s;%s;%s\n",
461 m_currentGroup.c_str(),
467 std::string m_currentGroup;
471 TestResultsCollectorBase* CSVCollector::Constructor()
473 return new CSVCollector();
479 : public TestResultsCollectorBase
482 static TestResultsCollectorBase* Constructor();
485 TAPCollector() : m_filename(DEFAULT_TAP_FILE_NAME) {}
487 virtual bool Configure()
489 m_output.open(m_filename.c_str(), std::ios_base::trunc);
490 if (m_output.fail()) {
491 LogError("Can't open output file: " << m_filename);
496 virtual std::string CollectorSpecificHelp() const
498 std::string retVal = "--file=<filename> - name of file for output\n"
500 retVal += DEFAULT_TAP_FILE_NAME;
507 Assert(m_output.good() && "Output file must be opened.");
508 m_output << "TAP version 13" << std::endl;
512 virtual void Finish()
514 m_output << "1.." << m_testIndex << std::endl;
515 m_output << m_collectedData.rdbuf();
519 virtual bool ParseCollectorSpecificArg(const std::string& arg)
521 const std::string argname = "--file=";
522 if (0 == arg.find(argname)) {
523 m_filename = arg.substr(argname.size());
532 virtual void CollectResult(const std::string& id,
533 const std::string& description,
534 const FailStatus::Type status = FailStatus::NONE,
535 const std::string& reason = "")
539 case TestResultsCollectorBase::FailStatus::NONE:
540 LogBasicTAP(true, id, description);
543 case TestResultsCollectorBase::FailStatus::FAILED:
544 LogBasicTAP(false, id, description);
547 case TestResultsCollectorBase::FailStatus::IGNORED:
548 LogBasicTAP(true, id, description);
549 m_collectedData << " # skip " << reason;
552 case TestResultsCollectorBase::FailStatus::TODO:
553 LogBasicTAP(false, id, description);
554 m_collectedData << " # TODO " << reason;
557 case TestResultsCollectorBase::FailStatus::INTERNAL:
558 LogBasicTAP(true, id, description);
560 m_collectedData << " ---" << std::endl;
561 m_collectedData << " message: " << reason << std::endl;
562 m_collectedData << " severity: Internal" << std::endl;
563 m_collectedData << " ..." << std::endl;
566 Assert(false && "Bad status");
570 void LogBasicTAP(bool isOK, const std::string& id,
571 const std::string& description)
574 m_collectedData << "not ";
576 m_collectedData << "ok " << m_testIndex << " [" <<
577 id << "] " << description;
582 m_collectedData << std::endl;
586 std::string m_filename;
587 std::stringstream m_collectedData;
588 std::ofstream m_output;
593 TestResultsCollectorBase* TAPCollector::Constructor()
595 return new TAPCollector();
599 void TestResultsCollectorBase::RegisterCollectorConstructor(
600 const std::string& name,
601 TestResultsCollectorBase::CollectorConstructorFunc func)
603 Assert(m_constructorsMap.find(name) == m_constructorsMap.end());
604 m_constructorsMap[name] = func;
607 TestResultsCollectorBase* TestResultsCollectorBase::Create(
608 const std::string& name)
610 ConstructorsMap::iterator found = m_constructorsMap.find(name);
611 if (found != m_constructorsMap.end())
612 return found->second();
617 std::vector<std::string> TestResultsCollectorBase::GetCollectorsNames()
619 std::vector<std::string> list;
620 FOREACH(it, m_constructorsMap)
622 list.push_back(it->first);
627 TestResultsCollectorBase::ConstructorsMap TestResultsCollectorBase::m_constructorsMap;
631 static int RegisterCollectorConstructors();
632 static const int RegisterHelperVariable = RegisterCollectorConstructors();
633 int RegisterCollectorConstructors()
635 (void)RegisterHelperVariable;
637 TestResultsCollectorBase::RegisterCollectorConstructor(
639 &ConsoleCollector::Constructor);
640 TestResultsCollectorBase::RegisterCollectorConstructor(
642 &HtmlCollector::Constructor);
643 TestResultsCollectorBase::RegisterCollectorConstructor(
645 &CSVCollector::Constructor);
646 TestResultsCollectorBase::RegisterCollectorConstructor(
648 &TAPCollector::Constructor);