| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/browser/tracing/trace_report_database.h" |
| |
| #include <optional> |
| #include <string> |
| |
| #include "base/files/scoped_file.h" |
| #include "base/files/scoped_temp_dir.h" |
| #include "base/functional/bind.h" |
| #include "base/strings/string_util.h" |
| #include "base/time/time.h" |
| #include "base/token.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace content { |
| namespace { |
| |
| NewTraceReport MakeNewTraceReport(base::Time now = base::Time::Now()) { |
| NewTraceReport new_report; |
| new_report.uuid = base::Token::CreateRandom(); |
| new_report.scenario_name = "test_scenario"; |
| new_report.upload_rule_name = "test_rule"; |
| new_report.total_size = 42; |
| new_report.creation_time = now; |
| new_report.trace_content = "trace proto"; |
| new_report.system_profile = "system profile"; |
| new_report.skip_reason = SkipUploadReason::kNoSkip; |
| return new_report; |
| } |
| |
| } // namespace |
| |
| class TraceReportDatabaseTest : public testing::Test { |
| protected: |
| void SetUp() override { |
| ASSERT_TRUE(trace_report_.OpenDatabaseInMemoryForTesting()); |
| } |
| |
| TraceReportDatabase trace_report_; |
| }; |
| |
| TEST_F(TraceReportDatabaseTest, CreatingAndDroppingLocalTraceTable) { |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 0u); |
| } |
| |
| // Test without Initializing the database before |
| TEST(TraceReportDatabaseNoOpenTest, OpenDatabaseIfExists) { |
| base::ScopedTempDir temp_dir; |
| TraceReportDatabase trace_report; |
| |
| ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| |
| EXPECT_FALSE(trace_report.OpenDatabaseIfExists(temp_dir.GetPath())); |
| |
| EXPECT_TRUE(trace_report.OpenDatabase(temp_dir.GetPath())); |
| } |
| |
| TEST_F(TraceReportDatabaseTest, AddingNewTraceReport) { |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 0u); |
| |
| // Create Report for the local traces database. |
| NewTraceReport new_report = MakeNewTraceReport(); |
| const auto new_uuid = new_report.uuid; |
| const auto new_size = new_report.total_size; |
| |
| ASSERT_TRUE(trace_report_.AddTrace(new_report)); |
| |
| auto received_reports = trace_report_.GetAllReports(); |
| |
| // Verify that the conversion from string to Token is done correctly |
| EXPECT_EQ(new_uuid, received_reports[0].uuid); |
| EXPECT_EQ(received_reports.size(), 1u); |
| EXPECT_TRUE(received_reports[0].has_trace_content); |
| EXPECT_EQ(received_reports[0].scenario_name, "test_scenario"); |
| EXPECT_EQ(received_reports[0].upload_rule_name, "test_rule"); |
| EXPECT_EQ(received_reports[0].total_size, new_size); |
| EXPECT_EQ(received_reports[0].upload_state, ReportUploadState::kPending); |
| } |
| |
| TEST_F(TraceReportDatabaseTest, AddingNewTraceReportNoContent) { |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 0u); |
| |
| // Create Report for the local traces database. |
| NewTraceReport new_report = MakeNewTraceReport(); |
| const auto new_uuid = new_report.uuid; |
| new_report.trace_content = ""; |
| |
| ASSERT_TRUE(trace_report_.AddTrace(new_report)); |
| |
| auto received_reports = trace_report_.GetAllReports(); |
| |
| // Verify that the conversion from string to Token is done correctly |
| EXPECT_EQ(received_reports.size(), 1u); |
| EXPECT_EQ(new_uuid, received_reports[0].uuid); |
| EXPECT_FALSE(received_reports[0].has_trace_content); |
| } |
| |
| TEST_F(TraceReportDatabaseTest, RetrieveTraceContentFromReport) { |
| // Create Report for the local traces database. |
| NewTraceReport new_report = MakeNewTraceReport(); |
| ASSERT_TRUE(trace_report_.AddTrace(new_report)); |
| |
| std::optional<std::string> trace_content = |
| trace_report_.GetTraceContent(new_report.uuid); |
| EXPECT_EQ(trace_content, new_report.trace_content); |
| |
| std::optional<std::string> system_profile = |
| trace_report_.GetSystemProfile(new_report.uuid); |
| EXPECT_EQ(system_profile, new_report.system_profile); |
| } |
| |
| TEST_F(TraceReportDatabaseTest, DeletingSingleTrace) { |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 0u); |
| |
| // Create Report for the local traces database. |
| NewTraceReport new_report = MakeNewTraceReport(); |
| |
| ASSERT_TRUE(trace_report_.AddTrace(new_report)); |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 1u); |
| |
| ASSERT_TRUE(trace_report_.DeleteTrace(new_report.uuid)); |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 0u); |
| } |
| |
| TEST_F(TraceReportDatabaseTest, DeletingAllTraces) { |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 0u); |
| |
| // Create multiple NewTraceReport and add to the |
| // local_traces table. |
| |
| for (int i = 0; i < 5; i++) { |
| NewTraceReport new_report = MakeNewTraceReport(); |
| |
| ASSERT_TRUE(trace_report_.AddTrace(new_report)); |
| } |
| |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 5u); |
| |
| ASSERT_TRUE(trace_report_.DeleteAllTraces()); |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 0u); |
| } |
| |
| TEST_F(TraceReportDatabaseTest, DeleteTracesInDateRange) { |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 0u); |
| |
| const base::Time today = base::Time::Now(); |
| // Create multiple NewTraceReport and add to the local_traces table. |
| |
| for (int i = 0; i < 5; i++) { |
| NewTraceReport new_report = MakeNewTraceReport(today); |
| |
| ASSERT_TRUE(trace_report_.AddTrace(new_report)); |
| } |
| |
| for (int i = 0; i < 3; i++) { |
| NewTraceReport new_report = MakeNewTraceReport(today - base::Days(20)); |
| |
| ASSERT_TRUE(trace_report_.AddTrace(new_report)); |
| } |
| |
| for (int i = 0; i < 2; i++) { |
| NewTraceReport new_report = MakeNewTraceReport(today - base::Days(10)); |
| |
| ASSERT_TRUE(trace_report_.AddTrace(new_report)); |
| } |
| |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 10u); |
| |
| const base::Time start = base::Time(today - base::Days(20)); |
| const base::Time end = base::Time(today - base::Days(10)); |
| |
| ASSERT_TRUE(trace_report_.DeleteTracesInDateRange(start, end)); |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 5u); |
| } |
| |
| TEST_F(TraceReportDatabaseTest, DeleteTraceReportsOlderThan) { |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 0u); |
| |
| const base::Time today = base::Time::Now(); |
| |
| // Create multiple NewTraceReport and add to the local_traces table. |
| for (int i = 0; i < 5; i++) { |
| NewTraceReport new_report = MakeNewTraceReport(today); |
| ASSERT_TRUE(trace_report_.AddTrace(new_report)); |
| } |
| |
| for (int i = 0; i < 3; i++) { |
| NewTraceReport new_report = MakeNewTraceReport(today - base::Days(20)); |
| ASSERT_TRUE(trace_report_.AddTrace(new_report)); |
| } |
| |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 8u); |
| |
| ASSERT_TRUE(trace_report_.DeleteTraceReportsOlderThan(base::Days(10))); |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 5u); |
| } |
| |
| TEST_F(TraceReportDatabaseTest, DeleteUploadedTraceContentOlderThan) { |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 0u); |
| |
| const base::Time today = base::Time::Now(); |
| |
| // Create multiple NewTraceReport and add to the local_traces table. |
| for (int i = 0; i < 3; i++) { |
| NewTraceReport new_report = MakeNewTraceReport(today - base::Days(20)); |
| ASSERT_TRUE(trace_report_.AddTrace(new_report)); |
| trace_report_.UploadComplete(new_report.uuid, today); |
| } |
| for (int i = 0; i < 3; i++) { |
| NewTraceReport new_report = MakeNewTraceReport(today - base::Days(20)); |
| ASSERT_TRUE(trace_report_.AddTrace(new_report)); |
| trace_report_.UploadComplete(new_report.uuid, today - base::Days(10)); |
| } |
| |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 6u); |
| |
| ASSERT_TRUE(trace_report_.DeleteUploadedTraceContentOlderThan(base::Days(5))); |
| auto received_reports = trace_report_.GetAllReports(); |
| EXPECT_EQ(received_reports.size(), 6u); |
| for (const auto& report : received_reports) { |
| EXPECT_EQ(report.has_trace_content, |
| report.upload_time >= (today - base::Days(5))); |
| } |
| } |
| |
| TEST_F(TraceReportDatabaseTest, DeleteOldTraceContent) { |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 0u); |
| |
| const base::Time today = base::Time::Now(); |
| |
| // Create multiple NewTraceReport and add to the local_traces table. |
| for (int i = 0; i < 5; i++) { |
| NewTraceReport new_report = MakeNewTraceReport(today); |
| ASSERT_TRUE(trace_report_.AddTrace(new_report)); |
| } |
| |
| std::vector<base::Token> old_traces; |
| for (int i = 0; i < 3; i++) { |
| NewTraceReport new_report = MakeNewTraceReport(today - base::Days(20)); |
| new_report.skip_reason = SkipUploadReason::kNotAnonymized; |
| old_traces.push_back(new_report.uuid); |
| ASSERT_TRUE(trace_report_.AddTrace(new_report)); |
| } |
| |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 8u); |
| |
| ASSERT_TRUE(trace_report_.DeleteOldTraceContent(5)); |
| auto received_reports = trace_report_.GetAllReports(); |
| EXPECT_EQ(received_reports.size(), 8u); |
| for (const auto& report : received_reports) { |
| EXPECT_EQ(report.has_trace_content, |
| trace_report_.GetTraceContent(report.uuid).has_value()); |
| } |
| for (const auto& uuid : old_traces) { |
| EXPECT_FALSE(trace_report_.GetTraceContent(uuid)); |
| } |
| } |
| |
| TEST_F(TraceReportDatabaseTest, AllPendingUploadSkipped) { |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 0u); |
| |
| ASSERT_TRUE(trace_report_.AddTrace(MakeNewTraceReport())); |
| ASSERT_TRUE(trace_report_.AddTrace(MakeNewTraceReport())); |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 2u); |
| |
| ASSERT_TRUE( |
| trace_report_.AllPendingUploadSkipped(SkipUploadReason::kUploadTimedOut)); |
| |
| auto all_traces = trace_report_.GetAllReports(); |
| EXPECT_EQ(all_traces.size(), 2u); |
| EXPECT_EQ(all_traces[0].upload_state, ReportUploadState::kNotUploaded); |
| EXPECT_EQ(all_traces[0].skip_reason, SkipUploadReason::kUploadTimedOut); |
| EXPECT_EQ(all_traces[1].upload_state, ReportUploadState::kNotUploaded); |
| EXPECT_EQ(all_traces[1].skip_reason, SkipUploadReason::kUploadTimedOut); |
| } |
| |
| TEST_F(TraceReportDatabaseTest, UserRequestedUpload) { |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 0u); |
| |
| // Create Report for the local traces database. |
| NewTraceReport new_report = MakeNewTraceReport(); |
| |
| ASSERT_TRUE(trace_report_.AddTrace(new_report)); |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 1u); |
| |
| ASSERT_TRUE(trace_report_.UserRequestedUpload(new_report.uuid)); |
| |
| auto all_traces = trace_report_.GetAllReports(); |
| EXPECT_EQ(all_traces.size(), 1u); |
| EXPECT_EQ(all_traces[0].upload_state, |
| ReportUploadState::kPending_UserRequested); |
| } |
| |
| TEST_F(TraceReportDatabaseTest, UserRequestedUploadNotAnonymized) { |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 0u); |
| |
| // Create Report for the local traces database. |
| NewTraceReport new_report = MakeNewTraceReport(); |
| new_report.skip_reason = SkipUploadReason::kNotAnonymized; |
| ASSERT_TRUE(trace_report_.AddTrace(new_report)); |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 1u); |
| |
| ASSERT_TRUE(trace_report_.UserRequestedUpload(new_report.uuid)); |
| |
| auto all_traces = trace_report_.GetAllReports(); |
| EXPECT_EQ(all_traces.size(), 1u); |
| EXPECT_EQ(all_traces[0].upload_state, ReportUploadState::kNotUploaded); |
| EXPECT_EQ(all_traces[0].skip_reason, SkipUploadReason::kNotAnonymized); |
| } |
| |
| TEST_F(TraceReportDatabaseTest, UploadComplete) { |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 0u); |
| |
| // Create Report for the local traces database. |
| NewTraceReport new_report = MakeNewTraceReport(); |
| const auto report_uuid = new_report.uuid; |
| |
| ASSERT_TRUE(trace_report_.AddTrace(new_report)); |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 1u); |
| |
| auto uploaded_time = base::Time::Now(); |
| ASSERT_TRUE(trace_report_.UploadComplete(report_uuid, uploaded_time)); |
| |
| auto all_traces = trace_report_.GetAllReports(); |
| EXPECT_EQ(all_traces.size(), 1u); |
| EXPECT_EQ(all_traces[0].upload_state, ReportUploadState::kUploaded); |
| EXPECT_EQ(all_traces[0].upload_time, uploaded_time); |
| |
| // Trace content is kept alive for a few days after being uploaded. |
| EXPECT_TRUE(trace_report_.GetTraceContent(report_uuid)); |
| } |
| |
| TEST_F(TraceReportDatabaseTest, UploadSkipped) { |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 0u); |
| |
| // Create Report for the local traces database. |
| NewTraceReport new_report = MakeNewTraceReport(); |
| const auto report_uuid = new_report.uuid; |
| |
| ASSERT_TRUE(trace_report_.AddTrace(new_report)); |
| EXPECT_EQ(trace_report_.GetAllReports().size(), 1u); |
| |
| ASSERT_TRUE(trace_report_.UploadSkipped(report_uuid, |
| SkipUploadReason::kUploadTimedOut)); |
| |
| auto all_traces = trace_report_.GetAllReports(); |
| EXPECT_EQ(all_traces.size(), 1u); |
| EXPECT_EQ(all_traces[0].upload_state, ReportUploadState::kNotUploaded); |
| EXPECT_EQ(all_traces[0].skip_reason, SkipUploadReason::kUploadTimedOut); |
| } |
| |
| TEST_F(TraceReportDatabaseTest, GetNextReportPendingUpload) { |
| EXPECT_FALSE(trace_report_.GetNextReportPendingUpload()); |
| |
| // Create Report for the local traces database. |
| NewTraceReport new_report = MakeNewTraceReport(); |
| |
| const auto copie_value = new_report.uuid; |
| |
| ASSERT_TRUE(trace_report_.AddTrace(new_report)); |
| |
| auto upload_report = trace_report_.GetNextReportPendingUpload(); |
| ASSERT_TRUE(upload_report); |
| EXPECT_EQ(upload_report->uuid, copie_value); |
| |
| auto uploaded_time = base::Time::Now(); |
| ASSERT_TRUE(trace_report_.UploadComplete(copie_value, uploaded_time)); |
| |
| EXPECT_FALSE(trace_report_.GetNextReportPendingUpload()); |
| } |
| |
| TEST_F(TraceReportDatabaseTest, UploadCountSince) { |
| const base::Time now = base::Time::Now(); |
| EXPECT_EQ(0u, trace_report_.UploadCountSince("test_scenario", "test_rule", |
| now - base::Days(2))); |
| |
| // Create Report for the local traces database. |
| NewTraceReport new_report = MakeNewTraceReport(now - base::Days(1)); |
| ASSERT_TRUE(trace_report_.AddTrace(new_report)); |
| |
| EXPECT_EQ(1u, trace_report_.UploadCountSince("test_scenario", "test_rule", |
| now - base::Days(2))); |
| EXPECT_EQ(0u, |
| trace_report_.UploadCountSince("test_scenario", "test_rule", now)); |
| EXPECT_EQ(0u, trace_report_.UploadCountSince("test_scenario2", "test_rule", |
| now - base::Days(2))); |
| EXPECT_EQ(0u, trace_report_.UploadCountSince("test_scenario", "test_rule2", |
| now - base::Days(2))); |
| } |
| |
| TEST_F(TraceReportDatabaseTest, GetScenarioCounts) { |
| const base::Time now = base::Time::Now(); |
| EXPECT_EQ(0u, |
| trace_report_.GetScenarioCountsSince(now - base::Days(2)).size()); |
| |
| // Create Report for the local traces database. |
| NewTraceReport new_report = MakeNewTraceReport(); |
| |
| ASSERT_TRUE(trace_report_.AddTrace(new_report)); |
| auto scenario_counts = |
| trace_report_.GetScenarioCountsSince(now - base::Days(2)); |
| |
| EXPECT_EQ(1U, scenario_counts.size()); |
| EXPECT_EQ(1U, scenario_counts["test_scenario"]); |
| } |
| |
| } // namespace content |