Home | History | Annotate | Download | only in metrics
      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.
      4 
      5 #include <string>
      6 
      7 #include "base/basictypes.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "base/port.h"
     10 #include "base/prefs/pref_service.h"
     11 #include "base/prefs/testing_pref_service.h"
     12 #include "base/strings/string_number_conversions.h"
     13 #include "base/strings/string_util.h"
     14 #include "base/strings/stringprintf.h"
     15 #include "base/threading/sequenced_worker_pool.h"
     16 #include "base/time/time.h"
     17 #include "base/tracked_objects.h"
     18 #include "chrome/browser/google/google_util.h"
     19 #include "chrome/browser/metrics/metrics_log.h"
     20 #include "chrome/browser/prefs/browser_prefs.h"
     21 #include "chrome/common/metrics/proto/profiler_event.pb.h"
     22 #include "chrome/common/metrics/proto/system_profile.pb.h"
     23 #include "chrome/common/metrics/variations/variations_util.h"
     24 #include "chrome/common/pref_names.h"
     25 #include "chrome/installer/util/google_update_settings.h"
     26 #include "content/public/browser/browser_thread.h"
     27 #include "content/public/common/process_type.h"
     28 #include "content/public/common/webplugininfo.h"
     29 #include "content/public/test/test_utils.h"
     30 #include "testing/gtest/include/gtest/gtest.h"
     31 #include "ui/gfx/size.h"
     32 #include "url/gurl.h"
     33 
     34 #if defined(OS_CHROMEOS)
     35 #include "chromeos/dbus/mock_dbus_thread_manager_without_gmock.h"
     36 #endif  // OS_CHROMEOS
     37 
     38 using base::TimeDelta;
     39 using metrics::ProfilerEventProto;
     40 using tracked_objects::ProcessDataSnapshot;
     41 using tracked_objects::TaskSnapshot;
     42 
     43 namespace {
     44 
     45 const char kClientId[] = "bogus client ID";
     46 const int64 kInstallDate = 1373051956;
     47 const int64 kEnabledDate = 1373001211;
     48 const int kSessionId = 127;
     49 const int kScreenWidth = 1024;
     50 const int kScreenHeight = 768;
     51 const int kScreenCount = 3;
     52 const float kScreenScaleFactor = 2;
     53 const char kBrandForTesting[] = "brand_for_testing";
     54 const chrome_variations::ActiveGroupId kFieldTrialIds[] = {
     55   {37, 43},
     56   {13, 47},
     57   {23, 17}
     58 };
     59 
     60 class TestMetricsLog : public MetricsLog {
     61  public:
     62   TestMetricsLog(const std::string& client_id, int session_id)
     63       : MetricsLog(client_id, session_id),
     64         brand_for_testing_(kBrandForTesting) {
     65     chrome::RegisterLocalState(prefs_.registry());
     66 
     67     prefs_.SetInt64(prefs::kInstallDate, kInstallDate);
     68     prefs_.SetString(prefs::kMetricsClientIDTimestamp,
     69                      base::Int64ToString(kEnabledDate));
     70 #if defined(OS_CHROMEOS)
     71     prefs_.SetInteger(prefs::kStabilityChildProcessCrashCount, 10);
     72     prefs_.SetInteger(prefs::kStabilityOtherUserCrashCount, 11);
     73     prefs_.SetInteger(prefs::kStabilityKernelCrashCount, 12);
     74     prefs_.SetInteger(prefs::kStabilitySystemUncleanShutdownCount, 13);
     75 #endif  // OS_CHROMEOS
     76   }
     77   virtual ~TestMetricsLog() {}
     78 
     79   virtual PrefService* GetPrefService() OVERRIDE {
     80     return &prefs_;
     81   }
     82 
     83   const metrics::ChromeUserMetricsExtension& uma_proto() const {
     84     return *MetricsLog::uma_proto();
     85   }
     86 
     87   const metrics::SystemProfileProto& system_profile() const {
     88     return uma_proto().system_profile();
     89   }
     90 
     91  private:
     92   virtual void GetFieldTrialIds(
     93       std::vector<chrome_variations::ActiveGroupId>* field_trial_ids) const
     94       OVERRIDE {
     95     ASSERT_TRUE(field_trial_ids->empty());
     96 
     97     for (size_t i = 0; i < arraysize(kFieldTrialIds); ++i) {
     98       field_trial_ids->push_back(kFieldTrialIds[i]);
     99     }
    100   }
    101 
    102   virtual gfx::Size GetScreenSize() const OVERRIDE {
    103     return gfx::Size(kScreenWidth, kScreenHeight);
    104   }
    105 
    106   virtual float GetScreenDeviceScaleFactor() const OVERRIDE {
    107     return kScreenScaleFactor;
    108   }
    109 
    110   virtual int GetScreenCount() const OVERRIDE {
    111     return kScreenCount;
    112   }
    113 
    114   TestingPrefServiceSimple prefs_;
    115 
    116   google_util::BrandForTesting brand_for_testing_;
    117 
    118   DISALLOW_COPY_AND_ASSIGN(TestMetricsLog);
    119 };
    120 
    121 }  // namespace
    122 
    123 class MetricsLogTest : public testing::Test {
    124  public:
    125   MetricsLogTest() : message_loop_(base::MessageLoop::TYPE_IO) {}
    126 
    127  protected:
    128   void TestRecordEnvironment(bool proto_only) {
    129     TestMetricsLog log(kClientId, kSessionId);
    130 
    131     std::vector<content::WebPluginInfo> plugins;
    132     GoogleUpdateMetrics google_update_metrics;
    133     if (proto_only)
    134       log.RecordEnvironmentProto(plugins, google_update_metrics);
    135     else
    136       log.RecordEnvironment(plugins, google_update_metrics);
    137 
    138     // Computed from original time of 1373051956.
    139     EXPECT_EQ(1373050800, log.system_profile().install_date());
    140 
    141     // Computed from original time of 1373001211.
    142     EXPECT_EQ(1373000400, log.system_profile().uma_enabled_date());
    143 
    144     const metrics::SystemProfileProto& system_profile = log.system_profile();
    145     ASSERT_EQ(arraysize(kFieldTrialIds),
    146               static_cast<size_t>(system_profile.field_trial_size()));
    147     for (size_t i = 0; i < arraysize(kFieldTrialIds); ++i) {
    148       const metrics::SystemProfileProto::FieldTrial& field_trial =
    149           system_profile.field_trial(i);
    150       EXPECT_EQ(kFieldTrialIds[i].name, field_trial.name_id());
    151       EXPECT_EQ(kFieldTrialIds[i].group, field_trial.group_id());
    152     }
    153 
    154     EXPECT_EQ(kBrandForTesting, system_profile.brand_code());
    155 
    156     const metrics::SystemProfileProto::Hardware& hardware =
    157         system_profile.hardware();
    158     EXPECT_EQ(kScreenWidth, hardware.primary_screen_width());
    159     EXPECT_EQ(kScreenHeight, hardware.primary_screen_height());
    160     EXPECT_EQ(kScreenScaleFactor, hardware.primary_screen_scale_factor());
    161     EXPECT_EQ(kScreenCount, hardware.screen_count());
    162 
    163     EXPECT_TRUE(hardware.has_cpu());
    164     EXPECT_TRUE(hardware.cpu().has_vendor_name());
    165     EXPECT_TRUE(hardware.cpu().has_signature());
    166 
    167     // TODO(isherman): Verify other data written into the protobuf as a result
    168     // of this call.
    169   }
    170 
    171   virtual void SetUp() OVERRIDE {
    172 #if defined(OS_CHROMEOS)
    173     mock_dbus_thread_manager_ =
    174         new chromeos::MockDBusThreadManagerWithoutGMock();
    175     chromeos::DBusThreadManager::InitializeForTesting(
    176         mock_dbus_thread_manager_);
    177 #endif  // OS_CHROMEOS
    178   }
    179 
    180   virtual void TearDown() OVERRIDE {
    181     // Drain the blocking pool from PostTaskAndReply executed by
    182     // MetrticsLog.network_observer_.
    183     content::BrowserThread::GetBlockingPool()->FlushForTesting();
    184     content::RunAllPendingInMessageLoop();
    185 
    186 #if defined(OS_CHROMEOS)
    187     chromeos::DBusThreadManager::Shutdown();
    188 #endif  // OS_CHROMEOS
    189   }
    190 
    191  private:
    192   // This is necessary because eventually some tests call base::RepeatingTimer
    193   // functions and a message loop is required for that.
    194   base::MessageLoop message_loop_;
    195 
    196 #if defined(OS_CHROMEOS)
    197   chromeos::MockDBusThreadManagerWithoutGMock* mock_dbus_thread_manager_;
    198 #endif  // OS_CHROMEOS
    199 };
    200 
    201 TEST_F(MetricsLogTest, RecordEnvironment) {
    202   // Test that recording the environment works via both of the public methods
    203   // RecordEnvironment() and RecordEnvironmentProto().
    204   TestRecordEnvironment(false);
    205   TestRecordEnvironment(true);
    206 }
    207 
    208 // Test that we properly write profiler data to the log.
    209 TEST_F(MetricsLogTest, RecordProfilerData) {
    210   TestMetricsLog log(kClientId, kSessionId);
    211   EXPECT_EQ(0, log.uma_proto().profiler_event_size());
    212 
    213   {
    214     ProcessDataSnapshot process_data;
    215     process_data.process_id = 177;
    216     process_data.tasks.push_back(TaskSnapshot());
    217     process_data.tasks.back().birth.location.file_name = "file";
    218     process_data.tasks.back().birth.location.function_name = "function";
    219     process_data.tasks.back().birth.location.line_number = 1337;
    220     process_data.tasks.back().birth.thread_name = "birth_thread";
    221     process_data.tasks.back().death_data.count = 37;
    222     process_data.tasks.back().death_data.run_duration_sum = 31;
    223     process_data.tasks.back().death_data.run_duration_max = 17;
    224     process_data.tasks.back().death_data.run_duration_sample = 13;
    225     process_data.tasks.back().death_data.queue_duration_sum = 8;
    226     process_data.tasks.back().death_data.queue_duration_max = 5;
    227     process_data.tasks.back().death_data.queue_duration_sample = 3;
    228     process_data.tasks.back().death_thread_name = "Still_Alive";
    229     process_data.tasks.push_back(TaskSnapshot());
    230     process_data.tasks.back().birth.location.file_name = "file2";
    231     process_data.tasks.back().birth.location.function_name = "function2";
    232     process_data.tasks.back().birth.location.line_number = 1773;
    233     process_data.tasks.back().birth.thread_name = "birth_thread2";
    234     process_data.tasks.back().death_data.count = 19;
    235     process_data.tasks.back().death_data.run_duration_sum = 23;
    236     process_data.tasks.back().death_data.run_duration_max = 11;
    237     process_data.tasks.back().death_data.run_duration_sample = 7;
    238     process_data.tasks.back().death_data.queue_duration_sum = 0;
    239     process_data.tasks.back().death_data.queue_duration_max = 0;
    240     process_data.tasks.back().death_data.queue_duration_sample = 0;
    241     process_data.tasks.back().death_thread_name = "death_thread";
    242 
    243     log.RecordProfilerData(process_data, content::PROCESS_TYPE_BROWSER);
    244     ASSERT_EQ(1, log.uma_proto().profiler_event_size());
    245     EXPECT_EQ(ProfilerEventProto::STARTUP_PROFILE,
    246               log.uma_proto().profiler_event(0).profile_type());
    247     EXPECT_EQ(ProfilerEventProto::WALL_CLOCK_TIME,
    248               log.uma_proto().profiler_event(0).time_source());
    249 
    250     ASSERT_EQ(2, log.uma_proto().profiler_event(0).tracked_object_size());
    251 
    252     const ProfilerEventProto::TrackedObject* tracked_object =
    253         &log.uma_proto().profiler_event(0).tracked_object(0);
    254     EXPECT_EQ(GG_UINT64_C(10123486280357988687),
    255               tracked_object->source_file_name_hash());
    256     EXPECT_EQ(GG_UINT64_C(13962325592283560029),
    257               tracked_object->source_function_name_hash());
    258     EXPECT_EQ(1337, tracked_object->source_line_number());
    259     EXPECT_EQ(GG_UINT64_C(3400908935414830400),
    260               tracked_object->birth_thread_name_hash());
    261     EXPECT_EQ(37, tracked_object->exec_count());
    262     EXPECT_EQ(31, tracked_object->exec_time_total());
    263     EXPECT_EQ(13, tracked_object->exec_time_sampled());
    264     EXPECT_EQ(8, tracked_object->queue_time_total());
    265     EXPECT_EQ(3, tracked_object->queue_time_sampled());
    266     EXPECT_EQ(GG_UINT64_C(10151977472163283085),
    267               tracked_object->exec_thread_name_hash());
    268     EXPECT_EQ(177U, tracked_object->process_id());
    269     EXPECT_EQ(ProfilerEventProto::TrackedObject::BROWSER,
    270               tracked_object->process_type());
    271 
    272     tracked_object = &log.uma_proto().profiler_event(0).tracked_object(1);
    273     EXPECT_EQ(GG_UINT64_C(2025659946535236365),
    274               tracked_object->source_file_name_hash());
    275     EXPECT_EQ(GG_UINT64_C(55232426147951219),
    276               tracked_object->source_function_name_hash());
    277     EXPECT_EQ(1773, tracked_object->source_line_number());
    278     EXPECT_EQ(GG_UINT64_C(15727396632046120663),
    279               tracked_object->birth_thread_name_hash());
    280     EXPECT_EQ(19, tracked_object->exec_count());
    281     EXPECT_EQ(23, tracked_object->exec_time_total());
    282     EXPECT_EQ(7, tracked_object->exec_time_sampled());
    283     EXPECT_EQ(0, tracked_object->queue_time_total());
    284     EXPECT_EQ(0, tracked_object->queue_time_sampled());
    285     EXPECT_EQ(GG_UINT64_C(14275151213201158253),
    286               tracked_object->exec_thread_name_hash());
    287     EXPECT_EQ(177U, tracked_object->process_id());
    288     EXPECT_EQ(ProfilerEventProto::TrackedObject::BROWSER,
    289               tracked_object->process_type());
    290   }
    291 
    292   {
    293     ProcessDataSnapshot process_data;
    294     process_data.process_id = 1177;
    295     process_data.tasks.push_back(TaskSnapshot());
    296     process_data.tasks.back().birth.location.file_name = "file3";
    297     process_data.tasks.back().birth.location.function_name = "function3";
    298     process_data.tasks.back().birth.location.line_number = 7331;
    299     process_data.tasks.back().birth.thread_name = "birth_thread3";
    300     process_data.tasks.back().death_data.count = 137;
    301     process_data.tasks.back().death_data.run_duration_sum = 131;
    302     process_data.tasks.back().death_data.run_duration_max = 117;
    303     process_data.tasks.back().death_data.run_duration_sample = 113;
    304     process_data.tasks.back().death_data.queue_duration_sum = 108;
    305     process_data.tasks.back().death_data.queue_duration_max = 105;
    306     process_data.tasks.back().death_data.queue_duration_sample = 103;
    307     process_data.tasks.back().death_thread_name = "death_thread3";
    308 
    309     log.RecordProfilerData(process_data, content::PROCESS_TYPE_RENDERER);
    310     ASSERT_EQ(1, log.uma_proto().profiler_event_size());
    311     EXPECT_EQ(ProfilerEventProto::STARTUP_PROFILE,
    312               log.uma_proto().profiler_event(0).profile_type());
    313     EXPECT_EQ(ProfilerEventProto::WALL_CLOCK_TIME,
    314               log.uma_proto().profiler_event(0).time_source());
    315     ASSERT_EQ(3, log.uma_proto().profiler_event(0).tracked_object_size());
    316 
    317     const ProfilerEventProto::TrackedObject* tracked_object =
    318         &log.uma_proto().profiler_event(0).tracked_object(2);
    319     EXPECT_EQ(GG_UINT64_C(2686523203278102732),
    320               tracked_object->source_file_name_hash());
    321     EXPECT_EQ(GG_UINT64_C(5081672290546182009),
    322               tracked_object->source_function_name_hash());
    323     EXPECT_EQ(7331, tracked_object->source_line_number());
    324     EXPECT_EQ(GG_UINT64_C(8768512930949373716),
    325               tracked_object->birth_thread_name_hash());
    326     EXPECT_EQ(137, tracked_object->exec_count());
    327     EXPECT_EQ(131, tracked_object->exec_time_total());
    328     EXPECT_EQ(113, tracked_object->exec_time_sampled());
    329     EXPECT_EQ(108, tracked_object->queue_time_total());
    330     EXPECT_EQ(103, tracked_object->queue_time_sampled());
    331     EXPECT_EQ(GG_UINT64_C(7246674144371406371),
    332               tracked_object->exec_thread_name_hash());
    333     EXPECT_EQ(1177U, tracked_object->process_id());
    334     EXPECT_EQ(ProfilerEventProto::TrackedObject::RENDERER,
    335               tracked_object->process_type());
    336   }
    337 }
    338