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 <climits>
     12 #include <memory>
     13 #include <string>
     14 #include <vector>
     15 
     16 #include "base/logging.h"
     17 #include "base/metrics/bucket_ranges.h"
     18 #include "base/metrics/histogram_macros.h"
     19 #include "base/metrics/persistent_histogram_allocator.h"
     20 #include "base/metrics/persistent_memory_allocator.h"
     21 #include "base/metrics/sample_vector.h"
     22 #include "base/metrics/statistics_recorder.h"
     23 #include "base/pickle.h"
     24 #include "base/strings/stringprintf.h"
     25 #include "base/time/time.h"
     26 #include "testing/gtest/include/gtest/gtest.h"
     27 
     28 namespace base {
     29 
     30 // Test parameter indicates if a persistent memory allocator should be used
     31 // for histogram allocation. False will allocate histograms from the process
     32 // heap.
     33 class HistogramTest : public testing::TestWithParam<bool> {
     34  protected:
     35   const int32_t kAllocatorMemorySize = 8 << 20;  // 8 MiB
     36 
     37   HistogramTest() : use_persistent_histogram_allocator_(GetParam()) {}
     38 
     39   void SetUp() override {
     40     if (use_persistent_histogram_allocator_)
     41       CreatePersistentHistogramAllocator();
     42 
     43     // Each test will have a clean state (no Histogram / BucketRanges
     44     // registered).
     45     InitializeStatisticsRecorder();
     46   }
     47 
     48   void TearDown() override {
     49     if (allocator_) {
     50       ASSERT_FALSE(allocator_->IsFull());
     51       ASSERT_FALSE(allocator_->IsCorrupt());
     52     }
     53     UninitializeStatisticsRecorder();
     54     DestroyPersistentHistogramAllocator();
     55   }
     56 
     57   void InitializeStatisticsRecorder() {
     58     DCHECK(!statistics_recorder_);
     59     statistics_recorder_ = StatisticsRecorder::CreateTemporaryForTesting();
     60   }
     61 
     62   void UninitializeStatisticsRecorder() {
     63     statistics_recorder_.reset();
     64   }
     65 
     66   void CreatePersistentHistogramAllocator() {
     67     // By getting the results-histogram before any persistent allocator
     68     // is attached, that histogram is guaranteed not to be stored in
     69     // any persistent memory segment (which simplifies some tests).
     70     GlobalHistogramAllocator::GetCreateHistogramResultHistogram();
     71 
     72     GlobalHistogramAllocator::CreateWithLocalMemory(
     73         kAllocatorMemorySize, 0, "HistogramAllocatorTest");
     74     allocator_ = GlobalHistogramAllocator::Get()->memory_allocator();
     75   }
     76 
     77   void DestroyPersistentHistogramAllocator() {
     78     allocator_ = nullptr;
     79     GlobalHistogramAllocator::ReleaseForTesting();
     80   }
     81 
     82   const bool use_persistent_histogram_allocator_;
     83 
     84   std::unique_ptr<StatisticsRecorder> statistics_recorder_;
     85   std::unique_ptr<char[]> allocator_memory_;
     86   PersistentMemoryAllocator* allocator_ = nullptr;
     87 
     88  private:
     89   DISALLOW_COPY_AND_ASSIGN(HistogramTest);
     90 };
     91 
     92 // Run all HistogramTest cases with both heap and persistent memory.
     93 INSTANTIATE_TEST_CASE_P(HeapAndPersistent, HistogramTest, testing::Bool());
     94 
     95 
     96 // Check for basic syntax and use.
     97 TEST_P(HistogramTest, BasicTest) {
     98   // Try basic construction
     99   HistogramBase* histogram = Histogram::FactoryGet(
    100       "TestHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
    101   EXPECT_TRUE(histogram);
    102 
    103   HistogramBase* linear_histogram = LinearHistogram::FactoryGet(
    104       "TestLinearHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
    105   EXPECT_TRUE(linear_histogram);
    106 
    107   std::vector<int> custom_ranges;
    108   custom_ranges.push_back(1);
    109   custom_ranges.push_back(5);
    110   HistogramBase* custom_histogram = CustomHistogram::FactoryGet(
    111       "TestCustomHistogram", custom_ranges, HistogramBase::kNoFlags);
    112   EXPECT_TRUE(custom_histogram);
    113 
    114   // Macros that create hitograms have an internal static variable which will
    115   // continue to point to those from the very first run of this method even
    116   // during subsequent runs.
    117   static bool already_run = false;
    118   if (already_run)
    119     return;
    120   already_run = true;
    121 
    122   // Use standard macros (but with fixed samples)
    123   LOCAL_HISTOGRAM_TIMES("Test2Histogram", TimeDelta::FromDays(1));
    124   LOCAL_HISTOGRAM_COUNTS("Test3Histogram", 30);
    125 
    126   LOCAL_HISTOGRAM_ENUMERATION("Test6Histogram", 129, 130);
    127 }
    128 
    129 // Check that the macro correctly matches histograms by name and records their
    130 // data together.
    131 TEST_P(HistogramTest, NameMatchTest) {
    132   // Macros that create hitograms have an internal static variable which will
    133   // continue to point to those from the very first run of this method even
    134   // during subsequent runs.
    135   static bool already_run = false;
    136   if (already_run)
    137     return;
    138   already_run = true;
    139 
    140   LOCAL_HISTOGRAM_PERCENTAGE("DuplicatedHistogram", 10);
    141   LOCAL_HISTOGRAM_PERCENTAGE("DuplicatedHistogram", 10);
    142   HistogramBase* histogram = LinearHistogram::FactoryGet(
    143       "DuplicatedHistogram", 1, 101, 102, HistogramBase::kNoFlags);
    144 
    145   std::unique_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
    146   EXPECT_EQ(2, samples->TotalCount());
    147   EXPECT_EQ(2, samples->GetCount(10));
    148 }
    149 
    150 // Check that delta calculations work correctly.
    151 TEST_P(HistogramTest, DeltaTest) {
    152   HistogramBase* histogram =
    153       Histogram::FactoryGet("DeltaHistogram", 1, 64, 8,
    154                             HistogramBase::kNoFlags);
    155   histogram->Add(1);
    156   histogram->Add(10);
    157   histogram->Add(50);
    158 
    159   std::unique_ptr<HistogramSamples> samples = histogram->SnapshotDelta();
    160   EXPECT_EQ(3, samples->TotalCount());
    161   EXPECT_EQ(1, samples->GetCount(1));
    162   EXPECT_EQ(1, samples->GetCount(10));
    163   EXPECT_EQ(1, samples->GetCount(50));
    164   EXPECT_EQ(samples->TotalCount(), samples->redundant_count());
    165 
    166   samples = histogram->SnapshotDelta();
    167   EXPECT_EQ(0, samples->TotalCount());
    168 
    169   histogram->Add(10);
    170   histogram->Add(10);
    171   samples = histogram->SnapshotDelta();
    172   EXPECT_EQ(2, samples->TotalCount());
    173   EXPECT_EQ(2, samples->GetCount(10));
    174 
    175   samples = histogram->SnapshotDelta();
    176   EXPECT_EQ(0, samples->TotalCount());
    177 }
    178 
    179 // Check that final-delta calculations work correctly.
    180 TEST_P(HistogramTest, FinalDeltaTest) {
    181   HistogramBase* histogram =
    182       Histogram::FactoryGet("FinalDeltaHistogram", 1, 64, 8,
    183                             HistogramBase::kNoFlags);
    184   histogram->Add(1);
    185   histogram->Add(10);
    186   histogram->Add(50);
    187 
    188   std::unique_ptr<HistogramSamples> samples = histogram->SnapshotDelta();
    189   EXPECT_EQ(3, samples->TotalCount());
    190   EXPECT_EQ(1, samples->GetCount(1));
    191   EXPECT_EQ(1, samples->GetCount(10));
    192   EXPECT_EQ(1, samples->GetCount(50));
    193   EXPECT_EQ(samples->TotalCount(), samples->redundant_count());
    194 
    195   histogram->Add(2);
    196   histogram->Add(50);
    197 
    198   samples = histogram->SnapshotFinalDelta();
    199   EXPECT_EQ(2, samples->TotalCount());
    200   EXPECT_EQ(1, samples->GetCount(2));
    201   EXPECT_EQ(1, samples->GetCount(50));
    202   EXPECT_EQ(samples->TotalCount(), samples->redundant_count());
    203 }
    204 
    205 TEST_P(HistogramTest, ExponentialRangesTest) {
    206   // Check that we got a nice exponential when there was enough room.
    207   BucketRanges ranges(9);
    208   Histogram::InitializeBucketRanges(1, 64, &ranges);
    209   EXPECT_EQ(0, ranges.range(0));
    210   int power_of_2 = 1;
    211   for (int i = 1; i < 8; i++) {
    212     EXPECT_EQ(power_of_2, ranges.range(i));
    213     power_of_2 *= 2;
    214   }
    215   EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges.range(8));
    216 
    217   // Check the corresponding Histogram will use the correct ranges.
    218   Histogram* histogram = static_cast<Histogram*>(
    219       Histogram::FactoryGet("Histogram", 1, 64, 8, HistogramBase::kNoFlags));
    220   EXPECT_TRUE(ranges.Equals(histogram->bucket_ranges()));
    221 
    222   // When bucket count is limited, exponential ranges will partially look like
    223   // linear.
    224   BucketRanges ranges2(16);
    225   Histogram::InitializeBucketRanges(1, 32, &ranges2);
    226 
    227   EXPECT_EQ(0, ranges2.range(0));
    228   EXPECT_EQ(1, ranges2.range(1));
    229   EXPECT_EQ(2, ranges2.range(2));
    230   EXPECT_EQ(3, ranges2.range(3));
    231   EXPECT_EQ(4, ranges2.range(4));
    232   EXPECT_EQ(5, ranges2.range(5));
    233   EXPECT_EQ(6, ranges2.range(6));
    234   EXPECT_EQ(7, ranges2.range(7));
    235   EXPECT_EQ(9, ranges2.range(8));
    236   EXPECT_EQ(11, ranges2.range(9));
    237   EXPECT_EQ(14, ranges2.range(10));
    238   EXPECT_EQ(17, ranges2.range(11));
    239   EXPECT_EQ(21, ranges2.range(12));
    240   EXPECT_EQ(26, ranges2.range(13));
    241   EXPECT_EQ(32, ranges2.range(14));
    242   EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges2.range(15));
    243 
    244   // Check the corresponding Histogram will use the correct ranges.
    245   Histogram* histogram2 = static_cast<Histogram*>(
    246       Histogram::FactoryGet("Histogram2", 1, 32, 15, HistogramBase::kNoFlags));
    247   EXPECT_TRUE(ranges2.Equals(histogram2->bucket_ranges()));
    248 }
    249 
    250 TEST_P(HistogramTest, LinearRangesTest) {
    251   BucketRanges ranges(9);
    252   LinearHistogram::InitializeBucketRanges(1, 7, &ranges);
    253   // Gets a nice linear set of bucket ranges.
    254   for (int i = 0; i < 8; i++)
    255     EXPECT_EQ(i, ranges.range(i));
    256   EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges.range(8));
    257 
    258   // The correspoding LinearHistogram should use the correct ranges.
    259   Histogram* histogram = static_cast<Histogram*>(
    260       LinearHistogram::FactoryGet("Linear", 1, 7, 8, HistogramBase::kNoFlags));
    261   EXPECT_TRUE(ranges.Equals(histogram->bucket_ranges()));
    262 
    263   // Linear ranges are not divisible.
    264   BucketRanges ranges2(6);
    265   LinearHistogram::InitializeBucketRanges(1, 6, &ranges2);
    266   EXPECT_EQ(0, ranges2.range(0));
    267   EXPECT_EQ(1, ranges2.range(1));
    268   EXPECT_EQ(3, ranges2.range(2));
    269   EXPECT_EQ(4, ranges2.range(3));
    270   EXPECT_EQ(6, ranges2.range(4));
    271   EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges2.range(5));
    272   // The correspoding LinearHistogram should use the correct ranges.
    273   Histogram* histogram2 = static_cast<Histogram*>(
    274       LinearHistogram::FactoryGet("Linear2", 1, 6, 5, HistogramBase::kNoFlags));
    275   EXPECT_TRUE(ranges2.Equals(histogram2->bucket_ranges()));
    276 }
    277 
    278 TEST_P(HistogramTest, ArrayToCustomRangesTest) {
    279   const HistogramBase::Sample ranges[3] = {5, 10, 20};
    280   std::vector<HistogramBase::Sample> ranges_vec =
    281       CustomHistogram::ArrayToCustomRanges(ranges, 3);
    282   ASSERT_EQ(6u, ranges_vec.size());
    283   EXPECT_EQ(5, ranges_vec[0]);
    284   EXPECT_EQ(6, ranges_vec[1]);
    285   EXPECT_EQ(10, ranges_vec[2]);
    286   EXPECT_EQ(11, ranges_vec[3]);
    287   EXPECT_EQ(20, ranges_vec[4]);
    288   EXPECT_EQ(21, ranges_vec[5]);
    289 }
    290 
    291 TEST_P(HistogramTest, CustomHistogramTest) {
    292   // A well prepared custom ranges.
    293   std::vector<HistogramBase::Sample> custom_ranges;
    294   custom_ranges.push_back(1);
    295   custom_ranges.push_back(2);
    296 
    297   Histogram* histogram = static_cast<Histogram*>(
    298       CustomHistogram::FactoryGet("TestCustomHistogram1", custom_ranges,
    299                                   HistogramBase::kNoFlags));
    300   const BucketRanges* ranges = histogram->bucket_ranges();
    301   ASSERT_EQ(4u, ranges->size());
    302   EXPECT_EQ(0, ranges->range(0));  // Auto added.
    303   EXPECT_EQ(1, ranges->range(1));
    304   EXPECT_EQ(2, ranges->range(2));
    305   EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges->range(3));  // Auto added.
    306 
    307   // A unordered custom ranges.
    308   custom_ranges.clear();
    309   custom_ranges.push_back(2);
    310   custom_ranges.push_back(1);
    311   histogram = static_cast<Histogram*>(
    312       CustomHistogram::FactoryGet("TestCustomHistogram2", custom_ranges,
    313                                   HistogramBase::kNoFlags));
    314   ranges = histogram->bucket_ranges();
    315   ASSERT_EQ(4u, ranges->size());
    316   EXPECT_EQ(0, ranges->range(0));
    317   EXPECT_EQ(1, ranges->range(1));
    318   EXPECT_EQ(2, ranges->range(2));
    319   EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges->range(3));
    320 
    321   // A custom ranges with duplicated values.
    322   custom_ranges.clear();
    323   custom_ranges.push_back(4);
    324   custom_ranges.push_back(1);
    325   custom_ranges.push_back(4);
    326   histogram = static_cast<Histogram*>(
    327       CustomHistogram::FactoryGet("TestCustomHistogram3", custom_ranges,
    328                                   HistogramBase::kNoFlags));
    329   ranges = histogram->bucket_ranges();
    330   ASSERT_EQ(4u, ranges->size());
    331   EXPECT_EQ(0, ranges->range(0));
    332   EXPECT_EQ(1, ranges->range(1));
    333   EXPECT_EQ(4, ranges->range(2));
    334   EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges->range(3));
    335 }
    336 
    337 TEST_P(HistogramTest, CustomHistogramWithOnly2Buckets) {
    338   // This test exploits the fact that the CustomHistogram can have 2 buckets,
    339   // while the base class Histogram is *supposed* to have at least 3 buckets.
    340   // We should probably change the restriction on the base class (or not inherit
    341   // the base class!).
    342 
    343   std::vector<HistogramBase::Sample> custom_ranges;
    344   custom_ranges.push_back(4);
    345 
    346   Histogram* histogram = static_cast<Histogram*>(
    347       CustomHistogram::FactoryGet("2BucketsCustomHistogram", custom_ranges,
    348                                   HistogramBase::kNoFlags));
    349   const BucketRanges* ranges = histogram->bucket_ranges();
    350   ASSERT_EQ(3u, ranges->size());
    351   EXPECT_EQ(0, ranges->range(0));
    352   EXPECT_EQ(4, ranges->range(1));
    353   EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges->range(2));
    354 }
    355 
    356 TEST_P(HistogramTest, AddCountTest) {
    357   const size_t kBucketCount = 50;
    358   Histogram* histogram = static_cast<Histogram*>(
    359       Histogram::FactoryGet("AddCountHistogram", 10, 100, kBucketCount,
    360                             HistogramBase::kNoFlags));
    361 
    362   histogram->AddCount(20, 15);
    363   histogram->AddCount(30, 14);
    364 
    365   std::unique_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
    366   EXPECT_EQ(29, samples->TotalCount());
    367   EXPECT_EQ(15, samples->GetCount(20));
    368   EXPECT_EQ(14, samples->GetCount(30));
    369 
    370   histogram->AddCount(20, 25);
    371   histogram->AddCount(30, 24);
    372 
    373   std::unique_ptr<HistogramSamples> samples2 = histogram->SnapshotSamples();
    374   EXPECT_EQ(78, samples2->TotalCount());
    375   EXPECT_EQ(40, samples2->GetCount(20));
    376   EXPECT_EQ(38, samples2->GetCount(30));
    377 }
    378 
    379 TEST_P(HistogramTest, AddCount_LargeValuesDontOverflow) {
    380   const size_t kBucketCount = 50;
    381   Histogram* histogram = static_cast<Histogram*>(
    382       Histogram::FactoryGet("AddCountHistogram", 10, 1000000000, kBucketCount,
    383                             HistogramBase::kNoFlags));
    384 
    385   histogram->AddCount(200000000, 15);
    386   histogram->AddCount(300000000, 14);
    387 
    388   std::unique_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
    389   EXPECT_EQ(29, samples->TotalCount());
    390   EXPECT_EQ(15, samples->GetCount(200000000));
    391   EXPECT_EQ(14, samples->GetCount(300000000));
    392 
    393   histogram->AddCount(200000000, 25);
    394   histogram->AddCount(300000000, 24);
    395 
    396   std::unique_ptr<HistogramSamples> samples2 = histogram->SnapshotSamples();
    397   EXPECT_EQ(78, samples2->TotalCount());
    398   EXPECT_EQ(40, samples2->GetCount(200000000));
    399   EXPECT_EQ(38, samples2->GetCount(300000000));
    400   EXPECT_EQ(19400000000LL, samples2->sum());
    401 }
    402 
    403 // Make sure histogram handles out-of-bounds data gracefully.
    404 TEST_P(HistogramTest, BoundsTest) {
    405   const size_t kBucketCount = 50;
    406   Histogram* histogram = static_cast<Histogram*>(
    407       Histogram::FactoryGet("Bounded", 10, 100, kBucketCount,
    408                             HistogramBase::kNoFlags));
    409 
    410   // Put two samples "out of bounds" above and below.
    411   histogram->Add(5);
    412   histogram->Add(-50);
    413 
    414   histogram->Add(100);
    415   histogram->Add(10000);
    416 
    417   // Verify they landed in the underflow, and overflow buckets.
    418   std::unique_ptr<SampleVector> samples = histogram->SnapshotSampleVector();
    419   EXPECT_EQ(2, samples->GetCountAtIndex(0));
    420   EXPECT_EQ(0, samples->GetCountAtIndex(1));
    421   size_t array_size = histogram->bucket_count();
    422   EXPECT_EQ(kBucketCount, array_size);
    423   EXPECT_EQ(0, samples->GetCountAtIndex(array_size - 2));
    424   EXPECT_EQ(2, samples->GetCountAtIndex(array_size - 1));
    425 
    426   std::vector<int> custom_ranges;
    427   custom_ranges.push_back(10);
    428   custom_ranges.push_back(50);
    429   custom_ranges.push_back(100);
    430   Histogram* test_custom_histogram = static_cast<Histogram*>(
    431       CustomHistogram::FactoryGet("TestCustomRangeBoundedHistogram",
    432                                   custom_ranges, HistogramBase::kNoFlags));
    433 
    434   // Put two samples "out of bounds" above and below.
    435   test_custom_histogram->Add(5);
    436   test_custom_histogram->Add(-50);
    437   test_custom_histogram->Add(100);
    438   test_custom_histogram->Add(1000);
    439   test_custom_histogram->Add(INT_MAX);
    440 
    441   // Verify they landed in the underflow, and overflow buckets.
    442   std::unique_ptr<SampleVector> custom_samples =
    443       test_custom_histogram->SnapshotSampleVector();
    444   EXPECT_EQ(2, custom_samples->GetCountAtIndex(0));
    445   EXPECT_EQ(0, custom_samples->GetCountAtIndex(1));
    446   size_t bucket_count = test_custom_histogram->bucket_count();
    447   EXPECT_EQ(0, custom_samples->GetCountAtIndex(bucket_count - 2));
    448   EXPECT_EQ(3, custom_samples->GetCountAtIndex(bucket_count - 1));
    449 }
    450 
    451 // Check to be sure samples land as expected is "correct" buckets.
    452 TEST_P(HistogramTest, BucketPlacementTest) {
    453   Histogram* histogram = static_cast<Histogram*>(
    454       Histogram::FactoryGet("Histogram", 1, 64, 8, HistogramBase::kNoFlags));
    455 
    456   // Add i+1 samples to the i'th bucket.
    457   histogram->Add(0);
    458   int power_of_2 = 1;
    459   for (int i = 1; i < 8; i++) {
    460     for (int j = 0; j <= i; j++)
    461       histogram->Add(power_of_2);
    462     power_of_2 *= 2;
    463   }
    464 
    465   // Check to see that the bucket counts reflect our additions.
    466   std::unique_ptr<SampleVector> samples = histogram->SnapshotSampleVector();
    467   for (int i = 0; i < 8; i++)
    468     EXPECT_EQ(i + 1, samples->GetCountAtIndex(i));
    469 }
    470 
    471 TEST_P(HistogramTest, CorruptSampleCounts) {
    472   // The internal code creates histograms via macros and thus keeps static
    473   // pointers to them. If those pointers are to persistent memory which will
    474   // be free'd then any following calls to that code will crash with a
    475   // segmentation violation.
    476   if (use_persistent_histogram_allocator_)
    477     return;
    478 
    479   Histogram* histogram = static_cast<Histogram*>(
    480       Histogram::FactoryGet("Histogram", 1, 64, 8, HistogramBase::kNoFlags));
    481 
    482   // Add some samples.
    483   histogram->Add(20);
    484   histogram->Add(40);
    485 
    486   std::unique_ptr<SampleVector> snapshot = histogram->SnapshotSampleVector();
    487   EXPECT_EQ(HistogramBase::NO_INCONSISTENCIES,
    488             histogram->FindCorruption(*snapshot));
    489   EXPECT_EQ(2, snapshot->redundant_count());
    490   EXPECT_EQ(2, snapshot->TotalCount());
    491 
    492   snapshot->counts_[3] += 100;  // Sample count won't match redundant count.
    493   EXPECT_EQ(HistogramBase::COUNT_LOW_ERROR,
    494             histogram->FindCorruption(*snapshot));
    495   snapshot->counts_[2] -= 200;
    496   EXPECT_EQ(HistogramBase::COUNT_HIGH_ERROR,
    497             histogram->FindCorruption(*snapshot));
    498 
    499   // But we can't spot a corruption if it is compensated for.
    500   snapshot->counts_[1] += 100;
    501   EXPECT_EQ(HistogramBase::NO_INCONSISTENCIES,
    502             histogram->FindCorruption(*snapshot));
    503 }
    504 
    505 TEST_P(HistogramTest, CorruptBucketBounds) {
    506   Histogram* histogram = static_cast<Histogram*>(
    507       Histogram::FactoryGet("Histogram", 1, 64, 8, HistogramBase::kNoFlags));
    508 
    509   std::unique_ptr<HistogramSamples> snapshot = histogram->SnapshotSamples();
    510   EXPECT_EQ(HistogramBase::NO_INCONSISTENCIES,
    511             histogram->FindCorruption(*snapshot));
    512 
    513   BucketRanges* bucket_ranges =
    514       const_cast<BucketRanges*>(histogram->bucket_ranges());
    515   HistogramBase::Sample tmp = bucket_ranges->range(1);
    516   bucket_ranges->set_range(1, bucket_ranges->range(2));
    517   bucket_ranges->set_range(2, tmp);
    518   EXPECT_EQ(
    519       HistogramBase::BUCKET_ORDER_ERROR | HistogramBase::RANGE_CHECKSUM_ERROR,
    520       histogram->FindCorruption(*snapshot));
    521 
    522   bucket_ranges->set_range(2, bucket_ranges->range(1));
    523   bucket_ranges->set_range(1, tmp);
    524   EXPECT_EQ(0U, histogram->FindCorruption(*snapshot));
    525 
    526   // Show that two simple changes don't offset each other
    527   bucket_ranges->set_range(3, bucket_ranges->range(3) + 1);
    528   EXPECT_EQ(HistogramBase::RANGE_CHECKSUM_ERROR,
    529             histogram->FindCorruption(*snapshot));
    530 
    531   bucket_ranges->set_range(4, bucket_ranges->range(4) - 1);
    532   EXPECT_EQ(HistogramBase::RANGE_CHECKSUM_ERROR,
    533             histogram->FindCorruption(*snapshot));
    534 
    535   // Repair histogram so that destructor won't DCHECK().
    536   bucket_ranges->set_range(3, bucket_ranges->range(3) - 1);
    537   bucket_ranges->set_range(4, bucket_ranges->range(4) + 1);
    538 }
    539 
    540 TEST_P(HistogramTest, HistogramSerializeInfo) {
    541   Histogram* histogram = static_cast<Histogram*>(
    542       Histogram::FactoryGet("Histogram", 1, 64, 8,
    543                             HistogramBase::kIPCSerializationSourceFlag));
    544   Pickle pickle;
    545   histogram->SerializeInfo(&pickle);
    546 
    547   PickleIterator iter(pickle);
    548 
    549   int type;
    550   EXPECT_TRUE(iter.ReadInt(&type));
    551   EXPECT_EQ(HISTOGRAM, type);
    552 
    553   std::string name;
    554   EXPECT_TRUE(iter.ReadString(&name));
    555   EXPECT_EQ("Histogram", name);
    556 
    557   int flag;
    558   EXPECT_TRUE(iter.ReadInt(&flag));
    559   EXPECT_EQ(HistogramBase::kIPCSerializationSourceFlag,
    560             flag & ~HistogramBase::kIsPersistent);
    561 
    562   int min;
    563   EXPECT_TRUE(iter.ReadInt(&min));
    564   EXPECT_EQ(1, min);
    565 
    566   int max;
    567   EXPECT_TRUE(iter.ReadInt(&max));
    568   EXPECT_EQ(64, max);
    569 
    570   uint32_t bucket_count;
    571   EXPECT_TRUE(iter.ReadUInt32(&bucket_count));
    572   EXPECT_EQ(8u, bucket_count);
    573 
    574   uint32_t checksum;
    575   EXPECT_TRUE(iter.ReadUInt32(&checksum));
    576   EXPECT_EQ(histogram->bucket_ranges()->checksum(), checksum);
    577 
    578   // No more data in the pickle.
    579   EXPECT_FALSE(iter.SkipBytes(1));
    580 }
    581 
    582 TEST_P(HistogramTest, CustomHistogramSerializeInfo) {
    583   std::vector<int> custom_ranges;
    584   custom_ranges.push_back(10);
    585   custom_ranges.push_back(100);
    586 
    587   HistogramBase* custom_histogram = CustomHistogram::FactoryGet(
    588       "TestCustomRangeBoundedHistogram",
    589       custom_ranges,
    590       HistogramBase::kNoFlags);
    591   Pickle pickle;
    592   custom_histogram->SerializeInfo(&pickle);
    593 
    594   // Validate the pickle.
    595   PickleIterator iter(pickle);
    596 
    597   int i;
    598   std::string s;
    599   uint32_t bucket_count;
    600   uint32_t ui32;
    601   EXPECT_TRUE(iter.ReadInt(&i) && iter.ReadString(&s) && iter.ReadInt(&i) &&
    602               iter.ReadInt(&i) && iter.ReadInt(&i) &&
    603               iter.ReadUInt32(&bucket_count) && iter.ReadUInt32(&ui32));
    604   EXPECT_EQ(3u, bucket_count);
    605 
    606   int range;
    607   EXPECT_TRUE(iter.ReadInt(&range));
    608   EXPECT_EQ(10, range);
    609   EXPECT_TRUE(iter.ReadInt(&range));
    610   EXPECT_EQ(100, range);
    611 
    612   // No more data in the pickle.
    613   EXPECT_FALSE(iter.SkipBytes(1));
    614 }
    615 
    616 TEST_P(HistogramTest, BadConstruction) {
    617   HistogramBase* histogram = Histogram::FactoryGet(
    618       "BadConstruction", 0, 100, 8, HistogramBase::kNoFlags);
    619   EXPECT_TRUE(histogram->HasConstructionArguments(1, 100, 8));
    620 
    621   // Try to get the same histogram name with different arguments.
    622   HistogramBase* bad_histogram = Histogram::FactoryGet(
    623       "BadConstruction", 0, 100, 7, HistogramBase::kNoFlags);
    624   EXPECT_EQ(NULL, bad_histogram);
    625   bad_histogram = Histogram::FactoryGet(
    626       "BadConstruction", 0, 99, 8, HistogramBase::kNoFlags);
    627   EXPECT_EQ(NULL, bad_histogram);
    628 
    629   HistogramBase* linear_histogram = LinearHistogram::FactoryGet(
    630       "BadConstructionLinear", 0, 100, 8, HistogramBase::kNoFlags);
    631   EXPECT_TRUE(linear_histogram->HasConstructionArguments(1, 100, 8));
    632 
    633   // Try to get the same histogram name with different arguments.
    634   bad_histogram = LinearHistogram::FactoryGet(
    635       "BadConstructionLinear", 0, 100, 7, HistogramBase::kNoFlags);
    636   EXPECT_EQ(NULL, bad_histogram);
    637   bad_histogram = LinearHistogram::FactoryGet(
    638       "BadConstructionLinear", 10, 100, 8, HistogramBase::kNoFlags);
    639   EXPECT_EQ(NULL, bad_histogram);
    640 }
    641 
    642 TEST_P(HistogramTest, FactoryTime) {
    643   const int kTestCreateCount = 1 << 14;  // Must be power-of-2.
    644   const int kTestLookupCount = 100000;
    645   const int kTestAddCount = 1000000;
    646 
    647   // Create all histogram names in advance for accurate timing below.
    648   std::vector<std::string> histogram_names;
    649   for (int i = 0; i < kTestCreateCount; ++i) {
    650     histogram_names.push_back(
    651         StringPrintf("TestHistogram.%d", i % kTestCreateCount));
    652   }
    653 
    654   // Calculate cost of creating histograms.
    655   TimeTicks create_start = TimeTicks::Now();
    656   for (int i = 0; i < kTestCreateCount; ++i) {
    657     Histogram::FactoryGet(histogram_names[i], 1, 100, 10,
    658                           HistogramBase::kNoFlags);
    659   }
    660   TimeDelta create_ticks = TimeTicks::Now() - create_start;
    661   int64_t create_ms = create_ticks.InMilliseconds();
    662 
    663   VLOG(1) << kTestCreateCount << " histogram creations took " << create_ms
    664           << "ms or about "
    665           << (create_ms * 1000000) / kTestCreateCount
    666           << "ns each.";
    667 
    668   // Calculate cost of looking up existing histograms.
    669   TimeTicks lookup_start = TimeTicks::Now();
    670   for (int i = 0; i < kTestLookupCount; ++i) {
    671     // 6007 is co-prime with kTestCreateCount and so will do lookups in an
    672     // order less likely to be cacheable (but still hit them all) should the
    673     // underlying storage use the exact histogram name as the key.
    674     const int i_mult = 6007;
    675     static_assert(i_mult < INT_MAX / kTestCreateCount, "Multiplier too big");
    676     int index = (i * i_mult) & (kTestCreateCount - 1);
    677     Histogram::FactoryGet(histogram_names[index], 1, 100, 10,
    678                           HistogramBase::kNoFlags);
    679   }
    680   TimeDelta lookup_ticks = TimeTicks::Now() - lookup_start;
    681   int64_t lookup_ms = lookup_ticks.InMilliseconds();
    682 
    683   VLOG(1) << kTestLookupCount << " histogram lookups took " << lookup_ms
    684           << "ms or about "
    685           << (lookup_ms * 1000000) / kTestLookupCount
    686           << "ns each.";
    687 
    688   // Calculate cost of accessing histograms.
    689   HistogramBase* histogram = Histogram::FactoryGet(
    690       histogram_names[0], 1, 100, 10, HistogramBase::kNoFlags);
    691   ASSERT_TRUE(histogram);
    692   TimeTicks add_start = TimeTicks::Now();
    693   for (int i = 0; i < kTestAddCount; ++i)
    694     histogram->Add(i & 127);
    695   TimeDelta add_ticks = TimeTicks::Now() - add_start;
    696   int64_t add_ms = add_ticks.InMilliseconds();
    697 
    698   VLOG(1) << kTestAddCount << " histogram adds took " << add_ms
    699           << "ms or about "
    700           << (add_ms * 1000000) / kTestAddCount
    701           << "ns each.";
    702 }
    703 
    704 #if GTEST_HAS_DEATH_TEST
    705 // For Histogram, LinearHistogram and CustomHistogram, the minimum for a
    706 // declared range is 1, while the maximum is (HistogramBase::kSampleType_MAX -
    707 // 1). But we accept ranges exceeding those limits, and silently clamped to
    708 // those limits. This is for backwards compatibility.
    709 TEST(HistogramDeathTest, BadRangesTest) {
    710   HistogramBase* histogram = Histogram::FactoryGet(
    711       "BadRanges", 0, HistogramBase::kSampleType_MAX, 8,
    712       HistogramBase::kNoFlags);
    713   EXPECT_TRUE(
    714       histogram->HasConstructionArguments(
    715           1, HistogramBase::kSampleType_MAX - 1, 8));
    716 
    717   HistogramBase* linear_histogram = LinearHistogram::FactoryGet(
    718       "BadRangesLinear", 0, HistogramBase::kSampleType_MAX, 8,
    719       HistogramBase::kNoFlags);
    720   EXPECT_TRUE(
    721       linear_histogram->HasConstructionArguments(
    722           1, HistogramBase::kSampleType_MAX - 1, 8));
    723 
    724   std::vector<int> custom_ranges;
    725   custom_ranges.push_back(0);
    726   custom_ranges.push_back(5);
    727   Histogram* custom_histogram = static_cast<Histogram*>(
    728       CustomHistogram::FactoryGet(
    729           "BadRangesCustom", custom_ranges, HistogramBase::kNoFlags));
    730   const BucketRanges* ranges = custom_histogram->bucket_ranges();
    731   ASSERT_EQ(3u, ranges->size());
    732   EXPECT_EQ(0, ranges->range(0));
    733   EXPECT_EQ(5, ranges->range(1));
    734   EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges->range(2));
    735 
    736   // CustomHistogram does not accepts kSampleType_MAX as range.
    737   custom_ranges.push_back(HistogramBase::kSampleType_MAX);
    738   EXPECT_DEATH(CustomHistogram::FactoryGet("BadRangesCustom2", custom_ranges,
    739                                            HistogramBase::kNoFlags),
    740                "");
    741 
    742   // CustomHistogram needs at least 1 valid range.
    743   custom_ranges.clear();
    744   custom_ranges.push_back(0);
    745   EXPECT_DEATH(CustomHistogram::FactoryGet("BadRangesCustom3", custom_ranges,
    746                                            HistogramBase::kNoFlags),
    747                "");
    748 }
    749 #endif
    750 
    751 }  // namespace base
    752