blob: 6ce4fdecf3fcddd2487f5e529e56f86d00f1a2e3 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/test/gtest_xml_unittest_result_printer.h"
#include "base/base64.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/time/time.h"
namespace base {
XmlUnitTestResultPrinter::XmlUnitTestResultPrinter() : output_file_(NULL) {
}
XmlUnitTestResultPrinter::~XmlUnitTestResultPrinter() {
if (output_file_) {
fprintf(output_file_, "</testsuites>\n");
fflush(output_file_);
CloseFile(output_file_);
}
}
bool XmlUnitTestResultPrinter::Initialize(const FilePath& output_file_path) {
DCHECK(!output_file_);
output_file_ = OpenFile(output_file_path, "w");
if (!output_file_)
return false;
fprintf(output_file_,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<testsuites>\n");
fflush(output_file_);
return true;
}
void XmlUnitTestResultPrinter::OnTestCaseStart(
const testing::TestCase& test_case) {
fprintf(output_file_, " <testsuite>\n");
fflush(output_file_);
}
void XmlUnitTestResultPrinter::OnTestStart(
const testing::TestInfo& test_info) {
// This is our custom extension - it helps to recognize which test was
// running when the test binary crashed. Note that we cannot even open the
// <testcase> tag here - it requires e.g. run time of the test to be known.
fprintf(output_file_,
" <x-teststart name=\"%s\" classname=\"%s\" />\n",
test_info.name(),
test_info.test_case_name());
fflush(output_file_);
}
void XmlUnitTestResultPrinter::OnTestEnd(const testing::TestInfo& test_info) {
fprintf(output_file_,
" <testcase name=\"%s\" status=\"run\" time=\"%.3f\""
" classname=\"%s\">\n",
test_info.name(),
static_cast<double>(test_info.result()->elapsed_time()) /
Time::kMillisecondsPerSecond,
test_info.test_case_name());
if (test_info.result()->Failed()) {
fprintf(output_file_,
" <failure message=\"\" type=\"\"></failure>\n");
}
for (int i = 0; i < test_info.result()->total_part_count(); ++i) {
WriteTestPartResult(test_info.result()->GetTestPartResult(i));
}
fprintf(output_file_, " </testcase>\n");
fflush(output_file_);
}
void XmlUnitTestResultPrinter::OnTestCaseEnd(
const testing::TestCase& test_case) {
fprintf(output_file_, " </testsuite>\n");
fflush(output_file_);
}
void XmlUnitTestResultPrinter::WriteTestPartResult(
const testing::TestPartResult& test_part_result) {
const char* type = "unknown";
switch (test_part_result.type()) {
case testing::TestPartResult::kSuccess:
type = "success";
break;
case testing::TestPartResult::kNonFatalFailure:
type = "failure";
break;
case testing::TestPartResult::kFatalFailure:
type = "fatal_failure";
break;
}
std::string summary = test_part_result.summary();
std::string summary_encoded;
Base64Encode(summary, &summary_encoded);
std::string message = test_part_result.message();
std::string message_encoded;
Base64Encode(message, &message_encoded);
fprintf(output_file_,
" <x-test-result-part type=\"%s\" file=\"%s\" line=\"%d\">\n"
" <summary>%s</summary>\n"
" <message>%s</message>\n"
" </x-test-result-part>\n",
type, test_part_result.file_name(), test_part_result.line_number(),
summary_encoded.c_str(), message_encoded.c_str());
fflush(output_file_);
}
} // namespace base