Index: components/browser_watcher/postmortem_report_collector_unittest.cc |
diff --git a/components/browser_watcher/postmortem_report_collector_unittest.cc b/components/browser_watcher/postmortem_report_collector_unittest.cc |
index 791a6cb070b5a3a99c3cf418336a54bce639992c..bd615e6eb536bc8d20cb8e73ba0e8a731efd9c63 100644 |
--- a/components/browser_watcher/postmortem_report_collector_unittest.cc |
+++ b/components/browser_watcher/postmortem_report_collector_unittest.cc |
@@ -40,6 +40,7 @@ using base::debug::ActivityUserData; |
using base::debug::GlobalActivityTracker; |
using base::debug::ThreadActivityTracker; |
using base::File; |
+using base::FilePath; |
using base::FilePersistentMemoryAllocator; |
using base::MemoryMappedFile; |
using base::PersistentMemoryAllocator; |
@@ -54,6 +55,58 @@ using testing::SetArgPointee; |
namespace { |
+TEST(PostmortemDeleterTest, BasicTest) { |
+ base::HistogramTester histogram_tester; |
+ base::ScopedTempDir temp_dir; |
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
+ |
+ // Create three files. |
+ FilePath path_one = temp_dir.GetPath().AppendASCII("a.pma"); |
+ FilePath path_two = temp_dir.GetPath().AppendASCII("b.pma"); |
+ FilePath path_three = temp_dir.GetPath().AppendASCII("c.pma"); |
+ |
+ std::vector<FilePath> stability_files = {path_one, path_two, path_three}; |
+ |
+ for (const FilePath& path : stability_files) { |
+ { |
+ base::ScopedFILE file(base::OpenFile(path, "w")); |
+ ASSERT_NE(file.get(), nullptr); |
+ } |
+ ASSERT_TRUE(base::PathExists(path)); |
+ } |
+ |
+ // Open one stability file to prevent its deletion. |
+ base::ScopedFILE file(base::OpenFile(path_two, "w")); |
+ ASSERT_NE(file.get(), nullptr); |
+ |
+ // Validate deletion and metrics. |
+ PostmortemDeleter deleter; |
+ deleter.Process(stability_files); |
+ |
+ ASSERT_FALSE(base::PathExists(path_one)); |
+ ASSERT_FALSE(base::PathExists(path_three)); |
+ histogram_tester.ExpectBucketCount("ActivityTracker.Collect.Status", |
+ UNCLEAN_SHUTDOWN, 2); |
+ |
+ ASSERT_TRUE(base::PathExists(path_two)); |
+ histogram_tester.ExpectBucketCount("ActivityTracker.Collect.Status", |
+ DEBUG_FILE_DELETION_FAILED, 1); |
+ |
+ std::vector<CollectionStatus> unexpected_statuses = { |
+ NONE, |
+ SUCCESS, |
+ ANALYZER_CREATION_FAILED, |
+ DEBUG_FILE_NO_DATA, |
+ PREPARE_NEW_CRASH_REPORT_FAILED, |
+ WRITE_TO_MINIDUMP_FAILED, |
+ FINISHED_WRITING_CRASH_REPORT_FAILED, |
+ COLLECTION_ATTEMPT}; |
+ for (CollectionStatus status : unexpected_statuses) { |
+ histogram_tester.ExpectBucketCount("ActivityTracker.Collect.Status", status, |
+ 0); |
+ } |
+} |
+ |
const char kProductName[] = "TestProduct"; |
const char kVersionNumber[] = "TestVersionNumber"; |
const char kChannelName[] = "TestChannel"; |
@@ -113,23 +166,17 @@ class MockCrashReportDatabase : public CrashReportDatabase { |
CrashReportDatabase::OperationStatus(const UUID& uuid)); |
}; |
-// Used for testing CollectAndSubmitAllPendingReports. |
class MockPostmortemReportCollector : public PostmortemReportCollector { |
public: |
- MockPostmortemReportCollector() |
+ explicit MockPostmortemReportCollector(CrashReportDatabase* crash_database) |
: PostmortemReportCollector(kProductName, |
kVersionNumber, |
kChannelName, |
+ crash_database, |
nullptr) {} |
- MOCK_METHOD3(GetDebugStateFilePaths, |
- std::vector<base::FilePath>( |
- const base::FilePath& debug_info_dir, |
- const base::FilePath::StringType& debug_file_pattern, |
- const std::set<base::FilePath>&)); |
MOCK_METHOD2(CollectOneReport, |
- CollectionStatus(const base::FilePath&, |
- StabilityReport* report)); |
+ CollectionStatus(const FilePath&, StabilityReport* report)); |
MOCK_METHOD4(WriteReportToMinidump, |
bool(StabilityReport* report, |
const crashpad::UUID& client_id, |
@@ -164,10 +211,11 @@ MATCHER_P(EqualsProto, message, "") { |
} // namespace |
-class PostmortemReportCollectorCollectAndSubmitAllPendingReportsTest |
- : public testing::Test { |
+class PostmortemReportCollectorProcessTest : public testing::Test { |
public: |
- void SetUpTest(bool system_session_clean) { |
+ void SetUpTest(bool system_session_clean, bool expect_write_dump) { |
+ collector_.reset(new MockPostmortemReportCollector(&database_)); |
+ |
// Create a dummy debug file. |
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
debug_file_ = temp_dir_.GetPath().AppendASCII("foo-1.pma"); |
@@ -177,29 +225,23 @@ class PostmortemReportCollectorCollectAndSubmitAllPendingReportsTest |
} |
ASSERT_TRUE(base::PathExists(debug_file_)); |
- // Expect collection of the debug file paths. |
- debug_file_pattern_ = FILE_PATH_LITERAL("foo-*.pma"); |
- std::vector<base::FilePath> debug_files{debug_file_}; |
- EXPECT_CALL(collector_, |
- GetDebugStateFilePaths(debug_file_.DirName(), |
- debug_file_pattern_, no_excluded_files_)) |
- .Times(1) |
- .WillOnce(Return(debug_files)); |
- |
EXPECT_CALL(database_, GetSettings()).Times(1).WillOnce(Return(nullptr)); |
// Expect a single collection call. |
StabilityReport report; |
report.mutable_system_state()->set_session_state( |
system_session_clean ? SystemState::CLEAN : SystemState::UNCLEAN); |
- EXPECT_CALL(collector_, CollectOneReport(debug_file_, _)) |
+ EXPECT_CALL(*collector_, CollectOneReport(debug_file_, _)) |
.Times(1) |
.WillOnce(DoAll(SetArgPointee<1>(report), Return(SUCCESS))); |
+ if (!expect_write_dump) |
+ return; |
+ |
// Expect the call to write the proto to a minidump. This involves |
// requesting a report from the crashpad database, writing the report, then |
// finalizing it with the database. |
- base::FilePath minidump_path = temp_dir_.GetPath().AppendASCII("foo-1.dmp"); |
+ FilePath minidump_path = temp_dir_.GetPath().AppendASCII("foo-1.dmp"); |
base::File minidump_file( |
minidump_path, base::File::FLAG_CREATE | base::File::File::FLAG_WRITE); |
crashpad::UUID new_report_uuid; |
@@ -211,137 +253,79 @@ class PostmortemReportCollectorCollectAndSubmitAllPendingReportsTest |
.WillOnce(DoAll(SetArgPointee<0>(&crashpad_report_), |
Return(CrashReportDatabase::kNoError))); |
- EXPECT_CALL(collector_, |
+ EXPECT_CALL(*collector_, |
WriteReportToMinidump(_, _, _, minidump_file.GetPlatformFile())) |
.Times(1) |
.WillOnce(Return(true)); |
} |
void ValidateHistograms(int unclean_cnt, int unclean_system_cnt) { |
- histogram_tester_.ExpectTotalCount( |
- "ActivityTracker.Collect.StabilityFileCount", 1); |
- histogram_tester_.ExpectBucketCount( |
- "ActivityTracker.Collect.StabilityFileCount", 1, 1); |
- histogram_tester_.ExpectTotalCount( |
- "ActivityTracker.Collect.UncleanShutdownCount", 1); |
- histogram_tester_.ExpectBucketCount( |
- "ActivityTracker.Collect.UncleanShutdownCount", unclean_cnt, 1); |
- histogram_tester_.ExpectTotalCount( |
- "ActivityTracker.Collect.UncleanSystemCount", 1); |
- histogram_tester_.ExpectBucketCount( |
- "ActivityTracker.Collect.UncleanSystemCount", unclean_system_cnt, 1); |
+ histogram_tester_.ExpectBucketCount("ActivityTracker.Collect.Status", |
+ UNCLEAN_SHUTDOWN, unclean_cnt); |
+ histogram_tester_.ExpectBucketCount("ActivityTracker.Collect.Status", |
+ UNCLEAN_SESSION, unclean_system_cnt); |
} |
void CollectReports(bool is_session_clean) { |
- SetUpTest(is_session_clean); |
+ SetUpTest(is_session_clean, true); |
EXPECT_CALL(database_, FinishedWritingCrashReport(&crashpad_report_, _)) |
.Times(1) |
.WillOnce(Return(CrashReportDatabase::kNoError)); |
// Run the test. |
- int success_cnt = collector_.CollectAndSubmitAllPendingReports( |
- debug_file_.DirName(), debug_file_pattern_, no_excluded_files_, |
- &database_); |
- ASSERT_EQ(1, success_cnt); |
+ std::vector<FilePath> debug_files{debug_file_}; |
+ collector_->Process(debug_files); |
ASSERT_FALSE(base::PathExists(debug_file_)); |
} |
protected: |
base::HistogramTester histogram_tester_; |
base::ScopedTempDir temp_dir_; |
- base::FilePath debug_file_; |
+ FilePath debug_file_; |
MockCrashReportDatabase database_; |
- MockPostmortemReportCollector collector_; |
- base::FilePath::StringType debug_file_pattern_; |
- std::set<base::FilePath> no_excluded_files_; |
+ std::unique_ptr<MockPostmortemReportCollector> collector_; |
CrashReportDatabase::NewReport crashpad_report_; |
}; |
-TEST_F(PostmortemReportCollectorCollectAndSubmitAllPendingReportsTest, |
- CollectAndSubmitAllPendingReportsCleanSession) { |
+TEST_F(PostmortemReportCollectorProcessTest, ProcessCleanSession) { |
CollectReports(true); |
int expected_unclean = 1; |
int expected_system_unclean = 0; |
ValidateHistograms(expected_unclean, expected_system_unclean); |
} |
-TEST_F(PostmortemReportCollectorCollectAndSubmitAllPendingReportsTest, |
- CollectAndSubmitAllPendingReportsUncleanSession) { |
+TEST_F(PostmortemReportCollectorProcessTest, ProcessUncleanSession) { |
CollectReports(false); |
int expected_unclean = 1; |
int expected_system_unclean = 1; |
ValidateHistograms(expected_unclean, expected_system_unclean); |
} |
-TEST_F(PostmortemReportCollectorCollectAndSubmitAllPendingReportsTest, |
- CollectAndSubmitAllPendingReportsStuckFile) { |
- SetUpTest(true); |
+TEST_F(PostmortemReportCollectorProcessTest, ProcessStuckFile) { |
+ bool system_session_clean = true; |
+ bool expect_write_dump = false; |
+ SetUpTest(system_session_clean, expect_write_dump); |
// Open the stability debug file to prevent its deletion. |
base::ScopedFILE file(base::OpenFile(debug_file_, "w")); |
ASSERT_NE(file.get(), nullptr); |
- // Expect Crashpad is notified of an error writing the crash report. |
- EXPECT_CALL(database_, ErrorWritingCrashReport(&crashpad_report_)) |
- .Times(1) |
- .WillOnce(Return(CrashReportDatabase::kNoError)); |
- |
// Run the test. |
- int success_cnt = collector_.CollectAndSubmitAllPendingReports( |
- debug_file_.DirName(), debug_file_pattern_, no_excluded_files_, |
- &database_); |
- ASSERT_EQ(0, success_cnt); |
+ std::vector<FilePath> debug_files{debug_file_}; |
+ collector_->Process(debug_files); |
ASSERT_TRUE(base::PathExists(debug_file_)); |
+ histogram_tester_.ExpectBucketCount("ActivityTracker.Collect.Status", |
+ DEBUG_FILE_DELETION_FAILED, 1); |
int expected_unclean = 0; |
int expected_system_unclean = 0; |
ValidateHistograms(expected_unclean, expected_system_unclean); |
} |
-TEST(PostmortemReportCollectorTest, GetDebugStateFilePaths) { |
- base::ScopedTempDir temp_dir; |
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
- |
- // Create files. |
- std::vector<base::FilePath> expected_paths; |
- std::set<base::FilePath> excluded_paths; |
- { |
- // Matches the pattern. |
- base::FilePath path = temp_dir.GetPath().AppendASCII("foo1.pma"); |
- base::ScopedFILE file(base::OpenFile(path, "w")); |
- ASSERT_NE(file.get(), nullptr); |
- expected_paths.push_back(path); |
- |
- // Matches the pattern, but is excluded. |
- path = temp_dir.GetPath().AppendASCII("foo2.pma"); |
- file.reset(base::OpenFile(path, "w")); |
- ASSERT_NE(file.get(), nullptr); |
- ASSERT_TRUE(excluded_paths.insert(path).second); |
- |
- // Matches the pattern. |
- path = temp_dir.GetPath().AppendASCII("foo3.pma"); |
- file.reset(base::OpenFile(path, "w")); |
- ASSERT_NE(file.get(), nullptr); |
- expected_paths.push_back(path); |
- |
- // Does not match the pattern. |
- path = temp_dir.GetPath().AppendASCII("bar.baz"); |
- file.reset(base::OpenFile(path, "w")); |
- ASSERT_NE(file.get(), nullptr); |
- } |
- |
- PostmortemReportCollector collector(kProductName, kVersionNumber, |
- kChannelName, nullptr); |
- EXPECT_THAT( |
- collector.GetDebugStateFilePaths( |
- temp_dir.GetPath(), FILE_PATH_LITERAL("foo*.pma"), excluded_paths), |
- testing::UnorderedElementsAreArray(expected_paths)); |
-} |
- |
TEST(PostmortemReportCollectorTest, CollectEmptyFile) { |
// Create an empty file. |
base::ScopedTempDir temp_dir; |
ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
- base::FilePath file_path = temp_dir.GetPath().AppendASCII("empty.pma"); |
+ FilePath file_path = temp_dir.GetPath().AppendASCII("empty.pma"); |
{ |
base::ScopedFILE file(base::OpenFile(file_path, "w")); |
ASSERT_NE(file.get(), nullptr); |
@@ -349,8 +333,9 @@ TEST(PostmortemReportCollectorTest, CollectEmptyFile) { |
ASSERT_TRUE(PathExists(file_path)); |
// Validate collection: an empty file cannot suppport an analyzer. |
+ MockCrashReportDatabase crash_db; |
PostmortemReportCollector collector(kProductName, kVersionNumber, |
- kChannelName, nullptr); |
+ kChannelName, &crash_db, nullptr); |
StabilityReport report; |
ASSERT_EQ(ANALYZER_CREATION_FAILED, |
collector.CollectOneReport(file_path, &report)); |
@@ -360,8 +345,7 @@ TEST(PostmortemReportCollectorTest, CollectRandomFile) { |
// Create a file with content we don't expect to be valid for a debug file. |
base::ScopedTempDir temp_dir; |
ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
- base::FilePath file_path = |
- temp_dir.GetPath().AppendASCII("invalid_content.pma"); |
+ FilePath file_path = temp_dir.GetPath().AppendASCII("invalid_content.pma"); |
{ |
base::ScopedFILE file(base::OpenFile(file_path, "w")); |
ASSERT_NE(file.get(), nullptr); |
@@ -376,8 +360,9 @@ TEST(PostmortemReportCollectorTest, CollectRandomFile) { |
// Validate collection: random content appears as though there is not |
// stability data. |
+ MockCrashReportDatabase crash_db; |
PostmortemReportCollector collector(kProductName, kVersionNumber, |
- kChannelName, nullptr); |
+ kChannelName, &crash_db, nullptr); |
StabilityReport report; |
ASSERT_NE(SUCCESS, collector.CollectOneReport(file_path, &report)); |
} |
@@ -466,11 +451,11 @@ class PostmortemReportCollectorCollectionTest : public testing::Test { |
return WrapUnique(new ThreadActivityTracker(mem_base, tracker_mem_size)); |
} |
- const base::FilePath& debug_file_path() const { return debug_file_path_; } |
+ const FilePath& debug_file_path() const { return debug_file_path_; } |
protected: |
base::ScopedTempDir temp_dir_; |
- base::FilePath debug_file_path_; |
+ FilePath debug_file_path_; |
std::unique_ptr<PersistentMemoryAllocator> allocator_; |
std::unique_ptr<ThreadActivityTracker> tracker_; |
@@ -506,8 +491,9 @@ TEST_F(PostmortemReportCollectorCollectionTest, CollectSuccess) { |
user_data->SetInt("some_int", 42); |
// Validate collection returns the expected report. |
+ MockCrashReportDatabase crash_db; |
PostmortemReportCollector collector(kProductName, kVersionNumber, |
- kChannelName, nullptr); |
+ kChannelName, &crash_db, nullptr); |
StabilityReport report; |
ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); |
@@ -594,11 +580,11 @@ class PostmortemReportCollectorCollectionFromGlobalTrackerTest |
debug_file_path_ = temp_dir_.GetPath().AppendASCII("debug.pma"); |
} |
- const base::FilePath& debug_file_path() { return debug_file_path_; } |
+ const FilePath& debug_file_path() { return debug_file_path_; } |
protected: |
base::ScopedTempDir temp_dir_; |
- base::FilePath debug_file_path_; |
+ FilePath debug_file_path_; |
}; |
TEST_F(PostmortemReportCollectorCollectionFromGlobalTrackerTest, |
@@ -610,8 +596,9 @@ TEST_F(PostmortemReportCollectorCollectionFromGlobalTrackerTest, |
GlobalActivityTracker::Get()->RecordLogMessage("foo bar"); |
// Collect the stability report. |
+ MockCrashReportDatabase crash_db; |
PostmortemReportCollector collector(kProductName, kVersionNumber, |
- kChannelName, nullptr); |
+ kChannelName, &crash_db, nullptr); |
StabilityReport report; |
ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); |
@@ -643,8 +630,9 @@ TEST_F(PostmortemReportCollectorCollectionFromGlobalTrackerTest, |
process_data.SetStringReference("sref", string2); |
// Collect the stability report. |
+ MockCrashReportDatabase crash_db; |
PostmortemReportCollector collector(kProductName, kVersionNumber, |
- kChannelName, nullptr); |
+ kChannelName, &crash_db, nullptr); |
StabilityReport report; |
ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); |
@@ -712,8 +700,9 @@ TEST_F(PostmortemReportCollectorCollectionFromGlobalTrackerTest, |
process_data.SetString("FieldTrial.foo", "bar"); |
// Collect the stability report. |
+ MockCrashReportDatabase crash_db; |
PostmortemReportCollector collector(kProductName, kVersionNumber, |
- kChannelName, nullptr); |
+ kChannelName, &crash_db, nullptr); |
StabilityReport report; |
ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); |
@@ -753,8 +742,9 @@ TEST_F(PostmortemReportCollectorCollectionFromGlobalTrackerTest, |
GlobalActivityTracker::Get()->RecordModuleInfo(module_info); |
// Collect the stability report. |
+ MockCrashReportDatabase crash_db; |
PostmortemReportCollector collector(kProductName, kVersionNumber, |
- kChannelName, nullptr); |
+ kChannelName, &crash_db, nullptr); |
StabilityReport report; |
ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); |
@@ -791,8 +781,9 @@ TEST_F(PostmortemReportCollectorCollectionFromGlobalTrackerTest, |
IsSessionUnclean(base::Time::FromInternalValue(12345LL))) |
.Times(1) |
.WillOnce(Return(SystemSessionAnalyzer::CLEAN)); |
+ MockCrashReportDatabase crash_db; |
PostmortemReportCollector collector(kProductName, kVersionNumber, |
- kChannelName, &analyzer); |
+ kChannelName, &crash_db, &analyzer); |
StabilityReport report; |
ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); |