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 "base/test/gtest_util.h" 16 #include "testing/gtest/include/gtest/gtest.h" 17 18 namespace base { 19 namespace { 20 21 TEST(SampleVectorTest, AccumulateTest) { 22 // Custom buckets: [1, 5) [5, 10) 23 BucketRanges ranges(3); 24 ranges.set_range(0, 1); 25 ranges.set_range(1, 5); 26 ranges.set_range(2, 10); 27 SampleVector samples(1, &ranges); 28 29 samples.Accumulate(1, 200); 30 samples.Accumulate(2, -300); 31 EXPECT_EQ(-100, samples.GetCountAtIndex(0)); 32 33 samples.Accumulate(5, 200); 34 EXPECT_EQ(200, samples.GetCountAtIndex(1)); 35 36 EXPECT_EQ(600, samples.sum()); 37 EXPECT_EQ(100, samples.redundant_count()); 38 EXPECT_EQ(samples.TotalCount(), samples.redundant_count()); 39 40 samples.Accumulate(5, -100); 41 EXPECT_EQ(100, samples.GetCountAtIndex(1)); 42 43 EXPECT_EQ(100, samples.sum()); 44 EXPECT_EQ(0, samples.redundant_count()); 45 EXPECT_EQ(samples.TotalCount(), samples.redundant_count()); 46 } 47 48 TEST(SampleVectorTest, Accumulate_LargeValuesDontOverflow) { 49 // Custom buckets: [1, 250000000) [250000000, 500000000) 50 BucketRanges ranges(3); 51 ranges.set_range(0, 1); 52 ranges.set_range(1, 250000000); 53 ranges.set_range(2, 500000000); 54 SampleVector samples(1, &ranges); 55 56 samples.Accumulate(240000000, 200); 57 samples.Accumulate(249999999, -300); 58 EXPECT_EQ(-100, samples.GetCountAtIndex(0)); 59 60 samples.Accumulate(250000000, 200); 61 EXPECT_EQ(200, samples.GetCountAtIndex(1)); 62 63 EXPECT_EQ(23000000300LL, samples.sum()); 64 EXPECT_EQ(100, samples.redundant_count()); 65 EXPECT_EQ(samples.TotalCount(), samples.redundant_count()); 66 67 samples.Accumulate(250000000, -100); 68 EXPECT_EQ(100, samples.GetCountAtIndex(1)); 69 70 EXPECT_EQ(-1999999700LL, samples.sum()); 71 EXPECT_EQ(0, samples.redundant_count()); 72 EXPECT_EQ(samples.TotalCount(), samples.redundant_count()); 73 } 74 75 TEST(SampleVectorTest, AddSubtractTest) { 76 // Custom buckets: [0, 1) [1, 2) [2, 3) [3, INT_MAX) 77 BucketRanges ranges(5); 78 ranges.set_range(0, 0); 79 ranges.set_range(1, 1); 80 ranges.set_range(2, 2); 81 ranges.set_range(3, 3); 82 ranges.set_range(4, INT_MAX); 83 84 SampleVector samples1(1, &ranges); 85 samples1.Accumulate(0, 100); 86 samples1.Accumulate(2, 100); 87 samples1.Accumulate(4, 100); 88 EXPECT_EQ(600, samples1.sum()); 89 EXPECT_EQ(300, samples1.TotalCount()); 90 EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount()); 91 92 SampleVector samples2(2, &ranges); 93 samples2.Accumulate(1, 200); 94 samples2.Accumulate(2, 200); 95 samples2.Accumulate(4, 200); 96 EXPECT_EQ(1400, samples2.sum()); 97 EXPECT_EQ(600, samples2.TotalCount()); 98 EXPECT_EQ(samples2.redundant_count(), samples2.TotalCount()); 99 100 samples1.Add(samples2); 101 EXPECT_EQ(100, samples1.GetCountAtIndex(0)); 102 EXPECT_EQ(200, samples1.GetCountAtIndex(1)); 103 EXPECT_EQ(300, samples1.GetCountAtIndex(2)); 104 EXPECT_EQ(300, samples1.GetCountAtIndex(3)); 105 EXPECT_EQ(2000, samples1.sum()); 106 EXPECT_EQ(900, samples1.TotalCount()); 107 EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount()); 108 109 samples1.Subtract(samples2); 110 EXPECT_EQ(100, samples1.GetCountAtIndex(0)); 111 EXPECT_EQ(0, samples1.GetCountAtIndex(1)); 112 EXPECT_EQ(100, samples1.GetCountAtIndex(2)); 113 EXPECT_EQ(100, samples1.GetCountAtIndex(3)); 114 EXPECT_EQ(600, samples1.sum()); 115 EXPECT_EQ(300, samples1.TotalCount()); 116 EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount()); 117 } 118 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_DCHECK_DEATH(samples.Accumulate(INT_MIN, 100)); 136 EXPECT_DCHECK_DEATH(samples.Accumulate(-1, 100)); 137 EXPECT_DCHECK_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_DCHECK_DEATH(samples2.Accumulate(0, 100)); 158 EXPECT_DCHECK_DEATH(samples2.Accumulate(10, 100)); 159 } 160 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_DCHECK_DEATH(samples1.Add(samples2)); 185 EXPECT_DCHECK_DEATH(samples1.Subtract(samples2)); 186 187 // Extra bucket in the end. 188 samples2.Accumulate(0, -100); 189 samples2.Accumulate(6, 100); 190 EXPECT_DCHECK_DEATH(samples1.Add(samples2)); 191 EXPECT_DCHECK_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_DCHECK_DEATH(samples1.Add(samples2)); 197 EXPECT_DCHECK_DEATH(samples1.Subtract(samples2)); 198 } 199 200 TEST(SampleVectorIteratorTest, IterateTest) { 201 BucketRanges ranges(5); 202 ranges.set_range(0, 0); 203 ranges.set_range(1, 1); 204 ranges.set_range(2, 2); 205 ranges.set_range(3, 3); 206 ranges.set_range(4, 4); 207 208 std::vector<HistogramBase::Count> counts(3); 209 counts[0] = 1; 210 counts[1] = 0; // Iterator will bypass this empty bucket. 211 counts[2] = 2; 212 213 // BucketRanges can have larger size than counts. 214 SampleVectorIterator it(&counts, &ranges); 215 size_t index; 216 217 HistogramBase::Sample min; 218 HistogramBase::Sample max; 219 HistogramBase::Count count; 220 it.Get(&min, &max, &count); 221 EXPECT_EQ(0, min); 222 EXPECT_EQ(1, max); 223 EXPECT_EQ(1, count); 224 EXPECT_TRUE(it.GetBucketIndex(&index)); 225 EXPECT_EQ(0u, index); 226 227 it.Next(); 228 it.Get(&min, &max, &count); 229 EXPECT_EQ(2, min); 230 EXPECT_EQ(3, max); 231 EXPECT_EQ(2, count); 232 EXPECT_TRUE(it.GetBucketIndex(&index)); 233 EXPECT_EQ(2u, index); 234 235 it.Next(); 236 EXPECT_TRUE(it.Done()); 237 238 // Create iterator from SampleVector. 239 SampleVector samples(1, &ranges); 240 samples.Accumulate(0, 0); 241 samples.Accumulate(1, 1); 242 samples.Accumulate(2, 2); 243 samples.Accumulate(3, 3); 244 std::unique_ptr<SampleCountIterator> it2 = samples.Iterator(); 245 246 int i; 247 for (i = 1; !it2->Done(); i++, it2->Next()) { 248 it2->Get(&min, &max, &count); 249 EXPECT_EQ(i, min); 250 EXPECT_EQ(i + 1, max); 251 EXPECT_EQ(i, count); 252 253 size_t index; 254 EXPECT_TRUE(it2->GetBucketIndex(&index)); 255 EXPECT_EQ(static_cast<size_t>(i), index); 256 } 257 EXPECT_EQ(4, i); 258 } 259 260 TEST(SampleVectorIteratorDeathTest, IterateDoneTest) { 261 BucketRanges ranges(5); 262 ranges.set_range(0, 0); 263 ranges.set_range(1, 1); 264 ranges.set_range(2, 2); 265 ranges.set_range(3, 3); 266 ranges.set_range(4, INT_MAX); 267 SampleVector samples(1, &ranges); 268 269 std::unique_ptr<SampleCountIterator> it = samples.Iterator(); 270 271 EXPECT_TRUE(it->Done()); 272 273 HistogramBase::Sample min; 274 HistogramBase::Sample max; 275 HistogramBase::Count count; 276 EXPECT_DCHECK_DEATH(it->Get(&min, &max, &count)); 277 278 EXPECT_DCHECK_DEATH(it->Next()); 279 280 samples.Accumulate(2, 100); 281 it = samples.Iterator(); 282 EXPECT_FALSE(it->Done()); 283 } 284 285 } // namespace 286 } // namespace base 287