xref: /aosp_15_r20/external/cronet/components/metrics/reporting_service_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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.
4 
5 #include "components/metrics/reporting_service.h"
6 
7 #include <stdint.h>
8 
9 #include <deque>
10 #include <memory>
11 #include <string>
12 
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/metrics_log.h"
20 #include "components/metrics/test/test_metrics_service_client.h"
21 #include "components/prefs/testing_pref_service.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "third_party/zlib/google/compression_utils.h"
24 
25 namespace metrics {
26 
27 namespace {
28 
29 // Represent a flushed log and its metadata to be used for testing.
30 struct TestLog {
TestLogmetrics::__anone0c9e1b90111::TestLog31   explicit TestLog(const std::string& log) : log(log), user_id(std::nullopt) {}
TestLogmetrics::__anone0c9e1b90111::TestLog32   TestLog(const std::string& log, uint64_t user_id)
33       : log(log), user_id(user_id) {}
TestLogmetrics::__anone0c9e1b90111::TestLog34   TestLog(const std::string& log, uint64_t user_id, LogMetadata log_metadata)
35       : log(log), user_id(user_id), log_metadata(log_metadata) {}
36   TestLog(const TestLog& other) = default;
37   ~TestLog() = default;
38 
39   const std::string log;
40   const std::optional<uint64_t> user_id;
41   const LogMetadata log_metadata;
42 };
43 
44 const char kTestUploadUrl[] = "test_url";
45 const char kTestMimeType[] = "test_mime_type";
46 
47 class TestLogStore : public LogStore {
48  public:
49   TestLogStore() = default;
50   ~TestLogStore() override = default;
51 
AddLog(const TestLog & log)52   void AddLog(const TestLog& log) { logs_.push_back(log); }
53 
54   // LogStore:
has_unsent_logs() const55   bool has_unsent_logs() const override { return !logs_.empty(); }
has_staged_log() const56   bool has_staged_log() const override { return !staged_log_hash_.empty(); }
staged_log() const57   const std::string& staged_log() const override { return logs_.front().log; }
staged_log_hash() const58   const std::string& staged_log_hash() const override {
59     return staged_log_hash_;
60   }
staged_log_user_id() const61   std::optional<uint64_t> staged_log_user_id() const override {
62     return logs_.front().user_id;
63   }
staged_log_metadata() const64   const LogMetadata staged_log_metadata() const override {
65     return logs_.front().log_metadata;
66   }
staged_log_signature() const67   const std::string& staged_log_signature() const override {
68     return base::EmptyString();
69   }
StageNextLog()70   void StageNextLog() override {
71     if (has_unsent_logs()) {
72       staged_log_hash_ = base::SHA1HashString(logs_.front().log);
73     }
74   }
DiscardStagedLog(base::StringPiece reason)75   void DiscardStagedLog(base::StringPiece reason) override {
76     if (!has_staged_log())
77       return;
78     logs_.pop_front();
79     staged_log_hash_.clear();
80   }
MarkStagedLogAsSent()81   void MarkStagedLogAsSent() override {}
TrimAndPersistUnsentLogs(bool overwrite_in_memory_store)82   void TrimAndPersistUnsentLogs(bool overwrite_in_memory_store) override {}
LoadPersistedUnsentLogs()83   void LoadPersistedUnsentLogs() override {}
84 
85  private:
86   std::string staged_log_hash_;
87   std::deque<TestLog> logs_;
88 };
89 
90 class TestReportingService : public ReportingService {
91  public:
TestReportingService(MetricsServiceClient * client,PrefService * local_state)92   TestReportingService(MetricsServiceClient* client, PrefService* local_state)
93       : ReportingService(client,
94                          local_state,
95                          100,
96                          /*logs_event_manager=*/nullptr) {
97     Initialize();
98   }
99 
100   TestReportingService(const TestReportingService&) = delete;
101   TestReportingService& operator=(const TestReportingService&) = delete;
102 
103   ~TestReportingService() override = default;
104 
AddLog(const TestLog & log)105   void AddLog(const TestLog& log) { log_store_.AddLog(log); }
HasUnsentLogs()106   bool HasUnsentLogs() { return log_store_.has_unsent_logs(); }
107 
108  private:
109   // ReportingService:
log_store()110   LogStore* log_store() override { return &log_store_; }
GetUploadUrl() const111   GURL GetUploadUrl() const override { return GURL(kTestUploadUrl); }
GetInsecureUploadUrl() const112   GURL GetInsecureUploadUrl() const override { return GURL(kTestUploadUrl); }
upload_mime_type() const113   base::StringPiece upload_mime_type() const override { return kTestMimeType; }
service_type() const114   MetricsLogUploader::MetricServiceType service_type() const override {
115     return MetricsLogUploader::MetricServiceType::UMA;
116   }
117 
118   TestLogStore log_store_;
119 };
120 
121 class ReportingServiceTest : public testing::Test {
122  public:
ReportingServiceTest()123   ReportingServiceTest()
124       : task_runner_(new base::TestSimpleTaskRunner),
125         task_runner_current_default_handle_(task_runner_) {
126     ReportingService::RegisterPrefs(testing_local_state_.registry());
127   }
128 
129   ReportingServiceTest(const ReportingServiceTest&) = delete;
130   ReportingServiceTest& operator=(const ReportingServiceTest&) = delete;
131 
~ReportingServiceTest()132   ~ReportingServiceTest() override {}
133 
GetLocalState()134   PrefService* GetLocalState() { return &testing_local_state_; }
135 
136  protected:
137   scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
138   base::SingleThreadTaskRunner::CurrentDefaultHandle
139       task_runner_current_default_handle_;
140   TestMetricsServiceClient client_;
141 
142  private:
143   TestingPrefServiceSimple testing_local_state_;
144 };
145 
146 }  // namespace
147 
TEST_F(ReportingServiceTest,BasicTest)148 TEST_F(ReportingServiceTest, BasicTest) {
149   TestReportingService service(&client_, GetLocalState());
150   service.AddLog(TestLog("log1"));
151   service.AddLog(TestLog("log2"));
152 
153   service.EnableReporting();
154   task_runner_->RunPendingTasks();
155   EXPECT_TRUE(client_.uploader()->is_uploading());
156   EXPECT_EQ(1, client_.uploader()->reporting_info().attempt_count());
157   EXPECT_FALSE(client_.uploader()->reporting_info().has_last_response_code());
158 
159   client_.uploader()->CompleteUpload(404);
160   task_runner_->RunPendingTasks();
161   EXPECT_TRUE(client_.uploader()->is_uploading());
162   EXPECT_EQ(2, client_.uploader()->reporting_info().attempt_count());
163   EXPECT_EQ(404, client_.uploader()->reporting_info().last_response_code());
164 
165   client_.uploader()->CompleteUpload(200);
166   task_runner_->RunPendingTasks();
167   EXPECT_TRUE(client_.uploader()->is_uploading());
168   EXPECT_EQ(1, client_.uploader()->reporting_info().attempt_count());
169   EXPECT_EQ(200, client_.uploader()->reporting_info().last_response_code());
170 
171   client_.uploader()->CompleteUpload(200);
172   EXPECT_EQ(0U, task_runner_->NumPendingTasks());
173   EXPECT_FALSE(client_.uploader()->is_uploading());
174 }
175 
TEST_F(ReportingServiceTest,UserIdLogsUploadedIfUserConsented)176 TEST_F(ReportingServiceTest, UserIdLogsUploadedIfUserConsented) {
177   uint64_t user_id = 12345;
178 
179   TestReportingService service(&client_, GetLocalState());
180   service.AddLog(TestLog("log1", user_id));
181   service.AddLog(TestLog("log2", user_id));
182   service.EnableReporting();
183   client_.AllowMetricUploadForUserId(user_id);
184 
185   task_runner_->RunPendingTasks();
186   EXPECT_TRUE(client_.uploader()->is_uploading());
187   EXPECT_EQ(1, client_.uploader()->reporting_info().attempt_count());
188   EXPECT_FALSE(client_.uploader()->reporting_info().has_last_response_code());
189   client_.uploader()->CompleteUpload(200);
190 
191   // Upload 2nd log and last response code logged.
192   task_runner_->RunPendingTasks();
193   EXPECT_EQ(200, client_.uploader()->reporting_info().last_response_code());
194   EXPECT_TRUE(client_.uploader()->is_uploading());
195 
196   client_.uploader()->CompleteUpload(200);
197   EXPECT_EQ(0U, task_runner_->NumPendingTasks());
198   EXPECT_FALSE(client_.uploader()->is_uploading());
199 }
200 
TEST_F(ReportingServiceTest,UserIdLogsNotUploadedIfUserNotConsented)201 TEST_F(ReportingServiceTest, UserIdLogsNotUploadedIfUserNotConsented) {
202   TestReportingService service(&client_, GetLocalState());
203   service.AddLog(TestLog("log1", 12345));
204   service.AddLog(TestLog("log2", 12345));
205   service.EnableReporting();
206 
207   // Log with user id should never be in uploading state if user upload
208   // disabled. |client_.uploader()| should be nullptr since it is lazily
209   // created when a log is to be uploaded for the first time.
210   EXPECT_EQ(client_.uploader(), nullptr);
211 }
212 
TEST_F(ReportingServiceTest,ForceDiscard)213 TEST_F(ReportingServiceTest, ForceDiscard) {
214   TestReportingService service(&client_, GetLocalState());
215   service.AddLog(TestLog("log1"));
216 
217   service.EnableReporting();
218 
219   // Simulate the server returning a 500 error, which indicates that the server
220   // is unhealthy.
221   task_runner_->RunPendingTasks();
222   EXPECT_TRUE(client_.uploader()->is_uploading());
223   client_.uploader()->CompleteUpload(500);
224   task_runner_->RunPendingTasks();
225   // Verify that the log is not discarded so that it can be re-sent later.
226   EXPECT_TRUE(service.HasUnsentLogs());
227   EXPECT_TRUE(client_.uploader()->is_uploading());
228 
229   // Simulate the server returning a 500 error again, but this time, with
230   // |force_discard| set to true.
231   client_.uploader()->CompleteUpload(500, /*force_discard=*/true);
232   task_runner_->RunPendingTasks();
233   // Verify that the log was discarded, and that |service| is not uploading
234   // anymore since there are no more logs.
235   EXPECT_FALSE(service.HasUnsentLogs());
236   EXPECT_EQ(0U, task_runner_->NumPendingTasks());
237   EXPECT_FALSE(client_.uploader()->is_uploading());
238 }
239 
240 }  // namespace metrics
241