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