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/sample_vector.h"
      6 
      7 #include <limits.h>
      8 #include <stddef.h>
      9 
     10 #include <memory>
     11 #include <vector>
     12 
     13 #include "base/metrics/bucket_ranges.h"
     14 #include "base/metrics/histogram.h"
     15 #include "base/test/gtest_util.h"
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 
     18 namespace base {
     19 namespace {
     20 
     21 TEST(SampleVectorTest, AccumulateTest) {
     22   // Custom buckets: [1, 5) [5, 10)
     23   BucketRanges ranges(3);
     24   ranges.set_range(0, 1);
     25   ranges.set_range(1, 5);
     26   ranges.set_range(2, 10);
     27   SampleVector samples(1, &ranges);
     28 
     29   samples.Accumulate(1, 200);
     30   samples.Accumulate(2, -300);
     31   EXPECT_EQ(-100, samples.GetCountAtIndex(0));
     32 
     33   samples.Accumulate(5, 200);
     34   EXPECT_EQ(200, samples.GetCountAtIndex(1));
     35 
     36   EXPECT_EQ(600, samples.sum());
     37   EXPECT_EQ(100, samples.redundant_count());
     38   EXPECT_EQ(samples.TotalCount(), samples.redundant_count());
     39 
     40   samples.Accumulate(5, -100);
     41   EXPECT_EQ(100, samples.GetCountAtIndex(1));
     42 
     43   EXPECT_EQ(100, samples.sum());
     44   EXPECT_EQ(0, samples.redundant_count());
     45   EXPECT_EQ(samples.TotalCount(), samples.redundant_count());
     46 }
     47 
     48 TEST(SampleVectorTest, Accumulate_LargeValuesDontOverflow) {
     49   // Custom buckets: [1, 250000000) [250000000, 500000000)
     50   BucketRanges ranges(3);
     51   ranges.set_range(0, 1);
     52   ranges.set_range(1, 250000000);
     53   ranges.set_range(2, 500000000);
     54   SampleVector samples(1, &ranges);
     55 
     56   samples.Accumulate(240000000, 200);
     57   samples.Accumulate(249999999, -300);
     58   EXPECT_EQ(-100, samples.GetCountAtIndex(0));
     59 
     60   samples.Accumulate(250000000, 200);
     61   EXPECT_EQ(200, samples.GetCountAtIndex(1));
     62 
     63   EXPECT_EQ(23000000300LL, samples.sum());
     64   EXPECT_EQ(100, samples.redundant_count());
     65   EXPECT_EQ(samples.TotalCount(), samples.redundant_count());
     66 
     67   samples.Accumulate(250000000, -100);
     68   EXPECT_EQ(100, samples.GetCountAtIndex(1));
     69 
     70   EXPECT_EQ(-1999999700LL, samples.sum());
     71   EXPECT_EQ(0, samples.redundant_count());
     72   EXPECT_EQ(samples.TotalCount(), samples.redundant_count());
     73 }
     74 
     75 TEST(SampleVectorTest, AddSubtractTest) {
     76   // Custom buckets: [0, 1) [1, 2) [2, 3) [3, INT_MAX)
     77   BucketRanges ranges(5);
     78   ranges.set_range(0, 0);
     79   ranges.set_range(1, 1);
     80   ranges.set_range(2, 2);
     81   ranges.set_range(3, 3);
     82   ranges.set_range(4, INT_MAX);
     83 
     84   SampleVector samples1(1, &ranges);
     85   samples1.Accumulate(0, 100);
     86   samples1.Accumulate(2, 100);
     87   samples1.Accumulate(4, 100);
     88   EXPECT_EQ(600, samples1.sum());
     89   EXPECT_EQ(300, samples1.TotalCount());
     90   EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount());
     91 
     92   SampleVector samples2(2, &ranges);
     93   samples2.Accumulate(1, 200);
     94   samples2.Accumulate(2, 200);
     95   samples2.Accumulate(4, 200);
     96   EXPECT_EQ(1400, samples2.sum());
     97   EXPECT_EQ(600, samples2.TotalCount());
     98   EXPECT_EQ(samples2.redundant_count(), samples2.TotalCount());
     99 
    100   samples1.Add(samples2);
    101   EXPECT_EQ(100, samples1.GetCountAtIndex(0));
    102   EXPECT_EQ(200, samples1.GetCountAtIndex(1));
    103   EXPECT_EQ(300, samples1.GetCountAtIndex(2));
    104   EXPECT_EQ(300, samples1.GetCountAtIndex(3));
    105   EXPECT_EQ(2000, samples1.sum());
    106   EXPECT_EQ(900, samples1.TotalCount());
    107   EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount());
    108 
    109   samples1.Subtract(samples2);
    110   EXPECT_EQ(100, samples1.GetCountAtIndex(0));
    111   EXPECT_EQ(0, samples1.GetCountAtIndex(1));
    112   EXPECT_EQ(100, samples1.GetCountAtIndex(2));
    113   EXPECT_EQ(100, samples1.GetCountAtIndex(3));
    114   EXPECT_EQ(600, samples1.sum());
    115   EXPECT_EQ(300, samples1.TotalCount());
    116   EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount());
    117 }
    118 
    119 TEST(SampleVectorDeathTest, BucketIndexTest) {
    120   // 8 buckets with exponential layout:
    121   // [0, 1) [1, 2) [2, 4) [4, 8) [8, 16) [16, 32) [32, 64) [64, INT_MAX)
    122   BucketRanges ranges(9);
    123   Histogram::InitializeBucketRanges(1, 64, &ranges);
    124   SampleVector samples(1, &ranges);
    125 
    126   // Normal case
    127   samples.Accumulate(0, 1);
    128   samples.Accumulate(3, 2);
    129   samples.Accumulate(64, 3);
    130   EXPECT_EQ(1, samples.GetCount(0));
    131   EXPECT_EQ(2, samples.GetCount(2));
    132   EXPECT_EQ(3, samples.GetCount(65));
    133 
    134   // Extreme case.
    135   EXPECT_DCHECK_DEATH(samples.Accumulate(INT_MIN, 100));
    136   EXPECT_DCHECK_DEATH(samples.Accumulate(-1, 100));
    137   EXPECT_DCHECK_DEATH(samples.Accumulate(INT_MAX, 100));
    138 
    139   // Custom buckets: [1, 5) [5, 10)
    140   // Note, this is not a valid BucketRanges for Histogram because it does not
    141   // have overflow buckets.
    142   BucketRanges ranges2(3);
    143   ranges2.set_range(0, 1);
    144   ranges2.set_range(1, 5);
    145   ranges2.set_range(2, 10);
    146   SampleVector samples2(2, &ranges2);
    147 
    148   // Normal case.
    149   samples2.Accumulate(1, 1);
    150   samples2.Accumulate(4, 1);
    151   samples2.Accumulate(5, 2);
    152   samples2.Accumulate(9, 2);
    153   EXPECT_EQ(2, samples2.GetCount(1));
    154   EXPECT_EQ(4, samples2.GetCount(5));
    155 
    156   // Extreme case.
    157   EXPECT_DCHECK_DEATH(samples2.Accumulate(0, 100));
    158   EXPECT_DCHECK_DEATH(samples2.Accumulate(10, 100));
    159 }
    160 
    161 TEST(SampleVectorDeathTest, AddSubtractBucketNotMatchTest) {
    162   // Custom buckets 1: [1, 3) [3, 5)
    163   BucketRanges ranges1(3);
    164   ranges1.set_range(0, 1);
    165   ranges1.set_range(1, 3);
    166   ranges1.set_range(2, 5);
    167   SampleVector samples1(1, &ranges1);
    168 
    169   // Custom buckets 2: [0, 1) [1, 3) [3, 6) [6, 7)
    170   BucketRanges ranges2(5);
    171   ranges2.set_range(0, 0);
    172   ranges2.set_range(1, 1);
    173   ranges2.set_range(2, 3);
    174   ranges2.set_range(3, 6);
    175   ranges2.set_range(4, 7);
    176   SampleVector samples2(2, &ranges2);
    177 
    178   samples2.Accumulate(1, 100);
    179   samples1.Add(samples2);
    180   EXPECT_EQ(100, samples1.GetCountAtIndex(0));
    181 
    182   // Extra bucket in the beginning.
    183   samples2.Accumulate(0, 100);
    184   EXPECT_DCHECK_DEATH(samples1.Add(samples2));
    185   EXPECT_DCHECK_DEATH(samples1.Subtract(samples2));
    186 
    187   // Extra bucket in the end.
    188   samples2.Accumulate(0, -100);
    189   samples2.Accumulate(6, 100);
    190   EXPECT_DCHECK_DEATH(samples1.Add(samples2));
    191   EXPECT_DCHECK_DEATH(samples1.Subtract(samples2));
    192 
    193   // Bucket not match: [3, 5) VS [3, 6)
    194   samples2.Accumulate(6, -100);
    195   samples2.Accumulate(3, 100);
    196   EXPECT_DCHECK_DEATH(samples1.Add(samples2));
    197   EXPECT_DCHECK_DEATH(samples1.Subtract(samples2));
    198 }
    199 
    200 TEST(SampleVectorIteratorTest, IterateTest) {
    201   BucketRanges ranges(5);
    202   ranges.set_range(0, 0);
    203   ranges.set_range(1, 1);
    204   ranges.set_range(2, 2);
    205   ranges.set_range(3, 3);
    206   ranges.set_range(4, 4);
    207 
    208   std::vector<HistogramBase::Count> counts(3);
    209   counts[0] = 1;
    210   counts[1] = 0;  // Iterator will bypass this empty bucket.
    211   counts[2] = 2;
    212 
    213   // BucketRanges can have larger size than counts.
    214   SampleVectorIterator it(&counts, &ranges);
    215   size_t index;
    216 
    217   HistogramBase::Sample min;
    218   HistogramBase::Sample max;
    219   HistogramBase::Count count;
    220   it.Get(&min, &max, &count);
    221   EXPECT_EQ(0, min);
    222   EXPECT_EQ(1, max);
    223   EXPECT_EQ(1, count);
    224   EXPECT_TRUE(it.GetBucketIndex(&index));
    225   EXPECT_EQ(0u, index);
    226 
    227   it.Next();
    228   it.Get(&min, &max, &count);
    229   EXPECT_EQ(2, min);
    230   EXPECT_EQ(3, max);
    231   EXPECT_EQ(2, count);
    232   EXPECT_TRUE(it.GetBucketIndex(&index));
    233   EXPECT_EQ(2u, index);
    234 
    235   it.Next();
    236   EXPECT_TRUE(it.Done());
    237 
    238   // Create iterator from SampleVector.
    239   SampleVector samples(1, &ranges);
    240   samples.Accumulate(0, 0);
    241   samples.Accumulate(1, 1);
    242   samples.Accumulate(2, 2);
    243   samples.Accumulate(3, 3);
    244   std::unique_ptr<SampleCountIterator> it2 = samples.Iterator();
    245 
    246   int i;
    247   for (i = 1; !it2->Done(); i++, it2->Next()) {
    248     it2->Get(&min, &max, &count);
    249     EXPECT_EQ(i, min);
    250     EXPECT_EQ(i + 1, max);
    251     EXPECT_EQ(i, count);
    252 
    253     size_t index;
    254     EXPECT_TRUE(it2->GetBucketIndex(&index));
    255     EXPECT_EQ(static_cast<size_t>(i), index);
    256   }
    257   EXPECT_EQ(4, i);
    258 }
    259 
    260 TEST(SampleVectorIteratorDeathTest, IterateDoneTest) {
    261   BucketRanges ranges(5);
    262   ranges.set_range(0, 0);
    263   ranges.set_range(1, 1);
    264   ranges.set_range(2, 2);
    265   ranges.set_range(3, 3);
    266   ranges.set_range(4, INT_MAX);
    267   SampleVector samples(1, &ranges);
    268 
    269   std::unique_ptr<SampleCountIterator> it = samples.Iterator();
    270 
    271   EXPECT_TRUE(it->Done());
    272 
    273   HistogramBase::Sample min;
    274   HistogramBase::Sample max;
    275   HistogramBase::Count count;
    276   EXPECT_DCHECK_DEATH(it->Get(&min, &max, &count));
    277 
    278   EXPECT_DCHECK_DEATH(it->Next());
    279 
    280   samples.Accumulate(2, 100);
    281   it = samples.Iterator();
    282   EXPECT_FALSE(it->Done());
    283 }
    284 
    285 }  // namespace
    286 }  // namespace base
    287