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 <vector>
      6 
      7 #include "base/metrics/histogram.h"
      8 #include "base/metrics/histogram_base.h"
      9 #include "base/metrics/sample_vector.h"
     10 #include "base/metrics/sparse_histogram.h"
     11 #include "base/metrics/statistics_recorder.h"
     12 #include "base/pickle.h"
     13 #include "testing/gtest/include/gtest/gtest.h"
     14 
     15 namespace base {
     16 
     17 class HistogramBaseTest : public testing::Test {
     18  protected:
     19   HistogramBaseTest() {
     20     // Each test will have a clean state (no Histogram / BucketRanges
     21     // registered).
     22     ResetStatisticsRecorder();
     23   }
     24 
     25   ~HistogramBaseTest() override = default;
     26 
     27   void ResetStatisticsRecorder() {
     28     // It is necessary to fully destruct any existing StatisticsRecorder
     29     // before creating a new one.
     30     statistics_recorder_.reset();
     31     statistics_recorder_ = StatisticsRecorder::CreateTemporaryForTesting();
     32   }
     33 
     34  private:
     35   std::unique_ptr<StatisticsRecorder> statistics_recorder_;
     36 
     37   DISALLOW_COPY_AND_ASSIGN(HistogramBaseTest);
     38 };
     39 
     40 TEST_F(HistogramBaseTest, DeserializeHistogram) {
     41   HistogramBase* histogram = Histogram::FactoryGet(
     42       "TestHistogram", 1, 1000, 10,
     43       (HistogramBase::kUmaTargetedHistogramFlag |
     44       HistogramBase::kIPCSerializationSourceFlag));
     45 
     46   Pickle pickle;
     47   histogram->SerializeInfo(&pickle);
     48 
     49   PickleIterator iter(pickle);
     50   HistogramBase* deserialized = DeserializeHistogramInfo(&iter);
     51   EXPECT_EQ(histogram, deserialized);
     52 
     53   ResetStatisticsRecorder();
     54 
     55   PickleIterator iter2(pickle);
     56   deserialized = DeserializeHistogramInfo(&iter2);
     57   EXPECT_TRUE(deserialized);
     58   EXPECT_NE(histogram, deserialized);
     59   EXPECT_EQ("TestHistogram", StringPiece(deserialized->histogram_name()));
     60   EXPECT_TRUE(deserialized->HasConstructionArguments(1, 1000, 10));
     61 
     62   // kIPCSerializationSourceFlag will be cleared.
     63   EXPECT_EQ(HistogramBase::kUmaTargetedHistogramFlag, deserialized->flags());
     64 }
     65 
     66 TEST_F(HistogramBaseTest, DeserializeLinearHistogram) {
     67   HistogramBase* histogram = LinearHistogram::FactoryGet(
     68       "TestHistogram", 1, 1000, 10,
     69       HistogramBase::kIPCSerializationSourceFlag);
     70 
     71   Pickle pickle;
     72   histogram->SerializeInfo(&pickle);
     73 
     74   PickleIterator iter(pickle);
     75   HistogramBase* deserialized = DeserializeHistogramInfo(&iter);
     76   EXPECT_EQ(histogram, deserialized);
     77 
     78   ResetStatisticsRecorder();
     79 
     80   PickleIterator iter2(pickle);
     81   deserialized = DeserializeHistogramInfo(&iter2);
     82   EXPECT_TRUE(deserialized);
     83   EXPECT_NE(histogram, deserialized);
     84   EXPECT_EQ("TestHistogram", StringPiece(deserialized->histogram_name()));
     85   EXPECT_TRUE(deserialized->HasConstructionArguments(1, 1000, 10));
     86   EXPECT_EQ(0, deserialized->flags());
     87 }
     88 
     89 TEST_F(HistogramBaseTest, DeserializeBooleanHistogram) {
     90   HistogramBase* histogram = BooleanHistogram::FactoryGet(
     91       "TestHistogram", HistogramBase::kIPCSerializationSourceFlag);
     92 
     93   Pickle pickle;
     94   histogram->SerializeInfo(&pickle);
     95 
     96   PickleIterator iter(pickle);
     97   HistogramBase* deserialized = DeserializeHistogramInfo(&iter);
     98   EXPECT_EQ(histogram, deserialized);
     99 
    100   ResetStatisticsRecorder();
    101 
    102   PickleIterator iter2(pickle);
    103   deserialized = DeserializeHistogramInfo(&iter2);
    104   EXPECT_TRUE(deserialized);
    105   EXPECT_NE(histogram, deserialized);
    106   EXPECT_EQ("TestHistogram", StringPiece(deserialized->histogram_name()));
    107   EXPECT_TRUE(deserialized->HasConstructionArguments(1, 2, 3));
    108   EXPECT_EQ(0, deserialized->flags());
    109 }
    110 
    111 TEST_F(HistogramBaseTest, DeserializeCustomHistogram) {
    112   std::vector<HistogramBase::Sample> ranges;
    113   ranges.push_back(13);
    114   ranges.push_back(5);
    115   ranges.push_back(9);
    116 
    117   HistogramBase* histogram = CustomHistogram::FactoryGet(
    118       "TestHistogram", ranges, HistogramBase::kIPCSerializationSourceFlag);
    119 
    120   Pickle pickle;
    121   histogram->SerializeInfo(&pickle);
    122 
    123   PickleIterator iter(pickle);
    124   HistogramBase* deserialized = DeserializeHistogramInfo(&iter);
    125   EXPECT_EQ(histogram, deserialized);
    126 
    127   ResetStatisticsRecorder();
    128 
    129   PickleIterator iter2(pickle);
    130   deserialized = DeserializeHistogramInfo(&iter2);
    131   EXPECT_TRUE(deserialized);
    132   EXPECT_NE(histogram, deserialized);
    133   EXPECT_EQ("TestHistogram", StringPiece(deserialized->histogram_name()));
    134   EXPECT_TRUE(deserialized->HasConstructionArguments(5, 13, 4));
    135   EXPECT_EQ(0, deserialized->flags());
    136 }
    137 
    138 TEST_F(HistogramBaseTest, DeserializeSparseHistogram) {
    139   HistogramBase* histogram = SparseHistogram::FactoryGet(
    140       "TestHistogram", HistogramBase::kIPCSerializationSourceFlag);
    141 
    142   Pickle pickle;
    143   histogram->SerializeInfo(&pickle);
    144 
    145   PickleIterator iter(pickle);
    146   HistogramBase* deserialized = DeserializeHistogramInfo(&iter);
    147   EXPECT_EQ(histogram, deserialized);
    148 
    149   ResetStatisticsRecorder();
    150 
    151   PickleIterator iter2(pickle);
    152   deserialized = DeserializeHistogramInfo(&iter2);
    153   EXPECT_TRUE(deserialized);
    154   EXPECT_NE(histogram, deserialized);
    155   EXPECT_EQ("TestHistogram", StringPiece(deserialized->histogram_name()));
    156   EXPECT_EQ(0, deserialized->flags());
    157 }
    158 
    159 TEST_F(HistogramBaseTest, AddKilo) {
    160   HistogramBase* histogram =
    161       LinearHistogram::FactoryGet("TestAddKiloHistogram", 1, 1000, 100, 0);
    162 
    163   histogram->AddKilo(100, 1000);
    164   histogram->AddKilo(200, 2000);
    165   histogram->AddKilo(300, 1500);
    166 
    167   std::unique_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
    168   EXPECT_EQ(1, samples->GetCount(100));
    169   EXPECT_EQ(2, samples->GetCount(200));
    170   EXPECT_LE(1, samples->GetCount(300));
    171   EXPECT_GE(2, samples->GetCount(300));
    172 }
    173 
    174 TEST_F(HistogramBaseTest, AddKiB) {
    175   HistogramBase* histogram =
    176       LinearHistogram::FactoryGet("TestAddKiBHistogram", 1, 1000, 100, 0);
    177 
    178   histogram->AddKiB(100, 1024);
    179   histogram->AddKiB(200, 2048);
    180   histogram->AddKiB(300, 1536);
    181 
    182   std::unique_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
    183   EXPECT_EQ(1, samples->GetCount(100));
    184   EXPECT_EQ(2, samples->GetCount(200));
    185   EXPECT_LE(1, samples->GetCount(300));
    186   EXPECT_GE(2, samples->GetCount(300));
    187 }
    188 
    189 TEST_F(HistogramBaseTest, AddTimeMillisecondsGranularityOverflow) {
    190   const HistogramBase::Sample sample_max =
    191       std::numeric_limits<HistogramBase::Sample>::max() / 2;
    192   HistogramBase* histogram = LinearHistogram::FactoryGet(
    193       "TestAddTimeMillisecondsGranularity1", 1, sample_max, 100, 0);
    194   int64_t large_positive = std::numeric_limits<int64_t>::max();
    195   // |add_count| is the number of large values that have been added to the
    196   // histogram. We consider a number to be 'large' if it cannot be represented
    197   // in a HistogramBase::Sample.
    198   int add_count = 0;
    199   while (large_positive > std::numeric_limits<HistogramBase::Sample>::max()) {
    200     // Add the TimeDelta corresponding to |large_positive| milliseconds to the
    201     // histogram.
    202     histogram->AddTimeMillisecondsGranularity(
    203         TimeDelta::FromMilliseconds(large_positive));
    204     ++add_count;
    205     // Reduce the value of |large_positive|. The choice of 7 here is
    206     // arbitrary.
    207     large_positive /= 7;
    208   }
    209   std::unique_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
    210   // All of the reported values must have gone into the max overflow bucket.
    211   EXPECT_EQ(add_count, samples->GetCount(sample_max));
    212 
    213   // We now perform the analoguous operations, now with negative values with a
    214   // large absolute value.
    215   histogram = LinearHistogram::FactoryGet("TestAddTimeMillisecondsGranularity2",
    216                                           1, sample_max, 100, 0);
    217   int64_t large_negative = std::numeric_limits<int64_t>::min();
    218   add_count = 0;
    219   while (large_negative < std::numeric_limits<HistogramBase::Sample>::min()) {
    220     histogram->AddTimeMillisecondsGranularity(
    221         TimeDelta::FromMilliseconds(large_negative));
    222     ++add_count;
    223     large_negative /= 7;
    224   }
    225   samples = histogram->SnapshotSamples();
    226   // All of the reported values must have gone into the min overflow bucket.
    227   EXPECT_EQ(add_count, samples->GetCount(0));
    228 }
    229 
    230 TEST_F(HistogramBaseTest, AddTimeMicrosecondsGranularityOverflow) {
    231   // Nothing to test if we don't have a high resolution clock.
    232   if (!TimeTicks::IsHighResolution())
    233     return;
    234 
    235   const HistogramBase::Sample sample_max =
    236       std::numeric_limits<HistogramBase::Sample>::max() / 2;
    237   HistogramBase* histogram = LinearHistogram::FactoryGet(
    238       "TestAddTimeMicrosecondsGranularity1", 1, sample_max, 100, 0);
    239   int64_t large_positive = std::numeric_limits<int64_t>::max();
    240   // |add_count| is the number of large values that have been added to the
    241   // histogram. We consider a number to be 'large' if it cannot be represented
    242   // in a HistogramBase::Sample.
    243   int add_count = 0;
    244   while (large_positive > std::numeric_limits<HistogramBase::Sample>::max()) {
    245     // Add the TimeDelta corresponding to |large_positive| microseconds to the
    246     // histogram.
    247     histogram->AddTimeMicrosecondsGranularity(
    248         TimeDelta::FromMicroseconds(large_positive));
    249     ++add_count;
    250     // Reduce the value of |large_positive|. The choice of 7 here is
    251     // arbitrary.
    252     large_positive /= 7;
    253   }
    254   std::unique_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
    255   // All of the reported values must have gone into the max overflow bucket.
    256   EXPECT_EQ(add_count, samples->GetCount(sample_max));
    257 
    258   // We now perform the analoguous operations, now with negative values with a
    259   // large absolute value.
    260   histogram = LinearHistogram::FactoryGet("TestAddTimeMicrosecondsGranularity2",
    261                                           1, sample_max, 100, 0);
    262   int64_t large_negative = std::numeric_limits<int64_t>::min();
    263   add_count = 0;
    264   while (large_negative < std::numeric_limits<HistogramBase::Sample>::min()) {
    265     histogram->AddTimeMicrosecondsGranularity(
    266         TimeDelta::FromMicroseconds(large_negative));
    267     ++add_count;
    268     large_negative /= 7;
    269   }
    270   samples = histogram->SnapshotSamples();
    271   // All of the reported values must have gone into the min overflow bucket.
    272   EXPECT_EQ(add_count, samples->GetCount(0));
    273 }
    274 
    275 }  // namespace base
    276