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