1 // Copyright 2014 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/test/metrics/histogram_tester.h"
6
7 #include <memory>
8 #include <string>
9
10 #include "base/metrics/histogram_macros.h"
11 #include "base/metrics/histogram_samples.h"
12 #include "testing/gmock/include/gmock/gmock.h"
13 #include "testing/gtest/include/gtest/gtest-spi.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 using ::testing::ElementsAre;
17 using ::testing::IsEmpty;
18
19 namespace {
20
21 const char kHistogram1[] = "Test1";
22 const char kHistogram2[] = "Test2";
23 const char kHistogram3[] = "Test3";
24 const char kHistogram4[] = "Test4";
25 const char kHistogram5[] = "Test5";
26 const char kHistogram6[] = "Test6";
27
28 } // namespace
29
30 namespace base {
31
32 typedef testing::Test HistogramTesterTest;
33
TEST_F(HistogramTesterTest,Scope)34 TEST_F(HistogramTesterTest, Scope) {
35 // Record a histogram before the creation of the recorder.
36 UMA_HISTOGRAM_BOOLEAN(kHistogram1, true);
37
38 HistogramTester tester;
39
40 // Verify that no histogram is recorded.
41 tester.ExpectTotalCount(kHistogram1, 0);
42
43 // Record a histogram after the creation of the recorder.
44 UMA_HISTOGRAM_BOOLEAN(kHistogram1, true);
45
46 // Verify that one histogram is recorded.
47 std::unique_ptr<HistogramSamples> samples(
48 tester.GetHistogramSamplesSinceCreation(kHistogram1));
49 EXPECT_TRUE(samples);
50 EXPECT_EQ(1, samples->TotalCount());
51 }
52
TEST_F(HistogramTesterTest,GetHistogramSamplesSinceCreationNotNull)53 TEST_F(HistogramTesterTest, GetHistogramSamplesSinceCreationNotNull) {
54 // Chose the histogram name uniquely, to ensure nothing was recorded for it so
55 // far.
56 static const char kHistogram[] =
57 "GetHistogramSamplesSinceCreationNotNullHistogram";
58 HistogramTester tester;
59
60 // Verify that the returned samples are empty but not null.
61 std::unique_ptr<HistogramSamples> samples(
62 tester.GetHistogramSamplesSinceCreation(kHistogram1));
63 EXPECT_TRUE(samples);
64 tester.ExpectTotalCount(kHistogram, 0);
65 }
66
TEST_F(HistogramTesterTest,TestUniqueSample)67 TEST_F(HistogramTesterTest, TestUniqueSample) {
68 HistogramTester tester;
69
70 // Emit '2' three times.
71 UMA_HISTOGRAM_COUNTS_100(kHistogram2, 2);
72 UMA_HISTOGRAM_COUNTS_100(kHistogram2, 2);
73 UMA_HISTOGRAM_COUNTS_100(kHistogram2, 2);
74
75 tester.ExpectUniqueSample(kHistogram2, 2, 3);
76 tester.ExpectUniqueTimeSample(kHistogram2, base::Milliseconds(2), 3);
77 }
78
79 // Verify that the expectation is violated if the bucket contains an incorrect
80 // number of samples.
TEST_F(HistogramTesterTest,TestUniqueSample_TooManySamplesInActualBucket)81 TEST_F(HistogramTesterTest, TestUniqueSample_TooManySamplesInActualBucket) {
82 auto failing_code = [] {
83 HistogramTester tester;
84
85 // Emit '2' four times.
86 UMA_HISTOGRAM_COUNTS_100(kHistogram2, 2);
87 UMA_HISTOGRAM_COUNTS_100(kHistogram2, 2);
88 UMA_HISTOGRAM_COUNTS_100(kHistogram2, 2);
89 UMA_HISTOGRAM_COUNTS_100(kHistogram2, 2);
90
91 // Expect exactly three samples in bucket 2. This is supposed to fail.
92 tester.ExpectUniqueSample(kHistogram2, 2, 3);
93 };
94 EXPECT_NONFATAL_FAILURE(failing_code(),
95 "Histogram \"Test2\" did not meet its expectations.");
96 }
97
98 // Verify that the expectation is violated if the bucket contains the correct
99 // number of samples but another bucket contains extra samples.
TEST_F(HistogramTesterTest,TestUniqueSample_OneExtraSampleInWrongBucket)100 TEST_F(HistogramTesterTest, TestUniqueSample_OneExtraSampleInWrongBucket) {
101 auto failing_code = [] {
102 HistogramTester tester;
103
104 // Emit '2' three times.
105 UMA_HISTOGRAM_COUNTS_100(kHistogram2, 2);
106 UMA_HISTOGRAM_COUNTS_100(kHistogram2, 2);
107 UMA_HISTOGRAM_COUNTS_100(kHistogram2, 2);
108 // Emit one unexpected '3'.
109 UMA_HISTOGRAM_COUNTS_100(kHistogram2, 3);
110
111 // Expect exactly three samples in bucket 2. This is supposed to fail.
112 tester.ExpectUniqueSample(kHistogram2, 2, 3);
113 };
114 EXPECT_NONFATAL_FAILURE(failing_code(),
115 "Histogram \"Test2\" did not meet its expectations.");
116 }
117
TEST_F(HistogramTesterTest,TestBucketsSample)118 TEST_F(HistogramTesterTest, TestBucketsSample) {
119 HistogramTester tester;
120
121 UMA_HISTOGRAM_COUNTS_100(kHistogram3, 2);
122 UMA_HISTOGRAM_COUNTS_100(kHistogram3, 2);
123 UMA_HISTOGRAM_COUNTS_100(kHistogram3, 2);
124 UMA_HISTOGRAM_COUNTS_100(kHistogram3, 2);
125 UMA_HISTOGRAM_COUNTS_100(kHistogram3, 3);
126
127 tester.ExpectBucketCount(kHistogram3, 2, 4);
128 tester.ExpectBucketCount(kHistogram3, 3, 1);
129
130 tester.ExpectTotalCount(kHistogram3, 5);
131 }
132
TEST_F(HistogramTesterTest,TestBucketsSampleWithScope)133 TEST_F(HistogramTesterTest, TestBucketsSampleWithScope) {
134 // Emit values twice, once before the tester creation and once after.
135 UMA_HISTOGRAM_COUNTS_100(kHistogram4, 2);
136
137 HistogramTester tester;
138 UMA_HISTOGRAM_COUNTS_100(kHistogram4, 3);
139
140 tester.ExpectBucketCount(kHistogram4, 2, 0);
141 tester.ExpectBucketCount(kHistogram4, 3, 1);
142
143 tester.ExpectTotalCount(kHistogram4, 1);
144 }
145
TEST_F(HistogramTesterTest,TestGetAllSamples)146 TEST_F(HistogramTesterTest, TestGetAllSamples) {
147 HistogramTester tester;
148 UMA_HISTOGRAM_ENUMERATION(kHistogram5, 2, 5);
149 UMA_HISTOGRAM_ENUMERATION(kHistogram5, 3, 5);
150 UMA_HISTOGRAM_ENUMERATION(kHistogram5, 3, 5);
151 UMA_HISTOGRAM_ENUMERATION(kHistogram5, 5, 5);
152
153 EXPECT_THAT(tester.GetAllSamples(kHistogram5),
154 ElementsAre(Bucket(2, 1), Bucket(3, 2), Bucket(5, 1)));
155 }
156
TEST_F(HistogramTesterTest,TestGetAllSamples_NoSamples)157 TEST_F(HistogramTesterTest, TestGetAllSamples_NoSamples) {
158 HistogramTester tester;
159 EXPECT_THAT(tester.GetAllSamples(kHistogram5), IsEmpty());
160 }
161
TEST_F(HistogramTesterTest,TestGetTotalSum)162 TEST_F(HistogramTesterTest, TestGetTotalSum) {
163 // Emit values twice, once before the tester creation and once after.
164 UMA_HISTOGRAM_COUNTS_100(kHistogram4, 2);
165
166 HistogramTester tester;
167 UMA_HISTOGRAM_COUNTS_100(kHistogram4, 3);
168 UMA_HISTOGRAM_COUNTS_100(kHistogram4, 4);
169
170 EXPECT_EQ(7, tester.GetTotalSum(kHistogram4));
171 }
172
TEST_F(HistogramTesterTest,TestGetTotalCountsForPrefix)173 TEST_F(HistogramTesterTest, TestGetTotalCountsForPrefix) {
174 HistogramTester tester;
175 UMA_HISTOGRAM_ENUMERATION("Test1.Test2.Test3", 2, 5);
176
177 // Regression check for bug https://crbug.com/659977.
178 EXPECT_TRUE(tester.GetTotalCountsForPrefix("Test2.").empty());
179
180 EXPECT_EQ(1u, tester.GetTotalCountsForPrefix("Test1.").size());
181 }
182
TEST_F(HistogramTesterTest,TestGetAllChangedHistograms)183 TEST_F(HistogramTesterTest, TestGetAllChangedHistograms) {
184 // Emit multiple values, some before tester creation.
185 UMA_HISTOGRAM_COUNTS_100(kHistogram6, true);
186 UMA_HISTOGRAM_COUNTS_100(kHistogram4, 4);
187
188 HistogramTester tester;
189 UMA_HISTOGRAM_COUNTS_100(kHistogram4, 3);
190
191 UMA_HISTOGRAM_ENUMERATION(kHistogram5, 2, 5);
192 UMA_HISTOGRAM_ENUMERATION(kHistogram5, 3, 5);
193 UMA_HISTOGRAM_ENUMERATION(kHistogram5, 4, 5);
194 UMA_HISTOGRAM_ENUMERATION(kHistogram5, 5, 5);
195
196 UMA_HISTOGRAM_ENUMERATION("Test1.Test2.Test3", 2, 5);
197 std::string results = tester.GetAllHistogramsRecorded();
198
199 EXPECT_EQ(std::string::npos, results.find("Histogram: Test1 recorded"));
200 EXPECT_NE(std::string::npos,
201 results.find("Histogram: Test4 recorded 1 new samples"));
202 EXPECT_NE(std::string::npos,
203 results.find("Histogram: Test5 recorded 4 new samples"));
204 EXPECT_NE(
205 std::string::npos,
206 results.find("Histogram: Test1.Test2.Test3 recorded 1 new samples"));
207 }
208
TEST_F(HistogramTesterTest,MissingHistogramMeansEmptyBuckets)209 TEST_F(HistogramTesterTest, MissingHistogramMeansEmptyBuckets) {
210 // When a histogram hasn't been instantiated, expecting counts of zero should
211 // still succeed.
212 static const char kHistogram[] = "MissingHistogramMeansEmptyBucketsHistogram";
213 HistogramTester tester;
214
215 tester.ExpectBucketCount(kHistogram, 42, 0);
216 tester.ExpectTotalCount(kHistogram, 0);
217 EXPECT_TRUE(tester.GetAllSamples(kHistogram).empty());
218 EXPECT_EQ(0, tester.GetTotalSum(kHistogram));
219 EXPECT_EQ(0, tester.GetBucketCount(kHistogram, 42));
220 EXPECT_EQ(0,
221 tester.GetHistogramSamplesSinceCreation(kHistogram)->TotalCount());
222 }
223
TEST_F(HistogramTesterTest,BucketsAre)224 TEST_F(HistogramTesterTest, BucketsAre) {
225 // Auxiliary functions for keeping the lines short.
226 auto a = [](std::vector<Bucket> b) { return b; };
227 auto b = [](base::Histogram::Sample min, base::Histogram::Count count) {
228 return Bucket(min, count);
229 };
230 using ::testing::Not;
231
232 EXPECT_THAT(a({}), BucketsAre());
233 EXPECT_THAT(a({}), BucketsAre(b(0, 0)));
234 EXPECT_THAT(a({}), BucketsAre(b(1, 0)));
235 EXPECT_THAT(a({}), BucketsAre(b(0, 0), b(1, 0)));
236 EXPECT_THAT(a({}), Not(BucketsAre(b(1, 1))));
237
238 EXPECT_THAT(a({b(1, 1)}), BucketsAre(b(1, 1)));
239 EXPECT_THAT(a({b(1, 1)}), BucketsAre(b(0, 0), b(1, 1)));
240 EXPECT_THAT(a({b(1, 1)}), Not(BucketsAre()));
241 EXPECT_THAT(a({b(1, 1)}), Not(BucketsAre(b(0, 0))));
242 EXPECT_THAT(a({b(1, 1)}), Not(BucketsAre(b(1, 0))));
243 EXPECT_THAT(a({b(1, 1)}), Not(BucketsAre(b(2, 1))));
244 EXPECT_THAT(a({b(1, 1)}), Not(BucketsAre(b(2, 2))));
245 EXPECT_THAT(a({b(1, 1)}), Not(BucketsAre(b(0, 0), b(1, 0))));
246 EXPECT_THAT(a({b(1, 1)}), Not(BucketsAre(b(0, 0), b(1, 1), b(2, 2))));
247 EXPECT_THAT(a({b(1, 1)}), Not(BucketsAre(b(0, 0), b(1, 0), b(2, 0))));
248
249 EXPECT_THAT(a({b(1, 1), b(2, 2)}), BucketsAre(b(1, 1), b(2, 2)));
250 EXPECT_THAT(a({b(1, 1), b(2, 2)}), BucketsAre(b(0, 0), b(1, 1), b(2, 2)));
251 EXPECT_THAT(a({b(1, 1), b(2, 2)}), Not(BucketsAre()));
252 EXPECT_THAT(a({b(1, 1), b(2, 2)}), Not(BucketsAre(b(0, 0))));
253 EXPECT_THAT(a({b(1, 1), b(2, 2)}), Not(BucketsAre(b(1, 1))));
254 EXPECT_THAT(a({b(1, 1), b(2, 2)}), Not(BucketsAre(b(2, 2))));
255 EXPECT_THAT(a({b(1, 1), b(2, 2)}), Not(BucketsAre(b(0, 0), b(1, 1))));
256 EXPECT_THAT(a({b(1, 1), b(2, 2)}), Not(BucketsAre(b(1, 0))));
257 EXPECT_THAT(a({b(1, 1), b(2, 2)}), Not(BucketsAre(b(2, 1))));
258 EXPECT_THAT(a({b(1, 1), b(2, 2)}), Not(BucketsAre(b(0, 0), b(1, 0))));
259 EXPECT_THAT(a({b(1, 1), b(2, 2)}),
260 Not(BucketsAre(b(0, 0), b(1, 0), b(2, 0))));
261 }
262
TEST_F(HistogramTesterTest,BucketsInclude)263 TEST_F(HistogramTesterTest, BucketsInclude) {
264 // Auxiliary function for the "actual" values to shorten lines.
265 auto a = [](std::vector<Bucket> b) { return b; };
266 auto b = [](base::Histogram::Sample min, base::Histogram::Count count) {
267 return Bucket(min, count);
268 };
269 using ::testing::Not;
270
271 EXPECT_THAT(a({}), BucketsInclude());
272 EXPECT_THAT(a({}), BucketsInclude(b(0, 0)));
273 EXPECT_THAT(a({}), BucketsInclude(b(1, 0)));
274 EXPECT_THAT(a({}), BucketsInclude(b(0, 0), b(1, 0)));
275 EXPECT_THAT(a({}), Not(BucketsInclude(b(1, 1))));
276
277 EXPECT_THAT(a({b(1, 1)}), BucketsInclude());
278 EXPECT_THAT(a({b(1, 1)}), BucketsInclude(b(0, 0)));
279 EXPECT_THAT(a({b(1, 1)}), BucketsInclude(b(1, 1)));
280 EXPECT_THAT(a({b(1, 1)}), BucketsInclude(b(0, 0), b(1, 1)));
281 EXPECT_THAT(a({b(1, 1)}), Not(BucketsInclude(b(1, 0))));
282 EXPECT_THAT(a({b(1, 1)}), Not(BucketsInclude(b(2, 1))));
283 EXPECT_THAT(a({b(1, 1)}), Not(BucketsInclude(b(2, 2))));
284 EXPECT_THAT(a({b(1, 1)}), Not(BucketsInclude(b(0, 0), b(1, 0))));
285 EXPECT_THAT(a({b(1, 1)}), Not(BucketsInclude(b(0, 0), b(1, 1), b(2, 2))));
286 EXPECT_THAT(a({b(1, 1)}), Not(BucketsInclude(b(0, 0), b(1, 0), b(2, 0))));
287
288 EXPECT_THAT(a({b(1, 1), b(2, 2)}), BucketsInclude());
289 EXPECT_THAT(a({b(1, 1), b(2, 2)}), BucketsInclude(b(0, 0)));
290 EXPECT_THAT(a({b(1, 1), b(2, 2)}), BucketsInclude(b(1, 1)));
291 EXPECT_THAT(a({b(1, 1), b(2, 2)}), BucketsInclude(b(2, 2)));
292 EXPECT_THAT(a({b(1, 1), b(2, 2)}), BucketsInclude(b(0, 0), b(1, 1)));
293 EXPECT_THAT(a({b(1, 1), b(2, 2)}), BucketsInclude(b(1, 1), b(2, 2)));
294 EXPECT_THAT(a({b(1, 1), b(2, 2)}), BucketsInclude(b(0, 0), b(1, 1), b(2, 2)));
295 EXPECT_THAT(a({b(1, 1), b(2, 2)}), Not(BucketsInclude(b(1, 0))));
296 EXPECT_THAT(a({b(1, 1), b(2, 2)}), Not(BucketsInclude(b(2, 1))));
297 EXPECT_THAT(a({b(1, 1), b(2, 2)}), Not(BucketsInclude(b(0, 0), b(1, 0))));
298 EXPECT_THAT(a({b(1, 1), b(2, 2)}),
299 Not(BucketsInclude(b(0, 0), b(1, 0), b(2, 0))));
300 }
301
302 } // namespace base
303