blob: 9ed08fc5d4fa3d252aa64397a6019f1a90341e16 [file] [log] [blame]
[email protected]767c9d92012-03-02 16:04:341// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
5#include <string>
6
[email protected]767c9d92012-03-02 16:04:347#include "base/basictypes.h"
[email protected]f65859e2013-02-04 20:00:258#include "base/message_loop.h"
[email protected]ed0fd002012-04-25 23:10:349#include "base/port.h"
[email protected]3853a4c2013-02-11 17:15:5710#include "base/prefs/pref_service.h"
[email protected]e5ba874f2013-02-14 17:20:1911#include "base/prefs/testing_pref_service.h"
[email protected]f9b294362013-06-10 20:22:3112#include "base/strings/string_util.h"
13#include "base/strings/stringprintf.h"
[email protected]c006916b2013-02-20 19:30:3514#include "base/threading/sequenced_worker_pool.h"
[email protected]84813472013-06-28 00:25:1915#include "base/time/time.h"
[email protected]ed0fd002012-04-25 23:10:3416#include "base/tracked_objects.h"
[email protected]24b9bb392013-01-29 20:29:2917#include "chrome/browser/google/google_util.h"
[email protected]cd1adc22009-01-16 01:29:2218#include "chrome/browser/metrics/metrics_log.h"
[email protected]2f9d81322011-02-21 09:55:4319#include "chrome/browser/prefs/browser_prefs.h"
[email protected]ed0fd002012-04-25 23:10:3420#include "chrome/common/metrics/proto/profiler_event.pb.h"
[email protected]767c9d92012-03-02 16:04:3421#include "chrome/common/metrics/proto/system_profile.pb.h"
[email protected]b1de2c72013-02-06 02:45:4722#include "chrome/common/metrics/variations/variations_util.h"
[email protected]c1834a92011-01-21 18:21:0323#include "chrome/common/pref_names.h"
[email protected]197c0772012-05-14 23:50:5124#include "chrome/installer/util/google_update_settings.h"
[email protected]c006916b2013-02-20 19:30:3525#include "content/public/browser/browser_thread.h"
[email protected]d5d383252013-07-04 14:44:3226#include "content/public/common/process_type.h"
[email protected]c006916b2013-02-20 19:30:3527#include "content/public/test/test_utils.h"
initial.commit09911bf2008-07-26 23:55:2928#include "testing/gtest/include/gtest/gtest.h"
[email protected]767c9d92012-03-02 16:04:3429#include "ui/gfx/size.h"
[email protected]761fa4702013-07-02 15:25:1530#include "url/gurl.h"
[email protected]fe58acc22012-02-29 01:29:5831#include "webkit/plugins/webplugininfo.h"
initial.commit09911bf2008-07-26 23:55:2932
[email protected]611ae29a2013-04-29 21:32:1933#if defined(OS_CHROMEOS)
[email protected]611ae29a2013-04-29 21:32:1934#include "chromeos/dbus/mock_dbus_thread_manager_without_gmock.h"
35#endif // OS_CHROMEOS
36
[email protected]e1acf6f2008-10-27 20:43:3337using base::TimeDelta;
[email protected]ed0fd002012-04-25 23:10:3438using metrics::ProfilerEventProto;
39using tracked_objects::ProcessDataSnapshot;
40using tracked_objects::TaskSnapshot;
[email protected]e1acf6f2008-10-27 20:43:3341
initial.commit09911bf2008-07-26 23:55:2942namespace {
[email protected]37f39e42010-01-06 17:35:1743
[email protected]767c9d92012-03-02 16:04:3444const char kClientId[] = "bogus client ID";
45const int kSessionId = 127;
46const int kScreenWidth = 1024;
47const int kScreenHeight = 768;
48const int kScreenCount = 3;
[email protected]aa96417972012-08-22 03:16:4449const float kScreenScaleFactor = 2;
[email protected]24b9bb392013-01-29 20:29:2950const char kBrandForTesting[] = "brand_for_testing";
[email protected]0c8b7ad2012-11-06 07:08:1451const chrome_variations::ActiveGroupId kFieldTrialIds[] = {
[email protected]767c9d92012-03-02 16:04:3452 {37, 43},
53 {13, 47},
54 {23, 17}
55};
56
57class TestMetricsLog : public MetricsLog {
58 public:
59 TestMetricsLog(const std::string& client_id, int session_id)
[email protected]24b9bb392013-01-29 20:29:2960 : MetricsLog(client_id, session_id),
61 brand_for_testing_(kBrandForTesting) {
[email protected]4082306d92013-02-21 14:51:0162 chrome::RegisterLocalState(prefs_.registry());
[email protected]767c9d92012-03-02 16:04:3463
64#if defined(OS_CHROMEOS)
65 prefs_.SetInteger(prefs::kStabilityChildProcessCrashCount, 10);
66 prefs_.SetInteger(prefs::kStabilityOtherUserCrashCount, 11);
67 prefs_.SetInteger(prefs::kStabilityKernelCrashCount, 12);
68 prefs_.SetInteger(prefs::kStabilitySystemUncleanShutdownCount, 13);
69#endif // OS_CHROMEOS
70 }
71 virtual ~TestMetricsLog() {}
72
73 virtual PrefService* GetPrefService() OVERRIDE {
74 return &prefs_;
[email protected]37f39e42010-01-06 17:35:1775 }
76
[email protected]ed0fd002012-04-25 23:10:3477 const metrics::ChromeUserMetricsExtension& uma_proto() const {
78 return *MetricsLog::uma_proto();
79 }
80
[email protected]767c9d92012-03-02 16:04:3481 const metrics::SystemProfileProto& system_profile() const {
[email protected]ed0fd002012-04-25 23:10:3482 return uma_proto().system_profile();
[email protected]767c9d92012-03-02 16:04:3483 }
[email protected]37f39e42010-01-06 17:35:1784
[email protected]767c9d92012-03-02 16:04:3485 private:
86 virtual std::string GetCurrentTimeString() OVERRIDE {
initial.commit09911bf2008-07-26 23:55:2987 return std::string();
88 }
[email protected]767c9d92012-03-02 16:04:3489
90 virtual void GetFieldTrialIds(
[email protected]0c8b7ad2012-11-06 07:08:1491 std::vector<chrome_variations::ActiveGroupId>* field_trial_ids) const
[email protected]767c9d92012-03-02 16:04:3492 OVERRIDE {
93 ASSERT_TRUE(field_trial_ids->empty());
94
95 for (size_t i = 0; i < arraysize(kFieldTrialIds); ++i) {
96 field_trial_ids->push_back(kFieldTrialIds[i]);
97 }
98 }
99
100 virtual gfx::Size GetScreenSize() const OVERRIDE {
101 return gfx::Size(kScreenWidth, kScreenHeight);
102 }
103
[email protected]aa96417972012-08-22 03:16:44104 virtual float GetScreenDeviceScaleFactor() const OVERRIDE {
105 return kScreenScaleFactor;
106 }
107
[email protected]767c9d92012-03-02 16:04:34108 virtual int GetScreenCount() const OVERRIDE {
109 return kScreenCount;
110 }
111
[email protected]5b199522012-12-22 17:24:44112 TestingPrefServiceSimple prefs_;
[email protected]767c9d92012-03-02 16:04:34113
[email protected]24b9bb392013-01-29 20:29:29114 google_util::BrandForTesting brand_for_testing_;
115
[email protected]767c9d92012-03-02 16:04:34116 DISALLOW_COPY_AND_ASSIGN(TestMetricsLog);
initial.commit09911bf2008-07-26 23:55:29117};
118
[email protected]fe58acc22012-02-29 01:29:58119} // namespace
initial.commit09911bf2008-07-26 23:55:29120
[email protected]fe58acc22012-02-29 01:29:58121class MetricsLogTest : public testing::Test {
[email protected]f65859e2013-02-04 20:00:25122 public:
[email protected]b3a25092013-05-28 22:08:16123 MetricsLogTest() : message_loop_(base::MessageLoop::TYPE_IO) {}
124
[email protected]bc66d532012-03-23 01:57:05125 protected:
126 void TestRecordEnvironment(bool proto_only) {
127 TestMetricsLog log(kClientId, kSessionId);
128
129 std::vector<webkit::WebPluginInfo> plugins;
[email protected]197c0772012-05-14 23:50:51130 GoogleUpdateMetrics google_update_metrics;
[email protected]bc66d532012-03-23 01:57:05131 if (proto_only)
[email protected]197c0772012-05-14 23:50:51132 log.RecordEnvironmentProto(plugins, google_update_metrics);
[email protected]bc66d532012-03-23 01:57:05133 else
[email protected]197c0772012-05-14 23:50:51134 log.RecordEnvironment(plugins, google_update_metrics, NULL);
[email protected]bc66d532012-03-23 01:57:05135
136 const metrics::SystemProfileProto& system_profile = log.system_profile();
137 ASSERT_EQ(arraysize(kFieldTrialIds),
138 static_cast<size_t>(system_profile.field_trial_size()));
139 for (size_t i = 0; i < arraysize(kFieldTrialIds); ++i) {
140 const metrics::SystemProfileProto::FieldTrial& field_trial =
141 system_profile.field_trial(i);
142 EXPECT_EQ(kFieldTrialIds[i].name, field_trial.name_id());
143 EXPECT_EQ(kFieldTrialIds[i].group, field_trial.group_id());
144 }
145
[email protected]24b9bb392013-01-29 20:29:29146 EXPECT_EQ(kBrandForTesting, system_profile.brand_code());
147
[email protected]aa96417972012-08-22 03:16:44148 const metrics::SystemProfileProto::Hardware& hardware =
149 system_profile.hardware();
150 EXPECT_EQ(kScreenWidth, hardware.primary_screen_width());
151 EXPECT_EQ(kScreenHeight, hardware.primary_screen_height());
152 EXPECT_EQ(kScreenScaleFactor, hardware.primary_screen_scale_factor());
153 EXPECT_EQ(kScreenCount, hardware.screen_count());
154
[email protected]bc66d532012-03-23 01:57:05155 // TODO(isherman): Verify other data written into the protobuf as a result
156 // of this call.
157 }
[email protected]c006916b2013-02-20 19:30:35158
[email protected]611ae29a2013-04-29 21:32:19159 virtual void SetUp() OVERRIDE {
160#if defined(OS_CHROMEOS)
[email protected]611ae29a2013-04-29 21:32:19161 mock_dbus_thread_manager_ =
162 new chromeos::MockDBusThreadManagerWithoutGMock();
163 chromeos::DBusThreadManager::InitializeForTesting(
164 mock_dbus_thread_manager_);
165#endif // OS_CHROMEOS
166 }
167
[email protected]c006916b2013-02-20 19:30:35168 virtual void TearDown() OVERRIDE {
169 // Drain the blocking pool from PostTaskAndReply executed by
170 // MetrticsLog.network_observer_.
171 content::BrowserThread::GetBlockingPool()->FlushForTesting();
172 content::RunAllPendingInMessageLoop();
[email protected]611ae29a2013-04-29 21:32:19173
174#if defined(OS_CHROMEOS)
175 chromeos::DBusThreadManager::Shutdown();
176#endif // OS_CHROMEOS
[email protected]c006916b2013-02-20 19:30:35177 }
178
[email protected]f65859e2013-02-04 20:00:25179 private:
180 // This is necessary because eventually some tests call base::RepeatingTimer
181 // functions and a message loop is required for that.
[email protected]b3a25092013-05-28 22:08:16182 base::MessageLoop message_loop_;
[email protected]611ae29a2013-04-29 21:32:19183
184#if defined(OS_CHROMEOS)
185 chromeos::MockDBusThreadManagerWithoutGMock* mock_dbus_thread_manager_;
186#endif // OS_CHROMEOS
[email protected]fe58acc22012-02-29 01:29:58187};
initial.commit09911bf2008-07-26 23:55:29188
[email protected]767c9d92012-03-02 16:04:34189TEST_F(MetricsLogTest, RecordEnvironment) {
[email protected]bc66d532012-03-23 01:57:05190 // Test that recording the environment works via both of the public methods
191 // RecordEnvironment() and RecordEnvironmentProto().
192 TestRecordEnvironment(false);
193 TestRecordEnvironment(true);
[email protected]767c9d92012-03-02 16:04:34194}
195
[email protected]ed0fd002012-04-25 23:10:34196// Test that we properly write profiler data to the log.
197TEST_F(MetricsLogTest, RecordProfilerData) {
198 TestMetricsLog log(kClientId, kSessionId);
199 EXPECT_EQ(0, log.uma_proto().profiler_event_size());
200
201 {
202 ProcessDataSnapshot process_data;
203 process_data.process_id = 177;
204 process_data.tasks.push_back(TaskSnapshot());
205 process_data.tasks.back().birth.location.file_name = "file";
206 process_data.tasks.back().birth.location.function_name = "function";
207 process_data.tasks.back().birth.location.line_number = 1337;
208 process_data.tasks.back().birth.thread_name = "birth_thread";
209 process_data.tasks.back().death_data.count = 37;
210 process_data.tasks.back().death_data.run_duration_sum = 31;
211 process_data.tasks.back().death_data.run_duration_max = 17;
212 process_data.tasks.back().death_data.run_duration_sample = 13;
213 process_data.tasks.back().death_data.queue_duration_sum = 8;
214 process_data.tasks.back().death_data.queue_duration_max = 5;
215 process_data.tasks.back().death_data.queue_duration_sample = 3;
216 process_data.tasks.back().death_thread_name = "Still_Alive";
217 process_data.tasks.push_back(TaskSnapshot());
218 process_data.tasks.back().birth.location.file_name = "file2";
219 process_data.tasks.back().birth.location.function_name = "function2";
220 process_data.tasks.back().birth.location.line_number = 1773;
221 process_data.tasks.back().birth.thread_name = "birth_thread2";
222 process_data.tasks.back().death_data.count = 19;
223 process_data.tasks.back().death_data.run_duration_sum = 23;
224 process_data.tasks.back().death_data.run_duration_max = 11;
225 process_data.tasks.back().death_data.run_duration_sample = 7;
226 process_data.tasks.back().death_data.queue_duration_sum = 0;
227 process_data.tasks.back().death_data.queue_duration_max = 0;
228 process_data.tasks.back().death_data.queue_duration_sample = 0;
229 process_data.tasks.back().death_thread_name = "death_thread";
230
231 log.RecordProfilerData(process_data, content::PROCESS_TYPE_BROWSER);
232 ASSERT_EQ(1, log.uma_proto().profiler_event_size());
233 EXPECT_EQ(ProfilerEventProto::STARTUP_PROFILE,
234 log.uma_proto().profiler_event(0).profile_type());
235 EXPECT_EQ(ProfilerEventProto::WALL_CLOCK_TIME,
236 log.uma_proto().profiler_event(0).time_source());
237
238 ASSERT_EQ(2, log.uma_proto().profiler_event(0).tracked_object_size());
239
240 const ProfilerEventProto::TrackedObject* tracked_object =
241 &log.uma_proto().profiler_event(0).tracked_object(0);
[email protected]ed0fd002012-04-25 23:10:34242 EXPECT_EQ(GG_UINT64_C(10123486280357988687),
[email protected]04162262012-10-23 01:17:25243 tracked_object->source_file_name_hash());
244 EXPECT_EQ(GG_UINT64_C(13962325592283560029),
[email protected]ed0fd002012-04-25 23:10:34245 tracked_object->source_function_name_hash());
246 EXPECT_EQ(1337, tracked_object->source_line_number());
247 EXPECT_EQ(GG_UINT64_C(3400908935414830400),
248 tracked_object->birth_thread_name_hash());
249 EXPECT_EQ(37, tracked_object->exec_count());
250 EXPECT_EQ(31, tracked_object->exec_time_total());
251 EXPECT_EQ(13, tracked_object->exec_time_sampled());
252 EXPECT_EQ(8, tracked_object->queue_time_total());
253 EXPECT_EQ(3, tracked_object->queue_time_sampled());
254 EXPECT_EQ(GG_UINT64_C(10151977472163283085),
255 tracked_object->exec_thread_name_hash());
256 EXPECT_EQ(177U, tracked_object->process_id());
257 EXPECT_EQ(ProfilerEventProto::TrackedObject::BROWSER,
258 tracked_object->process_type());
259
260 tracked_object = &log.uma_proto().profiler_event(0).tracked_object(1);
[email protected]ed0fd002012-04-25 23:10:34261 EXPECT_EQ(GG_UINT64_C(2025659946535236365),
[email protected]04162262012-10-23 01:17:25262 tracked_object->source_file_name_hash());
263 EXPECT_EQ(GG_UINT64_C(55232426147951219),
[email protected]ed0fd002012-04-25 23:10:34264 tracked_object->source_function_name_hash());
265 EXPECT_EQ(1773, tracked_object->source_line_number());
266 EXPECT_EQ(GG_UINT64_C(15727396632046120663),
267 tracked_object->birth_thread_name_hash());
268 EXPECT_EQ(19, tracked_object->exec_count());
269 EXPECT_EQ(23, tracked_object->exec_time_total());
270 EXPECT_EQ(7, tracked_object->exec_time_sampled());
271 EXPECT_EQ(0, tracked_object->queue_time_total());
272 EXPECT_EQ(0, tracked_object->queue_time_sampled());
273 EXPECT_EQ(GG_UINT64_C(14275151213201158253),
274 tracked_object->exec_thread_name_hash());
275 EXPECT_EQ(177U, tracked_object->process_id());
276 EXPECT_EQ(ProfilerEventProto::TrackedObject::BROWSER,
277 tracked_object->process_type());
278 }
279
280 {
281 ProcessDataSnapshot process_data;
282 process_data.process_id = 1177;
283 process_data.tasks.push_back(TaskSnapshot());
284 process_data.tasks.back().birth.location.file_name = "file3";
285 process_data.tasks.back().birth.location.function_name = "function3";
286 process_data.tasks.back().birth.location.line_number = 7331;
287 process_data.tasks.back().birth.thread_name = "birth_thread3";
288 process_data.tasks.back().death_data.count = 137;
289 process_data.tasks.back().death_data.run_duration_sum = 131;
290 process_data.tasks.back().death_data.run_duration_max = 117;
291 process_data.tasks.back().death_data.run_duration_sample = 113;
292 process_data.tasks.back().death_data.queue_duration_sum = 108;
293 process_data.tasks.back().death_data.queue_duration_max = 105;
294 process_data.tasks.back().death_data.queue_duration_sample = 103;
295 process_data.tasks.back().death_thread_name = "death_thread3";
296
297 log.RecordProfilerData(process_data, content::PROCESS_TYPE_RENDERER);
298 ASSERT_EQ(1, log.uma_proto().profiler_event_size());
299 EXPECT_EQ(ProfilerEventProto::STARTUP_PROFILE,
300 log.uma_proto().profiler_event(0).profile_type());
301 EXPECT_EQ(ProfilerEventProto::WALL_CLOCK_TIME,
302 log.uma_proto().profiler_event(0).time_source());
303 ASSERT_EQ(3, log.uma_proto().profiler_event(0).tracked_object_size());
304
305 const ProfilerEventProto::TrackedObject* tracked_object =
306 &log.uma_proto().profiler_event(0).tracked_object(2);
[email protected]ed0fd002012-04-25 23:10:34307 EXPECT_EQ(GG_UINT64_C(2686523203278102732),
[email protected]04162262012-10-23 01:17:25308 tracked_object->source_file_name_hash());
309 EXPECT_EQ(GG_UINT64_C(5081672290546182009),
[email protected]ed0fd002012-04-25 23:10:34310 tracked_object->source_function_name_hash());
311 EXPECT_EQ(7331, tracked_object->source_line_number());
312 EXPECT_EQ(GG_UINT64_C(8768512930949373716),
313 tracked_object->birth_thread_name_hash());
314 EXPECT_EQ(137, tracked_object->exec_count());
315 EXPECT_EQ(131, tracked_object->exec_time_total());
316 EXPECT_EQ(113, tracked_object->exec_time_sampled());
317 EXPECT_EQ(108, tracked_object->queue_time_total());
318 EXPECT_EQ(103, tracked_object->queue_time_sampled());
319 EXPECT_EQ(GG_UINT64_C(7246674144371406371),
320 tracked_object->exec_thread_name_hash());
321 EXPECT_EQ(1177U, tracked_object->process_id());
322 EXPECT_EQ(ProfilerEventProto::TrackedObject::RENDERER,
323 tracked_object->process_type());
324 }
325}
326
[email protected]767c9d92012-03-02 16:04:34327#if defined(OS_CHROMEOS)
328TEST_F(MetricsLogTest, ChromeOSStabilityData) {
329 TestMetricsLog log(kClientId, kSessionId);
330
[email protected]c1834a92011-01-21 18:21:03331 // Expect 3 warnings about not yet being able to send the
332 // Chrome OS stability stats.
[email protected]767c9d92012-03-02 16:04:34333 std::vector<webkit::WebPluginInfo> plugins;
334 PrefService* prefs = log.GetPrefService();
335 log.WriteStabilityElement(plugins, prefs);
[email protected]c1834a92011-01-21 18:21:03336 log.CloseLog();
337
[email protected]fe58acc22012-02-29 01:29:58338 int size = log.GetEncodedLogSizeXml();
[email protected]c1834a92011-01-21 18:21:03339 ASSERT_GT(size, 0);
340
[email protected]767c9d92012-03-02 16:04:34341 EXPECT_EQ(0, prefs->GetInteger(prefs::kStabilityChildProcessCrashCount));
342 EXPECT_EQ(0, prefs->GetInteger(prefs::kStabilityOtherUserCrashCount));
343 EXPECT_EQ(0, prefs->GetInteger(prefs::kStabilityKernelCrashCount));
344 EXPECT_EQ(0, prefs->GetInteger(prefs::kStabilitySystemUncleanShutdownCount));
[email protected]c1834a92011-01-21 18:21:03345
346 std::string encoded;
347 // Leave room for the NUL terminator.
[email protected]fe58acc22012-02-29 01:29:58348 bool encoding_result = log.GetEncodedLogXml(
[email protected]c1834a92011-01-21 18:21:03349 WriteInto(&encoded, size + 1), size);
350 ASSERT_TRUE(encoding_result);
351
352 // Check that we can find childprocesscrashcount, but not
353 // any of the ChromeOS ones that we are not emitting until log
354 // servers can handle them.
355 EXPECT_NE(std::string::npos,
356 encoded.find(" childprocesscrashcount=\"10\""));
357 EXPECT_EQ(std::string::npos,
358 encoded.find(" otherusercrashcount="));
359 EXPECT_EQ(std::string::npos,
360 encoded.find(" kernelcrashcount="));
361 EXPECT_EQ(std::string::npos,
362 encoded.find(" systemuncleanshutdowns="));
363}
[email protected]4eb47992010-06-16 18:15:00364#endif // OS_CHROMEOS