crash: Introduce util.h/cc
Move IsCrashTestInProgress() and IsDeveloperImage() to
util.h/cc. These functions will be needed for porting
the equivalents (is_crash_test_in_progress() and
is_developer_mode()) from crash_sender.sh to C++.
Add unit tests for them.
Also rename chrome_paths.h/cc to paths.h/cc and move
paths::Get() stuff to paths.h/cc.
BUG=chromium:391887
TEST=unit tests
Change-Id: I073e3dc783d9cc2ad840efc3d14b2bdef9d07f93
Reviewed-on: https://chromium-review.googlesource.com/1170710
Commit-Ready: Satoru Takabayashi <satorux@google.com>
Tested-by: Satoru Takabayashi <satorux@google.com>
Reviewed-by: Mike Frysinger <vapier@chromium.org>
Reviewed-by: Daichi Hirono <hirono@chromium.org>
diff --git a/crash-reporter/arc_collector.cc b/crash-reporter/arc_collector.cc
index ff01edd..a201fe0 100644
--- a/crash-reporter/arc_collector.cc
+++ b/crash-reporter/arc_collector.cc
@@ -24,6 +24,8 @@
#include <brillo/key_value_store.h>
#include <brillo/process.h>
+#include "crash-reporter/util.h"
+
using base::File;
using base::FilePath;
using base::ReadFileToString;
@@ -153,7 +155,7 @@
const std::string& cpu_abi) {
std::string reason;
const bool should_dump = UserCollectorBase::ShouldDump(
- is_feedback_allowed_function_(), IsDeveloperImage(), &reason);
+ is_feedback_allowed_function_(), util::IsDeveloperImage(), &reason);
std::ostringstream message;
message << "Received " << crash_type << " notification";
@@ -335,7 +337,7 @@
}
return UserCollectorBase::ShouldDump(is_feedback_allowed_function_(),
- IsDeveloperImage(), reason);
+ util::IsDeveloperImage(), reason);
}
UserCollectorBase::ErrorType ArcCollector::ConvertCoreToMinidump(
diff --git a/crash-reporter/crash-reporter.gyp b/crash-reporter/crash-reporter.gyp
index d063ea7..8416af1 100644
--- a/crash-reporter/crash-reporter.gyp
+++ b/crash-reporter/crash-reporter.gyp
@@ -5,6 +5,27 @@
'type': 'static_library',
'variables': {
'exported_deps': [
+ 'libchrome-<(libbase_ver)',
+ ],
+ 'deps': ['<@(exported_deps)'],
+ },
+ 'all_dependent_settings': {
+ 'variables': {
+ 'deps': [
+ '<@(exported_deps)',
+ ],
+ },
+ },
+ 'sources': [
+ 'paths.cc',
+ 'util.cc',
+ ],
+ },
+ {
+ 'target_name': 'libcrash_reporter',
+ 'type': 'static_library',
+ 'variables': {
+ 'exported_deps': [
'libbrillo-<(libbase_ver)',
'libchrome-<(libbase_ver)',
'libdebugd-client',
@@ -63,6 +84,7 @@
},
'dependencies': [
'libcrash',
+ 'libcrash_reporter',
],
'defines': [
'USE_CHEETS=<(USE_cheets)',
@@ -81,9 +103,11 @@
'libminijail',
],
},
+ 'dependencies': [
+ 'libcrash',
+ ],
'sources': [
'crash_sender.cc',
- 'crash_sender_paths.cc',
'crash_sender_util.cc',
],
},
@@ -159,20 +183,22 @@
'target_name': 'crash_reporter_test',
'type': 'executable',
'includes': ['../common-mk/common_test.gypi'],
- 'dependencies': ['libcrash'],
+ 'dependencies': [
+ 'libcrash',
+ 'libcrash_reporter',
+ ],
'sources': [
'chrome_collector_test.cc',
'crash_collector_test.cc',
'crash_collector_test.h',
'crash_reporter_logs_test.cc',
- 'crash_sender_paths.cc',
- 'crash_sender_paths_test.cc',
'crash_sender_util.cc',
'crash_sender_util_test.cc',
'ec_collector_test.cc',
'kernel_collector_test.cc',
'kernel_collector_test.h',
'kernel_warning_collector_test.cc',
+ 'paths_test.cc',
'selinux_violation_collector_test.cc',
'service_failure_collector_test.cc',
'test_util.cc',
@@ -180,6 +206,7 @@
'udev_collector_test.cc',
'unclean_shutdown_collector_test.cc',
'user_collector_test.cc',
+ 'util_test.cc',
],
'conditions': [
['USE_cheets == 1', {
diff --git a/crash-reporter/crash_collector.cc b/crash-reporter/crash_collector.cc
index d643c17..41e9a4f 100644
--- a/crash-reporter/crash_collector.cc
+++ b/crash-reporter/crash_collector.cc
@@ -32,17 +32,16 @@
#include <brillo/key_value_store.h>
#include <brillo/process.h>
-#include "crash-reporter/crash_common_paths.h"
+#include "crash-reporter/paths.h"
+#include "crash-reporter/util.h"
namespace {
const char kCollectChromeFile[] =
"/mnt/stateful_partition/etc/collect_chrome_crashes";
-const char kCrashTestInProgressPath[] = "crash-test-in-progress";
const char kCrashReporterStatePath[] = "/var/lib/crash_reporter";
const char kDefaultLogConfig[] = "/etc/crash_reporter_logs.conf";
const char kDefaultUserName[] = "chronos";
-const char kLeaveCoreFile[] = "/root/.leave_core";
const char kLsbRelease[] = "/etc/lsb-release";
const char kShellPath[] = "/bin/sh";
const char kSystemCrashPath[] = "/var/spool/crash";
@@ -832,24 +831,11 @@
}
}
-bool CrashCollector::IsCrashTestInProgress() {
- return base::PathExists(FilePath(paths::kSystemRunStateDirectory)
- .Append(kCrashTestInProgressPath));
-}
-
-bool CrashCollector::IsDeveloperImage() {
- // If we're testing crash reporter itself, we don't want to special-case
- // for developer images.
- if (IsCrashTestInProgress())
- return false;
- return base::PathExists(FilePath(kLeaveCoreFile));
-}
-
bool CrashCollector::ShouldHandleChromeCrashes() {
// If we're testing crash reporter itself, we don't want to allow an
// override for chrome crashes. And, let's be conservative and only
// allow an override for developer images.
- if (!IsCrashTestInProgress() && IsDeveloperImage()) {
+ if (!util::IsCrashTestInProgress() && util::IsDeveloperImage()) {
// Check if there's an override to indicate we should indeed collect
// chrome crashes. This allows the crashes to still be tracked when
// they occur in autotests. See "crosbug.com/17987".
diff --git a/crash-reporter/crash_collector.h b/crash-reporter/crash_collector.h
index 33437e8..102f0da 100644
--- a/crash-reporter/crash_collector.h
+++ b/crash-reporter/crash_collector.h
@@ -212,11 +212,6 @@
const std::string& exec_name,
const std::string& payload_name);
- // Returns true if the a crash test is currently running.
- bool IsCrashTestInProgress();
- // Returns true if we should consider ourselves to be running on a
- // developer image.
- bool IsDeveloperImage();
// Returns true if chrome crashes should be handled.
bool ShouldHandleChromeCrashes();
// Returns true if user crash directory may be used.
diff --git a/crash-reporter/crash_common_paths.h b/crash-reporter/crash_common_paths.h
deleted file mode 100644
index 602de3b..0000000
--- a/crash-reporter/crash_common_paths.h
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2018 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CRASH_REPORTER_CRASH_COMMON_PATHS_H_
-#define CRASH_REPORTER_CRASH_COMMON_PATHS_H_
-
-namespace paths {
-
-// The base directory where we keep various state flags.
-constexpr char kSystemRunStateDirectory[] = "/run/crash_reporter";
-
-} // namespace paths
-
-#endif // CRASH_REPORTER_CRASH_COMMON_PATHS_H_
diff --git a/crash-reporter/crash_sender.cc b/crash-reporter/crash_sender.cc
index 9d1984a..b29f77a 100644
--- a/crash-reporter/crash_sender.cc
+++ b/crash-reporter/crash_sender.cc
@@ -20,6 +20,7 @@
#include "crash-reporter/crash_sender_paths.h"
#include "crash-reporter/crash_sender_util.h"
+#include "crash-reporter/paths.h"
namespace {
diff --git a/crash-reporter/crash_sender.sh b/crash-reporter/crash_sender.sh
index 8e80471..346a23c 100755
--- a/crash-reporter/crash_sender.sh
+++ b/crash-reporter/crash_sender.sh
@@ -86,14 +86,14 @@
}
# Returns 0 if the a crash test is currently running. NOTE: Mirrors
-# crash_collector.cc:CrashCollector::IsCrashTestInProgress().
+# util.cc:IsCrashTestInProgress().
is_crash_test_in_progress() {
[ -f "${CRASH_TEST_IN_PROGRESS_FILE}" ] && return 0
return 1
}
# Returns 0 if we should consider ourselves to be running on a developer
-# image. NOTE: Mirrors crash_collector.cc:CrashCollector::IsDeveloperImage().
+# image. NOTE: Mirrors util.cc:IsDeveloperImage().
is_developer_image() {
# If we're testing crash reporter itself, we don't want to special-case
# for developer images.
diff --git a/crash-reporter/crash_sender_paths.h b/crash-reporter/crash_sender_paths.h
index ebb3bc4..3821974 100644
--- a/crash-reporter/crash_sender_paths.h
+++ b/crash-reporter/crash_sender_paths.h
@@ -5,13 +5,8 @@
#ifndef CRASH_REPORTER_CRASH_SENDER_PATHS_H_
#define CRASH_REPORTER_CRASH_SENDER_PATHS_H_
-#include <base/files/file_path.h>
-#include <base/strings/string_piece.h>
-
namespace paths {
-// The path constants here should be used with Get() function below.
-
// File whose existence mocks crash sending. If empty we pretend the
// crash sending was successful, otherwise unsuccessful.
constexpr char kMockCrashSending[] = "mock-crash-sending";
@@ -23,19 +18,6 @@
// Must be stateful to enable testing kernel crashes.
constexpr char kPauseCrashSending[] = "/var/lib/crash_sender_paused";
-// Gets a FilePath from the given path. A prefix will be added if the prefix is
-// set with SetPrefixForTesting().
-base::FilePath Get(base::StringPiece file_path);
-
-// Gets a FilePath from the given directory and the base name. A prefix will be
-// added if the prefix is set with SetPrefixForTesting().
-base::FilePath GetAt(base::StringPiece directory, base::StringPiece base_name);
-
-// Sets a prefix that'll be added when Get() is called, for unit testing.
-// For example, if "/tmp" is set as the prefix, Get("/run/foo") will return
-// "/tmp/run/foo". Passing "" will reset the prefix.
-void SetPrefixForTesting(const base::FilePath& prefix);
-
} // namespace paths
#endif // CRASH_REPORTER_CRASH_SENDER_PATHS_H_
diff --git a/crash-reporter/crash_sender_util.cc b/crash-reporter/crash_sender_util.cc
index ddbd2c8..01a81f1 100644
--- a/crash-reporter/crash_sender_util.cc
+++ b/crash-reporter/crash_sender_util.cc
@@ -15,8 +15,8 @@
#include <base/strings/string_number_conversions.h>
#include <brillo/flag_helper.h>
-#include "crash-reporter/crash_common_paths.h"
#include "crash-reporter/crash_sender_paths.h"
+#include "crash-reporter/paths.h"
namespace util {
diff --git a/crash-reporter/crash_sender_util_test.cc b/crash-reporter/crash_sender_util_test.cc
index 9ecadd0..cb322c8 100644
--- a/crash-reporter/crash_sender_util_test.cc
+++ b/crash-reporter/crash_sender_util_test.cc
@@ -13,8 +13,8 @@
#include <brillo/flag_helper.h>
#include <gtest/gtest.h>
-#include "crash-reporter/crash_common_paths.h"
#include "crash-reporter/crash_sender_paths.h"
+#include "crash-reporter/paths.h"
#include "crash-reporter/test_util.h"
namespace util {
diff --git a/crash-reporter/ec_collector.cc b/crash-reporter/ec_collector.cc
index b77dc5c..44fde30 100644
--- a/crash-reporter/ec_collector.cc
+++ b/crash-reporter/ec_collector.cc
@@ -10,6 +10,8 @@
#include <base/logging.h>
#include <base/strings/stringprintf.h>
+#include "crash-reporter/util.h"
+
using base::FilePath;
using base::StringPiece;
using base::StringPrintf;
@@ -55,7 +57,7 @@
std::string reason = "handling";
bool feedback = true;
- if (IsDeveloperImage()) {
+ if (util::IsDeveloperImage()) {
reason = "developer build - always dumping";
feedback = true;
} else if (!is_feedback_allowed_function_()) {
diff --git a/crash-reporter/kernel_collector.cc b/crash-reporter/kernel_collector.cc
index ae53a25..f40224b 100644
--- a/crash-reporter/kernel_collector.cc
+++ b/crash-reporter/kernel_collector.cc
@@ -19,6 +19,8 @@
using base::StringPiece;
using base::StringPrintf;
+#include "crash-reporter/util.h"
+
namespace {
const char kDefaultKernelStackSignature[] = "kernel-UnspecifiedStackSignature";
@@ -628,7 +630,7 @@
FilePath root_crash_directory;
std::string reason = "handling";
bool feedback = true;
- if (IsDeveloperImage()) {
+ if (util::IsDeveloperImage()) {
reason = "developer build - always dumping";
feedback = true;
} else if (!is_feedback_allowed_function_()) {
diff --git a/crash-reporter/kernel_warning_collector.cc b/crash-reporter/kernel_warning_collector.cc
index a1397fc..91d0b94 100644
--- a/crash-reporter/kernel_warning_collector.cc
+++ b/crash-reporter/kernel_warning_collector.cc
@@ -10,6 +10,8 @@
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
+#include "crash-reporter/util.h"
+
namespace {
const char kGenericWarningExecName[] = "kernel-warning";
const char kWifiWarningExecName[] = "kernel-wifi-warning";
@@ -47,7 +49,7 @@
bool KernelWarningCollector::Collect(WarningType type) {
std::string reason = "normal collection";
bool feedback = true;
- if (IsDeveloperImage()) {
+ if (util::IsDeveloperImage()) {
reason = "always collect from developer builds";
feedback = true;
} else if (!is_feedback_allowed_function_()) {
diff --git a/crash-reporter/crash_sender_paths.cc b/crash-reporter/paths.cc
similarity index 94%
rename from crash-reporter/crash_sender_paths.cc
rename to crash-reporter/paths.cc
index 32fc300..cba904e 100644
--- a/crash-reporter/crash_sender_paths.cc
+++ b/crash-reporter/paths.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "crash-reporter/crash_sender_paths.h"
+#include "crash-reporter/paths.h"
namespace paths {
diff --git a/crash-reporter/paths.h b/crash-reporter/paths.h
new file mode 100644
index 0000000..8626d8a
--- /dev/null
+++ b/crash-reporter/paths.h
@@ -0,0 +1,38 @@
+// Copyright 2018 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRASH_REPORTER_PATHS_H_
+#define CRASH_REPORTER_PATHS_H_
+
+#include <base/files/file_path.h>
+#include <base/strings/string_piece.h>
+
+namespace paths {
+
+// The base directory where we keep various state flags.
+constexpr char kSystemRunStateDirectory[] = "/run/crash_reporter";
+
+// File whose existence indicates this is a developer image.
+constexpr char kLeaveCoreFile[] = "/root/.leave_core";
+
+// Base name of file whose existence indicates a crash test is currently
+// running.
+constexpr char kCrashTestInProgress[] = "crash-test-in-progress";
+
+// Gets a FilePath from the given path. A prefix will be added if the prefix is
+// set with SetPrefixForTesting().
+base::FilePath Get(base::StringPiece file_path);
+
+// Gets a FilePath from the given directory and the base name. A prefix will be
+// added if the prefix is set with SetPrefixForTesting().
+base::FilePath GetAt(base::StringPiece directory, base::StringPiece base_name);
+
+// Sets a prefix that'll be added when Get() is called, for unit testing.
+// For example, if "/tmp" is set as the prefix, Get("/run/foo") will return
+// "/tmp/run/foo". Passing "" will reset the prefix.
+void SetPrefixForTesting(const base::FilePath& prefix);
+
+} // namespace paths
+
+#endif // CRASH_REPORTER_PATHS_H_
diff --git a/crash-reporter/crash_sender_paths_test.cc b/crash-reporter/paths_test.cc
similarity index 81%
rename from crash-reporter/crash_sender_paths_test.cc
rename to crash-reporter/paths_test.cc
index d467ac9..2f3b0e8 100644
--- a/crash-reporter/crash_sender_paths_test.cc
+++ b/crash-reporter/paths_test.cc
@@ -2,25 +2,25 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "crash-reporter/crash_sender_paths.h"
+#include "crash-reporter/paths.h"
#include <base/files/file_path.h>
#include <gtest/gtest.h>
namespace util {
-TEST(CrashSenderPathsTest, Get) {
+TEST(CrashCommonPathsTest, Get) {
EXPECT_EQ("/run/foo", paths::Get("/run/foo").value());
}
-TEST(CrashSenderPathsTest, SetPrefixForTesting) {
+TEST(CrashCommonPathsTest, SetPrefixForTesting) {
paths::SetPrefixForTesting(base::FilePath("/tmp"));
EXPECT_EQ("/tmp/run/foo", paths::Get("/run/foo").value());
paths::SetPrefixForTesting(base::FilePath());
EXPECT_EQ("/run/foo", paths::Get("/run/foo").value());
}
-TEST(CrashSenderPathsTest, GetAtWithPrefix) {
+TEST(CrashCommonPathsTest, GetAtWithPrefix) {
paths::SetPrefixForTesting(base::FilePath("/tmp"));
EXPECT_EQ("/tmp/run/foo", paths::GetAt("/run", "foo").value());
paths::SetPrefixForTesting(base::FilePath());
diff --git a/crash-reporter/selinux_violation_collector.cc b/crash-reporter/selinux_violation_collector.cc
index 4494e16..a9690f2 100644
--- a/crash-reporter/selinux_violation_collector.cc
+++ b/crash-reporter/selinux_violation_collector.cc
@@ -11,6 +11,8 @@
#include <base/rand_util.h>
#include <base/strings/stringprintf.h>
+#include "crash-reporter/util.h"
+
namespace {
constexpr char kExecName[] = "selinux-violation";
constexpr char kSignatureKey[] = "sig";
@@ -66,7 +68,7 @@
bool SELinuxViolationCollector::Collect() {
std::string reason = "normal collection";
bool feedback = true;
- if (IsDeveloperImage() || developer_image_for_testing_) {
+ if (util::IsDeveloperImage() || developer_image_for_testing_) {
feedback = true;
reason = "always collect from developer builds";
} else if (!is_feedback_allowed_function_()) {
diff --git a/crash-reporter/service_failure_collector.cc b/crash-reporter/service_failure_collector.cc
index 01f6871..9c62061 100644
--- a/crash-reporter/service_failure_collector.cc
+++ b/crash-reporter/service_failure_collector.cc
@@ -8,6 +8,8 @@
#include <base/logging.h>
#include <base/strings/stringprintf.h>
+#include "crash-reporter/util.h"
+
namespace {
const char kExecName[] = "service-failure";
const char kSignatureKey[] = "sig";
@@ -41,7 +43,7 @@
bool ServiceFailureCollector::Collect() {
std::string reason = "normal collection";
bool feedback = true;
- if (IsDeveloperImage()) {
+ if (util::IsDeveloperImage()) {
reason = "always collect from developer builds";
feedback = true;
} else if (!is_feedback_allowed_function_()) {
diff --git a/crash-reporter/udev_collector.cc b/crash-reporter/udev_collector.cc
index bca4e59..5a7645e 100644
--- a/crash-reporter/udev_collector.cc
+++ b/crash-reporter/udev_collector.cc
@@ -17,6 +17,8 @@
#include <base/strings/stringprintf.h>
#include <brillo/process.h>
+#include "crash-reporter/util.h"
+
using base::FilePath;
namespace {
@@ -38,7 +40,7 @@
UdevCollector::~UdevCollector() {}
bool UdevCollector::HandleCrash(const std::string& udev_event) {
- if (IsDeveloperImage()) {
+ if (util::IsDeveloperImage()) {
LOG(INFO) << "developer image - collect udev crash info.";
} else if (is_feedback_allowed_function_()) {
LOG(INFO) << "Consent given - collect udev crash info.";
@@ -80,7 +82,7 @@
bool UdevCollector::Enable() {
return base::WriteFile(FilePath(kDevCoredumpDisabledPath),
- IsDeveloperImage() ? "0" : "1", 1);
+ util::IsDeveloperImage() ? "0" : "1", 1);
}
bool UdevCollector::ProcessUdevCrashLogs(const FilePath& crash_directory,
diff --git a/crash-reporter/user_collector.cc b/crash-reporter/user_collector.cc
index f4dd755..408ca90 100644
--- a/crash-reporter/user_collector.cc
+++ b/crash-reporter/user_collector.cc
@@ -19,6 +19,8 @@
#include <base/strings/stringprintf.h>
#include <brillo/process.h>
+#include "crash-reporter/util.h"
+
using base::FilePath;
using base::StringPrintf;
@@ -289,8 +291,9 @@
uid_t,
const std::string& exec,
std::string* reason) {
- return ShouldDump(pid, is_feedback_allowed_function_(), IsDeveloperImage(),
- ShouldHandleChromeCrashes(), exec, reason);
+ return ShouldDump(pid, is_feedback_allowed_function_(),
+ util::IsDeveloperImage(), ShouldHandleChromeCrashes(), exec,
+ reason);
}
UserCollector::ErrorType UserCollector::ConvertCoreToMinidump(
diff --git a/crash-reporter/user_collector_base.cc b/crash-reporter/user_collector_base.cc
index ec55161..d9aab85 100644
--- a/crash-reporter/user_collector_base.cc
+++ b/crash-reporter/user_collector_base.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "crash-reporter/user_collector_base.h"
+
#include <pcrecpp.h>
#if USE_DIRENCRYPTION
@@ -13,7 +15,7 @@
#include <base/strings/stringprintf.h>
#include <brillo/syslog_logging.h>
-#include "crash-reporter/user_collector_base.h"
+#include "crash-reporter/util.h"
using base::FilePath;
using base::ReadFileToString;
@@ -295,7 +297,7 @@
// crash report.
WriteCrashMetaData(meta_path, exec, minidump_path.value());
- if (!IsDeveloperImage()) {
+ if (!util::IsDeveloperImage()) {
base::DeleteFile(core_path, false);
} else {
LOG(INFO) << "Leaving core file at " << core_path.value()
diff --git a/crash-reporter/util.cc b/crash-reporter/util.cc
new file mode 100644
index 0000000..ce31bd8
--- /dev/null
+++ b/crash-reporter/util.cc
@@ -0,0 +1,26 @@
+// Copyright 2018 The Chromium OS 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 "crash-reporter/util.h"
+
+#include <base/files/file_util.h>
+
+#include "crash-reporter/paths.h"
+
+namespace util {
+
+bool IsCrashTestInProgress() {
+ return base::PathExists(paths::GetAt(paths::kSystemRunStateDirectory,
+ paths::kCrashTestInProgress));
+}
+
+bool IsDeveloperImage() {
+ // If we're testing crash reporter itself, we don't want to special-case
+ // for developer images.
+ if (IsCrashTestInProgress())
+ return false;
+ return base::PathExists(paths::Get(paths::kLeaveCoreFile));
+}
+
+} // namespace util
diff --git a/crash-reporter/util.h b/crash-reporter/util.h
new file mode 100644
index 0000000..1b1595e
--- /dev/null
+++ b/crash-reporter/util.h
@@ -0,0 +1,18 @@
+// Copyright 2018 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRASH_REPORTER_UTIL_H_
+#define CRASH_REPORTER_UTIL_H_
+
+namespace util {
+
+// Returns true if integration tests are currently running.
+bool IsCrashTestInProgress();
+
+// Returns true if running on a developer image.
+bool IsDeveloperImage();
+
+} // namespace util
+
+#endif // CRASH_REPORTER_UTIL_H_
diff --git a/crash-reporter/util_test.cc b/crash-reporter/util_test.cc
new file mode 100644
index 0000000..a458741
--- /dev/null
+++ b/crash-reporter/util_test.cc
@@ -0,0 +1,53 @@
+// Copyright 2018 The Chromium OS 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 "crash-reporter/util.h"
+
+#include <base/files/file_util.h>
+#include <base/files/scoped_temp_dir.h>
+#include <gtest/gtest.h>
+
+#include "crash-reporter/crash_sender_paths.h"
+#include "crash-reporter/paths.h"
+#include "crash-reporter/test_util.h"
+
+namespace util {
+
+class CrashCommonUtilTest : public testing::Test {
+ private:
+ void SetUp() override {
+ ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
+ test_dir_ = scoped_temp_dir_.GetPath();
+ paths::SetPrefixForTesting(test_dir_);
+ }
+
+ void TearDown() override { paths::SetPrefixForTesting(base::FilePath()); }
+
+ base::FilePath test_dir_;
+ base::ScopedTempDir scoped_temp_dir_;
+};
+
+TEST_F(CrashCommonUtilTest, IsCrashTestInProgress) {
+ EXPECT_FALSE(IsCrashTestInProgress());
+ ASSERT_TRUE(
+ test_util::CreateFile(paths::GetAt(paths::kSystemRunStateDirectory,
+ paths::kCrashTestInProgress),
+ ""));
+ EXPECT_TRUE(IsCrashTestInProgress());
+}
+
+TEST_F(CrashCommonUtilTest, IsDeveloperImage) {
+ EXPECT_FALSE(IsDeveloperImage());
+
+ ASSERT_TRUE(test_util::CreateFile(paths::Get(paths::kLeaveCoreFile), ""));
+ EXPECT_TRUE(IsDeveloperImage());
+
+ ASSERT_TRUE(
+ test_util::CreateFile(paths::GetAt(paths::kSystemRunStateDirectory,
+ paths::kCrashTestInProgress),
+ ""));
+ EXPECT_FALSE(IsDeveloperImage());
+}
+
+} // namespace util