Home | History | Annotate | Download | only in metrics_private
      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 <map>
      6 
      7 #include "base/metrics/field_trial.h"
      8 #include "base/metrics/histogram.h"
      9 #include "base/metrics/statistics_recorder.h"
     10 #include "chrome/browser/extensions/extension_apitest.h"
     11 #include "chrome/common/metrics/variations/variations_associated_data.h"
     12 #include "content/public/browser/user_metrics.h"
     13 
     14 namespace {
     15 
     16 // The tests that are run by this extension are expected to record the following
     17 // user actions, with the specified counts.  If the tests in test.js are
     18 // modified, this array may need to be updated.
     19 struct RecordedUserAction {
     20   const char* name;
     21   int count;  // number of times the metric was recorded.
     22 } g_user_actions[] = {
     23   {"test.ua.1", 1},
     24   {"test.ua.2", 2},
     25 };
     26 
     27 // The tests that are run by this extension are expected to record the following
     28 // histograms.  If the tests in test.js are modified, this array may need to be
     29 // updated.
     30 struct RecordedHistogram {
     31   const char* name;
     32   base::HistogramType type;
     33   int min;
     34   int max;
     35   size_t buckets;
     36 } g_histograms[] = {
     37   {"test.h.1", base::HISTOGRAM, 1, 100, 50},  // custom
     38   {"test.h.2", base::LINEAR_HISTOGRAM, 1, 200, 50},  // custom
     39   {"test.h.3", base::LINEAR_HISTOGRAM, 1, 101, 102},  // percentage
     40   {"test.time", base::HISTOGRAM, 1, 10000, 50},
     41   {"test.medium.time", base::HISTOGRAM, 1, 180000, 50},
     42   {"test.long.time", base::HISTOGRAM, 1, 3600000, 50},
     43   {"test.count", base::HISTOGRAM, 1, 1000000, 50},
     44   {"test.medium.count", base::HISTOGRAM, 1, 10000, 50},
     45   {"test.small.count", base::HISTOGRAM, 1, 100, 50},
     46 };
     47 
     48 // This class observes and collects user action notifications that are sent
     49 // by the tests, so that they can be examined afterwards for correctness.
     50 class UserActionObserver {
     51  public:
     52   UserActionObserver();
     53   ~UserActionObserver();
     54 
     55   void ValidateUserActions(const RecordedUserAction* recorded, int count);
     56 
     57  private:
     58   typedef std::map<std::string, int> UserActionCountMap;
     59 
     60   void OnUserAction(const std::string& action);
     61 
     62   int num_metrics() const {
     63     return count_map_.size();
     64   }
     65 
     66   int GetMetricCount(const std::string& name) const {
     67     UserActionCountMap::const_iterator i = count_map_.find(name);
     68     return i == count_map_.end() ? -1 : i->second;
     69   }
     70 
     71   UserActionCountMap count_map_;
     72 
     73   content::ActionCallback action_callback_;
     74 
     75   DISALLOW_COPY_AND_ASSIGN(UserActionObserver);
     76 };
     77 
     78 UserActionObserver::UserActionObserver()
     79     : action_callback_(base::Bind(&UserActionObserver::OnUserAction,
     80                                   base::Unretained(this))) {
     81   content::AddActionCallback(action_callback_);
     82 }
     83 
     84 UserActionObserver::~UserActionObserver() {
     85   content::RemoveActionCallback(action_callback_);
     86 }
     87 
     88 void UserActionObserver::OnUserAction(const std::string& action) {
     89   ++(count_map_[action]);
     90 }
     91 
     92 void UserActionObserver::ValidateUserActions(const RecordedUserAction* recorded,
     93                                              int count) {
     94   for (int i = 0; i < count; ++i) {
     95     const RecordedUserAction& ua = recorded[i];
     96     EXPECT_EQ(ua.count, GetMetricCount(ua.name));
     97   }
     98 }
     99 
    100 void ValidateHistograms(const RecordedHistogram* recorded,
    101                         int count) {
    102   base::StatisticsRecorder::Histograms histograms;
    103   base::StatisticsRecorder::GetHistograms(&histograms);
    104 
    105   // Code other than the tests tun here will record some histogram values, but
    106   // we will ignore those. This function validates that all the histogram we
    107   // expect to see are present in the list, and that their basic info is
    108   // correct.
    109   for (int i = 0; i < count; ++i) {
    110     const RecordedHistogram& r = recorded[i];
    111     size_t j = 0;
    112     for (j = 0; j < histograms.size(); ++j) {
    113       base::HistogramBase* histogram(histograms[j]);
    114 
    115       if (r.name == histogram->histogram_name()) {
    116         EXPECT_EQ(r.type, histogram->GetHistogramType());
    117         EXPECT_TRUE(
    118             histogram->HasConstructionArguments(r.min, r.max, r.buckets));
    119         break;
    120       }
    121     }
    122     EXPECT_LT(j, histograms.size());
    123   }
    124 }
    125 
    126 }  // anonymous namespace
    127 
    128 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Metrics) {
    129   UserActionObserver observer;
    130 
    131   base::FieldTrialList::CreateFieldTrial("apitestfieldtrial2", "group1");
    132 
    133   std::map<std::string, std::string> params;
    134   params["a"] = "aa";
    135   params["b"] = "bb";
    136   ASSERT_TRUE(chrome_variations::AssociateVariationParams(
    137       "apitestfieldtrial2", "group1", params));
    138 
    139   ASSERT_TRUE(RunComponentExtensionTest("metrics")) << message_;
    140 
    141   observer.ValidateUserActions(g_user_actions, arraysize(g_user_actions));
    142   ValidateHistograms(g_histograms, arraysize(g_histograms));
    143 }
    144