histogram_tester.cc 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. // Copyright 2014 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. #include "base/test/metrics/histogram_tester.h"
  5. #include <stddef.h>
  6. #include "base/metrics/histogram.h"
  7. #include "base/metrics/histogram_samples.h"
  8. #include "base/metrics/metrics_hashes.h"
  9. #include "base/metrics/sample_map.h"
  10. #include "base/metrics/sparse_histogram.h"
  11. #include "base/metrics/statistics_recorder.h"
  12. #include "base/strings/string_util.h"
  13. #include "base/strings/stringprintf.h"
  14. #include "testing/gtest/include/gtest/gtest.h"
  15. namespace base {
  16. HistogramTester::HistogramTester() {
  17. // Record any histogram data that exists when the object is created so it can
  18. // be subtracted later.
  19. for (const auto* const histogram : StatisticsRecorder::GetHistograms()) {
  20. histograms_snapshot_[histogram->histogram_name()] =
  21. histogram->SnapshotSamples();
  22. }
  23. }
  24. HistogramTester::~HistogramTester() = default;
  25. void HistogramTester::ExpectUniqueSample(
  26. StringPiece name,
  27. HistogramBase::Sample sample,
  28. HistogramBase::Count expected_bucket_count) const {
  29. HistogramBase* histogram = StatisticsRecorder::FindHistogram(name);
  30. if (!histogram) {
  31. // No histogram means there were zero samples.
  32. EXPECT_EQ(0, expected_bucket_count)
  33. << "Zero samples found for Histogram \"" << name << "\".";
  34. return;
  35. }
  36. std::unique_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
  37. int actual_bucket_count;
  38. GetBucketCountForSamples(name, sample, *samples, &actual_bucket_count);
  39. int actual_total_count = GetTotalCountForSamples(name, *samples);
  40. EXPECT_TRUE(expected_bucket_count == actual_bucket_count &&
  41. expected_bucket_count == actual_total_count)
  42. << "Histogram \"" << name << "\" did not meet its expectations. "
  43. << "Bucket " << sample << " should contain " << expected_bucket_count
  44. << " samples and contained " << actual_bucket_count << " samples. "
  45. << "The total count of samples in the histogram should be "
  46. << expected_bucket_count << " and was " << actual_total_count << ".";
  47. }
  48. void HistogramTester::ExpectUniqueTimeSample(
  49. StringPiece name,
  50. TimeDelta sample,
  51. HistogramBase::Count expected_bucket_count) const {
  52. ExpectUniqueSample(name, sample.InMilliseconds(), expected_bucket_count);
  53. }
  54. void HistogramTester::ExpectBucketCount(
  55. StringPiece name,
  56. HistogramBase::Sample sample,
  57. HistogramBase::Count expected_count) const {
  58. HistogramBase* histogram = StatisticsRecorder::FindHistogram(name);
  59. if (histogram) {
  60. std::unique_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
  61. CheckBucketCount(name, sample, expected_count, *samples);
  62. } else {
  63. // No histogram means there were zero samples.
  64. EXPECT_EQ(0, expected_count)
  65. << "Histogram \"" << name << "\" does not exist.";
  66. }
  67. }
  68. void HistogramTester::ExpectTotalCount(StringPiece name,
  69. HistogramBase::Count count) const {
  70. HistogramBase* histogram = StatisticsRecorder::FindHistogram(name);
  71. if (histogram) {
  72. std::unique_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
  73. CheckTotalCount(name, count, *samples);
  74. } else {
  75. // No histogram means there were zero samples.
  76. EXPECT_EQ(count, 0) << "Histogram \"" << name << "\" does not exist.";
  77. }
  78. }
  79. void HistogramTester::ExpectTimeBucketCount(StringPiece name,
  80. TimeDelta sample,
  81. HistogramBase::Count count) const {
  82. ExpectBucketCount(name, sample.InMilliseconds(), count);
  83. }
  84. int64_t HistogramTester::GetTotalSum(StringPiece name) const {
  85. HistogramBase* histogram = StatisticsRecorder::FindHistogram(name);
  86. if (!histogram)
  87. return 0;
  88. int64_t original_sum = 0;
  89. auto original_samples_it = histograms_snapshot_.find(name);
  90. if (original_samples_it != histograms_snapshot_.end())
  91. original_sum = original_samples_it->second->sum();
  92. std::unique_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
  93. return samples->sum() - original_sum;
  94. }
  95. std::vector<Bucket> HistogramTester::GetAllSamples(StringPiece name) const {
  96. std::vector<Bucket> samples;
  97. std::unique_ptr<HistogramSamples> snapshot =
  98. GetHistogramSamplesSinceCreation(name);
  99. if (snapshot) {
  100. for (auto it = snapshot->Iterator(); !it->Done(); it->Next()) {
  101. HistogramBase::Sample sample;
  102. HistogramBase::Count count;
  103. it->Get(&sample, nullptr, &count);
  104. samples.push_back(Bucket(sample, count));
  105. }
  106. }
  107. return samples;
  108. }
  109. HistogramBase::Count HistogramTester::GetBucketCount(
  110. StringPiece name,
  111. HistogramBase::Sample sample) const {
  112. HistogramBase* histogram = StatisticsRecorder::FindHistogram(name);
  113. HistogramBase::Count count = 0;
  114. if (histogram) {
  115. std::unique_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
  116. GetBucketCountForSamples(name, sample, *samples, &count);
  117. }
  118. return count;
  119. }
  120. void HistogramTester::GetBucketCountForSamples(
  121. StringPiece name,
  122. HistogramBase::Sample sample,
  123. const HistogramSamples& samples,
  124. HistogramBase::Count* count) const {
  125. *count = samples.GetCount(sample);
  126. auto histogram_data = histograms_snapshot_.find(name);
  127. if (histogram_data != histograms_snapshot_.end())
  128. *count -= histogram_data->second->GetCount(sample);
  129. }
  130. HistogramTester::CountsMap HistogramTester::GetTotalCountsForPrefix(
  131. StringPiece prefix) const {
  132. EXPECT_TRUE(prefix.find('.') != StringPiece::npos)
  133. << "|prefix| ought to contain at least one period, to avoid matching too"
  134. << " many histograms.";
  135. CountsMap result;
  136. // Find candidate matches by using the logic built into GetSnapshot().
  137. for (const HistogramBase* histogram : StatisticsRecorder::GetHistograms()) {
  138. if (!StartsWith(histogram->histogram_name(), prefix,
  139. CompareCase::SENSITIVE)) {
  140. continue;
  141. }
  142. std::unique_ptr<HistogramSamples> new_samples =
  143. GetHistogramSamplesSinceCreation(histogram->histogram_name());
  144. // Omit unchanged histograms from the result.
  145. if (new_samples->TotalCount()) {
  146. result[histogram->histogram_name()] = new_samples->TotalCount();
  147. }
  148. }
  149. return result;
  150. }
  151. std::unique_ptr<HistogramSamples>
  152. HistogramTester::GetHistogramSamplesSinceCreation(
  153. StringPiece histogram_name) const {
  154. HistogramBase* histogram = StatisticsRecorder::FindHistogram(histogram_name);
  155. // Whether the histogram exists or not may not depend on the current test
  156. // calling this method, but rather on which tests ran before and possibly
  157. // generated a histogram or not (see http://crbug.com/473689). To provide a
  158. // response which is independent of the previously run tests, this method
  159. // creates empty samples in the absence of the histogram, rather than
  160. // returning null.
  161. if (!histogram) {
  162. return std::unique_ptr<HistogramSamples>(
  163. new SampleMap(HashMetricName(histogram_name)));
  164. }
  165. std::unique_ptr<HistogramSamples> named_samples =
  166. histogram->SnapshotSamples();
  167. auto original_samples_it = histograms_snapshot_.find(histogram_name);
  168. if (original_samples_it != histograms_snapshot_.end())
  169. named_samples->Subtract(*original_samples_it->second.get());
  170. return named_samples;
  171. }
  172. std::string HistogramTester::GetAllHistogramsRecorded() const {
  173. std::string output;
  174. for (const auto* const histogram : StatisticsRecorder::GetHistograms()) {
  175. std::unique_ptr<HistogramSamples> named_samples =
  176. histogram->SnapshotSamples();
  177. for (const auto& histogram_data : histograms_snapshot_) {
  178. if (histogram_data.first == histogram->histogram_name())
  179. named_samples->Subtract(*histogram_data.second);
  180. }
  181. if (named_samples->TotalCount()) {
  182. auto current_count = histogram->SnapshotSamples()->TotalCount();
  183. StringAppendF(&output, "Histogram: %s recorded %d new samples.\n",
  184. histogram->histogram_name(), named_samples->TotalCount());
  185. if (current_count != named_samples->TotalCount()) {
  186. StringAppendF(&output,
  187. "WARNING: There were samples recorded to this histogram "
  188. "before tester instantiation.\n");
  189. }
  190. histogram->WriteAscii(&output);
  191. StringAppendF(&output, "\n");
  192. }
  193. }
  194. return output;
  195. }
  196. void HistogramTester::CheckBucketCount(StringPiece name,
  197. HistogramBase::Sample sample,
  198. HistogramBase::Count expected_count,
  199. const HistogramSamples& samples) const {
  200. int actual_count;
  201. GetBucketCountForSamples(name, sample, samples, &actual_count);
  202. EXPECT_EQ(expected_count, actual_count)
  203. << "Histogram \"" << name
  204. << "\" does not have the right number of samples (" << expected_count
  205. << ") in the expected bucket (" << sample << "). It has (" << actual_count
  206. << ").";
  207. }
  208. int HistogramTester::GetTotalCountForSamples(
  209. StringPiece name,
  210. const HistogramSamples& samples) const {
  211. int actual_count = samples.TotalCount();
  212. auto histogram_data = histograms_snapshot_.find(name);
  213. if (histogram_data != histograms_snapshot_.end())
  214. actual_count -= histogram_data->second->TotalCount();
  215. return actual_count;
  216. }
  217. void HistogramTester::CheckTotalCount(StringPiece name,
  218. HistogramBase::Count expected_count,
  219. const HistogramSamples& samples) const {
  220. int actual_count = GetTotalCountForSamples(name, samples);
  221. EXPECT_EQ(expected_count, actual_count)
  222. << "Histogram \"" << name
  223. << "\" does not have the right total number of samples ("
  224. << expected_count << "). It has (" << actual_count << ").";
  225. }
  226. bool Bucket::operator==(const Bucket& other) const {
  227. return min == other.min && count == other.count;
  228. }
  229. void PrintTo(const Bucket& bucket, std::ostream* os) {
  230. *os << "Bucket " << bucket.min << ": " << bucket.count;
  231. }
  232. } // namespace base