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.
7 #include "base/basictypes.h"
8 #include "base/command_line.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/metrics/field_trial.h"
11 #include "base/port.h"
12 #include "base/prefs/pref_service.h"
13 #include "base/prefs/testing_pref_service.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/threading/sequenced_worker_pool.h"
18 #include "base/time/time.h"
19 #include "base/tracked_objects.h"
20 #include "chrome/browser/google/google_util.h"
21 #include "chrome/browser/metrics/metrics_log.h"
22 #include "chrome/browser/prefs/browser_prefs.h"
23 #include "chrome/common/chrome_switches.h"
24 #include "chrome/common/metrics/proto/profiler_event.pb.h"
25 #include "chrome/common/metrics/proto/system_profile.pb.h"
26 #include "chrome/common/metrics/variations/variations_util.h"
27 #include "chrome/common/pref_names.h"
28 #include "chrome/installer/util/google_update_settings.h"
29 #include "components/variations/entropy_provider.h"
30 #include "content/public/browser/browser_thread.h"
31 #include "content/public/common/process_type.h"
32 #include "content/public/common/webplugininfo.h"
33 #include "content/public/test/test_utils.h"
34 #include "testing/gtest/include/gtest/gtest.h"
35 #include "ui/gfx/size.h"
38 #if defined(OS_CHROMEOS)
39 #include "chrome/browser/chromeos/login/fake_user_manager.h"
40 #include "chrome/browser/chromeos/login/user_manager.h"
41 #include "chromeos/dbus/fake_dbus_thread_manager.h"
44 using base::TimeDelta;
45 using metrics::ProfilerEventProto;
46 using tracked_objects::ProcessDataSnapshot;
47 using tracked_objects::TaskSnapshot;
51 const char kClientId[] = "bogus client ID";
52 const int64 kInstallDate = 1373051956;
53 const int64 kEnabledDate = 1373001211;
54 const int kSessionId = 127;
55 const int kScreenWidth = 1024;
56 const int kScreenHeight = 768;
57 const int kScreenCount = 3;
58 const float kScreenScaleFactor = 2;
59 const char kBrandForTesting[] = "brand_for_testing";
60 const chrome_variations::ActiveGroupId kFieldTrialIds[] = {
66 class TestMetricsLog : public MetricsLog {
68 TestMetricsLog(const std::string& client_id, int session_id)
69 : MetricsLog(client_id, session_id),
70 brand_for_testing_(kBrandForTesting) {
71 chrome::RegisterLocalState(prefs_.registry());
73 prefs_.SetInt64(prefs::kInstallDate, kInstallDate);
74 prefs_.SetString(prefs::kMetricsClientIDTimestamp,
75 base::Int64ToString(kEnabledDate));
76 #if defined(OS_CHROMEOS)
77 prefs_.SetInteger(prefs::kStabilityChildProcessCrashCount, 10);
78 prefs_.SetInteger(prefs::kStabilityOtherUserCrashCount, 11);
79 prefs_.SetInteger(prefs::kStabilityKernelCrashCount, 12);
80 prefs_.SetInteger(prefs::kStabilitySystemUncleanShutdownCount, 13);
83 virtual ~TestMetricsLog() {}
85 virtual PrefService* GetPrefService() OVERRIDE {
89 const metrics::ChromeUserMetricsExtension& uma_proto() const {
90 return *MetricsLog::uma_proto();
93 const metrics::SystemProfileProto& system_profile() const {
94 return uma_proto().system_profile();
98 virtual void GetFieldTrialIds(
99 std::vector<chrome_variations::ActiveGroupId>* field_trial_ids) const
101 ASSERT_TRUE(field_trial_ids->empty());
103 for (size_t i = 0; i < arraysize(kFieldTrialIds); ++i) {
104 field_trial_ids->push_back(kFieldTrialIds[i]);
108 virtual gfx::Size GetScreenSize() const OVERRIDE {
109 return gfx::Size(kScreenWidth, kScreenHeight);
112 virtual float GetScreenDeviceScaleFactor() const OVERRIDE {
113 return kScreenScaleFactor;
116 virtual int GetScreenCount() const OVERRIDE {
120 TestingPrefServiceSimple prefs_;
122 google_util::BrandForTesting brand_for_testing_;
124 DISALLOW_COPY_AND_ASSIGN(TestMetricsLog);
129 class MetricsLogTest : public testing::Test {
131 MetricsLogTest() : message_loop_(base::MessageLoop::TYPE_IO) {}
134 void TestRecordEnvironment(bool proto_only) {
135 TestMetricsLog log(kClientId, kSessionId);
137 std::vector<content::WebPluginInfo> plugins;
138 GoogleUpdateMetrics google_update_metrics;
140 log.RecordEnvironmentProto(plugins, google_update_metrics);
142 log.RecordEnvironment(plugins, google_update_metrics, base::TimeDelta());
144 // Computed from original time of 1373051956.
145 EXPECT_EQ(1373050800, log.system_profile().install_date());
147 // Computed from original time of 1373001211.
148 EXPECT_EQ(1373000400, log.system_profile().uma_enabled_date());
150 const metrics::SystemProfileProto& system_profile = log.system_profile();
151 ASSERT_EQ(arraysize(kFieldTrialIds),
152 static_cast<size_t>(system_profile.field_trial_size()));
153 for (size_t i = 0; i < arraysize(kFieldTrialIds); ++i) {
154 const metrics::SystemProfileProto::FieldTrial& field_trial =
155 system_profile.field_trial(i);
156 EXPECT_EQ(kFieldTrialIds[i].name, field_trial.name_id());
157 EXPECT_EQ(kFieldTrialIds[i].group, field_trial.group_id());
160 EXPECT_EQ(kBrandForTesting, system_profile.brand_code());
162 const metrics::SystemProfileProto::Hardware& hardware =
163 system_profile.hardware();
164 EXPECT_EQ(kScreenWidth, hardware.primary_screen_width());
165 EXPECT_EQ(kScreenHeight, hardware.primary_screen_height());
166 EXPECT_EQ(kScreenScaleFactor, hardware.primary_screen_scale_factor());
167 EXPECT_EQ(kScreenCount, hardware.screen_count());
169 EXPECT_TRUE(hardware.has_cpu());
170 EXPECT_TRUE(hardware.cpu().has_vendor_name());
171 EXPECT_TRUE(hardware.cpu().has_signature());
173 // TODO(isherman): Verify other data written into the protobuf as a result
177 virtual void SetUp() OVERRIDE {
178 #if defined(OS_CHROMEOS)
179 fake_dbus_thread_manager_ = new chromeos::FakeDBusThreadManager();
180 chromeos::DBusThreadManager::InitializeForTesting(
181 fake_dbus_thread_manager_);
183 // Enable multi-profiles.
184 CommandLine::ForCurrentProcess()->AppendSwitch(switches::kMultiProfiles);
185 field_trial_list_.reset(new base::FieldTrialList(
186 new metrics::SHA1EntropyProvider("42")));
187 base::FieldTrialList::CreateTrialsFromString(
188 "ChromeOSUseMultiProfiles/Enable/",
189 base::FieldTrialList::ACTIVATE_TRIALS);
190 #endif // OS_CHROMEOS
193 virtual void TearDown() OVERRIDE {
194 // Drain the blocking pool from PostTaskAndReply executed by
195 // MetrticsLog.network_observer_.
196 content::BrowserThread::GetBlockingPool()->FlushForTesting();
197 content::RunAllPendingInMessageLoop();
199 #if defined(OS_CHROMEOS)
200 chromeos::DBusThreadManager::Shutdown();
201 #endif // OS_CHROMEOS
205 // This is necessary because eventually some tests call base::RepeatingTimer
206 // functions and a message loop is required for that.
207 base::MessageLoop message_loop_;
209 #if defined(OS_CHROMEOS)
210 chromeos::FakeDBusThreadManager* fake_dbus_thread_manager_;
211 scoped_ptr<base::FieldTrialList> field_trial_list_;
212 #endif // OS_CHROMEOS
215 TEST_F(MetricsLogTest, RecordEnvironment) {
216 // Test that recording the environment works via both of the public methods
217 // RecordEnvironment() and RecordEnvironmentProto().
218 TestRecordEnvironment(false);
219 TestRecordEnvironment(true);
222 // Test that we properly write profiler data to the log.
223 TEST_F(MetricsLogTest, RecordProfilerData) {
224 TestMetricsLog log(kClientId, kSessionId);
225 EXPECT_EQ(0, log.uma_proto().profiler_event_size());
228 ProcessDataSnapshot process_data;
229 process_data.process_id = 177;
230 process_data.tasks.push_back(TaskSnapshot());
231 process_data.tasks.back().birth.location.file_name = "file";
232 process_data.tasks.back().birth.location.function_name = "function";
233 process_data.tasks.back().birth.location.line_number = 1337;
234 process_data.tasks.back().birth.thread_name = "birth_thread";
235 process_data.tasks.back().death_data.count = 37;
236 process_data.tasks.back().death_data.run_duration_sum = 31;
237 process_data.tasks.back().death_data.run_duration_max = 17;
238 process_data.tasks.back().death_data.run_duration_sample = 13;
239 process_data.tasks.back().death_data.queue_duration_sum = 8;
240 process_data.tasks.back().death_data.queue_duration_max = 5;
241 process_data.tasks.back().death_data.queue_duration_sample = 3;
242 process_data.tasks.back().death_thread_name = "Still_Alive";
243 process_data.tasks.push_back(TaskSnapshot());
244 process_data.tasks.back().birth.location.file_name = "file2";
245 process_data.tasks.back().birth.location.function_name = "function2";
246 process_data.tasks.back().birth.location.line_number = 1773;
247 process_data.tasks.back().birth.thread_name = "birth_thread2";
248 process_data.tasks.back().death_data.count = 19;
249 process_data.tasks.back().death_data.run_duration_sum = 23;
250 process_data.tasks.back().death_data.run_duration_max = 11;
251 process_data.tasks.back().death_data.run_duration_sample = 7;
252 process_data.tasks.back().death_data.queue_duration_sum = 0;
253 process_data.tasks.back().death_data.queue_duration_max = 0;
254 process_data.tasks.back().death_data.queue_duration_sample = 0;
255 process_data.tasks.back().death_thread_name = "death_thread";
257 log.RecordProfilerData(process_data, content::PROCESS_TYPE_BROWSER);
258 ASSERT_EQ(1, log.uma_proto().profiler_event_size());
259 EXPECT_EQ(ProfilerEventProto::STARTUP_PROFILE,
260 log.uma_proto().profiler_event(0).profile_type());
261 EXPECT_EQ(ProfilerEventProto::WALL_CLOCK_TIME,
262 log.uma_proto().profiler_event(0).time_source());
264 ASSERT_EQ(2, log.uma_proto().profiler_event(0).tracked_object_size());
266 const ProfilerEventProto::TrackedObject* tracked_object =
267 &log.uma_proto().profiler_event(0).tracked_object(0);
268 EXPECT_EQ(GG_UINT64_C(10123486280357988687),
269 tracked_object->source_file_name_hash());
270 EXPECT_EQ(GG_UINT64_C(13962325592283560029),
271 tracked_object->source_function_name_hash());
272 EXPECT_EQ(1337, tracked_object->source_line_number());
273 EXPECT_EQ(GG_UINT64_C(3400908935414830400),
274 tracked_object->birth_thread_name_hash());
275 EXPECT_EQ(37, tracked_object->exec_count());
276 EXPECT_EQ(31, tracked_object->exec_time_total());
277 EXPECT_EQ(13, tracked_object->exec_time_sampled());
278 EXPECT_EQ(8, tracked_object->queue_time_total());
279 EXPECT_EQ(3, tracked_object->queue_time_sampled());
280 EXPECT_EQ(GG_UINT64_C(10151977472163283085),
281 tracked_object->exec_thread_name_hash());
282 EXPECT_EQ(177U, tracked_object->process_id());
283 EXPECT_EQ(ProfilerEventProto::TrackedObject::BROWSER,
284 tracked_object->process_type());
286 tracked_object = &log.uma_proto().profiler_event(0).tracked_object(1);
287 EXPECT_EQ(GG_UINT64_C(2025659946535236365),
288 tracked_object->source_file_name_hash());
289 EXPECT_EQ(GG_UINT64_C(55232426147951219),
290 tracked_object->source_function_name_hash());
291 EXPECT_EQ(1773, tracked_object->source_line_number());
292 EXPECT_EQ(GG_UINT64_C(15727396632046120663),
293 tracked_object->birth_thread_name_hash());
294 EXPECT_EQ(19, tracked_object->exec_count());
295 EXPECT_EQ(23, tracked_object->exec_time_total());
296 EXPECT_EQ(7, tracked_object->exec_time_sampled());
297 EXPECT_EQ(0, tracked_object->queue_time_total());
298 EXPECT_EQ(0, tracked_object->queue_time_sampled());
299 EXPECT_EQ(GG_UINT64_C(14275151213201158253),
300 tracked_object->exec_thread_name_hash());
301 EXPECT_EQ(177U, tracked_object->process_id());
302 EXPECT_EQ(ProfilerEventProto::TrackedObject::BROWSER,
303 tracked_object->process_type());
307 ProcessDataSnapshot process_data;
308 process_data.process_id = 1177;
309 process_data.tasks.push_back(TaskSnapshot());
310 process_data.tasks.back().birth.location.file_name = "file3";
311 process_data.tasks.back().birth.location.function_name = "function3";
312 process_data.tasks.back().birth.location.line_number = 7331;
313 process_data.tasks.back().birth.thread_name = "birth_thread3";
314 process_data.tasks.back().death_data.count = 137;
315 process_data.tasks.back().death_data.run_duration_sum = 131;
316 process_data.tasks.back().death_data.run_duration_max = 117;
317 process_data.tasks.back().death_data.run_duration_sample = 113;
318 process_data.tasks.back().death_data.queue_duration_sum = 108;
319 process_data.tasks.back().death_data.queue_duration_max = 105;
320 process_data.tasks.back().death_data.queue_duration_sample = 103;
321 process_data.tasks.back().death_thread_name = "death_thread3";
323 log.RecordProfilerData(process_data, content::PROCESS_TYPE_RENDERER);
324 ASSERT_EQ(1, log.uma_proto().profiler_event_size());
325 EXPECT_EQ(ProfilerEventProto::STARTUP_PROFILE,
326 log.uma_proto().profiler_event(0).profile_type());
327 EXPECT_EQ(ProfilerEventProto::WALL_CLOCK_TIME,
328 log.uma_proto().profiler_event(0).time_source());
329 ASSERT_EQ(3, log.uma_proto().profiler_event(0).tracked_object_size());
331 const ProfilerEventProto::TrackedObject* tracked_object =
332 &log.uma_proto().profiler_event(0).tracked_object(2);
333 EXPECT_EQ(GG_UINT64_C(2686523203278102732),
334 tracked_object->source_file_name_hash());
335 EXPECT_EQ(GG_UINT64_C(5081672290546182009),
336 tracked_object->source_function_name_hash());
337 EXPECT_EQ(7331, tracked_object->source_line_number());
338 EXPECT_EQ(GG_UINT64_C(8768512930949373716),
339 tracked_object->birth_thread_name_hash());
340 EXPECT_EQ(137, tracked_object->exec_count());
341 EXPECT_EQ(131, tracked_object->exec_time_total());
342 EXPECT_EQ(113, tracked_object->exec_time_sampled());
343 EXPECT_EQ(108, tracked_object->queue_time_total());
344 EXPECT_EQ(103, tracked_object->queue_time_sampled());
345 EXPECT_EQ(GG_UINT64_C(7246674144371406371),
346 tracked_object->exec_thread_name_hash());
347 EXPECT_EQ(1177U, tracked_object->process_id());
348 EXPECT_EQ(ProfilerEventProto::TrackedObject::RENDERER,
349 tracked_object->process_type());
353 #if defined(OS_CHROMEOS)
354 TEST_F(MetricsLogTest, MultiProfileUserCount) {
355 std::string user1("user1@example.com");
356 std::string user2("user2@example.com");
357 std::string user3("user3@example.com");
359 // |scoped_enabler| takes over the lifetime of |user_manager|.
360 chromeos::FakeUserManager* user_manager = new chromeos::FakeUserManager();
361 chromeos::ScopedUserManagerEnabler scoped_enabler(user_manager);
362 user_manager->AddKioskAppUser(user1);
363 user_manager->AddKioskAppUser(user2);
364 user_manager->AddKioskAppUser(user3);
366 user_manager->LoginUser(user1);
367 user_manager->LoginUser(user3);
369 TestMetricsLog log(kClientId, kSessionId);
370 std::vector<content::WebPluginInfo> plugins;
371 GoogleUpdateMetrics google_update_metrics;
372 log.RecordEnvironmentProto(plugins, google_update_metrics);
373 EXPECT_EQ(2u, log.system_profile().multi_profile_user_count());
376 TEST_F(MetricsLogTest, MultiProfileCountInvalidated) {
377 std::string user1("user1@example.com");
378 std::string user2("user2@example.com");
379 std::string user3("user3@example.com");
381 // |scoped_enabler| takes over the lifetime of |user_manager|.
382 chromeos::FakeUserManager* user_manager = new chromeos::FakeUserManager();
383 chromeos::ScopedUserManagerEnabler scoped_enabler(user_manager);
384 user_manager->AddKioskAppUser(user1);
385 user_manager->AddKioskAppUser(user2);
386 user_manager->AddKioskAppUser(user3);
388 user_manager->LoginUser(user1);
390 TestMetricsLog log(kClientId, kSessionId);
391 EXPECT_EQ(1u, log.system_profile().multi_profile_user_count());
393 user_manager->LoginUser(user2);
394 log.RecordEnvironmentProto(std::vector<content::WebPluginInfo>(),
395 GoogleUpdateMetrics());
396 EXPECT_EQ(0u, log.system_profile().multi_profile_user_count());
398 #endif // OS_CHROMEOS