|  | // Copyright 2014 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef BASE_TEST_HISTOGRAM_TESTER_H_ | 
|  | #define BASE_TEST_HISTOGRAM_TESTER_H_ | 
|  |  | 
|  | #include <map> | 
|  | #include <memory> | 
|  | #include <ostream> | 
|  | #include <string> | 
|  | #include <utility> | 
|  | #include <vector> | 
|  |  | 
|  | #include "base/macros.h" | 
|  | #include "base/metrics/histogram.h" | 
|  | #include "base/metrics/histogram_base.h" | 
|  | #include "base/time/time.h" | 
|  |  | 
|  | namespace base { | 
|  |  | 
|  | struct Bucket; | 
|  | class HistogramSamples; | 
|  |  | 
|  | // HistogramTester provides a simple interface for examining histograms, UMA | 
|  | // or otherwise. Tests can use this interface to verify that histogram data is | 
|  | // getting logged as intended. | 
|  | // | 
|  | // Note: When using this class from a browser test, one might have to call | 
|  | // SubprocessMetricsProvider::MergeHistogramDeltasForTesting() to sync the | 
|  | // histogram data between the renderer and browser processes. If it is in a | 
|  | // content browser test, then content::FetchHistogramsFromChildProcesses() | 
|  | // should be used to achieve that. | 
|  | class HistogramTester { | 
|  | public: | 
|  | using CountsMap = std::map<std::string, HistogramBase::Count>; | 
|  |  | 
|  | // Takes a snapshot of all current histograms counts. | 
|  | HistogramTester(); | 
|  | ~HistogramTester(); | 
|  |  | 
|  | // We know the exact number of samples in a bucket, and that no other bucket | 
|  | // should have samples. Measures the diff from the snapshot taken when this | 
|  | // object was constructed. | 
|  | void ExpectUniqueSample(const std::string& name, | 
|  | HistogramBase::Sample sample, | 
|  | HistogramBase::Count expected_count) const; | 
|  | template <typename T> | 
|  | void ExpectUniqueSample(const std::string& name, | 
|  | T sample, | 
|  | HistogramBase::Count expected_count) const { | 
|  | ExpectUniqueSample(name, static_cast<HistogramBase::Sample>(sample), | 
|  | expected_count); | 
|  | } | 
|  |  | 
|  | // We know the exact number of samples in a bucket, but other buckets may | 
|  | // have samples as well. Measures the diff from the snapshot taken when this | 
|  | // object was constructed. | 
|  | void ExpectBucketCount(const std::string& name, | 
|  | HistogramBase::Sample sample, | 
|  | HistogramBase::Count expected_count) const; | 
|  | template <typename T> | 
|  | void ExpectBucketCount(const std::string& name, | 
|  | T sample, | 
|  | HistogramBase::Count expected_count) const { | 
|  | ExpectBucketCount(name, static_cast<HistogramBase::Sample>(sample), | 
|  | expected_count); | 
|  | } | 
|  |  | 
|  | // We don't know the values of the samples, but we know how many there are. | 
|  | // This measures the diff from the snapshot taken when this object was | 
|  | // constructed. | 
|  | void ExpectTotalCount(const std::string& name, | 
|  | HistogramBase::Count count) const; | 
|  |  | 
|  | // We know exact number of samples for buckets corresponding to a time | 
|  | // interval. Other intervals may have samples too. | 
|  | void ExpectTimeBucketCount(const std::string& name, | 
|  | TimeDelta sample, | 
|  | HistogramBase::Count count) const; | 
|  |  | 
|  | // Returns a list of all of the buckets recorded since creation of this | 
|  | // object, as vector<Bucket>, where the Bucket represents the min boundary of | 
|  | // the bucket and the count of samples recorded to that bucket since creation. | 
|  | // | 
|  | // Example usage, using gMock: | 
|  | //   EXPECT_THAT(histogram_tester.GetAllSamples("HistogramName"), | 
|  | //               ElementsAre(Bucket(1, 5), Bucket(2, 10), Bucket(3, 5))); | 
|  | // | 
|  | // If you build the expected list programmatically, you can use ContainerEq: | 
|  | //   EXPECT_THAT(histogram_tester.GetAllSamples("HistogramName"), | 
|  | //               ContainerEq(expected_buckets)); | 
|  | // | 
|  | // or EXPECT_EQ if you prefer not to depend on gMock, at the expense of a | 
|  | // slightly less helpful failure message: | 
|  | //   EXPECT_EQ(expected_buckets, | 
|  | //             histogram_tester.GetAllSamples("HistogramName")); | 
|  | std::vector<Bucket> GetAllSamples(const std::string& name) const; | 
|  |  | 
|  | // Returns the value of the |sample| bucket for ths histogram |name|. | 
|  | HistogramBase::Count GetBucketCount(const std::string& name, | 
|  | HistogramBase::Sample sample) const; | 
|  |  | 
|  | // Finds histograms whose names start with |prefix|, and returns them along | 
|  | // with the counts of any samples added since the creation of this object. | 
|  | // Histograms that are unchanged are omitted from the result. The return value | 
|  | // is a map whose keys are the histogram name, and whose values are the sample | 
|  | // count. | 
|  | // | 
|  | // This is useful for cases where the code under test is choosing among a | 
|  | // family of related histograms and incrementing one of them. Typically you | 
|  | // should pass the result of this function directly to EXPECT_THAT. | 
|  | // | 
|  | // Example usage, using gmock (which produces better failure messages): | 
|  | //   #include "testing/gmock/include/gmock/gmock.h" | 
|  | // ... | 
|  | //   base::HistogramTester::CountsMap expected_counts; | 
|  | //   expected_counts["MyMetric.A"] = 1; | 
|  | //   expected_counts["MyMetric.B"] = 1; | 
|  | //   EXPECT_THAT(histogram_tester.GetTotalCountsForPrefix("MyMetric."), | 
|  | //               testing::ContainerEq(expected_counts)); | 
|  | CountsMap GetTotalCountsForPrefix(const std::string& prefix) const; | 
|  |  | 
|  | // Access a modified HistogramSamples containing only what has been logged | 
|  | // to the histogram since the creation of this object. | 
|  | std::unique_ptr<HistogramSamples> GetHistogramSamplesSinceCreation( | 
|  | const std::string& histogram_name) const; | 
|  |  | 
|  | private: | 
|  | // Verifies and asserts that value in the |sample| bucket matches the | 
|  | // |expected_count|. The bucket's current value is determined from |samples| | 
|  | // and is modified based on the snapshot stored for histogram |name|. | 
|  | void CheckBucketCount(const std::string& name, | 
|  | HistogramBase::Sample sample, | 
|  | Histogram::Count expected_count, | 
|  | const HistogramSamples& samples) const; | 
|  |  | 
|  | // Verifies that the total number of values recorded for the histogram |name| | 
|  | // is |expected_count|. This is checked against |samples| minus the snapshot | 
|  | // that was taken for |name|. | 
|  | void CheckTotalCount(const std::string& name, | 
|  | Histogram::Count expected_count, | 
|  | const HistogramSamples& samples) const; | 
|  |  | 
|  | // Sets the value for |count| to be the value in the |sample| bucket. The | 
|  | // bucket's current value is determined from |samples| and is modified based | 
|  | // on the snapshot stored for histogram |name|. | 
|  | void GetBucketCountForSamples(const std::string& name, | 
|  | HistogramBase::Sample sample, | 
|  | const HistogramSamples& samples, | 
|  | HistogramBase::Count* count) const; | 
|  |  | 
|  | // Used to determine the histogram changes made during this instance's | 
|  | // lifecycle. | 
|  | std::map<std::string, std::unique_ptr<HistogramSamples>> histograms_snapshot_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(HistogramTester); | 
|  | }; | 
|  |  | 
|  | struct Bucket { | 
|  | Bucket(HistogramBase::Sample min, HistogramBase::Count count) | 
|  | : min(min), count(count) {} | 
|  |  | 
|  | bool operator==(const Bucket& other) const; | 
|  |  | 
|  | HistogramBase::Sample min; | 
|  | HistogramBase::Count count; | 
|  | }; | 
|  |  | 
|  | void PrintTo(const Bucket& value, std::ostream* os); | 
|  |  | 
|  | }  // namespace base | 
|  |  | 
|  | #endif  // BASE_TEST_HISTOGRAM_TESTER_H_ |