Index: base/metrics/histogram_unittest.cc |
=================================================================== |
--- base/metrics/histogram_unittest.cc (revision 152603) |
+++ base/metrics/histogram_unittest.cc (working copy) |
@@ -4,6 +4,7 @@ |
// Test of Histogram class |
+#include <climits> |
#include <algorithm> |
#include <vector> |
@@ -19,6 +20,237 @@ |
namespace base { |
+TEST(BucketHistogramSamplesTest, AccumulateTest) { |
+ // Custom buckets: [1, 5) [5, 10) |
+ BucketRanges ranges(3); |
+ ranges.set_range(0, 1); |
+ ranges.set_range(1, 5); |
+ ranges.set_range(2, 10); |
+ BucketHistogramSamples samples(&ranges); |
+ |
+ samples.Accumulate(1, 200); |
+ samples.Accumulate(2, -300); |
+ EXPECT_EQ(-100, samples.GetCountFromBucketIndex(0)); |
+ |
+ samples.Accumulate(5, 200); |
+ EXPECT_EQ(200, samples.GetCountFromBucketIndex(1)); |
+ |
+ EXPECT_EQ(600, samples.sum()); |
+ EXPECT_EQ(100, samples.redundant_count()); |
+ EXPECT_EQ(samples.TotalCount(), samples.redundant_count()); |
+ |
+ samples.Accumulate(5, -100); |
+ EXPECT_EQ(100, samples.GetCountFromBucketIndex(1)); |
+ |
+ EXPECT_EQ(100, samples.sum()); |
+ EXPECT_EQ(0, samples.redundant_count()); |
+ EXPECT_EQ(samples.TotalCount(), samples.redundant_count()); |
+} |
+ |
+TEST(BucketHistogramSamplesDeathTest, BucketIndexTest) { |
+ // 8 buckets with exponential layout: |
+ // [0, 1) [1, 2) [2, 4) [4, 8) [8, 16) [16, 32) [32, 64) [64, INT_MAX) |
+ BucketRanges ranges(9); |
+ Histogram::InitializeBucketRanges(1, 64, 8, &ranges); |
+ BucketHistogramSamples samples(&ranges); |
+ |
+ // Normal case |
+ samples.Accumulate(0, 1); |
+ samples.Accumulate(3, 2); |
+ samples.Accumulate(64, 3); |
+ EXPECT_EQ(1, samples.GetCount(0)); |
+ EXPECT_EQ(2, samples.GetCount(2)); |
+ EXPECT_EQ(3, samples.GetCount(65)); |
+ |
+ // Extreme case. |
+ EXPECT_DEATH(samples.Accumulate(INT_MIN, 100), ""); |
+ EXPECT_DEATH(samples.Accumulate(-1, 100), ""); |
+ EXPECT_DEATH(samples.Accumulate(INT_MAX, 100), ""); |
+ |
+ // Custom buckets: [1, 5) [5, 10) |
+ // Note, this is not a valid BucketRanges for Histogram because it does not |
+ // have overflow buckets. |
+ BucketRanges ranges2(3); |
+ ranges2.set_range(0, 1); |
+ ranges2.set_range(1, 5); |
+ ranges2.set_range(2, 10); |
+ BucketHistogramSamples samples2(&ranges2); |
+ |
+ // Normal case. |
+ samples2.Accumulate(1, 1); |
+ samples2.Accumulate(4, 1); |
+ samples2.Accumulate(5, 2); |
+ samples2.Accumulate(9, 2); |
+ EXPECT_EQ(2, samples2.GetCount(1)); |
+ EXPECT_EQ(4, samples2.GetCount(5)); |
+ |
+ // Extreme case. |
+ EXPECT_DEATH(samples2.Accumulate(0, 100), ""); |
+ EXPECT_DEATH(samples2.Accumulate(10, 100), ""); |
+} |
+ |
+TEST(BucketHistogramSamplesTest, AddSubtractTest) { |
+ // Custom buckets: [0, 1) [1, 2) [2, 3) [3, INT_MAX) |
+ BucketRanges ranges(5); |
+ ranges.set_range(0, 0); |
+ ranges.set_range(1, 1); |
+ ranges.set_range(2, 2); |
+ ranges.set_range(3, 3); |
+ ranges.set_range(4, INT_MAX); |
+ |
+ BucketHistogramSamples samples1(&ranges); |
+ samples1.Accumulate(0, 100); |
+ samples1.Accumulate(2, 100); |
+ samples1.Accumulate(4, 100); |
+ EXPECT_EQ(600, samples1.sum()); |
+ EXPECT_EQ(300, samples1.TotalCount()); |
+ EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount()); |
+ |
+ BucketHistogramSamples samples2(&ranges); |
+ samples2.Accumulate(1, 200); |
+ samples2.Accumulate(2, 200); |
+ samples2.Accumulate(4, 200); |
+ EXPECT_EQ(1400, samples2.sum()); |
+ EXPECT_EQ(600, samples2.TotalCount()); |
+ EXPECT_EQ(samples2.redundant_count(), samples2.TotalCount()); |
+ |
+ samples1.Add(samples2); |
+ EXPECT_EQ(100, samples1.GetCountFromBucketIndex(0)); |
+ EXPECT_EQ(200, samples1.GetCountFromBucketIndex(1)); |
+ EXPECT_EQ(300, samples1.GetCountFromBucketIndex(2)); |
+ EXPECT_EQ(300, samples1.GetCountFromBucketIndex(3)); |
+ EXPECT_EQ(2000, samples1.sum()); |
+ EXPECT_EQ(900, samples1.TotalCount()); |
+ EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount()); |
+ |
+ samples1.Subtract(samples2); |
+ EXPECT_EQ(100, samples1.GetCountFromBucketIndex(0)); |
+ EXPECT_EQ(0, samples1.GetCountFromBucketIndex(1)); |
+ EXPECT_EQ(100, samples1.GetCountFromBucketIndex(2)); |
+ EXPECT_EQ(100, samples1.GetCountFromBucketIndex(3)); |
+ EXPECT_EQ(600, samples1.sum()); |
+ EXPECT_EQ(300, samples1.TotalCount()); |
+ EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount()); |
+} |
+ |
+TEST(BucketHistogramSamplesDeathTest, AddSubtractBucketNotMatchTest) { |
+ // Custom buckets 1: [1, 3) [3, 5) |
+ BucketRanges ranges1(3); |
+ ranges1.set_range(0, 1); |
+ ranges1.set_range(1, 3); |
+ ranges1.set_range(2, 5); |
+ BucketHistogramSamples samples1(&ranges1); |
+ |
+ // Custom buckets 2: [0, 1) [1, 3) [3, 6) [6, 7) |
+ BucketRanges ranges2(5); |
+ ranges2.set_range(0, 0); |
+ ranges2.set_range(1, 1); |
+ ranges2.set_range(2, 3); |
+ ranges2.set_range(3, 6); |
+ ranges2.set_range(4, 7); |
+ BucketHistogramSamples samples2(&ranges2); |
+ |
+ samples2.Accumulate(1, 100); |
+ samples1.Add(samples2); |
+ EXPECT_EQ(100, samples1.GetCountFromBucketIndex(0)); |
+ |
+ // Extra bucket in the beginning. |
+ samples2.Accumulate(0, 100); |
+ EXPECT_DEATH(samples1.Add(samples2), ""); |
+ EXPECT_DEATH(samples1.Subtract(samples2), ""); |
+ |
+ // Extra bucket in the end. |
+ samples2.Accumulate(0, -100); |
+ samples2.Accumulate(6, 100); |
+ EXPECT_DEATH(samples1.Add(samples2), ""); |
+ EXPECT_DEATH(samples1.Subtract(samples2), ""); |
+ |
+ // Bucket not match: [3, 5) VS [3, 6) |
+ samples2.Accumulate(6, -100); |
+ samples2.Accumulate(3, 100); |
+ EXPECT_DEATH(samples1.Add(samples2), ""); |
+ EXPECT_DEATH(samples1.Subtract(samples2), ""); |
+} |
+ |
+TEST(BucketHistogramSamplesTest, SerializationTest) { |
+} |
+ |
+TEST(BucketHistogramSamplesIteratorTest, IterateTest) { |
+ BucketRanges ranges(5); |
+ ranges.set_range(0, 0); |
+ ranges.set_range(1, 1); |
+ ranges.set_range(2, 2); |
+ ranges.set_range(3, 3); |
+ ranges.set_range(4, 4); |
+ |
+ vector<HistogramBase::Count> counts(3); |
+ counts[0] = 1; |
+ counts[1] = 0; // Iterator will bypass this empty bucket. |
+ counts[2] = 2; |
+ |
+ // BucketRanges can have larger size than counts. |
+ BucketHistogramSamplesIterator it(&counts, &ranges); |
+ |
+ HistogramBase::Sample min; |
+ HistogramBase::Sample max; |
+ HistogramBase::Count count; |
+ it.Get(&min, &max, &count); |
+ EXPECT_EQ(0, min); |
+ EXPECT_EQ(1, max); |
+ EXPECT_EQ(1, count); |
+ |
+ it.Next(); |
+ it.Get(&min, &max, &count); |
+ EXPECT_EQ(2, min); |
+ EXPECT_EQ(3, max); |
+ EXPECT_EQ(2, count); |
+ |
+ it.Next(); |
+ EXPECT_TRUE(it.Done()); |
+ |
+ // Create iterator from BucketHistogramSamples. |
+ BucketHistogramSamples samples(&ranges); |
+ samples.Accumulate(0, 0); |
+ samples.Accumulate(1, 1); |
+ samples.Accumulate(2, 2); |
+ samples.Accumulate(3, 3); |
+ scoped_ptr<SampleCountIterator> it2 = samples.Iterator(); |
+ |
+ int i; |
+ for (i = 1; !it2->Done(); i++, it2->Next()) { |
+ it2->Get(&min, &max, &count); |
+ EXPECT_EQ(i, min); |
+ EXPECT_EQ(i + 1, max); |
+ EXPECT_EQ(i, count); |
+ } |
+ EXPECT_EQ(4, i); |
+} |
+ |
+TEST(BucketHistogramSamplesIteratorDeathTest, IterateDoneTest) { |
+ BucketRanges ranges(5); |
+ ranges.set_range(0, 0); |
+ ranges.set_range(1, 1); |
+ ranges.set_range(2, 2); |
+ ranges.set_range(3, 3); |
+ ranges.set_range(4, INT_MAX); |
+ BucketHistogramSamples samples(&ranges); |
+ |
+ scoped_ptr<SampleCountIterator> it = samples.Iterator(); |
+ |
+ EXPECT_TRUE(it->Done()); |
+ |
+ HistogramBase::Sample min; |
+ HistogramBase::Sample max; |
+ HistogramBase::Count count; |
+ EXPECT_DEATH(it->Get(&min, &max, &count), ""); |
+ |
+ EXPECT_DEATH(it->Next(), ""); |
+ |
+ samples.Accumulate(2, 100); |
+ it = samples.Iterator(); |
+ EXPECT_FALSE(it->Done()); |
+} |
+ |
// Check for basic syntax and use. |
TEST(HistogramTest, BasicTest) { |
// Try basic construction |
@@ -206,14 +438,13 @@ |
histogram->Add(10000); |
// Verify they landed in the underflow, and overflow buckets. |
- Histogram::SampleSet sample; |
- histogram->SnapshotSample(&sample); |
- EXPECT_EQ(2, sample.counts(0)); |
- EXPECT_EQ(0, sample.counts(1)); |
+ scoped_ptr<BucketHistogramSamples> samples = histogram->SnapshotSamples(); |
+ EXPECT_EQ(2, samples->GetCountFromBucketIndex(0)); |
+ EXPECT_EQ(0, samples->GetCountFromBucketIndex(1)); |
size_t array_size = histogram->bucket_count(); |
EXPECT_EQ(kBucketCount, array_size); |
- EXPECT_EQ(0, sample.counts(array_size - 2)); |
- EXPECT_EQ(2, sample.counts(array_size - 1)); |
+ EXPECT_EQ(0, samples->GetCountFromBucketIndex(array_size - 2)); |
+ EXPECT_EQ(2, samples->GetCountFromBucketIndex(array_size - 1)); |
vector<int> custom_ranges; |
custom_ranges.push_back(10); |
@@ -227,15 +458,16 @@ |
test_custom_histogram->Add(-50); |
test_custom_histogram->Add(100); |
test_custom_histogram->Add(1000); |
+ test_custom_histogram->Add(INT_MAX); |
// Verify they landed in the underflow, and overflow buckets. |
- Histogram::SampleSet custom_sample; |
- test_custom_histogram->SnapshotSample(&custom_sample); |
- EXPECT_EQ(2, custom_sample.counts(0)); |
- EXPECT_EQ(0, custom_sample.counts(1)); |
- size_t custom_array_size = test_custom_histogram->bucket_count(); |
- EXPECT_EQ(0, custom_sample.counts(custom_array_size - 2)); |
- EXPECT_EQ(2, custom_sample.counts(custom_array_size - 1)); |
+ scoped_ptr<BucketHistogramSamples> custom_samples = |
+ test_custom_histogram->SnapshotSamples(); |
+ EXPECT_EQ(2, custom_samples->GetCountFromBucketIndex(0)); |
+ EXPECT_EQ(0, custom_samples->GetCountFromBucketIndex(1)); |
+ size_t bucket_count = test_custom_histogram->bucket_count(); |
+ EXPECT_EQ(0, custom_samples->GetCountFromBucketIndex(bucket_count - 2)); |
+ EXPECT_EQ(3, custom_samples->GetCountFromBucketIndex(bucket_count - 1)); |
} |
// Check to be sure samples land as expected is "correct" buckets. |
@@ -253,45 +485,45 @@ |
} |
// Check to see that the bucket counts reflect our additions. |
- Histogram::SampleSet sample; |
- histogram->SnapshotSample(&sample); |
+ scoped_ptr<BucketHistogramSamples> samples = histogram->SnapshotSamples(); |
for (int i = 0; i < 8; i++) |
- EXPECT_EQ(i + 1, sample.counts(i)); |
+ EXPECT_EQ(i + 1, samples->GetCountFromBucketIndex(i)); |
} |
TEST(HistogramTest, CorruptSampleCounts) { |
Histogram* histogram(Histogram::FactoryGet( |
"Histogram", 1, 64, 8, Histogram::kNoFlags)); // As per header file. |
- EXPECT_EQ(0, histogram->sample_.redundant_count()); |
- histogram->Add(20); // Add some samples. |
+ // Add some samples. |
+ histogram->Add(20); |
histogram->Add(40); |
- EXPECT_EQ(2, histogram->sample_.redundant_count()); |
- Histogram::SampleSet snapshot; |
- histogram->SnapshotSample(&snapshot); |
- EXPECT_EQ(Histogram::NO_INCONSISTENCIES, 0); |
- EXPECT_EQ(0, histogram->FindCorruption(snapshot)); // No default corruption. |
- EXPECT_EQ(2, snapshot.redundant_count()); |
+ scoped_ptr<BucketHistogramSamples> snapshot = histogram->SnapshotSamples(); |
+ EXPECT_EQ(Histogram::NO_INCONSISTENCIES, |
+ histogram->FindCorruption(*snapshot)); |
+ EXPECT_EQ(2, snapshot->redundant_count()); |
+ EXPECT_EQ(2, snapshot->TotalCount()); |
- snapshot.counts_[3] += 100; // Sample count won't match redundant count. |
- EXPECT_EQ(Histogram::COUNT_LOW_ERROR, histogram->FindCorruption(snapshot)); |
- snapshot.counts_[2] -= 200; |
- EXPECT_EQ(Histogram::COUNT_HIGH_ERROR, histogram->FindCorruption(snapshot)); |
+ snapshot->counts_[3] += 100; // Sample count won't match redundant count. |
+ EXPECT_EQ(Histogram::COUNT_LOW_ERROR, |
+ histogram->FindCorruption(*snapshot)); |
+ snapshot->counts_[2] -= 200; |
+ EXPECT_EQ(Histogram::COUNT_HIGH_ERROR, |
+ histogram->FindCorruption(*snapshot)); |
// But we can't spot a corruption if it is compensated for. |
- snapshot.counts_[1] += 100; |
- EXPECT_EQ(0, histogram->FindCorruption(snapshot)); |
+ snapshot->counts_[1] += 100; |
+ EXPECT_EQ(Histogram::NO_INCONSISTENCIES, |
+ histogram->FindCorruption(*snapshot)); |
} |
TEST(HistogramTest, CorruptBucketBounds) { |
Histogram* histogram(Histogram::FactoryGet( |
"Histogram", 1, 64, 8, Histogram::kNoFlags)); // As per header file. |
- Histogram::SampleSet snapshot; |
- histogram->SnapshotSample(&snapshot); |
- EXPECT_EQ(Histogram::NO_INCONSISTENCIES, 0); |
- EXPECT_EQ(0, histogram->FindCorruption(snapshot)); // No default corruption. |
+ scoped_ptr<BucketHistogramSamples> snapshot = histogram->SnapshotSamples(); |
+ EXPECT_EQ(Histogram::NO_INCONSISTENCIES, |
+ histogram->FindCorruption(*snapshot)); |
BucketRanges* bucket_ranges = |
const_cast<BucketRanges*>(histogram->bucket_ranges()); |
@@ -299,20 +531,20 @@ |
bucket_ranges->set_range(1, bucket_ranges->range(2)); |
bucket_ranges->set_range(2, tmp); |
EXPECT_EQ(Histogram::BUCKET_ORDER_ERROR | Histogram::RANGE_CHECKSUM_ERROR, |
- histogram->FindCorruption(snapshot)); |
+ histogram->FindCorruption(*snapshot)); |
bucket_ranges->set_range(2, bucket_ranges->range(1)); |
bucket_ranges->set_range(1, tmp); |
- EXPECT_EQ(0, histogram->FindCorruption(snapshot)); |
+ EXPECT_EQ(0, histogram->FindCorruption(*snapshot)); |
+ // Show that two simple changes don't offset each other |
bucket_ranges->set_range(3, bucket_ranges->range(3) + 1); |
EXPECT_EQ(Histogram::RANGE_CHECKSUM_ERROR, |
- histogram->FindCorruption(snapshot)); |
+ histogram->FindCorruption(*snapshot)); |
- // Show that two simple changes don't offset each other |
bucket_ranges->set_range(4, bucket_ranges->range(4) - 1); |
EXPECT_EQ(Histogram::RANGE_CHECKSUM_ERROR, |
- histogram->FindCorruption(snapshot)); |
+ histogram->FindCorruption(*snapshot)); |
// Repair histogram so that destructor won't DCHECK(). |
bucket_ranges->set_range(3, bucket_ranges->range(3) - 1); |