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