crash: Add specific error to user-collector sig.

The crash_reporter_user-collector signature is a catch-all signature for
a wide variety of errors. Using the same signature for all of these
errors jumbles them together and makes triaging them difficult.

BUG=chromium:1102611
TEST=tast run $DUT platform.UserCrash*
TEST=test_that --board=eve $DUT logging_UserCrash

Change-Id: I2b028f8f9f58ada5a21da8b86d14fa33dd66cb67
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2289935
Tested-by: Miriam Zimmerman <mutexlox@chromium.org>
Commit-Queue: Miriam Zimmerman <mutexlox@chromium.org>
Reviewed-by: Ian Barkley-Yeung <iby@chromium.org>
diff --git a/crash-reporter/crash_collector.cc b/crash-reporter/crash_collector.cc
index ee88fc5..f868daa 100644
--- a/crash-reporter/crash_collector.cc
+++ b/crash-reporter/crash_collector.cc
@@ -29,6 +29,7 @@
 #include <base/posix/eintr_wrapper.h>
 #include <base/run_loop.h>
 #include <base/scoped_clear_last_error.h>
+#include <base/strings/strcat.h>
 #include <base/strings/string_number_conversions.h>
 #include <base/strings/string_split.h>
 #include <base/strings/string_util.h>
@@ -1449,8 +1450,10 @@
     LOG(ERROR) << "Could not even get log directory; out of space?";
     return;
   }
-  AddCrashMetaData("sig", kCollectionErrorSignature);
-  AddCrashMetaData("error_type", GetErrorTypeSignature(error_type));
+
+  std::string type = GetErrorTypeSignature(error_type);
+  AddCrashMetaData("sig", base::StrCat({kCollectionErrorSignature, "_", type}));
+  AddCrashMetaData("error_type", type);
   FilePath log_path = GetCrashPath(crash_path, basename, "log");
 
   std::string error_log = brillo::GetLog();
diff --git a/crash-reporter/crash_collector.h b/crash-reporter/crash_collector.h
index 0d759dc..98bc762 100644
--- a/crash-reporter/crash_collector.h
+++ b/crash-reporter/crash_collector.h
@@ -192,6 +192,7 @@
   FRIEND_TEST(CrashCollectorTest, GetUptime);
   FRIEND_TEST(CrashCollectorTest, Initialize);
   FRIEND_TEST(CrashCollectorTest, MetaData);
+  FRIEND_TEST(CrashCollectorTest, ErrorCollectionMetaData);
   FRIEND_TEST(CrashCollectorTest, MetaDataDoesntCreateSymlink);
   FRIEND_TEST(CrashCollectorTest, MetaDataDoesntOverwriteSymlink);
   FRIEND_TEST(CrashCollectorTest, CollectionLogsToUMA);
diff --git a/crash-reporter/crash_collector_test.cc b/crash-reporter/crash_collector_test.cc
index cc678c9..c382013 100644
--- a/crash-reporter/crash_collector_test.cc
+++ b/crash-reporter/crash_collector_test.cc
@@ -893,6 +893,72 @@
   EXPECT_EQ(collector_.get_bytes_written(), expected_meta.size());
 }
 
+TEST_F(CrashCollectorTest, ErrorCollectionMetaData) {
+  // Set up metadata the collector will read
+  FilePath lsb_release = paths::Get("/etc/lsb-release");
+  std::string contents;
+  collector_.set_lsb_release_for_test(lsb_release);
+  const char kLsbContents[] =
+      "CHROMEOS_RELEASE_BOARD=lumpy\n"
+      "CHROMEOS_RELEASE_VERSION=6727.0.2015_01_26_0853\n"
+      "CHROMEOS_RELEASE_NAME=Chromium OS\n"
+      "CHROMEOS_RELEASE_CHROME_MILESTONE=82\n"
+      "CHROMEOS_RELEASE_DESCRIPTION=6727.0.2015_01_26_0853 (Test Build - foo)";
+  ASSERT_TRUE(test_util::CreateFile(lsb_release, kLsbContents));
+  base::Time os_time = base::Time::Now() - base::TimeDelta::FromDays(123);
+  // ext2/ext3 seem to have a timestamp granularity of 1s so round this time
+  // value down to the nearest second.
+  os_time = base::TimeDelta::FromSeconds(
+                (os_time - base::Time::UnixEpoch()).InSeconds()) +
+            base::Time::UnixEpoch();
+  ASSERT_TRUE(base::TouchFile(lsb_release, os_time, os_time));
+
+  std::unique_ptr<base::SimpleTestClock> test_clock =
+      std::make_unique<base::SimpleTestClock>();
+  test_clock->SetNow(base::Time::UnixEpoch() +
+                     base::TimeDelta::FromMilliseconds(kFakeNow));
+  collector_.set_test_clock(std::move(test_clock));
+
+  const char kKernelName[] = "Linux";
+  const char kKernelVersion[] = "3.8.11 #1 SMP Wed Aug 22 02:18:30 PDT 2018";
+  collector_.set_test_kernel_info(kKernelName, kKernelVersion);
+  collector_.set_crash_directory_for_test(test_dir_);
+
+  collector_.EnqueueCollectionErrorLog(
+      CrashCollector::kErrorUnsupported32BitCoreFile);
+
+  base::FilePath meta_file_path;
+  ASSERT_TRUE(test_util::DirectoryHasFileWithPattern(
+      test_dir_, "crash_reporter_failure.*.meta", &meta_file_path));
+
+  base::FilePath base_name = meta_file_path.BaseName().RemoveExtension();
+  base::FilePath pslog_name = base_name.AddExtension("pslog");
+  base::FilePath log_name = base_name.AddExtension("log");
+
+  EXPECT_TRUE(base::ReadFileToString(meta_file_path, &contents));
+  std::string expected_meta = StringPrintf(
+      "upload_var_collector=crash_reporter_failure\n"
+      "sig=crash_reporter-user-collection_unsupported-32bit-core-file\n"
+      "error_type=unsupported-32bit-core-file\n"
+      "upload_file_pslog=%s\n"
+      "upload_var_reportTimeMillis=%" PRId64
+      "\n"
+      "exec_name=crash_reporter_failure\n"
+      "upload_var_lsb-release=6727.0.2015_01_26_0853 (Test Build - foo)\n"
+      "ver=6727.0.2015_01_26_0853\n"
+      "upload_var_cros_milestone=82\n"
+      "os_millis=%" PRId64
+      "\n"
+      "upload_var_osName=%s\n"
+      "upload_var_osVersion=%s\n"
+      "payload=%s\n"
+      "done=1\n",
+      pslog_name.value().c_str(), kFakeNow,
+      (os_time - base::Time::UnixEpoch()).InMilliseconds(), kKernelName,
+      kKernelVersion, log_name.value().c_str());
+  EXPECT_EQ(expected_meta, contents);
+}
+
 // Test target of symlink is not overwritten.
 TEST_F(CrashCollectorTest, MetaDataDoesntOverwriteSymlink) {
   const char kSymlinkTarget[] = "important_file";