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"
10 #include "base/command_line.h"
11 #include "chrome/common/chrome_switches.h"
12 #include "chrome/common/pref_names.h"
13 #include "chrome/test/base/scoped_testing_local_state.h"
14 #include "chrome/test/base/testing_browser_process.h"
15 #include "components/variations/metrics_util.h"
16 #include "content/public/common/process_type.h"
17 #include "content/public/common/webplugininfo.h"
18 #include "content/public/test/test_browser_thread_bundle.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "ui/gfx/size.h"
22 #if defined(OS_CHROMEOS)
23 #include "chrome/browser/metrics/metrics_log_chromeos.h"
28 class TestMetricsService : public MetricsService {
30 TestMetricsService() {}
31 virtual ~TestMetricsService() {}
33 MetricsLogManager* log_manager() {
38 DISALLOW_COPY_AND_ASSIGN(TestMetricsService);
41 #if defined(OS_CHROMEOS)
42 class TestMetricsLogChromeOS : public MetricsLogChromeOS {
44 explicit TestMetricsLogChromeOS(
45 metrics::ChromeUserMetricsExtension* uma_proto)
46 : MetricsLogChromeOS(uma_proto) {
50 // Don't touch bluetooth information, as it won't be correctly initialized.
51 virtual void WriteBluetoothProto() OVERRIDE {
56 class TestMetricsLog : public MetricsLog {
58 TestMetricsLog(const std::string& client_id, int session_id)
59 : MetricsLog(client_id, session_id) {
60 #if defined(OS_CHROMEOS)
61 metrics_log_chromeos_.reset(new TestMetricsLogChromeOS(
62 MetricsLog::uma_proto()));
65 virtual ~TestMetricsLog() {}
68 virtual gfx::Size GetScreenSize() const OVERRIDE {
69 return gfx::Size(1024, 768);
72 virtual float GetScreenDeviceScaleFactor() const OVERRIDE {
76 virtual int GetScreenCount() const OVERRIDE {
80 DISALLOW_COPY_AND_ASSIGN(TestMetricsLog);
83 class MetricsServiceTest : public testing::Test {
86 : testing_local_state_(TestingBrowserProcess::GetGlobal()) {
89 virtual ~MetricsServiceTest() {
90 MetricsService::SetExecutionPhase(MetricsService::UNINITIALIZED_PHASE);
93 PrefService* GetLocalState() {
94 return testing_local_state_.Get();
97 // Returns true if there is a synthetic trial in the given vector that matches
98 // the given trial name and trial group; returns false otherwise.
99 bool HasSyntheticTrial(
100 const std::vector<chrome_variations::ActiveGroupId>& synthetic_trials,
101 const std::string& trial_name,
102 const std::string& trial_group) {
103 uint32 trial_name_hash = metrics::HashName(trial_name);
104 uint32 trial_group_hash = metrics::HashName(trial_group);
105 for (std::vector<chrome_variations::ActiveGroupId>::const_iterator it =
106 synthetic_trials.begin();
107 it != synthetic_trials.end(); ++it) {
108 if ((*it).name == trial_name_hash && (*it).group == trial_group_hash)
115 content::TestBrowserThreadBundle thread_bundle_;
116 ScopedTestingLocalState testing_local_state_;
118 DISALLOW_COPY_AND_ASSIGN(MetricsServiceTest);
123 // Ensure the ClientId is formatted as expected.
124 TEST_F(MetricsServiceTest, ClientIdCorrectlyFormatted) {
125 std::string clientid = MetricsService::GenerateClientID();
126 EXPECT_EQ(36U, clientid.length());
128 for (size_t i = 0; i < clientid.length(); ++i) {
129 char current = clientid[i];
130 if (i == 8 || i == 13 || i == 18 || i == 23)
131 EXPECT_EQ('-', current);
133 EXPECT_TRUE(isxdigit(current));
137 TEST_F(MetricsServiceTest, IsPluginProcess) {
139 MetricsService::IsPluginProcess(content::PROCESS_TYPE_PLUGIN));
141 MetricsService::IsPluginProcess(content::PROCESS_TYPE_PPAPI_PLUGIN));
143 MetricsService::IsPluginProcess(content::PROCESS_TYPE_GPU));
146 TEST_F(MetricsServiceTest, LowEntropySource0NotReset) {
147 MetricsService service;
149 // Get the low entropy source once, to initialize it.
150 service.GetLowEntropySource();
152 // Now, set it to 0 and ensure it doesn't get reset.
153 service.low_entropy_source_ = 0;
154 EXPECT_EQ(0, service.GetLowEntropySource());
155 // Call it another time, just to make sure.
156 EXPECT_EQ(0, service.GetLowEntropySource());
159 TEST_F(MetricsServiceTest, PermutedEntropyCacheClearedWhenLowEntropyReset) {
160 const PrefService::Preference* low_entropy_pref =
161 GetLocalState()->FindPreference(prefs::kMetricsLowEntropySource);
162 const char* kCachePrefName = prefs::kMetricsPermutedEntropyCache;
163 int low_entropy_value = -1;
165 // First, generate an initial low entropy source value.
167 EXPECT_TRUE(low_entropy_pref->IsDefaultValue());
169 MetricsService::SetExecutionPhase(MetricsService::UNINITIALIZED_PHASE);
170 MetricsService service;
171 service.GetLowEntropySource();
173 EXPECT_FALSE(low_entropy_pref->IsDefaultValue());
174 EXPECT_TRUE(low_entropy_pref->GetValue()->GetAsInteger(&low_entropy_value));
177 // Now, set a dummy value in the permuted entropy cache pref and verify that
178 // another call to GetLowEntropySource() doesn't clobber it when
179 // --reset-variation-state wasn't specified.
181 GetLocalState()->SetString(kCachePrefName, "test");
183 MetricsService::SetExecutionPhase(MetricsService::UNINITIALIZED_PHASE);
184 MetricsService service;
185 service.GetLowEntropySource();
187 EXPECT_EQ("test", GetLocalState()->GetString(kCachePrefName));
188 EXPECT_EQ(low_entropy_value,
189 GetLocalState()->GetInteger(prefs::kMetricsLowEntropySource));
192 // Verify that the cache does get reset if --reset-variations-state is passed.
194 CommandLine::ForCurrentProcess()->AppendSwitch(
195 switches::kResetVariationState);
197 MetricsService::SetExecutionPhase(MetricsService::UNINITIALIZED_PHASE);
198 MetricsService service;
199 service.GetLowEntropySource();
201 EXPECT_TRUE(GetLocalState()->GetString(kCachePrefName).empty());
205 TEST_F(MetricsServiceTest, InitialStabilityLogAfterCleanShutDown) {
206 base::FieldTrialList field_trial_list(NULL);
207 base::FieldTrialList::CreateFieldTrial("UMAStability", "SeparateLog");
209 GetLocalState()->SetBoolean(prefs::kStabilityExitedCleanly, true);
211 TestMetricsService service;
212 service.InitializeMetricsRecordingState(MetricsService::REPORTING_ENABLED);
213 // No initial stability log should be generated.
214 EXPECT_FALSE(service.log_manager()->has_unsent_logs());
215 EXPECT_FALSE(service.log_manager()->has_staged_log());
218 TEST_F(MetricsServiceTest, InitialStabilityLogAfterCrash) {
219 base::FieldTrialList field_trial_list(NULL);
220 base::FieldTrialList::CreateFieldTrial("UMAStability", "SeparateLog");
222 GetLocalState()->ClearPref(prefs::kStabilityExitedCleanly);
224 // Set up prefs to simulate restarting after a crash.
226 // Save an existing system profile to prefs, to correspond to what would be
227 // saved from a previous session.
228 TestMetricsLog log("client", 1);
229 log.RecordEnvironment(std::vector<content::WebPluginInfo>(),
230 GoogleUpdateMetrics(),
231 std::vector<chrome_variations::ActiveGroupId>());
233 // Record stability build time and version from previous session, so that
234 // stability metrics (including exited cleanly flag) won't be cleared.
235 GetLocalState()->SetInt64(prefs::kStabilityStatsBuildTime,
236 MetricsLog::GetBuildTime());
237 GetLocalState()->SetString(prefs::kStabilityStatsVersion,
238 MetricsLog::GetVersionString());
240 GetLocalState()->SetBoolean(prefs::kStabilityExitedCleanly, false);
242 TestMetricsService service;
243 service.InitializeMetricsRecordingState(MetricsService::REPORTING_ENABLED);
245 // The initial stability log should be generated and persisted in unsent logs.
246 MetricsLogManager* log_manager = service.log_manager();
247 EXPECT_TRUE(log_manager->has_unsent_logs());
248 EXPECT_FALSE(log_manager->has_staged_log());
250 // Stage the log and retrieve it.
251 log_manager->StageNextLogForUpload();
252 EXPECT_TRUE(log_manager->has_staged_log());
254 metrics::ChromeUserMetricsExtension uma_log;
255 EXPECT_TRUE(uma_log.ParseFromString(log_manager->staged_log_text()));
257 EXPECT_TRUE(uma_log.has_client_id());
258 EXPECT_TRUE(uma_log.has_session_id());
259 EXPECT_TRUE(uma_log.has_system_profile());
260 EXPECT_EQ(0, uma_log.user_action_event_size());
261 EXPECT_EQ(0, uma_log.omnibox_event_size());
262 EXPECT_EQ(0, uma_log.histogram_event_size());
263 EXPECT_EQ(0, uma_log.profiler_event_size());
264 EXPECT_EQ(0, uma_log.perf_data_size());
266 EXPECT_EQ(1, uma_log.system_profile().stability().crash_count());
269 // Crashes on at least Mac and Linux. http://crbug.com/320433
270 TEST_F(MetricsServiceTest, DISABLED_RegisterSyntheticTrial) {
271 MetricsService service;
273 // Add two synthetic trials and confirm that they show up in the list.
274 SyntheticTrialGroup trial1(metrics::HashName("TestTrial1"),
275 metrics::HashName("Group1"),
276 base::TimeTicks::Now());
277 service.RegisterSyntheticFieldTrial(trial1);
279 SyntheticTrialGroup trial2(metrics::HashName("TestTrial2"),
280 metrics::HashName("Group2"),
281 base::TimeTicks::Now());
282 service.RegisterSyntheticFieldTrial(trial2);
284 service.log_manager_.BeginLoggingWithLog(new MetricsLog("clientID", 1),
285 MetricsLog::INITIAL_LOG);
287 std::vector<chrome_variations::ActiveGroupId> synthetic_trials;
288 service.GetCurrentSyntheticFieldTrials(&synthetic_trials);
289 EXPECT_EQ(2U, synthetic_trials.size());
290 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial1", "Group1"));
291 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial2", "Group2"));
293 // Change the group for the first trial after the log started.
294 SyntheticTrialGroup trial3(metrics::HashName("TestTrial1"),
295 metrics::HashName("Group2"),
296 base::TimeTicks::Now());
297 service.RegisterSyntheticFieldTrial(trial3);
298 service.GetCurrentSyntheticFieldTrials(&synthetic_trials);
299 EXPECT_EQ(1U, synthetic_trials.size());
300 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial2", "Group2"));
302 // Add a new trial after the log started and confirm that it doesn't show up.
303 SyntheticTrialGroup trial4(metrics::HashName("TestTrial3"),
304 metrics::HashName("Group3"),
305 base::TimeTicks::Now());
306 service.RegisterSyntheticFieldTrial(trial4);
307 service.GetCurrentSyntheticFieldTrials(&synthetic_trials);
308 EXPECT_EQ(1U, synthetic_trials.size());
309 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial2", "Group2"));
312 service.log_manager_.FinishCurrentLog();
313 service.log_manager_.BeginLoggingWithLog(new MetricsLog("clientID", 1),
314 MetricsLog::ONGOING_LOG);
315 service.GetCurrentSyntheticFieldTrials(&synthetic_trials);
316 EXPECT_EQ(3U, synthetic_trials.size());
317 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial1", "Group2"));
318 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial2", "Group2"));
319 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial3", "Group3"));
320 service.log_manager_.FinishCurrentLog();