• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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,RecordId)168 TEST_F(MetricsLogTest, RecordId) {
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_record_id());
175   ASSERT_FALSE(log2.uma_proto()->has_record_id());
176   ASSERT_FALSE(log3.uma_proto()->has_record_id());
177 
178   // Set an initial record-id value in prefs, so test values are predictable.
179   prefs_.SetInteger(prefs::kMetricsLogRecordId, 500);
180 
181   log1.AssignRecordId(&prefs_);
182   log2.AssignRecordId(&prefs_);
183   log3.AssignRecordId(&prefs_);
184 
185   EXPECT_EQ(501, log1.uma_proto()->record_id());
186   EXPECT_EQ(502, log2.uma_proto()->record_id());
187   EXPECT_EQ(503, log3.uma_proto()->record_id());
188 }
189 
TEST_F(MetricsLogTest,LogType)190 TEST_F(MetricsLogTest, LogType) {
191   MetricsLog log1(kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client_);
192   EXPECT_EQ(MetricsLog::ONGOING_LOG, log1.log_type());
193 
194   MetricsLog log2(kClientId, kSessionId, MetricsLog::INITIAL_STABILITY_LOG,
195                   &client_);
196   EXPECT_EQ(MetricsLog::INITIAL_STABILITY_LOG, log2.log_type());
197 }
198 
TEST_F(MetricsLogTest,BasicRecord)199 TEST_F(MetricsLogTest, BasicRecord) {
200   client_.set_version_string("bogus version");
201   const std::string kOtherClientId = "0a94430b-18e5-43c8-a657-580f7e855ce2";
202   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
203   // Clears existing command line flags and sets mock flags:
204   // "--mock-flag-1 --mock-flag-2=unused_value"
205   // Hashes of these flags should be populated on the system_profile field.
206   command_line->InitFromArgv(0, nullptr);
207   command_line->AppendSwitch("mock-flag-1");
208   command_line->AppendSwitchASCII("mock-flag-2", "unused_value");
209 
210 #if BUILDFLAG(IS_LINUX)
211   base::ScopedEnvironmentVariableOverride scoped_desktop_override(
212       base::nix::kXdgCurrentDesktopEnvVar, "GNOME");
213   metrics::SystemProfileProto::OS::XdgCurrentDesktop expected_current_desktop =
214       metrics::SystemProfileProto::OS::GNOME;
215 
216   base::ScopedEnvironmentVariableOverride scoped_session_override(
217       base::nix::kXdgSessionTypeEnvVar, "wayland");
218   metrics::SystemProfileProto::OS::XdgSessionType expected_session_type =
219       metrics::SystemProfileProto::OS::WAYLAND;
220 #endif
221 
222   MetricsLog log(kOtherClientId, 137, MetricsLog::ONGOING_LOG, &client_);
223 
224   std::string encoded;
225   log.FinalizeLog(/*truncate_events=*/false, client_.GetVersionString(),
226                   log.GetCurrentClockTime(/*record_time_zone=*/true), &encoded);
227 
228   // A couple of fields are hard to mock, so these will be copied over directly
229   // for the expected output.
230   ChromeUserMetricsExtension parsed;
231   ASSERT_TRUE(parsed.ParseFromString(encoded));
232 
233   ChromeUserMetricsExtension expected;
234   expected.set_client_id(13917849739535108017ull);  // Hashed kOtherClientId
235   expected.set_session_id(137);
236 
237   SystemProfileProto* system_profile = expected.mutable_system_profile();
238   system_profile->set_app_version("bogus version");
239   // Make sure |client_uuid| in the system profile is the unhashed client id
240   // and is the same as the client id in |local_prefs|.
241   system_profile->set_client_uuid(kOtherClientId);
242   system_profile->set_channel(client_.GetChannel());
243   system_profile->set_application_locale(client_.GetApplicationLocale());
244   system_profile->set_brand_code(TestMetricsServiceClient::kBrandForTesting);
245   // Hashes of "mock-flag-1" and "mock-flag-2" from SetUpCommandLine.
246   system_profile->add_command_line_key_hash(2578836236);
247   system_profile->add_command_line_key_hash(2867288449);
248 
249 #if defined(ADDRESS_SANITIZER) || DCHECK_IS_ON()
250   system_profile->set_is_instrumented_build(true);
251 #endif
252   metrics::SystemProfileProto::Hardware* hardware =
253       system_profile->mutable_hardware();
254   hardware->set_cpu_architecture(base::SysInfo::OperatingSystemArchitecture());
255   auto app_os_arch = base::SysInfo::ProcessCPUArchitecture();
256   if (!app_os_arch.empty())
257     hardware->set_app_cpu_architecture(app_os_arch);
258   hardware->set_system_ram_mb(base::SysInfo::AmountOfPhysicalMemoryMB());
259   hardware->set_hardware_class(GetExpectedHardwareClass());
260 #if BUILDFLAG(IS_WIN)
261   hardware->set_dll_base(reinterpret_cast<uint64_t>(CURRENT_MODULE()));
262 #endif
263 
264 #if BUILDFLAG(IS_CHROMEOS_LACROS)
265   system_profile->mutable_os()->set_name("Lacros");
266 #elif BUILDFLAG(IS_CHROMEOS_ASH)
267   system_profile->mutable_os()->set_name("CrOS");
268 #else
269   system_profile->mutable_os()->set_name(base::SysInfo::OperatingSystemName());
270 #endif
271   system_profile->mutable_os()->set_version(
272       base::SysInfo::OperatingSystemVersion());
273 #if BUILDFLAG(IS_CHROMEOS_ASH)
274   system_profile->mutable_os()->set_kernel_version(
275       base::SysInfo::KernelVersion());
276 #elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
277   system_profile->mutable_os()->set_kernel_version(
278       base::SysInfo::OperatingSystemVersion());
279 #elif BUILDFLAG(IS_ANDROID)
280   system_profile->mutable_os()->set_build_fingerprint(
281       base::android::BuildInfo::GetInstance()->android_build_fp());
282   system_profile->set_app_package_name("test app");
283 #elif BUILDFLAG(IS_IOS)
284   system_profile->mutable_os()->set_build_number(
285       base::SysInfo::GetIOSBuildNumber());
286 #endif
287 
288 #if BUILDFLAG(IS_LINUX)
289   system_profile->mutable_os()->set_xdg_session_type(expected_session_type);
290   system_profile->mutable_os()->set_xdg_current_desktop(
291       expected_current_desktop);
292 #endif
293 
294   // Hard to mock.
295   system_profile->set_build_timestamp(
296       parsed.system_profile().build_timestamp());
297 #if BUILDFLAG(IS_ANDROID)
298   system_profile->set_installer_package(
299       parsed.system_profile().installer_package());
300 #endif
301 
302   // Not tested here; instead tested in Timestamps_* tests below.
303   expected.mutable_time_log_created()->CopyFrom(parsed.time_log_created());
304   expected.mutable_time_log_closed()->CopyFrom(parsed.time_log_closed());
305 
306   EXPECT_EQ(expected.SerializeAsString(), encoded);
307 }
308 
TEST_F(MetricsLogTest,FinalizeLog)309 TEST_F(MetricsLogTest, FinalizeLog) {
310   static const char kVersionString[] = "1";
311   static const char kNewVersionString[] = "2";
312   client_.set_version_string(kVersionString);
313 
314   TestMetricsLog log(kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client_);
315   TestMetricsLog log2(kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client_);
316 
317   // Fill logs with user actions and omnibox events. We put more than the limit
318   // to verify that when calling FinalizeLog(), we may optionally truncate
319   // those events.
320   const int kUserActionCount = internal::kUserActionEventLimit * 2;
321   for (int i = 0; i < kUserActionCount; ++i) {
322     log.RecordUserAction("BasicAction", base::TimeTicks::Now());
323     log2.RecordUserAction("BasicAction", base::TimeTicks::Now());
324   }
325   const int kOmniboxEventCount = internal::kOmniboxEventLimit * 2;
326   for (int i = 0; i < kOmniboxEventCount; ++i) {
327     // Add an empty omnibox event. Not fully realistic since these are normally
328     // supplied by a metrics provider.
329     log.mutable_uma_proto()->add_omnibox_event();
330     log2.mutable_uma_proto()->add_omnibox_event();
331   }
332 
333   // Finalize |log|. We truncate events, and we pass the same version string as
334   // the one that was used when the log was created.
335   std::string encoded;
336   log.FinalizeLog(/*truncate_events=*/true, client_.GetVersionString(),
337                   log.GetCurrentClockTime(/*record_time_zone=*/true), &encoded);
338 
339   // Finalize |log2|. We do not truncate events, and we pass a different version
340   // string than the one that was used when the log was created.
341   client_.set_version_string(kNewVersionString);
342   std::string encoded2;
343   log2.FinalizeLog(/*truncate_events=*/false, client_.GetVersionString(),
344                    log.GetCurrentClockTime(/*record_time_zone=*/true),
345                    &encoded2);
346 
347   ChromeUserMetricsExtension parsed;
348   parsed.ParseFromString(encoded);
349   ChromeUserMetricsExtension parsed2;
350   parsed2.ParseFromString(encoded2);
351 
352   // The user actions and omnibox events in |parsed| should have been truncated
353   // to the limits, while |parsed2| should be untouched.
354   EXPECT_EQ(parsed.user_action_event_size(), internal::kUserActionEventLimit);
355   EXPECT_EQ(parsed.omnibox_event_size(), internal::kOmniboxEventLimit);
356   EXPECT_EQ(parsed2.user_action_event_size(), kUserActionCount);
357   EXPECT_EQ(parsed2.omnibox_event_size(), kOmniboxEventCount);
358 
359   // |kNewVersionString| (the version string when |log2| was closed) should
360   // have been written to |parsed2| since it differs from |kVersionString|
361   // (the version string when |log2| was created). |parsed| should not have it
362   // since the version strings were the same.
363   EXPECT_EQ(parsed2.system_profile().app_version(), kVersionString);
364   EXPECT_EQ(parsed2.system_profile().log_written_by_app_version(),
365             kNewVersionString);
366   EXPECT_EQ(parsed.system_profile().app_version(), kVersionString);
367   EXPECT_FALSE(parsed.system_profile().has_log_written_by_app_version());
368 }
369 
TEST_F(MetricsLogTest,Timestamps_InitialStabilityLog)370 TEST_F(MetricsLogTest, Timestamps_InitialStabilityLog) {
371   std::unique_ptr<base::SimpleTestClock> clock =
372       std::make_unique<base::SimpleTestClock>();
373 
374   // Should not have times from initial stability logs.
375   clock->SetNow(base::Time::FromTimeT(1));
376   MetricsLog log(kClientId, kSessionId, MetricsLog::INITIAL_STABILITY_LOG,
377                  clock.get(), nullptr, &client_);
378   clock->SetNow(base::Time::FromTimeT(2));
379   std::string encoded;
380   // Don't set the close_time param since this is an initial stability log.
381   log.FinalizeLog(/*truncate_events=*/false, client_.GetVersionString(),
382                   /*close_time=*/absl::nullopt, &encoded);
383   ChromeUserMetricsExtension parsed;
384   ASSERT_TRUE(parsed.ParseFromString(encoded));
385   EXPECT_FALSE(parsed.has_time_log_created());
386   EXPECT_FALSE(parsed.has_time_log_closed());
387 }
388 
TEST_F(MetricsLogTest,Timestamps_IndependentLog)389 TEST_F(MetricsLogTest, Timestamps_IndependentLog) {
390   std::unique_ptr<base::SimpleTestClock> clock =
391       std::make_unique<base::SimpleTestClock>();
392 
393   // Should not have times from independent logs.
394   clock->SetNow(base::Time::FromTimeT(1));
395   MetricsLog log(kClientId, kSessionId, MetricsLog::INDEPENDENT_LOG,
396                  clock.get(), nullptr, &client_);
397   clock->SetNow(base::Time::FromTimeT(2));
398   std::string encoded;
399   // Don't set the close_time param since this is an independent log.
400   log.FinalizeLog(/*truncate_events=*/false, client_.GetVersionString(),
401                   /*close_time=*/absl::nullopt, &encoded);
402   ChromeUserMetricsExtension parsed;
403   ASSERT_TRUE(parsed.ParseFromString(encoded));
404   EXPECT_FALSE(parsed.has_time_log_created());
405   EXPECT_FALSE(parsed.has_time_log_closed());
406 }
407 
TEST_F(MetricsLogTest,Timestamps_OngoingLog)408 TEST_F(MetricsLogTest, Timestamps_OngoingLog) {
409   std::unique_ptr<base::SimpleTestClock> clock =
410       std::make_unique<base::SimpleTestClock>();
411 
412   // Should have times from regular (ongoing) logs.
413   clock->SetNow(base::Time::FromTimeT(1));
414   MetricsLog log(kClientId, kSessionId, MetricsLog::ONGOING_LOG, clock.get(),
415                  nullptr, &client_);
416   clock->SetNow(base::Time::FromTimeT(2));
417   std::string encoded;
418   log.FinalizeLog(/*truncate_events=*/false, client_.GetVersionString(),
419                   log.GetCurrentClockTime(/*record_time_zone=*/true), &encoded);
420   ChromeUserMetricsExtension parsed;
421   ASSERT_TRUE(parsed.ParseFromString(encoded));
422   EXPECT_TRUE(parsed.has_time_log_created());
423   EXPECT_EQ(parsed.time_log_created().time_sec(), 1);
424   EXPECT_EQ(parsed.time_log_created().time_source(),
425             ChromeUserMetricsExtension::RealLocalTime::CLIENT_CLOCK);
426   // The timezone should not be set in the time_log_created field.
427   EXPECT_FALSE(parsed.time_log_created().has_time_zone_offset_from_gmt_sec());
428   EXPECT_TRUE(parsed.has_time_log_closed());
429   EXPECT_EQ(parsed.time_log_closed().time_sec(), 2);
430   EXPECT_EQ(parsed.time_log_closed().time_source(),
431             ChromeUserMetricsExtension::RealLocalTime::CLIENT_CLOCK);
432   // The timezone should be set, but we don't check what it is.
433   EXPECT_TRUE(parsed.time_log_closed().has_time_zone_offset_from_gmt_sec());
434 }
435 
TEST_F(MetricsLogTest,Timestamps_OngoingLogLog_WithNetworkClockExists_AlwaysUnavailable)436 TEST_F(MetricsLogTest,
437        Timestamps_OngoingLogLog_WithNetworkClockExists_AlwaysUnavailable) {
438   // Setup a network clock that doesn't provide a timestamp (time unavailable).
439   base::test::TaskEnvironment task_environment(
440       base::test::TaskEnvironment::MainThreadType::IO);
441   std::unique_ptr<network_time::FieldTrialTest> field_trial_test(
442       new network_time::FieldTrialTest());
443   field_trial_test->SetFeatureParams(
444       true, 0.0, network_time::NetworkTimeTracker::FETCHES_ON_DEMAND_ONLY,
445       network_time::NetworkTimeTracker::ClockDriftSamples::NO_SAMPLES);
446   scoped_refptr<network::TestSharedURLLoaderFactory> shared_url_loader_factory =
447       base::MakeRefCounted<network::TestSharedURLLoaderFactory>();
448   TestingPrefServiceSimple pref_service;
449   network_time::NetworkTimeTracker::RegisterPrefs(pref_service.registry());
450   network_time::NetworkTimeTracker network_time_tracker(
451       std::make_unique<base::DefaultClock>(),
452       std::make_unique<base::DefaultTickClock>(), &pref_service,
453       shared_url_loader_factory);
454 
455   // Set up the backup client clock.
456   TestMetricsServiceClient client;
457   std::unique_ptr<base::SimpleTestClock> clock =
458       std::make_unique<base::SimpleTestClock>();
459 
460   // Should have times from regular (ongoing) logs.  These times should come
461   // from the backup client clock, not the (unavailable) network clock.
462   clock->SetNow(base::Time::FromTimeT(1));
463   MetricsLog log(kClientId, kSessionId, MetricsLog::ONGOING_LOG, clock.get(),
464                  &network_time_tracker, &client);
465   clock->SetNow(base::Time::FromTimeT(2));
466 
467   // Check the output.
468   std::string encoded;
469   log.FinalizeLog(/*truncate_events=*/false, client_.GetVersionString(),
470                   log.GetCurrentClockTime(/*record_time_zone=*/true), &encoded);
471   ChromeUserMetricsExtension parsed;
472   ASSERT_TRUE(parsed.ParseFromString(encoded));
473   EXPECT_TRUE(parsed.has_time_log_created());
474   EXPECT_EQ(parsed.time_log_created().time_sec(), 1);
475   EXPECT_EQ(parsed.time_log_created().time_source(),
476             ChromeUserMetricsExtension::RealLocalTime::CLIENT_CLOCK);
477   // The timezone should not be set in the time_log_created field.
478   EXPECT_FALSE(parsed.time_log_created().has_time_zone_offset_from_gmt_sec());
479   EXPECT_TRUE(parsed.has_time_log_closed());
480   EXPECT_EQ(parsed.time_log_closed().time_sec(), 2);
481   EXPECT_EQ(parsed.time_log_closed().time_source(),
482             ChromeUserMetricsExtension::RealLocalTime::CLIENT_CLOCK);
483   // The timezone should be set, but we don't check what it is.
484   EXPECT_TRUE(parsed.time_log_closed().has_time_zone_offset_from_gmt_sec());
485 }
486 
TEST_F(MetricsLogTest,Timestamps_OngoingLogLog_WithNetworkClockExists_UnavailableThenAvailable)487 TEST_F(
488     MetricsLogTest,
489     Timestamps_OngoingLogLog_WithNetworkClockExists_UnavailableThenAvailable) {
490   // Setup a network clock that initially doesn't provide a timestamp (time
491   // unavailable).
492   base::test::TaskEnvironment task_environment(
493       base::test::TaskEnvironment::MainThreadType::IO);
494   std::unique_ptr<network_time::FieldTrialTest> field_trial_test(
495       new network_time::FieldTrialTest());
496   field_trial_test->SetFeatureParams(
497       true, 0.0, network_time::NetworkTimeTracker::FETCHES_ON_DEMAND_ONLY,
498       network_time::NetworkTimeTracker::ClockDriftSamples::NO_SAMPLES);
499   scoped_refptr<network::TestSharedURLLoaderFactory> shared_url_loader_factory =
500       base::MakeRefCounted<network::TestSharedURLLoaderFactory>();
501   TestingPrefServiceSimple pref_service;
502   network_time::NetworkTimeTracker::RegisterPrefs(pref_service.registry());
503   base::SimpleTestClock* clock = new base::SimpleTestClock;
504   base::SimpleTestTickClock* tick_clock = new base::SimpleTestTickClock();
505   // Do this to be sure that |is_null| returns false.
506   clock->Advance(base::Days(111));
507   tick_clock->Advance(base::Days(222));
508   network_time::NetworkTimeTracker network_time_tracker(
509       std::unique_ptr<base::Clock>(clock),
510       std::unique_ptr<const base::TickClock>(tick_clock), &pref_service,
511       shared_url_loader_factory);
512 
513   // Should have times from regular (ongoing) logs.  The creation time should
514   // come from the backup client clock; the closure time should come from the
515   // network clock.
516   clock->SetNow(base::Time::FromTimeT(1));
517   TestMetricsServiceClient client;
518   MetricsLog log(kClientId, kSessionId, MetricsLog::ONGOING_LOG, clock,
519                  &network_time_tracker, &client);
520   // Advance the backup client clock.  (Value should not be used; merely
521   // advanced to make sure the new value doesn't show up anywhere.)
522   clock->SetNow(base::Time::FromTimeT(2));
523   // Set the network time tracker.
524   UpdateNetworkTime(&network_time_tracker, tick_clock,
525                     base::Time::FromTimeT(3));
526 
527   // Check the output.
528   std::string encoded;
529   log.FinalizeLog(/*truncate_events=*/false, client_.GetVersionString(),
530                   log.GetCurrentClockTime(/*record_time_zone=*/true), &encoded);
531   ChromeUserMetricsExtension parsed;
532   ASSERT_TRUE(parsed.ParseFromString(encoded));
533   EXPECT_TRUE(parsed.has_time_log_created());
534   EXPECT_EQ(parsed.time_log_created().time_sec(), 1);
535   EXPECT_EQ(parsed.time_log_created().time_source(),
536             ChromeUserMetricsExtension::RealLocalTime::CLIENT_CLOCK);
537   // The timezone should not be set in the time_log_created field.
538   EXPECT_FALSE(parsed.time_log_created().has_time_zone_offset_from_gmt_sec());
539   EXPECT_TRUE(parsed.has_time_log_closed());
540   EXPECT_EQ(parsed.time_log_closed().time_sec(), 3);
541   EXPECT_EQ(parsed.time_log_closed().time_source(),
542             ChromeUserMetricsExtension::RealLocalTime::NETWORK_TIME_CLOCK);
543   // The timezone should be set, but we don't check what it is.
544   EXPECT_TRUE(parsed.time_log_closed().has_time_zone_offset_from_gmt_sec());
545 }
546 
TEST_F(MetricsLogTest,Timestamps_OngoingLogLog_WithNetworkClockExists_AlwaysAvailable)547 TEST_F(MetricsLogTest,
548        Timestamps_OngoingLogLog_WithNetworkClockExists_AlwaysAvailable) {
549   // Setup a network clock that provides a timestamp.
550   base::test::TaskEnvironment task_environment(
551       base::test::TaskEnvironment::MainThreadType::IO);
552   std::unique_ptr<network_time::FieldTrialTest> field_trial_test(
553       new network_time::FieldTrialTest());
554   field_trial_test->SetFeatureParams(
555       true, 0.0, network_time::NetworkTimeTracker::FETCHES_ON_DEMAND_ONLY,
556       network_time::NetworkTimeTracker::ClockDriftSamples::NO_SAMPLES);
557   scoped_refptr<network::TestSharedURLLoaderFactory> shared_url_loader_factory =
558       base::MakeRefCounted<network::TestSharedURLLoaderFactory>();
559   TestingPrefServiceSimple pref_service;
560   network_time::NetworkTimeTracker::RegisterPrefs(pref_service.registry());
561   base::SimpleTestClock* clock = new base::SimpleTestClock;
562   base::SimpleTestTickClock* tick_clock = new base::SimpleTestTickClock();
563   // Do this to be sure that |is_null| returns false.
564   clock->Advance(base::Days(111));
565   tick_clock->Advance(base::Days(222));
566   network_time::NetworkTimeTracker network_time_tracker(
567       std::unique_ptr<base::Clock>(clock),
568       std::unique_ptr<const base::TickClock>(tick_clock), &pref_service,
569       shared_url_loader_factory);
570 
571   // Should have times from regular (ongoing) logs.  These times should come
572   // from the network clock.
573   // Set the backup client clock time.  (Value should not be used; merely set
574   // to make sure the value doesn't show up anywhere.)
575   clock->SetNow(base::Time::FromTimeT(1));
576   // Set the network time tracker.
577   UpdateNetworkTime(&network_time_tracker, tick_clock,
578                     base::Time::FromTimeT(2));
579   TestMetricsServiceClient client;
580   MetricsLog log(kClientId, kSessionId, MetricsLog::ONGOING_LOG, clock,
581                  &network_time_tracker, &client);
582   // Advance the backup client clock.  (Value should not be used; merely
583   // advanced to make sure the new value doesn't show up anywhere.)
584   clock->SetNow(base::Time::FromTimeT(3));
585   // Advance and set the network time clock.
586   UpdateNetworkTime(&network_time_tracker, tick_clock,
587                     base::Time::FromTimeT(4));
588 
589   // Check the output.
590   std::string encoded;
591   log.FinalizeLog(/*truncate_events=*/false, client_.GetVersionString(),
592                   log.GetCurrentClockTime(/*record_time_zone=*/true), &encoded);
593   ChromeUserMetricsExtension parsed;
594   ASSERT_TRUE(parsed.ParseFromString(encoded));
595   EXPECT_TRUE(parsed.has_time_log_created());
596   // Time should be the first time returned by the network time tracker.
597   EXPECT_EQ(parsed.time_log_created().time_sec(), 2);
598   EXPECT_EQ(parsed.time_log_created().time_source(),
599             ChromeUserMetricsExtension::RealLocalTime::NETWORK_TIME_CLOCK);
600   // The timezone should not be set in the time_log_created field.
601   EXPECT_FALSE(parsed.time_log_created().has_time_zone_offset_from_gmt_sec());
602   EXPECT_TRUE(parsed.has_time_log_closed());
603   // Time should be the second time returned by the network time tracker.
604   EXPECT_EQ(parsed.time_log_closed().time_sec(), 4);
605   EXPECT_EQ(parsed.time_log_closed().time_source(),
606             ChromeUserMetricsExtension::RealLocalTime::NETWORK_TIME_CLOCK);
607   // The timezone should be set, but we don't check what it is.
608   EXPECT_TRUE(parsed.time_log_closed().has_time_zone_offset_from_gmt_sec());
609 }
610 
TEST_F(MetricsLogTest,HistogramBucketFields)611 TEST_F(MetricsLogTest, HistogramBucketFields) {
612   // Create buckets: 1-5, 5-7, 7-8, 8-9, 9-10, 10-11, 11-12.
613   base::BucketRanges ranges(8);
614   ranges.set_range(0, 1);
615   ranges.set_range(1, 5);
616   ranges.set_range(2, 7);
617   ranges.set_range(3, 8);
618   ranges.set_range(4, 9);
619   ranges.set_range(5, 10);
620   ranges.set_range(6, 11);
621   ranges.set_range(7, 12);
622 
623   base::SampleVector samples(1, &ranges);
624   samples.Accumulate(3, 1);   // Bucket 1-5.
625   samples.Accumulate(6, 1);   // Bucket 5-7.
626   samples.Accumulate(8, 1);   // Bucket 8-9. (7-8 skipped)
627   samples.Accumulate(10, 1);  // Bucket 10-11. (9-10 skipped)
628   samples.Accumulate(11, 1);  // Bucket 11-12.
629   TestMetricsLog log(kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client_);
630   log.RecordHistogramDelta("Test", samples);
631 
632   const ChromeUserMetricsExtension& uma_proto = log.uma_proto();
633   const HistogramEventProto& histogram_proto =
634       uma_proto.histogram_event(uma_proto.histogram_event_size() - 1);
635 
636   // Buckets with samples: 1-5, 5-7, 8-9, 10-11, 11-12.
637   // Should become: 1-/, 5-7, /-9, 10-/, /-12.
638   ASSERT_EQ(5, histogram_proto.bucket_size());
639 
640   // 1-5 becomes 1-/ (max is same as next min).
641   EXPECT_TRUE(histogram_proto.bucket(0).has_min());
642   EXPECT_FALSE(histogram_proto.bucket(0).has_max());
643   EXPECT_EQ(1, histogram_proto.bucket(0).min());
644 
645   // 5-7 stays 5-7 (no optimization possible).
646   EXPECT_TRUE(histogram_proto.bucket(1).has_min());
647   EXPECT_TRUE(histogram_proto.bucket(1).has_max());
648   EXPECT_EQ(5, histogram_proto.bucket(1).min());
649   EXPECT_EQ(7, histogram_proto.bucket(1).max());
650 
651   // 8-9 becomes /-9 (min is same as max - 1).
652   EXPECT_FALSE(histogram_proto.bucket(2).has_min());
653   EXPECT_TRUE(histogram_proto.bucket(2).has_max());
654   EXPECT_EQ(9, histogram_proto.bucket(2).max());
655 
656   // 10-11 becomes 10-/ (both optimizations apply, omit max is prioritized).
657   EXPECT_TRUE(histogram_proto.bucket(3).has_min());
658   EXPECT_FALSE(histogram_proto.bucket(3).has_max());
659   EXPECT_EQ(10, histogram_proto.bucket(3).min());
660 
661   // 11-12 becomes /-12 (last record must keep max, min is same as max - 1).
662   EXPECT_FALSE(histogram_proto.bucket(4).has_min());
663   EXPECT_TRUE(histogram_proto.bucket(4).has_max());
664   EXPECT_EQ(12, histogram_proto.bucket(4).max());
665 }
666 
TEST_F(MetricsLogTest,HistogramSamplesCount)667 TEST_F(MetricsLogTest, HistogramSamplesCount) {
668   const std::string histogram_name = "test";
669   TestMetricsLog log(kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client_);
670 
671   // Create buckets: 1-5.
672   base::BucketRanges ranges(2);
673   ranges.set_range(0, 1);
674   ranges.set_range(1, 5);
675 
676   // Add two samples.
677   base::SampleVector samples(1, &ranges);
678   samples.Accumulate(3, 2);
679   log.RecordHistogramDelta(histogram_name, samples);
680 
681   EXPECT_EQ(2, log.log_metadata().samples_count.value());
682 
683   // Add two more samples.
684   log.RecordHistogramDelta(histogram_name, samples);
685   EXPECT_EQ(4, log.log_metadata().samples_count.value());
686 }
687 
TEST_F(MetricsLogTest,RecordEnvironment)688 TEST_F(MetricsLogTest, RecordEnvironment) {
689   TestMetricsLog log(kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client_);
690 
691   DelegatingProvider delegating_provider;
692   auto cpu_provider = std::make_unique<metrics::CPUMetricsProvider>();
693   delegating_provider.RegisterMetricsProvider(std::move(cpu_provider));
694   log.RecordEnvironment(&delegating_provider);
695 
696   // Check non-system profile values.
697   EXPECT_EQ(MetricsLog::Hash(kClientId), log.uma_proto().client_id());
698   EXPECT_EQ(kSessionId, log.uma_proto().session_id());
699   // Check that the system profile on the log has the correct values set.
700   CheckSystemProfile(log.system_profile());
701 
702   // Call RecordEnvironment() again and verify things are are still filled in.
703   log.RecordEnvironment(&delegating_provider);
704 
705   // Check non-system profile values.
706   EXPECT_EQ(MetricsLog::Hash(kClientId), log.uma_proto().client_id());
707   EXPECT_EQ(kSessionId, log.uma_proto().session_id());
708   // Check that the system profile on the log has the correct values set.
709   CheckSystemProfile(log.system_profile());
710 }
711 
TEST_F(MetricsLogTest,RecordEnvironmentExtendedStable)712 TEST_F(MetricsLogTest, RecordEnvironmentExtendedStable) {
713   client_.set_is_extended_stable_channel(true);
714   TestMetricsLog log(kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client_);
715 
716   DelegatingProvider delegating_provider;
717   auto cpu_provider = std::make_unique<metrics::CPUMetricsProvider>();
718   delegating_provider.RegisterMetricsProvider(std::move(cpu_provider));
719   log.RecordEnvironment(&delegating_provider);
720 
721   EXPECT_TRUE(log.system_profile().has_is_extended_stable_channel());
722   EXPECT_TRUE(log.system_profile().is_extended_stable_channel());
723 }
724 
TEST_F(MetricsLogTest,RecordEnvironmentEnableDefault)725 TEST_F(MetricsLogTest, RecordEnvironmentEnableDefault) {
726   TestMetricsLog log_unknown(kClientId, kSessionId, MetricsLog::ONGOING_LOG,
727                              &client_);
728 
729   DelegatingProvider delegating_provider;
730   log_unknown.RecordEnvironment(&delegating_provider);
731   EXPECT_FALSE(log_unknown.system_profile().has_uma_default_state());
732 
733   client_.set_enable_default(EnableMetricsDefault::OPT_IN);
734   TestMetricsLog log_opt_in(kClientId, kSessionId, MetricsLog::ONGOING_LOG,
735                             &client_);
736   log_opt_in.RecordEnvironment(&delegating_provider);
737   EXPECT_TRUE(log_opt_in.system_profile().has_uma_default_state());
738   EXPECT_EQ(SystemProfileProto_UmaDefaultState_OPT_IN,
739             log_opt_in.system_profile().uma_default_state());
740 
741   client_.set_enable_default(EnableMetricsDefault::OPT_OUT);
742   TestMetricsLog log_opt_out(kClientId, kSessionId, MetricsLog::ONGOING_LOG,
743                              &client_);
744   log_opt_out.RecordEnvironment(&delegating_provider);
745   EXPECT_TRUE(log_opt_out.system_profile().has_uma_default_state());
746   EXPECT_EQ(SystemProfileProto_UmaDefaultState_OPT_OUT,
747             log_opt_out.system_profile().uma_default_state());
748 
749   client_.set_reporting_is_managed(true);
750   TestMetricsLog log_managed(kClientId, kSessionId, MetricsLog::ONGOING_LOG,
751                              &client_);
752   log_managed.RecordEnvironment(&delegating_provider);
753   EXPECT_TRUE(log_managed.system_profile().has_uma_default_state());
754   EXPECT_EQ(SystemProfileProto_UmaDefaultState_POLICY_FORCED_ENABLED,
755             log_managed.system_profile().uma_default_state());
756 }
757 
TEST_F(MetricsLogTest,InitialLogStabilityMetrics)758 TEST_F(MetricsLogTest, InitialLogStabilityMetrics) {
759   TestMetricsLog log(kClientId, kSessionId, MetricsLog::INITIAL_STABILITY_LOG,
760                      &client_);
761   TestMetricsProvider* test_provider = new TestMetricsProvider();
762   DelegatingProvider delegating_provider;
763   delegating_provider.RegisterMetricsProvider(
764       base::WrapUnique<MetricsProvider>(test_provider));
765   log.RecordEnvironment(&delegating_provider);
766   log.RecordPreviousSessionData(&delegating_provider, &prefs_);
767 
768   // The test provider should have been called upon to provide initial
769   // stability and regular stability metrics.
770   EXPECT_TRUE(test_provider->provide_initial_stability_metrics_called());
771   EXPECT_TRUE(test_provider->provide_stability_metrics_called());
772 }
773 
TEST_F(MetricsLogTest,OngoingLogStabilityMetrics)774 TEST_F(MetricsLogTest, OngoingLogStabilityMetrics) {
775   TestMetricsLog log(kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client_);
776   TestMetricsProvider* test_provider = new TestMetricsProvider();
777   DelegatingProvider delegating_provider;
778   delegating_provider.RegisterMetricsProvider(
779       base::WrapUnique<MetricsProvider>(test_provider));
780   log.RecordEnvironment(&delegating_provider);
781   log.RecordCurrentSessionData(base::TimeDelta(), base::TimeDelta(),
782                                &delegating_provider, &prefs_);
783 
784   // The test provider should have been called upon to provide regular but not
785   // initial stability metrics.
786   EXPECT_FALSE(test_provider->provide_initial_stability_metrics_called());
787   EXPECT_TRUE(test_provider->provide_stability_metrics_called());
788 }
789 
TEST_F(MetricsLogTest,ChromeChannelWrittenToProtobuf)790 TEST_F(MetricsLogTest, ChromeChannelWrittenToProtobuf) {
791   TestMetricsLog log(kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client_);
792   EXPECT_TRUE(log.uma_proto().system_profile().has_channel());
793 }
794 
TEST_F(MetricsLogTest,ProductNotSetIfDefault)795 TEST_F(MetricsLogTest, ProductNotSetIfDefault) {
796   EXPECT_EQ(ChromeUserMetricsExtension::CHROME, client_.GetProduct());
797   TestMetricsLog log(kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client_);
798   // Check that the product isn't set, since it's default and also verify the
799   // default value is indeed equal to Chrome.
800   EXPECT_FALSE(log.uma_proto().has_product());
801   EXPECT_EQ(ChromeUserMetricsExtension::CHROME, log.uma_proto().product());
802 }
803 
TEST_F(MetricsLogTest,ProductSetIfNotDefault)804 TEST_F(MetricsLogTest, ProductSetIfNotDefault) {
805   const int32_t kTestProduct = 100;
806   EXPECT_NE(ChromeUserMetricsExtension::CHROME, kTestProduct);
807   client_.set_product(kTestProduct);
808   TestMetricsLog log(kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client_);
809   // Check that the product is set to |kTestProduct|.
810   EXPECT_TRUE(log.uma_proto().has_product());
811   EXPECT_EQ(kTestProduct, log.uma_proto().product());
812 }
813 
TEST_F(MetricsLogTest,ToInstallerPackage)814 TEST_F(MetricsLogTest, ToInstallerPackage) {
815   using internal::ToInstallerPackage;
816   EXPECT_EQ(SystemProfileProto::INSTALLER_PACKAGE_NONE, ToInstallerPackage(""));
817   EXPECT_EQ(SystemProfileProto::INSTALLER_PACKAGE_GOOGLE_PLAY_STORE,
818             ToInstallerPackage("com.android.vending"));
819   EXPECT_EQ(SystemProfileProto::INSTALLER_PACKAGE_OTHER,
820             ToInstallerPackage("foo"));
821 }
822 
823 }  // namespace metrics
824