Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1325)

Unified Diff: base/test/gtest_xml_util.cc

Issue 22893056: GTTF: make the new test launcher handle test crashes (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: ios Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/test/gtest_xml_util.h ('k') | base/test/test_launcher.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/test/gtest_xml_util.cc
diff --git a/base/test/gtest_xml_util.cc b/base/test/gtest_xml_util.cc
index 6187d9f3e5abb7d4eb11dce7ed88c653dadbba57..524369a6bd8144a6b727d2f0ff6227ee2d29a126 100644
--- a/base/test/gtest_xml_util.cc
+++ b/base/test/gtest_xml_util.cc
@@ -6,19 +6,100 @@
#include "base/file_util.h"
#include "base/logging.h"
+#include "base/strings/stringprintf.h"
#include "base/test/test_launcher.h"
#include "third_party/libxml/chromium/libxml_utils.h"
namespace base {
+namespace {
+
+// This is used for the xml parser to report errors. This assumes the context
+// is a pointer to a std::string where the error message should be appended.
+static void XmlErrorFunc(void *context, const char *message, ...) {
+ va_list args;
+ va_start(args, message);
+ std::string* error = static_cast<std::string*>(context);
+ base::StringAppendV(error, message, args);
+ va_end(args);
+}
+
+} // namespace
+
+XmlUnitTestResultPrinter::XmlUnitTestResultPrinter() : output_file_(NULL) {
+}
+
+XmlUnitTestResultPrinter::~XmlUnitTestResultPrinter() {
+ if (output_file_) {
+ fprintf(output_file_, "</testsuites>\n");
+ fflush(output_file_);
+ file_util::CloseFile(output_file_);
+ }
+}
+
+bool XmlUnitTestResultPrinter::Initialize(const FilePath& output_file_path) {
+ DCHECK(!output_file_);
+ output_file_ = file_util::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");
+ fprintf(output_file_, " </testcase>\n");
+ fflush(output_file_);
+}
+
+void XmlUnitTestResultPrinter::OnTestCaseEnd(
+ const testing::TestCase& test_case) {
+ fprintf(output_file_, " </testsuite>\n");
+ fflush(output_file_);
+}
+
bool ProcessGTestOutput(const base::FilePath& output_file,
- std::vector<TestResult>* results) {
+ std::vector<TestResult>* results,
+ bool* crashed) {
DCHECK(results);
std::string xml_contents;
if (!file_util::ReadFileToString(output_file, &xml_contents))
return false;
+ // Silence XML errors - otherwise they go to stderr.
+ std::string xml_errors;
+ ScopedXmlErrorFunc error_func(&xml_errors, &XmlErrorFunc);
+
XmlReader xml_reader;
if (!xml_reader.Load(xml_contents))
return false;
@@ -53,6 +134,23 @@ bool ProcessGTestOutput(const base::FilePath& output_file,
case STATE_TESTCASE:
if (node_name == "testsuite" && xml_reader.IsClosingElement()) {
state = STATE_TESTSUITE;
+ } else if (node_name == "x-teststart" &&
+ !xml_reader.IsClosingElement()) {
+ // This is our custom extension that helps recognize which test was
+ // running when the test binary crashed.
+ TestResult result;
+ if (!xml_reader.NodeAttribute("classname", &result.test_case_name))
+ return false;
+ if (!xml_reader.NodeAttribute("name", &result.test_name))
+ return false;
+
+ result.elapsed_time = TimeDelta();
+
+ // Assume the test crashed - we can correct that later.
+ result.success = false;
+ result.crashed = true;
+
+ results->push_back(result);
} else if (node_name == "testcase" && !xml_reader.IsClosingElement()) {
std::string test_status;
if (!xml_reader.NodeAttribute("status", &test_status))
@@ -77,6 +175,16 @@ bool ProcessGTestOutput(const base::FilePath& output_file,
Time::kMicrosecondsPerSecond);
result.success = true;
+ result.crashed = false;
+
+ if (!results->empty() &&
+ results->at(results->size() - 1).GetFullName() ==
+ result.GetFullName() &&
+ results->at(results->size() - 1).crashed) {
+ // Erase the fail-safe "crashed" result - now we know the test did
+ // not crash.
+ results->pop_back();
+ }
results->push_back(result);
} else if (node_name == "failure" && !xml_reader.IsClosingElement()) {
@@ -107,7 +215,8 @@ bool ProcessGTestOutput(const base::FilePath& output_file,
}
}
+ *crashed = (state != STATE_END);
return true;
}
-} // namespace base
+} // namespace base
« no previous file with comments | « base/test/gtest_xml_util.h ('k') | base/test/test_launcher.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698