103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// found in the LICENSE file.
403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/test/histogram_tester.h"
603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/metrics/histogram.h"
803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/metrics/histogram_samples.h"
903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/metrics/statistics_recorder.h"
1003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/stl_util.h"
1103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
1203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
1303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)namespace base {
1403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
1503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)HistogramTester::HistogramTester() {
1603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  StatisticsRecorder::Initialize();  // Safe to call multiple times.
1703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
1803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Record any histogram data that exists when the object is created so it can
1903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // be subtracted later.
2003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  StatisticsRecorder::Histograms histograms;
2103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  StatisticsRecorder::GetSnapshot(std::string(), &histograms);
2203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  for (size_t i = 0; i < histograms.size(); ++i) {
2303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    histograms_snapshot_[histograms[i]->histogram_name()] =
2403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        histograms[i]->SnapshotSamples().release();
2503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
2603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
2703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
2803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)HistogramTester::~HistogramTester() {
2903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  STLDeleteValues(&histograms_snapshot_);
3003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
3103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
3203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void HistogramTester::ExpectUniqueSample(
3303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const std::string& name,
3403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    base::HistogramBase::Sample sample,
3503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    base::HistogramBase::Count expected_count) const {
3603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  base::HistogramBase* histogram =
3703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      base::StatisticsRecorder::FindHistogram(name);
3803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_NE(static_cast<base::HistogramBase*>(NULL), histogram)
3903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      << "Histogram \"" << name << "\" does not exist.";
4003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
4103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (histogram) {
4203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    scoped_ptr<base::HistogramSamples> samples(histogram->SnapshotSamples());
4303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    CheckBucketCount(name, sample, expected_count, *samples);
4403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    CheckTotalCount(name, expected_count, *samples);
4503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
4603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
4703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
4803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void HistogramTester::ExpectBucketCount(
4903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const std::string& name,
5003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    base::HistogramBase::Sample sample,
5103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    base::HistogramBase::Count expected_count) const {
5203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  base::HistogramBase* histogram =
5303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      base::StatisticsRecorder::FindHistogram(name);
5403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_NE(static_cast<base::HistogramBase*>(NULL), histogram)
5503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      << "Histogram \"" << name << "\" does not exist.";
5603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
5703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (histogram) {
5803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    scoped_ptr<base::HistogramSamples> samples(histogram->SnapshotSamples());
5903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    CheckBucketCount(name, sample, expected_count, *samples);
6003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
6103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
6203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
6303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void HistogramTester::ExpectTotalCount(const std::string& name,
6403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                       base::HistogramBase::Count count) const {
6503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  base::HistogramBase* histogram =
6603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      base::StatisticsRecorder::FindHistogram(name);
6703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (histogram) {
6803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    scoped_ptr<base::HistogramSamples> samples(histogram->SnapshotSamples());
6903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    CheckTotalCount(name, count, *samples);
7003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  } else {
7103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    // No histogram means there were zero samples.
7203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    EXPECT_EQ(count, 0) << "Histogram \"" << name << "\" does not exist.";
7303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
7403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
7503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
7603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)scoped_ptr<HistogramSamples> HistogramTester::GetHistogramSamplesSinceCreation(
7703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const std::string& histogram_name) {
7803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  HistogramBase* histogram = StatisticsRecorder::FindHistogram(histogram_name);
7903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!histogram)
8003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return scoped_ptr<HistogramSamples>();
8103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  scoped_ptr<HistogramSamples> named_samples(histogram->SnapshotSamples());
8203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  HistogramSamples* named_original_samples =
8303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      histograms_snapshot_[histogram_name];
8403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (named_original_samples)
8503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    named_samples->Subtract(*named_original_samples);
8603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return named_samples.Pass();
8703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
8803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
8903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void HistogramTester::CheckBucketCount(
9003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const std::string& name,
9103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    base::HistogramBase::Sample sample,
9203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    base::HistogramBase::Count expected_count,
9303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    base::HistogramSamples& samples) const {
9403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  int actual_count = samples.GetCount(sample);
9503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  std::map<std::string, HistogramSamples*>::const_iterator histogram_data;
9603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  histogram_data = histograms_snapshot_.find(name);
9703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (histogram_data != histograms_snapshot_.end())
9803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    actual_count -= histogram_data->second->GetCount(sample);
9903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
10003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_EQ(expected_count, actual_count)
10103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      << "Histogram \"" << name
10203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      << "\" does not have the right number of samples (" << expected_count
10303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      << ") in the expected bucket (" << sample << "). It has (" << actual_count
10403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      << ").";
10503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
10603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
10703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void HistogramTester::CheckTotalCount(const std::string& name,
10803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                      base::HistogramBase::Count expected_count,
10903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                      base::HistogramSamples& samples) const {
11003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  int actual_count = samples.TotalCount();
11103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  std::map<std::string, HistogramSamples*>::const_iterator histogram_data;
11203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  histogram_data = histograms_snapshot_.find(name);
11303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (histogram_data != histograms_snapshot_.end())
11403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    actual_count -= histogram_data->second->TotalCount();
11503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
11603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_EQ(expected_count, actual_count)
11703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      << "Histogram \"" << name
11803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      << "\" does not have the right total number of samples ("
11903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      << expected_count << "). It has (" << actual_count << ").";
12003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
12103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
12203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}  // namespace base
123