xref: /aosp_15_r20/external/cronet/base/metrics/sparse_histogram_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 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 #include "base/metrics/sparse_histogram.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <memory>
8*6777b538SAndroid Build Coastguard Worker #include <string>
9*6777b538SAndroid Build Coastguard Worker #include <string_view>
10*6777b538SAndroid Build Coastguard Worker #include <vector>
11*6777b538SAndroid Build Coastguard Worker 
12*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram_base.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram_functions.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram_samples.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/metrics/metrics_hashes.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/metrics/persistent_histogram_allocator.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/metrics/persistent_memory_allocator.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/metrics/sample_map.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/metrics/statistics_recorder.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/pickle.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
24*6777b538SAndroid Build Coastguard Worker #include "base/values.h"
25*6777b538SAndroid Build Coastguard Worker #include "testing/gmock/include/gmock/gmock.h"
26*6777b538SAndroid Build Coastguard Worker 
27*6777b538SAndroid Build Coastguard Worker namespace base {
28*6777b538SAndroid Build Coastguard Worker 
29*6777b538SAndroid Build Coastguard Worker // Test parameter indicates if a persistent memory allocator should be used
30*6777b538SAndroid Build Coastguard Worker // for histogram allocation. False will allocate histograms from the process
31*6777b538SAndroid Build Coastguard Worker // heap.
32*6777b538SAndroid Build Coastguard Worker class SparseHistogramTest : public testing::TestWithParam<bool> {
33*6777b538SAndroid Build Coastguard Worker  public:
SparseHistogramTest()34*6777b538SAndroid Build Coastguard Worker   SparseHistogramTest() : use_persistent_histogram_allocator_(GetParam()) {}
35*6777b538SAndroid Build Coastguard Worker   SparseHistogramTest(const SparseHistogramTest&) = delete;
36*6777b538SAndroid Build Coastguard Worker   SparseHistogramTest& operator=(const SparseHistogramTest&) = delete;
37*6777b538SAndroid Build Coastguard Worker 
38*6777b538SAndroid Build Coastguard Worker  protected:
39*6777b538SAndroid Build Coastguard Worker   const int32_t kAllocatorMemorySize = 8 << 20;  // 8 MiB
40*6777b538SAndroid Build Coastguard Worker 
41*6777b538SAndroid Build Coastguard Worker   using CountAndBucketData = base::SparseHistogram::CountAndBucketData;
42*6777b538SAndroid Build Coastguard Worker 
SetUp()43*6777b538SAndroid Build Coastguard Worker   void SetUp() override {
44*6777b538SAndroid Build Coastguard Worker     if (use_persistent_histogram_allocator_)
45*6777b538SAndroid Build Coastguard Worker       CreatePersistentMemoryAllocator();
46*6777b538SAndroid Build Coastguard Worker 
47*6777b538SAndroid Build Coastguard Worker     // Each test will have a clean state (no Histogram / BucketRanges
48*6777b538SAndroid Build Coastguard Worker     // registered).
49*6777b538SAndroid Build Coastguard Worker     InitializeStatisticsRecorder();
50*6777b538SAndroid Build Coastguard Worker   }
51*6777b538SAndroid Build Coastguard Worker 
TearDown()52*6777b538SAndroid Build Coastguard Worker   void TearDown() override {
53*6777b538SAndroid Build Coastguard Worker     if (allocator_) {
54*6777b538SAndroid Build Coastguard Worker       ASSERT_FALSE(allocator_->IsFull());
55*6777b538SAndroid Build Coastguard Worker       ASSERT_FALSE(allocator_->IsCorrupt());
56*6777b538SAndroid Build Coastguard Worker     }
57*6777b538SAndroid Build Coastguard Worker     UninitializeStatisticsRecorder();
58*6777b538SAndroid Build Coastguard Worker     DestroyPersistentMemoryAllocator();
59*6777b538SAndroid Build Coastguard Worker   }
60*6777b538SAndroid Build Coastguard Worker 
InitializeStatisticsRecorder()61*6777b538SAndroid Build Coastguard Worker   void InitializeStatisticsRecorder() {
62*6777b538SAndroid Build Coastguard Worker     DCHECK(!statistics_recorder_);
63*6777b538SAndroid Build Coastguard Worker     statistics_recorder_ = StatisticsRecorder::CreateTemporaryForTesting();
64*6777b538SAndroid Build Coastguard Worker   }
65*6777b538SAndroid Build Coastguard Worker 
UninitializeStatisticsRecorder()66*6777b538SAndroid Build Coastguard Worker   void UninitializeStatisticsRecorder() { statistics_recorder_.reset(); }
67*6777b538SAndroid Build Coastguard Worker 
CreatePersistentMemoryAllocator()68*6777b538SAndroid Build Coastguard Worker   void CreatePersistentMemoryAllocator() {
69*6777b538SAndroid Build Coastguard Worker     GlobalHistogramAllocator::CreateWithLocalMemory(
70*6777b538SAndroid Build Coastguard Worker         kAllocatorMemorySize, 0, "SparseHistogramAllocatorTest");
71*6777b538SAndroid Build Coastguard Worker     allocator_ = GlobalHistogramAllocator::Get()->memory_allocator();
72*6777b538SAndroid Build Coastguard Worker   }
73*6777b538SAndroid Build Coastguard Worker 
DestroyPersistentMemoryAllocator()74*6777b538SAndroid Build Coastguard Worker   void DestroyPersistentMemoryAllocator() {
75*6777b538SAndroid Build Coastguard Worker     allocator_ = nullptr;
76*6777b538SAndroid Build Coastguard Worker     GlobalHistogramAllocator::ReleaseForTesting();
77*6777b538SAndroid Build Coastguard Worker   }
78*6777b538SAndroid Build Coastguard Worker 
NewSparseHistogram(const char * name)79*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<SparseHistogram> NewSparseHistogram(const char* name) {
80*6777b538SAndroid Build Coastguard Worker     // std::make_unique can't access protected ctor so do it manually. This
81*6777b538SAndroid Build Coastguard Worker     // test class is a friend so can access it.
82*6777b538SAndroid Build Coastguard Worker     return std::unique_ptr<SparseHistogram>(new SparseHistogram(name));
83*6777b538SAndroid Build Coastguard Worker   }
84*6777b538SAndroid Build Coastguard Worker 
GetCountAndBucketData(SparseHistogram * histogram)85*6777b538SAndroid Build Coastguard Worker   CountAndBucketData GetCountAndBucketData(SparseHistogram* histogram) {
86*6777b538SAndroid Build Coastguard Worker     // A simple wrapper around |GetCountAndBucketData| to make it visible for
87*6777b538SAndroid Build Coastguard Worker     // testing.
88*6777b538SAndroid Build Coastguard Worker     return histogram->GetCountAndBucketData();
89*6777b538SAndroid Build Coastguard Worker   }
90*6777b538SAndroid Build Coastguard Worker 
91*6777b538SAndroid Build Coastguard Worker   const bool use_persistent_histogram_allocator_;
92*6777b538SAndroid Build Coastguard Worker 
93*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<StatisticsRecorder> statistics_recorder_;
94*6777b538SAndroid Build Coastguard Worker   raw_ptr<PersistentMemoryAllocator> allocator_ = nullptr;
95*6777b538SAndroid Build Coastguard Worker };
96*6777b538SAndroid Build Coastguard Worker 
97*6777b538SAndroid Build Coastguard Worker // Run all HistogramTest cases with both heap and persistent memory.
98*6777b538SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(HeapAndPersistent,
99*6777b538SAndroid Build Coastguard Worker                          SparseHistogramTest,
100*6777b538SAndroid Build Coastguard Worker                          testing::Bool());
101*6777b538SAndroid Build Coastguard Worker 
TEST_P(SparseHistogramTest,BasicTest)102*6777b538SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, BasicTest) {
103*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse"));
104*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<HistogramSamples> snapshot(histogram->SnapshotSamples());
105*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0, snapshot->TotalCount());
106*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0, snapshot->sum());
107*6777b538SAndroid Build Coastguard Worker 
108*6777b538SAndroid Build Coastguard Worker   histogram->Add(100);
109*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<HistogramSamples> snapshot1(histogram->SnapshotSamples());
110*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(1, snapshot1->TotalCount());
111*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(1, snapshot1->GetCount(100));
112*6777b538SAndroid Build Coastguard Worker 
113*6777b538SAndroid Build Coastguard Worker   histogram->Add(100);
114*6777b538SAndroid Build Coastguard Worker   histogram->Add(101);
115*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<HistogramSamples> snapshot2(histogram->SnapshotSamples());
116*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(3, snapshot2->TotalCount());
117*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(2, snapshot2->GetCount(100));
118*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(1, snapshot2->GetCount(101));
119*6777b538SAndroid Build Coastguard Worker }
120*6777b538SAndroid Build Coastguard Worker 
TEST_P(SparseHistogramTest,BasicTestAddCount)121*6777b538SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, BasicTestAddCount) {
122*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse"));
123*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<HistogramSamples> snapshot(histogram->SnapshotSamples());
124*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0, snapshot->TotalCount());
125*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0, snapshot->sum());
126*6777b538SAndroid Build Coastguard Worker 
127*6777b538SAndroid Build Coastguard Worker   histogram->AddCount(100, 15);
128*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<HistogramSamples> snapshot1(histogram->SnapshotSamples());
129*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(15, snapshot1->TotalCount());
130*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(15, snapshot1->GetCount(100));
131*6777b538SAndroid Build Coastguard Worker 
132*6777b538SAndroid Build Coastguard Worker   histogram->AddCount(100, 15);
133*6777b538SAndroid Build Coastguard Worker   histogram->AddCount(101, 25);
134*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<HistogramSamples> snapshot2(histogram->SnapshotSamples());
135*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(55, snapshot2->TotalCount());
136*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(30, snapshot2->GetCount(100));
137*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(25, snapshot2->GetCount(101));
138*6777b538SAndroid Build Coastguard Worker }
139*6777b538SAndroid Build Coastguard Worker 
140*6777b538SAndroid Build Coastguard Worker // Check that delta calculations work correctly with SnapshotUnloggedSamples()
141*6777b538SAndroid Build Coastguard Worker // and MarkSamplesAsLogged().
TEST_P(SparseHistogramTest,UnloggedSamplesTest)142*6777b538SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, UnloggedSamplesTest) {
143*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse"));
144*6777b538SAndroid Build Coastguard Worker   histogram->AddCount(1, 1);
145*6777b538SAndroid Build Coastguard Worker   histogram->AddCount(2, 2);
146*6777b538SAndroid Build Coastguard Worker 
147*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<HistogramSamples> samples =
148*6777b538SAndroid Build Coastguard Worker       histogram->SnapshotUnloggedSamples();
149*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(3, samples->TotalCount());
150*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(1, samples->GetCount(1));
151*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(2, samples->GetCount(2));
152*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(samples->TotalCount(), samples->redundant_count());
153*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(5, samples->sum());
154*6777b538SAndroid Build Coastguard Worker 
155*6777b538SAndroid Build Coastguard Worker   // Snapshot unlogged samples again, which would be the same as above.
156*6777b538SAndroid Build Coastguard Worker   samples = histogram->SnapshotUnloggedSamples();
157*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(3, samples->TotalCount());
158*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(1, samples->GetCount(1));
159*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(2, samples->GetCount(2));
160*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(samples->TotalCount(), samples->redundant_count());
161*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(5, samples->sum());
162*6777b538SAndroid Build Coastguard Worker 
163*6777b538SAndroid Build Coastguard Worker   // Verify that marking the samples as logged works correctly, and that
164*6777b538SAndroid Build Coastguard Worker   // SnapshotDelta() will not pick up the samples.
165*6777b538SAndroid Build Coastguard Worker   histogram->MarkSamplesAsLogged(*samples);
166*6777b538SAndroid Build Coastguard Worker   samples = histogram->SnapshotUnloggedSamples();
167*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0, samples->TotalCount());
168*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(samples->TotalCount(), samples->redundant_count());
169*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0, samples->sum());
170*6777b538SAndroid Build Coastguard Worker   samples = histogram->SnapshotDelta();
171*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0, samples->TotalCount());
172*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(samples->TotalCount(), samples->redundant_count());
173*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0, samples->sum());
174*6777b538SAndroid Build Coastguard Worker 
175*6777b538SAndroid Build Coastguard Worker   // Similarly, verify that SnapshotDelta() marks the samples as logged.
176*6777b538SAndroid Build Coastguard Worker   histogram->AddCount(1, 1);
177*6777b538SAndroid Build Coastguard Worker   histogram->AddCount(2, 2);
178*6777b538SAndroid Build Coastguard Worker   samples = histogram->SnapshotDelta();
179*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(3, samples->TotalCount());
180*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(1, samples->GetCount(1));
181*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(2, samples->GetCount(2));
182*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(samples->TotalCount(), samples->redundant_count());
183*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(5, samples->sum());
184*6777b538SAndroid Build Coastguard Worker   samples = histogram->SnapshotUnloggedSamples();
185*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0, samples->TotalCount());
186*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(samples->TotalCount(), samples->redundant_count());
187*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0, samples->sum());
188*6777b538SAndroid Build Coastguard Worker 
189*6777b538SAndroid Build Coastguard Worker   // Verify that the logged samples contain everything emitted.
190*6777b538SAndroid Build Coastguard Worker   samples = histogram->SnapshotSamples();
191*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(6, samples->TotalCount());
192*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(samples->TotalCount(), samples->redundant_count());
193*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(2, samples->GetCount(1));
194*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(4, samples->GetCount(2));
195*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(10, samples->sum());
196*6777b538SAndroid Build Coastguard Worker }
197*6777b538SAndroid Build Coastguard Worker 
198*6777b538SAndroid Build Coastguard Worker // Check that IsDefinitelyEmpty() works with the results of SnapshotDelta().
TEST_P(SparseHistogramTest,IsDefinitelyEmpty_SnapshotDelta)199*6777b538SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, IsDefinitelyEmpty_SnapshotDelta) {
200*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse"));
201*6777b538SAndroid Build Coastguard Worker 
202*6777b538SAndroid Build Coastguard Worker   // No samples initially.
203*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(histogram->SnapshotDelta()->IsDefinitelyEmpty());
204*6777b538SAndroid Build Coastguard Worker 
205*6777b538SAndroid Build Coastguard Worker   histogram->Add(1);
206*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(histogram->SnapshotDelta()->IsDefinitelyEmpty());
207*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(histogram->SnapshotDelta()->IsDefinitelyEmpty());
208*6777b538SAndroid Build Coastguard Worker   histogram->Add(10);
209*6777b538SAndroid Build Coastguard Worker   histogram->Add(10);
210*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(histogram->SnapshotDelta()->IsDefinitelyEmpty());
211*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(histogram->SnapshotDelta()->IsDefinitelyEmpty());
212*6777b538SAndroid Build Coastguard Worker   histogram->Add(1);
213*6777b538SAndroid Build Coastguard Worker   histogram->Add(50);
214*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(histogram->SnapshotDelta()->IsDefinitelyEmpty());
215*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(histogram->SnapshotDelta()->IsDefinitelyEmpty());
216*6777b538SAndroid Build Coastguard Worker }
217*6777b538SAndroid Build Coastguard Worker 
TEST_P(SparseHistogramTest,AddCount_LargeValuesDontOverflow)218*6777b538SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, AddCount_LargeValuesDontOverflow) {
219*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse"));
220*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<HistogramSamples> snapshot(histogram->SnapshotSamples());
221*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0, snapshot->TotalCount());
222*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0, snapshot->sum());
223*6777b538SAndroid Build Coastguard Worker 
224*6777b538SAndroid Build Coastguard Worker   histogram->AddCount(1000000000, 15);
225*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<HistogramSamples> snapshot1(histogram->SnapshotSamples());
226*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(15, snapshot1->TotalCount());
227*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(15, snapshot1->GetCount(1000000000));
228*6777b538SAndroid Build Coastguard Worker 
229*6777b538SAndroid Build Coastguard Worker   histogram->AddCount(1000000000, 15);
230*6777b538SAndroid Build Coastguard Worker   histogram->AddCount(1010000000, 25);
231*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<HistogramSamples> snapshot2(histogram->SnapshotSamples());
232*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(55, snapshot2->TotalCount());
233*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(30, snapshot2->GetCount(1000000000));
234*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(25, snapshot2->GetCount(1010000000));
235*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(55250000000LL, snapshot2->sum());
236*6777b538SAndroid Build Coastguard Worker }
237*6777b538SAndroid Build Coastguard Worker 
238*6777b538SAndroid Build Coastguard Worker // Make sure that counts returned by Histogram::SnapshotDelta do not overflow
239*6777b538SAndroid Build Coastguard Worker // even when a total count (returned by Histogram::SnapshotSample) does.
TEST_P(SparseHistogramTest,AddCount_LargeCountsDontOverflow)240*6777b538SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, AddCount_LargeCountsDontOverflow) {
241*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse"));
242*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<HistogramSamples> snapshot(histogram->SnapshotSamples());
243*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0, snapshot->TotalCount());
244*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0, snapshot->sum());
245*6777b538SAndroid Build Coastguard Worker 
246*6777b538SAndroid Build Coastguard Worker   const int count = (1 << 30) - 1;
247*6777b538SAndroid Build Coastguard Worker 
248*6777b538SAndroid Build Coastguard Worker   // Repeat N times to make sure that there is no internal value overflow.
249*6777b538SAndroid Build Coastguard Worker   for (int i = 0; i < 10; ++i) {
250*6777b538SAndroid Build Coastguard Worker     histogram->AddCount(42, count);
251*6777b538SAndroid Build Coastguard Worker     std::unique_ptr<HistogramSamples> samples = histogram->SnapshotDelta();
252*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(count, samples->TotalCount());
253*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(count, samples->GetCount(42));
254*6777b538SAndroid Build Coastguard Worker   }
255*6777b538SAndroid Build Coastguard Worker }
256*6777b538SAndroid Build Coastguard Worker 
TEST_P(SparseHistogramTest,MacroBasicTest)257*6777b538SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, MacroBasicTest) {
258*6777b538SAndroid Build Coastguard Worker   UmaHistogramSparse("Sparse", 100);
259*6777b538SAndroid Build Coastguard Worker   UmaHistogramSparse("Sparse", 200);
260*6777b538SAndroid Build Coastguard Worker   UmaHistogramSparse("Sparse", 100);
261*6777b538SAndroid Build Coastguard Worker 
262*6777b538SAndroid Build Coastguard Worker   const StatisticsRecorder::Histograms histograms =
263*6777b538SAndroid Build Coastguard Worker       StatisticsRecorder::GetHistograms();
264*6777b538SAndroid Build Coastguard Worker 
265*6777b538SAndroid Build Coastguard Worker   ASSERT_THAT(histograms, testing::SizeIs(1));
266*6777b538SAndroid Build Coastguard Worker   const HistogramBase* const sparse_histogram = histograms[0];
267*6777b538SAndroid Build Coastguard Worker 
268*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(SPARSE_HISTOGRAM, sparse_histogram->GetHistogramType());
269*6777b538SAndroid Build Coastguard Worker   EXPECT_STREQ("Sparse", sparse_histogram->histogram_name());
270*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(
271*6777b538SAndroid Build Coastguard Worker       HistogramBase::kUmaTargetedHistogramFlag |
272*6777b538SAndroid Build Coastguard Worker           (use_persistent_histogram_allocator_ ? HistogramBase::kIsPersistent
273*6777b538SAndroid Build Coastguard Worker                                                : 0),
274*6777b538SAndroid Build Coastguard Worker       sparse_histogram->flags());
275*6777b538SAndroid Build Coastguard Worker 
276*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<HistogramSamples> samples =
277*6777b538SAndroid Build Coastguard Worker       sparse_histogram->SnapshotSamples();
278*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(3, samples->TotalCount());
279*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(2, samples->GetCount(100));
280*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(1, samples->GetCount(200));
281*6777b538SAndroid Build Coastguard Worker }
282*6777b538SAndroid Build Coastguard Worker 
TEST_P(SparseHistogramTest,MacroInLoopTest)283*6777b538SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, MacroInLoopTest) {
284*6777b538SAndroid Build Coastguard Worker   // Unlike the macros in histogram.h, SparseHistogram macros can have a
285*6777b538SAndroid Build Coastguard Worker   // variable as histogram name.
286*6777b538SAndroid Build Coastguard Worker   for (int i = 0; i < 2; i++) {
287*6777b538SAndroid Build Coastguard Worker     UmaHistogramSparse(StringPrintf("Sparse%d", i), 100);
288*6777b538SAndroid Build Coastguard Worker   }
289*6777b538SAndroid Build Coastguard Worker 
290*6777b538SAndroid Build Coastguard Worker   const StatisticsRecorder::Histograms histograms =
291*6777b538SAndroid Build Coastguard Worker       StatisticsRecorder::Sort(StatisticsRecorder::GetHistograms());
292*6777b538SAndroid Build Coastguard Worker   ASSERT_THAT(histograms, testing::SizeIs(2));
293*6777b538SAndroid Build Coastguard Worker   EXPECT_STREQ(histograms[0]->histogram_name(), "Sparse0");
294*6777b538SAndroid Build Coastguard Worker   EXPECT_STREQ(histograms[1]->histogram_name(), "Sparse1");
295*6777b538SAndroid Build Coastguard Worker }
296*6777b538SAndroid Build Coastguard Worker 
TEST_P(SparseHistogramTest,Serialize)297*6777b538SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, Serialize) {
298*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse"));
299*6777b538SAndroid Build Coastguard Worker   histogram->SetFlags(HistogramBase::kIPCSerializationSourceFlag);
300*6777b538SAndroid Build Coastguard Worker 
301*6777b538SAndroid Build Coastguard Worker   Pickle pickle;
302*6777b538SAndroid Build Coastguard Worker   histogram->SerializeInfo(&pickle);
303*6777b538SAndroid Build Coastguard Worker 
304*6777b538SAndroid Build Coastguard Worker   PickleIterator iter(pickle);
305*6777b538SAndroid Build Coastguard Worker 
306*6777b538SAndroid Build Coastguard Worker   int type;
307*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(iter.ReadInt(&type));
308*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(SPARSE_HISTOGRAM, type);
309*6777b538SAndroid Build Coastguard Worker 
310*6777b538SAndroid Build Coastguard Worker   std::string name;
311*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(iter.ReadString(&name));
312*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("Sparse", name);
313*6777b538SAndroid Build Coastguard Worker 
314*6777b538SAndroid Build Coastguard Worker   int flag;
315*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(iter.ReadInt(&flag));
316*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(HistogramBase::kIPCSerializationSourceFlag, flag);
317*6777b538SAndroid Build Coastguard Worker 
318*6777b538SAndroid Build Coastguard Worker   // No more data in the pickle.
319*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(iter.SkipBytes(1));
320*6777b538SAndroid Build Coastguard Worker }
321*6777b538SAndroid Build Coastguard Worker 
322*6777b538SAndroid Build Coastguard Worker // Ensure that race conditions that cause multiple, identical sparse histograms
323*6777b538SAndroid Build Coastguard Worker // to be created will safely resolve to a single one.
TEST_P(SparseHistogramTest,DuplicationSafety)324*6777b538SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, DuplicationSafety) {
325*6777b538SAndroid Build Coastguard Worker   const char histogram_name[] = "Duplicated";
326*6777b538SAndroid Build Coastguard Worker   size_t histogram_count = StatisticsRecorder::GetHistogramCount();
327*6777b538SAndroid Build Coastguard Worker 
328*6777b538SAndroid Build Coastguard Worker   // Create a histogram that we will later duplicate.
329*6777b538SAndroid Build Coastguard Worker   HistogramBase* original =
330*6777b538SAndroid Build Coastguard Worker       SparseHistogram::FactoryGet(histogram_name, HistogramBase::kNoFlags);
331*6777b538SAndroid Build Coastguard Worker   ++histogram_count;
332*6777b538SAndroid Build Coastguard Worker   DCHECK_EQ(histogram_count, StatisticsRecorder::GetHistogramCount());
333*6777b538SAndroid Build Coastguard Worker   original->Add(1);
334*6777b538SAndroid Build Coastguard Worker 
335*6777b538SAndroid Build Coastguard Worker   // Create a duplicate. This has to happen differently depending on where the
336*6777b538SAndroid Build Coastguard Worker   // memory is taken from.
337*6777b538SAndroid Build Coastguard Worker   if (use_persistent_histogram_allocator_) {
338*6777b538SAndroid Build Coastguard Worker     // To allocate from persistent memory, clear the last_created reference in
339*6777b538SAndroid Build Coastguard Worker     // the GlobalHistogramAllocator. This will cause an Import to recreate
340*6777b538SAndroid Build Coastguard Worker     // the just-created histogram which will then be released as a duplicate.
341*6777b538SAndroid Build Coastguard Worker     GlobalHistogramAllocator::Get()->ClearLastCreatedReferenceForTesting();
342*6777b538SAndroid Build Coastguard Worker     // Creating a different histogram will first do an Import to ensure it
343*6777b538SAndroid Build Coastguard Worker     // hasn't been created elsewhere, triggering the duplication and release.
344*6777b538SAndroid Build Coastguard Worker     SparseHistogram::FactoryGet("something.new", HistogramBase::kNoFlags);
345*6777b538SAndroid Build Coastguard Worker     ++histogram_count;
346*6777b538SAndroid Build Coastguard Worker   } else {
347*6777b538SAndroid Build Coastguard Worker     // To allocate from the heap, just call the (private) constructor directly.
348*6777b538SAndroid Build Coastguard Worker     // Delete it immediately like would have happened within FactoryGet();
349*6777b538SAndroid Build Coastguard Worker     std::unique_ptr<SparseHistogram> something =
350*6777b538SAndroid Build Coastguard Worker         NewSparseHistogram(histogram_name);
351*6777b538SAndroid Build Coastguard Worker     DCHECK_NE(original, something.get());
352*6777b538SAndroid Build Coastguard Worker   }
353*6777b538SAndroid Build Coastguard Worker   DCHECK_EQ(histogram_count, StatisticsRecorder::GetHistogramCount());
354*6777b538SAndroid Build Coastguard Worker 
355*6777b538SAndroid Build Coastguard Worker   // Re-creating the histogram via FactoryGet() will return the same one.
356*6777b538SAndroid Build Coastguard Worker   HistogramBase* duplicate =
357*6777b538SAndroid Build Coastguard Worker       SparseHistogram::FactoryGet(histogram_name, HistogramBase::kNoFlags);
358*6777b538SAndroid Build Coastguard Worker   DCHECK_EQ(original, duplicate);
359*6777b538SAndroid Build Coastguard Worker   DCHECK_EQ(histogram_count, StatisticsRecorder::GetHistogramCount());
360*6777b538SAndroid Build Coastguard Worker   duplicate->Add(2);
361*6777b538SAndroid Build Coastguard Worker 
362*6777b538SAndroid Build Coastguard Worker   // Ensure that original histograms are still cross-functional.
363*6777b538SAndroid Build Coastguard Worker   original->Add(2);
364*6777b538SAndroid Build Coastguard Worker   duplicate->Add(1);
365*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<HistogramSamples> snapshot_orig = original->SnapshotSamples();
366*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<HistogramSamples> snapshot_dup = duplicate->SnapshotSamples();
367*6777b538SAndroid Build Coastguard Worker   DCHECK_EQ(2, snapshot_orig->GetCount(2));
368*6777b538SAndroid Build Coastguard Worker   DCHECK_EQ(2, snapshot_dup->GetCount(1));
369*6777b538SAndroid Build Coastguard Worker }
370*6777b538SAndroid Build Coastguard Worker 
TEST_P(SparseHistogramTest,FactoryTime)371*6777b538SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, FactoryTime) {
372*6777b538SAndroid Build Coastguard Worker   const int kTestCreateCount = 1 << 10;  // Must be power-of-2.
373*6777b538SAndroid Build Coastguard Worker   const int kTestLookupCount = 100000;
374*6777b538SAndroid Build Coastguard Worker   const int kTestAddCount = 100000;
375*6777b538SAndroid Build Coastguard Worker 
376*6777b538SAndroid Build Coastguard Worker   // Create all histogram names in advance for accurate timing below.
377*6777b538SAndroid Build Coastguard Worker   std::vector<std::string> histogram_names;
378*6777b538SAndroid Build Coastguard Worker   for (int i = 0; i < kTestCreateCount; ++i) {
379*6777b538SAndroid Build Coastguard Worker     histogram_names.push_back(
380*6777b538SAndroid Build Coastguard Worker         StringPrintf("TestHistogram.%d", i % kTestCreateCount));
381*6777b538SAndroid Build Coastguard Worker   }
382*6777b538SAndroid Build Coastguard Worker 
383*6777b538SAndroid Build Coastguard Worker   // Calculate cost of creating histograms.
384*6777b538SAndroid Build Coastguard Worker   TimeTicks create_start = TimeTicks::Now();
385*6777b538SAndroid Build Coastguard Worker   for (int i = 0; i < kTestCreateCount; ++i)
386*6777b538SAndroid Build Coastguard Worker     SparseHistogram::FactoryGet(histogram_names[i], HistogramBase::kNoFlags);
387*6777b538SAndroid Build Coastguard Worker   TimeDelta create_ticks = TimeTicks::Now() - create_start;
388*6777b538SAndroid Build Coastguard Worker   int64_t create_ms = create_ticks.InMilliseconds();
389*6777b538SAndroid Build Coastguard Worker 
390*6777b538SAndroid Build Coastguard Worker   VLOG(1) << kTestCreateCount << " histogram creations took " << create_ms
391*6777b538SAndroid Build Coastguard Worker           << "ms or about " << (create_ms * 1000000) / kTestCreateCount
392*6777b538SAndroid Build Coastguard Worker           << "ns each.";
393*6777b538SAndroid Build Coastguard Worker 
394*6777b538SAndroid Build Coastguard Worker   // Calculate cost of looking up existing histograms.
395*6777b538SAndroid Build Coastguard Worker   TimeTicks lookup_start = TimeTicks::Now();
396*6777b538SAndroid Build Coastguard Worker   for (int i = 0; i < kTestLookupCount; ++i) {
397*6777b538SAndroid Build Coastguard Worker     // 6007 is co-prime with kTestCreateCount and so will do lookups in an
398*6777b538SAndroid Build Coastguard Worker     // order less likely to be cacheable (but still hit them all) should the
399*6777b538SAndroid Build Coastguard Worker     // underlying storage use the exact histogram name as the key.
400*6777b538SAndroid Build Coastguard Worker     const int i_mult = 6007;
401*6777b538SAndroid Build Coastguard Worker     static_assert(i_mult < INT_MAX / kTestCreateCount, "Multiplier too big");
402*6777b538SAndroid Build Coastguard Worker     int index = (i * i_mult) & (kTestCreateCount - 1);
403*6777b538SAndroid Build Coastguard Worker     SparseHistogram::FactoryGet(histogram_names[index],
404*6777b538SAndroid Build Coastguard Worker                                 HistogramBase::kNoFlags);
405*6777b538SAndroid Build Coastguard Worker   }
406*6777b538SAndroid Build Coastguard Worker   TimeDelta lookup_ticks = TimeTicks::Now() - lookup_start;
407*6777b538SAndroid Build Coastguard Worker   int64_t lookup_ms = lookup_ticks.InMilliseconds();
408*6777b538SAndroid Build Coastguard Worker 
409*6777b538SAndroid Build Coastguard Worker   VLOG(1) << kTestLookupCount << " histogram lookups took " << lookup_ms
410*6777b538SAndroid Build Coastguard Worker           << "ms or about " << (lookup_ms * 1000000) / kTestLookupCount
411*6777b538SAndroid Build Coastguard Worker           << "ns each.";
412*6777b538SAndroid Build Coastguard Worker 
413*6777b538SAndroid Build Coastguard Worker   // Calculate cost of accessing histograms.
414*6777b538SAndroid Build Coastguard Worker   HistogramBase* histogram =
415*6777b538SAndroid Build Coastguard Worker       SparseHistogram::FactoryGet(histogram_names[0], HistogramBase::kNoFlags);
416*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(histogram);
417*6777b538SAndroid Build Coastguard Worker   TimeTicks add_start = TimeTicks::Now();
418*6777b538SAndroid Build Coastguard Worker   for (int i = 0; i < kTestAddCount; ++i)
419*6777b538SAndroid Build Coastguard Worker     histogram->Add(i & 127);
420*6777b538SAndroid Build Coastguard Worker   TimeDelta add_ticks = TimeTicks::Now() - add_start;
421*6777b538SAndroid Build Coastguard Worker   int64_t add_ms = add_ticks.InMilliseconds();
422*6777b538SAndroid Build Coastguard Worker 
423*6777b538SAndroid Build Coastguard Worker   VLOG(1) << kTestAddCount << " histogram adds took " << add_ms
424*6777b538SAndroid Build Coastguard Worker           << "ms or about " << (add_ms * 1000000) / kTestAddCount << "ns each.";
425*6777b538SAndroid Build Coastguard Worker }
426*6777b538SAndroid Build Coastguard Worker 
TEST_P(SparseHistogramTest,ExtremeValues)427*6777b538SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, ExtremeValues) {
428*6777b538SAndroid Build Coastguard Worker   static const struct {
429*6777b538SAndroid Build Coastguard Worker     Histogram::Sample sample;
430*6777b538SAndroid Build Coastguard Worker     int64_t expected_max;
431*6777b538SAndroid Build Coastguard Worker   } cases[] = {
432*6777b538SAndroid Build Coastguard Worker       // Note: We use -2147483647 - 1 rather than -2147483648 because the later
433*6777b538SAndroid Build Coastguard Worker       // is interpreted as - operator applied to 2147483648 and the latter can't
434*6777b538SAndroid Build Coastguard Worker       // be represented as an int32 and causes a warning.
435*6777b538SAndroid Build Coastguard Worker       {-2147483647 - 1, -2147483647LL},
436*6777b538SAndroid Build Coastguard Worker       {0, 1},
437*6777b538SAndroid Build Coastguard Worker       {2147483647, 2147483648LL},
438*6777b538SAndroid Build Coastguard Worker   };
439*6777b538SAndroid Build Coastguard Worker 
440*6777b538SAndroid Build Coastguard Worker   for (size_t i = 0; i < std::size(cases); ++i) {
441*6777b538SAndroid Build Coastguard Worker     HistogramBase* histogram =
442*6777b538SAndroid Build Coastguard Worker         SparseHistogram::FactoryGet(StringPrintf("ExtremeValues_%zu", i),
443*6777b538SAndroid Build Coastguard Worker                                     HistogramBase::kUmaTargetedHistogramFlag);
444*6777b538SAndroid Build Coastguard Worker     histogram->Add(cases[i].sample);
445*6777b538SAndroid Build Coastguard Worker 
446*6777b538SAndroid Build Coastguard Worker     std::unique_ptr<HistogramSamples> snapshot = histogram->SnapshotSamples();
447*6777b538SAndroid Build Coastguard Worker     std::unique_ptr<SampleCountIterator> it = snapshot->Iterator();
448*6777b538SAndroid Build Coastguard Worker     ASSERT_FALSE(it->Done());
449*6777b538SAndroid Build Coastguard Worker 
450*6777b538SAndroid Build Coastguard Worker     base::Histogram::Sample min;
451*6777b538SAndroid Build Coastguard Worker     int64_t max;
452*6777b538SAndroid Build Coastguard Worker     base::Histogram::Count count;
453*6777b538SAndroid Build Coastguard Worker     it->Get(&min, &max, &count);
454*6777b538SAndroid Build Coastguard Worker 
455*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(1, count);
456*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(cases[i].sample, min);
457*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(cases[i].expected_max, max);
458*6777b538SAndroid Build Coastguard Worker 
459*6777b538SAndroid Build Coastguard Worker     it->Next();
460*6777b538SAndroid Build Coastguard Worker     EXPECT_TRUE(it->Done());
461*6777b538SAndroid Build Coastguard Worker   }
462*6777b538SAndroid Build Coastguard Worker }
463*6777b538SAndroid Build Coastguard Worker 
TEST_P(SparseHistogramTest,HistogramNameHash)464*6777b538SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, HistogramNameHash) {
465*6777b538SAndroid Build Coastguard Worker   const char kName[] = "TestName";
466*6777b538SAndroid Build Coastguard Worker   HistogramBase* histogram = SparseHistogram::FactoryGet(
467*6777b538SAndroid Build Coastguard Worker       kName, HistogramBase::kUmaTargetedHistogramFlag);
468*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(histogram->name_hash(), HashMetricName(kName));
469*6777b538SAndroid Build Coastguard Worker }
470*6777b538SAndroid Build Coastguard Worker 
TEST_P(SparseHistogramTest,CheckGetCountAndBucketData)471*6777b538SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, CheckGetCountAndBucketData) {
472*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse"));
473*6777b538SAndroid Build Coastguard Worker   // Add samples in reverse order and make sure the output is in correct order.
474*6777b538SAndroid Build Coastguard Worker   histogram->AddCount(/*sample=*/200, /*count=*/15);
475*6777b538SAndroid Build Coastguard Worker   histogram->AddCount(/*sample=*/100, /*count=*/5);
476*6777b538SAndroid Build Coastguard Worker   // Add samples to the same bucket and make sure they'll be aggregated.
477*6777b538SAndroid Build Coastguard Worker   histogram->AddCount(/*sample=*/100, /*count=*/5);
478*6777b538SAndroid Build Coastguard Worker 
479*6777b538SAndroid Build Coastguard Worker   const CountAndBucketData count_and_data_bucket =
480*6777b538SAndroid Build Coastguard Worker       GetCountAndBucketData(histogram.get());
481*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(25, count_and_data_bucket.count);
482*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(4000, count_and_data_bucket.sum);
483*6777b538SAndroid Build Coastguard Worker 
484*6777b538SAndroid Build Coastguard Worker   const base::Value::List& buckets_list = count_and_data_bucket.buckets;
485*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(2u, buckets_list.size());
486*6777b538SAndroid Build Coastguard Worker 
487*6777b538SAndroid Build Coastguard Worker   // Check the first bucket.
488*6777b538SAndroid Build Coastguard Worker   const base::Value::Dict* bucket1 = buckets_list[0].GetIfDict();
489*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(bucket1 != nullptr);
490*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(bucket1->FindInt("low"), std::optional<int>(100));
491*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(bucket1->FindInt("high"), std::optional<int>(101));
492*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(bucket1->FindInt("count"), std::optional<int>(10));
493*6777b538SAndroid Build Coastguard Worker 
494*6777b538SAndroid Build Coastguard Worker   // Check the second bucket.
495*6777b538SAndroid Build Coastguard Worker   const base::Value::Dict* bucket2 = buckets_list[1].GetIfDict();
496*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(bucket2 != nullptr);
497*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(bucket2->FindInt("low"), std::optional<int>(200));
498*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(bucket2->FindInt("high"), std::optional<int>(201));
499*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(bucket2->FindInt("count"), std::optional<int>(15));
500*6777b538SAndroid Build Coastguard Worker }
501*6777b538SAndroid Build Coastguard Worker 
TEST_P(SparseHistogramTest,WriteAscii)502*6777b538SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, WriteAscii) {
503*6777b538SAndroid Build Coastguard Worker   HistogramBase* histogram =
504*6777b538SAndroid Build Coastguard Worker       SparseHistogram::FactoryGet("AsciiOut", HistogramBase::kNoFlags);
505*6777b538SAndroid Build Coastguard Worker   histogram->AddCount(/*sample=*/4, /*count=*/5);
506*6777b538SAndroid Build Coastguard Worker   histogram->AddCount(/*sample=*/10, /*count=*/15);
507*6777b538SAndroid Build Coastguard Worker 
508*6777b538SAndroid Build Coastguard Worker   std::string output;
509*6777b538SAndroid Build Coastguard Worker   histogram->WriteAscii(&output);
510*6777b538SAndroid Build Coastguard Worker 
511*6777b538SAndroid Build Coastguard Worker   const char kOutputFormatRe[] =
512*6777b538SAndroid Build Coastguard Worker       R"(Histogram: AsciiOut recorded 20 samples.*\n)"
513*6777b538SAndroid Build Coastguard Worker       R"(4   -+O +\(5 = 25.0%\)\n)"
514*6777b538SAndroid Build Coastguard Worker       R"(10  -+O +\(15 = 75.0%\)\n)";
515*6777b538SAndroid Build Coastguard Worker 
516*6777b538SAndroid Build Coastguard Worker   EXPECT_THAT(output, testing::MatchesRegex(kOutputFormatRe));
517*6777b538SAndroid Build Coastguard Worker }
518*6777b538SAndroid Build Coastguard Worker 
TEST_P(SparseHistogramTest,ToGraphDict)519*6777b538SAndroid Build Coastguard Worker TEST_P(SparseHistogramTest, ToGraphDict) {
520*6777b538SAndroid Build Coastguard Worker   HistogramBase* histogram =
521*6777b538SAndroid Build Coastguard Worker       SparseHistogram::FactoryGet("HTMLOut", HistogramBase::kNoFlags);
522*6777b538SAndroid Build Coastguard Worker   histogram->AddCount(/*sample=*/4, /*count=*/5);
523*6777b538SAndroid Build Coastguard Worker   histogram->AddCount(/*sample=*/10, /*count=*/15);
524*6777b538SAndroid Build Coastguard Worker 
525*6777b538SAndroid Build Coastguard Worker   base::Value::Dict output = histogram->ToGraphDict();
526*6777b538SAndroid Build Coastguard Worker   std::string* header = output.FindString("header");
527*6777b538SAndroid Build Coastguard Worker   std::string* body = output.FindString("body");
528*6777b538SAndroid Build Coastguard Worker 
529*6777b538SAndroid Build Coastguard Worker   const char kOutputHeaderFormatRe[] =
530*6777b538SAndroid Build Coastguard Worker       R"(Histogram: HTMLOut recorded 20 samples.*)";
531*6777b538SAndroid Build Coastguard Worker   const char kOutputBodyFormatRe[] = R"(4   -+O +\(5 = 25.0%\)\n)"
532*6777b538SAndroid Build Coastguard Worker                                      R"(10  -+O +\(15 = 75.0%\)\n)";
533*6777b538SAndroid Build Coastguard Worker 
534*6777b538SAndroid Build Coastguard Worker   EXPECT_THAT(*header, testing::MatchesRegex(kOutputHeaderFormatRe));
535*6777b538SAndroid Build Coastguard Worker   EXPECT_THAT(*body, testing::MatchesRegex(kOutputBodyFormatRe));
536*6777b538SAndroid Build Coastguard Worker }
537*6777b538SAndroid Build Coastguard Worker 
538*6777b538SAndroid Build Coastguard Worker }  // namespace base
539