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