Set limit for number of failed EXPECTs per test in test launcher output.

Some tests may contain broken EXPECT with a large message inside a loop
with several thousands iterations and produce huge output (several
gigabytes). Limit number of serialized test result parts to prevent it.

R=phajdan.jr
BUG=

Review-Url: https://codereview.chromium.org/2846673004
Cr-Commit-Position: refs/heads/master@{#471766}


CrOS-Libchrome-Original-Commit: 452ecc0e7cf545a650047227a7e9ce4702ed227d
diff --git a/base/test/gtest_xml_unittest_result_printer.cc b/base/test/gtest_xml_unittest_result_printer.cc
index 31ac4ad..81a3d9f 100644
--- a/base/test/gtest_xml_unittest_result_printer.cc
+++ b/base/test/gtest_xml_unittest_result_printer.cc
@@ -5,14 +5,23 @@
 #include "base/test/gtest_xml_unittest_result_printer.h"
 
 #include "base/base64.h"
+#include "base/command_line.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
+#include "base/test/test_switches.h"
 #include "base/time/time.h"
 
 namespace base {
 
-XmlUnitTestResultPrinter::XmlUnitTestResultPrinter() : output_file_(NULL) {
-}
+namespace {
+const int kDefaultTestPartResultsLimit = 10;
+
+const char kTestPartLesultsLimitExceeded[] =
+    "Test part results limit exceeded. Use --test-launcher-test-part-limit to "
+    "increase or disable limit.";
+}  // namespace
+
+XmlUnitTestResultPrinter::XmlUnitTestResultPrinter() : output_file_(NULL) {}
 
 XmlUnitTestResultPrinter::~XmlUnitTestResultPrinter() {
   if (output_file_) {
@@ -73,12 +82,33 @@
     fprintf(output_file_,
             "      <failure message=\"\" type=\"\"></failure>\n");
   }
-  for (int i = 0; i < test_info.result()->total_part_count(); ++i) {
+
+  int limit = test_info.result()->total_part_count();
+  if (CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kTestLauncherTestPartResultsLimit)) {
+    std::string limit_str =
+        CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+            switches::kTestLauncherTestPartResultsLimit);
+    int test_part_results_limit = std::strtol(limit_str.c_str(), nullptr, 10);
+    if (test_part_results_limit >= 0)
+      limit = std::min(limit, test_part_results_limit);
+  } else {
+    limit = std::min(limit, kDefaultTestPartResultsLimit);
+  }
+
+  for (int i = 0; i < limit; ++i) {
     const auto& test_part_result = test_info.result()->GetTestPartResult(i);
     WriteTestPartResult(test_part_result.file_name(),
                         test_part_result.line_number(), test_part_result.type(),
                         test_part_result.summary(), test_part_result.message());
   }
+
+  if (test_info.result()->total_part_count() > limit) {
+    WriteTestPartResult(
+        "<unknown>", 0, testing::TestPartResult::kNonFatalFailure,
+        kTestPartLesultsLimitExceeded, kTestPartLesultsLimitExceeded);
+  }
+
   fprintf(output_file_, "    </testcase>\n");
   fflush(output_file_);
 }
diff --git a/base/test/launcher/unit_test_launcher.cc b/base/test/launcher/unit_test_launcher.cc
index 44c440f..65531a2 100644
--- a/base/test/launcher/unit_test_launcher.cc
+++ b/base/test/launcher/unit_test_launcher.cc
@@ -92,6 +92,11 @@
           "    Controls when full test output is printed.\n"
           "    auto means to print it when the test failed.\n"
           "\n"
+          "  --test-launcher-test-part-results-limit=N\n"
+          "    Sets the limit of failed EXPECT/ASSERT entries in the xml and\n"
+          "    JSON outputs per test to N (default N=10). Negative value \n"
+          "    will disable this limit.\n"
+          "\n"
           "  --test-launcher-total-shards=N\n"
           "    Sets the total number of shards to N.\n"
           "\n"
diff --git a/base/test/test_switches.cc b/base/test/test_switches.cc
index 817a38e..48f6861 100644
--- a/base/test/test_switches.cc
+++ b/base/test/test_switches.cc
@@ -56,6 +56,11 @@
 const char switches::kTestLauncherShardIndex[] =
     "test-launcher-shard-index";
 
+// Limit of test part results in the output. Default limit is 10.
+// Negative value will completely disable limit.
+const char switches::kTestLauncherTestPartResultsLimit[] =
+    "test-launcher-test-part-results-limit";
+
 // Total number of shards. Must be the same for all shards.
 const char switches::kTestLauncherTotalShards[] =
     "test-launcher-total-shards";
diff --git a/base/test/test_switches.h b/base/test/test_switches.h
index 88ef0ce..580aafd 100644
--- a/base/test/test_switches.h
+++ b/base/test/test_switches.h
@@ -22,6 +22,7 @@
 extern const char kTestLauncherPrintTestStdio[];
 extern const char kTestLauncherPrintWritablePath[];
 extern const char kTestLauncherShardIndex[];
+extern const char kTestLauncherTestPartResultsLimit[];
 extern const char kTestLauncherTotalShards[];
 extern const char kTestLauncherTimeout[];
 extern const char kTestLauncherTrace[];