Home | History | Annotate | Download | only in metrics
      1 // Copyright 2014 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 #ifndef BASE_TEST_METRICS_HISTOGRAM_TESTER_H_
      6 #define BASE_TEST_METRICS_HISTOGRAM_TESTER_H_
      7 
      8 #include <map>
      9 #include <memory>
     10 #include <ostream>
     11 #include <string>
     12 #include <utility>
     13 #include <vector>
     14 
     15 #include "base/macros.h"
     16 #include "base/metrics/histogram.h"
     17 #include "base/metrics/histogram_base.h"
     18 #include "base/time/time.h"
     19 
     20 namespace base {
     21 
     22 struct Bucket;
     23 class HistogramSamples;
     24 
     25 // HistogramTester provides a simple interface for examining histograms, UMA
     26 // or otherwise. Tests can use this interface to verify that histogram data is
     27 // getting logged as intended.
     28 //
     29 // Note: When using this class from a browser test, one might have to call
     30 // SubprocessMetricsProvider::MergeHistogramDeltasForTesting() to sync the
     31 // histogram data between the renderer and browser processes. If it is in a
     32 // content browser test, then content::FetchHistogramsFromChildProcesses()
     33 // should be used to achieve that.
     34 class HistogramTester {
     35  public:
     36   using CountsMap = std::map<std::string, HistogramBase::Count>;
     37 
     38   // Takes a snapshot of all current histograms counts.
     39   HistogramTester();
     40   ~HistogramTester();
     41 
     42   // We know the exact number of samples in a bucket, and that no other bucket
     43   // should have samples. Measures the diff from the snapshot taken when this
     44   // object was constructed.
     45   void ExpectUniqueSample(const std::string& name,
     46                           HistogramBase::Sample sample,
     47                           HistogramBase::Count expected_count) const;
     48   template <typename T>
     49   void ExpectUniqueSample(const std::string& name,
     50                           T sample,
     51                           HistogramBase::Count expected_count) const {
     52     ExpectUniqueSample(name, static_cast<HistogramBase::Sample>(sample),
     53                        expected_count);
     54   }
     55 
     56   // We know the exact number of samples in a bucket, but other buckets may
     57   // have samples as well. Measures the diff from the snapshot taken when this
     58   // object was constructed.
     59   void ExpectBucketCount(const std::string& name,
     60                          HistogramBase::Sample sample,
     61                          HistogramBase::Count expected_count) const;
     62   template <typename T>
     63   void ExpectBucketCount(const std::string& name,
     64                          T sample,
     65                          HistogramBase::Count expected_count) const {
     66     ExpectBucketCount(name, static_cast<HistogramBase::Sample>(sample),
     67                       expected_count);
     68   }
     69 
     70   // We don't know the values of the samples, but we know how many there are.
     71   // This measures the diff from the snapshot taken when this object was
     72   // constructed.
     73   void ExpectTotalCount(const std::string& name,
     74                         HistogramBase::Count count) const;
     75 
     76   // We know exact number of samples for buckets corresponding to a time
     77   // interval. Other intervals may have samples too.
     78   void ExpectTimeBucketCount(const std::string& name,
     79                              TimeDelta sample,
     80                              HistogramBase::Count count) const;
     81 
     82   // Returns a list of all of the buckets recorded since creation of this
     83   // object, as vector<Bucket>, where the Bucket represents the min boundary of
     84   // the bucket and the count of samples recorded to that bucket since creation.
     85   //
     86   // Example usage, using gMock:
     87   //   EXPECT_THAT(histogram_tester.GetAllSamples("HistogramName"),
     88   //               ElementsAre(Bucket(1, 5), Bucket(2, 10), Bucket(3, 5)));
     89   //
     90   // If you build the expected list programmatically, you can use ContainerEq:
     91   //   EXPECT_THAT(histogram_tester.GetAllSamples("HistogramName"),
     92   //               ContainerEq(expected_buckets));
     93   //
     94   // or EXPECT_EQ if you prefer not to depend on gMock, at the expense of a
     95   // slightly less helpful failure message:
     96   //   EXPECT_EQ(expected_buckets,
     97   //             histogram_tester.GetAllSamples("HistogramName"));
     98   std::vector<Bucket> GetAllSamples(const std::string& name) const;
     99 
    100   // Returns the value of the |sample| bucket for ths histogram |name|.
    101   HistogramBase::Count GetBucketCount(const std::string& name,
    102                                       HistogramBase::Sample sample) const;
    103 
    104   // Finds histograms whose names start with |prefix|, and returns them along
    105   // with the counts of any samples added since the creation of this object.
    106   // Histograms that are unchanged are omitted from the result. The return value
    107   // is a map whose keys are the histogram name, and whose values are the sample
    108   // count.
    109   //
    110   // This is useful for cases where the code under test is choosing among a
    111   // family of related histograms and incrementing one of them. Typically you
    112   // should pass the result of this function directly to EXPECT_THAT.
    113   //
    114   // Example usage, using gmock (which produces better failure messages):
    115   //   #include "testing/gmock/include/gmock/gmock.h"
    116   // ...
    117   //   base::HistogramTester::CountsMap expected_counts;
    118   //   expected_counts["MyMetric.A"] = 1;
    119   //   expected_counts["MyMetric.B"] = 1;
    120   //   EXPECT_THAT(histogram_tester.GetTotalCountsForPrefix("MyMetric."),
    121   //               testing::ContainerEq(expected_counts));
    122   CountsMap GetTotalCountsForPrefix(const std::string& prefix) const;
    123 
    124   // Access a modified HistogramSamples containing only what has been logged
    125   // to the histogram since the creation of this object.
    126   std::unique_ptr<HistogramSamples> GetHistogramSamplesSinceCreation(
    127       const std::string& histogram_name) const;
    128 
    129   // Dumps all histograms that have had new samples added to them into a string,
    130   // for debugging purposes. Note: this will dump the entire contents of any
    131   // modified histograms and not just the modified buckets.
    132   std::string GetAllHistogramsRecorded() const;
    133 
    134  private:
    135   // Verifies and asserts that value in the |sample| bucket matches the
    136   // |expected_count|. The bucket's current value is determined from |samples|
    137   // and is modified based on the snapshot stored for histogram |name|.
    138   void CheckBucketCount(const std::string& name,
    139                         HistogramBase::Sample sample,
    140                         Histogram::Count expected_count,
    141                         const HistogramSamples& samples) const;
    142 
    143   // Verifies that the total number of values recorded for the histogram |name|
    144   // is |expected_count|. This is checked against |samples| minus the snapshot
    145   // that was taken for |name|.
    146   void CheckTotalCount(const std::string& name,
    147                        Histogram::Count expected_count,
    148                        const HistogramSamples& samples) const;
    149 
    150   // Sets the value for |count| to be the value in the |sample| bucket. The
    151   // bucket's current value is determined from |samples| and is modified based
    152   // on the snapshot stored for histogram |name|.
    153   void GetBucketCountForSamples(const std::string& name,
    154                                 HistogramBase::Sample sample,
    155                                 const HistogramSamples& samples,
    156                                 HistogramBase::Count* count) const;
    157 
    158   // Used to determine the histogram changes made during this instance's
    159   // lifecycle.
    160   std::map<std::string, std::unique_ptr<HistogramSamples>> histograms_snapshot_;
    161 
    162   DISALLOW_COPY_AND_ASSIGN(HistogramTester);
    163 };
    164 
    165 struct Bucket {
    166   Bucket(HistogramBase::Sample min, HistogramBase::Count count)
    167       : min(min), count(count) {}
    168 
    169   bool operator==(const Bucket& other) const;
    170 
    171   HistogramBase::Sample min;
    172   HistogramBase::Count count;
    173 };
    174 
    175 void PrintTo(const Bucket& value, std::ostream* os);
    176 
    177 }  // namespace base
    178 
    179 #endif  // BASE_TEST_METRICS_HISTOGRAM_TESTER_H_
    180