Home | History | Annotate | Download | only in metrics
      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:
     29   void SetUp() override {
     30     // Each test will have a clean state (no Histogram / BucketRanges
     31     // registered).
     32     InitializeStatisticsRecorder();
     33   }
     34 
     35   void TearDown() override { UninitializeStatisticsRecorder(); }
     36 
     37   void InitializeStatisticsRecorder() {
     38     statistics_recorder_ = new StatisticsRecorder();
     39   }
     40 
     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.
     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.
     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 
     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 
    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 
    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 
    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 
    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.
    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.
    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.
    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 
    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 
    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 
    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 
    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 
    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.
    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