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