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