| 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 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 } | 135 } |
| 136 | 136 |
| 137 } // namespace | 137 } // namespace |
| 138 | 138 |
| 139 class PostmortemReportCollectorCollectAndSubmitTest : public testing::Test { | 139 class PostmortemReportCollectorCollectAndSubmitTest : public testing::Test { |
| 140 public: | 140 public: |
| 141 void SetUp() override { | 141 void SetUp() override { |
| 142 testing::Test::SetUp(); | 142 testing::Test::SetUp(); |
| 143 // Create a dummy debug file. | 143 // Create a dummy debug file. |
| 144 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | 144 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| 145 debug_file_ = temp_dir_.path().AppendASCII("foo-1.pma"); | 145 debug_file_ = temp_dir_.GetPath().AppendASCII("foo-1.pma"); |
| 146 { | 146 { |
| 147 base::ScopedFILE file(base::OpenFile(debug_file_, "w")); | 147 base::ScopedFILE file(base::OpenFile(debug_file_, "w")); |
| 148 ASSERT_NE(file.get(), nullptr); | 148 ASSERT_NE(file.get(), nullptr); |
| 149 } | 149 } |
| 150 ASSERT_TRUE(base::PathExists(debug_file_)); | 150 ASSERT_TRUE(base::PathExists(debug_file_)); |
| 151 | 151 |
| 152 // Expect collection of the debug file paths. | 152 // Expect collection of the debug file paths. |
| 153 debug_file_pattern_ = FILE_PATH_LITERAL("foo-*.pma"); | 153 debug_file_pattern_ = FILE_PATH_LITERAL("foo-*.pma"); |
| 154 std::vector<base::FilePath> debug_files{debug_file_}; | 154 std::vector<base::FilePath> debug_files{debug_file_}; |
| 155 EXPECT_CALL(collector_, | 155 EXPECT_CALL(collector_, |
| 156 GetDebugStateFilePaths(debug_file_.DirName(), | 156 GetDebugStateFilePaths(debug_file_.DirName(), |
| 157 debug_file_pattern_, no_excluded_files_)) | 157 debug_file_pattern_, no_excluded_files_)) |
| 158 .Times(1) | 158 .Times(1) |
| 159 .WillOnce(Return(debug_files)); | 159 .WillOnce(Return(debug_files)); |
| 160 | 160 |
| 161 EXPECT_CALL(database_, GetSettings()).Times(1).WillOnce(Return(nullptr)); | 161 EXPECT_CALL(database_, GetSettings()).Times(1).WillOnce(Return(nullptr)); |
| 162 | 162 |
| 163 // Expect collection to a proto of a single debug file. | 163 // Expect collection to a proto of a single debug file. |
| 164 // Note: caller takes ownership. | 164 // Note: caller takes ownership. |
| 165 StabilityReport* stability_report = new StabilityReport(); | 165 StabilityReport* stability_report = new StabilityReport(); |
| 166 EXPECT_CALL(collector_, CollectRaw(debug_file_)) | 166 EXPECT_CALL(collector_, CollectRaw(debug_file_)) |
| 167 .Times(1) | 167 .Times(1) |
| 168 .WillOnce(Return(stability_report)); | 168 .WillOnce(Return(stability_report)); |
| 169 | 169 |
| 170 // Expect the call to write the proto to a minidump. This involves | 170 // Expect the call to write the proto to a minidump. This involves |
| 171 // requesting a report from the crashpad database, writing the report, then | 171 // requesting a report from the crashpad database, writing the report, then |
| 172 // finalizing it with the database. | 172 // finalizing it with the database. |
| 173 base::FilePath minidump_path = temp_dir_.path().AppendASCII("foo-1.dmp"); | 173 base::FilePath minidump_path = temp_dir_.GetPath().AppendASCII("foo-1.dmp"); |
| 174 base::File minidump_file( | 174 base::File minidump_file( |
| 175 minidump_path, base::File::FLAG_CREATE | base::File::File::FLAG_WRITE); | 175 minidump_path, base::File::FLAG_CREATE | base::File::File::FLAG_WRITE); |
| 176 crashpad_report_ = {minidump_file.GetPlatformFile(), | 176 crashpad_report_ = {minidump_file.GetPlatformFile(), |
| 177 crashpad::UUID(UUID::InitializeWithNewTag{}), | 177 crashpad::UUID(UUID::InitializeWithNewTag{}), |
| 178 minidump_path}; | 178 minidump_path}; |
| 179 EXPECT_CALL(database_, PrepareNewCrashReport(_)) | 179 EXPECT_CALL(database_, PrepareNewCrashReport(_)) |
| 180 .Times(1) | 180 .Times(1) |
| 181 .WillOnce(DoAll(SetArgPointee<0>(&crashpad_report_), | 181 .WillOnce(DoAll(SetArgPointee<0>(&crashpad_report_), |
| 182 Return(CrashReportDatabase::kNoError))); | 182 Return(CrashReportDatabase::kNoError))); |
| 183 | 183 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 | 233 |
| 234 TEST(PostmortemReportCollectorTest, GetDebugStateFilePaths) { | 234 TEST(PostmortemReportCollectorTest, GetDebugStateFilePaths) { |
| 235 base::ScopedTempDir temp_dir; | 235 base::ScopedTempDir temp_dir; |
| 236 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 236 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| 237 | 237 |
| 238 // Create files. | 238 // Create files. |
| 239 std::vector<base::FilePath> expected_paths; | 239 std::vector<base::FilePath> expected_paths; |
| 240 std::set<base::FilePath> excluded_paths; | 240 std::set<base::FilePath> excluded_paths; |
| 241 { | 241 { |
| 242 // Matches the pattern. | 242 // Matches the pattern. |
| 243 base::FilePath path = temp_dir.path().AppendASCII("foo1.pma"); | 243 base::FilePath path = temp_dir.GetPath().AppendASCII("foo1.pma"); |
| 244 base::ScopedFILE file(base::OpenFile(path, "w")); | 244 base::ScopedFILE file(base::OpenFile(path, "w")); |
| 245 ASSERT_NE(file.get(), nullptr); | 245 ASSERT_NE(file.get(), nullptr); |
| 246 expected_paths.push_back(path); | 246 expected_paths.push_back(path); |
| 247 | 247 |
| 248 // Matches the pattern, but is excluded. | 248 // Matches the pattern, but is excluded. |
| 249 path = temp_dir.path().AppendASCII("foo2.pma"); | 249 path = temp_dir.GetPath().AppendASCII("foo2.pma"); |
| 250 file.reset(base::OpenFile(path, "w")); | 250 file.reset(base::OpenFile(path, "w")); |
| 251 ASSERT_NE(file.get(), nullptr); | 251 ASSERT_NE(file.get(), nullptr); |
| 252 ASSERT_TRUE(excluded_paths.insert(path).second); | 252 ASSERT_TRUE(excluded_paths.insert(path).second); |
| 253 | 253 |
| 254 // Matches the pattern. | 254 // Matches the pattern. |
| 255 path = temp_dir.path().AppendASCII("foo3.pma"); | 255 path = temp_dir.GetPath().AppendASCII("foo3.pma"); |
| 256 file.reset(base::OpenFile(path, "w")); | 256 file.reset(base::OpenFile(path, "w")); |
| 257 ASSERT_NE(file.get(), nullptr); | 257 ASSERT_NE(file.get(), nullptr); |
| 258 expected_paths.push_back(path); | 258 expected_paths.push_back(path); |
| 259 | 259 |
| 260 // Does not match the pattern. | 260 // Does not match the pattern. |
| 261 path = temp_dir.path().AppendASCII("bar.baz"); | 261 path = temp_dir.GetPath().AppendASCII("bar.baz"); |
| 262 file.reset(base::OpenFile(path, "w")); | 262 file.reset(base::OpenFile(path, "w")); |
| 263 ASSERT_NE(file.get(), nullptr); | 263 ASSERT_NE(file.get(), nullptr); |
| 264 } | 264 } |
| 265 | 265 |
| 266 PostmortemReportCollector collector; | 266 PostmortemReportCollector collector; |
| 267 EXPECT_THAT( | 267 EXPECT_THAT( |
| 268 collector.GetDebugStateFilePaths( | 268 collector.GetDebugStateFilePaths( |
| 269 temp_dir.path(), FILE_PATH_LITERAL("foo*.pma"), excluded_paths), | 269 temp_dir.GetPath(), FILE_PATH_LITERAL("foo*.pma"), excluded_paths), |
| 270 testing::UnorderedElementsAreArray(expected_paths)); | 270 testing::UnorderedElementsAreArray(expected_paths)); |
| 271 } | 271 } |
| 272 | 272 |
| 273 TEST(PostmortemReportCollectorTest, CollectEmptyFile) { | 273 TEST(PostmortemReportCollectorTest, CollectEmptyFile) { |
| 274 // Create an empty file. | 274 // Create an empty file. |
| 275 base::ScopedTempDir temp_dir; | 275 base::ScopedTempDir temp_dir; |
| 276 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 276 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| 277 base::FilePath file_path = temp_dir.path().AppendASCII("empty.pma"); | 277 base::FilePath file_path = temp_dir.GetPath().AppendASCII("empty.pma"); |
| 278 { | 278 { |
| 279 base::ScopedFILE file(base::OpenFile(file_path, "w")); | 279 base::ScopedFILE file(base::OpenFile(file_path, "w")); |
| 280 ASSERT_NE(file.get(), nullptr); | 280 ASSERT_NE(file.get(), nullptr); |
| 281 } | 281 } |
| 282 ASSERT_TRUE(PathExists(file_path)); | 282 ASSERT_TRUE(PathExists(file_path)); |
| 283 | 283 |
| 284 // Validate collection: an empty file cannot suppport an analyzer. | 284 // Validate collection: an empty file cannot suppport an analyzer. |
| 285 PostmortemReportCollector collector; | 285 PostmortemReportCollector collector; |
| 286 std::unique_ptr<StabilityReport> report; | 286 std::unique_ptr<StabilityReport> report; |
| 287 ASSERT_EQ(PostmortemReportCollector::ANALYZER_CREATION_FAILED, | 287 ASSERT_EQ(PostmortemReportCollector::ANALYZER_CREATION_FAILED, |
| 288 collector.Collect(file_path, &report)); | 288 collector.Collect(file_path, &report)); |
| 289 } | 289 } |
| 290 | 290 |
| 291 TEST(PostmortemReportCollectorTest, CollectRandomFile) { | 291 TEST(PostmortemReportCollectorTest, CollectRandomFile) { |
| 292 // Create a file with content we don't expect to be valid for a debug file. | 292 // Create a file with content we don't expect to be valid for a debug file. |
| 293 base::ScopedTempDir temp_dir; | 293 base::ScopedTempDir temp_dir; |
| 294 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 294 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| 295 base::FilePath file_path = temp_dir.path().AppendASCII("invalid_content.pma"); | 295 base::FilePath file_path = |
| 296 temp_dir.GetPath().AppendASCII("invalid_content.pma"); |
| 296 { | 297 { |
| 297 base::ScopedFILE file(base::OpenFile(file_path, "w")); | 298 base::ScopedFILE file(base::OpenFile(file_path, "w")); |
| 298 ASSERT_NE(file.get(), nullptr); | 299 ASSERT_NE(file.get(), nullptr); |
| 299 // Assuming this size is greater than the minimum size of a debug file. | 300 // Assuming this size is greater than the minimum size of a debug file. |
| 300 std::vector<uint8_t> data(1024); | 301 std::vector<uint8_t> data(1024); |
| 301 for (size_t i = 0; i < data.size(); ++i) | 302 for (size_t i = 0; i < data.size(); ++i) |
| 302 data[i] = i % UINT8_MAX; | 303 data[i] = i % UINT8_MAX; |
| 303 ASSERT_EQ(data.size(), | 304 ASSERT_EQ(data.size(), |
| 304 fwrite(&data.at(0), sizeof(uint8_t), data.size(), file.get())); | 305 fwrite(&data.at(0), sizeof(uint8_t), data.size(), file.get())); |
| 305 } | 306 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 324 } // namespace | 325 } // namespace |
| 325 | 326 |
| 326 class PostmortemReportCollectorCollectionTest : public testing::Test { | 327 class PostmortemReportCollectorCollectionTest : public testing::Test { |
| 327 public: | 328 public: |
| 328 // Create a proper debug file. | 329 // Create a proper debug file. |
| 329 void SetUp() override { | 330 void SetUp() override { |
| 330 testing::Test::SetUp(); | 331 testing::Test::SetUp(); |
| 331 | 332 |
| 332 // Create a file backed allocator. | 333 // Create a file backed allocator. |
| 333 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | 334 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| 334 debug_file_path_ = temp_dir_.path().AppendASCII("debug_file.pma"); | 335 debug_file_path_ = temp_dir_.GetPath().AppendASCII("debug_file.pma"); |
| 335 std::unique_ptr<PersistentMemoryAllocator> allocator = CreateAllocator(); | 336 std::unique_ptr<PersistentMemoryAllocator> allocator = CreateAllocator(); |
| 336 ASSERT_NE(nullptr, allocator); | 337 ASSERT_NE(nullptr, allocator); |
| 337 | 338 |
| 338 size_t tracker_mem_size = | 339 size_t tracker_mem_size = |
| 339 ThreadActivityTracker::SizeForStackDepth(kStackDepth); | 340 ThreadActivityTracker::SizeForStackDepth(kStackDepth); |
| 340 ASSERT_GT(kFileSize, tracker_mem_size); | 341 ASSERT_GT(kFileSize, tracker_mem_size); |
| 341 | 342 |
| 342 // Create some debug data using trackers. | 343 // Create some debug data using trackers. |
| 343 std::unique_ptr<ThreadActivityTracker> tracker = | 344 std::unique_ptr<ThreadActivityTracker> tracker = |
| 344 CreateTracker(allocator.get(), tracker_mem_size); | 345 CreateTracker(allocator.get(), tracker_mem_size); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 410 // Build the expected report. | 411 // Build the expected report. |
| 411 StabilityReport expected_report; | 412 StabilityReport expected_report; |
| 412 ProcessState* process_state = expected_report.add_process_states(); | 413 ProcessState* process_state = expected_report.add_process_states(); |
| 413 ThreadState* thread_state = process_state->add_threads(); | 414 ThreadState* thread_state = process_state->add_threads(); |
| 414 thread_state->set_thread_name(base::PlatformThread::GetName()); | 415 thread_state->set_thread_name(base::PlatformThread::GetName()); |
| 415 | 416 |
| 416 ASSERT_EQ(expected_report.SerializeAsString(), report->SerializeAsString()); | 417 ASSERT_EQ(expected_report.SerializeAsString(), report->SerializeAsString()); |
| 417 } | 418 } |
| 418 | 419 |
| 419 } // namespace browser_watcher | 420 } // namespace browser_watcher |
| OLD | NEW |