histogram_unittest.cc revision 731df977c0511bca2206b5f333555b1205ff1f43
1// Copyright (c) 2006-2008 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// Test of Histogram class 6 7#include "base/metrics/histogram.h" 8#include "base/time.h" 9#include "testing/gtest/include/gtest/gtest.h" 10 11namespace base { 12namespace { 13 14class HistogramTest : public testing::Test { 15}; 16 17// Check for basic syntax and use. 18TEST(HistogramTest, StartupShutdownTest) { 19 // Try basic construction 20 scoped_refptr<Histogram> histogram = Histogram::FactoryGet( 21 "TestHistogram", 1, 1000, 10, Histogram::kNoFlags); 22 scoped_refptr<Histogram> histogram1 = Histogram::FactoryGet( 23 "Test1Histogram", 1, 1000, 10, Histogram::kNoFlags); 24 25 scoped_refptr<Histogram> linear_histogram = LinearHistogram::FactoryGet( 26 "TestLinearHistogram", 1, 1000, 10, Histogram::kNoFlags); 27 scoped_refptr<Histogram> linear_histogram1 = LinearHistogram::FactoryGet( 28 "Test1LinearHistogram", 1, 1000, 10, Histogram::kNoFlags); 29 30 std::vector<int> custom_ranges; 31 custom_ranges.push_back(1); 32 custom_ranges.push_back(5); 33 custom_ranges.push_back(10); 34 custom_ranges.push_back(20); 35 custom_ranges.push_back(30); 36 scoped_refptr<Histogram> custom_histogram = CustomHistogram::FactoryGet( 37 "TestCustomHistogram", custom_ranges, Histogram::kNoFlags); 38 scoped_refptr<Histogram> custom_histogram1 = CustomHistogram::FactoryGet( 39 "Test1CustomHistogram", custom_ranges, Histogram::kNoFlags); 40 41 // Use standard macros (but with fixed samples) 42 HISTOGRAM_TIMES("Test2Histogram", TimeDelta::FromDays(1)); 43 HISTOGRAM_COUNTS("Test3Histogram", 30); 44 45 DHISTOGRAM_TIMES("Test4Histogram", TimeDelta::FromDays(1)); 46 DHISTOGRAM_COUNTS("Test5Histogram", 30); 47 48 HISTOGRAM_ENUMERATION("Test6Histogram", 129, 130); 49 50 // Try to construct samples. 51 Histogram::SampleSet sample1; 52 Histogram::SampleSet sample2; 53 54 // Use copy constructor of SampleSet 55 sample1 = sample2; 56 Histogram::SampleSet sample3(sample1); 57 58 // Finally test a statistics recorder, without really using it. 59 StatisticsRecorder recorder; 60} 61 62// Repeat with a recorder present to register with. 63TEST(HistogramTest, RecordedStartupTest) { 64 // Test a statistics recorder, by letting histograms register. 65 StatisticsRecorder recorder; // This initializes the global state. 66 67 StatisticsRecorder::Histograms histograms; 68 EXPECT_EQ(0U, histograms.size()); 69 StatisticsRecorder::GetHistograms(&histograms); // Load up lists 70 EXPECT_EQ(0U, histograms.size()); 71 72 // Try basic construction 73 scoped_refptr<Histogram> histogram = Histogram::FactoryGet( 74 "TestHistogram", 1, 1000, 10, Histogram::kNoFlags); 75 histograms.clear(); 76 StatisticsRecorder::GetHistograms(&histograms); // Load up lists 77 EXPECT_EQ(1U, histograms.size()); 78 scoped_refptr<Histogram> histogram1 = Histogram::FactoryGet( 79 "Test1Histogram", 1, 1000, 10, Histogram::kNoFlags); 80 histograms.clear(); 81 StatisticsRecorder::GetHistograms(&histograms); // Load up lists 82 EXPECT_EQ(2U, histograms.size()); 83 84 scoped_refptr<Histogram> linear_histogram = LinearHistogram::FactoryGet( 85 "TestLinearHistogram", 1, 1000, 10, Histogram::kNoFlags); 86 histograms.clear(); 87 StatisticsRecorder::GetHistograms(&histograms); // Load up lists 88 EXPECT_EQ(3U, histograms.size()); 89 90 scoped_refptr<Histogram> linear_histogram1 = LinearHistogram::FactoryGet( 91 "Test1LinearHistogram", 1, 1000, 10, Histogram::kNoFlags); 92 histograms.clear(); 93 StatisticsRecorder::GetHistograms(&histograms); // Load up lists 94 EXPECT_EQ(4U, histograms.size()); 95 96 std::vector<int> custom_ranges; 97 custom_ranges.push_back(1); 98 custom_ranges.push_back(5); 99 custom_ranges.push_back(10); 100 custom_ranges.push_back(20); 101 custom_ranges.push_back(30); 102 scoped_refptr<Histogram> custom_histogram = CustomHistogram::FactoryGet( 103 "TestCustomHistogram", custom_ranges, Histogram::kNoFlags); 104 scoped_refptr<Histogram> custom_histogram1 = CustomHistogram::FactoryGet( 105 "TestCustomHistogram", custom_ranges, Histogram::kNoFlags); 106 107 histograms.clear(); 108 StatisticsRecorder::GetHistograms(&histograms); // Load up lists 109 EXPECT_EQ(5U, histograms.size()); 110 111 // Use standard macros (but with fixed samples) 112 HISTOGRAM_TIMES("Test2Histogram", TimeDelta::FromDays(1)); 113 HISTOGRAM_COUNTS("Test3Histogram", 30); 114 histograms.clear(); 115 StatisticsRecorder::GetHistograms(&histograms); // Load up lists 116 EXPECT_EQ(7U, histograms.size()); 117 118 HISTOGRAM_ENUMERATION("TestEnumerationHistogram", 20, 200); 119 histograms.clear(); 120 StatisticsRecorder::GetHistograms(&histograms); // Load up lists 121 EXPECT_EQ(8U, histograms.size()); 122 123 DHISTOGRAM_TIMES("Test4Histogram", TimeDelta::FromDays(1)); 124 DHISTOGRAM_COUNTS("Test5Histogram", 30); 125 histograms.clear(); 126 StatisticsRecorder::GetHistograms(&histograms); // Load up lists 127#ifndef NDEBUG 128 EXPECT_EQ(10U, histograms.size()); 129#else 130 EXPECT_EQ(8U, histograms.size()); 131#endif 132} 133 134TEST(HistogramTest, RangeTest) { 135 StatisticsRecorder recorder; 136 StatisticsRecorder::Histograms histograms; 137 138 recorder.GetHistograms(&histograms); 139 EXPECT_EQ(0U, histograms.size()); 140 141 scoped_refptr<Histogram> histogram = Histogram::FactoryGet( 142 "Histogram", 1, 64, 8, Histogram::kNoFlags); // As per header file. 143 // Check that we got a nice exponential when there was enough rooom. 144 EXPECT_EQ(0, histogram->ranges(0)); 145 int power_of_2 = 1; 146 for (int i = 1; i < 8; i++) { 147 EXPECT_EQ(power_of_2, histogram->ranges(i)); 148 power_of_2 *= 2; 149 } 150 EXPECT_EQ(INT_MAX, histogram->ranges(8)); 151 152 scoped_refptr<Histogram> short_histogram = Histogram::FactoryGet( 153 "Histogram Shortened", 1, 7, 8, Histogram::kNoFlags); 154 // Check that when the number of buckets is short, we get a linear histogram 155 // for lack of space to do otherwise. 156 for (int i = 0; i < 8; i++) 157 EXPECT_EQ(i, short_histogram->ranges(i)); 158 EXPECT_EQ(INT_MAX, short_histogram->ranges(8)); 159 160 scoped_refptr<Histogram> linear_histogram = LinearHistogram::FactoryGet( 161 "Linear", 1, 7, 8, Histogram::kNoFlags); 162 // We also get a nice linear set of bucket ranges when we ask for it 163 for (int i = 0; i < 8; i++) 164 EXPECT_EQ(i, linear_histogram->ranges(i)); 165 EXPECT_EQ(INT_MAX, linear_histogram->ranges(8)); 166 167 scoped_refptr<Histogram> linear_broad_histogram = LinearHistogram::FactoryGet( 168 "Linear widened", 2, 14, 8, Histogram::kNoFlags); 169 // ...but when the list has more space, then the ranges naturally spread out. 170 for (int i = 0; i < 8; i++) 171 EXPECT_EQ(2 * i, linear_broad_histogram->ranges(i)); 172 EXPECT_EQ(INT_MAX, linear_broad_histogram->ranges(8)); 173 174 scoped_refptr<Histogram> transitioning_histogram = 175 Histogram::FactoryGet("LinearAndExponential", 1, 32, 15, 176 Histogram::kNoFlags); 177 // When space is a little tight, we transition from linear to exponential. 178 EXPECT_EQ(0, transitioning_histogram->ranges(0)); 179 EXPECT_EQ(1, transitioning_histogram->ranges(1)); 180 EXPECT_EQ(2, transitioning_histogram->ranges(2)); 181 EXPECT_EQ(3, transitioning_histogram->ranges(3)); 182 EXPECT_EQ(4, transitioning_histogram->ranges(4)); 183 EXPECT_EQ(5, transitioning_histogram->ranges(5)); 184 EXPECT_EQ(6, transitioning_histogram->ranges(6)); 185 EXPECT_EQ(7, transitioning_histogram->ranges(7)); 186 EXPECT_EQ(9, transitioning_histogram->ranges(8)); 187 EXPECT_EQ(11, transitioning_histogram->ranges(9)); 188 EXPECT_EQ(14, transitioning_histogram->ranges(10)); 189 EXPECT_EQ(17, transitioning_histogram->ranges(11)); 190 EXPECT_EQ(21, transitioning_histogram->ranges(12)); 191 EXPECT_EQ(26, transitioning_histogram->ranges(13)); 192 EXPECT_EQ(32, transitioning_histogram->ranges(14)); 193 EXPECT_EQ(INT_MAX, transitioning_histogram->ranges(15)); 194 195 std::vector<int> custom_ranges; 196 custom_ranges.push_back(0); 197 custom_ranges.push_back(9); 198 custom_ranges.push_back(10); 199 custom_ranges.push_back(11); 200 custom_ranges.push_back(300); 201 scoped_refptr<Histogram> test_custom_histogram = CustomHistogram::FactoryGet( 202 "TestCustomRangeHistogram", custom_ranges, Histogram::kNoFlags); 203 204 EXPECT_EQ(custom_ranges[0], test_custom_histogram->ranges(0)); 205 EXPECT_EQ(custom_ranges[1], test_custom_histogram->ranges(1)); 206 EXPECT_EQ(custom_ranges[2], test_custom_histogram->ranges(2)); 207 EXPECT_EQ(custom_ranges[3], test_custom_histogram->ranges(3)); 208 EXPECT_EQ(custom_ranges[4], test_custom_histogram->ranges(4)); 209 210 recorder.GetHistograms(&histograms); 211 EXPECT_EQ(6U, histograms.size()); 212} 213 214TEST(HistogramTest, CustomRangeTest) { 215 StatisticsRecorder recorder; 216 StatisticsRecorder::Histograms histograms; 217 218 // Check that missing leading zero is handled by an auto-insertion. 219 std::vector<int> custom_ranges; 220 // Don't include a zero. 221 custom_ranges.push_back(9); 222 custom_ranges.push_back(10); 223 custom_ranges.push_back(11); 224 scoped_refptr<Histogram> test_custom_histogram = CustomHistogram::FactoryGet( 225 "TestCustomRangeHistogram", custom_ranges, Histogram::kNoFlags); 226 227 EXPECT_EQ(0, test_custom_histogram->ranges(0)); // Auto added 228 EXPECT_EQ(custom_ranges[0], test_custom_histogram->ranges(1)); 229 EXPECT_EQ(custom_ranges[1], test_custom_histogram->ranges(2)); 230 EXPECT_EQ(custom_ranges[2], test_custom_histogram->ranges(3)); 231 232 // Check that unsorted data with dups is handled gracefully. 233 const int kSmall = 7; 234 const int kMid = 8; 235 const int kBig = 9; 236 custom_ranges.clear(); 237 custom_ranges.push_back(kBig); 238 custom_ranges.push_back(kMid); 239 custom_ranges.push_back(kSmall); 240 custom_ranges.push_back(kSmall); 241 custom_ranges.push_back(kMid); 242 custom_ranges.push_back(0); // Push an explicit zero. 243 custom_ranges.push_back(kBig); 244 245 scoped_refptr<Histogram> unsorted_histogram = CustomHistogram::FactoryGet( 246 "TestCustomUnsortedDupedHistogram", custom_ranges, Histogram::kNoFlags); 247 EXPECT_EQ(0, unsorted_histogram->ranges(0)); 248 EXPECT_EQ(kSmall, unsorted_histogram->ranges(1)); 249 EXPECT_EQ(kMid, unsorted_histogram->ranges(2)); 250 EXPECT_EQ(kBig, unsorted_histogram->ranges(3)); 251} 252 253 254// Make sure histogram handles out-of-bounds data gracefully. 255TEST(HistogramTest, BoundsTest) { 256 const size_t kBucketCount = 50; 257 scoped_refptr<Histogram> histogram = Histogram::FactoryGet( 258 "Bounded", 10, 100, kBucketCount, Histogram::kNoFlags); 259 260 // Put two samples "out of bounds" above and below. 261 histogram->Add(5); 262 histogram->Add(-50); 263 264 histogram->Add(100); 265 histogram->Add(10000); 266 267 // Verify they landed in the underflow, and overflow buckets. 268 Histogram::SampleSet sample; 269 histogram->SnapshotSample(&sample); 270 EXPECT_EQ(2, sample.counts(0)); 271 EXPECT_EQ(0, sample.counts(1)); 272 size_t array_size = histogram->bucket_count(); 273 EXPECT_EQ(kBucketCount, array_size); 274 EXPECT_EQ(0, sample.counts(array_size - 2)); 275 EXPECT_EQ(2, sample.counts(array_size - 1)); 276} 277 278// Check to be sure samples land as expected is "correct" buckets. 279TEST(HistogramTest, BucketPlacementTest) { 280 scoped_refptr<Histogram> histogram = Histogram::FactoryGet( 281 "Histogram", 1, 64, 8, Histogram::kNoFlags); // As per header file. 282 283 // Check that we got a nice exponential since there was enough rooom. 284 EXPECT_EQ(0, histogram->ranges(0)); 285 int power_of_2 = 1; 286 for (int i = 1; i < 8; i++) { 287 EXPECT_EQ(power_of_2, histogram->ranges(i)); 288 power_of_2 *= 2; 289 } 290 EXPECT_EQ(INT_MAX, histogram->ranges(8)); 291 292 // Add i+1 samples to the i'th bucket. 293 histogram->Add(0); 294 power_of_2 = 1; 295 for (int i = 1; i < 8; i++) { 296 for (int j = 0; j <= i; j++) 297 histogram->Add(power_of_2); 298 power_of_2 *= 2; 299 } 300 // Leave overflow bucket empty. 301 302 // Check to see that the bucket counts reflect our additions. 303 Histogram::SampleSet sample; 304 histogram->SnapshotSample(&sample); 305 EXPECT_EQ(INT_MAX, histogram->ranges(8)); 306 for (int i = 0; i < 8; i++) 307 EXPECT_EQ(i + 1, sample.counts(i)); 308} 309 310} // namespace 311} // namespace base 312