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"
24 class TestMetricsService
: public MetricsService
{
26 TestMetricsService() {}
27 virtual ~TestMetricsService() {}
29 MetricsLogManager
* log_manager() {
34 DISALLOW_COPY_AND_ASSIGN(TestMetricsService
);
37 class TestMetricsLog
: public MetricsLog
{
39 TestMetricsLog(const std::string
& client_id
, int session_id
)
40 : MetricsLog(client_id
, session_id
) {}
41 virtual ~TestMetricsLog() {}
44 virtual gfx::Size
GetScreenSize() const OVERRIDE
{
45 return gfx::Size(1024, 768);
48 virtual float GetScreenDeviceScaleFactor() const OVERRIDE
{
52 virtual int GetScreenCount() const OVERRIDE
{
56 virtual void WriteBluetoothProto(
57 metrics::SystemProfileProto::Hardware
* hardware
) OVERRIDE
{
60 DISALLOW_COPY_AND_ASSIGN(TestMetricsLog
);
63 class MetricsServiceTest
: public testing::Test
{
66 : testing_local_state_(TestingBrowserProcess::GetGlobal()) {
69 virtual ~MetricsServiceTest() {
70 MetricsService::SetExecutionPhase(MetricsService::UNINITIALIZED_PHASE
);
73 PrefService
* GetLocalState() {
74 return testing_local_state_
.Get();
77 // Returns true if there is a synthetic trial in the given vector that matches
78 // the given trial name and trial group; returns false otherwise.
79 bool HasSyntheticTrial(
80 const std::vector
<chrome_variations::ActiveGroupId
>& synthetic_trials
,
81 const std::string
& trial_name
,
82 const std::string
& trial_group
) {
83 uint32 trial_name_hash
= metrics::HashName(trial_name
);
84 uint32 trial_group_hash
= metrics::HashName(trial_group
);
85 for (std::vector
<chrome_variations::ActiveGroupId
>::const_iterator it
=
86 synthetic_trials
.begin();
87 it
!= synthetic_trials
.end(); ++it
) {
88 if ((*it
).name
== trial_name_hash
&& (*it
).group
== trial_group_hash
)
95 content::TestBrowserThreadBundle thread_bundle_
;
96 ScopedTestingLocalState testing_local_state_
;
98 DISALLOW_COPY_AND_ASSIGN(MetricsServiceTest
);
103 // Ensure the ClientId is formatted as expected.
104 TEST_F(MetricsServiceTest
, ClientIdCorrectlyFormatted
) {
105 std::string clientid
= MetricsService::GenerateClientID();
106 EXPECT_EQ(36U, clientid
.length());
108 for (size_t i
= 0; i
< clientid
.length(); ++i
) {
109 char current
= clientid
[i
];
110 if (i
== 8 || i
== 13 || i
== 18 || i
== 23)
111 EXPECT_EQ('-', current
);
113 EXPECT_TRUE(isxdigit(current
));
117 TEST_F(MetricsServiceTest
, IsPluginProcess
) {
119 MetricsService::IsPluginProcess(content::PROCESS_TYPE_PLUGIN
));
121 MetricsService::IsPluginProcess(content::PROCESS_TYPE_PPAPI_PLUGIN
));
123 MetricsService::IsPluginProcess(content::PROCESS_TYPE_GPU
));
126 TEST_F(MetricsServiceTest
, LowEntropySource0NotReset
) {
127 MetricsService service
;
129 // Get the low entropy source once, to initialize it.
130 service
.GetLowEntropySource();
132 // Now, set it to 0 and ensure it doesn't get reset.
133 service
.low_entropy_source_
= 0;
134 EXPECT_EQ(0, service
.GetLowEntropySource());
135 // Call it another time, just to make sure.
136 EXPECT_EQ(0, service
.GetLowEntropySource());
139 TEST_F(MetricsServiceTest
, PermutedEntropyCacheClearedWhenLowEntropyReset
) {
140 const PrefService::Preference
* low_entropy_pref
=
141 GetLocalState()->FindPreference(prefs::kMetricsLowEntropySource
);
142 const char* kCachePrefName
= prefs::kMetricsPermutedEntropyCache
;
143 int low_entropy_value
= -1;
145 // First, generate an initial low entropy source value.
147 EXPECT_TRUE(low_entropy_pref
->IsDefaultValue());
149 MetricsService::SetExecutionPhase(MetricsService::UNINITIALIZED_PHASE
);
150 MetricsService service
;
151 service
.GetLowEntropySource();
153 EXPECT_FALSE(low_entropy_pref
->IsDefaultValue());
154 EXPECT_TRUE(low_entropy_pref
->GetValue()->GetAsInteger(&low_entropy_value
));
157 // Now, set a dummy value in the permuted entropy cache pref and verify that
158 // another call to GetLowEntropySource() doesn't clobber it when
159 // --reset-variation-state wasn't specified.
161 GetLocalState()->SetString(kCachePrefName
, "test");
163 MetricsService::SetExecutionPhase(MetricsService::UNINITIALIZED_PHASE
);
164 MetricsService service
;
165 service
.GetLowEntropySource();
167 EXPECT_EQ("test", GetLocalState()->GetString(kCachePrefName
));
168 EXPECT_EQ(low_entropy_value
,
169 GetLocalState()->GetInteger(prefs::kMetricsLowEntropySource
));
172 // Verify that the cache does get reset if --reset-variations-state is passed.
174 CommandLine::ForCurrentProcess()->AppendSwitch(
175 switches::kResetVariationState
);
177 MetricsService::SetExecutionPhase(MetricsService::UNINITIALIZED_PHASE
);
178 MetricsService service
;
179 service
.GetLowEntropySource();
181 EXPECT_TRUE(GetLocalState()->GetString(kCachePrefName
).empty());
185 TEST_F(MetricsServiceTest
, InitialStabilityLogAfterCleanShutDown
) {
186 base::FieldTrialList
field_trial_list(NULL
);
187 base::FieldTrialList::CreateFieldTrial("UMAStability", "SeparateLog");
189 GetLocalState()->SetBoolean(prefs::kStabilityExitedCleanly
, true);
191 TestMetricsService service
;
192 service
.InitializeMetricsRecordingState(MetricsService::REPORTING_ENABLED
);
193 // No initial stability log should be generated.
194 EXPECT_FALSE(service
.log_manager()->has_unsent_logs());
195 EXPECT_FALSE(service
.log_manager()->has_staged_log());
198 TEST_F(MetricsServiceTest
, InitialStabilityLogAfterCrash
) {
199 base::FieldTrialList
field_trial_list(NULL
);
200 base::FieldTrialList::CreateFieldTrial("UMAStability", "SeparateLog");
202 GetLocalState()->ClearPref(prefs::kStabilityExitedCleanly
);
204 // Set up prefs to simulate restarting after a crash.
206 // Save an existing system profile to prefs, to correspond to what would be
207 // saved from a previous session.
208 TestMetricsLog
log("client", 1);
209 log
.RecordEnvironment(std::vector
<content::WebPluginInfo
>(),
210 GoogleUpdateMetrics(),
211 std::vector
<chrome_variations::ActiveGroupId
>());
213 // Record stability build time and version from previous session, so that
214 // stability metrics (including exited cleanly flag) won't be cleared.
215 GetLocalState()->SetInt64(prefs::kStabilityStatsBuildTime
,
216 MetricsLog::GetBuildTime());
217 GetLocalState()->SetString(prefs::kStabilityStatsVersion
,
218 MetricsLog::GetVersionString());
220 GetLocalState()->SetBoolean(prefs::kStabilityExitedCleanly
, false);
222 TestMetricsService service
;
223 service
.InitializeMetricsRecordingState(MetricsService::REPORTING_ENABLED
);
225 // The initial stability log should be generated and persisted in unsent logs.
226 MetricsLogManager
* log_manager
= service
.log_manager();
227 EXPECT_TRUE(log_manager
->has_unsent_logs());
228 EXPECT_FALSE(log_manager
->has_staged_log());
230 // Stage the log and retrieve it.
231 log_manager
->StageNextLogForUpload();
232 EXPECT_TRUE(log_manager
->has_staged_log());
234 metrics::ChromeUserMetricsExtension uma_log
;
235 EXPECT_TRUE(uma_log
.ParseFromString(log_manager
->staged_log_text()));
237 EXPECT_TRUE(uma_log
.has_client_id());
238 EXPECT_TRUE(uma_log
.has_session_id());
239 EXPECT_TRUE(uma_log
.has_system_profile());
240 EXPECT_EQ(0, uma_log
.user_action_event_size());
241 EXPECT_EQ(0, uma_log
.omnibox_event_size());
242 EXPECT_EQ(0, uma_log
.histogram_event_size());
243 EXPECT_EQ(0, uma_log
.profiler_event_size());
244 EXPECT_EQ(0, uma_log
.perf_data_size());
246 EXPECT_EQ(1, uma_log
.system_profile().stability().crash_count());
249 // Crashes on at least Mac and Linux. http://crbug.com/320433
250 TEST_F(MetricsServiceTest
, DISABLED_RegisterSyntheticTrial
) {
251 MetricsService service
;
253 // Add two synthetic trials and confirm that they show up in the list.
254 SyntheticTrialGroup
trial1(metrics::HashName("TestTrial1"),
255 metrics::HashName("Group1"),
256 base::TimeTicks::Now());
257 service
.RegisterSyntheticFieldTrial(trial1
);
259 SyntheticTrialGroup
trial2(metrics::HashName("TestTrial2"),
260 metrics::HashName("Group2"),
261 base::TimeTicks::Now());
262 service
.RegisterSyntheticFieldTrial(trial2
);
264 service
.log_manager_
.BeginLoggingWithLog(new MetricsLog("clientID", 1),
265 MetricsLog::INITIAL_LOG
);
267 std::vector
<chrome_variations::ActiveGroupId
> synthetic_trials
;
268 service
.GetCurrentSyntheticFieldTrials(&synthetic_trials
);
269 EXPECT_EQ(2U, synthetic_trials
.size());
270 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials
, "TestTrial1", "Group1"));
271 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials
, "TestTrial2", "Group2"));
273 // Change the group for the first trial after the log started.
274 SyntheticTrialGroup
trial3(metrics::HashName("TestTrial1"),
275 metrics::HashName("Group2"),
276 base::TimeTicks::Now());
277 service
.RegisterSyntheticFieldTrial(trial3
);
278 service
.GetCurrentSyntheticFieldTrials(&synthetic_trials
);
279 EXPECT_EQ(1U, synthetic_trials
.size());
280 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials
, "TestTrial2", "Group2"));
282 // Add a new trial after the log started and confirm that it doesn't show up.
283 SyntheticTrialGroup
trial4(metrics::HashName("TestTrial3"),
284 metrics::HashName("Group3"),
285 base::TimeTicks::Now());
286 service
.RegisterSyntheticFieldTrial(trial4
);
287 service
.GetCurrentSyntheticFieldTrials(&synthetic_trials
);
288 EXPECT_EQ(1U, synthetic_trials
.size());
289 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials
, "TestTrial2", "Group2"));
292 service
.log_manager_
.FinishCurrentLog();
293 service
.log_manager_
.BeginLoggingWithLog(new MetricsLog("clientID", 1),
294 MetricsLog::ONGOING_LOG
);
295 service
.GetCurrentSyntheticFieldTrials(&synthetic_trials
);
296 EXPECT_EQ(3U, synthetic_trials
.size());
297 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials
, "TestTrial1", "Group2"));
298 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials
, "TestTrial2", "Group2"));
299 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials
, "TestTrial3", "Group3"));
300 service
.log_manager_
.FinishCurrentLog();