| 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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 | 93 |
| 94 // A function that returns a unique_ptr cannot be mocked, so mock a function | 94 // A function that returns a unique_ptr cannot be mocked, so mock a function |
| 95 // that returns a raw pointer instead. | 95 // that returns a raw pointer instead. |
| 96 CollectionStatus Collect(const base::FilePath& debug_state_file, | 96 CollectionStatus Collect(const base::FilePath& debug_state_file, |
| 97 std::unique_ptr<StabilityReport>* report) override { | 97 std::unique_ptr<StabilityReport>* report) override { |
| 98 DCHECK_NE(nullptr, report); | 98 DCHECK_NE(nullptr, report); |
| 99 report->reset(CollectRaw(debug_state_file)); | 99 report->reset(CollectRaw(debug_state_file)); |
| 100 return SUCCESS; | 100 return SUCCESS; |
| 101 } | 101 } |
| 102 | 102 |
| 103 MOCK_METHOD0(GetProductName, const std::string&()); |
| 104 MOCK_METHOD0(GetProductVersion, const std::string&()); |
| 105 MOCK_METHOD0(GetProductChannel, const std::string&()); |
| 103 MOCK_METHOD3(GetDebugStateFilePaths, | 106 MOCK_METHOD3(GetDebugStateFilePaths, |
| 104 std::vector<base::FilePath>( | 107 std::vector<base::FilePath>( |
| 105 const base::FilePath& debug_info_dir, | 108 const base::FilePath& debug_info_dir, |
| 106 const base::FilePath::StringType& debug_file_pattern, | 109 const base::FilePath::StringType& debug_file_pattern, |
| 107 const std::set<base::FilePath>&)); | 110 const std::set<base::FilePath>&)); |
| 108 MOCK_METHOD1(CollectRaw, StabilityReport*(const base::FilePath&)); | 111 MOCK_METHOD1(CollectRaw, StabilityReport*(const base::FilePath&)); |
| 109 MOCK_METHOD4(WriteReportToMinidump, | 112 MOCK_METHOD4(WriteReportToMinidump, |
| 110 bool(const StabilityReport& report, | 113 bool(const StabilityReport& report, |
| 111 const crashpad::UUID& client_id, | 114 const crashpad::UUID& client_id, |
| 112 const crashpad::UUID& report_id, | 115 const crashpad::UUID& report_id, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 125 // serialization. | 128 // serialization. |
| 126 // TODO(manzagop): switch a matcher with guarantees. | 129 // TODO(manzagop): switch a matcher with guarantees. |
| 127 MATCHER_P(EqualsProto, message, "") { | 130 MATCHER_P(EqualsProto, message, "") { |
| 128 std::string expected_serialized; | 131 std::string expected_serialized; |
| 129 std::string actual_serialized; | 132 std::string actual_serialized; |
| 130 message.SerializeToString(&expected_serialized); | 133 message.SerializeToString(&expected_serialized); |
| 131 arg.SerializeToString(&actual_serialized); | 134 arg.SerializeToString(&actual_serialized); |
| 132 return expected_serialized == actual_serialized; | 135 return expected_serialized == actual_serialized; |
| 133 } | 136 } |
| 134 | 137 |
| 138 class PostmortemReportCollectorForTest : public PostmortemReportCollector { |
| 139 public: |
| 140 PostmortemReportCollectorForTest() |
| 141 : PostmortemReportCollector(), |
| 142 product_name_("TestProduct"), |
| 143 version_number_("TestVersionNumber"), |
| 144 channel_name_("TestChannel") {} |
| 145 ~PostmortemReportCollectorForTest() override = default; |
| 146 |
| 147 const std::string& GetProductName() override { return product_name_; } |
| 148 const std::string& GetProductVersion() override { return version_number_; } |
| 149 const std::string& GetProductChannel() override { return channel_name_; } |
| 150 |
| 151 private: |
| 152 std::string product_name_; |
| 153 std::string version_number_; |
| 154 std::string channel_name_; |
| 155 |
| 156 DISALLOW_COPY_AND_ASSIGN(PostmortemReportCollectorForTest); |
| 157 }; |
| 158 |
| 135 } // namespace | 159 } // namespace |
| 136 | 160 |
| 137 class PostmortemReportCollectorCollectAndSubmitTest : public testing::Test { | 161 class PostmortemReportCollectorCollectAndSubmitTest : public testing::Test { |
| 138 public: | 162 public: |
| 139 void SetUp() override { | 163 void SetUp() override { |
| 140 testing::Test::SetUp(); | 164 testing::Test::SetUp(); |
| 141 // Create a dummy debug file. | 165 // Create a dummy debug file. |
| 142 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | 166 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| 143 debug_file_ = temp_dir_.path().AppendASCII("foo-1.pma"); | 167 debug_file_ = temp_dir_.path().AppendASCII("foo-1.pma"); |
| 144 { | 168 { |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 254 file.reset(base::OpenFile(path, "w")); | 278 file.reset(base::OpenFile(path, "w")); |
| 255 ASSERT_NE(file.get(), nullptr); | 279 ASSERT_NE(file.get(), nullptr); |
| 256 expected_paths.push_back(path); | 280 expected_paths.push_back(path); |
| 257 | 281 |
| 258 // Does not match the pattern. | 282 // Does not match the pattern. |
| 259 path = temp_dir.path().AppendASCII("bar.baz"); | 283 path = temp_dir.path().AppendASCII("bar.baz"); |
| 260 file.reset(base::OpenFile(path, "w")); | 284 file.reset(base::OpenFile(path, "w")); |
| 261 ASSERT_NE(file.get(), nullptr); | 285 ASSERT_NE(file.get(), nullptr); |
| 262 } | 286 } |
| 263 | 287 |
| 264 PostmortemReportCollector collector; | 288 PostmortemReportCollectorForTest collector; |
| 265 EXPECT_THAT( | 289 EXPECT_THAT( |
| 266 collector.GetDebugStateFilePaths( | 290 collector.GetDebugStateFilePaths( |
| 267 temp_dir.path(), FILE_PATH_LITERAL("foo*.pma"), excluded_paths), | 291 temp_dir.path(), FILE_PATH_LITERAL("foo*.pma"), excluded_paths), |
| 268 testing::UnorderedElementsAreArray(expected_paths)); | 292 testing::UnorderedElementsAreArray(expected_paths)); |
| 269 } | 293 } |
| 270 | 294 |
| 271 TEST(PostmortemReportCollectorTest, CollectEmptyFile) { | 295 TEST(PostmortemReportCollectorTest, CollectEmptyFile) { |
| 272 // Create an empty file. | 296 // Create an empty file. |
| 273 base::ScopedTempDir temp_dir; | 297 base::ScopedTempDir temp_dir; |
| 274 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 298 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| 275 base::FilePath file_path = temp_dir.path().AppendASCII("empty.pma"); | 299 base::FilePath file_path = temp_dir.path().AppendASCII("empty.pma"); |
| 276 { | 300 { |
| 277 base::ScopedFILE file(base::OpenFile(file_path, "w")); | 301 base::ScopedFILE file(base::OpenFile(file_path, "w")); |
| 278 ASSERT_NE(file.get(), nullptr); | 302 ASSERT_NE(file.get(), nullptr); |
| 279 } | 303 } |
| 280 ASSERT_TRUE(PathExists(file_path)); | 304 ASSERT_TRUE(PathExists(file_path)); |
| 281 | 305 |
| 282 // Validate collection: an empty file cannot suppport an analyzer. | 306 // Validate collection: an empty file cannot suppport an analyzer. |
| 283 PostmortemReportCollector collector; | 307 PostmortemReportCollectorForTest collector; |
| 284 std::unique_ptr<StabilityReport> report; | 308 std::unique_ptr<StabilityReport> report; |
| 285 ASSERT_EQ(PostmortemReportCollector::ANALYZER_CREATION_FAILED, | 309 ASSERT_EQ(PostmortemReportCollector::ANALYZER_CREATION_FAILED, |
| 286 collector.Collect(file_path, &report)); | 310 collector.Collect(file_path, &report)); |
| 287 } | 311 } |
| 288 | 312 |
| 289 TEST(PostmortemReportCollectorTest, CollectRandomFile) { | 313 TEST(PostmortemReportCollectorTest, CollectRandomFile) { |
| 290 // Create a file with content we don't expect to be valid for a debug file. | 314 // Create a file with content we don't expect to be valid for a debug file. |
| 291 base::ScopedTempDir temp_dir; | 315 base::ScopedTempDir temp_dir; |
| 292 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 316 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| 293 base::FilePath file_path = temp_dir.path().AppendASCII("invalid_content.pma"); | 317 base::FilePath file_path = temp_dir.path().AppendASCII("invalid_content.pma"); |
| 294 { | 318 { |
| 295 base::ScopedFILE file(base::OpenFile(file_path, "w")); | 319 base::ScopedFILE file(base::OpenFile(file_path, "w")); |
| 296 ASSERT_NE(file.get(), nullptr); | 320 ASSERT_NE(file.get(), nullptr); |
| 297 // Assuming this size is greater than the minimum size of a debug file. | 321 // Assuming this size is greater than the minimum size of a debug file. |
| 298 std::vector<uint8_t> data(1024); | 322 std::vector<uint8_t> data(1024); |
| 299 for (size_t i = 0; i < data.size(); ++i) | 323 for (size_t i = 0; i < data.size(); ++i) |
| 300 data[i] = i % UINT8_MAX; | 324 data[i] = i % UINT8_MAX; |
| 301 ASSERT_EQ(data.size(), | 325 ASSERT_EQ(data.size(), |
| 302 fwrite(&data.at(0), sizeof(uint8_t), data.size(), file.get())); | 326 fwrite(&data.at(0), sizeof(uint8_t), data.size(), file.get())); |
| 303 } | 327 } |
| 304 ASSERT_TRUE(PathExists(file_path)); | 328 ASSERT_TRUE(PathExists(file_path)); |
| 305 | 329 |
| 306 // Validate collection: random content appears as though there is not | 330 // Validate collection: random content appears as though there is not |
| 307 // stability data. | 331 // stability data. |
| 308 PostmortemReportCollector collector; | 332 PostmortemReportCollectorForTest collector; |
| 309 std::unique_ptr<StabilityReport> report; | 333 std::unique_ptr<StabilityReport> report; |
| 310 ASSERT_EQ(PostmortemReportCollector::DEBUG_FILE_NO_DATA, | 334 ASSERT_EQ(PostmortemReportCollector::DEBUG_FILE_NO_DATA, |
| 311 collector.Collect(file_path, &report)); | 335 collector.Collect(file_path, &report)); |
| 312 } | 336 } |
| 313 | 337 |
| 314 namespace { | 338 namespace { |
| 315 | 339 |
| 316 // Parameters for the activity tracking. | 340 // Parameters for the activity tracking. |
| 317 const size_t kFileSize = 2 * 1024; | 341 const size_t kFileSize = 2 * 1024; |
| 318 const int kStackDepth = 4; | 342 const int kStackDepth = 4; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 392 | 416 |
| 393 const base::FilePath& debug_file_path() const { return debug_file_path_; } | 417 const base::FilePath& debug_file_path() const { return debug_file_path_; } |
| 394 | 418 |
| 395 private: | 419 private: |
| 396 base::ScopedTempDir temp_dir_; | 420 base::ScopedTempDir temp_dir_; |
| 397 base::FilePath debug_file_path_; | 421 base::FilePath debug_file_path_; |
| 398 }; | 422 }; |
| 399 | 423 |
| 400 TEST_F(PostmortemReportCollectorCollectionTest, CollectSuccess) { | 424 TEST_F(PostmortemReportCollectorCollectionTest, CollectSuccess) { |
| 401 // Validate collection returns the expected report. | 425 // Validate collection returns the expected report. |
| 402 PostmortemReportCollector collector; | 426 PostmortemReportCollectorForTest collector; |
| 403 std::unique_ptr<StabilityReport> report; | 427 std::unique_ptr<StabilityReport> report; |
| 404 ASSERT_EQ(PostmortemReportCollector::SUCCESS, | 428 ASSERT_EQ(PostmortemReportCollector::SUCCESS, |
| 405 collector.Collect(debug_file_path(), &report)); | 429 collector.Collect(debug_file_path(), &report)); |
| 406 ASSERT_NE(nullptr, report); | 430 ASSERT_NE(nullptr, report); |
| 407 | 431 |
| 408 // Build the expected report. | 432 // Build the expected report. |
| 409 StabilityReport expected_report; | 433 StabilityReport expected_report; |
| 410 ProcessState* process_state = expected_report.add_process_states(); | 434 ProcessState* process_state = expected_report.add_process_states(); |
| 411 ThreadState* thread_state = process_state->add_threads(); | 435 ThreadState* thread_state = process_state->add_threads(); |
| 412 thread_state->set_thread_name(base::PlatformThread::GetName()); | 436 thread_state->set_thread_name(base::PlatformThread::GetName()); |
| 413 | 437 |
| 414 ASSERT_EQ(expected_report.SerializeAsString(), report->SerializeAsString()); | 438 ASSERT_EQ(expected_report.SerializeAsString(), report->SerializeAsString()); |
| 415 } | 439 } |
| 416 | 440 |
| 417 } // namespace browser_watcher | 441 } // namespace browser_watcher |
| OLD | NEW |