Enable Enterprise enrollment on desktop builds.
[chromium-blink-merge.git] / chrome / browser / metrics / metrics_service_unittest.cc
blob48f7ec1d9667a6009670993a9790e66f36588aff
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/metrics/metrics_service.h"
7 #include <ctype.h>
8 #include <string>
10 #include "base/command_line.h"
11 #include "base/threading/platform_thread.h"
12 #include "chrome/common/chrome_switches.h"
13 #include "chrome/common/pref_names.h"
14 #include "chrome/test/base/scoped_testing_local_state.h"
15 #include "chrome/test/base/testing_browser_process.h"
16 #include "components/variations/metrics_util.h"
17 #include "content/public/common/process_type.h"
18 #include "content/public/common/webplugininfo.h"
19 #include "content/public/test/test_browser_thread_bundle.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "ui/gfx/size.h"
23 #if defined(OS_CHROMEOS)
24 #include "chrome/browser/metrics/metrics_log_chromeos.h"
25 #endif // OS_CHROMEOS
27 namespace {
29 using metrics::MetricsLogManager;
31 class TestMetricsService : public MetricsService {
32 public:
33 TestMetricsService() {}
34 virtual ~TestMetricsService() {}
36 MetricsLogManager* log_manager() {
37 return &log_manager_;
40 private:
41 DISALLOW_COPY_AND_ASSIGN(TestMetricsService);
44 #if defined(OS_CHROMEOS)
45 class TestMetricsLogChromeOS : public MetricsLogChromeOS {
46 public:
47 explicit TestMetricsLogChromeOS(
48 metrics::ChromeUserMetricsExtension* uma_proto)
49 : MetricsLogChromeOS(uma_proto) {
52 protected:
53 // Don't touch bluetooth information, as it won't be correctly initialized.
54 virtual void WriteBluetoothProto() OVERRIDE {
57 #endif // OS_CHROMEOS
59 class TestMetricsLog : public MetricsLog {
60 public:
61 TestMetricsLog(const std::string& client_id, int session_id)
62 : MetricsLog(client_id, session_id, MetricsLog::ONGOING_LOG) {
63 #if defined(OS_CHROMEOS)
64 metrics_log_chromeos_.reset(new TestMetricsLogChromeOS(
65 MetricsLog::uma_proto()));
66 #endif // OS_CHROMEOS
68 virtual ~TestMetricsLog() {}
70 private:
71 virtual gfx::Size GetScreenSize() const OVERRIDE {
72 return gfx::Size(1024, 768);
75 virtual float GetScreenDeviceScaleFactor() const OVERRIDE {
76 return 1.0f;
79 virtual int GetScreenCount() const OVERRIDE {
80 return 1;
83 DISALLOW_COPY_AND_ASSIGN(TestMetricsLog);
86 class MetricsServiceTest : public testing::Test {
87 public:
88 MetricsServiceTest()
89 : testing_local_state_(TestingBrowserProcess::GetGlobal()) {
92 virtual ~MetricsServiceTest() {
93 MetricsService::SetExecutionPhase(MetricsService::UNINITIALIZED_PHASE);
96 PrefService* GetLocalState() {
97 return testing_local_state_.Get();
100 // Waits until base::TimeTicks::Now() no longer equals |value|. This should
101 // take between 1-15ms per the documented resolution of base::TimeTicks.
102 void WaitUntilTimeChanges(const base::TimeTicks& value) {
103 while (base::TimeTicks::Now() == value) {
104 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1));
108 // Returns true if there is a synthetic trial in the given vector that matches
109 // the given trial name and trial group; returns false otherwise.
110 bool HasSyntheticTrial(
111 const std::vector<chrome_variations::ActiveGroupId>& synthetic_trials,
112 const std::string& trial_name,
113 const std::string& trial_group) {
114 uint32 trial_name_hash = metrics::HashName(trial_name);
115 uint32 trial_group_hash = metrics::HashName(trial_group);
116 for (std::vector<chrome_variations::ActiveGroupId>::const_iterator it =
117 synthetic_trials.begin();
118 it != synthetic_trials.end(); ++it) {
119 if ((*it).name == trial_name_hash && (*it).group == trial_group_hash)
120 return true;
122 return false;
125 private:
126 content::TestBrowserThreadBundle thread_bundle_;
127 ScopedTestingLocalState testing_local_state_;
129 DISALLOW_COPY_AND_ASSIGN(MetricsServiceTest);
132 } // namespace
134 // Ensure the ClientId is formatted as expected.
135 TEST_F(MetricsServiceTest, ClientIdCorrectlyFormatted) {
136 std::string clientid = MetricsService::GenerateClientID();
137 EXPECT_EQ(36U, clientid.length());
139 for (size_t i = 0; i < clientid.length(); ++i) {
140 char current = clientid[i];
141 if (i == 8 || i == 13 || i == 18 || i == 23)
142 EXPECT_EQ('-', current);
143 else
144 EXPECT_TRUE(isxdigit(current));
148 TEST_F(MetricsServiceTest, IsPluginProcess) {
149 EXPECT_TRUE(
150 MetricsService::IsPluginProcess(content::PROCESS_TYPE_PLUGIN));
151 EXPECT_TRUE(
152 MetricsService::IsPluginProcess(content::PROCESS_TYPE_PPAPI_PLUGIN));
153 EXPECT_FALSE(
154 MetricsService::IsPluginProcess(content::PROCESS_TYPE_GPU));
157 TEST_F(MetricsServiceTest, LowEntropySource0NotReset) {
158 MetricsService service;
160 // Get the low entropy source once, to initialize it.
161 service.GetLowEntropySource();
163 // Now, set it to 0 and ensure it doesn't get reset.
164 service.low_entropy_source_ = 0;
165 EXPECT_EQ(0, service.GetLowEntropySource());
166 // Call it another time, just to make sure.
167 EXPECT_EQ(0, service.GetLowEntropySource());
170 TEST_F(MetricsServiceTest, PermutedEntropyCacheClearedWhenLowEntropyReset) {
171 const PrefService::Preference* low_entropy_pref =
172 GetLocalState()->FindPreference(prefs::kMetricsLowEntropySource);
173 const char* kCachePrefName = prefs::kMetricsPermutedEntropyCache;
174 int low_entropy_value = -1;
176 // First, generate an initial low entropy source value.
178 EXPECT_TRUE(low_entropy_pref->IsDefaultValue());
180 MetricsService::SetExecutionPhase(MetricsService::UNINITIALIZED_PHASE);
181 MetricsService service;
182 service.GetLowEntropySource();
184 EXPECT_FALSE(low_entropy_pref->IsDefaultValue());
185 EXPECT_TRUE(low_entropy_pref->GetValue()->GetAsInteger(&low_entropy_value));
188 // Now, set a dummy value in the permuted entropy cache pref and verify that
189 // another call to GetLowEntropySource() doesn't clobber it when
190 // --reset-variation-state wasn't specified.
192 GetLocalState()->SetString(kCachePrefName, "test");
194 MetricsService::SetExecutionPhase(MetricsService::UNINITIALIZED_PHASE);
195 MetricsService service;
196 service.GetLowEntropySource();
198 EXPECT_EQ("test", GetLocalState()->GetString(kCachePrefName));
199 EXPECT_EQ(low_entropy_value,
200 GetLocalState()->GetInteger(prefs::kMetricsLowEntropySource));
203 // Verify that the cache does get reset if --reset-variations-state is passed.
205 CommandLine::ForCurrentProcess()->AppendSwitch(
206 switches::kResetVariationState);
208 MetricsService::SetExecutionPhase(MetricsService::UNINITIALIZED_PHASE);
209 MetricsService service;
210 service.GetLowEntropySource();
212 EXPECT_TRUE(GetLocalState()->GetString(kCachePrefName).empty());
216 TEST_F(MetricsServiceTest, InitialStabilityLogAfterCleanShutDown) {
217 base::FieldTrialList field_trial_list(NULL);
218 base::FieldTrialList::CreateFieldTrial("UMAStability", "SeparateLog");
220 GetLocalState()->SetBoolean(prefs::kStabilityExitedCleanly, true);
222 TestMetricsService service;
223 service.InitializeMetricsRecordingState(MetricsService::REPORTING_ENABLED);
224 // No initial stability log should be generated.
225 EXPECT_FALSE(service.log_manager()->has_unsent_logs());
226 EXPECT_FALSE(service.log_manager()->has_staged_log());
229 TEST_F(MetricsServiceTest, InitialStabilityLogAfterCrash) {
230 base::FieldTrialList field_trial_list(NULL);
231 base::FieldTrialList::CreateFieldTrial("UMAStability", "SeparateLog");
233 GetLocalState()->ClearPref(prefs::kStabilityExitedCleanly);
235 // Set up prefs to simulate restarting after a crash.
237 // Save an existing system profile to prefs, to correspond to what would be
238 // saved from a previous session.
239 TestMetricsLog log("client", 1);
240 log.RecordEnvironment(std::vector<content::WebPluginInfo>(),
241 GoogleUpdateMetrics(),
242 std::vector<chrome_variations::ActiveGroupId>());
244 // Record stability build time and version from previous session, so that
245 // stability metrics (including exited cleanly flag) won't be cleared.
246 GetLocalState()->SetInt64(prefs::kStabilityStatsBuildTime,
247 MetricsLog::GetBuildTime());
248 GetLocalState()->SetString(prefs::kStabilityStatsVersion,
249 MetricsLog::GetVersionString());
251 GetLocalState()->SetBoolean(prefs::kStabilityExitedCleanly, false);
253 TestMetricsService service;
254 service.InitializeMetricsRecordingState(MetricsService::REPORTING_ENABLED);
256 // The initial stability log should be generated and persisted in unsent logs.
257 MetricsLogManager* log_manager = service.log_manager();
258 EXPECT_TRUE(log_manager->has_unsent_logs());
259 EXPECT_FALSE(log_manager->has_staged_log());
261 // Stage the log and retrieve it.
262 log_manager->StageNextLogForUpload();
263 EXPECT_TRUE(log_manager->has_staged_log());
265 metrics::ChromeUserMetricsExtension uma_log;
266 EXPECT_TRUE(uma_log.ParseFromString(log_manager->staged_log_text()));
268 EXPECT_TRUE(uma_log.has_client_id());
269 EXPECT_TRUE(uma_log.has_session_id());
270 EXPECT_TRUE(uma_log.has_system_profile());
271 EXPECT_EQ(0, uma_log.user_action_event_size());
272 EXPECT_EQ(0, uma_log.omnibox_event_size());
273 EXPECT_EQ(0, uma_log.histogram_event_size());
274 EXPECT_EQ(0, uma_log.profiler_event_size());
275 EXPECT_EQ(0, uma_log.perf_data_size());
277 EXPECT_EQ(1, uma_log.system_profile().stability().crash_count());
280 TEST_F(MetricsServiceTest, RegisterSyntheticTrial) {
281 MetricsService service;
283 // Add two synthetic trials and confirm that they show up in the list.
284 SyntheticTrialGroup trial1(metrics::HashName("TestTrial1"),
285 metrics::HashName("Group1"));
286 service.RegisterSyntheticFieldTrial(trial1);
288 SyntheticTrialGroup trial2(metrics::HashName("TestTrial2"),
289 metrics::HashName("Group2"));
290 service.RegisterSyntheticFieldTrial(trial2);
291 // Ensure that time has advanced by at least a tick before proceeding.
292 WaitUntilTimeChanges(base::TimeTicks::Now());
294 service.log_manager_.BeginLoggingWithLog(
295 new MetricsLog("clientID", 1, MetricsLog::INITIAL_STABILITY_LOG));
296 // Save the time when the log was started (it's okay for this to be greater
297 // than the time recorded by the above call since it's used to ensure the
298 // value changes).
299 const base::TimeTicks begin_log_time = base::TimeTicks::Now();
301 std::vector<chrome_variations::ActiveGroupId> synthetic_trials;
302 service.GetCurrentSyntheticFieldTrials(&synthetic_trials);
303 EXPECT_EQ(2U, synthetic_trials.size());
304 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial1", "Group1"));
305 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial2", "Group2"));
307 // Ensure that time has advanced by at least a tick before proceeding.
308 WaitUntilTimeChanges(begin_log_time);
310 // Change the group for the first trial after the log started.
311 // TODO(asvitkine): Assumption that this is > than BeginLoggingWithLog() time.
312 SyntheticTrialGroup trial3(metrics::HashName("TestTrial1"),
313 metrics::HashName("Group2"));
314 service.RegisterSyntheticFieldTrial(trial3);
315 service.GetCurrentSyntheticFieldTrials(&synthetic_trials);
316 EXPECT_EQ(1U, synthetic_trials.size());
317 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial2", "Group2"));
319 // Add a new trial after the log started and confirm that it doesn't show up.
320 SyntheticTrialGroup trial4(metrics::HashName("TestTrial3"),
321 metrics::HashName("Group3"));
322 service.RegisterSyntheticFieldTrial(trial4);
323 service.GetCurrentSyntheticFieldTrials(&synthetic_trials);
324 EXPECT_EQ(1U, synthetic_trials.size());
325 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial2", "Group2"));
327 // Ensure that time has advanced by at least a tick before proceeding.
328 WaitUntilTimeChanges(base::TimeTicks::Now());
330 // Start a new log and ensure all three trials appear in it.
331 service.log_manager_.FinishCurrentLog();
332 service.log_manager_.BeginLoggingWithLog(
333 new MetricsLog("clientID", 1, MetricsLog::ONGOING_LOG));
334 service.GetCurrentSyntheticFieldTrials(&synthetic_trials);
335 EXPECT_EQ(3U, synthetic_trials.size());
336 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial1", "Group2"));
337 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial2", "Group2"));
338 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial3", "Group3"));
339 service.log_manager_.FinishCurrentLog();
342 TEST_F(MetricsServiceTest, MetricsReportingEnabled) {
343 #if !defined(OS_CHROMEOS)
344 GetLocalState()->SetBoolean(prefs::kMetricsReportingEnabled, false);
345 EXPECT_FALSE(MetricsServiceHelper::IsMetricsReportingEnabled());
346 GetLocalState()->SetBoolean(prefs::kMetricsReportingEnabled, true);
347 EXPECT_TRUE(MetricsServiceHelper::IsMetricsReportingEnabled());
348 GetLocalState()->ClearPref(prefs::kMetricsReportingEnabled);
349 EXPECT_FALSE(MetricsServiceHelper::IsMetricsReportingEnabled());
350 #else
351 // ChromeOS does not register prefs::kMetricsReportingEnabled and uses
352 // device settings for metrics reporting.
353 EXPECT_FALSE(MetricsServiceHelper::IsMetricsReportingEnabled());
354 #endif
357 TEST_F(MetricsServiceTest, CrashReportingEnabled) {
358 #if defined(GOOGLE_CHROME_BUILD)
359 // ChromeOS has different device settings for crash reporting.
360 #if !defined(OS_CHROMEOS)
361 #if defined(OS_ANDROID)
362 const char* crash_pref = prefs::kCrashReportingEnabled;
363 #else
364 const char* crash_pref = prefs::kMetricsReportingEnabled;
365 #endif
366 GetLocalState()->SetBoolean(crash_pref, false);
367 EXPECT_FALSE(MetricsServiceHelper::IsCrashReportingEnabled());
368 GetLocalState()->SetBoolean(crash_pref, true);
369 EXPECT_TRUE(MetricsServiceHelper::IsCrashReportingEnabled());
370 GetLocalState()->ClearPref(crash_pref);
371 EXPECT_FALSE(MetricsServiceHelper::IsCrashReportingEnabled());
372 #endif // !defined(OS_CHROMEOS)
373 #else // defined(GOOGLE_CHROME_BUILD)
374 // Chromium branded browsers never have crash reporting enabled.
375 EXPECT_FALSE(MetricsServiceHelper::IsCrashReportingEnabled());
376 #endif // defined(GOOGLE_CHROME_BUILD)
379 // Check that setting the kMetricsResetIds pref to true causes the client id to
380 // be reset. We do not check that the low entropy source is reset because we
381 // cannot ensure that metrics service won't generate the same id again.
382 TEST_F(MetricsServiceTest, ResetMetricsIDs) {
383 // Set an initial client id in prefs. It should not be possible for the
384 // metrics service to generate this id randomly.
385 const std::string kInitialClientId = "initial client id";
386 GetLocalState()->SetString(prefs::kMetricsClientID, kInitialClientId);
388 // Make sure the initial client id isn't reset by the metrics service.
390 MetricsService service;
391 service.ForceClientIdCreation();
392 EXPECT_TRUE(service.metrics_ids_reset_check_performed_);
393 EXPECT_EQ(kInitialClientId, service.client_id_);
397 // Set the reset pref to cause the IDs to be reset.
398 GetLocalState()->SetBoolean(prefs::kMetricsResetIds, true);
400 // Cause the actual reset to happen.
402 MetricsService service;
403 service.ForceClientIdCreation();
404 EXPECT_TRUE(service.metrics_ids_reset_check_performed_);
405 EXPECT_NE(kInitialClientId, service.client_id_);
407 service.GetLowEntropySource();
409 EXPECT_FALSE(GetLocalState()->GetBoolean(prefs::kMetricsResetIds));
412 std::string new_client_id =
413 GetLocalState()->GetString(prefs::kMetricsClientID);
415 EXPECT_NE(kInitialClientId, new_client_id);