Home | History | Annotate | Download | only in metrics
      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 <stddef.h>
      6 
      7 #include <vector>
      8 
      9 #include "base/bind.h"
     10 #include "base/json/json_reader.h"
     11 #include "base/memory/scoped_ptr.h"
     12 #include "base/metrics/histogram_macros.h"
     13 #include "base/metrics/sparse_histogram.h"
     14 #include "base/metrics/statistics_recorder.h"
     15 #include "base/values.h"
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 
     18 namespace base {
     19 
     20 class StatisticsRecorderTest : public testing::Test {
     21  protected:
     22   void SetUp() override {
     23     // Each test will have a clean state (no Histogram / BucketRanges
     24     // registered).
     25     InitializeStatisticsRecorder();
     26   }
     27 
     28   void TearDown() override { UninitializeStatisticsRecorder(); }
     29 
     30   void InitializeStatisticsRecorder() {
     31     statistics_recorder_ = new StatisticsRecorder();
     32   }
     33 
     34   void UninitializeStatisticsRecorder() {
     35     delete statistics_recorder_;
     36     statistics_recorder_ = NULL;
     37   }
     38 
     39   Histogram* CreateHistogram(const std::string& name,
     40                              HistogramBase::Sample min,
     41                              HistogramBase::Sample max,
     42                              size_t bucket_count) {
     43     BucketRanges* ranges = new BucketRanges(bucket_count + 1);
     44     Histogram::InitializeBucketRanges(min, max, ranges);
     45     const BucketRanges* registered_ranges =
     46         StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges);
     47     return new Histogram(name, min, max, registered_ranges);
     48   }
     49 
     50   void DeleteHistogram(HistogramBase* histogram) {
     51     delete histogram;
     52   }
     53 
     54   StatisticsRecorder* statistics_recorder_;
     55 };
     56 
     57 TEST_F(StatisticsRecorderTest, NotInitialized) {
     58   UninitializeStatisticsRecorder();
     59 
     60   ASSERT_FALSE(StatisticsRecorder::IsActive());
     61 
     62   StatisticsRecorder::Histograms registered_histograms;
     63   std::vector<const BucketRanges*> registered_ranges;
     64 
     65   StatisticsRecorder::GetHistograms(&registered_histograms);
     66   EXPECT_EQ(0u, registered_histograms.size());
     67 
     68   Histogram* histogram = CreateHistogram("TestHistogram", 1, 1000, 10);
     69 
     70   // When StatisticsRecorder is not initialized, register is a noop.
     71   EXPECT_EQ(histogram,
     72             StatisticsRecorder::RegisterOrDeleteDuplicate(histogram));
     73   // Manually delete histogram that was not registered.
     74   DeleteHistogram(histogram);
     75 
     76   // RegisterOrDeleteDuplicateRanges is a no-op.
     77   BucketRanges* ranges = new BucketRanges(3);
     78   ranges->ResetChecksum();
     79   EXPECT_EQ(ranges,
     80             StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges));
     81   StatisticsRecorder::GetBucketRanges(&registered_ranges);
     82   EXPECT_EQ(0u, registered_ranges.size());
     83 }
     84 
     85 TEST_F(StatisticsRecorderTest, RegisterBucketRanges) {
     86   std::vector<const BucketRanges*> registered_ranges;
     87 
     88   BucketRanges* ranges1 = new BucketRanges(3);
     89   ranges1->ResetChecksum();
     90   BucketRanges* ranges2 = new BucketRanges(4);
     91   ranges2->ResetChecksum();
     92 
     93   // Register new ranges.
     94   EXPECT_EQ(ranges1,
     95             StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges1));
     96   EXPECT_EQ(ranges2,
     97             StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges2));
     98   StatisticsRecorder::GetBucketRanges(&registered_ranges);
     99   ASSERT_EQ(2u, registered_ranges.size());
    100 
    101   // Register some ranges again.
    102   EXPECT_EQ(ranges1,
    103             StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges1));
    104   registered_ranges.clear();
    105   StatisticsRecorder::GetBucketRanges(&registered_ranges);
    106   ASSERT_EQ(2u, registered_ranges.size());
    107   // Make sure the ranges is still the one we know.
    108   ASSERT_EQ(3u, ranges1->size());
    109   EXPECT_EQ(0, ranges1->range(0));
    110   EXPECT_EQ(0, ranges1->range(1));
    111   EXPECT_EQ(0, ranges1->range(2));
    112 
    113   // Register ranges with same values.
    114   BucketRanges* ranges3 = new BucketRanges(3);
    115   ranges3->ResetChecksum();
    116   EXPECT_EQ(ranges1,  // returning ranges1
    117             StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges3));
    118   registered_ranges.clear();
    119   StatisticsRecorder::GetBucketRanges(&registered_ranges);
    120   ASSERT_EQ(2u, registered_ranges.size());
    121 }
    122 
    123 TEST_F(StatisticsRecorderTest, RegisterHistogram) {
    124   // Create a Histogram that was not registered.
    125   Histogram* histogram = CreateHistogram("TestHistogram", 1, 1000, 10);
    126 
    127   StatisticsRecorder::Histograms registered_histograms;
    128   StatisticsRecorder::GetHistograms(&registered_histograms);
    129   EXPECT_EQ(0u, registered_histograms.size());
    130 
    131   // Register the Histogram.
    132   EXPECT_EQ(histogram,
    133             StatisticsRecorder::RegisterOrDeleteDuplicate(histogram));
    134   StatisticsRecorder::GetHistograms(&registered_histograms);
    135   EXPECT_EQ(1u, registered_histograms.size());
    136 
    137   // Register the same Histogram again.
    138   EXPECT_EQ(histogram,
    139             StatisticsRecorder::RegisterOrDeleteDuplicate(histogram));
    140   registered_histograms.clear();
    141   StatisticsRecorder::GetHistograms(&registered_histograms);
    142   EXPECT_EQ(1u, registered_histograms.size());
    143 }
    144 
    145 TEST_F(StatisticsRecorderTest, FindHistogram) {
    146   HistogramBase* histogram1 = Histogram::FactoryGet(
    147       "TestHistogram1", 1, 1000, 10, HistogramBase::kNoFlags);
    148   HistogramBase* histogram2 = Histogram::FactoryGet(
    149       "TestHistogram2", 1, 1000, 10, HistogramBase::kNoFlags);
    150 
    151   EXPECT_EQ(histogram1, StatisticsRecorder::FindHistogram("TestHistogram1"));
    152   EXPECT_EQ(histogram2, StatisticsRecorder::FindHistogram("TestHistogram2"));
    153   EXPECT_TRUE(StatisticsRecorder::FindHistogram("TestHistogram") == NULL);
    154 }
    155 
    156 TEST_F(StatisticsRecorderTest, GetSnapshot) {
    157   Histogram::FactoryGet("TestHistogram1", 1, 1000, 10, Histogram::kNoFlags);
    158   Histogram::FactoryGet("TestHistogram2", 1, 1000, 10, Histogram::kNoFlags);
    159   Histogram::FactoryGet("TestHistogram3", 1, 1000, 10, Histogram::kNoFlags);
    160 
    161   StatisticsRecorder::Histograms snapshot;
    162   StatisticsRecorder::GetSnapshot("Test", &snapshot);
    163   EXPECT_EQ(3u, snapshot.size());
    164 
    165   snapshot.clear();
    166   StatisticsRecorder::GetSnapshot("1", &snapshot);
    167   EXPECT_EQ(1u, snapshot.size());
    168 
    169   snapshot.clear();
    170   StatisticsRecorder::GetSnapshot("hello", &snapshot);
    171   EXPECT_EQ(0u, snapshot.size());
    172 }
    173 
    174 TEST_F(StatisticsRecorderTest, RegisterHistogramWithFactoryGet) {
    175   StatisticsRecorder::Histograms registered_histograms;
    176 
    177   StatisticsRecorder::GetHistograms(&registered_histograms);
    178   ASSERT_EQ(0u, registered_histograms.size());
    179 
    180   // Create a histogram.
    181   HistogramBase* histogram = Histogram::FactoryGet(
    182       "TestHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
    183   registered_histograms.clear();
    184   StatisticsRecorder::GetHistograms(&registered_histograms);
    185   EXPECT_EQ(1u, registered_histograms.size());
    186 
    187   // Get an existing histogram.
    188   HistogramBase* histogram2 = Histogram::FactoryGet(
    189       "TestHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
    190   registered_histograms.clear();
    191   StatisticsRecorder::GetHistograms(&registered_histograms);
    192   EXPECT_EQ(1u, registered_histograms.size());
    193   EXPECT_EQ(histogram, histogram2);
    194 
    195   // Create a LinearHistogram.
    196   histogram = LinearHistogram::FactoryGet(
    197       "TestLinearHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
    198   registered_histograms.clear();
    199   StatisticsRecorder::GetHistograms(&registered_histograms);
    200   EXPECT_EQ(2u, registered_histograms.size());
    201 
    202   // Create a BooleanHistogram.
    203   histogram = BooleanHistogram::FactoryGet(
    204       "TestBooleanHistogram", HistogramBase::kNoFlags);
    205   registered_histograms.clear();
    206   StatisticsRecorder::GetHistograms(&registered_histograms);
    207   EXPECT_EQ(3u, registered_histograms.size());
    208 
    209   // Create a CustomHistogram.
    210   std::vector<int> custom_ranges;
    211   custom_ranges.push_back(1);
    212   custom_ranges.push_back(5);
    213   histogram = CustomHistogram::FactoryGet(
    214       "TestCustomHistogram", custom_ranges, HistogramBase::kNoFlags);
    215   registered_histograms.clear();
    216   StatisticsRecorder::GetHistograms(&registered_histograms);
    217   EXPECT_EQ(4u, registered_histograms.size());
    218 }
    219 
    220 TEST_F(StatisticsRecorderTest, RegisterHistogramWithMacros) {
    221   StatisticsRecorder::Histograms registered_histograms;
    222 
    223   HistogramBase* histogram = Histogram::FactoryGet(
    224       "TestHistogramCounts", 1, 1000000, 50, HistogramBase::kNoFlags);
    225 
    226   // The histogram we got from macro is the same as from FactoryGet.
    227   LOCAL_HISTOGRAM_COUNTS("TestHistogramCounts", 30);
    228   registered_histograms.clear();
    229   StatisticsRecorder::GetHistograms(&registered_histograms);
    230   ASSERT_EQ(1u, registered_histograms.size());
    231   EXPECT_EQ(histogram, registered_histograms[0]);
    232 
    233   LOCAL_HISTOGRAM_TIMES("TestHistogramTimes", TimeDelta::FromDays(1));
    234   LOCAL_HISTOGRAM_ENUMERATION("TestHistogramEnumeration", 20, 200);
    235 
    236   registered_histograms.clear();
    237   StatisticsRecorder::GetHistograms(&registered_histograms);
    238   EXPECT_EQ(3u, registered_histograms.size());
    239 }
    240 
    241 TEST_F(StatisticsRecorderTest, BucketRangesSharing) {
    242   std::vector<const BucketRanges*> ranges;
    243   StatisticsRecorder::GetBucketRanges(&ranges);
    244   EXPECT_EQ(0u, ranges.size());
    245 
    246   Histogram::FactoryGet("Histogram", 1, 64, 8, HistogramBase::kNoFlags);
    247   Histogram::FactoryGet("Histogram2", 1, 64, 8, HistogramBase::kNoFlags);
    248 
    249   StatisticsRecorder::GetBucketRanges(&ranges);
    250   EXPECT_EQ(1u, ranges.size());
    251 
    252   Histogram::FactoryGet("Histogram3", 1, 64, 16, HistogramBase::kNoFlags);
    253 
    254   ranges.clear();
    255   StatisticsRecorder::GetBucketRanges(&ranges);
    256   EXPECT_EQ(2u, ranges.size());
    257 }
    258 
    259 TEST_F(StatisticsRecorderTest, ToJSON) {
    260   LOCAL_HISTOGRAM_COUNTS("TestHistogram1", 30);
    261   LOCAL_HISTOGRAM_COUNTS("TestHistogram1", 40);
    262   LOCAL_HISTOGRAM_COUNTS("TestHistogram2", 30);
    263   LOCAL_HISTOGRAM_COUNTS("TestHistogram2", 40);
    264 
    265   std::string json(StatisticsRecorder::ToJSON(std::string()));
    266 
    267   // Check for valid JSON.
    268   scoped_ptr<Value> root = JSONReader::Read(json);
    269   ASSERT_TRUE(root.get());
    270 
    271   DictionaryValue* root_dict = NULL;
    272   ASSERT_TRUE(root->GetAsDictionary(&root_dict));
    273 
    274   // No query should be set.
    275   ASSERT_FALSE(root_dict->HasKey("query"));
    276 
    277   ListValue* histogram_list = NULL;
    278   ASSERT_TRUE(root_dict->GetList("histograms", &histogram_list));
    279   ASSERT_EQ(2u, histogram_list->GetSize());
    280 
    281   // Examine the first histogram.
    282   DictionaryValue* histogram_dict = NULL;
    283   ASSERT_TRUE(histogram_list->GetDictionary(0, &histogram_dict));
    284 
    285   int sample_count;
    286   ASSERT_TRUE(histogram_dict->GetInteger("count", &sample_count));
    287   EXPECT_EQ(2, sample_count);
    288 
    289   // Test the query filter.
    290   std::string query("TestHistogram2");
    291   json = StatisticsRecorder::ToJSON(query);
    292 
    293   root = JSONReader::Read(json);
    294   ASSERT_TRUE(root.get());
    295   ASSERT_TRUE(root->GetAsDictionary(&root_dict));
    296 
    297   std::string query_value;
    298   ASSERT_TRUE(root_dict->GetString("query", &query_value));
    299   EXPECT_EQ(query, query_value);
    300 
    301   ASSERT_TRUE(root_dict->GetList("histograms", &histogram_list));
    302   ASSERT_EQ(1u, histogram_list->GetSize());
    303 
    304   ASSERT_TRUE(histogram_list->GetDictionary(0, &histogram_dict));
    305 
    306   std::string histogram_name;
    307   ASSERT_TRUE(histogram_dict->GetString("name", &histogram_name));
    308   EXPECT_EQ("TestHistogram2", histogram_name);
    309 
    310   json.clear();
    311   UninitializeStatisticsRecorder();
    312 
    313   // No data should be returned.
    314   json = StatisticsRecorder::ToJSON(query);
    315   EXPECT_TRUE(json.empty());
    316 }
    317 
    318 namespace {
    319 
    320 // CallbackCheckWrapper is simply a convenient way to check and store that
    321 // a callback was actually run.
    322 struct CallbackCheckWrapper {
    323   CallbackCheckWrapper() : called(false), last_histogram_value(0) {}
    324 
    325   void OnHistogramChanged(base::HistogramBase::Sample histogram_value) {
    326     called = true;
    327     last_histogram_value = histogram_value;
    328   }
    329 
    330   bool called;
    331   base::HistogramBase::Sample last_histogram_value;
    332 };
    333 
    334 }  // namespace
    335 
    336 // Check that you can't overwrite the callback with another.
    337 TEST_F(StatisticsRecorderTest, SetCallbackFailsWithoutHistogramTest) {
    338   CallbackCheckWrapper callback_wrapper;
    339 
    340   bool result = base::StatisticsRecorder::SetCallback(
    341       "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
    342                                   base::Unretained(&callback_wrapper)));
    343   EXPECT_TRUE(result);
    344 
    345   result = base::StatisticsRecorder::SetCallback(
    346       "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
    347                                   base::Unretained(&callback_wrapper)));
    348   EXPECT_FALSE(result);
    349 }
    350 
    351 // Check that you can't overwrite the callback with another.
    352 TEST_F(StatisticsRecorderTest, SetCallbackFailsWithHistogramTest) {
    353   HistogramBase* histogram = Histogram::FactoryGet("TestHistogram", 1, 1000, 10,
    354                                                    HistogramBase::kNoFlags);
    355   EXPECT_TRUE(histogram);
    356 
    357   CallbackCheckWrapper callback_wrapper;
    358 
    359   bool result = base::StatisticsRecorder::SetCallback(
    360       "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
    361                                   base::Unretained(&callback_wrapper)));
    362   EXPECT_TRUE(result);
    363   EXPECT_EQ(histogram->flags() & base::HistogramBase::kCallbackExists,
    364             base::HistogramBase::kCallbackExists);
    365 
    366   result = base::StatisticsRecorder::SetCallback(
    367       "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
    368                                   base::Unretained(&callback_wrapper)));
    369   EXPECT_FALSE(result);
    370   EXPECT_EQ(histogram->flags() & base::HistogramBase::kCallbackExists,
    371             base::HistogramBase::kCallbackExists);
    372 
    373   histogram->Add(1);
    374 
    375   EXPECT_TRUE(callback_wrapper.called);
    376 }
    377 
    378 // Check that you can't overwrite the callback with another.
    379 TEST_F(StatisticsRecorderTest, ClearCallbackSuceedsWithHistogramTest) {
    380   HistogramBase* histogram = Histogram::FactoryGet("TestHistogram", 1, 1000, 10,
    381                                                    HistogramBase::kNoFlags);
    382   EXPECT_TRUE(histogram);
    383 
    384   CallbackCheckWrapper callback_wrapper;
    385 
    386   bool result = base::StatisticsRecorder::SetCallback(
    387       "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
    388                                   base::Unretained(&callback_wrapper)));
    389   EXPECT_TRUE(result);
    390   EXPECT_EQ(histogram->flags() & base::HistogramBase::kCallbackExists,
    391             base::HistogramBase::kCallbackExists);
    392 
    393   base::StatisticsRecorder::ClearCallback("TestHistogram");
    394   EXPECT_EQ(histogram->flags() & base::HistogramBase::kCallbackExists, 0);
    395 
    396   histogram->Add(1);
    397 
    398   EXPECT_FALSE(callback_wrapper.called);
    399 }
    400 
    401 // Check that callback is used.
    402 TEST_F(StatisticsRecorderTest, CallbackUsedTest) {
    403   {
    404     HistogramBase* histogram = Histogram::FactoryGet(
    405         "TestHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
    406     EXPECT_TRUE(histogram);
    407 
    408     CallbackCheckWrapper callback_wrapper;
    409 
    410     base::StatisticsRecorder::SetCallback(
    411         "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
    412                                     base::Unretained(&callback_wrapper)));
    413 
    414     histogram->Add(1);
    415 
    416     EXPECT_TRUE(callback_wrapper.called);
    417     EXPECT_EQ(callback_wrapper.last_histogram_value, 1);
    418   }
    419 
    420   {
    421     HistogramBase* linear_histogram = LinearHistogram::FactoryGet(
    422         "TestLinearHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
    423 
    424     CallbackCheckWrapper callback_wrapper;
    425 
    426     base::StatisticsRecorder::SetCallback(
    427         "TestLinearHistogram",
    428         base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
    429                    base::Unretained(&callback_wrapper)));
    430 
    431     linear_histogram->Add(1);
    432 
    433     EXPECT_TRUE(callback_wrapper.called);
    434     EXPECT_EQ(callback_wrapper.last_histogram_value, 1);
    435   }
    436 
    437   {
    438     std::vector<int> custom_ranges;
    439     custom_ranges.push_back(1);
    440     custom_ranges.push_back(5);
    441     HistogramBase* custom_histogram = CustomHistogram::FactoryGet(
    442         "TestCustomHistogram", custom_ranges, HistogramBase::kNoFlags);
    443 
    444     CallbackCheckWrapper callback_wrapper;
    445 
    446     base::StatisticsRecorder::SetCallback(
    447         "TestCustomHistogram",
    448         base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
    449                    base::Unretained(&callback_wrapper)));
    450 
    451     custom_histogram->Add(1);
    452 
    453     EXPECT_TRUE(callback_wrapper.called);
    454     EXPECT_EQ(callback_wrapper.last_histogram_value, 1);
    455   }
    456 
    457   {
    458     HistogramBase* custom_histogram = SparseHistogram::FactoryGet(
    459         "TestSparseHistogram", HistogramBase::kNoFlags);
    460 
    461     CallbackCheckWrapper callback_wrapper;
    462 
    463     base::StatisticsRecorder::SetCallback(
    464         "TestSparseHistogram",
    465         base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
    466                    base::Unretained(&callback_wrapper)));
    467 
    468     custom_histogram->Add(1);
    469 
    470     EXPECT_TRUE(callback_wrapper.called);
    471     EXPECT_EQ(callback_wrapper.last_histogram_value, 1);
    472   }
    473 }
    474 
    475 // Check that setting a callback before the histogram exists works.
    476 TEST_F(StatisticsRecorderTest, CallbackUsedBeforeHistogramCreatedTest) {
    477   CallbackCheckWrapper callback_wrapper;
    478 
    479   base::StatisticsRecorder::SetCallback(
    480       "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
    481                                   base::Unretained(&callback_wrapper)));
    482 
    483   HistogramBase* histogram = Histogram::FactoryGet("TestHistogram", 1, 1000, 10,
    484                                                    HistogramBase::kNoFlags);
    485   EXPECT_TRUE(histogram);
    486   histogram->Add(1);
    487 
    488   EXPECT_TRUE(callback_wrapper.called);
    489   EXPECT_EQ(callback_wrapper.last_histogram_value, 1);
    490 }
    491 
    492 }  // namespace base
    493