xref: /aosp_15_r20/external/cronet/base/test/metrics/histogram_tester.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2014 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_TEST_METRICS_HISTOGRAM_TESTER_H_
6*6777b538SAndroid Build Coastguard Worker #define BASE_TEST_METRICS_HISTOGRAM_TESTER_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <functional>
9*6777b538SAndroid Build Coastguard Worker #include <map>
10*6777b538SAndroid Build Coastguard Worker #include <memory>
11*6777b538SAndroid Build Coastguard Worker #include <ostream>
12*6777b538SAndroid Build Coastguard Worker #include <string>
13*6777b538SAndroid Build Coastguard Worker #include <string_view>
14*6777b538SAndroid Build Coastguard Worker #include <type_traits>
15*6777b538SAndroid Build Coastguard Worker #include <utility>
16*6777b538SAndroid Build Coastguard Worker #include <vector>
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker #include "base/location.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram_base.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
22*6777b538SAndroid Build Coastguard Worker #include "testing/gmock/include/gmock/gmock.h"
23*6777b538SAndroid Build Coastguard Worker 
24*6777b538SAndroid Build Coastguard Worker namespace base {
25*6777b538SAndroid Build Coastguard Worker 
26*6777b538SAndroid Build Coastguard Worker struct Bucket;
27*6777b538SAndroid Build Coastguard Worker class HistogramSamples;
28*6777b538SAndroid Build Coastguard Worker 
29*6777b538SAndroid Build Coastguard Worker // HistogramTester provides a simple interface for examining histograms, UMA
30*6777b538SAndroid Build Coastguard Worker // or otherwise. Tests can use this interface to verify that histogram data is
31*6777b538SAndroid Build Coastguard Worker // getting logged as intended.
32*6777b538SAndroid Build Coastguard Worker //
33*6777b538SAndroid Build Coastguard Worker // Note: When using this class from a browser test, one might have to call
34*6777b538SAndroid Build Coastguard Worker // SubprocessMetricsProvider::MergeHistogramDeltasForTesting() to sync the
35*6777b538SAndroid Build Coastguard Worker // histogram data between the renderer and browser processes. If it is in a
36*6777b538SAndroid Build Coastguard Worker // content browser test, then content::FetchHistogramsFromChildProcesses()
37*6777b538SAndroid Build Coastguard Worker // should be used to achieve that.
38*6777b538SAndroid Build Coastguard Worker // To test histograms in Java tests, use HistogramWatcher.
39*6777b538SAndroid Build Coastguard Worker class HistogramTester {
40*6777b538SAndroid Build Coastguard Worker  public:
41*6777b538SAndroid Build Coastguard Worker   using CountsMap = std::map<std::string, HistogramBase::Count, std::less<>>;
42*6777b538SAndroid Build Coastguard Worker 
43*6777b538SAndroid Build Coastguard Worker   // Takes a snapshot of all current histograms counts.
44*6777b538SAndroid Build Coastguard Worker   HistogramTester();
45*6777b538SAndroid Build Coastguard Worker 
46*6777b538SAndroid Build Coastguard Worker   HistogramTester(const HistogramTester&) = delete;
47*6777b538SAndroid Build Coastguard Worker   HistogramTester& operator=(const HistogramTester&) = delete;
48*6777b538SAndroid Build Coastguard Worker 
49*6777b538SAndroid Build Coastguard Worker   ~HistogramTester();
50*6777b538SAndroid Build Coastguard Worker 
51*6777b538SAndroid Build Coastguard Worker   // EXPECTs that the number of samples in bucket |sample| of histogram |name|
52*6777b538SAndroid Build Coastguard Worker   // grew by |expected_bucket_count| since the HistogramTester was created and
53*6777b538SAndroid Build Coastguard Worker   // that no other bucket of the histogram gained any extra samples.
54*6777b538SAndroid Build Coastguard Worker   // If a bucket had samples before the HistogramTester was created, these
55*6777b538SAndroid Build Coastguard Worker   // samples are completely ignored.
56*6777b538SAndroid Build Coastguard Worker   void ExpectUniqueSample(std::string_view name,
57*6777b538SAndroid Build Coastguard Worker                           HistogramBase::Sample sample,
58*6777b538SAndroid Build Coastguard Worker                           HistogramBase::Count expected_bucket_count,
59*6777b538SAndroid Build Coastguard Worker                           const Location& location = FROM_HERE) const;
60*6777b538SAndroid Build Coastguard Worker   template <typename T>
61*6777b538SAndroid Build Coastguard Worker   void ExpectUniqueSample(std::string_view name,
62*6777b538SAndroid Build Coastguard Worker                           T sample,
63*6777b538SAndroid Build Coastguard Worker                           HistogramBase::Count expected_bucket_count,
64*6777b538SAndroid Build Coastguard Worker                           const Location& location = FROM_HERE) const {
65*6777b538SAndroid Build Coastguard Worker     ExpectUniqueSample(name, static_cast<HistogramBase::Sample>(sample),
66*6777b538SAndroid Build Coastguard Worker                        expected_bucket_count, location);
67*6777b538SAndroid Build Coastguard Worker   }
68*6777b538SAndroid Build Coastguard Worker   void ExpectUniqueTimeSample(std::string_view name,
69*6777b538SAndroid Build Coastguard Worker                               TimeDelta sample,
70*6777b538SAndroid Build Coastguard Worker                               HistogramBase::Count expected_bucket_count,
71*6777b538SAndroid Build Coastguard Worker                               const Location& location = FROM_HERE) const;
72*6777b538SAndroid Build Coastguard Worker 
73*6777b538SAndroid Build Coastguard Worker   // EXPECTs that the number of samples in bucket |sample| of histogram |name|
74*6777b538SAndroid Build Coastguard Worker   // grew by |expected_count| since the HistogramTester was created. Samples in
75*6777b538SAndroid Build Coastguard Worker   // other buckets are ignored.
76*6777b538SAndroid Build Coastguard Worker   void ExpectBucketCount(std::string_view name,
77*6777b538SAndroid Build Coastguard Worker                          HistogramBase::Sample sample,
78*6777b538SAndroid Build Coastguard Worker                          HistogramBase::Count expected_count,
79*6777b538SAndroid Build Coastguard Worker                          const Location& location = FROM_HERE) const;
80*6777b538SAndroid Build Coastguard Worker   template <typename T>
81*6777b538SAndroid Build Coastguard Worker   void ExpectBucketCount(std::string_view name,
82*6777b538SAndroid Build Coastguard Worker                          T sample,
83*6777b538SAndroid Build Coastguard Worker                          HistogramBase::Count expected_count,
84*6777b538SAndroid Build Coastguard Worker                          const Location& location = FROM_HERE) const {
85*6777b538SAndroid Build Coastguard Worker     ExpectBucketCount(name, static_cast<HistogramBase::Sample>(sample),
86*6777b538SAndroid Build Coastguard Worker                       expected_count, location);
87*6777b538SAndroid Build Coastguard Worker   }
88*6777b538SAndroid Build Coastguard Worker   void ExpectTimeBucketCount(std::string_view name,
89*6777b538SAndroid Build Coastguard Worker                              TimeDelta sample,
90*6777b538SAndroid Build Coastguard Worker                              HistogramBase::Count expected_count,
91*6777b538SAndroid Build Coastguard Worker                              const Location& location = FROM_HERE) const;
92*6777b538SAndroid Build Coastguard Worker 
93*6777b538SAndroid Build Coastguard Worker   // EXPECTs that the total number of samples in histogram |name|
94*6777b538SAndroid Build Coastguard Worker   // grew by |expected_count| since the HistogramTester was created.
95*6777b538SAndroid Build Coastguard Worker   void ExpectTotalCount(std::string_view name,
96*6777b538SAndroid Build Coastguard Worker                         HistogramBase::Count expected_count,
97*6777b538SAndroid Build Coastguard Worker                         const Location& location = FROM_HERE) const;
98*6777b538SAndroid Build Coastguard Worker 
99*6777b538SAndroid Build Coastguard Worker   // Returns the sum of all samples recorded since the HistogramTester was
100*6777b538SAndroid Build Coastguard Worker   // created.
101*6777b538SAndroid Build Coastguard Worker   int64_t GetTotalSum(std::string_view name) const;
102*6777b538SAndroid Build Coastguard Worker 
103*6777b538SAndroid Build Coastguard Worker   // Returns a list of all of the buckets recorded since creation of this
104*6777b538SAndroid Build Coastguard Worker   // object, as vector<Bucket>, where the Bucket represents the min boundary of
105*6777b538SAndroid Build Coastguard Worker   // the bucket and the count of samples recorded to that bucket since creation.
106*6777b538SAndroid Build Coastguard Worker   //
107*6777b538SAndroid Build Coastguard Worker   // Note: The histogram defines the bucket boundaries. If you test a histogram
108*6777b538SAndroid Build Coastguard Worker   // with exponential bucket sizes, this function may not be particularly useful
109*6777b538SAndroid Build Coastguard Worker   // because you would need to guess the bucket boundaries.
110*6777b538SAndroid Build Coastguard Worker   //
111*6777b538SAndroid Build Coastguard Worker   // Example usage, using gMock:
112*6777b538SAndroid Build Coastguard Worker   //   EXPECT_THAT(histogram_tester.GetAllSamples("HistogramName"),
113*6777b538SAndroid Build Coastguard Worker   //               ElementsAre(Bucket(1, 5), Bucket(2, 10), Bucket(3, 5)));
114*6777b538SAndroid Build Coastguard Worker   //
115*6777b538SAndroid Build Coastguard Worker   // If you want make empty bucket explicit, use the BucketsAre() matcher
116*6777b538SAndroid Build Coastguard Worker   // defined below:
117*6777b538SAndroid Build Coastguard Worker   //   EXPECT_THAT(histogram_tester.GetAllSamples("HistogramName"),
118*6777b538SAndroid Build Coastguard Worker   //               BucketsAre(Bucket(1, 0), Bucket(2, 10), Bucket(3, 5)));
119*6777b538SAndroid Build Coastguard Worker   //
120*6777b538SAndroid Build Coastguard Worker   // If you want to test a superset relation, prefer BucketsInclude() over
121*6777b538SAndroid Build Coastguard Worker   // IsSupersetOf() because the former handles empty buckets as expected:
122*6777b538SAndroid Build Coastguard Worker   //   EXPECT_THAT(histogram_tester.GetAllSamples("HistogramName"),
123*6777b538SAndroid Build Coastguard Worker   //               BucketsInclude(Bucket(1, 0), Bucket(2, 10), Bucket(3, 5)));
124*6777b538SAndroid Build Coastguard Worker   // With IsSupersetOf(), this expectation would always fail because
125*6777b538SAndroid Build Coastguard Worker   // GetAllSamples() does not contain empty buckets.
126*6777b538SAndroid Build Coastguard Worker   //
127*6777b538SAndroid Build Coastguard Worker   // If you build the expected list programmatically, you can use the matchers
128*6777b538SAndroid Build Coastguard Worker   // ElementsAreArray(), BucketsAreArray(), BucketsIncludeArray().
129*6777b538SAndroid Build Coastguard Worker   //
130*6777b538SAndroid Build Coastguard Worker   // If you prefer not to depend on gMock at the expense of a slightly less
131*6777b538SAndroid Build Coastguard Worker   // helpful failure message, use EXPECT_EQ:
132*6777b538SAndroid Build Coastguard Worker   //   EXPECT_EQ(expected_buckets,
133*6777b538SAndroid Build Coastguard Worker   //             histogram_tester.GetAllSamples("HistogramName"));
134*6777b538SAndroid Build Coastguard Worker   std::vector<Bucket> GetAllSamples(std::string_view name) const;
135*6777b538SAndroid Build Coastguard Worker 
136*6777b538SAndroid Build Coastguard Worker   // Returns the value of the |sample| bucket for ths histogram |name|.
137*6777b538SAndroid Build Coastguard Worker   HistogramBase::Count GetBucketCount(std::string_view name,
138*6777b538SAndroid Build Coastguard Worker                                       HistogramBase::Sample sample) const;
139*6777b538SAndroid Build Coastguard Worker   template <typename T>
GetBucketCount(std::string_view name,T sample)140*6777b538SAndroid Build Coastguard Worker   HistogramBase::Count GetBucketCount(std::string_view name, T sample) const {
141*6777b538SAndroid Build Coastguard Worker     return GetBucketCount(name, static_cast<HistogramBase::Sample>(sample));
142*6777b538SAndroid Build Coastguard Worker   }
143*6777b538SAndroid Build Coastguard Worker 
144*6777b538SAndroid Build Coastguard Worker   // Finds histograms whose names start with |prefix|, and returns them along
145*6777b538SAndroid Build Coastguard Worker   // with the counts of any samples added since the creation of this object.
146*6777b538SAndroid Build Coastguard Worker   // Histograms that are unchanged are omitted from the result. The return value
147*6777b538SAndroid Build Coastguard Worker   // is a map whose keys are the histogram name, and whose values are the sample
148*6777b538SAndroid Build Coastguard Worker   // count.
149*6777b538SAndroid Build Coastguard Worker   //
150*6777b538SAndroid Build Coastguard Worker   // This is useful for cases where the code under test is choosing among a
151*6777b538SAndroid Build Coastguard Worker   // family of related histograms and incrementing one of them. Typically you
152*6777b538SAndroid Build Coastguard Worker   // should pass the result of this function directly to EXPECT_THAT.
153*6777b538SAndroid Build Coastguard Worker   //
154*6777b538SAndroid Build Coastguard Worker   // Example usage, using gmock (which produces better failure messages):
155*6777b538SAndroid Build Coastguard Worker   //   #include "testing/gmock/include/gmock/gmock.h"
156*6777b538SAndroid Build Coastguard Worker   // ...
157*6777b538SAndroid Build Coastguard Worker   //   base::HistogramTester::CountsMap expected_counts;
158*6777b538SAndroid Build Coastguard Worker   //   expected_counts["MyMetric.A"] = 1;
159*6777b538SAndroid Build Coastguard Worker   //   expected_counts["MyMetric.B"] = 1;
160*6777b538SAndroid Build Coastguard Worker   //   EXPECT_THAT(histogram_tester.GetTotalCountsForPrefix("MyMetric."),
161*6777b538SAndroid Build Coastguard Worker   //               testing::ContainerEq(expected_counts));
162*6777b538SAndroid Build Coastguard Worker   CountsMap GetTotalCountsForPrefix(std::string_view prefix) const;
163*6777b538SAndroid Build Coastguard Worker 
164*6777b538SAndroid Build Coastguard Worker   // Returns the HistogramSamples recorded since the creation of the
165*6777b538SAndroid Build Coastguard Worker   // HistogramTester.
166*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<HistogramSamples> GetHistogramSamplesSinceCreation(
167*6777b538SAndroid Build Coastguard Worker       std::string_view histogram_name) const;
168*6777b538SAndroid Build Coastguard Worker 
169*6777b538SAndroid Build Coastguard Worker   // Dumps all histograms that have had new samples added to them into a string,
170*6777b538SAndroid Build Coastguard Worker   // for debugging purposes. Note: this will dump the entire contents of any
171*6777b538SAndroid Build Coastguard Worker   // modified histograms and not just the modified buckets.
172*6777b538SAndroid Build Coastguard Worker   std::string GetAllHistogramsRecorded() const;
173*6777b538SAndroid Build Coastguard Worker 
174*6777b538SAndroid Build Coastguard Worker  private:
175*6777b538SAndroid Build Coastguard Worker   // Returns the total number of values recorded for |histogram| since the
176*6777b538SAndroid Build Coastguard Worker   // HistogramTester was created.
177*6777b538SAndroid Build Coastguard Worker   int GetTotalCountForSamples(const HistogramBase& histogram) const;
178*6777b538SAndroid Build Coastguard Worker 
179*6777b538SAndroid Build Coastguard Worker   // Sets |*sample_count| to number of samples by which bucket |sample| bucket
180*6777b538SAndroid Build Coastguard Worker   // grew since the HistogramTester was created. If |total_count| is non-null,
181*6777b538SAndroid Build Coastguard Worker   // sets |*total_count| to the number of samples recorded for |histogram|
182*6777b538SAndroid Build Coastguard Worker   // since the HistogramTester was created.
183*6777b538SAndroid Build Coastguard Worker   void GetBucketCountForSamples(const HistogramBase& histogram,
184*6777b538SAndroid Build Coastguard Worker                                 HistogramBase::Sample sample,
185*6777b538SAndroid Build Coastguard Worker                                 HistogramBase::Count* sample_count,
186*6777b538SAndroid Build Coastguard Worker                                 HistogramBase::Count* total_count) const;
187*6777b538SAndroid Build Coastguard Worker 
188*6777b538SAndroid Build Coastguard Worker   // Returns the deltas for |histogram| since the HistogramTester was created
189*6777b538SAndroid Build Coastguard Worker   // as an ASCII art histogram for debugging purposes.
190*6777b538SAndroid Build Coastguard Worker   std::string SnapshotToString(const HistogramBase& histogram) const;
191*6777b538SAndroid Build Coastguard Worker 
192*6777b538SAndroid Build Coastguard Worker   // Snapshot of all histograms recorded before the HistogramTester was created.
193*6777b538SAndroid Build Coastguard Worker   // Used to determine the histogram changes made during this instance's
194*6777b538SAndroid Build Coastguard Worker   // lifecycle.
195*6777b538SAndroid Build Coastguard Worker   std::map<std::string, std::unique_ptr<HistogramSamples>, std::less<>>
196*6777b538SAndroid Build Coastguard Worker       histograms_snapshot_;
197*6777b538SAndroid Build Coastguard Worker };
198*6777b538SAndroid Build Coastguard Worker 
199*6777b538SAndroid Build Coastguard Worker struct Bucket {
BucketBucket200*6777b538SAndroid Build Coastguard Worker   Bucket(HistogramBase::Sample min, HistogramBase::Count count)
201*6777b538SAndroid Build Coastguard Worker       : min(min), count(count) {}
202*6777b538SAndroid Build Coastguard Worker 
203*6777b538SAndroid Build Coastguard Worker   // A variant of the above constructor that accepts an `EnumType` for the `min`
204*6777b538SAndroid Build Coastguard Worker   // value. Typically, this `EnumType` is the C++ enum (class) that is
205*6777b538SAndroid Build Coastguard Worker   // associated with the metric this bucket is referring to.
206*6777b538SAndroid Build Coastguard Worker   //
207*6777b538SAndroid Build Coastguard Worker   // The constructor forwards to the above non-templated constructor. Therefore,
208*6777b538SAndroid Build Coastguard Worker   // `EnumType` must be implicitly convertible to `HistogramBase::Sample`.
209*6777b538SAndroid Build Coastguard Worker   template <typename MetricEnum,
210*6777b538SAndroid Build Coastguard Worker             typename = std::enable_if_t<std::is_enum_v<MetricEnum>>>
BucketBucket211*6777b538SAndroid Build Coastguard Worker   Bucket(MetricEnum min, HistogramBase::Count count)
212*6777b538SAndroid Build Coastguard Worker       : Bucket(static_cast<std::underlying_type_t<MetricEnum>>(min), count) {}
213*6777b538SAndroid Build Coastguard Worker 
214*6777b538SAndroid Build Coastguard Worker   friend bool operator==(const Bucket&, const Bucket&) = default;
215*6777b538SAndroid Build Coastguard Worker 
216*6777b538SAndroid Build Coastguard Worker   HistogramBase::Sample min;
217*6777b538SAndroid Build Coastguard Worker   HistogramBase::Count count;
218*6777b538SAndroid Build Coastguard Worker };
219*6777b538SAndroid Build Coastguard Worker 
220*6777b538SAndroid Build Coastguard Worker void PrintTo(const Bucket& value, std::ostream* os);
221*6777b538SAndroid Build Coastguard Worker 
222*6777b538SAndroid Build Coastguard Worker // The BucketsAre[Array]() and BucketsInclude[Array]() matchers are intended to
223*6777b538SAndroid Build Coastguard Worker // match GetAllSamples().
224*6777b538SAndroid Build Coastguard Worker //
225*6777b538SAndroid Build Coastguard Worker // Unlike the standard matchers UnorderedElementsAreArray() and IsSupersetOf(),
226*6777b538SAndroid Build Coastguard Worker // they explicitly support empty buckets (`Bucket::count == 0`). Empty buckets
227*6777b538SAndroid Build Coastguard Worker // need special handling because GetAllSamples() doesn't contain empty ones.
228*6777b538SAndroid Build Coastguard Worker 
229*6777b538SAndroid Build Coastguard Worker // BucketsAre() and BucketsAreArray() match a container that contains exactly
230*6777b538SAndroid Build Coastguard Worker // the non-empty `buckets`.
231*6777b538SAndroid Build Coastguard Worker //
232*6777b538SAndroid Build Coastguard Worker // For example,
233*6777b538SAndroid Build Coastguard Worker //   EXPECT_THAT(histogram_tester.GetAllSamples("HistogramName"),
234*6777b538SAndroid Build Coastguard Worker //               BucketsAre(Bucket(Enum::A, 0),
235*6777b538SAndroid Build Coastguard Worker //                          Bucket(Enum::B, 1),
236*6777b538SAndroid Build Coastguard Worker //                          Bucket(Enum::C, 2)));
237*6777b538SAndroid Build Coastguard Worker // - matches the actual value `{Bucket(B, 1), Bucket(C, 2)}`;
238*6777b538SAndroid Build Coastguard Worker // - does not match `{Bucket(A, n), Bucket(B, 1), Bucket(C, 2)}` for any `n`
239*6777b538SAndroid Build Coastguard Worker //   (including `n == 0`).
240*6777b538SAndroid Build Coastguard Worker template <typename BucketArray>
BucketsAreArray(BucketArray buckets)241*6777b538SAndroid Build Coastguard Worker auto BucketsAreArray(BucketArray buckets) {
242*6777b538SAndroid Build Coastguard Worker   auto non_empty_buckets = buckets;
243*6777b538SAndroid Build Coastguard Worker   std::erase_if(non_empty_buckets, [](Bucket b) { return b.count == 0; });
244*6777b538SAndroid Build Coastguard Worker   return ::testing::UnorderedElementsAreArray(non_empty_buckets);
245*6777b538SAndroid Build Coastguard Worker }
246*6777b538SAndroid Build Coastguard Worker 
247*6777b538SAndroid Build Coastguard Worker template <typename... BucketTypes>
BucketsAre(BucketTypes...buckets)248*6777b538SAndroid Build Coastguard Worker auto BucketsAre(BucketTypes... buckets) {
249*6777b538SAndroid Build Coastguard Worker   return BucketsAreArray(std::vector<Bucket>{buckets...});
250*6777b538SAndroid Build Coastguard Worker }
251*6777b538SAndroid Build Coastguard Worker 
252*6777b538SAndroid Build Coastguard Worker // BucketsInclude() and BucketsIncludeArray() are empty-bucket-friendly
253*6777b538SAndroid Build Coastguard Worker // replacements of IsSupersetOf[Array](): they match a container that contains
254*6777b538SAndroid Build Coastguard Worker // all non-empty `buckets` and none of the empty `buckets`.
255*6777b538SAndroid Build Coastguard Worker //
256*6777b538SAndroid Build Coastguard Worker // For example,
257*6777b538SAndroid Build Coastguard Worker //   EXPECT_THAT(histogram_tester.GetAllSamples("HistogramName"),
258*6777b538SAndroid Build Coastguard Worker //               BucketsInclude(Bucket(Enum::A, 0),
259*6777b538SAndroid Build Coastguard Worker //                              Bucket(Enum::B, 1),
260*6777b538SAndroid Build Coastguard Worker //                              Bucket(Enum::C, 2)));
261*6777b538SAndroid Build Coastguard Worker // - matches `{Bucket(B, 1), Bucket(C, 2), Bucket(D, 3)}`;
262*6777b538SAndroid Build Coastguard Worker // - not match `{Bucket(A, n), Bucket(B, 1), Bucket(C, 2), Bucket(D, 3)}` for
263*6777b538SAndroid Build Coastguard Worker //   any `n` (including `n == 0`).
264*6777b538SAndroid Build Coastguard Worker template <typename BucketArray>
BucketsIncludeArray(const BucketArray & buckets)265*6777b538SAndroid Build Coastguard Worker auto BucketsIncludeArray(const BucketArray& buckets) {
266*6777b538SAndroid Build Coastguard Worker   // The `empty_buckets` have `count == 0`, so the `HistogramBase::Sample`
267*6777b538SAndroid Build Coastguard Worker   // suffices.
268*6777b538SAndroid Build Coastguard Worker   std::vector<HistogramBase::Sample> empty_buckets;
269*6777b538SAndroid Build Coastguard Worker   std::vector<Bucket> non_empty_buckets;
270*6777b538SAndroid Build Coastguard Worker   for (const Bucket& b : buckets) {
271*6777b538SAndroid Build Coastguard Worker     if (b.count == 0) {
272*6777b538SAndroid Build Coastguard Worker       empty_buckets.push_back(b.min);
273*6777b538SAndroid Build Coastguard Worker     } else {
274*6777b538SAndroid Build Coastguard Worker       non_empty_buckets.push_back(b);
275*6777b538SAndroid Build Coastguard Worker     }
276*6777b538SAndroid Build Coastguard Worker   }
277*6777b538SAndroid Build Coastguard Worker   using ::testing::AllOf;
278*6777b538SAndroid Build Coastguard Worker   using ::testing::AnyOfArray;
279*6777b538SAndroid Build Coastguard Worker   using ::testing::Each;
280*6777b538SAndroid Build Coastguard Worker   using ::testing::Field;
281*6777b538SAndroid Build Coastguard Worker   using ::testing::IsSupersetOf;
282*6777b538SAndroid Build Coastguard Worker   using ::testing::Not;
283*6777b538SAndroid Build Coastguard Worker   return AllOf(
284*6777b538SAndroid Build Coastguard Worker       IsSupersetOf(non_empty_buckets),
285*6777b538SAndroid Build Coastguard Worker       Each(Field("Bucket::min", &Bucket::min, Not(AnyOfArray(empty_buckets)))));
286*6777b538SAndroid Build Coastguard Worker }
287*6777b538SAndroid Build Coastguard Worker 
288*6777b538SAndroid Build Coastguard Worker template <typename... BucketTypes>
BucketsInclude(BucketTypes...buckets)289*6777b538SAndroid Build Coastguard Worker auto BucketsInclude(BucketTypes... buckets) {
290*6777b538SAndroid Build Coastguard Worker   return BucketsIncludeArray(std::vector<Bucket>{buckets...});
291*6777b538SAndroid Build Coastguard Worker }
292*6777b538SAndroid Build Coastguard Worker 
293*6777b538SAndroid Build Coastguard Worker }  // namespace base
294*6777b538SAndroid Build Coastguard Worker 
295*6777b538SAndroid Build Coastguard Worker #endif  // BASE_TEST_METRICS_HISTOGRAM_TESTER_H_
296