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
14namespace {
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.
19struct 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.
30struct 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.
50class 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
78UserActionObserver::UserActionObserver()
79    : action_callback_(base::Bind(&UserActionObserver::OnUserAction,
80                                  base::Unretained(this))) {
81  content::AddActionCallback(action_callback_);
82}
83
84UserActionObserver::~UserActionObserver() {
85  content::RemoveActionCallback(action_callback_);
86}
87
88void UserActionObserver::OnUserAction(const std::string& action) {
89  ++(count_map_[action]);
90}
91
92void 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
100void 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
128IN_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