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