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 <vector>
6
7#include "base/json/json_reader.h"
8#include "base/memory/scoped_ptr.h"
9#include "base/metrics/histogram.h"
10#include "base/metrics/statistics_recorder.h"
11#include "base/values.h"
12#include "testing/gtest/include/gtest/gtest.h"
13
14namespace base {
15
16class StatisticsRecorderTest : public testing::Test {
17 protected:
18  virtual void SetUp() {
19    // Each test will have a clean state (no Histogram / BucketRanges
20    // registered).
21    InitializeStatisticsRecorder();
22  }
23
24  virtual void TearDown() {
25    UninitializeStatisticsRecorder();
26  }
27
28  void InitializeStatisticsRecorder() {
29    statistics_recorder_ = new StatisticsRecorder();
30  }
31
32  void UninitializeStatisticsRecorder() {
33    delete statistics_recorder_;
34    statistics_recorder_ = NULL;
35  }
36
37  Histogram* CreateHistogram(const std::string& name,
38                             HistogramBase::Sample min,
39                             HistogramBase::Sample max,
40                             size_t bucket_count) {
41    BucketRanges* ranges = new BucketRanges(bucket_count + 1);
42    Histogram::InitializeBucketRanges(min, max, ranges);
43    const BucketRanges* registered_ranges =
44        StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges);
45    return new Histogram(name, min, max, registered_ranges);
46  }
47
48  void DeleteHistogram(HistogramBase* histogram) {
49    delete histogram;
50  }
51
52  StatisticsRecorder* statistics_recorder_;
53};
54
55TEST_F(StatisticsRecorderTest, NotInitialized) {
56  UninitializeStatisticsRecorder();
57
58  ASSERT_FALSE(StatisticsRecorder::IsActive());
59
60  StatisticsRecorder::Histograms registered_histograms;
61  std::vector<const BucketRanges*> registered_ranges;
62
63  StatisticsRecorder::GetHistograms(&registered_histograms);
64  EXPECT_EQ(0u, registered_histograms.size());
65
66  Histogram* histogram = CreateHistogram("TestHistogram", 1, 1000, 10);
67
68  // When StatisticsRecorder is not initialized, register is a noop.
69  EXPECT_EQ(histogram,
70            StatisticsRecorder::RegisterOrDeleteDuplicate(histogram));
71  // Manually delete histogram that was not registered.
72  DeleteHistogram(histogram);
73
74  // RegisterOrDeleteDuplicateRanges is a no-op.
75  BucketRanges* ranges = new BucketRanges(3);;
76  ranges->ResetChecksum();
77  EXPECT_EQ(ranges,
78            StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges));
79  StatisticsRecorder::GetBucketRanges(&registered_ranges);
80  EXPECT_EQ(0u, registered_ranges.size());
81}
82
83TEST_F(StatisticsRecorderTest, RegisterBucketRanges) {
84  std::vector<const BucketRanges*> registered_ranges;
85
86  BucketRanges* ranges1 = new BucketRanges(3);;
87  ranges1->ResetChecksum();
88  BucketRanges* ranges2 = new BucketRanges(4);;
89  ranges2->ResetChecksum();
90
91  // Register new ranges.
92  EXPECT_EQ(ranges1,
93            StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges1));
94  EXPECT_EQ(ranges2,
95            StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges2));
96  StatisticsRecorder::GetBucketRanges(&registered_ranges);
97  ASSERT_EQ(2u, registered_ranges.size());
98
99  // Register some ranges again.
100  EXPECT_EQ(ranges1,
101            StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges1));
102  registered_ranges.clear();
103  StatisticsRecorder::GetBucketRanges(&registered_ranges);
104  ASSERT_EQ(2u, registered_ranges.size());
105  // Make sure the ranges is still the one we know.
106  ASSERT_EQ(3u, ranges1->size());
107  EXPECT_EQ(0, ranges1->range(0));
108  EXPECT_EQ(0, ranges1->range(1));
109  EXPECT_EQ(0, ranges1->range(2));
110
111  // Register ranges with same values.
112  BucketRanges* ranges3 = new BucketRanges(3);;
113  ranges3->ResetChecksum();
114  EXPECT_EQ(ranges1,  // returning ranges1
115            StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges3));
116  registered_ranges.clear();
117  StatisticsRecorder::GetBucketRanges(&registered_ranges);
118  ASSERT_EQ(2u, registered_ranges.size());
119}
120
121TEST_F(StatisticsRecorderTest, RegisterHistogram) {
122  // Create a Histogram that was not registered.
123  Histogram* histogram = CreateHistogram("TestHistogram", 1, 1000, 10);
124
125  StatisticsRecorder::Histograms registered_histograms;
126  StatisticsRecorder::GetHistograms(&registered_histograms);
127  EXPECT_EQ(0u, registered_histograms.size());
128
129  // Register the Histogram.
130  EXPECT_EQ(histogram,
131            StatisticsRecorder::RegisterOrDeleteDuplicate(histogram));
132  StatisticsRecorder::GetHistograms(&registered_histograms);
133  EXPECT_EQ(1u, registered_histograms.size());
134
135  // Register the same Histogram again.
136  EXPECT_EQ(histogram,
137            StatisticsRecorder::RegisterOrDeleteDuplicate(histogram));
138  registered_histograms.clear();
139  StatisticsRecorder::GetHistograms(&registered_histograms);
140  EXPECT_EQ(1u, registered_histograms.size());
141}
142
143TEST_F(StatisticsRecorderTest, FindHistogram) {
144  HistogramBase* histogram1 = Histogram::FactoryGet(
145      "TestHistogram1", 1, 1000, 10, HistogramBase::kNoFlags);
146  HistogramBase* histogram2 = Histogram::FactoryGet(
147      "TestHistogram2", 1, 1000, 10, HistogramBase::kNoFlags);
148
149  EXPECT_EQ(histogram1, StatisticsRecorder::FindHistogram("TestHistogram1"));
150  EXPECT_EQ(histogram2, StatisticsRecorder::FindHistogram("TestHistogram2"));
151  EXPECT_TRUE(StatisticsRecorder::FindHistogram("TestHistogram") == NULL);
152}
153
154TEST_F(StatisticsRecorderTest, GetSnapshot) {
155  Histogram::FactoryGet("TestHistogram1", 1, 1000, 10, Histogram::kNoFlags);
156  Histogram::FactoryGet("TestHistogram2", 1, 1000, 10, Histogram::kNoFlags);
157  Histogram::FactoryGet("TestHistogram3", 1, 1000, 10, Histogram::kNoFlags);
158
159  StatisticsRecorder::Histograms snapshot;
160  StatisticsRecorder::GetSnapshot("Test", &snapshot);
161  EXPECT_EQ(3u, snapshot.size());
162
163  snapshot.clear();
164  StatisticsRecorder::GetSnapshot("1", &snapshot);
165  EXPECT_EQ(1u, snapshot.size());
166
167  snapshot.clear();
168  StatisticsRecorder::GetSnapshot("hello", &snapshot);
169  EXPECT_EQ(0u, snapshot.size());
170}
171
172TEST_F(StatisticsRecorderTest, RegisterHistogramWithFactoryGet) {
173  StatisticsRecorder::Histograms registered_histograms;
174
175  StatisticsRecorder::GetHistograms(&registered_histograms);
176  ASSERT_EQ(0u, registered_histograms.size());
177
178  // Create a histogram.
179  HistogramBase* histogram = Histogram::FactoryGet(
180      "TestHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
181  registered_histograms.clear();
182  StatisticsRecorder::GetHistograms(&registered_histograms);
183  EXPECT_EQ(1u, registered_histograms.size());
184
185  // Get an existing histogram.
186  HistogramBase* histogram2 = Histogram::FactoryGet(
187      "TestHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
188  registered_histograms.clear();
189  StatisticsRecorder::GetHistograms(&registered_histograms);
190  EXPECT_EQ(1u, registered_histograms.size());
191  EXPECT_EQ(histogram, histogram2);
192
193  // Create a LinearHistogram.
194  histogram = LinearHistogram::FactoryGet(
195      "TestLinearHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
196  registered_histograms.clear();
197  StatisticsRecorder::GetHistograms(&registered_histograms);
198  EXPECT_EQ(2u, registered_histograms.size());
199
200  // Create a BooleanHistogram.
201  histogram = BooleanHistogram::FactoryGet(
202      "TestBooleanHistogram", HistogramBase::kNoFlags);
203  registered_histograms.clear();
204  StatisticsRecorder::GetHistograms(&registered_histograms);
205  EXPECT_EQ(3u, registered_histograms.size());
206
207  // Create a CustomHistogram.
208  std::vector<int> custom_ranges;
209  custom_ranges.push_back(1);
210  custom_ranges.push_back(5);
211  histogram = CustomHistogram::FactoryGet(
212      "TestCustomHistogram", custom_ranges, HistogramBase::kNoFlags);
213  registered_histograms.clear();
214  StatisticsRecorder::GetHistograms(&registered_histograms);
215  EXPECT_EQ(4u, registered_histograms.size());
216}
217
218TEST_F(StatisticsRecorderTest, RegisterHistogramWithMacros) {
219  StatisticsRecorder::Histograms registered_histograms;
220
221  HistogramBase* histogram = Histogram::FactoryGet(
222      "TestHistogramCounts", 1, 1000000, 50, HistogramBase::kNoFlags);
223
224  // The histogram we got from macro is the same as from FactoryGet.
225  LOCAL_HISTOGRAM_COUNTS("TestHistogramCounts", 30);
226  registered_histograms.clear();
227  StatisticsRecorder::GetHistograms(&registered_histograms);
228  ASSERT_EQ(1u, registered_histograms.size());
229  EXPECT_EQ(histogram, registered_histograms[0]);
230
231  LOCAL_HISTOGRAM_TIMES("TestHistogramTimes", TimeDelta::FromDays(1));
232  LOCAL_HISTOGRAM_ENUMERATION("TestHistogramEnumeration", 20, 200);
233
234  registered_histograms.clear();
235  StatisticsRecorder::GetHistograms(&registered_histograms);
236  EXPECT_EQ(3u, registered_histograms.size());
237}
238
239TEST_F(StatisticsRecorderTest, BucketRangesSharing) {
240  std::vector<const BucketRanges*> ranges;
241  StatisticsRecorder::GetBucketRanges(&ranges);
242  EXPECT_EQ(0u, ranges.size());
243
244  Histogram::FactoryGet("Histogram", 1, 64, 8, HistogramBase::kNoFlags);
245  Histogram::FactoryGet("Histogram2", 1, 64, 8, HistogramBase::kNoFlags);
246
247  StatisticsRecorder::GetBucketRanges(&ranges);
248  EXPECT_EQ(1u, ranges.size());
249
250  Histogram::FactoryGet("Histogram3", 1, 64, 16, HistogramBase::kNoFlags);
251
252  ranges.clear();
253  StatisticsRecorder::GetBucketRanges(&ranges);
254  EXPECT_EQ(2u, ranges.size());
255}
256
257TEST_F(StatisticsRecorderTest, ToJSON) {
258  LOCAL_HISTOGRAM_COUNTS("TestHistogram1", 30);
259  LOCAL_HISTOGRAM_COUNTS("TestHistogram1", 40);
260  LOCAL_HISTOGRAM_COUNTS("TestHistogram2", 30);
261  LOCAL_HISTOGRAM_COUNTS("TestHistogram2", 40);
262
263  std::string json(StatisticsRecorder::ToJSON(std::string()));
264
265  // Check for valid JSON.
266  scoped_ptr<Value> root;
267  root.reset(JSONReader::Read(json));
268  ASSERT_TRUE(root.get());
269
270  DictionaryValue* root_dict = NULL;
271  ASSERT_TRUE(root->GetAsDictionary(&root_dict));
272
273  // No query should be set.
274  ASSERT_FALSE(root_dict->HasKey("query"));
275
276  ListValue* histogram_list = NULL;
277  ASSERT_TRUE(root_dict->GetList("histograms", &histogram_list));
278  ASSERT_EQ(2u, histogram_list->GetSize());
279
280  // Examine the first histogram.
281  DictionaryValue* histogram_dict = NULL;
282  ASSERT_TRUE(histogram_list->GetDictionary(0, &histogram_dict));
283
284  int sample_count;
285  ASSERT_TRUE(histogram_dict->GetInteger("count", &sample_count));
286  EXPECT_EQ(2, sample_count);
287
288  // Test the query filter.
289  std::string query("TestHistogram2");
290  json = StatisticsRecorder::ToJSON(query);
291
292  root.reset(JSONReader::Read(json));
293  ASSERT_TRUE(root.get());
294  ASSERT_TRUE(root->GetAsDictionary(&root_dict));
295
296  std::string query_value;
297  ASSERT_TRUE(root_dict->GetString("query", &query_value));
298  EXPECT_EQ(query, query_value);
299
300  ASSERT_TRUE(root_dict->GetList("histograms", &histogram_list));
301  ASSERT_EQ(1u, histogram_list->GetSize());
302
303  ASSERT_TRUE(histogram_list->GetDictionary(0, &histogram_dict));
304
305  std::string histogram_name;
306  ASSERT_TRUE(histogram_dict->GetString("name", &histogram_name));
307  EXPECT_EQ("TestHistogram2", histogram_name);
308
309  json.clear();
310  UninitializeStatisticsRecorder();
311
312  // No data should be returned.
313  json = StatisticsRecorder::ToJSON(query);
314  EXPECT_TRUE(json.empty());
315}
316
317}  // namespace base
318