Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2006-2008 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 // Test of Histogram class
      6 
      7 #include "base/histogram.h"
      8 #include "base/string_util.h"
      9 #include "base/time.h"
     10 #include "testing/gtest/include/gtest/gtest.h"
     11 
     12 using base::TimeDelta;
     13 
     14 namespace {
     15 
     16 class HistogramTest : public testing::Test {
     17 };
     18 
     19 // Check for basic syntax and use.
     20 TEST(HistogramTest, StartupShutdownTest) {
     21   // Try basic construction
     22   scoped_refptr<Histogram> histogram = Histogram::FactoryGet(
     23       "TestHistogram", 1, 1000, 10, Histogram::kNoFlags);
     24   scoped_refptr<Histogram> histogram1 = Histogram::FactoryGet(
     25       "Test1Histogram", 1, 1000, 10, Histogram::kNoFlags);
     26 
     27   scoped_refptr<Histogram> linear_histogram = LinearHistogram::FactoryGet(
     28       "TestLinearHistogram", 1, 1000, 10, Histogram::kNoFlags);
     29   scoped_refptr<Histogram> linear_histogram1 = LinearHistogram::FactoryGet(
     30       "Test1LinearHistogram", 1, 1000, 10, Histogram::kNoFlags);
     31 
     32   // Use standard macros (but with fixed samples)
     33   HISTOGRAM_TIMES("Test2Histogram", TimeDelta::FromDays(1));
     34   HISTOGRAM_COUNTS("Test3Histogram", 30);
     35 
     36   DHISTOGRAM_TIMES("Test4Histogram", TimeDelta::FromDays(1));
     37   DHISTOGRAM_COUNTS("Test5Histogram", 30);
     38 
     39   HISTOGRAM_ENUMERATION("Test6Histogram", 129, 130);
     40 
     41   // Try to construct samples.
     42   Histogram::SampleSet sample1;
     43   Histogram::SampleSet sample2;
     44 
     45   // Use copy constructor of SampleSet
     46   sample1 = sample2;
     47   Histogram::SampleSet sample3(sample1);
     48 
     49   // Finally test a statistics recorder, without really using it.
     50   StatisticsRecorder recorder;
     51 }
     52 
     53 // Repeat with a recorder present to register with.
     54 TEST(HistogramTest, RecordedStartupTest) {
     55   // Test a statistics recorder, by letting histograms register.
     56   StatisticsRecorder recorder;  // This initializes the global state.
     57 
     58   StatisticsRecorder::Histograms histograms;
     59   EXPECT_EQ(0U, histograms.size());
     60   StatisticsRecorder::GetHistograms(&histograms);  // Load up lists
     61   EXPECT_EQ(0U, histograms.size());
     62 
     63   // Try basic construction
     64   scoped_refptr<Histogram> histogram = Histogram::FactoryGet(
     65       "TestHistogram", 1, 1000, 10, Histogram::kNoFlags);
     66   histograms.clear();
     67   StatisticsRecorder::GetHistograms(&histograms);  // Load up lists
     68   EXPECT_EQ(1U, histograms.size());
     69   scoped_refptr<Histogram> histogram1 = Histogram::FactoryGet(
     70       "Test1Histogram", 1, 1000, 10, Histogram::kNoFlags);
     71   histograms.clear();
     72   StatisticsRecorder::GetHistograms(&histograms);  // Load up lists
     73   EXPECT_EQ(2U, histograms.size());
     74 
     75   scoped_refptr<Histogram> linear_histogram = LinearHistogram::FactoryGet(
     76       "TestLinearHistogram", 1, 1000, 10, Histogram::kNoFlags);
     77   scoped_refptr<Histogram> linear_histogram1 = LinearHistogram::FactoryGet(
     78       "Test1LinearHistogram", 1, 1000, 10, Histogram::kNoFlags);
     79   histograms.clear();
     80   StatisticsRecorder::GetHistograms(&histograms);  // Load up lists
     81   EXPECT_EQ(4U, histograms.size());
     82 
     83   // Use standard macros (but with fixed samples)
     84   HISTOGRAM_TIMES("Test2Histogram", TimeDelta::FromDays(1));
     85   HISTOGRAM_COUNTS("Test3Histogram", 30);
     86   histograms.clear();
     87   StatisticsRecorder::GetHistograms(&histograms);  // Load up lists
     88   EXPECT_EQ(6U, histograms.size());
     89 
     90   HISTOGRAM_ENUMERATION("TestEnumerationHistogram", 20, 200);
     91   histograms.clear();
     92   StatisticsRecorder::GetHistograms(&histograms);  // Load up lists
     93   EXPECT_EQ(7U, histograms.size());
     94 
     95   DHISTOGRAM_TIMES("Test4Histogram", TimeDelta::FromDays(1));
     96   DHISTOGRAM_COUNTS("Test5Histogram", 30);
     97   histograms.clear();
     98   StatisticsRecorder::GetHistograms(&histograms);  // Load up lists
     99 #ifndef NDEBUG
    100   EXPECT_EQ(9U, histograms.size());
    101 #else
    102   EXPECT_EQ(7U, histograms.size());
    103 #endif
    104 }
    105 
    106 TEST(HistogramTest, RangeTest) {
    107   StatisticsRecorder recorder;
    108   StatisticsRecorder::Histograms histograms;
    109 
    110   recorder.GetHistograms(&histograms);
    111   EXPECT_EQ(0U, histograms.size());
    112 
    113   scoped_refptr<Histogram> histogram = Histogram::FactoryGet(
    114       "Histogram", 1, 64, 8, Histogram::kNoFlags);  // As per header file.
    115   // Check that we got a nice exponential when there was enough rooom.
    116   EXPECT_EQ(0, histogram->ranges(0));
    117   int power_of_2 = 1;
    118   for (int i = 1; i < 8; i++) {
    119     EXPECT_EQ(power_of_2, histogram->ranges(i));
    120     power_of_2 *= 2;
    121   }
    122   EXPECT_EQ(INT_MAX, histogram->ranges(8));
    123 
    124   scoped_refptr<Histogram> short_histogram = Histogram::FactoryGet(
    125       "Histogram Shortened", 1, 7, 8, Histogram::kNoFlags);
    126   // Check that when the number of buckets is short, we get a linear histogram
    127   // for lack of space to do otherwise.
    128   for (int i = 0; i < 8; i++)
    129     EXPECT_EQ(i, short_histogram->ranges(i));
    130   EXPECT_EQ(INT_MAX, short_histogram->ranges(8));
    131 
    132   scoped_refptr<Histogram> linear_histogram = LinearHistogram::FactoryGet(
    133       "Linear", 1, 7, 8, Histogram::kNoFlags);
    134   // We also get a nice linear set of bucket ranges when we ask for it
    135   for (int i = 0; i < 8; i++)
    136     EXPECT_EQ(i, linear_histogram->ranges(i));
    137   EXPECT_EQ(INT_MAX, linear_histogram->ranges(8));
    138 
    139   scoped_refptr<Histogram> linear_broad_histogram = LinearHistogram::FactoryGet(
    140       "Linear widened", 2, 14, 8, Histogram::kNoFlags);
    141   // ...but when the list has more space, then the ranges naturally spread out.
    142   for (int i = 0; i < 8; i++)
    143     EXPECT_EQ(2 * i, linear_broad_histogram->ranges(i));
    144   EXPECT_EQ(INT_MAX, linear_broad_histogram->ranges(8));
    145 
    146   scoped_refptr<Histogram> transitioning_histogram =
    147       Histogram::FactoryGet("LinearAndExponential", 1, 32, 15,
    148                                       Histogram::kNoFlags);
    149   // When space is a little tight, we transition from linear to exponential.
    150   EXPECT_EQ(0, transitioning_histogram->ranges(0));
    151   EXPECT_EQ(1, transitioning_histogram->ranges(1));
    152   EXPECT_EQ(2, transitioning_histogram->ranges(2));
    153   EXPECT_EQ(3, transitioning_histogram->ranges(3));
    154   EXPECT_EQ(4, transitioning_histogram->ranges(4));
    155   EXPECT_EQ(5, transitioning_histogram->ranges(5));
    156   EXPECT_EQ(6, transitioning_histogram->ranges(6));
    157   EXPECT_EQ(7, transitioning_histogram->ranges(7));
    158   EXPECT_EQ(9, transitioning_histogram->ranges(8));
    159   EXPECT_EQ(11, transitioning_histogram->ranges(9));
    160   EXPECT_EQ(14, transitioning_histogram->ranges(10));
    161   EXPECT_EQ(17, transitioning_histogram->ranges(11));
    162   EXPECT_EQ(21, transitioning_histogram->ranges(12));
    163   EXPECT_EQ(26, transitioning_histogram->ranges(13));
    164   EXPECT_EQ(32, transitioning_histogram->ranges(14));
    165   EXPECT_EQ(INT_MAX, transitioning_histogram->ranges(15));
    166 
    167   recorder.GetHistograms(&histograms);
    168   EXPECT_EQ(5U, histograms.size());
    169 }
    170 
    171 // Make sure histogram handles out-of-bounds data gracefully.
    172 TEST(HistogramTest, BoundsTest) {
    173   const size_t kBucketCount = 50;
    174   scoped_refptr<Histogram> histogram = Histogram::FactoryGet(
    175       "Bounded", 10, 100, kBucketCount, Histogram::kNoFlags);
    176 
    177   // Put two samples "out of bounds" above and below.
    178   histogram->Add(5);
    179   histogram->Add(-50);
    180 
    181   histogram->Add(100);
    182   histogram->Add(10000);
    183 
    184   // Verify they landed in the underflow, and overflow buckets.
    185   Histogram::SampleSet sample;
    186   histogram->SnapshotSample(&sample);
    187   EXPECT_EQ(2, sample.counts(0));
    188   EXPECT_EQ(0, sample.counts(1));
    189   size_t array_size = histogram->bucket_count();
    190   EXPECT_EQ(kBucketCount, array_size);
    191   EXPECT_EQ(0, sample.counts(array_size - 2));
    192   EXPECT_EQ(2, sample.counts(array_size - 1));
    193 }
    194 
    195 // Check to be sure samples land as expected is "correct" buckets.
    196 TEST(HistogramTest, BucketPlacementTest) {
    197   scoped_refptr<Histogram> histogram = Histogram::FactoryGet(
    198       "Histogram", 1, 64, 8, Histogram::kNoFlags);  // As per header file.
    199 
    200   // Check that we got a nice exponential since there was enough rooom.
    201   EXPECT_EQ(0, histogram->ranges(0));
    202   int power_of_2 = 1;
    203   for (int i = 1; i < 8; i++) {
    204     EXPECT_EQ(power_of_2, histogram->ranges(i));
    205     power_of_2 *= 2;
    206   }
    207   EXPECT_EQ(INT_MAX, histogram->ranges(8));
    208 
    209   // Add i+1 samples to the i'th bucket.
    210   histogram->Add(0);
    211   power_of_2 = 1;
    212   for (int i = 1; i < 8; i++) {
    213     for (int j = 0; j <= i; j++)
    214       histogram->Add(power_of_2);
    215     power_of_2 *= 2;
    216   }
    217   // Leave overflow bucket empty.
    218 
    219   // Check to see that the bucket counts reflect our additions.
    220   Histogram::SampleSet sample;
    221   histogram->SnapshotSample(&sample);
    222   EXPECT_EQ(INT_MAX, histogram->ranges(8));
    223   for (int i = 0; i < 8; i++)
    224     EXPECT_EQ(i + 1, sample.counts(i));
    225 }
    226 
    227 
    228 }  // namespace
    229