OLD | NEW |
---|---|
(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(¬_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(¬_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(¬_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(¬_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(¬_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 | |
OLD | NEW |