gtest_xml_util.cc 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. // Copyright 2013 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/test/gtest_xml_util.h"
  5. #include <stdint.h>
  6. #include "base/base64.h"
  7. #include "base/check.h"
  8. #include "base/files/file_util.h"
  9. #include "base/strings/string_number_conversions.h"
  10. #include "base/strings/stringprintf.h"
  11. #include "base/test/gtest_util.h"
  12. #include "base/test/launcher/test_launcher.h"
  13. #include "third_party/libxml/chromium/xml_reader.h"
  14. namespace base {
  15. struct Link {
  16. // The name of the test case.
  17. std::string name;
  18. // The name of the classname of the test.
  19. std::string classname;
  20. // The name of the link.
  21. std::string link_name;
  22. // The actual link.
  23. std::string link;
  24. };
  25. bool ProcessGTestOutput(const base::FilePath& output_file,
  26. std::vector<TestResult>* results,
  27. bool* crashed) {
  28. DCHECK(results);
  29. std::string xml_contents;
  30. if (!ReadFileToString(output_file, &xml_contents))
  31. return false;
  32. XmlReader xml_reader;
  33. if (!xml_reader.Load(xml_contents))
  34. return false;
  35. enum {
  36. STATE_INIT,
  37. STATE_TESTSUITE,
  38. STATE_TESTCASE,
  39. STATE_TEST_RESULT,
  40. STATE_FAILURE,
  41. STATE_END,
  42. } state = STATE_INIT;
  43. std::vector<Link> links;
  44. while (xml_reader.Read()) {
  45. xml_reader.SkipToElement();
  46. std::string node_name(xml_reader.NodeName());
  47. switch (state) {
  48. case STATE_INIT:
  49. if (node_name == "testsuites" && !xml_reader.IsClosingElement())
  50. state = STATE_TESTSUITE;
  51. else
  52. return false;
  53. break;
  54. case STATE_TESTSUITE:
  55. if (node_name == "testsuites" && xml_reader.IsClosingElement())
  56. state = STATE_END;
  57. else if (node_name == "testsuite" && !xml_reader.IsClosingElement())
  58. state = STATE_TESTCASE;
  59. else
  60. return false;
  61. break;
  62. case STATE_TESTCASE:
  63. if (node_name == "testsuite" && xml_reader.IsClosingElement()) {
  64. state = STATE_TESTSUITE;
  65. } else if (node_name == "x-teststart" &&
  66. !xml_reader.IsClosingElement()) {
  67. // This is our custom extension that helps recognize which test was
  68. // running when the test binary crashed.
  69. TestResult result;
  70. std::string test_case_name;
  71. if (!xml_reader.NodeAttribute("classname", &test_case_name))
  72. return false;
  73. std::string test_name;
  74. if (!xml_reader.NodeAttribute("name", &test_name))
  75. return false;
  76. result.full_name = FormatFullTestName(test_case_name, test_name);
  77. result.elapsed_time = TimeDelta();
  78. std::string test_timestamp_str;
  79. Time test_timestamp;
  80. if (xml_reader.NodeAttribute("timestamp", &test_timestamp_str) &&
  81. Time::FromString(test_timestamp_str.c_str(), &test_timestamp)) {
  82. result.timestamp = test_timestamp;
  83. }
  84. // Assume the test crashed - we can correct that later.
  85. result.status = TestResult::TEST_CRASH;
  86. results->push_back(result);
  87. } else if (node_name == "testcase" && !xml_reader.IsClosingElement()) {
  88. std::string test_status;
  89. if (!xml_reader.NodeAttribute("status", &test_status))
  90. return false;
  91. if (test_status != "run" && test_status != "notrun")
  92. return false;
  93. if (test_status != "run")
  94. break;
  95. TestResult result;
  96. std::string test_case_name;
  97. if (!xml_reader.NodeAttribute("classname", &test_case_name))
  98. return false;
  99. std::string test_name;
  100. if (!xml_reader.NodeAttribute("name", &test_name))
  101. return false;
  102. result.full_name = test_case_name + "." + test_name;
  103. std::string test_time_str;
  104. if (!xml_reader.NodeAttribute("time", &test_time_str))
  105. return false;
  106. result.elapsed_time = Microseconds(
  107. static_cast<int64_t>(strtod(test_time_str.c_str(), nullptr) *
  108. Time::kMicrosecondsPerSecond));
  109. // The timestamp attribute records the local date and time of the test
  110. // execution. It might be missing in the xml generated by older
  111. // version of test launcher or gtest.
  112. // https://github.com/google/googletest/blob/main/docs/advanced.md#generating-an-xml-report
  113. std::string test_timestamp_str;
  114. Time test_timestamp;
  115. if (xml_reader.NodeAttribute("timestamp", &test_timestamp_str) &&
  116. Time::FromString(test_timestamp_str.c_str(), &test_timestamp)) {
  117. result.timestamp = test_timestamp;
  118. }
  119. result.status = TestResult::TEST_SUCCESS;
  120. if (!results->empty() &&
  121. results->back().full_name == result.full_name &&
  122. results->back().status == TestResult::TEST_CRASH) {
  123. // Erase the fail-safe "crashed" result - now we know the test did
  124. // not crash.
  125. results->pop_back();
  126. }
  127. for (const Link& link : links) {
  128. if (link.name == test_name && link.classname == test_case_name) {
  129. result.AddLink(link.link_name, link.link);
  130. }
  131. }
  132. links.clear();
  133. results->push_back(result);
  134. } else if (node_name == "link" && !xml_reader.IsClosingElement()) {
  135. Link link;
  136. if (!xml_reader.NodeAttribute("name", &link.name))
  137. return false;
  138. if (!xml_reader.NodeAttribute("classname", &link.classname))
  139. return false;
  140. if (!xml_reader.NodeAttribute("link_name", &link.link_name))
  141. return false;
  142. if (!xml_reader.ReadElementContent(&link.link))
  143. return false;
  144. links.push_back(link);
  145. } else if (node_name == "link" && xml_reader.IsClosingElement()) {
  146. // Deliberately empty.
  147. } else if (node_name == "failure" && !xml_reader.IsClosingElement()) {
  148. std::string failure_message;
  149. if (!xml_reader.NodeAttribute("message", &failure_message))
  150. return false;
  151. DCHECK(!results->empty());
  152. results->back().status = TestResult::TEST_FAILURE;
  153. state = STATE_FAILURE;
  154. } else if (node_name == "testcase" && xml_reader.IsClosingElement()) {
  155. // Deliberately empty.
  156. } else if (node_name == "x-test-result-part" &&
  157. !xml_reader.IsClosingElement()) {
  158. std::string result_type;
  159. if (!xml_reader.NodeAttribute("type", &result_type))
  160. return false;
  161. std::string file_name;
  162. if (!xml_reader.NodeAttribute("file", &file_name))
  163. return false;
  164. std::string line_number_str;
  165. if (!xml_reader.NodeAttribute("line", &line_number_str))
  166. return false;
  167. int line_number;
  168. if (!StringToInt(line_number_str, &line_number))
  169. return false;
  170. TestResultPart::Type type;
  171. if (!TestResultPart::TypeFromString(result_type, &type))
  172. return false;
  173. TestResultPart test_result_part;
  174. test_result_part.type = type;
  175. test_result_part.file_name = file_name,
  176. test_result_part.line_number = line_number;
  177. DCHECK(!results->empty());
  178. results->back().test_result_parts.push_back(test_result_part);
  179. state = STATE_TEST_RESULT;
  180. } else {
  181. return false;
  182. }
  183. break;
  184. case STATE_TEST_RESULT:
  185. if (node_name == "summary" && !xml_reader.IsClosingElement()) {
  186. std::string summary;
  187. if (!xml_reader.ReadElementContent(&summary))
  188. return false;
  189. if (!Base64Decode(summary, &summary))
  190. return false;
  191. DCHECK(!results->empty());
  192. DCHECK(!results->back().test_result_parts.empty());
  193. results->back().test_result_parts.back().summary = summary;
  194. } else if (node_name == "summary" && xml_reader.IsClosingElement()) {
  195. } else if (node_name == "message" && !xml_reader.IsClosingElement()) {
  196. std::string message;
  197. if (!xml_reader.ReadElementContent(&message))
  198. return false;
  199. if (!Base64Decode(message, &message))
  200. return false;
  201. DCHECK(!results->empty());
  202. DCHECK(!results->back().test_result_parts.empty());
  203. results->back().test_result_parts.back().message = message;
  204. } else if (node_name == "message" && xml_reader.IsClosingElement()) {
  205. } else if (node_name == "x-test-result-part" &&
  206. xml_reader.IsClosingElement()) {
  207. state = STATE_TESTCASE;
  208. } else {
  209. return false;
  210. }
  211. break;
  212. case STATE_FAILURE:
  213. if (node_name == "failure" && xml_reader.IsClosingElement())
  214. state = STATE_TESTCASE;
  215. else
  216. return false;
  217. break;
  218. case STATE_END:
  219. // If we are here and there are still XML elements, the file has wrong
  220. // format.
  221. return false;
  222. }
  223. }
  224. if (crashed) {
  225. *crashed = (state != STATE_END);
  226. }
  227. return true;
  228. }
  229. } // namespace base