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

Side by Side Diff: client/crash_report_database_test.cc

Issue 842513002: Create CrashReportDatabase interface, a test, and a Mac implementation. (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Created 5 years, 11 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 | « client/crash_report_database_mac.mm ('k') | util/mac/xattr.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 The Crashpad Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "client/crash_report_database.h"
16
17 #include <sys/stat.h>
18
19 #include "gtest/gtest.h"
20 #include "util/file/file_io.h"
21 #include "util/test/scoped_temp_dir.h"
22
23 namespace crashpad {
24 namespace test {
25 namespace {
26
27 bool FileExistsAtPath(const base::FilePath& path) {
28 #if defined(OS_POSIX)
29 struct stat st;
30 return lstat(path.value().c_str(), &st) == 0;
31 #else
32 #error "Not implemented"
33 #endif
34 }
35
36 void CreateFile(const base::FilePath& path) {
37 FileHandle handle = LoggingOpenFileForWrite(path,
38 FileWriteMode::kCreateOrFail,
39 FilePermissions::kWorldReadable);
40 ASSERT_GE(handle, 0);
41 ASSERT_TRUE(
42 LoggingWriteFile(handle, path.value().c_str(), path.value().length()));
43 ASSERT_TRUE(LoggingCloseFile(handle));
44 }
45
46 class CrashReportDatabaseTest : public testing::Test {
47 protected:
48 // testing::Test:
49 void SetUp() override {
50 db_ = CrashReportDatabase::Initialize(path());
51 ASSERT_TRUE(db_.get());
52 }
53
54 void ResetDatabase() {
55 db_.reset();
56 }
57
58 CrashReportDatabase* db() const { return db_.get(); }
59 const base::FilePath& path() const { return temp_dir_.path(); }
60
61 void CreateCrashReport(CrashReportDatabase::Report* report) {
62 EXPECT_EQ(CrashReportDatabase::kNoError,
63 db_->PrepareNewCrashReport(report));
64 ExpectPreparedCrashReport(*report);
65 CreateFile(report->file_path);
66 ASSERT_TRUE(FileExistsAtPath(report->file_path));
67 EXPECT_EQ(CrashReportDatabase::kNoError,
68 db_->FinishedWritingCrashReport(report->uuid));
69 }
70
71 void ExpectPreparedCrashReport(const CrashReportDatabase::Report& report) {
72 EXPECT_NE(UUID(), report.uuid);
73 EXPECT_FALSE(report.file_path.empty());
74 EXPECT_FALSE(FileExistsAtPath(report.file_path));
75 EXPECT_TRUE(report.id.empty());
76 EXPECT_FALSE(report.uploaded);
77 EXPECT_EQ(0, report.last_upload_attempt_time);
78 EXPECT_EQ(0, report.upload_attempts);
79 }
80
81 private:
82 ScopedTempDir temp_dir_;
83 scoped_ptr<CrashReportDatabase> db_;
84 };
85
86 TEST_F(CrashReportDatabaseTest, Initialize) {
87 // Initialize the database for the first time, creating it.
88 EXPECT_TRUE(db());
89
90 // Close and reopen the database at the same path.
91 ResetDatabase();
92 EXPECT_FALSE(db());
93 auto db = CrashReportDatabase::Initialize(path());
94 EXPECT_TRUE(db.get());
95
96 std::vector<const CrashReportDatabase::Report> reports;
97 EXPECT_EQ(CrashReportDatabase::kNoError, db->GetNotUploadedReports(&reports));
98 EXPECT_TRUE(reports.empty());
99 EXPECT_EQ(CrashReportDatabase::kNoError, db->GetUploadedReports(&reports));
100 EXPECT_TRUE(reports.empty());
101 }
102
103 TEST_F(CrashReportDatabaseTest, PrepareNewCrashReport) {
104 CrashReportDatabase::Report report;
105 EXPECT_EQ(CrashReportDatabase::kNoError,
106 db()->PrepareNewCrashReport(&report));
107 ExpectPreparedCrashReport(report);
108
109 CrashReportDatabase::Report query;
110 EXPECT_EQ(CrashReportDatabase::kReportNotFound,
111 db()->LookUpCrashReport(report.uuid, &query));
112 }
113
114 TEST_F(CrashReportDatabaseTest, FinishedWritingCrashReport) {
115 CrashReportDatabase::Report report;
116 EXPECT_EQ(CrashReportDatabase::kNoError,
117 db()->PrepareNewCrashReport(&report));
118 ExpectPreparedCrashReport(report);
119
120 CrashReportDatabase::Report query;
121 EXPECT_EQ(CrashReportDatabase::kReportNotFound,
122 db()->LookUpCrashReport(report.uuid, &query));
123
124 CreateFile(report.file_path);
125
126 EXPECT_EQ(CrashReportDatabase::kNoError,
127 db()->FinishedWritingCrashReport(report.uuid));
128 EXPECT_EQ(CrashReportDatabase::kNoError,
129 db()->LookUpCrashReport(report.uuid, &query));
130 EXPECT_EQ(report.uuid, query.uuid);
131 EXPECT_TRUE(report.id.empty());
132 EXPECT_FALSE(report.uploaded);
133 EXPECT_EQ(0, report.last_upload_attempt_time);
134 EXPECT_EQ(0, report.upload_attempts);
135
136 std::vector<const CrashReportDatabase::Report> reports;
137 EXPECT_EQ(CrashReportDatabase::kNoError,
138 db()->GetNotUploadedReports(&reports));
139 ASSERT_EQ(1u, reports.size());
140 EXPECT_EQ(report.uuid, reports[0].uuid);
141
142 reports.clear();
143 EXPECT_EQ(CrashReportDatabase::kNoError,
144 db()->GetUploadedReports(&reports));
145 EXPECT_TRUE(reports.empty());
146 }
147
148 TEST_F(CrashReportDatabaseTest, LookUpCrashReport) {
149 UUID uuid;
150
151 {
152 CrashReportDatabase::Report report;
153 CreateCrashReport(&report);
154 uuid = report.uuid;
155 }
156
157 {
158 CrashReportDatabase::Report report;
159 EXPECT_EQ(CrashReportDatabase::kNoError,
160 db()->LookUpCrashReport(uuid, &report));
161 EXPECT_EQ(uuid, report.uuid);
162 EXPECT_NE(std::string::npos, report.file_path.value().find(path().value()));
163 EXPECT_EQ("", report.id);
164 EXPECT_FALSE(report.uploaded);
165 EXPECT_EQ(0, report.last_upload_attempt_time);
166 EXPECT_EQ(0, report.upload_attempts);
167 }
168
169 EXPECT_EQ(CrashReportDatabase::kNoError,
170 db()->RecordUploadAttempt(uuid, true, "test"));
171
172 {
173 CrashReportDatabase::Report report;
174 EXPECT_EQ(CrashReportDatabase::kNoError,
175 db()->LookUpCrashReport(uuid, &report));
176 EXPECT_EQ(uuid, report.uuid);
177 EXPECT_NE(std::string::npos, report.file_path.value().find(path().value()));
178 EXPECT_EQ("test", report.id);
179 EXPECT_TRUE(report.uploaded);
180 EXPECT_NE(0, report.last_upload_attempt_time);
181 EXPECT_EQ(1, report.upload_attempts);
182 }
183 }
184
185 TEST_F(CrashReportDatabaseTest, FinishedWritingCrashReportError) {
186 CrashReportDatabase::Report report;
187 EXPECT_EQ(CrashReportDatabase::kNoError,
188 db()->PrepareNewCrashReport(&report));
189 ExpectPreparedCrashReport(report);
190
191 EXPECT_EQ(CrashReportDatabase::kReportNotFound,
192 db()->FinishedWritingCrashReport(report.uuid));
193 }
194
195 TEST_F(CrashReportDatabaseTest, RecordUploadAttempt) {
196 std::vector<CrashReportDatabase::Report> reports(3);
197 CreateCrashReport(&reports[0]);
198 CreateCrashReport(&reports[1]);
199 CreateCrashReport(&reports[2]);
200
201 // Record two attempts: one successful, one not.
202 EXPECT_EQ(CrashReportDatabase::kNoError,
203 db()->RecordUploadAttempt(reports[1].uuid, false, ""));
204 EXPECT_EQ(CrashReportDatabase::kNoError,
205 db()->RecordUploadAttempt(reports[2].uuid, true, "abc123"));
206
207 std::vector<CrashReportDatabase::Report> query(3);
208
209 EXPECT_EQ(CrashReportDatabase::kNoError,
210 db()->LookUpCrashReport(reports[0].uuid, &query[0]));
211 EXPECT_EQ(CrashReportDatabase::kNoError,
212 db()->LookUpCrashReport(reports[1].uuid, &query[1]));
213 EXPECT_EQ(CrashReportDatabase::kNoError,
214 db()->LookUpCrashReport(reports[2].uuid, &query[2]));
215
216 EXPECT_EQ("", query[0].id);
217 EXPECT_EQ("", query[1].id);
218 EXPECT_EQ("abc123", query[2].id);
219
220 EXPECT_FALSE(query[0].uploaded);
221 EXPECT_FALSE(query[1].uploaded);
222 EXPECT_TRUE(query[2].uploaded);
223
224 EXPECT_EQ(0, query[0].last_upload_attempt_time);
225 EXPECT_NE(0, query[1].last_upload_attempt_time);
226 EXPECT_NE(0, query[2].last_upload_attempt_time);
227
228 EXPECT_EQ(0, query[0].upload_attempts);
229 EXPECT_EQ(1, query[1].upload_attempts);
230 EXPECT_EQ(1, query[2].upload_attempts);
231
232 // Attempt to upload and fail again.
233 EXPECT_EQ(CrashReportDatabase::kNoError,
234 db()->RecordUploadAttempt(reports[1].uuid, false, ""));
235
236 time_t report_2_upload_time = query[2].last_upload_attempt_time;
237
238 EXPECT_EQ(CrashReportDatabase::kNoError,
239 db()->LookUpCrashReport(reports[0].uuid, &query[0]));
240 EXPECT_EQ(CrashReportDatabase::kNoError,
241 db()->LookUpCrashReport(reports[1].uuid, &query[1]));
242 EXPECT_EQ(CrashReportDatabase::kNoError,
243 db()->LookUpCrashReport(reports[2].uuid, &query[2]));
244
245 EXPECT_FALSE(query[0].uploaded);
246 EXPECT_FALSE(query[1].uploaded);
247 EXPECT_TRUE(query[2].uploaded);
248
249 EXPECT_EQ(0, query[0].last_upload_attempt_time);
250 EXPECT_GE(query[1].last_upload_attempt_time, report_2_upload_time);
251 EXPECT_EQ(report_2_upload_time, query[2].last_upload_attempt_time);
252
253 EXPECT_EQ(0, query[0].upload_attempts);
254 EXPECT_EQ(2, query[1].upload_attempts);
255 EXPECT_EQ(1, query[2].upload_attempts);
256
257 // Third time's the charm: upload and succeed.
258 EXPECT_EQ(CrashReportDatabase::kNoError,
259 db()->RecordUploadAttempt(reports[1].uuid, true, "666hahaha"));
260
261 time_t report_1_upload_time = query[1].last_upload_attempt_time;
262
263 EXPECT_EQ(CrashReportDatabase::kNoError,
264 db()->LookUpCrashReport(reports[0].uuid, &query[0]));
265 EXPECT_EQ(CrashReportDatabase::kNoError,
266 db()->LookUpCrashReport(reports[1].uuid, &query[1]));
267 EXPECT_EQ(CrashReportDatabase::kNoError,
268 db()->LookUpCrashReport(reports[2].uuid, &query[2]));
269
270 EXPECT_FALSE(query[0].uploaded);
271 EXPECT_TRUE(query[1].uploaded);
272 EXPECT_TRUE(query[2].uploaded);
273
274 EXPECT_EQ(0, query[0].last_upload_attempt_time);
275 EXPECT_GE(query[1].last_upload_attempt_time, report_1_upload_time);
276 EXPECT_EQ(report_2_upload_time, query[2].last_upload_attempt_time);
277
278 EXPECT_EQ(0, query[0].upload_attempts);
279 EXPECT_EQ(3, query[1].upload_attempts);
280 EXPECT_EQ(1, query[2].upload_attempts);
281 }
282
283 // This test covers both query functions since they are related.
284 TEST_F(CrashReportDatabaseTest, GetUploadedAndNotUploadedReports) {
285 std::vector<CrashReportDatabase::Report> reports(5);
286 CreateCrashReport(&reports[0]);
287 CreateCrashReport(&reports[1]);
288 CreateCrashReport(&reports[2]);
289 CreateCrashReport(&reports[3]);
290 CreateCrashReport(&reports[4]);
291
292 const UUID& report_0_uuid = reports[0].uuid;
293 const UUID& report_1_uuid = reports[1].uuid;
294 const UUID& report_2_uuid = reports[2].uuid;
295 const UUID& report_3_uuid = reports[3].uuid;
296 const UUID& report_4_uuid = reports[4].uuid;
297
298 std::vector<const CrashReportDatabase::Report> not_uploaded;
299 EXPECT_EQ(CrashReportDatabase::kNoError,
300 db()->GetNotUploadedReports(&not_uploaded));
301
302 std::vector<const CrashReportDatabase::Report> uploaded;
303 EXPECT_EQ(CrashReportDatabase::kNoError,
304 db()->GetUploadedReports(&uploaded));
305
306 EXPECT_EQ(reports.size(), not_uploaded.size());
307 EXPECT_EQ(0u, uploaded.size());
308
309 // Upload one report successfully.
310 EXPECT_EQ(CrashReportDatabase::kNoError,
311 db()->RecordUploadAttempt(report_1_uuid, true, "report1"));
312
313 not_uploaded.clear();
314 EXPECT_EQ(CrashReportDatabase::kNoError,
315 db()->GetNotUploadedReports(&not_uploaded));
316 uploaded.clear();
317 EXPECT_EQ(CrashReportDatabase::kNoError,
318 db()->GetUploadedReports(&uploaded));
319
320 EXPECT_EQ(4u, not_uploaded.size());
321 ASSERT_EQ(1u, uploaded.size());
322
323 for (const auto& report : not_uploaded)
324 EXPECT_NE(report_1_uuid, report.uuid);
325 EXPECT_EQ(report_1_uuid, uploaded[0].uuid);
326 EXPECT_EQ("report1", uploaded[0].id);
327 EXPECT_EQ(true, uploaded[0].uploaded);
328 EXPECT_GT(uploaded[0].last_upload_attempt_time, 0);
329 EXPECT_EQ(1, uploaded[0].upload_attempts);
330
331 const CrashReportDatabase::Report uploaded_report_1 = uploaded[0];
332
333 // Fail to upload one report.
Robert Sesek 2015/01/06 23:40:29 After this, things could be more thorough. I didn'
334 EXPECT_EQ(CrashReportDatabase::kNoError,
335 db()->RecordUploadAttempt(report_2_uuid, false, ""));
336
337 not_uploaded.clear();
338 EXPECT_EQ(CrashReportDatabase::kNoError,
339 db()->GetNotUploadedReports(&not_uploaded));
340 uploaded.clear();
341 EXPECT_EQ(CrashReportDatabase::kNoError,
342 db()->GetUploadedReports(&uploaded));
343
344 EXPECT_EQ(4u, not_uploaded.size());
345 ASSERT_EQ(1u, uploaded.size());
346
347 for (const auto& report : not_uploaded) {
348 if (report.upload_attempts != 0) {
349 EXPECT_EQ(report_2_uuid, report.uuid);
350 EXPECT_GT(report.last_upload_attempt_time, 0);
351 EXPECT_FALSE(report.uploaded);
352 EXPECT_TRUE(report.id.empty());
353 }
354 }
355
356 // Upload a second report.
357 EXPECT_EQ(CrashReportDatabase::kNoError,
358 db()->RecordUploadAttempt(report_4_uuid, true, "report_4"));
359
360 not_uploaded.clear();
361 EXPECT_EQ(CrashReportDatabase::kNoError,
362 db()->GetNotUploadedReports(&not_uploaded));
363 uploaded.clear();
364 EXPECT_EQ(CrashReportDatabase::kNoError,
365 db()->GetUploadedReports(&uploaded));
366
367 EXPECT_EQ(3u, not_uploaded.size());
368 ASSERT_EQ(2u, uploaded.size());
369
370 // Succeed the failed report.
371 EXPECT_EQ(CrashReportDatabase::kNoError,
372 db()->RecordUploadAttempt(report_2_uuid, true, "report 2"));
373
374 not_uploaded.clear();
375 EXPECT_EQ(CrashReportDatabase::kNoError,
376 db()->GetNotUploadedReports(&not_uploaded));
377 uploaded.clear();
378 EXPECT_EQ(CrashReportDatabase::kNoError,
379 db()->GetUploadedReports(&uploaded));
380
381 EXPECT_EQ(2u, not_uploaded.size());
382 ASSERT_EQ(3u, uploaded.size());
383
384 for (const auto& report : not_uploaded) {
385 EXPECT_TRUE(report.uuid == report_0_uuid ||
386 report.uuid == report_3_uuid);
387 }
388 }
389
390 } // namespace
391 } // namespace test
392 } // namespace crashpad
OLDNEW
« no previous file with comments | « client/crash_report_database_mac.mm ('k') | util/mac/xattr.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698