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/sample_vector.h"
10 #include "base/metrics/sparse_histogram.h"
11 #include "base/metrics/statistics_recorder.h"
12 #include "base/pickle.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 namespace base {
16
17 class HistogramBaseTest : public testing::Test {
18 protected:
HistogramBaseTest()19 HistogramBaseTest() {
20 // Each test will have a clean state (no Histogram / BucketRanges
21 // registered).
22 ResetStatisticsRecorder();
23 }
24
25 ~HistogramBaseTest() override = default;
26
ResetStatisticsRecorder()27 void ResetStatisticsRecorder() {
28 // It is necessary to fully destruct any existing StatisticsRecorder
29 // before creating a new one.
30 statistics_recorder_.reset();
31 statistics_recorder_ = StatisticsRecorder::CreateTemporaryForTesting();
32 }
33
34 private:
35 std::unique_ptr<StatisticsRecorder> statistics_recorder_;
36
37 DISALLOW_COPY_AND_ASSIGN(HistogramBaseTest);
38 };
39
TEST_F(HistogramBaseTest,DeserializeHistogram)40 TEST_F(HistogramBaseTest, DeserializeHistogram) {
41 HistogramBase* histogram = Histogram::FactoryGet(
42 "TestHistogram", 1, 1000, 10,
43 (HistogramBase::kUmaTargetedHistogramFlag |
44 HistogramBase::kIPCSerializationSourceFlag));
45
46 Pickle pickle;
47 histogram->SerializeInfo(&pickle);
48
49 PickleIterator iter(pickle);
50 HistogramBase* deserialized = DeserializeHistogramInfo(&iter);
51 EXPECT_EQ(histogram, deserialized);
52
53 ResetStatisticsRecorder();
54
55 PickleIterator iter2(pickle);
56 deserialized = DeserializeHistogramInfo(&iter2);
57 EXPECT_TRUE(deserialized);
58 EXPECT_NE(histogram, deserialized);
59 EXPECT_EQ("TestHistogram", StringPiece(deserialized->histogram_name()));
60 EXPECT_TRUE(deserialized->HasConstructionArguments(1, 1000, 10));
61
62 // kIPCSerializationSourceFlag will be cleared.
63 EXPECT_EQ(HistogramBase::kUmaTargetedHistogramFlag, deserialized->flags());
64 }
65
TEST_F(HistogramBaseTest,DeserializeLinearHistogram)66 TEST_F(HistogramBaseTest, DeserializeLinearHistogram) {
67 HistogramBase* histogram = LinearHistogram::FactoryGet(
68 "TestHistogram", 1, 1000, 10,
69 HistogramBase::kIPCSerializationSourceFlag);
70
71 Pickle pickle;
72 histogram->SerializeInfo(&pickle);
73
74 PickleIterator iter(pickle);
75 HistogramBase* deserialized = DeserializeHistogramInfo(&iter);
76 EXPECT_EQ(histogram, deserialized);
77
78 ResetStatisticsRecorder();
79
80 PickleIterator iter2(pickle);
81 deserialized = DeserializeHistogramInfo(&iter2);
82 EXPECT_TRUE(deserialized);
83 EXPECT_NE(histogram, deserialized);
84 EXPECT_EQ("TestHistogram", StringPiece(deserialized->histogram_name()));
85 EXPECT_TRUE(deserialized->HasConstructionArguments(1, 1000, 10));
86 EXPECT_EQ(0, deserialized->flags());
87 }
88
TEST_F(HistogramBaseTest,DeserializeBooleanHistogram)89 TEST_F(HistogramBaseTest, DeserializeBooleanHistogram) {
90 HistogramBase* histogram = BooleanHistogram::FactoryGet(
91 "TestHistogram", HistogramBase::kIPCSerializationSourceFlag);
92
93 Pickle pickle;
94 histogram->SerializeInfo(&pickle);
95
96 PickleIterator iter(pickle);
97 HistogramBase* deserialized = DeserializeHistogramInfo(&iter);
98 EXPECT_EQ(histogram, deserialized);
99
100 ResetStatisticsRecorder();
101
102 PickleIterator iter2(pickle);
103 deserialized = DeserializeHistogramInfo(&iter2);
104 EXPECT_TRUE(deserialized);
105 EXPECT_NE(histogram, deserialized);
106 EXPECT_EQ("TestHistogram", StringPiece(deserialized->histogram_name()));
107 EXPECT_TRUE(deserialized->HasConstructionArguments(1, 2, 3));
108 EXPECT_EQ(0, deserialized->flags());
109 }
110
TEST_F(HistogramBaseTest,DeserializeCustomHistogram)111 TEST_F(HistogramBaseTest, DeserializeCustomHistogram) {
112 std::vector<HistogramBase::Sample> ranges;
113 ranges.push_back(13);
114 ranges.push_back(5);
115 ranges.push_back(9);
116
117 HistogramBase* histogram = CustomHistogram::FactoryGet(
118 "TestHistogram", ranges, HistogramBase::kIPCSerializationSourceFlag);
119
120 Pickle pickle;
121 histogram->SerializeInfo(&pickle);
122
123 PickleIterator iter(pickle);
124 HistogramBase* deserialized = DeserializeHistogramInfo(&iter);
125 EXPECT_EQ(histogram, deserialized);
126
127 ResetStatisticsRecorder();
128
129 PickleIterator iter2(pickle);
130 deserialized = DeserializeHistogramInfo(&iter2);
131 EXPECT_TRUE(deserialized);
132 EXPECT_NE(histogram, deserialized);
133 EXPECT_EQ("TestHistogram", StringPiece(deserialized->histogram_name()));
134 EXPECT_TRUE(deserialized->HasConstructionArguments(5, 13, 4));
135 EXPECT_EQ(0, deserialized->flags());
136 }
137
TEST_F(HistogramBaseTest,DeserializeSparseHistogram)138 TEST_F(HistogramBaseTest, DeserializeSparseHistogram) {
139 HistogramBase* histogram = SparseHistogram::FactoryGet(
140 "TestHistogram", HistogramBase::kIPCSerializationSourceFlag);
141
142 Pickle pickle;
143 histogram->SerializeInfo(&pickle);
144
145 PickleIterator iter(pickle);
146 HistogramBase* deserialized = DeserializeHistogramInfo(&iter);
147 EXPECT_EQ(histogram, deserialized);
148
149 ResetStatisticsRecorder();
150
151 PickleIterator iter2(pickle);
152 deserialized = DeserializeHistogramInfo(&iter2);
153 EXPECT_TRUE(deserialized);
154 EXPECT_NE(histogram, deserialized);
155 EXPECT_EQ("TestHistogram", StringPiece(deserialized->histogram_name()));
156 EXPECT_EQ(0, deserialized->flags());
157 }
158
TEST_F(HistogramBaseTest,AddKilo)159 TEST_F(HistogramBaseTest, AddKilo) {
160 HistogramBase* histogram =
161 LinearHistogram::FactoryGet("TestAddKiloHistogram", 1, 1000, 100, 0);
162
163 histogram->AddKilo(100, 1000);
164 histogram->AddKilo(200, 2000);
165 histogram->AddKilo(300, 1500);
166
167 std::unique_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
168 EXPECT_EQ(1, samples->GetCount(100));
169 EXPECT_EQ(2, samples->GetCount(200));
170 EXPECT_LE(1, samples->GetCount(300));
171 EXPECT_GE(2, samples->GetCount(300));
172 }
173
TEST_F(HistogramBaseTest,AddKiB)174 TEST_F(HistogramBaseTest, AddKiB) {
175 HistogramBase* histogram =
176 LinearHistogram::FactoryGet("TestAddKiBHistogram", 1, 1000, 100, 0);
177
178 histogram->AddKiB(100, 1024);
179 histogram->AddKiB(200, 2048);
180 histogram->AddKiB(300, 1536);
181
182 std::unique_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
183 EXPECT_EQ(1, samples->GetCount(100));
184 EXPECT_EQ(2, samples->GetCount(200));
185 EXPECT_LE(1, samples->GetCount(300));
186 EXPECT_GE(2, samples->GetCount(300));
187 }
188
TEST_F(HistogramBaseTest,AddTimeMillisecondsGranularityOverflow)189 TEST_F(HistogramBaseTest, AddTimeMillisecondsGranularityOverflow) {
190 const HistogramBase::Sample sample_max =
191 std::numeric_limits<HistogramBase::Sample>::max() / 2;
192 HistogramBase* histogram = LinearHistogram::FactoryGet(
193 "TestAddTimeMillisecondsGranularity1", 1, sample_max, 100, 0);
194 int64_t large_positive = std::numeric_limits<int64_t>::max();
195 // |add_count| is the number of large values that have been added to the
196 // histogram. We consider a number to be 'large' if it cannot be represented
197 // in a HistogramBase::Sample.
198 int add_count = 0;
199 while (large_positive > std::numeric_limits<HistogramBase::Sample>::max()) {
200 // Add the TimeDelta corresponding to |large_positive| milliseconds to the
201 // histogram.
202 histogram->AddTimeMillisecondsGranularity(
203 TimeDelta::FromMilliseconds(large_positive));
204 ++add_count;
205 // Reduce the value of |large_positive|. The choice of 7 here is
206 // arbitrary.
207 large_positive /= 7;
208 }
209 std::unique_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
210 // All of the reported values must have gone into the max overflow bucket.
211 EXPECT_EQ(add_count, samples->GetCount(sample_max));
212
213 // We now perform the analoguous operations, now with negative values with a
214 // large absolute value.
215 histogram = LinearHistogram::FactoryGet("TestAddTimeMillisecondsGranularity2",
216 1, sample_max, 100, 0);
217 int64_t large_negative = std::numeric_limits<int64_t>::min();
218 add_count = 0;
219 while (large_negative < std::numeric_limits<HistogramBase::Sample>::min()) {
220 histogram->AddTimeMillisecondsGranularity(
221 TimeDelta::FromMilliseconds(large_negative));
222 ++add_count;
223 large_negative /= 7;
224 }
225 samples = histogram->SnapshotSamples();
226 // All of the reported values must have gone into the min overflow bucket.
227 EXPECT_EQ(add_count, samples->GetCount(0));
228 }
229
TEST_F(HistogramBaseTest,AddTimeMicrosecondsGranularityOverflow)230 TEST_F(HistogramBaseTest, AddTimeMicrosecondsGranularityOverflow) {
231 // Nothing to test if we don't have a high resolution clock.
232 if (!TimeTicks::IsHighResolution())
233 return;
234
235 const HistogramBase::Sample sample_max =
236 std::numeric_limits<HistogramBase::Sample>::max() / 2;
237 HistogramBase* histogram = LinearHistogram::FactoryGet(
238 "TestAddTimeMicrosecondsGranularity1", 1, sample_max, 100, 0);
239 int64_t large_positive = std::numeric_limits<int64_t>::max();
240 // |add_count| is the number of large values that have been added to the
241 // histogram. We consider a number to be 'large' if it cannot be represented
242 // in a HistogramBase::Sample.
243 int add_count = 0;
244 while (large_positive > std::numeric_limits<HistogramBase::Sample>::max()) {
245 // Add the TimeDelta corresponding to |large_positive| microseconds to the
246 // histogram.
247 histogram->AddTimeMicrosecondsGranularity(
248 TimeDelta::FromMicroseconds(large_positive));
249 ++add_count;
250 // Reduce the value of |large_positive|. The choice of 7 here is
251 // arbitrary.
252 large_positive /= 7;
253 }
254 std::unique_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
255 // All of the reported values must have gone into the max overflow bucket.
256 EXPECT_EQ(add_count, samples->GetCount(sample_max));
257
258 // We now perform the analoguous operations, now with negative values with a
259 // large absolute value.
260 histogram = LinearHistogram::FactoryGet("TestAddTimeMicrosecondsGranularity2",
261 1, sample_max, 100, 0);
262 int64_t large_negative = std::numeric_limits<int64_t>::min();
263 add_count = 0;
264 while (large_negative < std::numeric_limits<HistogramBase::Sample>::min()) {
265 histogram->AddTimeMicrosecondsGranularity(
266 TimeDelta::FromMicroseconds(large_negative));
267 ++add_count;
268 large_negative /= 7;
269 }
270 samples = histogram->SnapshotSamples();
271 // All of the reported values must have gone into the min overflow bucket.
272 EXPECT_EQ(add_count, samples->GetCount(0));
273 }
274
275 } // namespace base
276