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/histogram.h" 8 #include "base/string_util.h" 9 #include "base/time.h" 10 #include "testing/gtest/include/gtest/gtest.h" 11 12 using base::TimeDelta; 13 14 namespace { 15 16 class HistogramTest : public testing::Test { 17 }; 18 19 // Check for basic syntax and use. 20 TEST(HistogramTest, StartupShutdownTest) { 21 // Try basic construction 22 scoped_refptr<Histogram> histogram = Histogram::FactoryGet( 23 "TestHistogram", 1, 1000, 10, Histogram::kNoFlags); 24 scoped_refptr<Histogram> histogram1 = Histogram::FactoryGet( 25 "Test1Histogram", 1, 1000, 10, Histogram::kNoFlags); 26 27 scoped_refptr<Histogram> linear_histogram = LinearHistogram::FactoryGet( 28 "TestLinearHistogram", 1, 1000, 10, Histogram::kNoFlags); 29 scoped_refptr<Histogram> linear_histogram1 = LinearHistogram::FactoryGet( 30 "Test1LinearHistogram", 1, 1000, 10, Histogram::kNoFlags); 31 32 // Use standard macros (but with fixed samples) 33 HISTOGRAM_TIMES("Test2Histogram", TimeDelta::FromDays(1)); 34 HISTOGRAM_COUNTS("Test3Histogram", 30); 35 36 DHISTOGRAM_TIMES("Test4Histogram", TimeDelta::FromDays(1)); 37 DHISTOGRAM_COUNTS("Test5Histogram", 30); 38 39 HISTOGRAM_ENUMERATION("Test6Histogram", 129, 130); 40 41 // Try to construct samples. 42 Histogram::SampleSet sample1; 43 Histogram::SampleSet sample2; 44 45 // Use copy constructor of SampleSet 46 sample1 = sample2; 47 Histogram::SampleSet sample3(sample1); 48 49 // Finally test a statistics recorder, without really using it. 50 StatisticsRecorder recorder; 51 } 52 53 // Repeat with a recorder present to register with. 54 TEST(HistogramTest, RecordedStartupTest) { 55 // Test a statistics recorder, by letting histograms register. 56 StatisticsRecorder recorder; // This initializes the global state. 57 58 StatisticsRecorder::Histograms histograms; 59 EXPECT_EQ(0U, histograms.size()); 60 StatisticsRecorder::GetHistograms(&histograms); // Load up lists 61 EXPECT_EQ(0U, histograms.size()); 62 63 // Try basic construction 64 scoped_refptr<Histogram> histogram = Histogram::FactoryGet( 65 "TestHistogram", 1, 1000, 10, Histogram::kNoFlags); 66 histograms.clear(); 67 StatisticsRecorder::GetHistograms(&histograms); // Load up lists 68 EXPECT_EQ(1U, histograms.size()); 69 scoped_refptr<Histogram> histogram1 = Histogram::FactoryGet( 70 "Test1Histogram", 1, 1000, 10, Histogram::kNoFlags); 71 histograms.clear(); 72 StatisticsRecorder::GetHistograms(&histograms); // Load up lists 73 EXPECT_EQ(2U, histograms.size()); 74 75 scoped_refptr<Histogram> linear_histogram = LinearHistogram::FactoryGet( 76 "TestLinearHistogram", 1, 1000, 10, Histogram::kNoFlags); 77 scoped_refptr<Histogram> linear_histogram1 = LinearHistogram::FactoryGet( 78 "Test1LinearHistogram", 1, 1000, 10, Histogram::kNoFlags); 79 histograms.clear(); 80 StatisticsRecorder::GetHistograms(&histograms); // Load up lists 81 EXPECT_EQ(4U, histograms.size()); 82 83 // Use standard macros (but with fixed samples) 84 HISTOGRAM_TIMES("Test2Histogram", TimeDelta::FromDays(1)); 85 HISTOGRAM_COUNTS("Test3Histogram", 30); 86 histograms.clear(); 87 StatisticsRecorder::GetHistograms(&histograms); // Load up lists 88 EXPECT_EQ(6U, histograms.size()); 89 90 HISTOGRAM_ENUMERATION("TestEnumerationHistogram", 20, 200); 91 histograms.clear(); 92 StatisticsRecorder::GetHistograms(&histograms); // Load up lists 93 EXPECT_EQ(7U, histograms.size()); 94 95 DHISTOGRAM_TIMES("Test4Histogram", TimeDelta::FromDays(1)); 96 DHISTOGRAM_COUNTS("Test5Histogram", 30); 97 histograms.clear(); 98 StatisticsRecorder::GetHistograms(&histograms); // Load up lists 99 #ifndef NDEBUG 100 EXPECT_EQ(9U, histograms.size()); 101 #else 102 EXPECT_EQ(7U, histograms.size()); 103 #endif 104 } 105 106 TEST(HistogramTest, RangeTest) { 107 StatisticsRecorder recorder; 108 StatisticsRecorder::Histograms histograms; 109 110 recorder.GetHistograms(&histograms); 111 EXPECT_EQ(0U, histograms.size()); 112 113 scoped_refptr<Histogram> histogram = Histogram::FactoryGet( 114 "Histogram", 1, 64, 8, Histogram::kNoFlags); // As per header file. 115 // Check that we got a nice exponential when there was enough rooom. 116 EXPECT_EQ(0, histogram->ranges(0)); 117 int power_of_2 = 1; 118 for (int i = 1; i < 8; i++) { 119 EXPECT_EQ(power_of_2, histogram->ranges(i)); 120 power_of_2 *= 2; 121 } 122 EXPECT_EQ(INT_MAX, histogram->ranges(8)); 123 124 scoped_refptr<Histogram> short_histogram = Histogram::FactoryGet( 125 "Histogram Shortened", 1, 7, 8, Histogram::kNoFlags); 126 // Check that when the number of buckets is short, we get a linear histogram 127 // for lack of space to do otherwise. 128 for (int i = 0; i < 8; i++) 129 EXPECT_EQ(i, short_histogram->ranges(i)); 130 EXPECT_EQ(INT_MAX, short_histogram->ranges(8)); 131 132 scoped_refptr<Histogram> linear_histogram = LinearHistogram::FactoryGet( 133 "Linear", 1, 7, 8, Histogram::kNoFlags); 134 // We also get a nice linear set of bucket ranges when we ask for it 135 for (int i = 0; i < 8; i++) 136 EXPECT_EQ(i, linear_histogram->ranges(i)); 137 EXPECT_EQ(INT_MAX, linear_histogram->ranges(8)); 138 139 scoped_refptr<Histogram> linear_broad_histogram = LinearHistogram::FactoryGet( 140 "Linear widened", 2, 14, 8, Histogram::kNoFlags); 141 // ...but when the list has more space, then the ranges naturally spread out. 142 for (int i = 0; i < 8; i++) 143 EXPECT_EQ(2 * i, linear_broad_histogram->ranges(i)); 144 EXPECT_EQ(INT_MAX, linear_broad_histogram->ranges(8)); 145 146 scoped_refptr<Histogram> transitioning_histogram = 147 Histogram::FactoryGet("LinearAndExponential", 1, 32, 15, 148 Histogram::kNoFlags); 149 // When space is a little tight, we transition from linear to exponential. 150 EXPECT_EQ(0, transitioning_histogram->ranges(0)); 151 EXPECT_EQ(1, transitioning_histogram->ranges(1)); 152 EXPECT_EQ(2, transitioning_histogram->ranges(2)); 153 EXPECT_EQ(3, transitioning_histogram->ranges(3)); 154 EXPECT_EQ(4, transitioning_histogram->ranges(4)); 155 EXPECT_EQ(5, transitioning_histogram->ranges(5)); 156 EXPECT_EQ(6, transitioning_histogram->ranges(6)); 157 EXPECT_EQ(7, transitioning_histogram->ranges(7)); 158 EXPECT_EQ(9, transitioning_histogram->ranges(8)); 159 EXPECT_EQ(11, transitioning_histogram->ranges(9)); 160 EXPECT_EQ(14, transitioning_histogram->ranges(10)); 161 EXPECT_EQ(17, transitioning_histogram->ranges(11)); 162 EXPECT_EQ(21, transitioning_histogram->ranges(12)); 163 EXPECT_EQ(26, transitioning_histogram->ranges(13)); 164 EXPECT_EQ(32, transitioning_histogram->ranges(14)); 165 EXPECT_EQ(INT_MAX, transitioning_histogram->ranges(15)); 166 167 recorder.GetHistograms(&histograms); 168 EXPECT_EQ(5U, histograms.size()); 169 } 170 171 // Make sure histogram handles out-of-bounds data gracefully. 172 TEST(HistogramTest, BoundsTest) { 173 const size_t kBucketCount = 50; 174 scoped_refptr<Histogram> histogram = Histogram::FactoryGet( 175 "Bounded", 10, 100, kBucketCount, Histogram::kNoFlags); 176 177 // Put two samples "out of bounds" above and below. 178 histogram->Add(5); 179 histogram->Add(-50); 180 181 histogram->Add(100); 182 histogram->Add(10000); 183 184 // Verify they landed in the underflow, and overflow buckets. 185 Histogram::SampleSet sample; 186 histogram->SnapshotSample(&sample); 187 EXPECT_EQ(2, sample.counts(0)); 188 EXPECT_EQ(0, sample.counts(1)); 189 size_t array_size = histogram->bucket_count(); 190 EXPECT_EQ(kBucketCount, array_size); 191 EXPECT_EQ(0, sample.counts(array_size - 2)); 192 EXPECT_EQ(2, sample.counts(array_size - 1)); 193 } 194 195 // Check to be sure samples land as expected is "correct" buckets. 196 TEST(HistogramTest, BucketPlacementTest) { 197 scoped_refptr<Histogram> histogram = Histogram::FactoryGet( 198 "Histogram", 1, 64, 8, Histogram::kNoFlags); // As per header file. 199 200 // Check that we got a nice exponential since there was enough rooom. 201 EXPECT_EQ(0, histogram->ranges(0)); 202 int power_of_2 = 1; 203 for (int i = 1; i < 8; i++) { 204 EXPECT_EQ(power_of_2, histogram->ranges(i)); 205 power_of_2 *= 2; 206 } 207 EXPECT_EQ(INT_MAX, histogram->ranges(8)); 208 209 // Add i+1 samples to the i'th bucket. 210 histogram->Add(0); 211 power_of_2 = 1; 212 for (int i = 1; i < 8; i++) { 213 for (int j = 0; j <= i; j++) 214 histogram->Add(power_of_2); 215 power_of_2 *= 2; 216 } 217 // Leave overflow bucket empty. 218 219 // Check to see that the bucket counts reflect our additions. 220 Histogram::SampleSet sample; 221 histogram->SnapshotSample(&sample); 222 EXPECT_EQ(INT_MAX, histogram->ranges(8)); 223 for (int i = 0; i < 8; i++) 224 EXPECT_EQ(i + 1, sample.counts(i)); 225 } 226 227 228 } // namespace 229