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

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: Additional comments 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 "base/rand_util.h"
24 #include "gmock/gmock.h"
25 #include "gtest/gtest.h"
26 #include "test/scoped_temp_dir.h"
27 #include "util/file/file_io.h"
28
29 namespace crashpad {
30 namespace test {
31 namespace {
32
33 class MockDatabase : public CrashReportDatabase {
34 public:
35 // CrashReportDatabase:
36 MOCK_METHOD0(GetSettings, Settings*());
37 MOCK_METHOD1(PrepareNewCrashReport, OperationStatus(NewReport**));
38 MOCK_METHOD2(FinishedWritingCrashReport, OperationStatus(NewReport*, UUID*));
39 MOCK_METHOD1(ErrorWritingCrashReport, OperationStatus(NewReport*));
40 MOCK_METHOD2(LookUpCrashReport, OperationStatus(const UUID&, Report*));
41 MOCK_METHOD1(GetPendingReports, OperationStatus(std::vector<Report>*));
42 MOCK_METHOD1(GetCompletedReports, OperationStatus(std::vector<Report>*));
43 MOCK_METHOD2(GetReportForUploading,
44 OperationStatus(const UUID&, const Report**));
45 MOCK_METHOD3(RecordUploadAttempt,
46 OperationStatus(const Report*, bool, const std::string&));
47 MOCK_METHOD1(SkipReportUpload, OperationStatus(const UUID&));
48 MOCK_METHOD1(DeleteReport, OperationStatus(const UUID&));
49 };
50
51 time_t NDaysAgo(int num_days) {
52 return time(nullptr) - (num_days * 60 * 60 * 24);
53 }
54
55 TEST(PruneCrashReports, AgeCondition) {
56 CrashReportDatabase::Report report_80_days;
57 report_80_days.creation_time = NDaysAgo(80);
58
59 CrashReportDatabase::Report report_10_days;
60 report_10_days.creation_time = NDaysAgo(10);
61
62 CrashReportDatabase::Report report_30_days;
63 report_30_days.creation_time = NDaysAgo(30);
64
65 AgePruneCondition condition(30);
66 EXPECT_TRUE(condition.ShouldPruneReport(report_80_days));
67 EXPECT_FALSE(condition.ShouldPruneReport(report_10_days));
68 EXPECT_FALSE(condition.ShouldPruneReport(report_30_days));
69 }
70
71 TEST(PruneCrashReports, SizeCondition) {
72 ScopedTempDir temp_dir;
73
74 CrashReportDatabase::Report report_128;
75 report_128.file_path = temp_dir.path().Append(FILE_PATH_LITERAL("file128"));
76 CrashReportDatabase::Report report_1024;
77 report_1024.file_path = temp_dir.path().Append(FILE_PATH_LITERAL("file1024"));
78
79 {
80 ScopedFileHandle scoped_file_128(
81 LoggingOpenFileForWrite(report_128.file_path,
82 FileWriteMode::kCreateOrFail,
83 FilePermissions::kOwnerOnly));
84 ASSERT_TRUE(scoped_file_128.is_valid());
85
86 std::string string;
87 for (int i = 0; i < 128; ++i)
88 string.push_back(static_cast<char>(i));
89 ASSERT_TRUE(LoggingWriteFile(scoped_file_128.get(),
90 string.c_str(), string.length()));
91
92 ScopedFileHandle scoped_file_1024(
93 LoggingOpenFileForWrite(report_1024.file_path,
94 FileWriteMode::kCreateOrFail,
95 FilePermissions::kOwnerOnly));
96 ASSERT_TRUE(scoped_file_1024.is_valid());
97
98 for (int i = 0; i < 1024; i += string.size()) {
99 ASSERT_TRUE(LoggingWriteFile(scoped_file_1024.get(),
100 string.c_str(), string.length()));
101 }
102 }
103
104 {
105 DatabaseSizePruneCondition condition(1);
106 EXPECT_FALSE(condition.ShouldPruneReport(report_128));
107 EXPECT_FALSE(condition.ShouldPruneReport(report_128));
108 EXPECT_FALSE(condition.ShouldPruneReport(report_128));
109 EXPECT_FALSE(condition.ShouldPruneReport(report_128));
110 EXPECT_FALSE(condition.ShouldPruneReport(report_128));
111 EXPECT_FALSE(condition.ShouldPruneReport(report_128));
112 EXPECT_FALSE(condition.ShouldPruneReport(report_128));
113 EXPECT_FALSE(condition.ShouldPruneReport(report_128));
114 EXPECT_TRUE(condition.ShouldPruneReport(report_128));
115 }
116
117 {
118 DatabaseSizePruneCondition condition(0);
119 EXPECT_TRUE(condition.ShouldPruneReport(report_1024));
120 }
121
122 {
123 DatabaseSizePruneCondition condition(2);
124 EXPECT_FALSE(condition.ShouldPruneReport(report_1024));
125 EXPECT_FALSE(condition.ShouldPruneReport(report_1024));
126 EXPECT_TRUE(condition.ShouldPruneReport(report_128));
127 }
128 }
129
130 class StaticCondition : public PruneCondition {
131 public:
132 explicit StaticCondition(bool value) : value_(value), did_execute_(false) {}
133 ~StaticCondition() {}
134
135 bool ShouldPruneReport(const CrashReportDatabase::Report& report) override {
136 did_execute_ = true;
137 return value_;
138 }
139
140 bool did_execute() const { return did_execute_; }
141
142 private:
143 const bool value_;
144 bool did_execute_;
145 };
146
147 TEST(PruneCrashReports, BinaryCondition) {
148 const struct {
149 const char* name;
150 BinaryPruneCondition::Operator op;
151 bool lhs_value;
152 bool rhs_value;
153 bool cond_result;
154 bool lhs_executed;
155 bool rhs_executed;
156 } kTests[] = {
157 {"false && false",
158 BinaryPruneCondition::AND, false, false,
159 false, true, false},
160 {"false && true",
161 BinaryPruneCondition::AND, false, true,
162 false, true, false},
163 {"true && false",
164 BinaryPruneCondition::AND, true, false,
165 false, true, true},
166 {"true && true",
167 BinaryPruneCondition::AND, true, true,
168 true, true, true},
169 {"false || false",
170 BinaryPruneCondition::OR, false, false,
171 false, true, true},
172 {"false || true",
173 BinaryPruneCondition::OR, false, true,
174 true, true, true},
175 {"true || false",
176 BinaryPruneCondition::OR, true, false,
177 true, true, false},
178 {"true || true",
179 BinaryPruneCondition::OR, true, true,
180 true, true, false},
181 };
182 for (const auto& test : kTests) {
183 SCOPED_TRACE(test.name);
184 auto lhs = new StaticCondition(test.lhs_value);
185 auto rhs = new StaticCondition(test.rhs_value);
186 BinaryPruneCondition condition(test.op, lhs, rhs);
187 CrashReportDatabase::Report report;
188 EXPECT_EQ(test.cond_result, condition.ShouldPruneReport(report));
189 EXPECT_EQ(test.lhs_executed, lhs->did_execute());
190 EXPECT_EQ(test.rhs_executed, rhs->did_execute());
191 }
192 }
193
194 MATCHER_P(TestUUID, data_1, "") {
195 return arg.data_1 == data_1;
196 }
197
198 TEST(PruneCrashReports, PruneOrder) {
199 using ::testing::_;
200 using ::testing::DoAll;
201 using ::testing::Return;
202 using ::testing::SetArgPointee;
203
204 std::vector<CrashReportDatabase::Report> reports;
205 for (int i = 0; i < 10; ++i) {
206 CrashReportDatabase::Report temp;
207 temp.uuid.data_1 = i;
208 temp.creation_time = NDaysAgo(i * 10);
209 reports.push_back(temp);
210 }
211 // The randomness from std::rand() is not, so use a better rand() instead.
212 std::random_shuffle(reports.begin(), reports.end(), [](int rand_max) {
213 return base::RandUint64() % rand_max;
214 });
215 std::vector<CrashReportDatabase::Report> pending_reports(
216 reports.begin(), reports.begin() + 5);
217 std::vector<CrashReportDatabase::Report> completed_reports(
218 reports.begin() + 5, reports.end());
219
220 MockDatabase db;
221 EXPECT_CALL(db, GetPendingReports(_)).WillOnce(DoAll(
222 SetArgPointee<0>(pending_reports),
223 Return(CrashReportDatabase::kNoError)));
224 EXPECT_CALL(db, GetCompletedReports(_)).WillOnce(DoAll(
225 SetArgPointee<0>(completed_reports),
226 Return(CrashReportDatabase::kNoError)));
227 for (size_t i = 0; i < reports.size(); ++i) {
228 EXPECT_CALL(db, DeleteReport(TestUUID(i)))
229 .WillOnce(Return(CrashReportDatabase::kNoError));
230 }
231
232 StaticCondition delete_all(true);
233 PruneCrashReportDatabase(&db, &delete_all);
234 }
235
236 } // namespace
237 } // namespace test
238 } // 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