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