1 // Copyright 2014 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/metrics/reporting_service.h"
13 #include "base/functional/bind.h"
14 #include "base/hash/sha1.h"
15 #include "base/strings/string_util.h"
16 #include "base/task/single_thread_task_runner.h"
17 #include "base/test/test_simple_task_runner.h"
18 #include "components/metrics/log_store.h"
19 #include "components/metrics/test/test_metrics_service_client.h"
20 #include "components/prefs/testing_pref_service.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "third_party/zlib/google/compression_utils.h"
28 // Represent a flushed log and its metadata to be used for testing.
30 explicit TestLog(const std::string& log) : log(log), user_id(absl::nullopt) {}
31 TestLog(const std::string& log, uint64_t user_id)
32 : log(log), user_id(user_id) {}
33 TestLog(const TestLog& other) = default;
36 const std::string log;
37 const absl::optional<uint64_t> user_id;
40 const char kTestUploadUrl[] = "test_url";
41 const char kTestMimeType[] = "test_mime_type";
43 class TestLogStore : public LogStore {
45 TestLogStore() = default;
46 ~TestLogStore() override = default;
48 void AddLog(const TestLog& log) { logs_.push_back(log); }
51 bool has_unsent_logs() const override { return !logs_.empty(); }
52 bool has_staged_log() const override { return !staged_log_hash_.empty(); }
53 const std::string& staged_log() const override { return logs_.front().log; }
54 const std::string& staged_log_hash() const override {
55 return staged_log_hash_;
57 absl::optional<uint64_t> staged_log_user_id() const override {
58 return logs_.front().user_id;
60 const std::string& staged_log_signature() const override {
61 return base::EmptyString();
63 void StageNextLog() override {
64 if (has_unsent_logs()) {
65 staged_log_hash_ = base::SHA1HashString(logs_.front().log);
68 void DiscardStagedLog(base::StringPiece reason) override {
69 if (!has_staged_log())
72 staged_log_hash_.clear();
74 void MarkStagedLogAsSent() override {}
75 void TrimAndPersistUnsentLogs(bool overwrite_in_memory_store) override {}
76 void LoadPersistedUnsentLogs() override {}
79 std::string staged_log_hash_;
80 std::deque<TestLog> logs_;
83 class TestReportingService : public ReportingService {
85 TestReportingService(MetricsServiceClient* client, PrefService* local_state)
86 : ReportingService(client,
89 /*logs_event_manager=*/nullptr) {
93 TestReportingService(const TestReportingService&) = delete;
94 TestReportingService& operator=(const TestReportingService&) = delete;
96 ~TestReportingService() override = default;
98 void AddLog(const TestLog& log) { log_store_.AddLog(log); }
99 bool HasUnsentLogs() { return log_store_.has_unsent_logs(); }
103 LogStore* log_store() override { return &log_store_; }
104 GURL GetUploadUrl() const override { return GURL(kTestUploadUrl); }
105 GURL GetInsecureUploadUrl() const override { return GURL(kTestUploadUrl); }
106 base::StringPiece upload_mime_type() const override { return kTestMimeType; }
107 MetricsLogUploader::MetricServiceType service_type() const override {
108 return MetricsLogUploader::MetricServiceType::UMA;
111 TestLogStore log_store_;
114 class ReportingServiceTest : public testing::Test {
116 ReportingServiceTest()
117 : task_runner_(new base::TestSimpleTaskRunner),
118 task_runner_current_default_handle_(task_runner_) {
119 ReportingService::RegisterPrefs(testing_local_state_.registry());
122 ReportingServiceTest(const ReportingServiceTest&) = delete;
123 ReportingServiceTest& operator=(const ReportingServiceTest&) = delete;
125 ~ReportingServiceTest() override {}
127 PrefService* GetLocalState() { return &testing_local_state_; }
130 scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
131 base::SingleThreadTaskRunner::CurrentDefaultHandle
132 task_runner_current_default_handle_;
133 TestMetricsServiceClient client_;
136 TestingPrefServiceSimple testing_local_state_;
141 TEST_F(ReportingServiceTest, BasicTest) {
142 TestReportingService service(&client_, GetLocalState());
143 service.AddLog(TestLog("log1"));
144 service.AddLog(TestLog("log2"));
146 service.EnableReporting();
147 task_runner_->RunPendingTasks();
148 EXPECT_TRUE(client_.uploader()->is_uploading());
149 EXPECT_EQ(1, client_.uploader()->reporting_info().attempt_count());
150 EXPECT_FALSE(client_.uploader()->reporting_info().has_last_response_code());
152 client_.uploader()->CompleteUpload(404);
153 task_runner_->RunPendingTasks();
154 EXPECT_TRUE(client_.uploader()->is_uploading());
155 EXPECT_EQ(2, client_.uploader()->reporting_info().attempt_count());
156 EXPECT_EQ(404, client_.uploader()->reporting_info().last_response_code());
158 client_.uploader()->CompleteUpload(200);
159 task_runner_->RunPendingTasks();
160 EXPECT_TRUE(client_.uploader()->is_uploading());
161 EXPECT_EQ(1, client_.uploader()->reporting_info().attempt_count());
162 EXPECT_EQ(200, client_.uploader()->reporting_info().last_response_code());
164 client_.uploader()->CompleteUpload(200);
165 EXPECT_EQ(0U, task_runner_->NumPendingTasks());
166 EXPECT_FALSE(client_.uploader()->is_uploading());
169 TEST_F(ReportingServiceTest, UserIdLogsUploadedIfUserConsented) {
170 uint64_t user_id = 12345;
172 TestReportingService service(&client_, GetLocalState());
173 service.AddLog(TestLog("log1", user_id));
174 service.AddLog(TestLog("log2", user_id));
175 service.EnableReporting();
176 client_.AllowMetricUploadForUserId(user_id);
178 task_runner_->RunPendingTasks();
179 EXPECT_TRUE(client_.uploader()->is_uploading());
180 EXPECT_EQ(1, client_.uploader()->reporting_info().attempt_count());
181 EXPECT_FALSE(client_.uploader()->reporting_info().has_last_response_code());
182 client_.uploader()->CompleteUpload(200);
184 // Upload 2nd log and last response code logged.
185 task_runner_->RunPendingTasks();
186 EXPECT_EQ(200, client_.uploader()->reporting_info().last_response_code());
187 EXPECT_TRUE(client_.uploader()->is_uploading());
189 client_.uploader()->CompleteUpload(200);
190 EXPECT_EQ(0U, task_runner_->NumPendingTasks());
191 EXPECT_FALSE(client_.uploader()->is_uploading());
194 TEST_F(ReportingServiceTest, UserIdLogsNotUploadedIfUserNotConsented) {
195 TestReportingService service(&client_, GetLocalState());
196 service.AddLog(TestLog("log1", 12345));
197 service.AddLog(TestLog("log2", 12345));
198 service.EnableReporting();
200 // Log with user id should never be in uploading state if user upload
201 // disabled. |client_.uploader()| should be nullptr since it is lazily
202 // created when a log is to be uploaded for the first time.
203 EXPECT_EQ(client_.uploader(), nullptr);
206 TEST_F(ReportingServiceTest, ForceDiscard) {
207 TestReportingService service(&client_, GetLocalState());
208 service.AddLog(TestLog("log1"));
210 service.EnableReporting();
212 // Simulate the server returning a 500 error, which indicates that the server
214 task_runner_->RunPendingTasks();
215 EXPECT_TRUE(client_.uploader()->is_uploading());
216 client_.uploader()->CompleteUpload(500);
217 task_runner_->RunPendingTasks();
218 // Verify that the log is not discarded so that it can be re-sent later.
219 EXPECT_TRUE(service.HasUnsentLogs());
220 EXPECT_TRUE(client_.uploader()->is_uploading());
222 // Simulate the server returning a 500 error again, but this time, with
223 // |force_discard| set to true.
224 client_.uploader()->CompleteUpload(500, /*force_discard=*/true);
225 task_runner_->RunPendingTasks();
226 // Verify that the log was discarded, and that |service| is not uploading
227 // anymore since there are no more logs.
228 EXPECT_FALSE(service.HasUnsentLogs());
229 EXPECT_EQ(0U, task_runner_->NumPendingTasks());
230 EXPECT_FALSE(client_.uploader()->is_uploading());
233 } // namespace metrics