Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / base / metrics / histogram_unittest.cc
blobf189267f3587affbf6624455ca0a6426cfd21ed5
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.
5 #include "base/metrics/histogram.h"
7 #include <climits>
8 #include <algorithm>
9 #include <vector>
11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/metrics/bucket_ranges.h"
14 #include "base/metrics/histogram_macros.h"
15 #include "base/metrics/sample_vector.h"
16 #include "base/metrics/statistics_recorder.h"
17 #include "base/pickle.h"
18 #include "base/time/time.h"
19 #include "testing/gtest/include/gtest/gtest.h"
21 namespace base {
23 class HistogramTest : public testing::Test {
24 protected:
25 void SetUp() override {
26 // Each test will have a clean state (no Histogram / BucketRanges
27 // registered).
28 InitializeStatisticsRecorder();
31 void TearDown() override { UninitializeStatisticsRecorder(); }
33 void InitializeStatisticsRecorder() {
34 statistics_recorder_ = new StatisticsRecorder();
37 void UninitializeStatisticsRecorder() {
38 delete statistics_recorder_;
39 statistics_recorder_ = NULL;
42 StatisticsRecorder* statistics_recorder_;
45 // Check for basic syntax and use.
46 TEST_F(HistogramTest, BasicTest) {
47 // Try basic construction
48 HistogramBase* histogram = Histogram::FactoryGet(
49 "TestHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
50 EXPECT_TRUE(histogram);
52 HistogramBase* linear_histogram = LinearHistogram::FactoryGet(
53 "TestLinearHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
54 EXPECT_TRUE(linear_histogram);
56 std::vector<int> custom_ranges;
57 custom_ranges.push_back(1);
58 custom_ranges.push_back(5);
59 HistogramBase* custom_histogram = CustomHistogram::FactoryGet(
60 "TestCustomHistogram", custom_ranges, HistogramBase::kNoFlags);
61 EXPECT_TRUE(custom_histogram);
63 // Use standard macros (but with fixed samples)
64 LOCAL_HISTOGRAM_TIMES("Test2Histogram", TimeDelta::FromDays(1));
65 LOCAL_HISTOGRAM_COUNTS("Test3Histogram", 30);
67 LOCAL_HISTOGRAM_ENUMERATION("Test6Histogram", 129, 130);
70 // Check that the macro correctly matches histograms by name and records their
71 // data together.
72 TEST_F(HistogramTest, NameMatchTest) {
73 LOCAL_HISTOGRAM_PERCENTAGE("DuplicatedHistogram", 10);
74 LOCAL_HISTOGRAM_PERCENTAGE("DuplicatedHistogram", 10);
75 HistogramBase* histogram = LinearHistogram::FactoryGet(
76 "DuplicatedHistogram", 1, 101, 102, HistogramBase::kNoFlags);
78 scoped_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
79 EXPECT_EQ(2, samples->TotalCount());
80 EXPECT_EQ(2, samples->GetCount(10));
83 TEST_F(HistogramTest, ExponentialRangesTest) {
84 // Check that we got a nice exponential when there was enough rooom.
85 BucketRanges ranges(9);
86 Histogram::InitializeBucketRanges(1, 64, &ranges);
87 EXPECT_EQ(0, ranges.range(0));
88 int power_of_2 = 1;
89 for (int i = 1; i < 8; i++) {
90 EXPECT_EQ(power_of_2, ranges.range(i));
91 power_of_2 *= 2;
93 EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges.range(8));
95 // Check the corresponding Histogram will use the correct ranges.
96 Histogram* histogram = static_cast<Histogram*>(
97 Histogram::FactoryGet("Histogram", 1, 64, 8, HistogramBase::kNoFlags));
98 EXPECT_TRUE(ranges.Equals(histogram->bucket_ranges()));
100 // When bucket count is limited, exponential ranges will partially look like
101 // linear.
102 BucketRanges ranges2(16);
103 Histogram::InitializeBucketRanges(1, 32, &ranges2);
105 EXPECT_EQ(0, ranges2.range(0));
106 EXPECT_EQ(1, ranges2.range(1));
107 EXPECT_EQ(2, ranges2.range(2));
108 EXPECT_EQ(3, ranges2.range(3));
109 EXPECT_EQ(4, ranges2.range(4));
110 EXPECT_EQ(5, ranges2.range(5));
111 EXPECT_EQ(6, ranges2.range(6));
112 EXPECT_EQ(7, ranges2.range(7));
113 EXPECT_EQ(9, ranges2.range(8));
114 EXPECT_EQ(11, ranges2.range(9));
115 EXPECT_EQ(14, ranges2.range(10));
116 EXPECT_EQ(17, ranges2.range(11));
117 EXPECT_EQ(21, ranges2.range(12));
118 EXPECT_EQ(26, ranges2.range(13));
119 EXPECT_EQ(32, ranges2.range(14));
120 EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges2.range(15));
122 // Check the corresponding Histogram will use the correct ranges.
123 Histogram* histogram2 = static_cast<Histogram*>(
124 Histogram::FactoryGet("Histogram2", 1, 32, 15, HistogramBase::kNoFlags));
125 EXPECT_TRUE(ranges2.Equals(histogram2->bucket_ranges()));
128 TEST_F(HistogramTest, LinearRangesTest) {
129 BucketRanges ranges(9);
130 LinearHistogram::InitializeBucketRanges(1, 7, &ranges);
131 // Gets a nice linear set of bucket ranges.
132 for (int i = 0; i < 8; i++)
133 EXPECT_EQ(i, ranges.range(i));
134 EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges.range(8));
136 // The correspoding LinearHistogram should use the correct ranges.
137 Histogram* histogram = static_cast<Histogram*>(
138 LinearHistogram::FactoryGet("Linear", 1, 7, 8, HistogramBase::kNoFlags));
139 EXPECT_TRUE(ranges.Equals(histogram->bucket_ranges()));
141 // Linear ranges are not divisible.
142 BucketRanges ranges2(6);
143 LinearHistogram::InitializeBucketRanges(1, 6, &ranges2);
144 EXPECT_EQ(0, ranges2.range(0));
145 EXPECT_EQ(1, ranges2.range(1));
146 EXPECT_EQ(3, ranges2.range(2));
147 EXPECT_EQ(4, ranges2.range(3));
148 EXPECT_EQ(6, ranges2.range(4));
149 EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges2.range(5));
150 // The correspoding LinearHistogram should use the correct ranges.
151 Histogram* histogram2 = static_cast<Histogram*>(
152 LinearHistogram::FactoryGet("Linear2", 1, 6, 5, HistogramBase::kNoFlags));
153 EXPECT_TRUE(ranges2.Equals(histogram2->bucket_ranges()));
156 TEST_F(HistogramTest, ArrayToCustomRangesTest) {
157 const HistogramBase::Sample ranges[3] = {5, 10, 20};
158 std::vector<HistogramBase::Sample> ranges_vec =
159 CustomHistogram::ArrayToCustomRanges(ranges, 3);
160 ASSERT_EQ(6u, ranges_vec.size());
161 EXPECT_EQ(5, ranges_vec[0]);
162 EXPECT_EQ(6, ranges_vec[1]);
163 EXPECT_EQ(10, ranges_vec[2]);
164 EXPECT_EQ(11, ranges_vec[3]);
165 EXPECT_EQ(20, ranges_vec[4]);
166 EXPECT_EQ(21, ranges_vec[5]);
169 TEST_F(HistogramTest, CustomHistogramTest) {
170 // A well prepared custom ranges.
171 std::vector<HistogramBase::Sample> custom_ranges;
172 custom_ranges.push_back(1);
173 custom_ranges.push_back(2);
175 Histogram* histogram = static_cast<Histogram*>(
176 CustomHistogram::FactoryGet("TestCustomHistogram1", custom_ranges,
177 HistogramBase::kNoFlags));
178 const BucketRanges* ranges = histogram->bucket_ranges();
179 ASSERT_EQ(4u, ranges->size());
180 EXPECT_EQ(0, ranges->range(0)); // Auto added.
181 EXPECT_EQ(1, ranges->range(1));
182 EXPECT_EQ(2, ranges->range(2));
183 EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges->range(3)); // Auto added.
185 // A unordered custom ranges.
186 custom_ranges.clear();
187 custom_ranges.push_back(2);
188 custom_ranges.push_back(1);
189 histogram = static_cast<Histogram*>(
190 CustomHistogram::FactoryGet("TestCustomHistogram2", custom_ranges,
191 HistogramBase::kNoFlags));
192 ranges = histogram->bucket_ranges();
193 ASSERT_EQ(4u, ranges->size());
194 EXPECT_EQ(0, ranges->range(0));
195 EXPECT_EQ(1, ranges->range(1));
196 EXPECT_EQ(2, ranges->range(2));
197 EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges->range(3));
199 // A custom ranges with duplicated values.
200 custom_ranges.clear();
201 custom_ranges.push_back(4);
202 custom_ranges.push_back(1);
203 custom_ranges.push_back(4);
204 histogram = static_cast<Histogram*>(
205 CustomHistogram::FactoryGet("TestCustomHistogram3", custom_ranges,
206 HistogramBase::kNoFlags));
207 ranges = histogram->bucket_ranges();
208 ASSERT_EQ(4u, ranges->size());
209 EXPECT_EQ(0, ranges->range(0));
210 EXPECT_EQ(1, ranges->range(1));
211 EXPECT_EQ(4, ranges->range(2));
212 EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges->range(3));
215 TEST_F(HistogramTest, CustomHistogramWithOnly2Buckets) {
216 // This test exploits the fact that the CustomHistogram can have 2 buckets,
217 // while the base class Histogram is *supposed* to have at least 3 buckets.
218 // We should probably change the restriction on the base class (or not inherit
219 // the base class!).
221 std::vector<HistogramBase::Sample> custom_ranges;
222 custom_ranges.push_back(4);
224 Histogram* histogram = static_cast<Histogram*>(
225 CustomHistogram::FactoryGet("2BucketsCustomHistogram", custom_ranges,
226 HistogramBase::kNoFlags));
227 const BucketRanges* ranges = histogram->bucket_ranges();
228 ASSERT_EQ(3u, ranges->size());
229 EXPECT_EQ(0, ranges->range(0));
230 EXPECT_EQ(4, ranges->range(1));
231 EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges->range(2));
234 // Make sure histogram handles out-of-bounds data gracefully.
235 TEST_F(HistogramTest, BoundsTest) {
236 const size_t kBucketCount = 50;
237 Histogram* histogram = static_cast<Histogram*>(
238 Histogram::FactoryGet("Bounded", 10, 100, kBucketCount,
239 HistogramBase::kNoFlags));
241 // Put two samples "out of bounds" above and below.
242 histogram->Add(5);
243 histogram->Add(-50);
245 histogram->Add(100);
246 histogram->Add(10000);
248 // Verify they landed in the underflow, and overflow buckets.
249 scoped_ptr<SampleVector> samples = histogram->SnapshotSampleVector();
250 EXPECT_EQ(2, samples->GetCountAtIndex(0));
251 EXPECT_EQ(0, samples->GetCountAtIndex(1));
252 size_t array_size = histogram->bucket_count();
253 EXPECT_EQ(kBucketCount, array_size);
254 EXPECT_EQ(0, samples->GetCountAtIndex(array_size - 2));
255 EXPECT_EQ(2, samples->GetCountAtIndex(array_size - 1));
257 std::vector<int> custom_ranges;
258 custom_ranges.push_back(10);
259 custom_ranges.push_back(50);
260 custom_ranges.push_back(100);
261 Histogram* test_custom_histogram = static_cast<Histogram*>(
262 CustomHistogram::FactoryGet("TestCustomRangeBoundedHistogram",
263 custom_ranges, HistogramBase::kNoFlags));
265 // Put two samples "out of bounds" above and below.
266 test_custom_histogram->Add(5);
267 test_custom_histogram->Add(-50);
268 test_custom_histogram->Add(100);
269 test_custom_histogram->Add(1000);
270 test_custom_histogram->Add(INT_MAX);
272 // Verify they landed in the underflow, and overflow buckets.
273 scoped_ptr<SampleVector> custom_samples =
274 test_custom_histogram->SnapshotSampleVector();
275 EXPECT_EQ(2, custom_samples->GetCountAtIndex(0));
276 EXPECT_EQ(0, custom_samples->GetCountAtIndex(1));
277 size_t bucket_count = test_custom_histogram->bucket_count();
278 EXPECT_EQ(0, custom_samples->GetCountAtIndex(bucket_count - 2));
279 EXPECT_EQ(3, custom_samples->GetCountAtIndex(bucket_count - 1));
282 // Check to be sure samples land as expected is "correct" buckets.
283 TEST_F(HistogramTest, BucketPlacementTest) {
284 Histogram* histogram = static_cast<Histogram*>(
285 Histogram::FactoryGet("Histogram", 1, 64, 8, HistogramBase::kNoFlags));
287 // Add i+1 samples to the i'th bucket.
288 histogram->Add(0);
289 int power_of_2 = 1;
290 for (int i = 1; i < 8; i++) {
291 for (int j = 0; j <= i; j++)
292 histogram->Add(power_of_2);
293 power_of_2 *= 2;
296 // Check to see that the bucket counts reflect our additions.
297 scoped_ptr<SampleVector> samples = histogram->SnapshotSampleVector();
298 for (int i = 0; i < 8; i++)
299 EXPECT_EQ(i + 1, samples->GetCountAtIndex(i));
302 TEST_F(HistogramTest, CorruptSampleCounts) {
303 Histogram* histogram = static_cast<Histogram*>(
304 Histogram::FactoryGet("Histogram", 1, 64, 8, HistogramBase::kNoFlags));
306 // Add some samples.
307 histogram->Add(20);
308 histogram->Add(40);
310 scoped_ptr<SampleVector> snapshot = histogram->SnapshotSampleVector();
311 EXPECT_EQ(HistogramBase::NO_INCONSISTENCIES,
312 histogram->FindCorruption(*snapshot));
313 EXPECT_EQ(2, snapshot->redundant_count());
314 EXPECT_EQ(2, snapshot->TotalCount());
316 snapshot->counts_[3] += 100; // Sample count won't match redundant count.
317 EXPECT_EQ(HistogramBase::COUNT_LOW_ERROR,
318 histogram->FindCorruption(*snapshot));
319 snapshot->counts_[2] -= 200;
320 EXPECT_EQ(HistogramBase::COUNT_HIGH_ERROR,
321 histogram->FindCorruption(*snapshot));
323 // But we can't spot a corruption if it is compensated for.
324 snapshot->counts_[1] += 100;
325 EXPECT_EQ(HistogramBase::NO_INCONSISTENCIES,
326 histogram->FindCorruption(*snapshot));
329 TEST_F(HistogramTest, CorruptBucketBounds) {
330 Histogram* histogram = static_cast<Histogram*>(
331 Histogram::FactoryGet("Histogram", 1, 64, 8, HistogramBase::kNoFlags));
333 scoped_ptr<SampleVector> snapshot = histogram->SnapshotSampleVector();
334 EXPECT_EQ(HistogramBase::NO_INCONSISTENCIES,
335 histogram->FindCorruption(*snapshot));
337 BucketRanges* bucket_ranges =
338 const_cast<BucketRanges*>(histogram->bucket_ranges());
339 HistogramBase::Sample tmp = bucket_ranges->range(1);
340 bucket_ranges->set_range(1, bucket_ranges->range(2));
341 bucket_ranges->set_range(2, tmp);
342 EXPECT_EQ(
343 HistogramBase::BUCKET_ORDER_ERROR | HistogramBase::RANGE_CHECKSUM_ERROR,
344 histogram->FindCorruption(*snapshot));
346 bucket_ranges->set_range(2, bucket_ranges->range(1));
347 bucket_ranges->set_range(1, tmp);
348 EXPECT_EQ(0, histogram->FindCorruption(*snapshot));
350 // Show that two simple changes don't offset each other
351 bucket_ranges->set_range(3, bucket_ranges->range(3) + 1);
352 EXPECT_EQ(HistogramBase::RANGE_CHECKSUM_ERROR,
353 histogram->FindCorruption(*snapshot));
355 bucket_ranges->set_range(4, bucket_ranges->range(4) - 1);
356 EXPECT_EQ(HistogramBase::RANGE_CHECKSUM_ERROR,
357 histogram->FindCorruption(*snapshot));
359 // Repair histogram so that destructor won't DCHECK().
360 bucket_ranges->set_range(3, bucket_ranges->range(3) - 1);
361 bucket_ranges->set_range(4, bucket_ranges->range(4) + 1);
364 TEST_F(HistogramTest, HistogramSerializeInfo) {
365 Histogram* histogram = static_cast<Histogram*>(
366 Histogram::FactoryGet("Histogram", 1, 64, 8,
367 HistogramBase::kIPCSerializationSourceFlag));
368 Pickle pickle;
369 histogram->SerializeInfo(&pickle);
371 PickleIterator iter(pickle);
373 int type;
374 EXPECT_TRUE(iter.ReadInt(&type));
375 EXPECT_EQ(HISTOGRAM, type);
377 std::string name;
378 EXPECT_TRUE(iter.ReadString(&name));
379 EXPECT_EQ("Histogram", name);
381 int flag;
382 EXPECT_TRUE(iter.ReadInt(&flag));
383 EXPECT_EQ(HistogramBase::kIPCSerializationSourceFlag, flag);
385 int min;
386 EXPECT_TRUE(iter.ReadInt(&min));
387 EXPECT_EQ(1, min);
389 int max;
390 EXPECT_TRUE(iter.ReadInt(&max));
391 EXPECT_EQ(64, max);
393 int64 bucket_count;
394 EXPECT_TRUE(iter.ReadInt64(&bucket_count));
395 EXPECT_EQ(8, bucket_count);
397 uint32 checksum;
398 EXPECT_TRUE(iter.ReadUInt32(&checksum));
399 EXPECT_EQ(histogram->bucket_ranges()->checksum(), checksum);
401 // No more data in the pickle.
402 EXPECT_FALSE(iter.SkipBytes(1));
405 TEST_F(HistogramTest, CustomHistogramSerializeInfo) {
406 std::vector<int> custom_ranges;
407 custom_ranges.push_back(10);
408 custom_ranges.push_back(100);
410 HistogramBase* custom_histogram = CustomHistogram::FactoryGet(
411 "TestCustomRangeBoundedHistogram",
412 custom_ranges,
413 HistogramBase::kNoFlags);
414 Pickle pickle;
415 custom_histogram->SerializeInfo(&pickle);
417 // Validate the pickle.
418 PickleIterator iter(pickle);
420 int i;
421 std::string s;
422 int64 bucket_count;
423 uint32 ui32;
424 EXPECT_TRUE(iter.ReadInt(&i) && iter.ReadString(&s) && iter.ReadInt(&i) &&
425 iter.ReadInt(&i) && iter.ReadInt(&i) &&
426 iter.ReadInt64(&bucket_count) && iter.ReadUInt32(&ui32));
427 EXPECT_EQ(3, bucket_count);
429 int range;
430 EXPECT_TRUE(iter.ReadInt(&range));
431 EXPECT_EQ(10, range);
432 EXPECT_TRUE(iter.ReadInt(&range));
433 EXPECT_EQ(100, range);
435 // No more data in the pickle.
436 EXPECT_FALSE(iter.SkipBytes(1));
439 TEST_F(HistogramTest, BadConstruction) {
440 HistogramBase* histogram = Histogram::FactoryGet(
441 "BadConstruction", 0, 100, 8, HistogramBase::kNoFlags);
442 EXPECT_TRUE(histogram->HasConstructionArguments(1, 100, 8));
444 // Try to get the same histogram name with different arguments.
445 HistogramBase* bad_histogram = Histogram::FactoryGet(
446 "BadConstruction", 0, 100, 7, HistogramBase::kNoFlags);
447 EXPECT_EQ(NULL, bad_histogram);
448 bad_histogram = Histogram::FactoryGet(
449 "BadConstruction", 0, 99, 8, HistogramBase::kNoFlags);
450 EXPECT_EQ(NULL, bad_histogram);
452 HistogramBase* linear_histogram = LinearHistogram::FactoryGet(
453 "BadConstructionLinear", 0, 100, 8, HistogramBase::kNoFlags);
454 EXPECT_TRUE(linear_histogram->HasConstructionArguments(1, 100, 8));
456 // Try to get the same histogram name with different arguments.
457 bad_histogram = LinearHistogram::FactoryGet(
458 "BadConstructionLinear", 0, 100, 7, HistogramBase::kNoFlags);
459 EXPECT_EQ(NULL, bad_histogram);
460 bad_histogram = LinearHistogram::FactoryGet(
461 "BadConstructionLinear", 10, 100, 8, HistogramBase::kNoFlags);
462 EXPECT_EQ(NULL, bad_histogram);
465 #if GTEST_HAS_DEATH_TEST
466 // For Histogram, LinearHistogram and CustomHistogram, the minimum for a
467 // declared range is 1, while the maximum is (HistogramBase::kSampleType_MAX -
468 // 1). But we accept ranges exceeding those limits, and silently clamped to
469 // those limits. This is for backwards compatibility.
470 TEST(HistogramDeathTest, BadRangesTest) {
471 HistogramBase* histogram = Histogram::FactoryGet(
472 "BadRanges", 0, HistogramBase::kSampleType_MAX, 8,
473 HistogramBase::kNoFlags);
474 EXPECT_TRUE(
475 histogram->HasConstructionArguments(
476 1, HistogramBase::kSampleType_MAX - 1, 8));
478 HistogramBase* linear_histogram = LinearHistogram::FactoryGet(
479 "BadRangesLinear", 0, HistogramBase::kSampleType_MAX, 8,
480 HistogramBase::kNoFlags);
481 EXPECT_TRUE(
482 linear_histogram->HasConstructionArguments(
483 1, HistogramBase::kSampleType_MAX - 1, 8));
485 std::vector<int> custom_ranges;
486 custom_ranges.push_back(0);
487 custom_ranges.push_back(5);
488 Histogram* custom_histogram = static_cast<Histogram*>(
489 CustomHistogram::FactoryGet(
490 "BadRangesCustom", custom_ranges, HistogramBase::kNoFlags));
491 const BucketRanges* ranges = custom_histogram->bucket_ranges();
492 ASSERT_EQ(3u, ranges->size());
493 EXPECT_EQ(0, ranges->range(0));
494 EXPECT_EQ(5, ranges->range(1));
495 EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges->range(2));
497 // CustomHistogram does not accepts kSampleType_MAX as range.
498 custom_ranges.push_back(HistogramBase::kSampleType_MAX);
499 EXPECT_DEATH(CustomHistogram::FactoryGet("BadRangesCustom2", custom_ranges,
500 HistogramBase::kNoFlags),
501 "");
503 // CustomHistogram needs at least 1 valid range.
504 custom_ranges.clear();
505 custom_ranges.push_back(0);
506 EXPECT_DEATH(CustomHistogram::FactoryGet("BadRangesCustom3", custom_ranges,
507 HistogramBase::kNoFlags),
508 "");
510 #endif
512 } // namespace base