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> ExpectUniqueSample(const std::string & name,T sample,HistogramBase::Count expected_count)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> ExpectBucketCount(const std::string & name,T sample,HistogramBase::Count expected_count)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 { BucketBucket166 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