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