1 // Copyright (c) 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/metrics/persistent_sample_map.h"
6 
7 #include <memory>
8 
9 #include "base/memory/ptr_util.h"
10 #include "base/metrics/persistent_histogram_allocator.h"
11 #include "base/test/gtest_util.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 
14 namespace base {
15 namespace {
16 
CreateHistogramAllocator(size_t bytes)17 std::unique_ptr<PersistentHistogramAllocator> CreateHistogramAllocator(
18     size_t bytes) {
19   return std::make_unique<PersistentHistogramAllocator>(
20       std::make_unique<LocalPersistentMemoryAllocator>(bytes, 0, ""));
21 }
22 
DuplicateHistogramAllocator(PersistentHistogramAllocator * original)23 std::unique_ptr<PersistentHistogramAllocator> DuplicateHistogramAllocator(
24     PersistentHistogramAllocator* original) {
25   return std::make_unique<PersistentHistogramAllocator>(
26       std::make_unique<PersistentMemoryAllocator>(
27           const_cast<void*>(original->data()), original->length(), 0,
28           original->Id(), original->Name(), false));
29 }
30 
TEST(PersistentSampleMapTest,AccumulateTest)31 TEST(PersistentSampleMapTest, AccumulateTest) {
32   std::unique_ptr<PersistentHistogramAllocator> allocator =
33       CreateHistogramAllocator(64 << 10);  // 64 KiB
34   HistogramSamples::LocalMetadata meta;
35   PersistentSampleMap samples(1, allocator.get(), &meta);
36 
37   samples.Accumulate(1, 100);
38   samples.Accumulate(2, 200);
39   samples.Accumulate(1, -200);
40   EXPECT_EQ(-100, samples.GetCount(1));
41   EXPECT_EQ(200, samples.GetCount(2));
42 
43   EXPECT_EQ(300, samples.sum());
44   EXPECT_EQ(100, samples.TotalCount());
45   EXPECT_EQ(samples.redundant_count(), samples.TotalCount());
46 }
47 
TEST(PersistentSampleMapTest,Accumulate_LargeValuesDontOverflow)48 TEST(PersistentSampleMapTest, Accumulate_LargeValuesDontOverflow) {
49   std::unique_ptr<PersistentHistogramAllocator> allocator =
50       CreateHistogramAllocator(64 << 10);  // 64 KiB
51   HistogramSamples::LocalMetadata meta;
52   PersistentSampleMap samples(1, allocator.get(), &meta);
53 
54   samples.Accumulate(250000000, 100);
55   samples.Accumulate(500000000, 200);
56   samples.Accumulate(250000000, -200);
57   EXPECT_EQ(-100, samples.GetCount(250000000));
58   EXPECT_EQ(200, samples.GetCount(500000000));
59 
60   EXPECT_EQ(75000000000LL, samples.sum());
61   EXPECT_EQ(100, samples.TotalCount());
62   EXPECT_EQ(samples.redundant_count(), samples.TotalCount());
63 }
64 
TEST(PersistentSampleMapTest,AddSubtractTest)65 TEST(PersistentSampleMapTest, AddSubtractTest) {
66   std::unique_ptr<PersistentHistogramAllocator> allocator1 =
67       CreateHistogramAllocator(64 << 10);  // 64 KiB
68   HistogramSamples::LocalMetadata meta1;
69   PersistentSampleMap samples1(1, allocator1.get(), &meta1);
70   samples1.Accumulate(1, 100);
71   samples1.Accumulate(2, 100);
72   samples1.Accumulate(3, 100);
73 
74   std::unique_ptr<PersistentHistogramAllocator> allocator2 =
75       DuplicateHistogramAllocator(allocator1.get());
76   HistogramSamples::LocalMetadata meta2;
77   PersistentSampleMap samples2(2, allocator2.get(), &meta2);
78   samples2.Accumulate(1, 200);
79   samples2.Accumulate(2, 200);
80   samples2.Accumulate(4, 200);
81 
82   samples1.Add(samples2);
83   EXPECT_EQ(300, samples1.GetCount(1));
84   EXPECT_EQ(300, samples1.GetCount(2));
85   EXPECT_EQ(100, samples1.GetCount(3));
86   EXPECT_EQ(200, samples1.GetCount(4));
87   EXPECT_EQ(2000, samples1.sum());
88   EXPECT_EQ(900, samples1.TotalCount());
89   EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount());
90 
91   samples1.Subtract(samples2);
92   EXPECT_EQ(100, samples1.GetCount(1));
93   EXPECT_EQ(100, samples1.GetCount(2));
94   EXPECT_EQ(100, samples1.GetCount(3));
95   EXPECT_EQ(0, samples1.GetCount(4));
96   EXPECT_EQ(600, samples1.sum());
97   EXPECT_EQ(300, samples1.TotalCount());
98   EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount());
99 }
100 
TEST(PersistentSampleMapTest,PersistenceTest)101 TEST(PersistentSampleMapTest, PersistenceTest) {
102   std::unique_ptr<PersistentHistogramAllocator> allocator1 =
103       CreateHistogramAllocator(64 << 10);  // 64 KiB
104   HistogramSamples::LocalMetadata meta12;
105   PersistentSampleMap samples1(12, allocator1.get(), &meta12);
106   samples1.Accumulate(1, 100);
107   samples1.Accumulate(2, 200);
108   samples1.Accumulate(1, -200);
109   samples1.Accumulate(-1, 1);
110   EXPECT_EQ(-100, samples1.GetCount(1));
111   EXPECT_EQ(200, samples1.GetCount(2));
112   EXPECT_EQ(1, samples1.GetCount(-1));
113   EXPECT_EQ(299, samples1.sum());
114   EXPECT_EQ(101, samples1.TotalCount());
115   EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount());
116 
117   std::unique_ptr<PersistentHistogramAllocator> allocator2 =
118       DuplicateHistogramAllocator(allocator1.get());
119   PersistentSampleMap samples2(12, allocator2.get(), &meta12);
120   EXPECT_EQ(samples1.id(), samples2.id());
121   EXPECT_EQ(samples1.sum(), samples2.sum());
122   EXPECT_EQ(samples1.redundant_count(), samples2.redundant_count());
123   EXPECT_EQ(samples1.TotalCount(), samples2.TotalCount());
124   EXPECT_EQ(-100, samples2.GetCount(1));
125   EXPECT_EQ(200, samples2.GetCount(2));
126   EXPECT_EQ(1, samples2.GetCount(-1));
127   EXPECT_EQ(299, samples2.sum());
128   EXPECT_EQ(101, samples2.TotalCount());
129   EXPECT_EQ(samples2.redundant_count(), samples2.TotalCount());
130 
131   samples1.Accumulate(-1, -1);
132   EXPECT_EQ(0, samples2.GetCount(3));
133   EXPECT_EQ(0, samples1.GetCount(3));
134   samples2.Accumulate(3, 300);
135   EXPECT_EQ(300, samples2.GetCount(3));
136   EXPECT_EQ(300, samples1.GetCount(3));
137   EXPECT_EQ(samples1.sum(), samples2.sum());
138   EXPECT_EQ(samples1.redundant_count(), samples2.redundant_count());
139   EXPECT_EQ(samples1.TotalCount(), samples2.TotalCount());
140 
141   EXPECT_EQ(0, samples2.GetCount(4));
142   EXPECT_EQ(0, samples1.GetCount(4));
143   samples1.Accumulate(4, 400);
144   EXPECT_EQ(400, samples2.GetCount(4));
145   EXPECT_EQ(400, samples1.GetCount(4));
146   samples2.Accumulate(4, 4000);
147   EXPECT_EQ(4400, samples2.GetCount(4));
148   EXPECT_EQ(4400, samples1.GetCount(4));
149   EXPECT_EQ(samples1.sum(), samples2.sum());
150   EXPECT_EQ(samples1.redundant_count(), samples2.redundant_count());
151   EXPECT_EQ(samples1.TotalCount(), samples2.TotalCount());
152 }
153 
TEST(PersistentSampleMapIteratorTest,IterateTest)154 TEST(PersistentSampleMapIteratorTest, IterateTest) {
155   std::unique_ptr<PersistentHistogramAllocator> allocator =
156       CreateHistogramAllocator(64 << 10);  // 64 KiB
157   HistogramSamples::LocalMetadata meta;
158   PersistentSampleMap samples(1, allocator.get(), &meta);
159   samples.Accumulate(1, 100);
160   samples.Accumulate(2, 200);
161   samples.Accumulate(4, -300);
162   samples.Accumulate(5, 0);
163 
164   std::unique_ptr<SampleCountIterator> it = samples.Iterator();
165 
166   HistogramBase::Sample min;
167   int64_t max;
168   HistogramBase::Count count;
169 
170   it->Get(&min, &max, &count);
171   EXPECT_EQ(1, min);
172   EXPECT_EQ(2, max);
173   EXPECT_EQ(100, count);
174   EXPECT_FALSE(it->GetBucketIndex(nullptr));
175 
176   it->Next();
177   it->Get(&min, &max, &count);
178   EXPECT_EQ(2, min);
179   EXPECT_EQ(3, max);
180   EXPECT_EQ(200, count);
181 
182   it->Next();
183   it->Get(&min, &max, &count);
184   EXPECT_EQ(4, min);
185   EXPECT_EQ(5, max);
186   EXPECT_EQ(-300, count);
187 
188   it->Next();
189   EXPECT_TRUE(it->Done());
190 }
191 
TEST(PersistentSampleMapIteratorTest,SkipEmptyRanges)192 TEST(PersistentSampleMapIteratorTest, SkipEmptyRanges) {
193   std::unique_ptr<PersistentHistogramAllocator> allocator1 =
194       CreateHistogramAllocator(64 << 10);  // 64 KiB
195   HistogramSamples::LocalMetadata meta1;
196   PersistentSampleMap samples1(1, allocator1.get(), &meta1);
197   samples1.Accumulate(5, 1);
198   samples1.Accumulate(10, 2);
199   samples1.Accumulate(15, 3);
200   samples1.Accumulate(20, 4);
201   samples1.Accumulate(25, 5);
202 
203   std::unique_ptr<PersistentHistogramAllocator> allocator2 =
204       DuplicateHistogramAllocator(allocator1.get());
205   HistogramSamples::LocalMetadata meta2;
206   PersistentSampleMap samples2(2, allocator2.get(), &meta2);
207   samples2.Accumulate(5, 1);
208   samples2.Accumulate(20, 4);
209   samples2.Accumulate(25, 5);
210 
211   samples1.Subtract(samples2);
212 
213   std::unique_ptr<SampleCountIterator> it = samples1.Iterator();
214   EXPECT_FALSE(it->Done());
215 
216   HistogramBase::Sample min;
217   int64_t max;
218   HistogramBase::Count count;
219 
220   it->Get(&min, &max, &count);
221   EXPECT_EQ(10, min);
222   EXPECT_EQ(11, max);
223   EXPECT_EQ(2, count);
224 
225   it->Next();
226   EXPECT_FALSE(it->Done());
227 
228   it->Get(&min, &max, &count);
229   EXPECT_EQ(15, min);
230   EXPECT_EQ(16, max);
231   EXPECT_EQ(3, count);
232 
233   it->Next();
234   EXPECT_TRUE(it->Done());
235 }
236 
TEST(PersistentSampleMapIteratorDeathTest,IterateDoneTest)237 TEST(PersistentSampleMapIteratorDeathTest, IterateDoneTest) {
238   std::unique_ptr<PersistentHistogramAllocator> allocator =
239       CreateHistogramAllocator(64 << 10);  // 64 KiB
240   HistogramSamples::LocalMetadata meta;
241   PersistentSampleMap samples(1, allocator.get(), &meta);
242 
243   std::unique_ptr<SampleCountIterator> it = samples.Iterator();
244 
245   EXPECT_TRUE(it->Done());
246 
247   HistogramBase::Sample min;
248   int64_t max;
249   HistogramBase::Count count;
250   EXPECT_DCHECK_DEATH(it->Get(&min, &max, &count));
251 
252   EXPECT_DCHECK_DEATH(it->Next());
253 
254   samples.Accumulate(1, 100);
255   it = samples.Iterator();
256   EXPECT_FALSE(it->Done());
257 }
258 
259 }  // namespace
260 }  // namespace base
261