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