• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 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/sample_vector.h"
6 
7 #include <limits.h>
8 #include <stddef.h>
9 
10 #include <memory>
11 #include <vector>
12 
13 #include "base/metrics/bucket_ranges.h"
14 #include "base/metrics/histogram.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 
17 namespace base {
18 namespace {
19 
TEST(SampleVectorTest,AccumulateTest)20 TEST(SampleVectorTest, AccumulateTest) {
21   // Custom buckets: [1, 5) [5, 10)
22   BucketRanges ranges(3);
23   ranges.set_range(0, 1);
24   ranges.set_range(1, 5);
25   ranges.set_range(2, 10);
26   SampleVector samples(1, &ranges);
27 
28   samples.Accumulate(1, 200);
29   samples.Accumulate(2, -300);
30   EXPECT_EQ(-100, samples.GetCountAtIndex(0));
31 
32   samples.Accumulate(5, 200);
33   EXPECT_EQ(200, samples.GetCountAtIndex(1));
34 
35   EXPECT_EQ(600, samples.sum());
36   EXPECT_EQ(100, samples.redundant_count());
37   EXPECT_EQ(samples.TotalCount(), samples.redundant_count());
38 
39   samples.Accumulate(5, -100);
40   EXPECT_EQ(100, samples.GetCountAtIndex(1));
41 
42   EXPECT_EQ(100, samples.sum());
43   EXPECT_EQ(0, samples.redundant_count());
44   EXPECT_EQ(samples.TotalCount(), samples.redundant_count());
45 }
46 
TEST(SampleVectorTest,Accumulate_LargeValuesDontOverflow)47 TEST(SampleVectorTest, Accumulate_LargeValuesDontOverflow) {
48   // Custom buckets: [1, 250000000) [250000000, 500000000)
49   BucketRanges ranges(3);
50   ranges.set_range(0, 1);
51   ranges.set_range(1, 250000000);
52   ranges.set_range(2, 500000000);
53   SampleVector samples(1, &ranges);
54 
55   samples.Accumulate(240000000, 200);
56   samples.Accumulate(249999999, -300);
57   EXPECT_EQ(-100, samples.GetCountAtIndex(0));
58 
59   samples.Accumulate(250000000, 200);
60   EXPECT_EQ(200, samples.GetCountAtIndex(1));
61 
62   EXPECT_EQ(23000000300LL, samples.sum());
63   EXPECT_EQ(100, samples.redundant_count());
64   EXPECT_EQ(samples.TotalCount(), samples.redundant_count());
65 
66   samples.Accumulate(250000000, -100);
67   EXPECT_EQ(100, samples.GetCountAtIndex(1));
68 
69   EXPECT_EQ(-1999999700LL, samples.sum());
70   EXPECT_EQ(0, samples.redundant_count());
71   EXPECT_EQ(samples.TotalCount(), samples.redundant_count());
72 }
73 
TEST(SampleVectorTest,AddSubtractTest)74 TEST(SampleVectorTest, AddSubtractTest) {
75   // Custom buckets: [0, 1) [1, 2) [2, 3) [3, INT_MAX)
76   BucketRanges ranges(5);
77   ranges.set_range(0, 0);
78   ranges.set_range(1, 1);
79   ranges.set_range(2, 2);
80   ranges.set_range(3, 3);
81   ranges.set_range(4, INT_MAX);
82 
83   SampleVector samples1(1, &ranges);
84   samples1.Accumulate(0, 100);
85   samples1.Accumulate(2, 100);
86   samples1.Accumulate(4, 100);
87   EXPECT_EQ(600, samples1.sum());
88   EXPECT_EQ(300, samples1.TotalCount());
89   EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount());
90 
91   SampleVector samples2(2, &ranges);
92   samples2.Accumulate(1, 200);
93   samples2.Accumulate(2, 200);
94   samples2.Accumulate(4, 200);
95   EXPECT_EQ(1400, samples2.sum());
96   EXPECT_EQ(600, samples2.TotalCount());
97   EXPECT_EQ(samples2.redundant_count(), samples2.TotalCount());
98 
99   samples1.Add(samples2);
100   EXPECT_EQ(100, samples1.GetCountAtIndex(0));
101   EXPECT_EQ(200, samples1.GetCountAtIndex(1));
102   EXPECT_EQ(300, samples1.GetCountAtIndex(2));
103   EXPECT_EQ(300, samples1.GetCountAtIndex(3));
104   EXPECT_EQ(2000, samples1.sum());
105   EXPECT_EQ(900, samples1.TotalCount());
106   EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount());
107 
108   samples1.Subtract(samples2);
109   EXPECT_EQ(100, samples1.GetCountAtIndex(0));
110   EXPECT_EQ(0, samples1.GetCountAtIndex(1));
111   EXPECT_EQ(100, samples1.GetCountAtIndex(2));
112   EXPECT_EQ(100, samples1.GetCountAtIndex(3));
113   EXPECT_EQ(600, samples1.sum());
114   EXPECT_EQ(300, samples1.TotalCount());
115   EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount());
116 }
117 
118 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && GTEST_HAS_DEATH_TEST
TEST(SampleVectorDeathTest,BucketIndexTest)119 TEST(SampleVectorDeathTest, BucketIndexTest) {
120   // 8 buckets with exponential layout:
121   // [0, 1) [1, 2) [2, 4) [4, 8) [8, 16) [16, 32) [32, 64) [64, INT_MAX)
122   BucketRanges ranges(9);
123   Histogram::InitializeBucketRanges(1, 64, &ranges);
124   SampleVector samples(1, &ranges);
125 
126   // Normal case
127   samples.Accumulate(0, 1);
128   samples.Accumulate(3, 2);
129   samples.Accumulate(64, 3);
130   EXPECT_EQ(1, samples.GetCount(0));
131   EXPECT_EQ(2, samples.GetCount(2));
132   EXPECT_EQ(3, samples.GetCount(65));
133 
134   // Extreme case.
135   EXPECT_DEATH(samples.Accumulate(INT_MIN, 100), "");
136   EXPECT_DEATH(samples.Accumulate(-1, 100), "");
137   EXPECT_DEATH(samples.Accumulate(INT_MAX, 100), "");
138 
139   // Custom buckets: [1, 5) [5, 10)
140   // Note, this is not a valid BucketRanges for Histogram because it does not
141   // have overflow buckets.
142   BucketRanges ranges2(3);
143   ranges2.set_range(0, 1);
144   ranges2.set_range(1, 5);
145   ranges2.set_range(2, 10);
146   SampleVector samples2(2, &ranges2);
147 
148   // Normal case.
149   samples2.Accumulate(1, 1);
150   samples2.Accumulate(4, 1);
151   samples2.Accumulate(5, 2);
152   samples2.Accumulate(9, 2);
153   EXPECT_EQ(2, samples2.GetCount(1));
154   EXPECT_EQ(4, samples2.GetCount(5));
155 
156   // Extreme case.
157   EXPECT_DEATH(samples2.Accumulate(0, 100), "");
158   EXPECT_DEATH(samples2.Accumulate(10, 100), "");
159 }
160 
TEST(SampleVectorDeathTest,AddSubtractBucketNotMatchTest)161 TEST(SampleVectorDeathTest, AddSubtractBucketNotMatchTest) {
162   // Custom buckets 1: [1, 3) [3, 5)
163   BucketRanges ranges1(3);
164   ranges1.set_range(0, 1);
165   ranges1.set_range(1, 3);
166   ranges1.set_range(2, 5);
167   SampleVector samples1(1, &ranges1);
168 
169   // Custom buckets 2: [0, 1) [1, 3) [3, 6) [6, 7)
170   BucketRanges ranges2(5);
171   ranges2.set_range(0, 0);
172   ranges2.set_range(1, 1);
173   ranges2.set_range(2, 3);
174   ranges2.set_range(3, 6);
175   ranges2.set_range(4, 7);
176   SampleVector samples2(2, &ranges2);
177 
178   samples2.Accumulate(1, 100);
179   samples1.Add(samples2);
180   EXPECT_EQ(100, samples1.GetCountAtIndex(0));
181 
182   // Extra bucket in the beginning.
183   samples2.Accumulate(0, 100);
184   EXPECT_DEATH(samples1.Add(samples2), "");
185   EXPECT_DEATH(samples1.Subtract(samples2), "");
186 
187   // Extra bucket in the end.
188   samples2.Accumulate(0, -100);
189   samples2.Accumulate(6, 100);
190   EXPECT_DEATH(samples1.Add(samples2), "");
191   EXPECT_DEATH(samples1.Subtract(samples2), "");
192 
193   // Bucket not match: [3, 5) VS [3, 6)
194   samples2.Accumulate(6, -100);
195   samples2.Accumulate(3, 100);
196   EXPECT_DEATH(samples1.Add(samples2), "");
197   EXPECT_DEATH(samples1.Subtract(samples2), "");
198 }
199 
200 #endif
201 // (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && GTEST_HAS_DEATH_TEST
202 
TEST(SampleVectorIteratorTest,IterateTest)203 TEST(SampleVectorIteratorTest, IterateTest) {
204   BucketRanges ranges(5);
205   ranges.set_range(0, 0);
206   ranges.set_range(1, 1);
207   ranges.set_range(2, 2);
208   ranges.set_range(3, 3);
209   ranges.set_range(4, 4);
210 
211   std::vector<HistogramBase::Count> counts(3);
212   counts[0] = 1;
213   counts[1] = 0;  // Iterator will bypass this empty bucket.
214   counts[2] = 2;
215 
216   // BucketRanges can have larger size than counts.
217   SampleVectorIterator it(&counts, &ranges);
218   size_t index;
219 
220   HistogramBase::Sample min;
221   HistogramBase::Sample max;
222   HistogramBase::Count count;
223   it.Get(&min, &max, &count);
224   EXPECT_EQ(0, min);
225   EXPECT_EQ(1, max);
226   EXPECT_EQ(1, count);
227   EXPECT_TRUE(it.GetBucketIndex(&index));
228   EXPECT_EQ(0u, index);
229 
230   it.Next();
231   it.Get(&min, &max, &count);
232   EXPECT_EQ(2, min);
233   EXPECT_EQ(3, max);
234   EXPECT_EQ(2, count);
235   EXPECT_TRUE(it.GetBucketIndex(&index));
236   EXPECT_EQ(2u, index);
237 
238   it.Next();
239   EXPECT_TRUE(it.Done());
240 
241   // Create iterator from SampleVector.
242   SampleVector samples(1, &ranges);
243   samples.Accumulate(0, 0);
244   samples.Accumulate(1, 1);
245   samples.Accumulate(2, 2);
246   samples.Accumulate(3, 3);
247   std::unique_ptr<SampleCountIterator> it2 = samples.Iterator();
248 
249   int i;
250   for (i = 1; !it2->Done(); i++, it2->Next()) {
251     it2->Get(&min, &max, &count);
252     EXPECT_EQ(i, min);
253     EXPECT_EQ(i + 1, max);
254     EXPECT_EQ(i, count);
255 
256     size_t index;
257     EXPECT_TRUE(it2->GetBucketIndex(&index));
258     EXPECT_EQ(static_cast<size_t>(i), index);
259   }
260   EXPECT_EQ(4, i);
261 }
262 
263 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && GTEST_HAS_DEATH_TEST
264 
TEST(SampleVectorIteratorDeathTest,IterateDoneTest)265 TEST(SampleVectorIteratorDeathTest, IterateDoneTest) {
266   BucketRanges ranges(5);
267   ranges.set_range(0, 0);
268   ranges.set_range(1, 1);
269   ranges.set_range(2, 2);
270   ranges.set_range(3, 3);
271   ranges.set_range(4, INT_MAX);
272   SampleVector samples(1, &ranges);
273 
274   std::unique_ptr<SampleCountIterator> it = samples.Iterator();
275 
276   EXPECT_TRUE(it->Done());
277 
278   HistogramBase::Sample min;
279   HistogramBase::Sample max;
280   HistogramBase::Count count;
281   EXPECT_DEATH(it->Get(&min, &max, &count), "");
282 
283   EXPECT_DEATH(it->Next(), "");
284 
285   samples.Accumulate(2, 100);
286   it = samples.Iterator();
287   EXPECT_FALSE(it->Done());
288 }
289 
290 #endif
291 // (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && GTEST_HAS_DEATH_TEST
292 
293 }  // namespace
294 }  // namespace base
295