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

Side by Side Diff: client/prune_crash_reports_test.cc

Issue 1392653002: Add functionality to prune old crash reports from the database. (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Created 5 years, 2 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
« client/prune_crash_reports.cc ('K') | « client/prune_crash_reports.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
(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/prune_crash_reports.h"
16
17 #include <stdlib.h>
18
19 #include <algorithm>
20 #include <string>
21 #include <vector>
22
23 #include "gtest/gtest.h"
24 #include "test/scoped_temp_dir.h"
25 #include "util/file/file_io.h"
26
27 namespace crashpad {
28 namespace test {
29 namespace {
30
31 class TestDatabase : public CrashReportDatabase {
Mark Mentovai 2015/10/07 03:54:28 I don’t know if gmock would make the TestDatabase
Robert Sesek 2015/10/07 16:24:35 Gmock is never easy to deal with. But it is less c
32 public:
33 TestDatabase()
34 : pending_reports_(), completed_reports_(), deleted_reports_() {}
35 ~TestDatabase() override {}
36
37 std::vector<Report>* pending_reports() { return &pending_reports_; }
38 std::vector<Report>* completed_reports() { return &completed_reports_; }
39
40 const std::vector<UUID>& deleted_reports() { return deleted_reports_; }
41
42 // CrashReportDatabase:
43 Settings* GetSettings() override { return nullptr; }
44 OperationStatus PrepareNewCrashReport(NewReport** report) override {
45 return kDatabaseError;
46 }
47
48 OperationStatus FinishedWritingCrashReport(NewReport* report,
49 UUID* uuid) override {
50 return kDatabaseError;
51 }
52 OperationStatus ErrorWritingCrashReport(NewReport* report) override {
53 return kDatabaseError;
54 }
55 OperationStatus LookUpCrashReport(const UUID& uuid,
56 Report* report) override {
57 return kDatabaseError;
58 }
59 OperationStatus GetPendingReports(std::vector<Report>* reports) override {
60 *reports = pending_reports_;
61 return kNoError;
62 }
63 OperationStatus GetCompletedReports(std::vector<Report>* reports) override {
64 *reports = completed_reports_;
65 return kNoError;
66 }
67 OperationStatus GetReportForUploading(const UUID& uuid,
68 const Report** report) override {
69 return kDatabaseError;
70 }
71 OperationStatus RecordUploadAttempt(const Report* report,
72 bool successful,
73 const std::string& id) override {
74 return kDatabaseError;
75 }
76 OperationStatus SkipReportUpload(const UUID& uuid) override {
77 return kDatabaseError;
78 }
79 OperationStatus DeleteReport(const UUID& uuid) override {
80 auto condition = [uuid](const CrashReportDatabase::Report& report) {
81 return report.uuid == uuid;
82 };
83
84 auto it = std::remove_if(pending_reports_.begin(), pending_reports_.end(),
85 condition);
86 if (it != pending_reports_.end())
87 pending_reports_.erase(it);
88
89 it = std::remove_if(completed_reports_.begin(), completed_reports_.end(),
90 condition);
91 if (it != completed_reports_.end())
92 completed_reports_.erase(it);
93
94 deleted_reports_.push_back(uuid);
95 return kNoError;
96 }
97
98 private:
99 std::vector<Report> pending_reports_;
100 std::vector<Report> completed_reports_;
101 std::vector<UUID> deleted_reports_;
102
103 DISALLOW_COPY_AND_ASSIGN(TestDatabase);
104 };
105
106 time_t NDaysAgo(int num_days) {
107 return time(nullptr) - (num_days * 60 * 60 * 24);
108 }
109
110 TEST(PruneCrashReports, AgeCondition) {
111 CrashReportDatabase::Report report_80_days;
112 report_80_days.creation_time = NDaysAgo(80);
113
114 CrashReportDatabase::Report report_10_days;
115 report_10_days.creation_time = NDaysAgo(10);
116
117 CrashReportDatabase::Report report_30_days;
118 report_30_days.creation_time = NDaysAgo(30);
119
120 AgePruneCondition condition(30);
121 EXPECT_TRUE(condition.ShouldPruneReport(report_80_days));
122 EXPECT_FALSE(condition.ShouldPruneReport(report_10_days));
123 EXPECT_FALSE(condition.ShouldPruneReport(report_30_days));
124 }
125
126 TEST(PruneCrashReports, SizeCondition) {
127 ScopedTempDir temp_dir;
128
129 CrashReportDatabase::Report report_128;
130 report_128.file_path = temp_dir.path().Append(FILE_PATH_LITERAL("file128"));
131 CrashReportDatabase::Report report_1024;
132 report_1024.file_path = temp_dir.path().Append(FILE_PATH_LITERAL("file1024"));
133
134 {
135 ScopedFileHandle scoped_file_128(
136 LoggingOpenFileForWrite(report_128.file_path,
137 FileWriteMode::kCreateOrFail,
138 FilePermissions::kOwnerOnly));
139 ASSERT_TRUE(scoped_file_128.is_valid());
140
141 std::string string;
142 for (int i = 0; i < 128; ++i)
143 string.push_back(i);
scottmg 2015/10/06 22:22:07 warning converting int to char here on Windows.
Robert Sesek 2015/10/07 16:24:35 Done.
144 ASSERT_TRUE(LoggingWriteFile(scoped_file_128.get(),
145 string.c_str(), string.length()));
146
147 ScopedFileHandle scoped_file_1024(
148 LoggingOpenFileForWrite(report_1024.file_path,
149 FileWriteMode::kCreateOrFail,
150 FilePermissions::kOwnerOnly));
151 ASSERT_TRUE(scoped_file_1024.is_valid());
152
153 for (int i = 0; i < 1024; i += string.size()) {
154 ASSERT_TRUE(LoggingWriteFile(scoped_file_1024.get(),
155 string.c_str(), string.length()));
156 }
157 }
158
159 {
160 DatabaseSizePruneCondition condition(512);
161 EXPECT_FALSE(condition.ShouldPruneReport(report_128));
162 EXPECT_FALSE(condition.ShouldPruneReport(report_128));
163 EXPECT_FALSE(condition.ShouldPruneReport(report_128));
164 EXPECT_FALSE(condition.ShouldPruneReport(report_128));
165 EXPECT_TRUE(condition.ShouldPruneReport(report_128));
166 }
167
168 {
169 DatabaseSizePruneCondition condition(512);
170 EXPECT_TRUE(condition.ShouldPruneReport(report_1024));
171 }
172
173 {
174 DatabaseSizePruneCondition condition(2100);
175 EXPECT_FALSE(condition.ShouldPruneReport(report_1024));
176 EXPECT_FALSE(condition.ShouldPruneReport(report_1024));
177 EXPECT_TRUE(condition.ShouldPruneReport(report_128));
178 }
179 }
180
181 class StaticCondition : public PruneCondition {
182 public:
183 explicit StaticCondition(bool value) : value_(value) {}
184 ~StaticCondition() {}
185
186 bool ShouldPruneReport(const CrashReportDatabase::Report& report) override {
187 return value_;
188 }
189
190 private:
191 bool value_;
192 };
193
194 TEST(PruneCrashReports, BinaryAND) {
195 BinaryPruneCondition false_false(BinaryPruneCondition::AND,
196 new StaticCondition(false), new StaticCondition(false));
197 BinaryPruneCondition false_true(BinaryPruneCondition::AND,
198 new StaticCondition(false), new StaticCondition(true));
199 BinaryPruneCondition true_false(BinaryPruneCondition::AND,
200 new StaticCondition(true), new StaticCondition(false));
201 BinaryPruneCondition true_true(BinaryPruneCondition::AND,
202 new StaticCondition(true), new StaticCondition(true));
203
204 CrashReportDatabase::Report report;
205
206 EXPECT_FALSE(false_false.ShouldPruneReport(report));
207 EXPECT_FALSE(false_true.ShouldPruneReport(report));
208 EXPECT_FALSE(true_false.ShouldPruneReport(report));
209 EXPECT_TRUE(true_true.ShouldPruneReport(report));
210 }
211
212 TEST(PruneCrashReports, BinaryOR) {
213 BinaryPruneCondition false_false(BinaryPruneCondition::OR,
214 new StaticCondition(false), new StaticCondition(false));
215 BinaryPruneCondition false_true(BinaryPruneCondition::OR,
216 new StaticCondition(false), new StaticCondition(true));
217 BinaryPruneCondition true_false(BinaryPruneCondition::OR,
218 new StaticCondition(true), new StaticCondition(false));
219 BinaryPruneCondition true_true(BinaryPruneCondition::OR,
220 new StaticCondition(true), new StaticCondition(true));
221
222 CrashReportDatabase::Report report;
223
224 EXPECT_FALSE(false_false.ShouldPruneReport(report));
225 EXPECT_TRUE(false_true.ShouldPruneReport(report));
226 EXPECT_TRUE(true_false.ShouldPruneReport(report));
227 EXPECT_TRUE(true_true.ShouldPruneReport(report));
228 }
229
230 TEST(PruneCrashReports, PruneOrder) {
231 TestDatabase db;
232
233 std::vector<CrashReportDatabase::Report> reports;
234 for (int i = 0; i < 10; ++i) {
235 CrashReportDatabase::Report temp;
236 temp.uuid.data_1 = i;
237 temp.creation_time = NDaysAgo(i * 10);
238 reports.push_back(temp);
239 }
240
241 // The randomness from std::rand() is not, so use arc4random instead.
242 std::random_shuffle(reports.begin(), reports.end(), [](int rand_max) {
243 return arc4random() % rand_max;
scottmg 2015/10/06 22:22:07 arc4random doesn't exist on Windows.
scottmg 2015/10/06 22:35:29 (Should have mentioned we have base/rand_util.h wh
Robert Sesek 2015/10/07 16:24:35 Done.
244 });
245 db.pending_reports()->insert(db.pending_reports()->end(),
246 reports.begin(), reports.begin() + 5);
247 db.completed_reports()->insert(db.completed_reports()->end(),
248 reports.begin() + 5, reports.end());
249
250 StaticCondition delete_all(true);
251 PruneCrashReportDatabase(&db, &delete_all);
252
253 ASSERT_EQ(reports.size(), db.deleted_reports().size());
254 for (size_t i = 0; i < reports.size(); ++i) {
255 EXPECT_EQ(i, db.deleted_reports()[i].data_1);
256 }
257
258 EXPECT_TRUE(db.pending_reports()->empty());
259 EXPECT_TRUE(db.completed_reports()->empty());
260 }
261
262 } // namespace
263 } // namespace test
264 } // namespace crashpad
OLDNEW
« client/prune_crash_reports.cc ('K') | « client/prune_crash_reports.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698