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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « client/prune_crash_reports.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: client/prune_crash_reports_test.cc
diff --git a/client/prune_crash_reports_test.cc b/client/prune_crash_reports_test.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6c825c810cbbd2f92af1b9257beaeef451fcaafa
--- /dev/null
+++ b/client/prune_crash_reports_test.cc
@@ -0,0 +1,236 @@
+// Copyright 2015 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "client/prune_crash_reports.h"
+
+#include <stdlib.h>
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include "base/rand_util.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "test/scoped_temp_dir.h"
+#include "util/file/file_io.h"
+
+namespace crashpad {
+namespace test {
+namespace {
+
+class MockDatabase : public CrashReportDatabase {
+ public:
+ // CrashReportDatabase:
+ MOCK_METHOD0(GetSettings, Settings*());
+ MOCK_METHOD1(PrepareNewCrashReport, OperationStatus(NewReport**));
+ MOCK_METHOD2(FinishedWritingCrashReport, OperationStatus(NewReport*, UUID*));
+ MOCK_METHOD1(ErrorWritingCrashReport, OperationStatus(NewReport*));
+ MOCK_METHOD2(LookUpCrashReport, OperationStatus(const UUID&, Report*));
+ MOCK_METHOD1(GetPendingReports, OperationStatus(std::vector<Report>*));
+ MOCK_METHOD1(GetCompletedReports, OperationStatus(std::vector<Report>*));
+ MOCK_METHOD2(GetReportForUploading,
+ OperationStatus(const UUID&, const Report**));
+ MOCK_METHOD3(RecordUploadAttempt,
+ OperationStatus(const Report*, bool, const std::string&));
+ MOCK_METHOD1(SkipReportUpload, OperationStatus(const UUID&));
+ MOCK_METHOD1(DeleteReport, OperationStatus(const UUID&));
+};
+
+time_t NDaysAgo(int num_days) {
+ return time(nullptr) - (num_days * 60 * 60 * 24);
+}
+
+TEST(PruneCrashReports, AgeCondition) {
+ CrashReportDatabase::Report report_80_days;
+ report_80_days.creation_time = NDaysAgo(80);
+
+ CrashReportDatabase::Report report_10_days;
+ report_10_days.creation_time = NDaysAgo(10);
+
+ CrashReportDatabase::Report report_30_days;
+ report_30_days.creation_time = NDaysAgo(30);
+
+ AgePruneCondition condition(30);
+ EXPECT_TRUE(condition.ShouldPruneReport(report_80_days));
+ EXPECT_FALSE(condition.ShouldPruneReport(report_10_days));
+ EXPECT_FALSE(condition.ShouldPruneReport(report_30_days));
+}
+
+TEST(PruneCrashReports, SizeCondition) {
+ ScopedTempDir temp_dir;
+
+ CrashReportDatabase::Report report_1k;
+ report_1k.file_path = temp_dir.path().Append(FILE_PATH_LITERAL("file1024"));
+ CrashReportDatabase::Report report_3k;
+ report_3k.file_path = temp_dir.path().Append(FILE_PATH_LITERAL("file3072"));
+
+ {
+ ScopedFileHandle scoped_file_1k(
+ LoggingOpenFileForWrite(report_1k.file_path,
+ FileWriteMode::kCreateOrFail,
+ FilePermissions::kOwnerOnly));
+ ASSERT_TRUE(scoped_file_1k.is_valid());
+
+ std::string string;
+ for (int i = 0; i < 128; ++i)
+ string.push_back(static_cast<char>(i));
+
+ for (int i = 0; i < 1024; i += string.size()) {
+ ASSERT_TRUE(LoggingWriteFile(scoped_file_1k.get(),
+ string.c_str(), string.length()));
+ }
+
+ ScopedFileHandle scoped_file_3k(
+ LoggingOpenFileForWrite(report_3k.file_path,
+ FileWriteMode::kCreateOrFail,
+ FilePermissions::kOwnerOnly));
+ ASSERT_TRUE(scoped_file_3k.is_valid());
+
+ for (int i = 0; i < 3072; i += string.size()) {
+ ASSERT_TRUE(LoggingWriteFile(scoped_file_3k.get(),
+ string.c_str(), string.length()));
+ }
+ }
+
+ {
+ DatabaseSizePruneCondition condition(1);
+ EXPECT_FALSE(condition.ShouldPruneReport(report_1k));
+ EXPECT_TRUE(condition.ShouldPruneReport(report_1k));
+ }
+
+ {
+ DatabaseSizePruneCondition condition(1);
+ EXPECT_TRUE(condition.ShouldPruneReport(report_3k));
+ }
+
+ {
+ DatabaseSizePruneCondition condition(6);
+ EXPECT_FALSE(condition.ShouldPruneReport(report_3k));
+ EXPECT_FALSE(condition.ShouldPruneReport(report_3k));
+ EXPECT_TRUE(condition.ShouldPruneReport(report_1k));
+ }
+}
+
+class StaticCondition final : public PruneCondition {
+ public:
+ explicit StaticCondition(bool value) : value_(value), did_execute_(false) {}
+ ~StaticCondition() {}
+
+ bool ShouldPruneReport(const CrashReportDatabase::Report& report) override {
+ did_execute_ = true;
+ return value_;
+ }
+
+ bool did_execute() const { return did_execute_; }
+
+ private:
+ const bool value_;
+ bool did_execute_;
+
+ DISALLOW_COPY_AND_ASSIGN(StaticCondition);
+};
+
+TEST(PruneCrashReports, BinaryCondition) {
+ const struct {
+ const char* name;
+ BinaryPruneCondition::Operator op;
+ bool lhs_value;
+ bool rhs_value;
+ bool cond_result;
+ bool lhs_executed;
+ bool rhs_executed;
+ } kTests[] = {
+ {"false && false",
+ BinaryPruneCondition::AND, false, false,
+ false, true, false},
+ {"false && true",
+ BinaryPruneCondition::AND, false, true,
+ false, true, false},
+ {"true && false",
+ BinaryPruneCondition::AND, true, false,
+ false, true, true},
+ {"true && true",
+ BinaryPruneCondition::AND, true, true,
+ true, true, true},
+ {"false || false",
+ BinaryPruneCondition::OR, false, false,
+ false, true, true},
+ {"false || true",
+ BinaryPruneCondition::OR, false, true,
+ true, true, true},
+ {"true || false",
+ BinaryPruneCondition::OR, true, false,
+ true, true, false},
+ {"true || true",
+ BinaryPruneCondition::OR, true, true,
+ true, true, false},
+ };
+ for (const auto& test : kTests) {
+ SCOPED_TRACE(test.name);
+ auto lhs = new StaticCondition(test.lhs_value);
+ auto rhs = new StaticCondition(test.rhs_value);
+ BinaryPruneCondition condition(test.op, lhs, rhs);
+ CrashReportDatabase::Report report;
+ EXPECT_EQ(test.cond_result, condition.ShouldPruneReport(report));
+ EXPECT_EQ(test.lhs_executed, lhs->did_execute());
+ EXPECT_EQ(test.rhs_executed, rhs->did_execute());
+ }
+}
+
+MATCHER_P(TestUUID, data_1, "") {
+ return arg.data_1 == data_1;
+}
+
+TEST(PruneCrashReports, PruneOrder) {
+ using ::testing::_;
+ using ::testing::DoAll;
+ using ::testing::Return;
+ using ::testing::SetArgPointee;
+
+ std::vector<CrashReportDatabase::Report> reports;
+ for (int i = 0; i < 10; ++i) {
+ CrashReportDatabase::Report temp;
+ temp.uuid.data_1 = i;
+ temp.creation_time = NDaysAgo(i * 10);
+ reports.push_back(temp);
+ }
+ // The randomness from std::rand() is not, so use a better rand() instead.
+ std::random_shuffle(reports.begin(), reports.end(), [](int rand_max) {
+ return base::RandUint64() % rand_max;
+ });
+ std::vector<CrashReportDatabase::Report> pending_reports(
+ reports.begin(), reports.begin() + 5);
+ std::vector<CrashReportDatabase::Report> completed_reports(
+ reports.begin() + 5, reports.end());
+
+ MockDatabase db;
+ EXPECT_CALL(db, GetPendingReports(_)).WillOnce(DoAll(
+ SetArgPointee<0>(pending_reports),
+ Return(CrashReportDatabase::kNoError)));
+ EXPECT_CALL(db, GetCompletedReports(_)).WillOnce(DoAll(
+ SetArgPointee<0>(completed_reports),
+ Return(CrashReportDatabase::kNoError)));
+ for (size_t i = 0; i < reports.size(); ++i) {
+ EXPECT_CALL(db, DeleteReport(TestUUID(i)))
+ .WillOnce(Return(CrashReportDatabase::kNoError));
+ }
+
+ StaticCondition delete_all(true);
+ PruneCrashReportDatabase(&db, &delete_all);
+}
+
+} // namespace
+} // namespace test
+} // namespace crashpad
« 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