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 "build/build_config.h"
18 #include "client/settings.h"
19 #include "gtest/gtest.h"
20 #include "test/errors.h"
21 #include "test/file.h"
22 #include "test/filesystem.h"
23 #include "test/scoped_temp_dir.h"
24 #include "util/file/file_io.h"
25 #include "util/file/filesystem.h"
26 
27 namespace crashpad {
28 namespace test {
29 namespace {
30 
31 class CrashReportDatabaseTest : public testing::Test {
32  public:
CrashReportDatabaseTest()33   CrashReportDatabaseTest() {}
34 
35  protected:
36   // testing::Test:
SetUp()37   void SetUp() override {
38     db_ = CrashReportDatabase::Initialize(path());
39     ASSERT_TRUE(db_);
40   }
41 
ResetDatabase()42   void ResetDatabase() { db_.reset(); }
43 
db()44   CrashReportDatabase* db() { return db_.get(); }
path() const45   base::FilePath path() const {
46     return temp_dir_.path().Append(FILE_PATH_LITERAL("crashpad_test_database"));
47   }
48 
CreateCrashReport(CrashReportDatabase::Report * report)49   void CreateCrashReport(CrashReportDatabase::Report* report) {
50     std::unique_ptr<CrashReportDatabase::NewReport> new_report;
51     ASSERT_EQ(db_->PrepareNewCrashReport(&new_report),
52               CrashReportDatabase::kNoError);
53     static constexpr char kTest[] = "test";
54     ASSERT_TRUE(new_report->Writer()->Write(kTest, sizeof(kTest)));
55 
56     char contents[sizeof(kTest)];
57     FileReaderInterface* reader = new_report->Reader();
58     ASSERT_TRUE(reader->ReadExactly(contents, sizeof(contents)));
59     EXPECT_EQ(memcmp(contents, kTest, sizeof(contents)), 0);
60     EXPECT_EQ(reader->ReadExactly(contents, 1), 0);
61 
62     UUID uuid;
63     EXPECT_EQ(db_->FinishedWritingCrashReport(std::move(new_report), &uuid),
64               CrashReportDatabase::kNoError);
65 
66     EXPECT_EQ(db_->LookUpCrashReport(uuid, report),
67               CrashReportDatabase::kNoError);
68     ExpectPreparedCrashReport(*report);
69   }
70 
UploadReport(const UUID & uuid,bool successful,const std::string & id)71   void UploadReport(const UUID& uuid, bool successful, const std::string& id) {
72     Settings* const settings = db_->GetSettings();
73     ASSERT_TRUE(settings);
74     time_t times[2];
75     ASSERT_TRUE(settings->GetLastUploadAttemptTime(&times[0]));
76 
77     std::unique_ptr<const CrashReportDatabase::UploadReport> report;
78     ASSERT_EQ(db_->GetReportForUploading(uuid, &report),
79               CrashReportDatabase::kNoError);
80     EXPECT_NE(report->uuid, UUID());
81     EXPECT_FALSE(report->file_path.empty());
82     EXPECT_TRUE(FileExists(report->file_path)) << report->file_path.value();
83     EXPECT_GT(report->creation_time, 0);
84     if (successful) {
85       EXPECT_EQ(db_->RecordUploadComplete(std::move(report), id),
86                 CrashReportDatabase::kNoError);
87     } else {
88       report.reset();
89     }
90 
91     ASSERT_TRUE(settings->GetLastUploadAttemptTime(&times[1]));
92     EXPECT_NE(times[1], 0);
93     EXPECT_GE(times[1], times[0]);
94   }
95 
ExpectPreparedCrashReport(const CrashReportDatabase::Report & report)96   void ExpectPreparedCrashReport(const CrashReportDatabase::Report& report) {
97     EXPECT_NE(report.uuid, UUID());
98     EXPECT_FALSE(report.file_path.empty());
99     EXPECT_TRUE(FileExists(report.file_path)) << report.file_path.value();
100     EXPECT_TRUE(report.id.empty());
101     EXPECT_GT(report.creation_time, 0);
102     EXPECT_FALSE(report.uploaded);
103     EXPECT_EQ(report.last_upload_attempt_time, 0);
104     EXPECT_EQ(report.upload_attempts, 0);
105     EXPECT_FALSE(report.upload_explicitly_requested);
106     EXPECT_GE(report.total_size, 0u);
107   }
108 
RelocateDatabase()109   void RelocateDatabase() {
110     ResetDatabase();
111     temp_dir_.Rename();
112     SetUp();
113   }
114 
RequestUpload(const UUID & uuid)115   CrashReportDatabase::OperationStatus RequestUpload(const UUID& uuid) {
116     CrashReportDatabase::OperationStatus os = db()->RequestUpload(uuid);
117 
118     CrashReportDatabase::Report report;
119     EXPECT_EQ(db_->LookUpCrashReport(uuid, &report),
120               CrashReportDatabase::kNoError);
121 
122     return os;
123   }
124 
125  private:
126   ScopedTempDir temp_dir_;
127   std::unique_ptr<CrashReportDatabase> db_;
128 
129   DISALLOW_COPY_AND_ASSIGN(CrashReportDatabaseTest);
130 };
131 
TEST_F(CrashReportDatabaseTest,Initialize)132 TEST_F(CrashReportDatabaseTest, Initialize) {
133   // Initialize the database for the first time, creating it.
134   ASSERT_TRUE(db());
135 
136   Settings* settings = db()->GetSettings();
137 
138   UUID client_ids[3];
139   ASSERT_TRUE(settings->GetClientID(&client_ids[0]));
140   EXPECT_NE(client_ids[0], UUID());
141 
142   time_t last_upload_attempt_time;
143   ASSERT_TRUE(settings->GetLastUploadAttemptTime(&last_upload_attempt_time));
144   EXPECT_EQ(last_upload_attempt_time, 0);
145 
146   // Close and reopen the database at the same path.
147   ResetDatabase();
148   EXPECT_FALSE(db());
149   auto db = CrashReportDatabase::InitializeWithoutCreating(path());
150   ASSERT_TRUE(db);
151 
152   settings = db->GetSettings();
153 
154   ASSERT_TRUE(settings->GetClientID(&client_ids[1]));
155   EXPECT_EQ(client_ids[1], client_ids[0]);
156 
157   ASSERT_TRUE(settings->GetLastUploadAttemptTime(&last_upload_attempt_time));
158   EXPECT_EQ(last_upload_attempt_time, 0);
159 
160   // Check that the database can also be opened by the method that is permitted
161   // to create it.
162   db = CrashReportDatabase::Initialize(path());
163   ASSERT_TRUE(db);
164 
165   settings = db->GetSettings();
166 
167   ASSERT_TRUE(settings->GetClientID(&client_ids[2]));
168   EXPECT_EQ(client_ids[2], client_ids[0]);
169 
170   ASSERT_TRUE(settings->GetLastUploadAttemptTime(&last_upload_attempt_time));
171   EXPECT_EQ(last_upload_attempt_time, 0);
172 
173   std::vector<CrashReportDatabase::Report> reports;
174   EXPECT_EQ(db->GetPendingReports(&reports), CrashReportDatabase::kNoError);
175   EXPECT_TRUE(reports.empty());
176   reports.clear();
177   EXPECT_EQ(db->GetCompletedReports(&reports), CrashReportDatabase::kNoError);
178   EXPECT_TRUE(reports.empty());
179 
180   // InitializeWithoutCreating() shouldn’t create a nonexistent database.
181   base::FilePath non_database_path =
182       path().DirName().Append(FILE_PATH_LITERAL("not_a_database"));
183   db = CrashReportDatabase::InitializeWithoutCreating(non_database_path);
184   EXPECT_FALSE(db);
185 }
186 
TEST_F(CrashReportDatabaseTest,NewCrashReport)187 TEST_F(CrashReportDatabaseTest, NewCrashReport) {
188   std::unique_ptr<CrashReportDatabase::NewReport> new_report;
189   EXPECT_EQ(db()->PrepareNewCrashReport(&new_report),
190             CrashReportDatabase::kNoError);
191   UUID expect_uuid = new_report->ReportID();
192   UUID uuid;
193   EXPECT_EQ(db()->FinishedWritingCrashReport(std::move(new_report), &uuid),
194             CrashReportDatabase::kNoError);
195   EXPECT_EQ(uuid, expect_uuid);
196 
197   CrashReportDatabase::Report report;
198   EXPECT_EQ(db()->LookUpCrashReport(uuid, &report),
199             CrashReportDatabase::kNoError);
200   ExpectPreparedCrashReport(report);
201 
202   std::vector<CrashReportDatabase::Report> reports;
203   EXPECT_EQ(db()->GetPendingReports(&reports), CrashReportDatabase::kNoError);
204   ASSERT_EQ(reports.size(), 1u);
205   EXPECT_EQ(reports[0].uuid, report.uuid);
206 
207   reports.clear();
208   EXPECT_EQ(db()->GetCompletedReports(&reports), CrashReportDatabase::kNoError);
209   EXPECT_TRUE(reports.empty());
210 }
211 
TEST_F(CrashReportDatabaseTest,LookUpCrashReport)212 TEST_F(CrashReportDatabaseTest, LookUpCrashReport) {
213   UUID uuid;
214 
215   {
216     CrashReportDatabase::Report report;
217     CreateCrashReport(&report);
218     uuid = report.uuid;
219   }
220 
221   {
222     CrashReportDatabase::Report report;
223     EXPECT_EQ(db()->LookUpCrashReport(uuid, &report),
224               CrashReportDatabase::kNoError);
225     EXPECT_EQ(report.uuid, uuid);
226     EXPECT_NE(report.file_path.value().find(path().value()), std::string::npos);
227     EXPECT_EQ(report.id, std::string());
228     EXPECT_FALSE(report.uploaded);
229     EXPECT_EQ(report.last_upload_attempt_time, 0);
230     EXPECT_EQ(report.upload_attempts, 0);
231     EXPECT_FALSE(report.upload_explicitly_requested);
232   }
233 
234   UploadReport(uuid, true, "test");
235 
236   {
237     CrashReportDatabase::Report report;
238     EXPECT_EQ(db()->LookUpCrashReport(uuid, &report),
239               CrashReportDatabase::kNoError);
240     EXPECT_EQ(report.uuid, uuid);
241     EXPECT_NE(report.file_path.value().find(path().value()), std::string::npos);
242     EXPECT_EQ(report.id, "test");
243     EXPECT_TRUE(report.uploaded);
244     EXPECT_NE(report.last_upload_attempt_time, 0);
245     EXPECT_EQ(report.upload_attempts, 1);
246     EXPECT_FALSE(report.upload_explicitly_requested);
247   }
248 }
249 
TEST_F(CrashReportDatabaseTest,RecordUploadAttempt)250 TEST_F(CrashReportDatabaseTest, RecordUploadAttempt) {
251   std::vector<CrashReportDatabase::Report> reports(3);
252   CreateCrashReport(&reports[0]);
253   CreateCrashReport(&reports[1]);
254   CreateCrashReport(&reports[2]);
255 
256   // Record two attempts: one successful, one not.
257   UploadReport(reports[1].uuid, false, std::string());
258   UploadReport(reports[2].uuid, true, "abc123");
259 
260   std::vector<CrashReportDatabase::Report> query(3);
261   EXPECT_EQ(db()->LookUpCrashReport(reports[0].uuid, &query[0]),
262             CrashReportDatabase::kNoError);
263   EXPECT_EQ(db()->LookUpCrashReport(reports[1].uuid, &query[1]),
264             CrashReportDatabase::kNoError);
265   EXPECT_EQ(db()->LookUpCrashReport(reports[2].uuid, &query[2]),
266             CrashReportDatabase::kNoError);
267 
268   EXPECT_EQ(query[0].id, std::string());
269   EXPECT_EQ(query[1].id, std::string());
270   EXPECT_EQ(query[2].id, "abc123");
271 
272   EXPECT_FALSE(query[0].uploaded);
273   EXPECT_FALSE(query[1].uploaded);
274   EXPECT_TRUE(query[2].uploaded);
275 
276   EXPECT_EQ(query[0].last_upload_attempt_time, 0);
277   EXPECT_NE(query[1].last_upload_attempt_time, 0);
278   EXPECT_NE(query[2].last_upload_attempt_time, 0);
279 
280   EXPECT_EQ(query[0].upload_attempts, 0);
281   EXPECT_EQ(query[1].upload_attempts, 1);
282   EXPECT_EQ(query[2].upload_attempts, 1);
283 
284   // Attempt to upload and fail again.
285   UploadReport(reports[1].uuid, false, std::string());
286 
287   time_t report_2_upload_time = query[2].last_upload_attempt_time;
288 
289   EXPECT_EQ(db()->LookUpCrashReport(reports[0].uuid, &query[0]),
290             CrashReportDatabase::kNoError);
291   EXPECT_EQ(db()->LookUpCrashReport(reports[1].uuid, &query[1]),
292             CrashReportDatabase::kNoError);
293   EXPECT_EQ(db()->LookUpCrashReport(reports[2].uuid, &query[2]),
294             CrashReportDatabase::kNoError);
295 
296   EXPECT_FALSE(query[0].uploaded);
297   EXPECT_FALSE(query[1].uploaded);
298   EXPECT_TRUE(query[2].uploaded);
299 
300   EXPECT_EQ(query[0].last_upload_attempt_time, 0);
301   EXPECT_GE(query[1].last_upload_attempt_time, report_2_upload_time);
302   EXPECT_EQ(query[2].last_upload_attempt_time, report_2_upload_time);
303 
304   EXPECT_EQ(query[0].upload_attempts, 0);
305   EXPECT_EQ(query[1].upload_attempts, 2);
306   EXPECT_EQ(query[2].upload_attempts, 1);
307 
308   // Third time's the charm: upload and succeed.
309   UploadReport(reports[1].uuid, true, "666hahaha");
310 
311   time_t report_1_upload_time = query[1].last_upload_attempt_time;
312 
313   EXPECT_EQ(db()->LookUpCrashReport(reports[0].uuid, &query[0]),
314             CrashReportDatabase::kNoError);
315   EXPECT_EQ(db()->LookUpCrashReport(reports[1].uuid, &query[1]),
316             CrashReportDatabase::kNoError);
317   EXPECT_EQ(db()->LookUpCrashReport(reports[2].uuid, &query[2]),
318             CrashReportDatabase::kNoError);
319 
320   EXPECT_FALSE(query[0].uploaded);
321   EXPECT_TRUE(query[1].uploaded);
322   EXPECT_TRUE(query[2].uploaded);
323 
324   EXPECT_EQ(query[0].last_upload_attempt_time, 0);
325   EXPECT_GE(query[1].last_upload_attempt_time, report_1_upload_time);
326   EXPECT_EQ(query[2].last_upload_attempt_time, report_2_upload_time);
327 
328   EXPECT_EQ(query[0].upload_attempts, 0);
329   EXPECT_EQ(query[1].upload_attempts, 3);
330   EXPECT_EQ(query[2].upload_attempts, 1);
331 }
332 
333 // This test covers both query functions since they are related.
TEST_F(CrashReportDatabaseTest,GetCompletedAndNotUploadedReports)334 TEST_F(CrashReportDatabaseTest, GetCompletedAndNotUploadedReports) {
335   std::vector<CrashReportDatabase::Report> reports(5);
336   CreateCrashReport(&reports[0]);
337   CreateCrashReport(&reports[1]);
338   CreateCrashReport(&reports[2]);
339   CreateCrashReport(&reports[3]);
340   CreateCrashReport(&reports[4]);
341 
342   const UUID& report_0_uuid = reports[0].uuid;
343   const UUID& report_1_uuid = reports[1].uuid;
344   const UUID& report_2_uuid = reports[2].uuid;
345   const UUID& report_3_uuid = reports[3].uuid;
346   const UUID& report_4_uuid = reports[4].uuid;
347 
348   std::vector<CrashReportDatabase::Report> pending;
349   EXPECT_EQ(db()->GetPendingReports(&pending), CrashReportDatabase::kNoError);
350 
351   std::vector<CrashReportDatabase::Report> completed;
352   EXPECT_EQ(db()->GetCompletedReports(&completed),
353             CrashReportDatabase::kNoError);
354 
355   EXPECT_EQ(pending.size(), reports.size());
356   EXPECT_EQ(completed.size(), 0u);
357 
358   // Upload one report successfully.
359   UploadReport(report_1_uuid, true, "report1");
360 
361   pending.clear();
362   EXPECT_EQ(db()->GetPendingReports(&pending), CrashReportDatabase::kNoError);
363   completed.clear();
364   EXPECT_EQ(db()->GetCompletedReports(&completed),
365             CrashReportDatabase::kNoError);
366 
367   EXPECT_EQ(pending.size(), 4u);
368   ASSERT_EQ(completed.size(), 1u);
369 
370   for (const auto& report : pending) {
371     EXPECT_NE(report.uuid, report_1_uuid);
372     EXPECT_FALSE(report.file_path.empty());
373   }
374   EXPECT_EQ(completed[0].uuid, report_1_uuid);
375   EXPECT_EQ(completed[0].id, "report1");
376   EXPECT_EQ(completed[0].uploaded, true);
377   EXPECT_GT(completed[0].last_upload_attempt_time, 0);
378   EXPECT_EQ(completed[0].upload_attempts, 1);
379 
380   // Fail to upload one report.
381   UploadReport(report_2_uuid, false, std::string());
382 
383   pending.clear();
384   EXPECT_EQ(db()->GetPendingReports(&pending), CrashReportDatabase::kNoError);
385   completed.clear();
386   EXPECT_EQ(db()->GetCompletedReports(&completed),
387             CrashReportDatabase::kNoError);
388 
389   EXPECT_EQ(pending.size(), 4u);
390   ASSERT_EQ(completed.size(), 1u);
391 
392   for (const auto& report : pending) {
393     if (report.upload_attempts != 0) {
394       EXPECT_EQ(report.uuid, report_2_uuid);
395       EXPECT_GT(report.last_upload_attempt_time, 0);
396       EXPECT_FALSE(report.uploaded);
397       EXPECT_TRUE(report.id.empty());
398     }
399     EXPECT_FALSE(report.file_path.empty());
400   }
401 
402   // Upload a second report.
403   UploadReport(report_4_uuid, true, "report_4");
404 
405   pending.clear();
406   EXPECT_EQ(db()->GetPendingReports(&pending), CrashReportDatabase::kNoError);
407   completed.clear();
408   EXPECT_EQ(db()->GetCompletedReports(&completed),
409             CrashReportDatabase::kNoError);
410 
411   EXPECT_EQ(pending.size(), 3u);
412   ASSERT_EQ(completed.size(), 2u);
413 
414   // Succeed the failed report.
415   UploadReport(report_2_uuid, true, "report 2");
416 
417   pending.clear();
418   EXPECT_EQ(db()->GetPendingReports(&pending), CrashReportDatabase::kNoError);
419   completed.clear();
420   EXPECT_EQ(db()->GetCompletedReports(&completed),
421             CrashReportDatabase::kNoError);
422 
423   EXPECT_EQ(pending.size(), 2u);
424   ASSERT_EQ(completed.size(), 3u);
425 
426   for (const auto& report : pending) {
427     EXPECT_TRUE(report.uuid == report_0_uuid || report.uuid == report_3_uuid);
428     EXPECT_FALSE(report.file_path.empty());
429   }
430 
431   // Skip upload for one report.
432   EXPECT_EQ(db()->SkipReportUpload(
433                 report_3_uuid, Metrics::CrashSkippedReason::kUploadsDisabled),
434             CrashReportDatabase::kNoError);
435 
436   pending.clear();
437   EXPECT_EQ(db()->GetPendingReports(&pending), CrashReportDatabase::kNoError);
438   completed.clear();
439   EXPECT_EQ(db()->GetCompletedReports(&completed),
440             CrashReportDatabase::kNoError);
441 
442   ASSERT_EQ(pending.size(), 1u);
443   ASSERT_EQ(completed.size(), 4u);
444 
445   EXPECT_EQ(pending[0].uuid, report_0_uuid);
446 
447   for (const auto& report : completed) {
448     if (report.uuid == report_3_uuid) {
449       EXPECT_FALSE(report.uploaded);
450       EXPECT_EQ(report.upload_attempts, 0);
451       EXPECT_EQ(report.last_upload_attempt_time, 0);
452     } else {
453       EXPECT_TRUE(report.uploaded);
454       EXPECT_GT(report.upload_attempts, 0);
455       EXPECT_GT(report.last_upload_attempt_time, 0);
456     }
457     EXPECT_FALSE(report.file_path.empty());
458   }
459 }
460 
TEST_F(CrashReportDatabaseTest,DuelingUploads)461 TEST_F(CrashReportDatabaseTest, DuelingUploads) {
462   CrashReportDatabase::Report report;
463   CreateCrashReport(&report);
464 
465   std::unique_ptr<const CrashReportDatabase::UploadReport> upload_report;
466   EXPECT_EQ(db()->GetReportForUploading(report.uuid, &upload_report),
467             CrashReportDatabase::kNoError);
468 
469   std::unique_ptr<const CrashReportDatabase::UploadReport> upload_report_2;
470   EXPECT_EQ(db()->GetReportForUploading(report.uuid, &upload_report_2),
471             CrashReportDatabase::kBusyError);
472   EXPECT_FALSE(upload_report_2);
473 
474   EXPECT_EQ(db()->RecordUploadComplete(std::move(upload_report), std::string()),
475             CrashReportDatabase::kNoError);
476 }
477 
TEST_F(CrashReportDatabaseTest,UploadAlreadyUploaded)478 TEST_F(CrashReportDatabaseTest, UploadAlreadyUploaded) {
479   CrashReportDatabase::Report report;
480   CreateCrashReport(&report);
481 
482   std::unique_ptr<const CrashReportDatabase::UploadReport> upload_report;
483   EXPECT_EQ(db()->GetReportForUploading(report.uuid, &upload_report),
484             CrashReportDatabase::kNoError);
485   EXPECT_EQ(db()->RecordUploadComplete(std::move(upload_report), std::string()),
486             CrashReportDatabase::kNoError);
487 
488   std::unique_ptr<const CrashReportDatabase::UploadReport> upload_report_2;
489   EXPECT_EQ(db()->GetReportForUploading(report.uuid, &upload_report_2),
490             CrashReportDatabase::kReportNotFound);
491   EXPECT_FALSE(upload_report_2.get());
492 }
493 
TEST_F(CrashReportDatabaseTest,MoveDatabase)494 TEST_F(CrashReportDatabaseTest, MoveDatabase) {
495   std::unique_ptr<CrashReportDatabase::NewReport> new_report;
496   EXPECT_EQ(db()->PrepareNewCrashReport(&new_report),
497             CrashReportDatabase::kNoError);
498   UUID uuid;
499   EXPECT_EQ(db()->FinishedWritingCrashReport(std::move(new_report), &uuid),
500             CrashReportDatabase::kNoError);
501 
502   RelocateDatabase();
503 
504   CrashReportDatabase::Report report;
505   EXPECT_EQ(db()->LookUpCrashReport(uuid, &report),
506             CrashReportDatabase::kNoError);
507   ExpectPreparedCrashReport(report);
508 }
509 
TEST_F(CrashReportDatabaseTest,ReportRemoved)510 TEST_F(CrashReportDatabaseTest, ReportRemoved) {
511   std::unique_ptr<CrashReportDatabase::NewReport> new_report;
512   EXPECT_EQ(db()->PrepareNewCrashReport(&new_report),
513             CrashReportDatabase::kNoError);
514 
515   UUID uuid;
516   EXPECT_EQ(db()->FinishedWritingCrashReport(std::move(new_report), &uuid),
517             CrashReportDatabase::kNoError);
518 
519   CrashReportDatabase::Report report;
520   EXPECT_EQ(db()->LookUpCrashReport(uuid, &report),
521             CrashReportDatabase::kNoError);
522 
523   EXPECT_TRUE(LoggingRemoveFile(report.file_path));
524 
525   EXPECT_EQ(db()->LookUpCrashReport(uuid, &report),
526             CrashReportDatabase::kReportNotFound);
527 }
528 
TEST_F(CrashReportDatabaseTest,DeleteReport)529 TEST_F(CrashReportDatabaseTest, DeleteReport) {
530   CrashReportDatabase::Report keep_pending;
531   CrashReportDatabase::Report delete_pending;
532   CrashReportDatabase::Report keep_completed;
533   CrashReportDatabase::Report delete_completed;
534 
535   CreateCrashReport(&keep_pending);
536   CreateCrashReport(&delete_pending);
537   CreateCrashReport(&keep_completed);
538   CreateCrashReport(&delete_completed);
539 
540   EXPECT_TRUE(FileExists(keep_pending.file_path));
541   EXPECT_TRUE(FileExists(delete_pending.file_path));
542   EXPECT_TRUE(FileExists(keep_completed.file_path));
543   EXPECT_TRUE(FileExists(delete_completed.file_path));
544 
545   UploadReport(keep_completed.uuid, true, "1");
546   UploadReport(delete_completed.uuid, true, "2");
547 
548   EXPECT_EQ(db()->LookUpCrashReport(keep_completed.uuid, &keep_completed),
549             CrashReportDatabase::kNoError);
550   EXPECT_EQ(db()->LookUpCrashReport(delete_completed.uuid, &delete_completed),
551             CrashReportDatabase::kNoError);
552 
553   EXPECT_TRUE(FileExists(keep_completed.file_path));
554   EXPECT_TRUE(FileExists(delete_completed.file_path));
555 
556   EXPECT_EQ(db()->DeleteReport(delete_pending.uuid),
557             CrashReportDatabase::kNoError);
558   EXPECT_FALSE(FileExists(delete_pending.file_path));
559   EXPECT_EQ(db()->LookUpCrashReport(delete_pending.uuid, &delete_pending),
560             CrashReportDatabase::kReportNotFound);
561   EXPECT_EQ(db()->DeleteReport(delete_pending.uuid),
562             CrashReportDatabase::kReportNotFound);
563 
564   EXPECT_EQ(db()->DeleteReport(delete_completed.uuid),
565             CrashReportDatabase::kNoError);
566   EXPECT_FALSE(FileExists(delete_completed.file_path));
567   EXPECT_EQ(db()->LookUpCrashReport(delete_completed.uuid, &delete_completed),
568             CrashReportDatabase::kReportNotFound);
569   EXPECT_EQ(db()->DeleteReport(delete_completed.uuid),
570             CrashReportDatabase::kReportNotFound);
571 
572   EXPECT_EQ(db()->LookUpCrashReport(keep_pending.uuid, &keep_pending),
573             CrashReportDatabase::kNoError);
574   EXPECT_EQ(db()->LookUpCrashReport(keep_completed.uuid, &keep_completed),
575             CrashReportDatabase::kNoError);
576 }
577 
TEST_F(CrashReportDatabaseTest,DeleteReportEmptyingDatabase)578 TEST_F(CrashReportDatabaseTest, DeleteReportEmptyingDatabase) {
579   CrashReportDatabase::Report report;
580   CreateCrashReport(&report);
581 
582   EXPECT_TRUE(FileExists(report.file_path));
583 
584   UploadReport(report.uuid, true, "1");
585 
586   EXPECT_EQ(db()->LookUpCrashReport(report.uuid, &report),
587             CrashReportDatabase::kNoError);
588 
589   EXPECT_TRUE(FileExists(report.file_path));
590 
591   // This causes an empty database to be written, make sure this is handled.
592   EXPECT_EQ(db()->DeleteReport(report.uuid), CrashReportDatabase::kNoError);
593   EXPECT_FALSE(FileExists(report.file_path));
594 }
595 
TEST_F(CrashReportDatabaseTest,ReadEmptyDatabase)596 TEST_F(CrashReportDatabaseTest, ReadEmptyDatabase) {
597   CrashReportDatabase::Report report;
598   CreateCrashReport(&report);
599   EXPECT_EQ(db()->DeleteReport(report.uuid), CrashReportDatabase::kNoError);
600 
601   // Deleting and the creating another report causes an empty database to be
602   // loaded. Make sure this is handled.
603 
604   CrashReportDatabase::Report report2;
605   CreateCrashReport(&report2);
606 }
607 
TEST_F(CrashReportDatabaseTest,RequestUpload)608 TEST_F(CrashReportDatabaseTest, RequestUpload) {
609   std::vector<CrashReportDatabase::Report> reports(2);
610   CreateCrashReport(&reports[0]);
611   CreateCrashReport(&reports[1]);
612 
613   const UUID& report_0_uuid = reports[0].uuid;
614   const UUID& report_1_uuid = reports[1].uuid;
615 
616   // Skipped report gets back to pending state after RequestUpload is called.
617   EXPECT_EQ(db()->SkipReportUpload(
618                 report_1_uuid, Metrics::CrashSkippedReason::kUploadsDisabled),
619             CrashReportDatabase::kNoError);
620 
621   std::vector<CrashReportDatabase::Report> pending_reports;
622   CrashReportDatabase::OperationStatus os =
623       db()->GetPendingReports(&pending_reports);
624   EXPECT_EQ(os, CrashReportDatabase::kNoError);
625   ASSERT_EQ(pending_reports.size(), 1u);
626   EXPECT_EQ(report_0_uuid, pending_reports[0].uuid);
627 
628   pending_reports.clear();
629   EXPECT_EQ(RequestUpload(report_1_uuid), CrashReportDatabase::kNoError);
630   os = db()->GetPendingReports(&pending_reports);
631   EXPECT_EQ(os, CrashReportDatabase::kNoError);
632   ASSERT_EQ(pending_reports.size(), 2u);
633 
634   // Check individual reports.
635   const CrashReportDatabase::Report* explicitly_requested_report;
636   const CrashReportDatabase::Report* pending_report;
637   if (pending_reports[0].uuid == report_0_uuid) {
638     pending_report = &pending_reports[0];
639     explicitly_requested_report = &pending_reports[1];
640   } else {
641     pending_report = &pending_reports[1];
642     explicitly_requested_report = &pending_reports[0];
643   }
644 
645   EXPECT_EQ(pending_report->uuid, report_0_uuid);
646   EXPECT_FALSE(pending_report->upload_explicitly_requested);
647 
648   EXPECT_EQ(explicitly_requested_report->uuid, report_1_uuid);
649   EXPECT_TRUE(explicitly_requested_report->upload_explicitly_requested);
650 
651   // Explicitly requested reports will not have upload_explicitly_requested bit
652   // after getting skipped.
653   EXPECT_EQ(db()->SkipReportUpload(
654                 report_1_uuid, Metrics::CrashSkippedReason::kUploadsDisabled),
655             CrashReportDatabase::kNoError);
656   CrashReportDatabase::Report report;
657   EXPECT_EQ(db()->LookUpCrashReport(report_1_uuid, &report),
658             CrashReportDatabase::kNoError);
659   EXPECT_FALSE(report.upload_explicitly_requested);
660 
661   // Pending report gets correctly affected after RequestUpload is called.
662   pending_reports.clear();
663   EXPECT_EQ(RequestUpload(report_0_uuid), CrashReportDatabase::kNoError);
664   os = db()->GetPendingReports(&pending_reports);
665   EXPECT_EQ(os, CrashReportDatabase::kNoError);
666   EXPECT_EQ(pending_reports.size(), 1u);
667   EXPECT_EQ(report_0_uuid, pending_reports[0].uuid);
668   EXPECT_TRUE(pending_reports[0].upload_explicitly_requested);
669 
670   // Already uploaded report cannot be requested for the new upload.
671   UploadReport(report_0_uuid, true, "1");
672   EXPECT_EQ(RequestUpload(report_0_uuid),
673             CrashReportDatabase::kCannotRequestUpload);
674 }
675 
TEST_F(CrashReportDatabaseTest,Attachments)676 TEST_F(CrashReportDatabaseTest, Attachments) {
677 #if defined(OS_APPLE) || defined(OS_WIN)
678   // Attachments aren't supported on Mac and Windows yet.
679   GTEST_SKIP();
680 #else
681   std::unique_ptr<CrashReportDatabase::NewReport> new_report;
682   ASSERT_EQ(db()->PrepareNewCrashReport(&new_report),
683             CrashReportDatabase::kNoError);
684 
685   FileWriter* attach_some_file = new_report->AddAttachment("some_file");
686   ASSERT_NE(attach_some_file, nullptr);
687   static constexpr char test_data[] = "test data";
688   attach_some_file->Write(test_data, sizeof(test_data));
689 
690   FileWriter* failed_attach = new_report->AddAttachment("not/a valid fi!e");
691   EXPECT_EQ(failed_attach, nullptr);
692 
693   UUID expect_uuid = new_report->ReportID();
694   UUID uuid;
695   ASSERT_EQ(db()->FinishedWritingCrashReport(std::move(new_report), &uuid),
696             CrashReportDatabase::kNoError);
697   EXPECT_EQ(uuid, expect_uuid);
698 
699   CrashReportDatabase::Report report;
700   EXPECT_EQ(db()->LookUpCrashReport(uuid, &report),
701             CrashReportDatabase::kNoError);
702   ExpectPreparedCrashReport(report);
703 
704   std::vector<CrashReportDatabase::Report> reports;
705   EXPECT_EQ(db()->GetPendingReports(&reports), CrashReportDatabase::kNoError);
706   ASSERT_EQ(reports.size(), 1u);
707   EXPECT_EQ(reports[0].uuid, report.uuid);
708 
709   std::unique_ptr<const CrashReportDatabase::UploadReport> upload_report;
710   ASSERT_EQ(db()->GetReportForUploading(reports[0].uuid, &upload_report),
711             CrashReportDatabase::kNoError);
712   std::map<std::string, FileReader*> result_attachments =
713       upload_report->GetAttachments();
714   EXPECT_EQ(result_attachments.size(), 1u);
715   EXPECT_NE(result_attachments.find("some_file"), result_attachments.end());
716   char result_buffer[sizeof(test_data)];
717   result_attachments["some_file"]->Read(result_buffer, sizeof(result_buffer));
718   EXPECT_EQ(memcmp(test_data, result_buffer, sizeof(test_data)), 0);
719 #endif
720 }
721 
TEST_F(CrashReportDatabaseTest,OrphanedAttachments)722 TEST_F(CrashReportDatabaseTest, OrphanedAttachments) {
723 #if defined(OS_APPLE) || defined(OS_WIN)
724   // Attachments aren't supported on Mac and Windows yet.
725   GTEST_SKIP();
726 #else
727   // TODO: This is using paths that are specific to the generic implementation
728   // and will need to be generalized for Mac and Windows.
729   std::unique_ptr<CrashReportDatabase::NewReport> new_report;
730   ASSERT_EQ(db()->PrepareNewCrashReport(&new_report),
731             CrashReportDatabase::kNoError);
732 
733   FileWriter* file1 = new_report->AddAttachment("file1");
734   ASSERT_NE(file1, nullptr);
735   FileWriter* file2 = new_report->AddAttachment("file2");
736   ASSERT_NE(file2, nullptr);
737 
738   UUID expect_uuid = new_report->ReportID();
739   UUID uuid;
740   ASSERT_EQ(db()->FinishedWritingCrashReport(std::move(new_report), &uuid),
741             CrashReportDatabase::kNoError);
742   EXPECT_EQ(uuid, expect_uuid);
743 
744   CrashReportDatabase::Report report;
745   ASSERT_EQ(db()->LookUpCrashReport(uuid, &report),
746             CrashReportDatabase::kNoError);
747 
748   ASSERT_TRUE(LoggingRemoveFile(report.file_path));
749 
750   ASSERT_TRUE(LoggingRemoveFile(base::FilePath(
751       report.file_path.RemoveFinalExtension().value() + ".meta")));
752 
753   ASSERT_EQ(db()->LookUpCrashReport(uuid, &report),
754             CrashReportDatabase::kReportNotFound);
755 
756   base::FilePath report_attachments_dir(
757       path().Append("attachments").Append(uuid.ToString()));
758   base::FilePath file_path1(report_attachments_dir.Append("file1"));
759   base::FilePath file_path2(report_attachments_dir.Append("file2"));
760   EXPECT_TRUE(FileExists(file_path1));
761   EXPECT_TRUE(FileExists(file_path1));
762 
763   EXPECT_EQ(db()->CleanDatabase(0), 0);
764 
765   EXPECT_FALSE(FileExists(file_path1));
766   EXPECT_FALSE(FileExists(file_path2));
767   EXPECT_FALSE(FileExists(report_attachments_dir));
768 #endif
769 }
770 
771 // This test uses knowledge of the database format to break it, so it only
772 // applies to the unfified database implementation.
773 #if !defined(OS_APPLE) && !defined(OS_WIN)
TEST_F(CrashReportDatabaseTest,CleanBrokenDatabase)774 TEST_F(CrashReportDatabaseTest, CleanBrokenDatabase) {
775   // Remove report files if metadata goes missing.
776   CrashReportDatabase::Report report;
777   ASSERT_NO_FATAL_FAILURE(CreateCrashReport(&report));
778 
779   const base::FilePath metadata(
780       report.file_path.RemoveFinalExtension().value() +
781       FILE_PATH_LITERAL(".meta"));
782   ASSERT_TRUE(PathExists(report.file_path));
783   ASSERT_TRUE(PathExists(metadata));
784 
785   ASSERT_TRUE(LoggingRemoveFile(metadata));
786   EXPECT_EQ(db()->CleanDatabase(0), 1);
787 
788   EXPECT_FALSE(PathExists(report.file_path));
789   EXPECT_FALSE(PathExists(metadata));
790 
791   // Remove metadata files if reports go missing.
792   ASSERT_NO_FATAL_FAILURE(CreateCrashReport(&report));
793   const base::FilePath metadata2(
794       report.file_path.RemoveFinalExtension().value() +
795       FILE_PATH_LITERAL(".meta"));
796   ASSERT_TRUE(PathExists(report.file_path));
797   ASSERT_TRUE(PathExists(metadata2));
798 
799   ASSERT_TRUE(LoggingRemoveFile(report.file_path));
800   EXPECT_EQ(db()->CleanDatabase(0), 1);
801 
802   EXPECT_FALSE(PathExists(report.file_path));
803   EXPECT_FALSE(PathExists(metadata2));
804 
805   // Remove stale new files.
806   std::unique_ptr<CrashReportDatabase::NewReport> new_report;
807   EXPECT_EQ(db()->PrepareNewCrashReport(&new_report),
808             CrashReportDatabase::kNoError);
809   new_report->Writer()->Close();
810   EXPECT_EQ(db()->CleanDatabase(0), 1);
811 
812   // Remove stale lock files and their associated reports.
813   ASSERT_NO_FATAL_FAILURE(CreateCrashReport(&report));
814   const base::FilePath metadata3(
815       report.file_path.RemoveFinalExtension().value() +
816       FILE_PATH_LITERAL(".meta"));
817   ASSERT_TRUE(PathExists(report.file_path));
818   ASSERT_TRUE(PathExists(metadata3));
819 
820   const base::FilePath lockpath(
821       report.file_path.RemoveFinalExtension().value() +
822       FILE_PATH_LITERAL(".lock"));
823   ScopedFileHandle handle(LoggingOpenFileForWrite(
824       lockpath, FileWriteMode::kCreateOrFail, FilePermissions::kOwnerOnly));
825   ASSERT_TRUE(handle.is_valid());
826 
827   time_t expired_timestamp = time(nullptr) - 60 * 60 * 24 * 3;
828 
829   ASSERT_TRUE(LoggingWriteFile(
830       handle.get(), &expired_timestamp, sizeof(expired_timestamp)));
831   ASSERT_TRUE(LoggingCloseFile(handle.get()));
832   ignore_result(handle.release());
833 
834   EXPECT_EQ(db()->CleanDatabase(0), 1);
835 
836   EXPECT_FALSE(PathExists(report.file_path));
837   EXPECT_FALSE(PathExists(metadata3));
838 }
839 #endif  // !OS_APPLE && !OS_WIN
840 
TEST_F(CrashReportDatabaseTest,TotalSize_MainReportOnly)841 TEST_F(CrashReportDatabaseTest, TotalSize_MainReportOnly) {
842   std::unique_ptr<CrashReportDatabase::NewReport> new_report;
843   ASSERT_EQ(db()->PrepareNewCrashReport(&new_report),
844             CrashReportDatabase::kNoError);
845 
846   // Main report.
847   static constexpr char main_report_data[] = "dlbvandslhb";
848   ASSERT_TRUE(
849       new_report->Writer()->Write(main_report_data, sizeof(main_report_data)));
850 
851   UUID uuid;
852   ASSERT_EQ(db()->FinishedWritingCrashReport(std::move(new_report), &uuid),
853             CrashReportDatabase::kNoError);
854 
855   CrashReportDatabase::Report report;
856   ASSERT_EQ(db()->LookUpCrashReport(uuid, &report),
857             CrashReportDatabase::kNoError);
858 
859   EXPECT_EQ(report.total_size, sizeof(main_report_data));
860 }
861 
TEST_F(CrashReportDatabaseTest,GetReportSize_RightSizeWithAttachments)862 TEST_F(CrashReportDatabaseTest, GetReportSize_RightSizeWithAttachments) {
863 #if defined(OS_APPLE) || defined(OS_WIN)
864   // Attachments aren't supported on Mac and Windows yet.
865   return;
866 #else
867   std::unique_ptr<CrashReportDatabase::NewReport> new_report;
868   ASSERT_EQ(db()->PrepareNewCrashReport(&new_report),
869             CrashReportDatabase::kNoError);
870 
871   // Main report.
872   static constexpr char main_report_data[] = "dlbvandslhb";
873   ASSERT_TRUE(
874       new_report->Writer()->Write(main_report_data, sizeof(main_report_data)));
875 
876   // First attachment.
877   FileWriter* attachment_1 = new_report->AddAttachment("my_attachment_1");
878   ASSERT_NE(attachment_1, nullptr);
879   static constexpr char attachment_1_data[] = "vKDnidhvbiudshoihbvdsoiuh nhh";
880   attachment_1->Write(attachment_1_data, sizeof(attachment_1_data));
881 
882   // Second attachment.
883   FileWriter* attachment_2 = new_report->AddAttachment("my_attachment_2");
884   ASSERT_NE(attachment_2, nullptr);
885   static constexpr char attachment_2_data[] = "sgvsvgusiyguysigfkhpmo-[";
886   attachment_2->Write(attachment_2_data, sizeof(attachment_2_data));
887 
888   UUID uuid;
889   ASSERT_EQ(db()->FinishedWritingCrashReport(std::move(new_report), &uuid),
890             CrashReportDatabase::kNoError);
891 
892   CrashReportDatabase::Report report;
893   ASSERT_EQ(db()->LookUpCrashReport(uuid, &report),
894             CrashReportDatabase::kNoError);
895   EXPECT_EQ(report.total_size,
896             sizeof(main_report_data) + sizeof(attachment_1_data) +
897                 sizeof(attachment_2_data));
898 #endif
899 }
900 
901 }  // namespace
902 }  // namespace test
903 }  // namespace crashpad
904