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