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

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
« no previous file with comments | « 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_1k;
75 report_1k.file_path = temp_dir.path().Append(FILE_PATH_LITERAL("file1024"));
76 CrashReportDatabase::Report report_3k;
77 report_3k.file_path = temp_dir.path().Append(FILE_PATH_LITERAL("file3072"));
78
79 {
80 ScopedFileHandle scoped_file_1k(
81 LoggingOpenFileForWrite(report_1k.file_path,
82 FileWriteMode::kCreateOrFail,
83 FilePermissions::kOwnerOnly));
84 ASSERT_TRUE(scoped_file_1k.is_valid());
85
86 std::string string;
87 for (int i = 0; i < 128; ++i)
88 string.push_back(static_cast<char>(i));
89
90 for (int i = 0; i < 1024; i += string.size()) {
91 ASSERT_TRUE(LoggingWriteFile(scoped_file_1k.get(),
92 string.c_str(), string.length()));
93 }
94
95 ScopedFileHandle scoped_file_3k(
96 LoggingOpenFileForWrite(report_3k.file_path,
97 FileWriteMode::kCreateOrFail,
98 FilePermissions::kOwnerOnly));
99 ASSERT_TRUE(scoped_file_3k.is_valid());
100
101 for (int i = 0; i < 3072; i += string.size()) {
102 ASSERT_TRUE(LoggingWriteFile(scoped_file_3k.get(),
103 string.c_str(), string.length()));
104 }
105 }
106
107 {
108 DatabaseSizePruneCondition condition(1);
109 EXPECT_FALSE(condition.ShouldPruneReport(report_1k));
110 EXPECT_TRUE(condition.ShouldPruneReport(report_1k));
111 }
112
113 {
114 DatabaseSizePruneCondition condition(1);
115 EXPECT_TRUE(condition.ShouldPruneReport(report_3k));
116 }
117
118 {
119 DatabaseSizePruneCondition condition(6);
120 EXPECT_FALSE(condition.ShouldPruneReport(report_3k));
121 EXPECT_FALSE(condition.ShouldPruneReport(report_3k));
122 EXPECT_TRUE(condition.ShouldPruneReport(report_1k));
123 }
124 }
125
126 class StaticCondition final : public PruneCondition {
127 public:
128 explicit StaticCondition(bool value) : value_(value), did_execute_(false) {}
129 ~StaticCondition() {}
130
131 bool ShouldPruneReport(const CrashReportDatabase::Report& report) override {
132 did_execute_ = true;
133 return value_;
134 }
135
136 bool did_execute() const { return did_execute_; }
137
138 private:
139 const bool value_;
140 bool did_execute_;
141
142 DISALLOW_COPY_AND_ASSIGN(StaticCondition);
143 };
144
145 TEST(PruneCrashReports, BinaryCondition) {
146 const struct {
147 const char* name;
148 BinaryPruneCondition::Operator op;
149 bool lhs_value;
150 bool rhs_value;
151 bool cond_result;
152 bool lhs_executed;
153 bool rhs_executed;
154 } kTests[] = {
155 {"false && false",
156 BinaryPruneCondition::AND, false, false,
157 false, true, false},
158 {"false && true",
159 BinaryPruneCondition::AND, false, true,
160 false, true, false},
161 {"true && false",
162 BinaryPruneCondition::AND, true, false,
163 false, true, true},
164 {"true && true",
165 BinaryPruneCondition::AND, true, true,
166 true, true, true},
167 {"false || false",
168 BinaryPruneCondition::OR, false, false,
169 false, true, true},
170 {"false || true",
171 BinaryPruneCondition::OR, false, true,
172 true, true, true},
173 {"true || false",
174 BinaryPruneCondition::OR, true, false,
175 true, true, false},
176 {"true || true",
177 BinaryPruneCondition::OR, true, true,
178 true, true, false},
179 };
180 for (const auto& test : kTests) {
181 SCOPED_TRACE(test.name);
182 auto lhs = new StaticCondition(test.lhs_value);
183 auto rhs = new StaticCondition(test.rhs_value);
184 BinaryPruneCondition condition(test.op, lhs, rhs);
185 CrashReportDatabase::Report report;
186 EXPECT_EQ(test.cond_result, condition.ShouldPruneReport(report));
187 EXPECT_EQ(test.lhs_executed, lhs->did_execute());
188 EXPECT_EQ(test.rhs_executed, rhs->did_execute());
189 }
190 }
191
192 MATCHER_P(TestUUID, data_1, "") {
193 return arg.data_1 == data_1;
194 }
195
196 TEST(PruneCrashReports, PruneOrder) {
197 using ::testing::_;
198 using ::testing::DoAll;
199 using ::testing::Return;
200 using ::testing::SetArgPointee;
201
202 std::vector<CrashReportDatabase::Report> reports;
203 for (int i = 0; i < 10; ++i) {
204 CrashReportDatabase::Report temp;
205 temp.uuid.data_1 = i;
206 temp.creation_time = NDaysAgo(i * 10);
207 reports.push_back(temp);
208 }
209 // The randomness from std::rand() is not, so use a better rand() instead.
210 std::random_shuffle(reports.begin(), reports.end(), [](int rand_max) {
211 return base::RandUint64() % rand_max;
212 });
213 std::vector<CrashReportDatabase::Report> pending_reports(
214 reports.begin(), reports.begin() + 5);
215 std::vector<CrashReportDatabase::Report> completed_reports(
216 reports.begin() + 5, reports.end());
217
218 MockDatabase db;
219 EXPECT_CALL(db, GetPendingReports(_)).WillOnce(DoAll(
220 SetArgPointee<0>(pending_reports),
221 Return(CrashReportDatabase::kNoError)));
222 EXPECT_CALL(db, GetCompletedReports(_)).WillOnce(DoAll(
223 SetArgPointee<0>(completed_reports),
224 Return(CrashReportDatabase::kNoError)));
225 for (size_t i = 0; i < reports.size(); ++i) {
226 EXPECT_CALL(db, DeleteReport(TestUUID(i)))
227 .WillOnce(Return(CrashReportDatabase::kNoError));
228 }
229
230 StaticCondition delete_all(true);
231 PruneCrashReportDatabase(&db, &delete_all);
232 }
233
234 } // namespace
235 } // namespace test
236 } // namespace crashpad
OLDNEW
« no previous file with comments | « client/prune_crash_reports.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698