Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(404)

Side by Side Diff: components/browser_watcher/stability_report_extractor_unittest.cc

Issue 2926113002: Relocate stability report extraction tests to seperate file (Closed)
Patch Set: remove unused var/function (thanks clang) Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « components/browser_watcher/postmortem_report_collector_unittest.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2017 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/stability_report_extractor.h"
6
7 #include <stdint.h>
8 6
9 #include <memory> 7 #include <memory>
10 #include <set>
11 #include <string>
12 #include <utility> 8 #include <utility>
13 #include <vector>
14 9
15 #include "base/debug/activity_analyzer.h"
16 #include "base/debug/activity_tracker.h" 10 #include "base/debug/activity_tracker.h"
17 #include "base/files/file.h" 11 #include "base/files/file.h"
18 #include "base/files/file_path.h" 12 #include "base/files/file_path.h"
19 #include "base/files/file_util.h"
20 #include "base/files/memory_mapped_file.h" 13 #include "base/files/memory_mapped_file.h"
21 #include "base/files/scoped_file.h"
22 #include "base/files/scoped_temp_dir.h" 14 #include "base/files/scoped_temp_dir.h"
23 #include "base/memory/ptr_util.h" 15 #include "base/memory/ptr_util.h"
24 #include "base/metrics/persistent_memory_allocator.h" 16 #include "base/metrics/persistent_memory_allocator.h"
25 #include "base/process/process_handle.h"
26 #include "base/stl_util.h" 17 #include "base/stl_util.h"
27 #include "base/test/histogram_tester.h"
28 #include "base/threading/platform_thread.h"
29 #include "components/browser_watcher/stability_data_names.h"
30 #include "components/browser_watcher/stability_report_extractor.h"
31 #include "testing/gmock/include/gmock/gmock.h"
32 #include "testing/gtest/include/gtest/gtest.h" 18 #include "testing/gtest/include/gtest/gtest.h"
33 #include "third_party/crashpad/crashpad/client/crash_report_database.h" 19 #include "third_party/crashpad/crashpad/client/crash_report_database.h"
34 20
35 namespace browser_watcher { 21 namespace browser_watcher {
36 22
37 using base::debug::ActivityData; 23 using base::debug::ActivityData;
38 using base::debug::ActivityTrackerMemoryAllocator; 24 using base::debug::ActivityTrackerMemoryAllocator;
39 using base::debug::ActivityUserData; 25 using base::debug::ActivityUserData;
40 using base::debug::GlobalActivityTracker; 26 using base::debug::GlobalActivityTracker;
41 using base::debug::ThreadActivityTracker; 27 using base::debug::ThreadActivityTracker;
42 using base::File; 28 using base::File;
43 using base::FilePath; 29 using base::FilePath;
44 using base::FilePersistentMemoryAllocator; 30 using base::FilePersistentMemoryAllocator;
45 using base::MemoryMappedFile; 31 using base::MemoryMappedFile;
46 using base::PersistentMemoryAllocator; 32 using base::PersistentMemoryAllocator;
47 using base::WrapUnique; 33 using base::WrapUnique;
48 using crashpad::CrashReportDatabase;
49 using crashpad::Settings;
50 using crashpad::UUID;
51 using testing::_;
52 using testing::DoAll;
53 using testing::Return;
54 using testing::SetArgPointee;
55 34
56 namespace { 35 namespace {
57 36
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);
94
95 std::vector<CollectionStatus> unexpected_statuses = {
96 NONE,
97 SUCCESS,
98 ANALYZER_CREATION_FAILED,
99 DEBUG_FILE_NO_DATA,
100 PREPARE_NEW_CRASH_REPORT_FAILED,
101 WRITE_TO_MINIDUMP_FAILED,
102 FINISHED_WRITING_CRASH_REPORT_FAILED,
103 COLLECTION_ATTEMPT};
104 for (CollectionStatus status : unexpected_statuses) {
105 histogram_tester.ExpectBucketCount("ActivityTracker.Collect.Status", status,
106 0);
107 }
108 }
109
110 const char kProductName[] = "TestProduct";
111 const char kVersionNumber[] = "TestVersionNumber";
112 const char kChannelName[] = "TestChannel";
113
114 // The tracker creates some data entries internally. 37 // The tracker creates some data entries internally.
115 const size_t kInternalProcessDatums = 1; 38 const size_t kInternalProcessDatums = 1;
116 39
117 void ContainsKeyValue(
118 const google::protobuf::Map<std::string, TypedValue>& data,
119 const std::string& key,
120 const std::string& value) {
121 auto it = data.find(key);
122 ASSERT_TRUE(it != data.end());
123 EXPECT_EQ(TypedValue::kStringValue, it->second.value_case());
124 EXPECT_EQ(value, it->second.string_value());
125 }
126
127 // Exposes a public constructor in order to create a dummy database.
128 class MockCrashReportDatabase : public CrashReportDatabase {
129 public:
130 MockCrashReportDatabase() {}
131 MOCK_METHOD0(GetSettings, Settings*());
132 MOCK_METHOD1(PrepareNewCrashReport,
133 CrashReportDatabase::CrashReportDatabase::OperationStatus(
134 NewReport** report));
135 MOCK_METHOD2(FinishedWritingCrashReport,
136 CrashReportDatabase::CrashReportDatabase::OperationStatus(
137 CrashReportDatabase::NewReport* report,
138 crashpad::UUID* uuid));
139 MOCK_METHOD1(ErrorWritingCrashReport,
140 CrashReportDatabase::CrashReportDatabase::OperationStatus(
141 NewReport* report));
142 MOCK_METHOD2(LookUpCrashReport,
143 CrashReportDatabase::CrashReportDatabase::OperationStatus(
144 const UUID& uuid,
145 Report* report));
146 MOCK_METHOD1(
147 GetPendingReports,
148 CrashReportDatabase::OperationStatus(std::vector<Report>* reports));
149 MOCK_METHOD1(
150 GetCompletedReports,
151 CrashReportDatabase::OperationStatus(std::vector<Report>* reports));
152 MOCK_METHOD2(GetReportForUploading,
153 CrashReportDatabase::OperationStatus(const UUID& uuid,
154 const Report** report));
155 MOCK_METHOD3(RecordUploadAttempt,
156 CrashReportDatabase::OperationStatus(const Report* report,
157 bool successful,
158 const std::string& id));
159 MOCK_METHOD2(SkipReportUpload,
160 CrashReportDatabase::OperationStatus(
161 const UUID& uuid,
162 crashpad::Metrics::CrashSkippedReason reason));
163 MOCK_METHOD1(DeleteReport,
164 CrashReportDatabase::OperationStatus(const UUID& uuid));
165 MOCK_METHOD1(RequestUpload,
166 CrashReportDatabase::OperationStatus(const UUID& uuid));
167 };
168
169 class MockPostmortemReportCollector : public PostmortemReportCollector {
170 public:
171 explicit MockPostmortemReportCollector(CrashReportDatabase* crash_database)
172 : PostmortemReportCollector(kProductName,
173 kVersionNumber,
174 kChannelName,
175 crash_database,
176 nullptr) {}
177
178 MOCK_METHOD2(CollectOneReport,
179 CollectionStatus(const FilePath&, StabilityReport* report));
180 MOCK_METHOD4(WriteReportToMinidump,
181 bool(StabilityReport* report,
182 const crashpad::UUID& client_id,
183 const crashpad::UUID& report_id,
184 base::PlatformFile minidump_file));
185 };
186
187 class MockSystemSessionAnalyzer : public SystemSessionAnalyzer {
188 public:
189 MockSystemSessionAnalyzer() : SystemSessionAnalyzer(10U) {}
190 MOCK_METHOD1(IsSessionUnclean, Status(base::Time timestamp));
191 };
192
193 // Checks if two proto messages are the same based on their serializations. Note
194 // this only works if serialization is deterministic, which is not guaranteed.
195 // In practice, serialization is deterministic (even for protocol buffers with
196 // maps) and such matchers are common in the Chromium code base. Also note that
197 // in the context of this test, false positive matches are the problem and these
198 // are not possible (otherwise serialization would be ambiguous). False
199 // negatives would lead to test failure and developer action. Alternatives are:
200 // 1) a generic matcher (likely not possible without reflections, missing from
201 // lite runtime), 2) a specialized matcher or 3) implementing deterministic
202 // serialization.
203 // TODO(manzagop): switch a matcher with guarantees.
204 MATCHER_P(EqualsProto, message, "") {
205 std::string expected_serialized;
206 std::string actual_serialized;
207 message.SerializeToString(&expected_serialized);
208 arg.SerializeToString(&actual_serialized);
209 return expected_serialized == actual_serialized;
210 }
211
212 } // namespace
213
214 class PostmortemReportCollectorProcessTest : public testing::Test {
215 public:
216 void SetUpTest(bool system_session_clean, bool expect_write_dump) {
217 collector_.reset(new MockPostmortemReportCollector(&database_));
218
219 // Create a dummy debug file.
220 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
221 debug_file_ = temp_dir_.GetPath().AppendASCII("foo-1.pma");
222 {
223 base::ScopedFILE file(base::OpenFile(debug_file_, "w"));
224 ASSERT_NE(file.get(), nullptr);
225 }
226 ASSERT_TRUE(base::PathExists(debug_file_));
227
228 EXPECT_CALL(database_, GetSettings()).Times(1).WillOnce(Return(nullptr));
229
230 // Expect a single collection call.
231 StabilityReport report;
232 report.mutable_system_state()->set_session_state(
233 system_session_clean ? SystemState::CLEAN : SystemState::UNCLEAN);
234 EXPECT_CALL(*collector_, CollectOneReport(debug_file_, _))
235 .Times(1)
236 .WillOnce(DoAll(SetArgPointee<1>(report), Return(SUCCESS)));
237
238 if (!expect_write_dump)
239 return;
240
241 // Expect the call to write the proto to a minidump. This involves
242 // requesting a report from the crashpad database, writing the report, then
243 // finalizing it with the database.
244 FilePath minidump_path = temp_dir_.GetPath().AppendASCII("foo-1.dmp");
245 base::File minidump_file(
246 minidump_path, base::File::FLAG_CREATE | base::File::File::FLAG_WRITE);
247 crashpad::UUID new_report_uuid;
248 new_report_uuid.InitializeWithNew();
249 crashpad_report_ = {minidump_file.GetPlatformFile(), new_report_uuid,
250 minidump_path};
251 EXPECT_CALL(database_, PrepareNewCrashReport(_))
252 .Times(1)
253 .WillOnce(DoAll(SetArgPointee<0>(&crashpad_report_),
254 Return(CrashReportDatabase::kNoError)));
255
256 EXPECT_CALL(*collector_,
257 WriteReportToMinidump(_, _, _, minidump_file.GetPlatformFile()))
258 .Times(1)
259 .WillOnce(Return(true));
260 }
261 void ValidateHistograms(int unclean_cnt, int unclean_system_cnt) {
262 histogram_tester_.ExpectBucketCount("ActivityTracker.Collect.Status",
263 UNCLEAN_SHUTDOWN, unclean_cnt);
264 histogram_tester_.ExpectBucketCount("ActivityTracker.Collect.Status",
265 UNCLEAN_SESSION, unclean_system_cnt);
266 }
267 void CollectReports(bool is_session_clean) {
268 SetUpTest(is_session_clean, true);
269
270 EXPECT_CALL(database_, FinishedWritingCrashReport(&crashpad_report_, _))
271 .Times(1)
272 .WillOnce(Return(CrashReportDatabase::kNoError));
273
274 // Run the test.
275 std::vector<FilePath> debug_files{debug_file_};
276 collector_->Process(debug_files);
277 ASSERT_FALSE(base::PathExists(debug_file_));
278 }
279
280 protected:
281 base::HistogramTester histogram_tester_;
282 base::ScopedTempDir temp_dir_;
283 FilePath debug_file_;
284 MockCrashReportDatabase database_;
285 std::unique_ptr<MockPostmortemReportCollector> collector_;
286 CrashReportDatabase::NewReport crashpad_report_;
287 };
288
289 TEST_F(PostmortemReportCollectorProcessTest, ProcessCleanSession) {
290 CollectReports(true);
291 int expected_unclean = 1;
292 int expected_system_unclean = 0;
293 ValidateHistograms(expected_unclean, expected_system_unclean);
294 }
295
296 TEST_F(PostmortemReportCollectorProcessTest, ProcessUncleanSession) {
297 CollectReports(false);
298 int expected_unclean = 1;
299 int expected_system_unclean = 1;
300 ValidateHistograms(expected_unclean, expected_system_unclean);
301 }
302
303 TEST_F(PostmortemReportCollectorProcessTest, ProcessStuckFile) {
304 bool system_session_clean = true;
305 bool expect_write_dump = false;
306 SetUpTest(system_session_clean, expect_write_dump);
307
308 // Open the stability debug file to prevent its deletion.
309 base::ScopedFILE file(base::OpenFile(debug_file_, "w"));
310 ASSERT_NE(file.get(), nullptr);
311
312 // Run the test.
313 std::vector<FilePath> debug_files{debug_file_};
314 collector_->Process(debug_files);
315 ASSERT_TRUE(base::PathExists(debug_file_));
316
317 histogram_tester_.ExpectBucketCount("ActivityTracker.Collect.Status",
318 DEBUG_FILE_DELETION_FAILED, 1);
319 int expected_unclean = 0;
320 int expected_system_unclean = 0;
321 ValidateHistograms(expected_unclean, expected_system_unclean);
322 }
323
324 TEST(PostmortemReportCollectorTest, CollectEmptyFile) {
325 // Create an empty file.
326 base::ScopedTempDir temp_dir;
327 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
328 FilePath file_path = temp_dir.GetPath().AppendASCII("empty.pma");
329 {
330 base::ScopedFILE file(base::OpenFile(file_path, "w"));
331 ASSERT_NE(file.get(), nullptr);
332 }
333 ASSERT_TRUE(PathExists(file_path));
334
335 // Validate collection: an empty file cannot suppport an analyzer.
336 MockCrashReportDatabase crash_db;
337 PostmortemReportCollector collector(kProductName, kVersionNumber,
338 kChannelName, &crash_db, nullptr);
339 StabilityReport report;
340 ASSERT_EQ(ANALYZER_CREATION_FAILED,
341 collector.CollectOneReport(file_path, &report));
342 }
343
344 TEST(PostmortemReportCollectorTest, CollectRandomFile) {
345 // Create a file with content we don't expect to be valid for a debug file.
346 base::ScopedTempDir temp_dir;
347 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
348 FilePath file_path = temp_dir.GetPath().AppendASCII("invalid_content.pma");
349 {
350 base::ScopedFILE file(base::OpenFile(file_path, "w"));
351 ASSERT_NE(file.get(), nullptr);
352 // Assuming this size is greater than the minimum size of a debug file.
353 std::vector<uint8_t> data(1024);
354 for (size_t i = 0; i < data.size(); ++i)
355 data[i] = i % UINT8_MAX;
356 ASSERT_EQ(data.size(),
357 fwrite(&data.at(0), sizeof(uint8_t), data.size(), file.get()));
358 }
359 ASSERT_TRUE(PathExists(file_path));
360
361 // Validate collection: random content appears as though there is not
362 // stability data.
363 MockCrashReportDatabase crash_db;
364 PostmortemReportCollector collector(kProductName, kVersionNumber,
365 kChannelName, &crash_db, nullptr);
366 StabilityReport report;
367 ASSERT_NE(SUCCESS, collector.CollectOneReport(file_path, &report));
368 }
369
370 namespace {
371
372 // Parameters for the activity tracking. 40 // Parameters for the activity tracking.
373 const size_t kFileSize = 64 << 10; // 64 KiB 41 const size_t kFileSize = 64 << 10; // 64 KiB
374 const int kStackDepth = 6; 42 const int kStackDepth = 6;
375 const uint64_t kAllocatorId = 0; 43 const uint64_t kAllocatorId = 0;
376 const char kAllocatorName[] = "PostmortemReportCollectorCollectionTest"; 44 const char kAllocatorName[] = "PostmortemReportCollectorCollectionTest";
377 const uint64_t kTaskSequenceNum = 42; 45 const uint64_t kTaskSequenceNum = 42;
378 const uintptr_t kTaskOrigin = 1000U; 46 const uintptr_t kTaskOrigin = 1000U;
379 const uintptr_t kLockAddress = 1001U; 47 const uintptr_t kLockAddress = 1001U;
380 const uintptr_t kEventAddress = 1002U; 48 const uintptr_t kEventAddress = 1002U;
381 const int kThreadId = 43; 49 const int kThreadId = 43;
382 const int kProcessId = 44; 50 const int kProcessId = 44;
383 const int kAnotherThreadId = 45; 51 const int kAnotherThreadId = 45;
384 const uint32_t kGenericId = 46U; 52 const uint32_t kGenericId = 46U;
385 const int32_t kGenericData = 47; 53 const int32_t kGenericData = 47;
386 54
387 } // namespace 55 } // namespace
388 56
389 // Sets up a file backed thread tracker for direct access. A 57 // Sets up a file backed thread tracker for direct access. A
390 // GlobalActivityTracker is not created, meaning there is no risk of 58 // GlobalActivityTracker is not created, meaning there is no risk of
391 // the instrumentation interfering with the file's content. 59 // the instrumentation interfering with the file's content.
392 class PostmortemReportCollectorCollectionTest : public testing::Test { 60 class StabilityReportExtractorThreadTrackerTest : public testing::Test {
393 public: 61 public:
394 // Create a proper debug file. 62 // Create a proper debug file.
395 void SetUp() override { 63 void SetUp() override {
396 testing::Test::SetUp(); 64 testing::Test::SetUp();
397 65
398 // Create a file backed allocator. 66 // Create a file backed allocator.
399 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 67 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
400 debug_file_path_ = temp_dir_.GetPath().AppendASCII("debug_file.pma"); 68 debug_file_path_ = temp_dir_.GetPath().AppendASCII("debug_file.pma");
401 allocator_ = CreateAllocator(); 69 allocator_ = CreateAllocator();
402 ASSERT_NE(nullptr, allocator_); 70 ASSERT_NE(nullptr, allocator_);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 const FilePath& debug_file_path() const { return debug_file_path_; } 122 const FilePath& debug_file_path() const { return debug_file_path_; }
455 123
456 protected: 124 protected:
457 base::ScopedTempDir temp_dir_; 125 base::ScopedTempDir temp_dir_;
458 FilePath debug_file_path_; 126 FilePath debug_file_path_;
459 127
460 std::unique_ptr<PersistentMemoryAllocator> allocator_; 128 std::unique_ptr<PersistentMemoryAllocator> allocator_;
461 std::unique_ptr<ThreadActivityTracker> tracker_; 129 std::unique_ptr<ThreadActivityTracker> tracker_;
462 }; 130 };
463 131
464 TEST_F(PostmortemReportCollectorCollectionTest, CollectSuccess) { 132 TEST_F(StabilityReportExtractorThreadTrackerTest, CollectSuccess) {
465 // Create some activity data. 133 // Create some activity data.
466 tracker_->PushActivity(reinterpret_cast<void*>(kTaskOrigin), 134 tracker_->PushActivity(reinterpret_cast<void*>(kTaskOrigin),
467 base::debug::Activity::ACT_TASK_RUN, 135 base::debug::Activity::ACT_TASK_RUN,
468 ActivityData::ForTask(kTaskSequenceNum)); 136 ActivityData::ForTask(kTaskSequenceNum));
469 tracker_->PushActivity( 137 tracker_->PushActivity(
470 nullptr, base::debug::Activity::ACT_LOCK_ACQUIRE, 138 nullptr, base::debug::Activity::ACT_LOCK_ACQUIRE,
471 ActivityData::ForLock(reinterpret_cast<void*>(kLockAddress))); 139 ActivityData::ForLock(reinterpret_cast<void*>(kLockAddress)));
472 ThreadActivityTracker::ActivityId activity_id = tracker_->PushActivity( 140 ThreadActivityTracker::ActivityId activity_id = tracker_->PushActivity(
473 nullptr, base::debug::Activity::ACT_EVENT_WAIT, 141 nullptr, base::debug::Activity::ACT_EVENT_WAIT,
474 ActivityData::ForEvent(reinterpret_cast<void*>(kEventAddress))); 142 ActivityData::ForEvent(reinterpret_cast<void*>(kEventAddress)));
475 tracker_->PushActivity(nullptr, base::debug::Activity::ACT_THREAD_JOIN, 143 tracker_->PushActivity(nullptr, base::debug::Activity::ACT_THREAD_JOIN,
476 ActivityData::ForThread(kThreadId)); 144 ActivityData::ForThread(kThreadId));
477 tracker_->PushActivity(nullptr, base::debug::Activity::ACT_PROCESS_WAIT, 145 tracker_->PushActivity(nullptr, base::debug::Activity::ACT_PROCESS_WAIT,
478 ActivityData::ForProcess(kProcessId)); 146 ActivityData::ForProcess(kProcessId));
479 tracker_->PushActivity(nullptr, base::debug::Activity::ACT_GENERIC, 147 tracker_->PushActivity(nullptr, base::debug::Activity::ACT_GENERIC,
480 ActivityData::ForGeneric(kGenericId, kGenericData)); 148 ActivityData::ForGeneric(kGenericId, kGenericData));
481 // Note: this exceeds the activity stack's capacity. 149 // Note: this exceeds the activity stack's capacity.
482 tracker_->PushActivity(nullptr, base::debug::Activity::ACT_THREAD_JOIN, 150 tracker_->PushActivity(nullptr, base::debug::Activity::ACT_THREAD_JOIN,
483 ActivityData::ForThread(kAnotherThreadId)); 151 ActivityData::ForThread(kAnotherThreadId));
484 152
485 // Add some user data. 153 // Add some user data.
486 ActivityTrackerMemoryAllocator user_data_allocator( 154 ActivityTrackerMemoryAllocator user_data_allocator(
487 allocator_.get(), GlobalActivityTracker::kTypeIdUserDataRecord, 155 allocator_.get(), GlobalActivityTracker::kTypeIdUserDataRecord,
488 GlobalActivityTracker::kTypeIdUserDataRecordFree, 1024U, 10U, false); 156 GlobalActivityTracker::kTypeIdUserDataRecordFree, 1024U, 10U, false);
489 std::unique_ptr<ActivityUserData> user_data = 157 std::unique_ptr<ActivityUserData> user_data =
490 tracker_->GetUserData(activity_id, &user_data_allocator); 158 tracker_->GetUserData(activity_id, &user_data_allocator);
491 user_data->SetInt("some_int", 42); 159 user_data->SetInt("some_int", 42);
492 160
493 // Validate collection returns the expected report. 161 // Validate collection returns the expected report.
494 MockCrashReportDatabase crash_db;
495 PostmortemReportCollector collector(kProductName, kVersionNumber,
496 kChannelName, &crash_db, nullptr);
497 StabilityReport report; 162 StabilityReport report;
498 ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); 163 ASSERT_EQ(SUCCESS, Extract(debug_file_path(), &report));
499 164
500 // Validate the report. 165 // Validate the report.
501 ASSERT_EQ(1, report.process_states_size()); 166 ASSERT_EQ(1, report.process_states_size());
502 const ProcessState& process_state = report.process_states(0); 167 const ProcessState& process_state = report.process_states(0);
503 EXPECT_EQ(base::GetCurrentProcId(), process_state.process_id()); 168 EXPECT_EQ(base::GetCurrentProcId(), process_state.process_id());
504 ASSERT_EQ(1, process_state.threads_size()); 169 ASSERT_EQ(1, process_state.threads_size());
505 170
506 const ThreadState& thread_state = process_state.threads(0); 171 const ThreadState& thread_state = process_state.threads(0);
507 EXPECT_EQ(base::PlatformThread::GetName(), thread_state.thread_name()); 172 EXPECT_EQ(base::PlatformThread::GetName(), thread_state.thread_name());
508 #if defined(OS_WIN) 173 #if defined(OS_WIN)
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
551 } 216 }
552 { 217 {
553 const Activity& activity = thread_state.activities(5); 218 const Activity& activity = thread_state.activities(5);
554 EXPECT_EQ(Activity::ACT_GENERIC, activity.type()); 219 EXPECT_EQ(Activity::ACT_GENERIC, activity.type());
555 EXPECT_EQ(kGenericId, activity.generic_id()); 220 EXPECT_EQ(kGenericId, activity.generic_id());
556 EXPECT_EQ(kGenericData, activity.generic_data()); 221 EXPECT_EQ(kGenericData, activity.generic_data());
557 EXPECT_EQ(0U, activity.user_data().size()); 222 EXPECT_EQ(0U, activity.user_data().size());
558 } 223 }
559 } 224 }
560 225
561 class PostmortemReportCollectorCollectionFromGlobalTrackerTest 226 // Tests stability report extraction.
562 : public testing::Test { 227 class StabilityReportExtractorTest : public testing::Test {
563 public: 228 public:
564 const int kMemorySize = 1 << 20; // 1MiB 229 const int kMemorySize = 1 << 20; // 1MiB
565 230
566 PostmortemReportCollectorCollectionFromGlobalTrackerTest() {} 231 StabilityReportExtractorTest() {}
567 ~PostmortemReportCollectorCollectionFromGlobalTrackerTest() override { 232 ~StabilityReportExtractorTest() override {
568 GlobalActivityTracker* global_tracker = GlobalActivityTracker::Get(); 233 GlobalActivityTracker* global_tracker = GlobalActivityTracker::Get();
569 if (global_tracker) { 234 if (global_tracker) {
570 global_tracker->ReleaseTrackerForCurrentThreadForTesting(); 235 global_tracker->ReleaseTrackerForCurrentThreadForTesting();
571 delete global_tracker; 236 delete global_tracker;
572 } 237 }
573 } 238 }
574 239
575 void SetUp() override { 240 void SetUp() override {
576 testing::Test::SetUp(); 241 testing::Test::SetUp();
577 242
578 // Set up a debug file path. 243 // Set up a debug file path.
579 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 244 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
580 debug_file_path_ = temp_dir_.GetPath().AppendASCII("debug.pma"); 245 debug_file_path_ = temp_dir_.GetPath().AppendASCII("debug.pma");
581 } 246 }
582 247
583 const FilePath& debug_file_path() { return debug_file_path_; } 248 const FilePath& debug_file_path() { return debug_file_path_; }
584 249
585 protected: 250 protected:
586 base::ScopedTempDir temp_dir_; 251 base::ScopedTempDir temp_dir_;
587 FilePath debug_file_path_; 252 FilePath debug_file_path_;
588 }; 253 };
589 254
590 TEST_F(PostmortemReportCollectorCollectionFromGlobalTrackerTest, 255 TEST_F(StabilityReportExtractorTest, LogCollection) {
591 LogCollection) {
592 // Record some log messages. 256 // Record some log messages.
593 GlobalActivityTracker::CreateWithFile(debug_file_path(), kMemorySize, 0ULL, 257 GlobalActivityTracker::CreateWithFile(debug_file_path(), kMemorySize, 0ULL,
594 "", 3); 258 "", 3);
595 GlobalActivityTracker::Get()->RecordLogMessage("hello world"); 259 GlobalActivityTracker::Get()->RecordLogMessage("hello world");
596 GlobalActivityTracker::Get()->RecordLogMessage("foo bar"); 260 GlobalActivityTracker::Get()->RecordLogMessage("foo bar");
597 261
598 // Collect the stability report. 262 // Collect the stability report.
599 MockCrashReportDatabase crash_db;
600 PostmortemReportCollector collector(kProductName, kVersionNumber,
601 kChannelName, &crash_db, nullptr);
602 StabilityReport report; 263 StabilityReport report;
603 ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); 264 ASSERT_EQ(SUCCESS, Extract(debug_file_path(), &report));
604 265
605 // Validate the report's log content. 266 // Validate the report's log content.
606 ASSERT_EQ(2, report.log_messages_size()); 267 ASSERT_EQ(2, report.log_messages_size());
607 ASSERT_EQ("hello world", report.log_messages(0)); 268 ASSERT_EQ("hello world", report.log_messages(0));
608 ASSERT_EQ("foo bar", report.log_messages(1)); 269 ASSERT_EQ("foo bar", report.log_messages(1));
609 } 270 }
610 271
611 TEST_F(PostmortemReportCollectorCollectionFromGlobalTrackerTest, 272 TEST_F(StabilityReportExtractorTest, ProcessUserDataCollection) {
612 ProcessUserDataCollection) {
613 const char string1[] = "foo"; 273 const char string1[] = "foo";
614 const char string2[] = "bar"; 274 const char string2[] = "bar";
615 275
616 // Record some process user data. 276 // Record some process user data.
617 GlobalActivityTracker::CreateWithFile(debug_file_path(), kMemorySize, 0ULL, 277 GlobalActivityTracker::CreateWithFile(debug_file_path(), kMemorySize, 0ULL,
618 "", 3); 278 "", 3);
619 ActivityUserData& process_data = GlobalActivityTracker::Get()->process_data(); 279 ActivityUserData& process_data = GlobalActivityTracker::Get()->process_data();
620 ActivityUserData::Snapshot snapshot; 280 ActivityUserData::Snapshot snapshot;
621 ASSERT_TRUE(process_data.CreateSnapshot(&snapshot)); 281 ASSERT_TRUE(process_data.CreateSnapshot(&snapshot));
622 ASSERT_EQ(kInternalProcessDatums, snapshot.size()); 282 ASSERT_EQ(kInternalProcessDatums, snapshot.size());
623 process_data.Set("raw", "foo", 3); 283 process_data.Set("raw", "foo", 3);
624 process_data.SetString("string", "bar"); 284 process_data.SetString("string", "bar");
625 process_data.SetChar("char", '9'); 285 process_data.SetChar("char", '9');
626 process_data.SetInt("int", -9999); 286 process_data.SetInt("int", -9999);
627 process_data.SetUint("uint", 9999); 287 process_data.SetUint("uint", 9999);
628 process_data.SetBool("bool", true); 288 process_data.SetBool("bool", true);
629 process_data.SetReference("ref", string1, strlen(string1)); 289 process_data.SetReference("ref", string1, strlen(string1));
630 process_data.SetStringReference("sref", string2); 290 process_data.SetStringReference("sref", string2);
631 291
632 // Collect the stability report. 292 // Collect the stability report.
633 MockCrashReportDatabase crash_db;
634 PostmortemReportCollector collector(kProductName, kVersionNumber,
635 kChannelName, &crash_db, nullptr);
636 StabilityReport report; 293 StabilityReport report;
637 ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); 294 ASSERT_EQ(SUCCESS, Extract(debug_file_path(), &report));
638 295
639 // Validate the report's user data. 296 // Validate the report's user data.
640 const auto& collected_data = report.global_data(); 297 const auto& collected_data = report.global_data();
641 ASSERT_EQ(kInternalProcessDatums + 12U, collected_data.size()); 298 ASSERT_EQ(kInternalProcessDatums + 8U, collected_data.size());
642 299
643 ASSERT_TRUE(base::ContainsKey(collected_data, "raw")); 300 ASSERT_TRUE(base::ContainsKey(collected_data, "raw"));
644 EXPECT_EQ(TypedValue::kBytesValue, collected_data.at("raw").value_case()); 301 EXPECT_EQ(TypedValue::kBytesValue, collected_data.at("raw").value_case());
645 EXPECT_EQ("foo", collected_data.at("raw").bytes_value()); 302 EXPECT_EQ("foo", collected_data.at("raw").bytes_value());
646 303
647 ASSERT_TRUE(base::ContainsKey(collected_data, "string")); 304 ASSERT_TRUE(base::ContainsKey(collected_data, "string"));
648 EXPECT_EQ(TypedValue::kStringValue, collected_data.at("string").value_case()); 305 EXPECT_EQ(TypedValue::kStringValue, collected_data.at("string").value_case());
649 EXPECT_EQ("bar", collected_data.at("string").string_value()); 306 EXPECT_EQ("bar", collected_data.at("string").string_value());
650 307
651 ASSERT_TRUE(base::ContainsKey(collected_data, "char")); 308 ASSERT_TRUE(base::ContainsKey(collected_data, "char"));
(...skipping 18 matching lines...) Expand all
670 EXPECT_EQ(reinterpret_cast<uintptr_t>(string1), ref.address()); 327 EXPECT_EQ(reinterpret_cast<uintptr_t>(string1), ref.address());
671 EXPECT_EQ(strlen(string1), static_cast<uint64_t>(ref.size())); 328 EXPECT_EQ(strlen(string1), static_cast<uint64_t>(ref.size()));
672 329
673 ASSERT_TRUE(base::ContainsKey(collected_data, "sref")); 330 ASSERT_TRUE(base::ContainsKey(collected_data, "sref"));
674 EXPECT_EQ(TypedValue::kStringReference, 331 EXPECT_EQ(TypedValue::kStringReference,
675 collected_data.at("sref").value_case()); 332 collected_data.at("sref").value_case());
676 const TypedValue::Reference& sref = 333 const TypedValue::Reference& sref =
677 collected_data.at("sref").string_reference(); 334 collected_data.at("sref").string_reference();
678 EXPECT_EQ(reinterpret_cast<uintptr_t>(string2), sref.address()); 335 EXPECT_EQ(reinterpret_cast<uintptr_t>(string2), sref.address());
679 EXPECT_EQ(strlen(string2), static_cast<uint64_t>(sref.size())); 336 EXPECT_EQ(strlen(string2), static_cast<uint64_t>(sref.size()));
680
681 // Reporter's version details.
682 ContainsKeyValue(collected_data, kStabilityReporterProduct, kProductName);
683 ContainsKeyValue(collected_data, kStabilityReporterChannel, kChannelName);
684 #if defined(ARCH_CPU_X86)
685 ContainsKeyValue(collected_data, kStabilityReporterPlatform, "Win32");
686 #elif defined(ARCH_CPU_X86_64)
687 ContainsKeyValue(collected_data, kStabilityReporterPlatform, "Win64");
688 #endif
689 ContainsKeyValue(collected_data, kStabilityReporterVersion, kVersionNumber);
690 } 337 }
691 338
692 TEST_F(PostmortemReportCollectorCollectionFromGlobalTrackerTest, 339 TEST_F(StabilityReportExtractorTest, FieldTrialCollection) {
693 FieldTrialCollection) {
694 // Record some data. 340 // Record some data.
695 GlobalActivityTracker::CreateWithFile(debug_file_path(), kMemorySize, 0ULL, 341 GlobalActivityTracker::CreateWithFile(debug_file_path(), kMemorySize, 0ULL,
696 "", 3); 342 "", 3);
697 ActivityUserData& process_data = GlobalActivityTracker::Get()->process_data(); 343 ActivityUserData& process_data = GlobalActivityTracker::Get()->process_data();
698 process_data.SetString("string", "bar"); 344 process_data.SetString("string", "bar");
699 process_data.SetString("FieldTrial.string", "bar"); 345 process_data.SetString("FieldTrial.string", "bar");
700 process_data.SetString("FieldTrial.foo", "bar"); 346 process_data.SetString("FieldTrial.foo", "bar");
701 347
702 // Collect the stability report. 348 // Collect the stability report.
703 MockCrashReportDatabase crash_db;
704 PostmortemReportCollector collector(kProductName, kVersionNumber,
705 kChannelName, &crash_db, nullptr);
706 StabilityReport report; 349 StabilityReport report;
707 ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); 350 ASSERT_EQ(SUCCESS, Extract(debug_file_path(), &report));
708 351
709 // Validate the report's experiment and global data. 352 // Validate the report's experiment and global data.
710 ASSERT_EQ(2, report.field_trials_size()); 353 ASSERT_EQ(2, report.field_trials_size());
711 EXPECT_NE(0U, report.field_trials(0).name_id()); 354 EXPECT_NE(0U, report.field_trials(0).name_id());
712 EXPECT_NE(0U, report.field_trials(0).group_id()); 355 EXPECT_NE(0U, report.field_trials(0).group_id());
713 EXPECT_NE(0U, report.field_trials(1).name_id()); 356 EXPECT_NE(0U, report.field_trials(1).name_id());
714 EXPECT_EQ(report.field_trials(0).group_id(), 357 EXPECT_EQ(report.field_trials(0).group_id(),
715 report.field_trials(1).group_id()); 358 report.field_trials(1).group_id());
716 359
717 // Expect 5 key/value pairs (including product details). 360 // Expect 1 key/value pair.
718 const auto& collected_data = report.global_data(); 361 const auto& collected_data = report.global_data();
719 EXPECT_EQ(kInternalProcessDatums + 5U, collected_data.size()); 362 EXPECT_EQ(kInternalProcessDatums + 1U, collected_data.size());
720 EXPECT_TRUE(base::ContainsKey(collected_data, "string")); 363 EXPECT_TRUE(base::ContainsKey(collected_data, "string"));
721 } 364 }
722 365
723 TEST_F(PostmortemReportCollectorCollectionFromGlobalTrackerTest, 366 TEST_F(StabilityReportExtractorTest, ModuleCollection) {
724 ModuleCollection) {
725 // Record some module information. 367 // Record some module information.
726 GlobalActivityTracker::CreateWithFile(debug_file_path(), kMemorySize, 0ULL, 368 GlobalActivityTracker::CreateWithFile(debug_file_path(), kMemorySize, 0ULL,
727 "", 3); 369 "", 3);
728 370
729 base::debug::GlobalActivityTracker::ModuleInfo module_info = {}; 371 base::debug::GlobalActivityTracker::ModuleInfo module_info = {};
730 module_info.is_loaded = true; 372 module_info.is_loaded = true;
731 module_info.address = 0x123456; 373 module_info.address = 0x123456;
732 module_info.load_time = 1111LL; 374 module_info.load_time = 1111LL;
733 module_info.size = 0x2d000; 375 module_info.size = 0x2d000;
734 module_info.timestamp = 0xCAFECAFE; 376 module_info.timestamp = 0xCAFECAFE;
735 module_info.age = 1; 377 module_info.age = 1;
736 crashpad::UUID debug_uuid; 378 crashpad::UUID debug_uuid;
737 debug_uuid.InitializeFromString("11223344-5566-7788-abcd-0123456789ab"); 379 debug_uuid.InitializeFromString("11223344-5566-7788-abcd-0123456789ab");
738 memcpy(module_info.identifier, &debug_uuid, sizeof(module_info.identifier)); 380 memcpy(module_info.identifier, &debug_uuid, sizeof(module_info.identifier));
739 module_info.file = "foo"; 381 module_info.file = "foo";
740 module_info.debug_file = "bar"; 382 module_info.debug_file = "bar";
741 383
742 GlobalActivityTracker::Get()->RecordModuleInfo(module_info); 384 GlobalActivityTracker::Get()->RecordModuleInfo(module_info);
743 385
744 // Collect the stability report. 386 // Collect the stability report.
745 MockCrashReportDatabase crash_db;
746 PostmortemReportCollector collector(kProductName, kVersionNumber,
747 kChannelName, &crash_db, nullptr);
748 StabilityReport report; 387 StabilityReport report;
749 ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report)); 388 ASSERT_EQ(SUCCESS, Extract(debug_file_path(), &report));
750 389
751 // Validate the report's modules content. 390 // Validate the report's modules content.
752 ASSERT_EQ(1, report.process_states_size()); 391 ASSERT_EQ(1, report.process_states_size());
753 const ProcessState& process_state = report.process_states(0); 392 const ProcessState& process_state = report.process_states(0);
754 ASSERT_EQ(1, process_state.modules_size()); 393 ASSERT_EQ(1, process_state.modules_size());
755 394
756 const CodeModule collected_module = process_state.modules(0); 395 const CodeModule collected_module = process_state.modules(0);
757 EXPECT_EQ(module_info.address, 396 EXPECT_EQ(module_info.address,
758 static_cast<uintptr_t>(collected_module.base_address())); 397 static_cast<uintptr_t>(collected_module.base_address()));
759 EXPECT_EQ(module_info.size, static_cast<size_t>(collected_module.size())); 398 EXPECT_EQ(module_info.size, static_cast<size_t>(collected_module.size()));
760 EXPECT_EQ(module_info.file, collected_module.code_file()); 399 EXPECT_EQ(module_info.file, collected_module.code_file());
761 EXPECT_EQ("CAFECAFE2d000", collected_module.code_identifier()); 400 EXPECT_EQ("CAFECAFE2d000", collected_module.code_identifier());
762 EXPECT_EQ(module_info.debug_file, collected_module.debug_file()); 401 EXPECT_EQ(module_info.debug_file, collected_module.debug_file());
763 EXPECT_EQ("1122334455667788ABCD0123456789AB1", 402 EXPECT_EQ("1122334455667788ABCD0123456789AB1",
764 collected_module.debug_identifier()); 403 collected_module.debug_identifier());
765 EXPECT_EQ("", collected_module.version()); 404 EXPECT_EQ("", collected_module.version());
766 EXPECT_EQ(0LL, collected_module.shrink_down_delta()); 405 EXPECT_EQ(0LL, collected_module.shrink_down_delta());
767 EXPECT_EQ(!module_info.is_loaded, collected_module.is_unloaded()); 406 EXPECT_EQ(!module_info.is_loaded, collected_module.is_unloaded());
768 } 407 }
769 408
770 TEST_F(PostmortemReportCollectorCollectionFromGlobalTrackerTest,
771 SystemStateTest) {
772 // Setup.
773 GlobalActivityTracker::CreateWithFile(debug_file_path(), kMemorySize, 0ULL,
774 "", 3);
775 ActivityUserData& process_data = GlobalActivityTracker::Get()->process_data();
776 process_data.SetInt(kStabilityStartTimestamp, 12345LL);
777
778 // Collect.
779 MockSystemSessionAnalyzer analyzer;
780 EXPECT_CALL(analyzer,
781 IsSessionUnclean(base::Time::FromInternalValue(12345LL)))
782 .Times(1)
783 .WillOnce(Return(SystemSessionAnalyzer::CLEAN));
784 MockCrashReportDatabase crash_db;
785 PostmortemReportCollector collector(kProductName, kVersionNumber,
786 kChannelName, &crash_db, &analyzer);
787 StabilityReport report;
788 ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report));
789
790 // Validate the report.
791 ASSERT_EQ(SystemState::CLEAN, report.system_state().session_state());
792 }
793
794 } // namespace browser_watcher 409 } // namespace browser_watcher
OLDNEW
« no previous file with comments | « components/browser_watcher/postmortem_report_collector_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698