Index: base/test/gtest_xml_util.cc |
diff --git a/base/test/gtest_xml_util.cc b/base/test/gtest_xml_util.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..6187d9f3e5abb7d4eb11dce7ed88c653dadbba57 |
--- /dev/null |
+++ b/base/test/gtest_xml_util.cc |
@@ -0,0 +1,113 @@ |
+// Copyright 2013 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_util.h" |
+ |
+#include "base/file_util.h" |
+#include "base/logging.h" |
+#include "base/test/test_launcher.h" |
+#include "third_party/libxml/chromium/libxml_utils.h" |
+ |
+namespace base { |
+ |
+bool ProcessGTestOutput(const base::FilePath& output_file, |
+ std::vector<TestResult>* results) { |
+ DCHECK(results); |
+ |
+ std::string xml_contents; |
+ if (!file_util::ReadFileToString(output_file, &xml_contents)) |
+ return false; |
+ |
+ XmlReader xml_reader; |
+ if (!xml_reader.Load(xml_contents)) |
+ return false; |
+ |
+ enum { |
+ STATE_INIT, |
+ STATE_TESTSUITE, |
+ STATE_TESTCASE, |
+ STATE_FAILURE, |
+ STATE_END, |
+ } state = STATE_INIT; |
+ |
+ while (xml_reader.Read()) { |
+ xml_reader.SkipToElement(); |
+ std::string node_name(xml_reader.NodeName()); |
+ |
+ switch (state) { |
+ case STATE_INIT: |
+ if (node_name == "testsuites" && !xml_reader.IsClosingElement()) |
+ state = STATE_TESTSUITE; |
+ else |
+ return false; |
+ break; |
+ case STATE_TESTSUITE: |
+ if (node_name == "testsuites" && xml_reader.IsClosingElement()) |
+ state = STATE_END; |
+ else if (node_name == "testsuite" && !xml_reader.IsClosingElement()) |
+ state = STATE_TESTCASE; |
+ else |
+ return false; |
+ break; |
+ case STATE_TESTCASE: |
+ if (node_name == "testsuite" && xml_reader.IsClosingElement()) { |
+ state = STATE_TESTSUITE; |
+ } else if (node_name == "testcase" && !xml_reader.IsClosingElement()) { |
+ std::string test_status; |
+ if (!xml_reader.NodeAttribute("status", &test_status)) |
+ return false; |
+ |
+ if (test_status != "run" && test_status != "notrun") |
+ return false; |
+ if (test_status != "run") |
+ break; |
+ |
+ TestResult result; |
+ if (!xml_reader.NodeAttribute("classname", &result.test_case_name)) |
+ return false; |
+ if (!xml_reader.NodeAttribute("name", &result.test_name)) |
+ return false; |
+ |
+ std::string test_time_str; |
+ if (!xml_reader.NodeAttribute("time", &test_time_str)) |
+ return false; |
+ result.elapsed_time = |
+ TimeDelta::FromMicroseconds(strtod(test_time_str.c_str(), NULL) * |
+ Time::kMicrosecondsPerSecond); |
+ |
+ result.success = true; |
+ |
+ results->push_back(result); |
+ } else if (node_name == "failure" && !xml_reader.IsClosingElement()) { |
+ std::string failure_message; |
+ if (!xml_reader.NodeAttribute("message", &failure_message)) |
+ return false; |
+ |
+ DCHECK(!results->empty()); |
+ results->at(results->size() - 1).success = false; |
+ |
+ state = STATE_FAILURE; |
+ } else if (node_name == "testcase" && xml_reader.IsClosingElement()) { |
+ // Deliberately empty. |
+ } else { |
+ return false; |
+ } |
+ break; |
+ case STATE_FAILURE: |
+ if (node_name == "failure" && xml_reader.IsClosingElement()) |
+ state = STATE_TESTCASE; |
+ else |
+ return false; |
+ break; |
+ case STATE_END: |
+ // If we are here and there are still XML elements, the file has wrong |
+ // format. |
+ return false; |
+ } |
+ } |
+ |
+ return true; |
+} |
+ |
+} // namespace base |