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/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 | |
OLD | NEW |