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