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/metrics/histogram.h"
8#include "base/metrics/histogram_base.h"
9#include "base/metrics/sparse_histogram.h"
10#include "base/metrics/statistics_recorder.h"
11#include "base/pickle.h"
12#include "testing/gtest/include/gtest/gtest.h"
13
14namespace base {
15
16class HistogramBaseTest : public testing::Test {
17 protected:
18  HistogramBaseTest() {
19    // Each test will have a clean state (no Histogram / BucketRanges
20    // registered).
21    ResetStatisticsRecorder();
22  }
23
24  ~HistogramBaseTest() override {
25    HistogramBase::report_histogram_ = nullptr;
26  }
27
28  void ResetStatisticsRecorder() {
29    // It is necessary to fully destruct any existing StatisticsRecorder
30    // before creating a new one.
31    statistics_recorder_.reset();
32    statistics_recorder_ = StatisticsRecorder::CreateTemporaryForTesting();
33  }
34
35  HistogramBase* GetCreationReportHistogram(const std::string& name) {
36    HistogramBase::EnableActivityReportHistogram(name);
37    return HistogramBase::report_histogram_;
38  }
39
40 private:
41  std::unique_ptr<StatisticsRecorder> statistics_recorder_;
42
43  DISALLOW_COPY_AND_ASSIGN(HistogramBaseTest);
44};
45
46TEST_F(HistogramBaseTest, DeserializeHistogram) {
47  HistogramBase* histogram = Histogram::FactoryGet(
48      "TestHistogram", 1, 1000, 10,
49      (HistogramBase::kUmaTargetedHistogramFlag |
50      HistogramBase::kIPCSerializationSourceFlag));
51
52  Pickle pickle;
53  ASSERT_TRUE(histogram->SerializeInfo(&pickle));
54
55  PickleIterator iter(pickle);
56  HistogramBase* deserialized = DeserializeHistogramInfo(&iter);
57  EXPECT_EQ(histogram, deserialized);
58
59  ResetStatisticsRecorder();
60
61  PickleIterator iter2(pickle);
62  deserialized = DeserializeHistogramInfo(&iter2);
63  EXPECT_TRUE(deserialized);
64  EXPECT_NE(histogram, deserialized);
65  EXPECT_EQ("TestHistogram", deserialized->histogram_name());
66  EXPECT_TRUE(deserialized->HasConstructionArguments(1, 1000, 10));
67
68  // kIPCSerializationSourceFlag will be cleared.
69  EXPECT_EQ(HistogramBase::kUmaTargetedHistogramFlag, deserialized->flags());
70}
71
72TEST_F(HistogramBaseTest, DeserializeLinearHistogram) {
73  HistogramBase* histogram = LinearHistogram::FactoryGet(
74      "TestHistogram", 1, 1000, 10,
75      HistogramBase::kIPCSerializationSourceFlag);
76
77  Pickle pickle;
78  ASSERT_TRUE(histogram->SerializeInfo(&pickle));
79
80  PickleIterator iter(pickle);
81  HistogramBase* deserialized = DeserializeHistogramInfo(&iter);
82  EXPECT_EQ(histogram, deserialized);
83
84  ResetStatisticsRecorder();
85
86  PickleIterator iter2(pickle);
87  deserialized = DeserializeHistogramInfo(&iter2);
88  EXPECT_TRUE(deserialized);
89  EXPECT_NE(histogram, deserialized);
90  EXPECT_EQ("TestHistogram", deserialized->histogram_name());
91  EXPECT_TRUE(deserialized->HasConstructionArguments(1, 1000, 10));
92  EXPECT_EQ(0, deserialized->flags());
93}
94
95TEST_F(HistogramBaseTest, DeserializeBooleanHistogram) {
96  HistogramBase* histogram = BooleanHistogram::FactoryGet(
97      "TestHistogram", HistogramBase::kIPCSerializationSourceFlag);
98
99  Pickle pickle;
100  ASSERT_TRUE(histogram->SerializeInfo(&pickle));
101
102  PickleIterator iter(pickle);
103  HistogramBase* deserialized = DeserializeHistogramInfo(&iter);
104  EXPECT_EQ(histogram, deserialized);
105
106  ResetStatisticsRecorder();
107
108  PickleIterator iter2(pickle);
109  deserialized = DeserializeHistogramInfo(&iter2);
110  EXPECT_TRUE(deserialized);
111  EXPECT_NE(histogram, deserialized);
112  EXPECT_EQ("TestHistogram", deserialized->histogram_name());
113  EXPECT_TRUE(deserialized->HasConstructionArguments(1, 2, 3));
114  EXPECT_EQ(0, deserialized->flags());
115}
116
117TEST_F(HistogramBaseTest, DeserializeCustomHistogram) {
118  std::vector<HistogramBase::Sample> ranges;
119  ranges.push_back(13);
120  ranges.push_back(5);
121  ranges.push_back(9);
122
123  HistogramBase* histogram = CustomHistogram::FactoryGet(
124      "TestHistogram", ranges, HistogramBase::kIPCSerializationSourceFlag);
125
126  Pickle pickle;
127  ASSERT_TRUE(histogram->SerializeInfo(&pickle));
128
129  PickleIterator iter(pickle);
130  HistogramBase* deserialized = DeserializeHistogramInfo(&iter);
131  EXPECT_EQ(histogram, deserialized);
132
133  ResetStatisticsRecorder();
134
135  PickleIterator iter2(pickle);
136  deserialized = DeserializeHistogramInfo(&iter2);
137  EXPECT_TRUE(deserialized);
138  EXPECT_NE(histogram, deserialized);
139  EXPECT_EQ("TestHistogram", deserialized->histogram_name());
140  EXPECT_TRUE(deserialized->HasConstructionArguments(5, 13, 4));
141  EXPECT_EQ(0, deserialized->flags());
142}
143
144TEST_F(HistogramBaseTest, DeserializeSparseHistogram) {
145  HistogramBase* histogram = SparseHistogram::FactoryGet(
146      "TestHistogram", HistogramBase::kIPCSerializationSourceFlag);
147
148  Pickle pickle;
149  ASSERT_TRUE(histogram->SerializeInfo(&pickle));
150
151  PickleIterator iter(pickle);
152  HistogramBase* deserialized = DeserializeHistogramInfo(&iter);
153  EXPECT_EQ(histogram, deserialized);
154
155  ResetStatisticsRecorder();
156
157  PickleIterator iter2(pickle);
158  deserialized = DeserializeHistogramInfo(&iter2);
159  EXPECT_TRUE(deserialized);
160  EXPECT_NE(histogram, deserialized);
161  EXPECT_EQ("TestHistogram", deserialized->histogram_name());
162  EXPECT_EQ(0, deserialized->flags());
163}
164
165TEST_F(HistogramBaseTest, CreationReportHistogram) {
166  // Enabled creation report. Itself is not included in the report.
167  HistogramBase* report = GetCreationReportHistogram("CreationReportTest");
168  ASSERT_TRUE(report);
169
170  std::vector<HistogramBase::Sample> ranges;
171  ranges.push_back(1);
172  ranges.push_back(2);
173  ranges.push_back(4);
174  ranges.push_back(8);
175  ranges.push_back(10);
176
177  // Create all histogram types and verify counts.
178  Histogram::FactoryGet("CRH-Histogram", 1, 10, 5, 0);
179  LinearHistogram::FactoryGet("CRH-Linear", 1, 10, 5, 0);
180  BooleanHistogram::FactoryGet("CRH-Boolean", 0);
181  CustomHistogram::FactoryGet("CRH-Custom", ranges, 0);
182  SparseHistogram::FactoryGet("CRH-Sparse", 0);
183
184  std::unique_ptr<HistogramSamples> samples = report->SnapshotSamples();
185  EXPECT_EQ(1, samples->GetCount(HISTOGRAM_REPORT_CREATED));
186  EXPECT_EQ(5, samples->GetCount(HISTOGRAM_REPORT_HISTOGRAM_CREATED));
187  EXPECT_EQ(0, samples->GetCount(HISTOGRAM_REPORT_HISTOGRAM_LOOKUP));
188  EXPECT_EQ(1, samples->GetCount(HISTOGRAM_REPORT_TYPE_LOGARITHMIC));
189  EXPECT_EQ(1, samples->GetCount(HISTOGRAM_REPORT_TYPE_LINEAR));
190  EXPECT_EQ(1, samples->GetCount(HISTOGRAM_REPORT_TYPE_BOOLEAN));
191  EXPECT_EQ(1, samples->GetCount(HISTOGRAM_REPORT_TYPE_CUSTOM));
192  EXPECT_EQ(1, samples->GetCount(HISTOGRAM_REPORT_TYPE_SPARSE));
193
194  // Create all flag types and verify counts.
195  Histogram::FactoryGet("CRH-Histogram-UMA-Targeted", 1, 10, 5,
196                        HistogramBase::kUmaTargetedHistogramFlag);
197  Histogram::FactoryGet("CRH-Histogram-UMA-Stability", 1, 10, 5,
198                        HistogramBase::kUmaStabilityHistogramFlag);
199  SparseHistogram::FactoryGet("CRH-Sparse-UMA-Targeted",
200                              HistogramBase::kUmaTargetedHistogramFlag);
201  SparseHistogram::FactoryGet("CRH-Sparse-UMA-Stability",
202                              HistogramBase::kUmaStabilityHistogramFlag);
203  samples = report->SnapshotSamples();
204  EXPECT_EQ(1, samples->GetCount(HISTOGRAM_REPORT_CREATED));
205  EXPECT_EQ(9, samples->GetCount(HISTOGRAM_REPORT_HISTOGRAM_CREATED));
206  EXPECT_EQ(0, samples->GetCount(HISTOGRAM_REPORT_HISTOGRAM_LOOKUP));
207  EXPECT_EQ(2, samples->GetCount(HISTOGRAM_REPORT_FLAG_UMA_TARGETED));
208  EXPECT_EQ(2, samples->GetCount(HISTOGRAM_REPORT_FLAG_UMA_STABILITY));
209
210  // Do lookup of existing histograms and verify counts.
211  Histogram::FactoryGet("CRH-Histogram", 1, 10, 5, 0);
212  LinearHistogram::FactoryGet("CRH-Linear", 1, 10, 5, 0);
213  BooleanHistogram::FactoryGet("CRH-Boolean", 0);
214  CustomHistogram::FactoryGet("CRH-Custom", ranges, 0);
215  SparseHistogram::FactoryGet("CRH-Sparse", 0);
216  samples = report->SnapshotSamples();
217  EXPECT_EQ(1, samples->GetCount(HISTOGRAM_REPORT_CREATED));
218  EXPECT_EQ(9, samples->GetCount(HISTOGRAM_REPORT_HISTOGRAM_CREATED));
219  EXPECT_EQ(5, samples->GetCount(HISTOGRAM_REPORT_HISTOGRAM_LOOKUP));
220}
221
222}  // namespace base
223