xref: /aosp_15_r20/external/cronet/components/metrics/metrics_log_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/metrics_log.h"
6 
7 #include <stddef.h>
8 #include <stdint.h>
9 
10 #include <string>
11 
12 #include "base/base64.h"
13 #include "base/command_line.h"
14 #include "base/memory/ptr_util.h"
15 #include "base/metrics/bucket_ranges.h"
16 #include "base/metrics/sample_vector.h"
17 #include "base/strings/strcat.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_util.h"
20 #include "base/system/sys_info.h"
21 #include "base/test/simple_test_clock.h"
22 #include "base/test/simple_test_tick_clock.h"
23 #include "base/test/task_environment.h"
24 #include "base/time/default_clock.h"
25 #include "base/time/default_tick_clock.h"
26 #include "base/time/time.h"
27 #include "build/build_config.h"
28 #include "build/chromeos_buildflags.h"
29 #include "components/metrics/cpu_metrics_provider.h"
30 #include "components/metrics/delegating_provider.h"
31 #include "components/metrics/environment_recorder.h"
32 #include "components/metrics/metrics_pref_names.h"
33 #include "components/metrics/metrics_state_manager.h"
34 #include "components/metrics/test/test_metrics_provider.h"
35 #include "components/metrics/test/test_metrics_service_client.h"
36 #include "components/network_time/network_time_test_utils.h"
37 #include "components/prefs/pref_service.h"
38 #include "components/prefs/testing_pref_service.h"
39 #include "components/variations/active_field_trials.h"
40 #include "services/network/test/test_shared_url_loader_factory.h"
41 #include "testing/gtest/include/gtest/gtest.h"
42 #include "third_party/metrics_proto/chrome_user_metrics_extension.pb.h"
43 
44 #if BUILDFLAG(IS_ANDROID)
45 #include "base/android/build_info.h"
46 #endif
47 
48 #if BUILDFLAG(IS_WIN)
49 #include "base/win/current_module.h"
50 #endif
51 
52 #if BUILDFLAG(IS_LINUX)
53 #include "base/nix/xdg_util.h"
54 #include "base/scoped_environment_variable_override.h"
55 #endif
56 
57 namespace metrics {
58 namespace {
59 
60 const char kClientId[] = "0a94430b-18e5-43c8-a657-580f7e855ce1";
61 const int kSessionId = 127;
62 
63 class TestMetricsLog : public MetricsLog {
64  public:
TestMetricsLog(const std::string & client_id,int session_id,LogType log_type,MetricsServiceClient * client)65   TestMetricsLog(const std::string& client_id,
66                  int session_id,
67                  LogType log_type,
68                  MetricsServiceClient* client)
69       : MetricsLog(client_id, session_id, log_type, client) {}
70 
71   TestMetricsLog(const TestMetricsLog&) = delete;
72   TestMetricsLog& operator=(const TestMetricsLog&) = delete;
73 
~TestMetricsLog()74   ~TestMetricsLog() override {}
75 
uma_proto() const76   const ChromeUserMetricsExtension& uma_proto() const {
77     return *MetricsLog::uma_proto();
78   }
79 
mutable_uma_proto()80   ChromeUserMetricsExtension* mutable_uma_proto() {
81     return MetricsLog::uma_proto();
82   }
83 
system_profile() const84   const SystemProfileProto& system_profile() const {
85     return uma_proto().system_profile();
86   }
87 };
88 
89 // Returns the expected hardware class for a metrics log.
GetExpectedHardwareClass()90 std::string GetExpectedHardwareClass() {
91 #if BUILDFLAG(IS_CHROMEOS_ASH)
92   // Currently, we are relying on base/ implementation for functionality on our
93   // side which can be fragile if in the future someone decides to change that.
94   // This replicates the logic to get the hardware class for ChromeOS and this
95   // result should match with the result by calling
96   // base::SysInfo::HardwareModelName().
97   std::string board = base::SysInfo::GetLsbReleaseBoard();
98   if (board == "unknown") {
99     return "";
100   }
101   const size_t index = board.find("-signed-");
102   if (index != std::string::npos)
103     board.resize(index);
104   return base::ToUpperASCII(board);
105 #else
106   return base::SysInfo::HardwareModelName();
107 #endif
108 }
109 
110 // Sets the time in |network_time| to |time|.
UpdateNetworkTime(network_time::NetworkTimeTracker * network_time_tracker,base::TickClock * tick_clock,base::Time time)111 void UpdateNetworkTime(network_time::NetworkTimeTracker* network_time_tracker,
112                        base::TickClock* tick_clock,
113                        base::Time time) {
114   network_time_tracker->UpdateNetworkTime(
115       time,
116       base::Seconds(1),         // resolution
117       base::Milliseconds(250),  // latency
118       tick_clock->NowTicks());  // posting time
119 }
120 
121 }  // namespace
122 
123 class MetricsLogTest : public testing::Test {
124  public:
MetricsLogTest()125   MetricsLogTest() { MetricsLog::RegisterPrefs(prefs_.registry()); }
126 
127   MetricsLogTest(const MetricsLogTest&) = delete;
128   MetricsLogTest& operator=(const MetricsLogTest&) = delete;
129 
~MetricsLogTest()130   ~MetricsLogTest() override {}
131 
132  protected:
133   // Check that the values in |system_values| are filled in and expected ones
134   // correspond to the test data defined at the top of this file.
CheckSystemProfile(const SystemProfileProto & system_profile)135   void CheckSystemProfile(const SystemProfileProto& system_profile) {
136     // Check for presence of core system profile fields.
137     EXPECT_TRUE(system_profile.has_build_timestamp());
138     EXPECT_TRUE(system_profile.has_app_version());
139     EXPECT_TRUE(system_profile.has_channel());
140     EXPECT_FALSE(system_profile.has_is_extended_stable_channel());
141     EXPECT_TRUE(system_profile.has_application_locale());
142     EXPECT_TRUE(system_profile.has_client_uuid());
143 
144     const SystemProfileProto::OS& os = system_profile.os();
145     EXPECT_TRUE(os.has_name());
146     EXPECT_TRUE(os.has_version());
147 
148     // Check matching test brand code.
149     EXPECT_EQ(TestMetricsServiceClient::kBrandForTesting,
150               system_profile.brand_code());
151 
152     // Check for presence of fields set by a metrics provider.
153     const SystemProfileProto::Hardware& hardware = system_profile.hardware();
154     EXPECT_EQ(hardware.hardware_class(), GetExpectedHardwareClass());
155     EXPECT_TRUE(hardware.has_cpu());
156     EXPECT_TRUE(hardware.cpu().has_vendor_name());
157     EXPECT_TRUE(hardware.cpu().has_signature());
158     EXPECT_TRUE(hardware.cpu().has_num_cores());
159 
160     // TODO(isherman): Verify other data written into the protobuf as a result
161     // of this call.
162   }
163 
164   TestMetricsServiceClient client_;
165   TestingPrefServiceSimple prefs_;
166 };
167 
TEST_F(MetricsLogTest,FinalizedRecordId)168 TEST_F(MetricsLogTest, FinalizedRecordId) {
169   MetricsLog log1(kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client_);
170   MetricsLog log2(kClientId, kSessionId, MetricsLog::INDEPENDENT_LOG, &client_);
171   MetricsLog log3(kClientId, kSessionId, MetricsLog::INITIAL_STABILITY_LOG,
172                   &client_);
173 
174   ASSERT_FALSE(log1.uma_proto()->has_finalized_record_id());
175   ASSERT_FALSE(log2.uma_proto()->has_finalized_record_id());
176   ASSERT_FALSE(log3.uma_proto()->has_finalized_record_id());
177 
178   // Set an initial finalized record-id value in prefs, so test values are
179   // predictable.
180   prefs_.SetInteger(prefs::kMetricsLogFinalizedRecordId, 500);
181 
182   log1.AssignFinalizedRecordId(&prefs_);
183   log2.AssignFinalizedRecordId(&prefs_);
184   log3.AssignFinalizedRecordId(&prefs_);
185 
186   EXPECT_EQ(501, log1.uma_proto()->finalized_record_id());
187   EXPECT_EQ(502, log2.uma_proto()->finalized_record_id());
188   EXPECT_EQ(503, log3.uma_proto()->finalized_record_id());
189 }
190 
TEST_F(MetricsLogTest,RecordId)191 TEST_F(MetricsLogTest, RecordId) {
192   MetricsLog log1(kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client_);
193   MetricsLog log2(kClientId, kSessionId, MetricsLog::INDEPENDENT_LOG, &client_);
194   MetricsLog log3(kClientId, kSessionId, MetricsLog::INITIAL_STABILITY_LOG,
195                   &client_);
196 
197   ASSERT_FALSE(log1.uma_proto()->has_record_id());
198   ASSERT_FALSE(log2.uma_proto()->has_record_id());
199   ASSERT_FALSE(log3.uma_proto()->has_record_id());
200 
201   // Set an initial record-id value in prefs, so test values are predictable.
202   prefs_.SetInteger(prefs::kMetricsLogRecordId, 500);
203 
204   log1.AssignRecordId(&prefs_);
205   log2.AssignRecordId(&prefs_);
206   log3.AssignRecordId(&prefs_);
207 
208   EXPECT_EQ(501, log1.uma_proto()->record_id());
209   EXPECT_EQ(502, log2.uma_proto()->record_id());
210   EXPECT_EQ(503, log3.uma_proto()->record_id());
211 }
212 
TEST_F(MetricsLogTest,SessionHash)213 TEST_F(MetricsLogTest, SessionHash) {
214   MetricsLog log1(kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client_);
215   MetricsLog log2(kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client_);
216 
217   // Verify that created logs are tagged with the same session hash.
218   EXPECT_TRUE(log1.uma_proto()->system_profile().has_session_hash());
219   EXPECT_TRUE(log2.uma_proto()->system_profile().has_session_hash());
220   EXPECT_EQ(log1.uma_proto()->system_profile().session_hash(),
221             log2.uma_proto()->system_profile().session_hash());
222 }
223 
TEST_F(MetricsLogTest,LogType)224 TEST_F(MetricsLogTest, LogType) {
225   MetricsLog log1(kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client_);
226   EXPECT_EQ(MetricsLog::ONGOING_LOG, log1.log_type());
227 
228   MetricsLog log2(kClientId, kSessionId, MetricsLog::INITIAL_STABILITY_LOG,
229                   &client_);
230   EXPECT_EQ(MetricsLog::INITIAL_STABILITY_LOG, log2.log_type());
231 }
232 
TEST_F(MetricsLogTest,BasicRecord)233 TEST_F(MetricsLogTest, BasicRecord) {
234   client_.set_version_string("bogus version");
235   const std::string kOtherClientId = "0a94430b-18e5-43c8-a657-580f7e855ce2";
236   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
237   // Clears existing command line flags and sets mock flags:
238   // "--mock-flag-1 --mock-flag-2=unused_value"
239   // Hashes of these flags should be populated on the system_profile field.
240   command_line->InitFromArgv(0, nullptr);
241   command_line->AppendSwitch("mock-flag-1");
242   command_line->AppendSwitchASCII("mock-flag-2", "unused_value");
243 
244 #if BUILDFLAG(IS_LINUX)
245   base::ScopedEnvironmentVariableOverride scoped_desktop_override(
246       base::nix::kXdgCurrentDesktopEnvVar, "GNOME");
247   metrics::SystemProfileProto::OS::XdgCurrentDesktop expected_current_desktop =
248       metrics::SystemProfileProto::OS::GNOME;
249 
250   base::ScopedEnvironmentVariableOverride scoped_session_override(
251       base::nix::kXdgSessionTypeEnvVar, "wayland");
252   metrics::SystemProfileProto::OS::XdgSessionType expected_session_type =
253       metrics::SystemProfileProto::OS::WAYLAND;
254 #endif
255 
256   MetricsLog log(kOtherClientId, 137, MetricsLog::ONGOING_LOG, &client_);
257 
258   std::string encoded;
259   log.FinalizeLog(/*truncate_events=*/false, client_.GetVersionString(),
260                   log.GetCurrentClockTime(/*record_time_zone=*/true), &encoded);
261 
262   // A couple of fields are hard to mock, so these will be copied over directly
263   // for the expected output.
264   ChromeUserMetricsExtension parsed;
265   ASSERT_TRUE(parsed.ParseFromString(encoded));
266 
267   ChromeUserMetricsExtension expected;
268   expected.set_client_id(13917849739535108017ull);  // Hashed kOtherClientId
269   expected.set_session_id(137);
270 
271   SystemProfileProto* system_profile = expected.mutable_system_profile();
272   system_profile->set_app_version("bogus version");
273   // Make sure |client_uuid| in the system profile is the unhashed client id
274   // and is the same as the client id in |local_prefs|.
275   system_profile->set_client_uuid(kOtherClientId);
276   system_profile->set_channel(client_.GetChannel());
277   system_profile->set_application_locale(client_.GetApplicationLocale());
278   system_profile->set_brand_code(TestMetricsServiceClient::kBrandForTesting);
279   // Hashes of "mock-flag-1" and "mock-flag-2" from SetUpCommandLine.
280   system_profile->add_command_line_key_hash(2578836236);
281   system_profile->add_command_line_key_hash(2867288449);
282   // The session hash.
283   system_profile->set_session_hash(
284       log.uma_proto()->system_profile().session_hash());
285 
286 #if defined(ADDRESS_SANITIZER) || DCHECK_IS_ON()
287   system_profile->set_is_instrumented_build(true);
288 #endif
289   metrics::SystemProfileProto::Hardware* hardware =
290       system_profile->mutable_hardware();
291   hardware->set_cpu_architecture(base::SysInfo::OperatingSystemArchitecture());
292   auto app_os_arch = base::SysInfo::ProcessCPUArchitecture();
293   if (!app_os_arch.empty())
294     hardware->set_app_cpu_architecture(app_os_arch);
295   hardware->set_system_ram_mb(base::SysInfo::AmountOfPhysicalMemoryMB());
296   hardware->set_hardware_class(GetExpectedHardwareClass());
297 #if BUILDFLAG(IS_WIN)
298   hardware->set_dll_base(reinterpret_cast<uint64_t>(CURRENT_MODULE()));
299 #endif
300 
301 #if BUILDFLAG(IS_CHROMEOS_LACROS)
302   system_profile->mutable_os()->set_name("Lacros");
303 #elif BUILDFLAG(IS_CHROMEOS_ASH)
304   system_profile->mutable_os()->set_name("CrOS");
305 #else
306   system_profile->mutable_os()->set_name(base::SysInfo::OperatingSystemName());
307 #endif
308   system_profile->mutable_os()->set_version(
309       base::SysInfo::OperatingSystemVersion());
310 #if BUILDFLAG(IS_CHROMEOS_ASH)
311   system_profile->mutable_os()->set_kernel_version(
312       base::SysInfo::KernelVersion());
313 #elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
314   system_profile->mutable_os()->set_kernel_version(
315       base::SysInfo::OperatingSystemVersion());
316 #elif BUILDFLAG(IS_ANDROID)
317   system_profile->mutable_os()->set_build_fingerprint(
318       base::android::BuildInfo::GetInstance()->android_build_fp());
319   system_profile->set_app_package_name("test app");
320 #elif BUILDFLAG(IS_IOS)
321   system_profile->mutable_os()->set_build_number(
322       base::SysInfo::GetIOSBuildNumber());
323 #endif
324 
325 #if BUILDFLAG(IS_LINUX)
326   system_profile->mutable_os()->set_xdg_session_type(expected_session_type);
327   system_profile->mutable_os()->set_xdg_current_desktop(
328       expected_current_desktop);
329 #endif
330 
331   // Hard to mock.
332   system_profile->set_build_timestamp(
333       parsed.system_profile().build_timestamp());
334 #if BUILDFLAG(IS_ANDROID)
335   system_profile->set_installer_package(
336       parsed.system_profile().installer_package());
337 #endif
338 
339   // Not tested here; instead tested in Timestamps_* tests below.
340   expected.mutable_time_log_created()->CopyFrom(parsed.time_log_created());
341   expected.mutable_time_log_closed()->CopyFrom(parsed.time_log_closed());
342 
343   EXPECT_EQ(expected.SerializeAsString(), encoded);
344 }
345 
TEST_F(MetricsLogTest,FinalizeLog)346 TEST_F(MetricsLogTest, FinalizeLog) {
347   static const char kVersionString[] = "1";
348   static const char kNewVersionString[] = "2";
349   client_.set_version_string(kVersionString);
350 
351   TestMetricsLog log(kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client_);
352   TestMetricsLog log2(kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client_);
353 
354   // Fill logs with user actions and omnibox events. We put more than the limit
355   // to verify that when calling FinalizeLog(), we may optionally truncate
356   // those events.
357   const int kUserActionCount = internal::kUserActionEventLimit * 2;
358   for (int i = 0; i < kUserActionCount; ++i) {
359     log.RecordUserAction("BasicAction", base::TimeTicks::Now());
360     log2.RecordUserAction("BasicAction", base::TimeTicks::Now());
361   }
362   const int kOmniboxEventCount = internal::kOmniboxEventLimit * 2;
363   for (int i = 0; i < kOmniboxEventCount; ++i) {
364     // Add an empty omnibox event. Not fully realistic since these are normally
365     // supplied by a metrics provider.
366     log.mutable_uma_proto()->add_omnibox_event();
367     log2.mutable_uma_proto()->add_omnibox_event();
368   }
369 
370   // Finalize |log|. We truncate events, and we pass the same version string as
371   // the one that was used when the log was created.
372   std::string encoded;
373   log.FinalizeLog(/*truncate_events=*/true, client_.GetVersionString(),
374                   log.GetCurrentClockTime(/*record_time_zone=*/true), &encoded);
375 
376   // Finalize |log2|. We do not truncate events, and we pass a different version
377   // string than the one that was used when the log was created.
378   client_.set_version_string(kNewVersionString);
379   std::string encoded2;
380   log2.FinalizeLog(/*truncate_events=*/false, client_.GetVersionString(),
381                    log.GetCurrentClockTime(/*record_time_zone=*/true),
382                    &encoded2);
383 
384   ChromeUserMetricsExtension parsed;
385   parsed.ParseFromString(encoded);
386   ChromeUserMetricsExtension parsed2;
387   parsed2.ParseFromString(encoded2);
388 
389   // The user actions and omnibox events in |parsed| should have been truncated
390   // to the limits, while |parsed2| should be untouched.
391   EXPECT_EQ(parsed.user_action_event_size(), internal::kUserActionEventLimit);
392   EXPECT_EQ(parsed.omnibox_event_size(), internal::kOmniboxEventLimit);
393   EXPECT_EQ(parsed2.user_action_event_size(), kUserActionCount);
394   EXPECT_EQ(parsed2.omnibox_event_size(), kOmniboxEventCount);
395 
396   // |kNewVersionString| (the version string when |log2| was closed) should
397   // have been written to |parsed2| since it differs from |kVersionString|
398   // (the version string when |log2| was created). |parsed| should not have it
399   // since the version strings were the same.
400   EXPECT_EQ(parsed2.system_profile().app_version(), kVersionString);
401   EXPECT_EQ(parsed2.system_profile().log_written_by_app_version(),
402             kNewVersionString);
403   EXPECT_EQ(parsed.system_profile().app_version(), kVersionString);
404   EXPECT_FALSE(parsed.system_profile().has_log_written_by_app_version());
405 }
406 
TEST_F(MetricsLogTest,Timestamps_InitialStabilityLog)407 TEST_F(MetricsLogTest, Timestamps_InitialStabilityLog) {
408   std::unique_ptr<base::SimpleTestClock> clock =
409       std::make_unique<base::SimpleTestClock>();
410 
411   // Should not have times from initial stability logs.
412   clock->SetNow(base::Time::FromTimeT(1));
413   MetricsLog log(kClientId, kSessionId, MetricsLog::INITIAL_STABILITY_LOG,
414                  clock.get(), nullptr, &client_);
415   clock->SetNow(base::Time::FromTimeT(2));
416   std::string encoded;
417   // Don't set the close_time param since this is an initial stability log.
418   log.FinalizeLog(/*truncate_events=*/false, client_.GetVersionString(),
419                   /*close_time=*/std::nullopt, &encoded);
420   ChromeUserMetricsExtension parsed;
421   ASSERT_TRUE(parsed.ParseFromString(encoded));
422   EXPECT_FALSE(parsed.has_time_log_created());
423   EXPECT_FALSE(parsed.has_time_log_closed());
424 }
425 
TEST_F(MetricsLogTest,Timestamps_IndependentLog)426 TEST_F(MetricsLogTest, Timestamps_IndependentLog) {
427   std::unique_ptr<base::SimpleTestClock> clock =
428       std::make_unique<base::SimpleTestClock>();
429 
430   // Should not have times from independent logs.
431   clock->SetNow(base::Time::FromTimeT(1));
432   MetricsLog log(kClientId, kSessionId, MetricsLog::INDEPENDENT_LOG,
433                  clock.get(), nullptr, &client_);
434   clock->SetNow(base::Time::FromTimeT(2));
435   std::string encoded;
436   // Don't set the close_time param since this is an independent log.
437   log.FinalizeLog(/*truncate_events=*/false, client_.GetVersionString(),
438                   /*close_time=*/std::nullopt, &encoded);
439   ChromeUserMetricsExtension parsed;
440   ASSERT_TRUE(parsed.ParseFromString(encoded));
441   EXPECT_FALSE(parsed.has_time_log_created());
442   EXPECT_FALSE(parsed.has_time_log_closed());
443 }
444 
TEST_F(MetricsLogTest,Timestamps_OngoingLog)445 TEST_F(MetricsLogTest, Timestamps_OngoingLog) {
446   std::unique_ptr<base::SimpleTestClock> clock =
447       std::make_unique<base::SimpleTestClock>();
448 
449   // Should have times from regular (ongoing) logs.
450   clock->SetNow(base::Time::FromTimeT(1));
451   MetricsLog log(kClientId, kSessionId, MetricsLog::ONGOING_LOG, clock.get(),
452                  nullptr, &client_);
453   clock->SetNow(base::Time::FromTimeT(2));
454   std::string encoded;
455   log.FinalizeLog(/*truncate_events=*/false, client_.GetVersionString(),
456                   log.GetCurrentClockTime(/*record_time_zone=*/true), &encoded);
457   ChromeUserMetricsExtension parsed;
458   ASSERT_TRUE(parsed.ParseFromString(encoded));
459   EXPECT_TRUE(parsed.has_time_log_created());
460   EXPECT_EQ(parsed.time_log_created().time_sec(), 1);
461   EXPECT_EQ(parsed.time_log_created().time_source(),
462             ChromeUserMetricsExtension::RealLocalTime::CLIENT_CLOCK);
463   // The timezone should not be set in the time_log_created field.
464   EXPECT_FALSE(parsed.time_log_created().has_time_zone_offset_from_gmt_sec());
465   EXPECT_TRUE(parsed.has_time_log_closed());
466   EXPECT_EQ(parsed.time_log_closed().time_sec(), 2);
467   EXPECT_EQ(parsed.time_log_closed().time_source(),
468             ChromeUserMetricsExtension::RealLocalTime::CLIENT_CLOCK);
469   // The timezone should be set, but we don't check what it is.
470   EXPECT_TRUE(parsed.time_log_closed().has_time_zone_offset_from_gmt_sec());
471 }
472 
TEST_F(MetricsLogTest,Timestamps_OngoingLogLog_WithNetworkClockExists_AlwaysUnavailable)473 TEST_F(MetricsLogTest,
474        Timestamps_OngoingLogLog_WithNetworkClockExists_AlwaysUnavailable) {
475   // Setup a network clock that doesn't provide a timestamp (time unavailable).
476   base::test::TaskEnvironment task_environment(
477       base::test::TaskEnvironment::MainThreadType::IO);
478   std::unique_ptr<network_time::FieldTrialTest> field_trial_test(
479       new network_time::FieldTrialTest());
480   field_trial_test->SetFeatureParams(
481       true, 0.0, network_time::NetworkTimeTracker::FETCHES_ON_DEMAND_ONLY);
482   scoped_refptr<network::TestSharedURLLoaderFactory> shared_url_loader_factory =
483       base::MakeRefCounted<network::TestSharedURLLoaderFactory>();
484   TestingPrefServiceSimple pref_service;
485   network_time::NetworkTimeTracker::RegisterPrefs(pref_service.registry());
486   network_time::NetworkTimeTracker network_time_tracker(
487       std::make_unique<base::DefaultClock>(),
488       std::make_unique<base::DefaultTickClock>(), &pref_service,
489       shared_url_loader_factory, /*fetch_behavior=*/std::nullopt);
490 
491   // Set up the backup client clock.
492   TestMetricsServiceClient client;
493   std::unique_ptr<base::SimpleTestClock> clock =
494       std::make_unique<base::SimpleTestClock>();
495 
496   // Should have times from regular (ongoing) logs.  These times should come
497   // from the backup client clock, not the (unavailable) network clock.
498   clock->SetNow(base::Time::FromTimeT(1));
499   MetricsLog log(kClientId, kSessionId, MetricsLog::ONGOING_LOG, clock.get(),
500                  &network_time_tracker, &client);
501   clock->SetNow(base::Time::FromTimeT(2));
502 
503   // Check the output.
504   std::string encoded;
505   log.FinalizeLog(/*truncate_events=*/false, client_.GetVersionString(),
506                   log.GetCurrentClockTime(/*record_time_zone=*/true), &encoded);
507   ChromeUserMetricsExtension parsed;
508   ASSERT_TRUE(parsed.ParseFromString(encoded));
509   EXPECT_TRUE(parsed.has_time_log_created());
510   EXPECT_EQ(parsed.time_log_created().time_sec(), 1);
511   EXPECT_EQ(parsed.time_log_created().time_source(),
512             ChromeUserMetricsExtension::RealLocalTime::CLIENT_CLOCK);
513   // The timezone should not be set in the time_log_created field.
514   EXPECT_FALSE(parsed.time_log_created().has_time_zone_offset_from_gmt_sec());
515   EXPECT_TRUE(parsed.has_time_log_closed());
516   EXPECT_EQ(parsed.time_log_closed().time_sec(), 2);
517   EXPECT_EQ(parsed.time_log_closed().time_source(),
518             ChromeUserMetricsExtension::RealLocalTime::CLIENT_CLOCK);
519   // The timezone should be set, but we don't check what it is.
520   EXPECT_TRUE(parsed.time_log_closed().has_time_zone_offset_from_gmt_sec());
521 }
522 
TEST_F(MetricsLogTest,Timestamps_OngoingLogLog_WithNetworkClockExists_UnavailableThenAvailable)523 TEST_F(
524     MetricsLogTest,
525     Timestamps_OngoingLogLog_WithNetworkClockExists_UnavailableThenAvailable) {
526   // Setup a network clock that initially doesn't provide a timestamp (time
527   // unavailable).
528   base::test::TaskEnvironment task_environment(
529       base::test::TaskEnvironment::MainThreadType::IO);
530   std::unique_ptr<network_time::FieldTrialTest> field_trial_test(
531       new network_time::FieldTrialTest());
532   field_trial_test->SetFeatureParams(
533       true, 0.0, network_time::NetworkTimeTracker::FETCHES_ON_DEMAND_ONLY);
534   scoped_refptr<network::TestSharedURLLoaderFactory> shared_url_loader_factory =
535       base::MakeRefCounted<network::TestSharedURLLoaderFactory>();
536   TestingPrefServiceSimple pref_service;
537   network_time::NetworkTimeTracker::RegisterPrefs(pref_service.registry());
538   base::SimpleTestClock* clock = new base::SimpleTestClock;
539   base::SimpleTestTickClock* tick_clock = new base::SimpleTestTickClock();
540   // Do this to be sure that |is_null| returns false.
541   clock->Advance(base::Days(111));
542   tick_clock->Advance(base::Days(222));
543   network_time::NetworkTimeTracker network_time_tracker(
544       std::unique_ptr<base::Clock>(clock),
545       std::unique_ptr<const base::TickClock>(tick_clock), &pref_service,
546       shared_url_loader_factory, /*fetch_behavior=*/std::nullopt);
547 
548   // Should have times from regular (ongoing) logs.  The creation time should
549   // come from the backup client clock; the closure time should come from the
550   // network clock.
551   clock->SetNow(base::Time::FromTimeT(1));
552   TestMetricsServiceClient client;
553   MetricsLog log(kClientId, kSessionId, MetricsLog::ONGOING_LOG, clock,
554                  &network_time_tracker, &client);
555   // Advance the backup client clock.  (Value should not be used; merely
556   // advanced to make sure the new value doesn't show up anywhere.)
557   clock->SetNow(base::Time::FromTimeT(2));
558   // Set the network time tracker.
559   UpdateNetworkTime(&network_time_tracker, tick_clock,
560                     base::Time::FromTimeT(3));
561 
562   // Check the output.
563   std::string encoded;
564   log.FinalizeLog(/*truncate_events=*/false, client_.GetVersionString(),
565                   log.GetCurrentClockTime(/*record_time_zone=*/true), &encoded);
566   ChromeUserMetricsExtension parsed;
567   ASSERT_TRUE(parsed.ParseFromString(encoded));
568   EXPECT_TRUE(parsed.has_time_log_created());
569   EXPECT_EQ(parsed.time_log_created().time_sec(), 1);
570   EXPECT_EQ(parsed.time_log_created().time_source(),
571             ChromeUserMetricsExtension::RealLocalTime::CLIENT_CLOCK);
572   // The timezone should not be set in the time_log_created field.
573   EXPECT_FALSE(parsed.time_log_created().has_time_zone_offset_from_gmt_sec());
574   EXPECT_TRUE(parsed.has_time_log_closed());
575   EXPECT_EQ(parsed.time_log_closed().time_sec(), 3);
576   EXPECT_EQ(parsed.time_log_closed().time_source(),
577             ChromeUserMetricsExtension::RealLocalTime::NETWORK_TIME_CLOCK);
578   // The timezone should be set, but we don't check what it is.
579   EXPECT_TRUE(parsed.time_log_closed().has_time_zone_offset_from_gmt_sec());
580 }
581 
TEST_F(MetricsLogTest,Timestamps_OngoingLogLog_WithNetworkClockExists_AlwaysAvailable)582 TEST_F(MetricsLogTest,
583        Timestamps_OngoingLogLog_WithNetworkClockExists_AlwaysAvailable) {
584   // Setup a network clock that provides a timestamp.
585   base::test::TaskEnvironment task_environment(
586       base::test::TaskEnvironment::MainThreadType::IO);
587   std::unique_ptr<network_time::FieldTrialTest> field_trial_test(
588       new network_time::FieldTrialTest());
589   field_trial_test->SetFeatureParams(
590       true, 0.0, network_time::NetworkTimeTracker::FETCHES_ON_DEMAND_ONLY);
591   scoped_refptr<network::TestSharedURLLoaderFactory> shared_url_loader_factory =
592       base::MakeRefCounted<network::TestSharedURLLoaderFactory>();
593   TestingPrefServiceSimple pref_service;
594   network_time::NetworkTimeTracker::RegisterPrefs(pref_service.registry());
595   base::SimpleTestClock* clock = new base::SimpleTestClock;
596   base::SimpleTestTickClock* tick_clock = new base::SimpleTestTickClock();
597   // Do this to be sure that |is_null| returns false.
598   clock->Advance(base::Days(111));
599   tick_clock->Advance(base::Days(222));
600   network_time::NetworkTimeTracker network_time_tracker(
601       std::unique_ptr<base::Clock>(clock),
602       std::unique_ptr<const base::TickClock>(tick_clock), &pref_service,
603       shared_url_loader_factory, /*fetch_behavior=*/std::nullopt);
604 
605   // Should have times from regular (ongoing) logs.  These times should come
606   // from the network clock.
607   // Set the backup client clock time.  (Value should not be used; merely set
608   // to make sure the value doesn't show up anywhere.)
609   clock->SetNow(base::Time::FromTimeT(1));
610   // Set the network time tracker.
611   UpdateNetworkTime(&network_time_tracker, tick_clock,
612                     base::Time::FromTimeT(2));
613   TestMetricsServiceClient client;
614   MetricsLog log(kClientId, kSessionId, MetricsLog::ONGOING_LOG, clock,
615                  &network_time_tracker, &client);
616   // Advance the backup client clock.  (Value should not be used; merely
617   // advanced to make sure the new value doesn't show up anywhere.)
618   clock->SetNow(base::Time::FromTimeT(3));
619   // Advance and set the network time clock.
620   UpdateNetworkTime(&network_time_tracker, tick_clock,
621                     base::Time::FromTimeT(4));
622 
623   // Check the output.
624   std::string encoded;
625   log.FinalizeLog(/*truncate_events=*/false, client_.GetVersionString(),
626                   log.GetCurrentClockTime(/*record_time_zone=*/true), &encoded);
627   ChromeUserMetricsExtension parsed;
628   ASSERT_TRUE(parsed.ParseFromString(encoded));
629   EXPECT_TRUE(parsed.has_time_log_created());
630   // Time should be the first time returned by the network time tracker.
631   EXPECT_EQ(parsed.time_log_created().time_sec(), 2);
632   EXPECT_EQ(parsed.time_log_created().time_source(),
633             ChromeUserMetricsExtension::RealLocalTime::NETWORK_TIME_CLOCK);
634   // The timezone should not be set in the time_log_created field.
635   EXPECT_FALSE(parsed.time_log_created().has_time_zone_offset_from_gmt_sec());
636   EXPECT_TRUE(parsed.has_time_log_closed());
637   // Time should be the second time returned by the network time tracker.
638   EXPECT_EQ(parsed.time_log_closed().time_sec(), 4);
639   EXPECT_EQ(parsed.time_log_closed().time_source(),
640             ChromeUserMetricsExtension::RealLocalTime::NETWORK_TIME_CLOCK);
641   // The timezone should be set, but we don't check what it is.
642   EXPECT_TRUE(parsed.time_log_closed().has_time_zone_offset_from_gmt_sec());
643 }
644 
TEST_F(MetricsLogTest,HistogramBucketFields)645 TEST_F(MetricsLogTest, HistogramBucketFields) {
646   // Create buckets: 1-5, 5-7, 7-8, 8-9, 9-10, 10-11, 11-12.
647   base::BucketRanges ranges(8);
648   ranges.set_range(0, 1);
649   ranges.set_range(1, 5);
650   ranges.set_range(2, 7);
651   ranges.set_range(3, 8);
652   ranges.set_range(4, 9);
653   ranges.set_range(5, 10);
654   ranges.set_range(6, 11);
655   ranges.set_range(7, 12);
656 
657   base::SampleVector samples(1, &ranges);
658   samples.Accumulate(3, 1);   // Bucket 1-5.
659   samples.Accumulate(6, 1);   // Bucket 5-7.
660   samples.Accumulate(8, 1);   // Bucket 8-9. (7-8 skipped)
661   samples.Accumulate(10, 1);  // Bucket 10-11. (9-10 skipped)
662   samples.Accumulate(11, 1);  // Bucket 11-12.
663   TestMetricsLog log(kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client_);
664   log.RecordHistogramDelta("Test", samples);
665 
666   const ChromeUserMetricsExtension& uma_proto = log.uma_proto();
667   const HistogramEventProto& histogram_proto =
668       uma_proto.histogram_event(uma_proto.histogram_event_size() - 1);
669 
670   // Buckets with samples: 1-5, 5-7, 8-9, 10-11, 11-12.
671   // Should become: 1-/, 5-7, /-9, 10-/, /-12.
672   ASSERT_EQ(5, histogram_proto.bucket_size());
673 
674   // 1-5 becomes 1-/ (max is same as next min).
675   EXPECT_TRUE(histogram_proto.bucket(0).has_min());
676   EXPECT_FALSE(histogram_proto.bucket(0).has_max());
677   EXPECT_EQ(1, histogram_proto.bucket(0).min());
678 
679   // 5-7 stays 5-7 (no optimization possible).
680   EXPECT_TRUE(histogram_proto.bucket(1).has_min());
681   EXPECT_TRUE(histogram_proto.bucket(1).has_max());
682   EXPECT_EQ(5, histogram_proto.bucket(1).min());
683   EXPECT_EQ(7, histogram_proto.bucket(1).max());
684 
685   // 8-9 becomes /-9 (min is same as max - 1).
686   EXPECT_FALSE(histogram_proto.bucket(2).has_min());
687   EXPECT_TRUE(histogram_proto.bucket(2).has_max());
688   EXPECT_EQ(9, histogram_proto.bucket(2).max());
689 
690   // 10-11 becomes 10-/ (both optimizations apply, omit max is prioritized).
691   EXPECT_TRUE(histogram_proto.bucket(3).has_min());
692   EXPECT_FALSE(histogram_proto.bucket(3).has_max());
693   EXPECT_EQ(10, histogram_proto.bucket(3).min());
694 
695   // 11-12 becomes /-12 (last record must keep max, min is same as max - 1).
696   EXPECT_FALSE(histogram_proto.bucket(4).has_min());
697   EXPECT_TRUE(histogram_proto.bucket(4).has_max());
698   EXPECT_EQ(12, histogram_proto.bucket(4).max());
699 }
700 
TEST_F(MetricsLogTest,HistogramSamplesCount)701 TEST_F(MetricsLogTest, HistogramSamplesCount) {
702   const std::string histogram_name = "test";
703   TestMetricsLog log(kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client_);
704 
705   // Create buckets: 1-5.
706   base::BucketRanges ranges(2);
707   ranges.set_range(0, 1);
708   ranges.set_range(1, 5);
709 
710   // Add two samples.
711   base::SampleVector samples(1, &ranges);
712   samples.Accumulate(3, 2);
713   log.RecordHistogramDelta(histogram_name, samples);
714 
715   EXPECT_EQ(2, log.log_metadata().samples_count.value());
716 
717   // Add two more samples.
718   log.RecordHistogramDelta(histogram_name, samples);
719   EXPECT_EQ(4, log.log_metadata().samples_count.value());
720 }
721 
TEST_F(MetricsLogTest,RecordEnvironment)722 TEST_F(MetricsLogTest, RecordEnvironment) {
723   TestMetricsLog log(kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client_);
724 
725   DelegatingProvider delegating_provider;
726   auto cpu_provider = std::make_unique<metrics::CPUMetricsProvider>();
727   delegating_provider.RegisterMetricsProvider(std::move(cpu_provider));
728   log.RecordEnvironment(&delegating_provider);
729 
730   // Check non-system profile values.
731   EXPECT_EQ(MetricsLog::Hash(kClientId), log.uma_proto().client_id());
732   EXPECT_EQ(kSessionId, log.uma_proto().session_id());
733   // Check that the system profile on the log has the correct values set.
734   CheckSystemProfile(log.system_profile());
735 
736   // Call RecordEnvironment() again and verify things are are still filled in.
737   log.RecordEnvironment(&delegating_provider);
738 
739   // Check non-system profile values.
740   EXPECT_EQ(MetricsLog::Hash(kClientId), log.uma_proto().client_id());
741   EXPECT_EQ(kSessionId, log.uma_proto().session_id());
742   // Check that the system profile on the log has the correct values set.
743   CheckSystemProfile(log.system_profile());
744 }
745 
TEST_F(MetricsLogTest,RecordEnvironmentExtendedStable)746 TEST_F(MetricsLogTest, RecordEnvironmentExtendedStable) {
747   client_.set_is_extended_stable_channel(true);
748   TestMetricsLog log(kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client_);
749 
750   DelegatingProvider delegating_provider;
751   auto cpu_provider = std::make_unique<metrics::CPUMetricsProvider>();
752   delegating_provider.RegisterMetricsProvider(std::move(cpu_provider));
753   log.RecordEnvironment(&delegating_provider);
754 
755   EXPECT_TRUE(log.system_profile().has_is_extended_stable_channel());
756   EXPECT_TRUE(log.system_profile().is_extended_stable_channel());
757 }
758 
TEST_F(MetricsLogTest,RecordEnvironmentEnableDefault)759 TEST_F(MetricsLogTest, RecordEnvironmentEnableDefault) {
760   TestMetricsLog log_unknown(kClientId, kSessionId, MetricsLog::ONGOING_LOG,
761                              &client_);
762 
763   DelegatingProvider delegating_provider;
764   log_unknown.RecordEnvironment(&delegating_provider);
765   EXPECT_FALSE(log_unknown.system_profile().has_uma_default_state());
766 
767   client_.set_enable_default(EnableMetricsDefault::OPT_IN);
768   TestMetricsLog log_opt_in(kClientId, kSessionId, MetricsLog::ONGOING_LOG,
769                             &client_);
770   log_opt_in.RecordEnvironment(&delegating_provider);
771   EXPECT_TRUE(log_opt_in.system_profile().has_uma_default_state());
772   EXPECT_EQ(SystemProfileProto_UmaDefaultState_OPT_IN,
773             log_opt_in.system_profile().uma_default_state());
774 
775   client_.set_enable_default(EnableMetricsDefault::OPT_OUT);
776   TestMetricsLog log_opt_out(kClientId, kSessionId, MetricsLog::ONGOING_LOG,
777                              &client_);
778   log_opt_out.RecordEnvironment(&delegating_provider);
779   EXPECT_TRUE(log_opt_out.system_profile().has_uma_default_state());
780   EXPECT_EQ(SystemProfileProto_UmaDefaultState_OPT_OUT,
781             log_opt_out.system_profile().uma_default_state());
782 
783   client_.set_reporting_is_managed(true);
784   TestMetricsLog log_managed(kClientId, kSessionId, MetricsLog::ONGOING_LOG,
785                              &client_);
786   log_managed.RecordEnvironment(&delegating_provider);
787   EXPECT_TRUE(log_managed.system_profile().has_uma_default_state());
788   EXPECT_EQ(SystemProfileProto_UmaDefaultState_POLICY_FORCED_ENABLED,
789             log_managed.system_profile().uma_default_state());
790 }
791 
TEST_F(MetricsLogTest,InitialLogStabilityMetrics)792 TEST_F(MetricsLogTest, InitialLogStabilityMetrics) {
793   TestMetricsLog log(kClientId, kSessionId, MetricsLog::INITIAL_STABILITY_LOG,
794                      &client_);
795   TestMetricsProvider* test_provider = new TestMetricsProvider();
796   DelegatingProvider delegating_provider;
797   delegating_provider.RegisterMetricsProvider(
798       base::WrapUnique<MetricsProvider>(test_provider));
799   log.RecordEnvironment(&delegating_provider);
800   log.RecordPreviousSessionData(&delegating_provider, &prefs_);
801 
802   // The test provider should have been called upon to provide initial
803   // stability and regular stability metrics.
804   EXPECT_TRUE(test_provider->provide_initial_stability_metrics_called());
805   EXPECT_TRUE(test_provider->provide_stability_metrics_called());
806 }
807 
TEST_F(MetricsLogTest,OngoingLogStabilityMetrics)808 TEST_F(MetricsLogTest, OngoingLogStabilityMetrics) {
809   TestMetricsLog log(kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client_);
810   TestMetricsProvider* test_provider = new TestMetricsProvider();
811   DelegatingProvider delegating_provider;
812   delegating_provider.RegisterMetricsProvider(
813       base::WrapUnique<MetricsProvider>(test_provider));
814   log.RecordEnvironment(&delegating_provider);
815   log.RecordCurrentSessionData(base::TimeDelta(), base::TimeDelta(),
816                                &delegating_provider, &prefs_);
817 
818   // The test provider should have been called upon to provide regular but not
819   // initial stability metrics.
820   EXPECT_FALSE(test_provider->provide_initial_stability_metrics_called());
821   EXPECT_TRUE(test_provider->provide_stability_metrics_called());
822 }
823 
TEST_F(MetricsLogTest,ChromeChannelWrittenToProtobuf)824 TEST_F(MetricsLogTest, ChromeChannelWrittenToProtobuf) {
825   TestMetricsLog log(kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client_);
826   EXPECT_TRUE(log.uma_proto().system_profile().has_channel());
827 }
828 
TEST_F(MetricsLogTest,ProductNotSetIfDefault)829 TEST_F(MetricsLogTest, ProductNotSetIfDefault) {
830   EXPECT_EQ(ChromeUserMetricsExtension::CHROME, client_.GetProduct());
831   TestMetricsLog log(kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client_);
832   // Check that the product isn't set, since it's default and also verify the
833   // default value is indeed equal to Chrome.
834   EXPECT_FALSE(log.uma_proto().has_product());
835   EXPECT_EQ(ChromeUserMetricsExtension::CHROME, log.uma_proto().product());
836 }
837 
TEST_F(MetricsLogTest,ProductSetIfNotDefault)838 TEST_F(MetricsLogTest, ProductSetIfNotDefault) {
839   const int32_t kTestProduct = 100;
840   EXPECT_NE(ChromeUserMetricsExtension::CHROME, kTestProduct);
841   client_.set_product(kTestProduct);
842   TestMetricsLog log(kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client_);
843   // Check that the product is set to |kTestProduct|.
844   EXPECT_TRUE(log.uma_proto().has_product());
845   EXPECT_EQ(kTestProduct, log.uma_proto().product());
846 }
847 
TEST_F(MetricsLogTest,ToInstallerPackage)848 TEST_F(MetricsLogTest, ToInstallerPackage) {
849   using internal::ToInstallerPackage;
850   EXPECT_EQ(SystemProfileProto::INSTALLER_PACKAGE_NONE, ToInstallerPackage(""));
851   EXPECT_EQ(SystemProfileProto::INSTALLER_PACKAGE_GOOGLE_PLAY_STORE,
852             ToInstallerPackage("com.android.vending"));
853   EXPECT_EQ(SystemProfileProto::INSTALLER_PACKAGE_OTHER,
854             ToInstallerPackage("foo"));
855 }
856 
857 }  // namespace metrics
858