OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/browser_watcher/postmortem_report_collector.h" | 5 #include "components/browser_watcher/postmortem_report_collector.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <memory> | 9 #include <memory> |
10 #include <set> | 10 #include <set> |
(...skipping 22 matching lines...) Expand all Loading... | |
33 #include "third_party/crashpad/crashpad/client/crash_report_database.h" | 33 #include "third_party/crashpad/crashpad/client/crash_report_database.h" |
34 | 34 |
35 namespace browser_watcher { | 35 namespace browser_watcher { |
36 | 36 |
37 using base::debug::ActivityData; | 37 using base::debug::ActivityData; |
38 using base::debug::ActivityTrackerMemoryAllocator; | 38 using base::debug::ActivityTrackerMemoryAllocator; |
39 using base::debug::ActivityUserData; | 39 using base::debug::ActivityUserData; |
40 using base::debug::GlobalActivityTracker; | 40 using base::debug::GlobalActivityTracker; |
41 using base::debug::ThreadActivityTracker; | 41 using base::debug::ThreadActivityTracker; |
42 using base::File; | 42 using base::File; |
43 using base::FilePath; | |
43 using base::FilePersistentMemoryAllocator; | 44 using base::FilePersistentMemoryAllocator; |
44 using base::MemoryMappedFile; | 45 using base::MemoryMappedFile; |
45 using base::PersistentMemoryAllocator; | 46 using base::PersistentMemoryAllocator; |
46 using base::WrapUnique; | 47 using base::WrapUnique; |
47 using crashpad::CrashReportDatabase; | 48 using crashpad::CrashReportDatabase; |
48 using crashpad::Settings; | 49 using crashpad::Settings; |
49 using crashpad::UUID; | 50 using crashpad::UUID; |
50 using testing::_; | 51 using testing::_; |
51 using testing::DoAll; | 52 using testing::DoAll; |
52 using testing::Return; | 53 using testing::Return; |
53 using testing::SetArgPointee; | 54 using testing::SetArgPointee; |
54 | 55 |
55 namespace { | 56 namespace { |
56 | 57 |
58 TEST(PostmortemDeleterTest, BasicTest) { | |
59 base::HistogramTester histogram_tester; | |
60 base::ScopedTempDir temp_dir; | |
61 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | |
62 | |
63 // Create three files. | |
64 FilePath path_one = temp_dir.GetPath().AppendASCII("a.pma"); | |
65 FilePath path_two = temp_dir.GetPath().AppendASCII("b.pma"); | |
66 FilePath path_three = temp_dir.GetPath().AppendASCII("c.pma"); | |
67 | |
68 std::vector<FilePath> stability_files = {path_one, path_two, path_three}; | |
69 | |
70 for (const FilePath& path : stability_files) { | |
71 { | |
72 base::ScopedFILE file(base::OpenFile(path, "w")); | |
73 ASSERT_NE(file.get(), nullptr); | |
74 } | |
75 ASSERT_TRUE(base::PathExists(path)); | |
76 } | |
77 | |
78 // Open one stability file to prevent its deletion. | |
79 base::ScopedFILE file(base::OpenFile(path_two, "w")); | |
80 ASSERT_NE(file.get(), nullptr); | |
81 | |
82 // Validate deletion and metrics. | |
83 PostmortemDeleter deleter; | |
84 deleter.Process(stability_files); | |
85 | |
86 ASSERT_FALSE(base::PathExists(path_one)); | |
87 ASSERT_FALSE(base::PathExists(path_three)); | |
88 histogram_tester.ExpectBucketCount("ActivityTracker.Collect.Status", | |
89 UNCLEAN_SHUTDOWN, 2); | |
90 | |
91 ASSERT_TRUE(base::PathExists(path_two)); | |
92 histogram_tester.ExpectBucketCount("ActivityTracker.Collect.Status", | |
93 DEBUG_FILE_DELETION_FAILED, 1); | |
Sigurður Ásgeirsson
2017/06/05 15:39:39
nice. Stupid question, though - wouldn't the Postm
manzagop (departed)
2017/06/05 18:02:16
Done.
| |
94 } | |
95 | |
57 const char kProductName[] = "TestProduct"; | 96 const char kProductName[] = "TestProduct"; |
58 const char kVersionNumber[] = "TestVersionNumber"; | 97 const char kVersionNumber[] = "TestVersionNumber"; |
59 const char kChannelName[] = "TestChannel"; | 98 const char kChannelName[] = "TestChannel"; |
60 | 99 |
61 // The tracker creates some data entries internally. | 100 // The tracker creates some data entries internally. |
62 const size_t kInternalProcessDatums = 1; | 101 const size_t kInternalProcessDatums = 1; |
63 | 102 |
64 void ContainsKeyValue( | 103 void ContainsKeyValue( |
65 const google::protobuf::Map<std::string, TypedValue>& data, | 104 const google::protobuf::Map<std::string, TypedValue>& data, |
66 const std::string& key, | 105 const std::string& key, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
106 MOCK_METHOD2(SkipReportUpload, | 145 MOCK_METHOD2(SkipReportUpload, |
107 CrashReportDatabase::OperationStatus( | 146 CrashReportDatabase::OperationStatus( |
108 const UUID& uuid, | 147 const UUID& uuid, |
109 crashpad::Metrics::CrashSkippedReason reason)); | 148 crashpad::Metrics::CrashSkippedReason reason)); |
110 MOCK_METHOD1(DeleteReport, | 149 MOCK_METHOD1(DeleteReport, |
111 CrashReportDatabase::OperationStatus(const UUID& uuid)); | 150 CrashReportDatabase::OperationStatus(const UUID& uuid)); |
112 MOCK_METHOD1(RequestUpload, | 151 MOCK_METHOD1(RequestUpload, |
113 CrashReportDatabase::OperationStatus(const UUID& uuid)); | 152 CrashReportDatabase::OperationStatus(const UUID& uuid)); |
114 }; | 153 }; |
115 | 154 |
116 // Used for testing CollectAndSubmitAllPendingReports. | |
117 class MockPostmortemReportCollector : public PostmortemReportCollector { | 155 class MockPostmortemReportCollector : public PostmortemReportCollector { |
118 public: | 156 public: |
119 MockPostmortemReportCollector() | 157 explicit MockPostmortemReportCollector(CrashReportDatabase* crash_database) |
120 : PostmortemReportCollector(kProductName, | 158 : PostmortemReportCollector(kProductName, |
121 kVersionNumber, | 159 kVersionNumber, |
122 kChannelName, | 160 kChannelName, |
161 crash_database, | |
123 nullptr) {} | 162 nullptr) {} |
124 | 163 |
125 MOCK_METHOD3(GetDebugStateFilePaths, | |
126 std::vector<base::FilePath>( | |
127 const base::FilePath& debug_info_dir, | |
128 const base::FilePath::StringType& debug_file_pattern, | |
129 const std::set<base::FilePath>&)); | |
130 MOCK_METHOD2(CollectOneReport, | 164 MOCK_METHOD2(CollectOneReport, |
131 CollectionStatus(const base::FilePath&, | 165 CollectionStatus(const FilePath&, StabilityReport* report)); |
132 StabilityReport* report)); | |
133 MOCK_METHOD4(WriteReportToMinidump, | 166 MOCK_METHOD4(WriteReportToMinidump, |
134 bool(StabilityReport* report, | 167 bool(StabilityReport* report, |
135 const crashpad::UUID& client_id, | 168 const crashpad::UUID& client_id, |
136 const crashpad::UUID& report_id, | 169 const crashpad::UUID& report_id, |
137 base::PlatformFile minidump_file)); | 170 base::PlatformFile minidump_file)); |
138 }; | 171 }; |
139 | 172 |
140 class MockSystemSessionAnalyzer : public SystemSessionAnalyzer { | 173 class MockSystemSessionAnalyzer : public SystemSessionAnalyzer { |
141 public: | 174 public: |
142 MockSystemSessionAnalyzer() : SystemSessionAnalyzer(10U) {} | 175 MockSystemSessionAnalyzer() : SystemSessionAnalyzer(10U) {} |
(...skipping 14 matching lines...) Expand all Loading... | |
157 MATCHER_P(EqualsProto, message, "") { | 190 MATCHER_P(EqualsProto, message, "") { |
158 std::string expected_serialized; | 191 std::string expected_serialized; |
159 std::string actual_serialized; | 192 std::string actual_serialized; |
160 message.SerializeToString(&expected_serialized); | 193 message.SerializeToString(&expected_serialized); |
161 arg.SerializeToString(&actual_serialized); | 194 arg.SerializeToString(&actual_serialized); |
162 return expected_serialized == actual_serialized; | 195 return expected_serialized == actual_serialized; |
163 } | 196 } |
164 | 197 |
165 } // namespace | 198 } // namespace |
166 | 199 |
167 class PostmortemReportCollectorCollectAndSubmitAllPendingReportsTest | 200 class PostmortemReportCollectorProcessTest : public testing::Test { |
168 : public testing::Test { | |
169 public: | 201 public: |
170 void SetUpTest(bool system_session_clean) { | 202 void SetUpTest(bool system_session_clean, bool expect_write_dump) { |
203 collector_.reset(new MockPostmortemReportCollector(&database_)); | |
204 | |
171 // Create a dummy debug file. | 205 // Create a dummy debug file. |
172 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | 206 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
173 debug_file_ = temp_dir_.GetPath().AppendASCII("foo-1.pma"); | 207 debug_file_ = temp_dir_.GetPath().AppendASCII("foo-1.pma"); |
174 { | 208 { |
175 base::ScopedFILE file(base::OpenFile(debug_file_, "w")); | 209 base::ScopedFILE file(base::OpenFile(debug_file_, "w")); |
176 ASSERT_NE(file.get(), nullptr); | 210 ASSERT_NE(file.get(), nullptr); |
177 } | 211 } |
178 ASSERT_TRUE(base::PathExists(debug_file_)); | 212 ASSERT_TRUE(base::PathExists(debug_file_)); |
179 | 213 |
180 // Expect collection of the debug file paths. | |
181 debug_file_pattern_ = FILE_PATH_LITERAL("foo-*.pma"); | |
182 std::vector<base::FilePath> debug_files{debug_file_}; | |
183 EXPECT_CALL(collector_, | |
184 GetDebugStateFilePaths(debug_file_.DirName(), | |
185 debug_file_pattern_, no_excluded_files_)) | |
186 .Times(1) | |
187 .WillOnce(Return(debug_files)); | |
188 | |
189 EXPECT_CALL(database_, GetSettings()).Times(1).WillOnce(Return(nullptr)); | 214 EXPECT_CALL(database_, GetSettings()).Times(1).WillOnce(Return(nullptr)); |
190 | 215 |
191 // Expect a single collection call. | 216 // Expect a single collection call. |
192 StabilityReport report; | 217 StabilityReport report; |
193 report.mutable_system_state()->set_session_state( | 218 report.mutable_system_state()->set_session_state( |
194 system_session_clean ? SystemState::CLEAN : SystemState::UNCLEAN); | 219 system_session_clean ? SystemState::CLEAN : SystemState::UNCLEAN); |
195 EXPECT_CALL(collector_, CollectOneReport(debug_file_, _)) | 220 EXPECT_CALL(*collector_, CollectOneReport(debug_file_, _)) |
196 .Times(1) | 221 .Times(1) |
197 .WillOnce(DoAll(SetArgPointee<1>(report), Return(SUCCESS))); | 222 .WillOnce(DoAll(SetArgPointee<1>(report), Return(SUCCESS))); |
198 | 223 |
224 if (!expect_write_dump) | |
225 return; | |
226 | |
199 // Expect the call to write the proto to a minidump. This involves | 227 // Expect the call to write the proto to a minidump. This involves |
200 // requesting a report from the crashpad database, writing the report, then | 228 // requesting a report from the crashpad database, writing the report, then |
201 // finalizing it with the database. | 229 // finalizing it with the database. |
202 base::FilePath minidump_path = temp_dir_.GetPath().AppendASCII("foo-1.dmp"); | 230 FilePath minidump_path = temp_dir_.GetPath().AppendASCII("foo-1.dmp"); |
203 base::File minidump_file( | 231 base::File minidump_file( |
204 minidump_path, base::File::FLAG_CREATE | base::File::File::FLAG_WRITE); | 232 minidump_path, base::File::FLAG_CREATE | base::File::File::FLAG_WRITE); |
205 crashpad::UUID new_report_uuid; | 233 crashpad::UUID new_report_uuid; |
206 new_report_uuid.InitializeWithNew(); | 234 new_report_uuid.InitializeWithNew(); |
207 crashpad_report_ = {minidump_file.GetPlatformFile(), new_report_uuid, | 235 crashpad_report_ = {minidump_file.GetPlatformFile(), new_report_uuid, |
208 minidump_path}; | 236 minidump_path}; |
209 EXPECT_CALL(database_, PrepareNewCrashReport(_)) | 237 EXPECT_CALL(database_, PrepareNewCrashReport(_)) |
210 .Times(1) | 238 .Times(1) |
211 .WillOnce(DoAll(SetArgPointee<0>(&crashpad_report_), | 239 .WillOnce(DoAll(SetArgPointee<0>(&crashpad_report_), |
212 Return(CrashReportDatabase::kNoError))); | 240 Return(CrashReportDatabase::kNoError))); |
213 | 241 |
214 EXPECT_CALL(collector_, | 242 EXPECT_CALL(*collector_, |
215 WriteReportToMinidump(_, _, _, minidump_file.GetPlatformFile())) | 243 WriteReportToMinidump(_, _, _, minidump_file.GetPlatformFile())) |
216 .Times(1) | 244 .Times(1) |
217 .WillOnce(Return(true)); | 245 .WillOnce(Return(true)); |
218 } | 246 } |
219 void ValidateHistograms(int unclean_cnt, int unclean_system_cnt) { | 247 void ValidateHistograms(int unclean_cnt, int unclean_system_cnt) { |
220 histogram_tester_.ExpectTotalCount( | 248 histogram_tester_.ExpectBucketCount("ActivityTracker.Collect.Status", |
221 "ActivityTracker.Collect.StabilityFileCount", 1); | 249 UNCLEAN_SHUTDOWN, unclean_cnt); |
222 histogram_tester_.ExpectBucketCount( | 250 histogram_tester_.ExpectBucketCount("ActivityTracker.Collect.Status", |
223 "ActivityTracker.Collect.StabilityFileCount", 1, 1); | 251 UNCLEAN_SESSION, unclean_system_cnt); |
224 histogram_tester_.ExpectTotalCount( | |
225 "ActivityTracker.Collect.UncleanShutdownCount", 1); | |
226 histogram_tester_.ExpectBucketCount( | |
227 "ActivityTracker.Collect.UncleanShutdownCount", unclean_cnt, 1); | |
228 histogram_tester_.ExpectTotalCount( | |
229 "ActivityTracker.Collect.UncleanSystemCount", 1); | |
230 histogram_tester_.ExpectBucketCount( | |
231 "ActivityTracker.Collect.UncleanSystemCount", unclean_system_cnt, 1); | |
232 } | 252 } |
233 void CollectReports(bool is_session_clean) { | 253 void CollectReports(bool is_session_clean) { |
234 SetUpTest(is_session_clean); | 254 SetUpTest(is_session_clean, true); |
235 | 255 |
236 EXPECT_CALL(database_, FinishedWritingCrashReport(&crashpad_report_, _)) | 256 EXPECT_CALL(database_, FinishedWritingCrashReport(&crashpad_report_, _)) |
237 .Times(1) | 257 .Times(1) |
238 .WillOnce(Return(CrashReportDatabase::kNoError)); | 258 .WillOnce(Return(CrashReportDatabase::kNoError)); |
239 | 259 |
240 // Run the test. | 260 // Run the test. |
241 int success_cnt = collector_.CollectAndSubmitAllPendingReports( | 261 std::vector<FilePath> debug_files{debug_file_}; |
242 debug_file_.DirName(), debug_file_pattern_, no_excluded_files_, | 262 collector_->Process(debug_files); |
243 &database_); | |
244 ASSERT_EQ(1, success_cnt); | |
245 ASSERT_FALSE(base::PathExists(debug_file_)); | 263 ASSERT_FALSE(base::PathExists(debug_file_)); |
246 } | 264 } |
247 | 265 |
248 protected: | 266 protected: |
249 base::HistogramTester histogram_tester_; | 267 base::HistogramTester histogram_tester_; |
250 base::ScopedTempDir temp_dir_; | 268 base::ScopedTempDir temp_dir_; |
251 base::FilePath debug_file_; | 269 FilePath debug_file_; |
252 MockCrashReportDatabase database_; | 270 MockCrashReportDatabase database_; |
253 MockPostmortemReportCollector collector_; | 271 std::unique_ptr<MockPostmortemReportCollector> collector_; |
254 base::FilePath::StringType debug_file_pattern_; | |
255 std::set<base::FilePath> no_excluded_files_; | |
256 CrashReportDatabase::NewReport crashpad_report_; | 272 CrashReportDatabase::NewReport crashpad_report_; |
257 }; | 273 }; |
258 | 274 |
259 TEST_F(PostmortemReportCollectorCollectAndSubmitAllPendingReportsTest, | 275 TEST_F(PostmortemReportCollectorProcessTest, ProcessCleanSession) { |
260 CollectAndSubmitAllPendingReportsCleanSession) { | |
261 CollectReports(true); | 276 CollectReports(true); |
262 int expected_unclean = 1; | 277 int expected_unclean = 1; |
263 int expected_system_unclean = 0; | 278 int expected_system_unclean = 0; |
264 ValidateHistograms(expected_unclean, expected_system_unclean); | 279 ValidateHistograms(expected_unclean, expected_system_unclean); |
265 } | 280 } |
266 | 281 |
267 TEST_F(PostmortemReportCollectorCollectAndSubmitAllPendingReportsTest, | 282 TEST_F(PostmortemReportCollectorProcessTest, ProcessUncleanSession) { |
268 CollectAndSubmitAllPendingReportsUncleanSession) { | |
269 CollectReports(false); | 283 CollectReports(false); |
270 int expected_unclean = 1; | 284 int expected_unclean = 1; |
271 int expected_system_unclean = 1; | 285 int expected_system_unclean = 1; |
272 ValidateHistograms(expected_unclean, expected_system_unclean); | 286 ValidateHistograms(expected_unclean, expected_system_unclean); |
273 } | 287 } |
274 | 288 |
275 TEST_F(PostmortemReportCollectorCollectAndSubmitAllPendingReportsTest, | 289 TEST_F(PostmortemReportCollectorProcessTest, ProcessStuckFile) { |
276 CollectAndSubmitAllPendingReportsStuckFile) { | 290 bool system_session_clean = true; |
277 SetUpTest(true); | 291 bool expect_write_dump = false; |
292 SetUpTest(system_session_clean, expect_write_dump); | |
278 | 293 |
279 // Open the stability debug file to prevent its deletion. | 294 // Open the stability debug file to prevent its deletion. |
280 base::ScopedFILE file(base::OpenFile(debug_file_, "w")); | 295 base::ScopedFILE file(base::OpenFile(debug_file_, "w")); |
281 ASSERT_NE(file.get(), nullptr); | 296 ASSERT_NE(file.get(), nullptr); |
282 | 297 |
283 // Expect Crashpad is notified of an error writing the crash report. | |
284 EXPECT_CALL(database_, ErrorWritingCrashReport(&crashpad_report_)) | |
285 .Times(1) | |
286 .WillOnce(Return(CrashReportDatabase::kNoError)); | |
287 | |
288 // Run the test. | 298 // Run the test. |
289 int success_cnt = collector_.CollectAndSubmitAllPendingReports( | 299 std::vector<FilePath> debug_files{debug_file_}; |
290 debug_file_.DirName(), debug_file_pattern_, no_excluded_files_, | 300 collector_->Process(debug_files); |
291 &database_); | |
292 ASSERT_EQ(0, success_cnt); | |
293 ASSERT_TRUE(base::PathExists(debug_file_)); | 301 ASSERT_TRUE(base::PathExists(debug_file_)); |
294 | 302 |
303 histogram_tester_.ExpectBucketCount("ActivityTracker.Collect.Status", | |
304 DEBUG_FILE_DELETION_FAILED, 1); | |
295 int expected_unclean = 0; | 305 int expected_unclean = 0; |
296 int expected_system_unclean = 0; | 306 int expected_system_unclean = 0; |
297 ValidateHistograms(expected_unclean, expected_system_unclean); | 307 ValidateHistograms(expected_unclean, expected_system_unclean); |
298 } | 308 } |
299 | 309 |
300 TEST(PostmortemReportCollectorTest, GetDebugStateFilePaths) { | |
301 base::ScopedTempDir temp_dir; | |
302 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | |
303 | |
304 // Create files. | |
305 std::vector<base::FilePath> expected_paths; | |
306 std::set<base::FilePath> excluded_paths; | |
307 { | |
308 // Matches the pattern. | |
309 base::FilePath path = temp_dir.GetPath().AppendASCII("foo1.pma"); | |
310 base::ScopedFILE file(base::OpenFile(path, "w")); | |
311 ASSERT_NE(file.get(), nullptr); | |
312 expected_paths.push_back(path); | |
313 | |
314 // Matches the pattern, but is excluded. | |
315 path = temp_dir.GetPath().AppendASCII("foo2.pma"); | |
316 file.reset(base::OpenFile(path, "w")); | |
317 ASSERT_NE(file.get(), nullptr); | |
318 ASSERT_TRUE(excluded_paths.insert(path).second); | |
319 | |
320 // Matches the pattern. | |
321 path = temp_dir.GetPath().AppendASCII("foo3.pma"); | |
322 file.reset(base::OpenFile(path, "w")); | |
323 ASSERT_NE(file.get(), nullptr); | |
324 expected_paths.push_back(path); | |
325 | |
326 // Does not match the pattern. | |
327 path = temp_dir.GetPath().AppendASCII("bar.baz"); | |
328 file.reset(base::OpenFile(path, "w")); | |
329 ASSERT_NE(file.get(), nullptr); | |
330 } | |
331 | |
332 PostmortemReportCollector collector(kProductName, kVersionNumber, | |
333 kChannelName, nullptr); | |
334 EXPECT_THAT( | |
335 collector.GetDebugStateFilePaths( | |
336 temp_dir.GetPath(), FILE_PATH_LITERAL("foo*.pma"), excluded_paths), | |
337 testing::UnorderedElementsAreArray(expected_paths)); | |
338 } | |
339 | |
340 TEST(PostmortemReportCollectorTest, CollectEmptyFile) { | 310 TEST(PostmortemReportCollectorTest, CollectEmptyFile) { |
341 // Create an empty file. | 311 // Create an empty file. |
342 base::ScopedTempDir temp_dir; | 312 base::ScopedTempDir temp_dir; |
343 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 313 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
344 base::FilePath file_path = temp_dir.GetPath().AppendASCII("empty.pma"); | 314 FilePath file_path = temp_dir.GetPath().AppendASCII("empty.pma"); |
345 { | 315 { |
346 base::ScopedFILE file(base::OpenFile(file_path, "w")); | 316 base::ScopedFILE file(base::OpenFile(file_path, "w")); |
347 ASSERT_NE(file.get(), nullptr); | 317 ASSERT_NE(file.get(), nullptr); |
348 } | 318 } |
349 ASSERT_TRUE(PathExists(file_path)); | 319 ASSERT_TRUE(PathExists(file_path)); |
350 | 320 |
351 // Validate collection: an empty file cannot suppport an analyzer. | 321 // Validate collection: an empty file cannot suppport an analyzer. |
322 MockCrashReportDatabase crash_db; | |
352 PostmortemReportCollector collector(kProductName, kVersionNumber, | 323 PostmortemReportCollector collector(kProductName, kVersionNumber, |
353 kChannelName, nullptr); | 324 kChannelName, &crash_db, nullptr); |
354 StabilityReport report; | 325 StabilityReport report; |
355 ASSERT_EQ(ANALYZER_CREATION_FAILED, | 326 ASSERT_EQ(ANALYZER_CREATION_FAILED, |
356 collector.CollectOneReport(file_path, &report)); | 327 collector.CollectOneReport(file_path, &report)); |
357 } | 328 } |
358 | 329 |
359 TEST(PostmortemReportCollectorTest, CollectRandomFile) { | 330 TEST(PostmortemReportCollectorTest, CollectRandomFile) { |
360 // Create a file with content we don't expect to be valid for a debug file. | 331 // Create a file with content we don't expect to be valid for a debug file. |
361 base::ScopedTempDir temp_dir; | 332 base::ScopedTempDir temp_dir; |
362 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 333 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
363 base::FilePath file_path = | 334 FilePath file_path = temp_dir.GetPath().AppendASCII("invalid_content.pma"); |
364 temp_dir.GetPath().AppendASCII("invalid_content.pma"); | |
365 { | 335 { |
366 base::ScopedFILE file(base::OpenFile(file_path, "w")); | 336 base::ScopedFILE file(base::OpenFile(file_path, "w")); |
367 ASSERT_NE(file.get(), nullptr); | 337 ASSERT_NE(file.get(), nullptr); |
368 // Assuming this size is greater than the minimum size of a debug file. | 338 // Assuming this size is greater than the minimum size of a debug file. |
369 std::vector<uint8_t> data(1024); | 339 std::vector<uint8_t> data(1024); |
370 for (size_t i = 0; i < data.size(); ++i) | 340 for (size_t i = 0; i < data.size(); ++i) |
371 data[i] = i % UINT8_MAX; | 341 data[i] = i % UINT8_MAX; |
372 ASSERT_EQ(data.size(), | 342 ASSERT_EQ(data.size(), |
373 fwrite(&data.at(0), sizeof(uint8_t), data.size(), file.get())); | 343 fwrite(&data.at(0), sizeof(uint8_t), data.size(), file.get())); |
374 } | 344 } |
375 ASSERT_TRUE(PathExists(file_path)); | 345 ASSERT_TRUE(PathExists(file_path)); |
376 | 346 |
377 // Validate collection: random content appears as though there is not | 347 // Validate collection: random content appears as though there is not |
378 // stability data. | 348 // stability data. |
349 MockCrashReportDatabase crash_db; | |
379 PostmortemReportCollector collector(kProductName, kVersionNumber, | 350 PostmortemReportCollector collector(kProductName, kVersionNumber, |
380 kChannelName, nullptr); | 351 kChannelName, &crash_db, nullptr); |
381 StabilityReport report; | 352 StabilityReport report; |
382 ASSERT_NE(SUCCESS, collector.CollectOneReport(file_path, &report)); | 353 ASSERT_NE(SUCCESS, collector.CollectOneReport(file_path, &report)); |
383 } | 354 } |
384 | 355 |
385 namespace { | 356 namespace { |
386 | 357 |
387 // Parameters for the activity tracking. | 358 // Parameters for the activity tracking. |
388 const size_t kFileSize = 64 << 10; // 64 KiB | 359 const size_t kFileSize = 64 << 10; // 64 KiB |
389 const int kStackDepth = 6; | 360 const int kStackDepth = 6; |
390 const uint64_t kAllocatorId = 0; | 361 const uint64_t kAllocatorId = 0; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
459 PersistentMemoryAllocator::kSizeAny); | 430 PersistentMemoryAllocator::kSizeAny); |
460 if (mem_base == nullptr) | 431 if (mem_base == nullptr) |
461 return nullptr; | 432 return nullptr; |
462 | 433 |
463 // Make the allocation iterable so it can be found by other processes. | 434 // Make the allocation iterable so it can be found by other processes. |
464 allocator->MakeIterable(mem_reference); | 435 allocator->MakeIterable(mem_reference); |
465 | 436 |
466 return WrapUnique(new ThreadActivityTracker(mem_base, tracker_mem_size)); | 437 return WrapUnique(new ThreadActivityTracker(mem_base, tracker_mem_size)); |
467 } | 438 } |
468 | 439 |
469 const base::FilePath& debug_file_path() const { return debug_file_path_; } | 440 const FilePath& debug_file_path() const { return debug_file_path_; } |
470 | 441 |
471 protected: | 442 protected: |
472 base::ScopedTempDir temp_dir_; | 443 base::ScopedTempDir temp_dir_; |
473 base::FilePath debug_file_path_; | 444 FilePath debug_file_path_; |
474 | 445 |
475 std::unique_ptr<PersistentMemoryAllocator> allocator_; | 446 std::unique_ptr<PersistentMemoryAllocator> allocator_; |
476 std::unique_ptr<ThreadActivityTracker> tracker_; | 447 std::unique_ptr<ThreadActivityTracker> tracker_; |
477 }; | 448 }; |
478 | 449 |
479 TEST_F(PostmortemReportCollectorCollectionTest, CollectSuccess) { | 450 TEST_F(PostmortemReportCollectorCollectionTest, CollectSuccess) { |
480 // Create some activity data. | 451 // Create some activity data. |
481 tracker_->PushActivity(reinterpret_cast<void*>(kTaskOrigin), | 452 tracker_->PushActivity(reinterpret_cast<void*>(kTaskOrigin), |
482 base::debug::Activity::ACT_TASK_RUN, | 453 base::debug::Activity::ACT_TASK_RUN, |
483 ActivityData::ForTask(kTaskSequenceNum)); | 454 ActivityData::ForTask(kTaskSequenceNum)); |
(...skipping 15 matching lines...) Expand all Loading... | |
499 | 470 |
500 // Add some user data. | 471 // Add some user data. |
501 ActivityTrackerMemoryAllocator user_data_allocator( | 472 ActivityTrackerMemoryAllocator user_data_allocator( |
502 allocator_.get(), GlobalActivityTracker::kTypeIdUserDataRecord, | 473 allocator_.get(), GlobalActivityTracker::kTypeIdUserDataRecord, |
503 GlobalActivityTracker::kTypeIdUserDataRecordFree, 1024U, 10U, false); | 474 GlobalActivityTracker::kTypeIdUserDataRecordFree, 1024U, 10U, false); |
504 std::unique_ptr<ActivityUserData> user_data = | 475 std::unique_ptr<ActivityUserData> user_data = |
505 tracker_->GetUserData(activity_id, &user_data_allocator); | 476 tracker_->GetUserData(activity_id, &user_data_allocator); |
506 user_data->SetInt("some_int", 42); | 477 user_data->SetInt("some_int", 42); |
507 | 478 |
508 // Validate collection returns the expected report. | 479 // Validate collection returns the expected report. |
480 MockCrashReportDatabase crash_db; | |
509 PostmortemReportCollector collector(kProductName, kVersionNumber, | 481 PostmortemReportCollector collector(kProductName, kVersionNumber, |
510 kChannelName, nullptr); | 482 kChannelName, &crash_db, nullptr); |
511 StabilityReport report; | 483 StabilityReport report; |
512 ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); | 484 ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); |
513 | 485 |
514 // Validate the report. | 486 // Validate the report. |
515 ASSERT_EQ(1, report.process_states_size()); | 487 ASSERT_EQ(1, report.process_states_size()); |
516 const ProcessState& process_state = report.process_states(0); | 488 const ProcessState& process_state = report.process_states(0); |
517 EXPECT_EQ(base::GetCurrentProcId(), process_state.process_id()); | 489 EXPECT_EQ(base::GetCurrentProcId(), process_state.process_id()); |
518 ASSERT_EQ(1, process_state.threads_size()); | 490 ASSERT_EQ(1, process_state.threads_size()); |
519 | 491 |
520 const ThreadState& thread_state = process_state.threads(0); | 492 const ThreadState& thread_state = process_state.threads(0); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
587 } | 559 } |
588 | 560 |
589 void SetUp() override { | 561 void SetUp() override { |
590 testing::Test::SetUp(); | 562 testing::Test::SetUp(); |
591 | 563 |
592 // Set up a debug file path. | 564 // Set up a debug file path. |
593 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | 565 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
594 debug_file_path_ = temp_dir_.GetPath().AppendASCII("debug.pma"); | 566 debug_file_path_ = temp_dir_.GetPath().AppendASCII("debug.pma"); |
595 } | 567 } |
596 | 568 |
597 const base::FilePath& debug_file_path() { return debug_file_path_; } | 569 const FilePath& debug_file_path() { return debug_file_path_; } |
598 | 570 |
599 protected: | 571 protected: |
600 base::ScopedTempDir temp_dir_; | 572 base::ScopedTempDir temp_dir_; |
601 base::FilePath debug_file_path_; | 573 FilePath debug_file_path_; |
602 }; | 574 }; |
603 | 575 |
604 TEST_F(PostmortemReportCollectorCollectionFromGlobalTrackerTest, | 576 TEST_F(PostmortemReportCollectorCollectionFromGlobalTrackerTest, |
605 LogCollection) { | 577 LogCollection) { |
606 // Record some log messages. | 578 // Record some log messages. |
607 GlobalActivityTracker::CreateWithFile(debug_file_path(), kMemorySize, 0ULL, | 579 GlobalActivityTracker::CreateWithFile(debug_file_path(), kMemorySize, 0ULL, |
608 "", 3); | 580 "", 3); |
609 GlobalActivityTracker::Get()->RecordLogMessage("hello world"); | 581 GlobalActivityTracker::Get()->RecordLogMessage("hello world"); |
610 GlobalActivityTracker::Get()->RecordLogMessage("foo bar"); | 582 GlobalActivityTracker::Get()->RecordLogMessage("foo bar"); |
611 | 583 |
612 // Collect the stability report. | 584 // Collect the stability report. |
585 MockCrashReportDatabase crash_db; | |
613 PostmortemReportCollector collector(kProductName, kVersionNumber, | 586 PostmortemReportCollector collector(kProductName, kVersionNumber, |
614 kChannelName, nullptr); | 587 kChannelName, &crash_db, nullptr); |
615 StabilityReport report; | 588 StabilityReport report; |
616 ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); | 589 ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); |
617 | 590 |
618 // Validate the report's log content. | 591 // Validate the report's log content. |
619 ASSERT_EQ(2, report.log_messages_size()); | 592 ASSERT_EQ(2, report.log_messages_size()); |
620 ASSERT_EQ("hello world", report.log_messages(0)); | 593 ASSERT_EQ("hello world", report.log_messages(0)); |
621 ASSERT_EQ("foo bar", report.log_messages(1)); | 594 ASSERT_EQ("foo bar", report.log_messages(1)); |
622 } | 595 } |
623 | 596 |
624 TEST_F(PostmortemReportCollectorCollectionFromGlobalTrackerTest, | 597 TEST_F(PostmortemReportCollectorCollectionFromGlobalTrackerTest, |
(...skipping 11 matching lines...) Expand all Loading... | |
636 process_data.Set("raw", "foo", 3); | 609 process_data.Set("raw", "foo", 3); |
637 process_data.SetString("string", "bar"); | 610 process_data.SetString("string", "bar"); |
638 process_data.SetChar("char", '9'); | 611 process_data.SetChar("char", '9'); |
639 process_data.SetInt("int", -9999); | 612 process_data.SetInt("int", -9999); |
640 process_data.SetUint("uint", 9999); | 613 process_data.SetUint("uint", 9999); |
641 process_data.SetBool("bool", true); | 614 process_data.SetBool("bool", true); |
642 process_data.SetReference("ref", string1, strlen(string1)); | 615 process_data.SetReference("ref", string1, strlen(string1)); |
643 process_data.SetStringReference("sref", string2); | 616 process_data.SetStringReference("sref", string2); |
644 | 617 |
645 // Collect the stability report. | 618 // Collect the stability report. |
619 MockCrashReportDatabase crash_db; | |
646 PostmortemReportCollector collector(kProductName, kVersionNumber, | 620 PostmortemReportCollector collector(kProductName, kVersionNumber, |
647 kChannelName, nullptr); | 621 kChannelName, &crash_db, nullptr); |
648 StabilityReport report; | 622 StabilityReport report; |
649 ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); | 623 ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); |
650 | 624 |
651 // Validate the report's user data. | 625 // Validate the report's user data. |
652 const auto& collected_data = report.global_data(); | 626 const auto& collected_data = report.global_data(); |
653 ASSERT_EQ(kInternalProcessDatums + 12U, collected_data.size()); | 627 ASSERT_EQ(kInternalProcessDatums + 12U, collected_data.size()); |
654 | 628 |
655 ASSERT_TRUE(base::ContainsKey(collected_data, "raw")); | 629 ASSERT_TRUE(base::ContainsKey(collected_data, "raw")); |
656 EXPECT_EQ(TypedValue::kBytesValue, collected_data.at("raw").value_case()); | 630 EXPECT_EQ(TypedValue::kBytesValue, collected_data.at("raw").value_case()); |
657 EXPECT_EQ("foo", collected_data.at("raw").bytes_value()); | 631 EXPECT_EQ("foo", collected_data.at("raw").bytes_value()); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
705 FieldTrialCollection) { | 679 FieldTrialCollection) { |
706 // Record some data. | 680 // Record some data. |
707 GlobalActivityTracker::CreateWithFile(debug_file_path(), kMemorySize, 0ULL, | 681 GlobalActivityTracker::CreateWithFile(debug_file_path(), kMemorySize, 0ULL, |
708 "", 3); | 682 "", 3); |
709 ActivityUserData& process_data = GlobalActivityTracker::Get()->process_data(); | 683 ActivityUserData& process_data = GlobalActivityTracker::Get()->process_data(); |
710 process_data.SetString("string", "bar"); | 684 process_data.SetString("string", "bar"); |
711 process_data.SetString("FieldTrial.string", "bar"); | 685 process_data.SetString("FieldTrial.string", "bar"); |
712 process_data.SetString("FieldTrial.foo", "bar"); | 686 process_data.SetString("FieldTrial.foo", "bar"); |
713 | 687 |
714 // Collect the stability report. | 688 // Collect the stability report. |
689 MockCrashReportDatabase crash_db; | |
715 PostmortemReportCollector collector(kProductName, kVersionNumber, | 690 PostmortemReportCollector collector(kProductName, kVersionNumber, |
716 kChannelName, nullptr); | 691 kChannelName, &crash_db, nullptr); |
717 StabilityReport report; | 692 StabilityReport report; |
718 ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); | 693 ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); |
719 | 694 |
720 // Validate the report's experiment and global data. | 695 // Validate the report's experiment and global data. |
721 ASSERT_EQ(2, report.field_trials_size()); | 696 ASSERT_EQ(2, report.field_trials_size()); |
722 EXPECT_NE(0U, report.field_trials(0).name_id()); | 697 EXPECT_NE(0U, report.field_trials(0).name_id()); |
723 EXPECT_NE(0U, report.field_trials(0).group_id()); | 698 EXPECT_NE(0U, report.field_trials(0).group_id()); |
724 EXPECT_NE(0U, report.field_trials(1).name_id()); | 699 EXPECT_NE(0U, report.field_trials(1).name_id()); |
725 EXPECT_EQ(report.field_trials(0).group_id(), | 700 EXPECT_EQ(report.field_trials(0).group_id(), |
726 report.field_trials(1).group_id()); | 701 report.field_trials(1).group_id()); |
(...skipping 19 matching lines...) Expand all Loading... | |
746 module_info.age = 1; | 721 module_info.age = 1; |
747 crashpad::UUID debug_uuid; | 722 crashpad::UUID debug_uuid; |
748 debug_uuid.InitializeFromString("11223344-5566-7788-abcd-0123456789ab"); | 723 debug_uuid.InitializeFromString("11223344-5566-7788-abcd-0123456789ab"); |
749 memcpy(module_info.identifier, &debug_uuid, sizeof(module_info.identifier)); | 724 memcpy(module_info.identifier, &debug_uuid, sizeof(module_info.identifier)); |
750 module_info.file = "foo"; | 725 module_info.file = "foo"; |
751 module_info.debug_file = "bar"; | 726 module_info.debug_file = "bar"; |
752 | 727 |
753 GlobalActivityTracker::Get()->RecordModuleInfo(module_info); | 728 GlobalActivityTracker::Get()->RecordModuleInfo(module_info); |
754 | 729 |
755 // Collect the stability report. | 730 // Collect the stability report. |
731 MockCrashReportDatabase crash_db; | |
756 PostmortemReportCollector collector(kProductName, kVersionNumber, | 732 PostmortemReportCollector collector(kProductName, kVersionNumber, |
757 kChannelName, nullptr); | 733 kChannelName, &crash_db, nullptr); |
758 StabilityReport report; | 734 StabilityReport report; |
759 ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); | 735 ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); |
760 | 736 |
761 // Validate the report's modules content. | 737 // Validate the report's modules content. |
762 ASSERT_EQ(1, report.process_states_size()); | 738 ASSERT_EQ(1, report.process_states_size()); |
763 const ProcessState& process_state = report.process_states(0); | 739 const ProcessState& process_state = report.process_states(0); |
764 ASSERT_EQ(1, process_state.modules_size()); | 740 ASSERT_EQ(1, process_state.modules_size()); |
765 | 741 |
766 const CodeModule collected_module = process_state.modules(0); | 742 const CodeModule collected_module = process_state.modules(0); |
767 EXPECT_EQ(module_info.address, | 743 EXPECT_EQ(module_info.address, |
(...skipping 16 matching lines...) Expand all Loading... | |
784 "", 3); | 760 "", 3); |
785 ActivityUserData& process_data = GlobalActivityTracker::Get()->process_data(); | 761 ActivityUserData& process_data = GlobalActivityTracker::Get()->process_data(); |
786 process_data.SetInt(kStabilityStartTimestamp, 12345LL); | 762 process_data.SetInt(kStabilityStartTimestamp, 12345LL); |
787 | 763 |
788 // Collect. | 764 // Collect. |
789 MockSystemSessionAnalyzer analyzer; | 765 MockSystemSessionAnalyzer analyzer; |
790 EXPECT_CALL(analyzer, | 766 EXPECT_CALL(analyzer, |
791 IsSessionUnclean(base::Time::FromInternalValue(12345LL))) | 767 IsSessionUnclean(base::Time::FromInternalValue(12345LL))) |
792 .Times(1) | 768 .Times(1) |
793 .WillOnce(Return(SystemSessionAnalyzer::CLEAN)); | 769 .WillOnce(Return(SystemSessionAnalyzer::CLEAN)); |
770 MockCrashReportDatabase crash_db; | |
794 PostmortemReportCollector collector(kProductName, kVersionNumber, | 771 PostmortemReportCollector collector(kProductName, kVersionNumber, |
795 kChannelName, &analyzer); | 772 kChannelName, &crash_db, &analyzer); |
796 StabilityReport report; | 773 StabilityReport report; |
797 ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); | 774 ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); |
798 | 775 |
799 // Validate the report. | 776 // Validate the report. |
800 ASSERT_EQ(SystemState::CLEAN, report.system_state().session_state()); | 777 ASSERT_EQ(SystemState::CLEAN, report.system_state().session_state()); |
801 } | 778 } |
802 | 779 |
803 } // namespace browser_watcher | 780 } // namespace browser_watcher |
OLD | NEW |