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 "base/metrics/statistics_recorder.h"
      6 
      7 #include <stddef.h>
      8 
      9 #include <memory>
     10 #include <utility>
     11 #include <vector>
     12 
     13 #include "base/bind.h"
     14 #include "base/json/json_reader.h"
     15 #include "base/logging.h"
     16 #include "base/memory/weak_ptr.h"
     17 #include "base/metrics/histogram_base.h"
     18 #include "base/metrics/histogram_macros.h"
     19 #include "base/metrics/persistent_histogram_allocator.h"
     20 #include "base/metrics/record_histogram_checker.h"
     21 #include "base/metrics/sparse_histogram.h"
     22 #include "base/values.h"
     23 #include "testing/gmock/include/gmock/gmock.h"
     24 #include "testing/gtest/include/gtest/gtest.h"
     25 
     26 namespace {
     27 
     28 // Class to make sure any manipulations we do to the min log level are
     29 // contained (i.e., do not affect other unit tests).
     30 class LogStateSaver {
     31  public:
     32   LogStateSaver() : old_min_log_level_(logging::GetMinLogLevel()) {}
     33 
     34   ~LogStateSaver() { logging::SetMinLogLevel(old_min_log_level_); }
     35 
     36  private:
     37   int old_min_log_level_;
     38 
     39   DISALLOW_COPY_AND_ASSIGN(LogStateSaver);
     40 };
     41 
     42 // Test implementation of RecordHistogramChecker interface.
     43 class OddRecordHistogramChecker : public base::RecordHistogramChecker {
     44  public:
     45   ~OddRecordHistogramChecker() override = default;
     46 
     47   // base::RecordHistogramChecker:
     48   bool ShouldRecord(uint64_t histogram_hash) const override {
     49     return histogram_hash % 2;
     50   }
     51 };
     52 
     53 }  // namespace
     54 
     55 namespace base {
     56 
     57 using testing::IsEmpty;
     58 using testing::SizeIs;
     59 using testing::UnorderedElementsAre;
     60 
     61 class StatisticsRecorderTest : public testing::TestWithParam<bool> {
     62  protected:
     63   const int32_t kAllocatorMemorySize = 64 << 10;  // 64 KiB
     64 
     65   StatisticsRecorderTest() : use_persistent_histogram_allocator_(GetParam()) {
     66     // Each test will have a clean state (no Histogram / BucketRanges
     67     // registered).
     68     InitializeStatisticsRecorder();
     69 
     70     // Use persistent memory for histograms if so indicated by test parameter.
     71     if (use_persistent_histogram_allocator_) {
     72       GlobalHistogramAllocator::CreateWithLocalMemory(kAllocatorMemorySize, 0,
     73                                                       "StatisticsRecorderTest");
     74     }
     75   }
     76 
     77   ~StatisticsRecorderTest() override {
     78     GlobalHistogramAllocator::ReleaseForTesting();
     79     UninitializeStatisticsRecorder();
     80   }
     81 
     82   void InitializeStatisticsRecorder() {
     83     DCHECK(!statistics_recorder_);
     84     statistics_recorder_ = StatisticsRecorder::CreateTemporaryForTesting();
     85   }
     86 
     87   // Deletes the global recorder if there is any. This is used by test
     88   // NotInitialized to ensure a clean global state.
     89   void UninitializeStatisticsRecorder() {
     90     statistics_recorder_.reset();
     91     delete StatisticsRecorder::top_;
     92     DCHECK(!StatisticsRecorder::top_);
     93   }
     94 
     95   bool HasGlobalRecorder() { return StatisticsRecorder::top_ != nullptr; }
     96 
     97   Histogram* CreateHistogram(const char* name,
     98                              HistogramBase::Sample min,
     99                              HistogramBase::Sample max,
    100                              size_t bucket_count) {
    101     BucketRanges* ranges = new BucketRanges(bucket_count + 1);
    102     Histogram::InitializeBucketRanges(min, max, ranges);
    103     const BucketRanges* registered_ranges =
    104         StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges);
    105     return new Histogram(name, min, max, registered_ranges);
    106   }
    107 
    108   void InitLogOnShutdown() { StatisticsRecorder::InitLogOnShutdown(); }
    109 
    110   bool IsVLogInitialized() { return StatisticsRecorder::is_vlog_initialized_; }
    111 
    112   void ResetVLogInitialized() {
    113     UninitializeStatisticsRecorder();
    114     StatisticsRecorder::is_vlog_initialized_ = false;
    115   }
    116 
    117   const bool use_persistent_histogram_allocator_;
    118 
    119   std::unique_ptr<StatisticsRecorder> statistics_recorder_;
    120   std::unique_ptr<GlobalHistogramAllocator> old_global_allocator_;
    121 
    122  private:
    123   LogStateSaver log_state_saver_;
    124 
    125   DISALLOW_COPY_AND_ASSIGN(StatisticsRecorderTest);
    126 };
    127 
    128 // Run all HistogramTest cases with both heap and persistent memory.
    129 INSTANTIATE_TEST_CASE_P(Allocator, StatisticsRecorderTest, testing::Bool());
    130 
    131 TEST_P(StatisticsRecorderTest, NotInitialized) {
    132   UninitializeStatisticsRecorder();
    133   EXPECT_FALSE(HasGlobalRecorder());
    134 
    135   HistogramBase* const histogram =
    136       CreateHistogram("TestHistogram", 1, 1000, 10);
    137   EXPECT_EQ(StatisticsRecorder::RegisterOrDeleteDuplicate(histogram),
    138             histogram);
    139   EXPECT_TRUE(HasGlobalRecorder());
    140   EXPECT_THAT(StatisticsRecorder::GetHistograms(),
    141               UnorderedElementsAre(histogram));
    142 
    143   UninitializeStatisticsRecorder();
    144   EXPECT_FALSE(HasGlobalRecorder());
    145 
    146   BucketRanges* const ranges = new BucketRanges(3);
    147   ranges->ResetChecksum();
    148   EXPECT_EQ(StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges),
    149             ranges);
    150   EXPECT_TRUE(HasGlobalRecorder());
    151   EXPECT_THAT(StatisticsRecorder::GetBucketRanges(),
    152               UnorderedElementsAre(ranges));
    153 }
    154 
    155 TEST_P(StatisticsRecorderTest, RegisterBucketRanges) {
    156   std::vector<const BucketRanges*> registered_ranges;
    157 
    158   BucketRanges* ranges1 = new BucketRanges(3);
    159   ranges1->ResetChecksum();
    160   BucketRanges* ranges2 = new BucketRanges(4);
    161   ranges2->ResetChecksum();
    162 
    163   // Register new ranges.
    164   EXPECT_EQ(ranges1,
    165             StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges1));
    166   EXPECT_EQ(ranges2,
    167             StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges2));
    168   EXPECT_THAT(StatisticsRecorder::GetBucketRanges(),
    169               UnorderedElementsAre(ranges1, ranges2));
    170 
    171   // Register some ranges again.
    172   EXPECT_EQ(ranges1,
    173             StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges1));
    174   EXPECT_THAT(StatisticsRecorder::GetBucketRanges(),
    175               UnorderedElementsAre(ranges1, ranges2));
    176 
    177   // Make sure the ranges is still the one we know.
    178   ASSERT_EQ(3u, ranges1->size());
    179   EXPECT_EQ(0, ranges1->range(0));
    180   EXPECT_EQ(0, ranges1->range(1));
    181   EXPECT_EQ(0, ranges1->range(2));
    182 
    183   // Register ranges with same values.
    184   BucketRanges* ranges3 = new BucketRanges(3);
    185   ranges3->ResetChecksum();
    186   EXPECT_EQ(ranges1,  // returning ranges1
    187             StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges3));
    188   EXPECT_THAT(StatisticsRecorder::GetBucketRanges(),
    189               UnorderedElementsAre(ranges1, ranges2));
    190 }
    191 
    192 TEST_P(StatisticsRecorderTest, RegisterHistogram) {
    193   // Create a Histogram that was not registered.
    194   Histogram* const histogram1 = CreateHistogram("TestHistogram1", 1, 1000, 10);
    195 
    196   EXPECT_THAT(StatisticsRecorder::GetHistograms(), IsEmpty());
    197 
    198   // Register the Histogram.
    199   EXPECT_EQ(histogram1,
    200             StatisticsRecorder::RegisterOrDeleteDuplicate(histogram1));
    201   EXPECT_THAT(StatisticsRecorder::GetHistograms(),
    202               UnorderedElementsAre(histogram1));
    203 
    204   // Register the same Histogram again.
    205   EXPECT_EQ(histogram1,
    206             StatisticsRecorder::RegisterOrDeleteDuplicate(histogram1));
    207   EXPECT_THAT(StatisticsRecorder::GetHistograms(),
    208               UnorderedElementsAre(histogram1));
    209 
    210   // Register another Histogram with the same name.
    211   Histogram* const histogram2 = CreateHistogram("TestHistogram1", 1, 1000, 10);
    212   EXPECT_NE(histogram1, histogram2);
    213   EXPECT_EQ(histogram1,
    214             StatisticsRecorder::RegisterOrDeleteDuplicate(histogram2));
    215   EXPECT_THAT(StatisticsRecorder::GetHistograms(),
    216               UnorderedElementsAre(histogram1));
    217 
    218   // Register another Histogram with a different name.
    219   Histogram* const histogram3 = CreateHistogram("TestHistogram0", 1, 1000, 10);
    220   EXPECT_NE(histogram1, histogram3);
    221   EXPECT_EQ(histogram3,
    222             StatisticsRecorder::RegisterOrDeleteDuplicate(histogram3));
    223   EXPECT_THAT(StatisticsRecorder::GetHistograms(),
    224               UnorderedElementsAre(histogram1, histogram3));
    225 }
    226 
    227 TEST_P(StatisticsRecorderTest, FindHistogram) {
    228   HistogramBase* histogram1 = Histogram::FactoryGet(
    229       "TestHistogram1", 1, 1000, 10, HistogramBase::kNoFlags);
    230   HistogramBase* histogram2 = Histogram::FactoryGet(
    231       "TestHistogram2", 1, 1000, 10, HistogramBase::kNoFlags);
    232 
    233   EXPECT_EQ(histogram1, StatisticsRecorder::FindHistogram("TestHistogram1"));
    234   EXPECT_EQ(histogram2, StatisticsRecorder::FindHistogram("TestHistogram2"));
    235   EXPECT_FALSE(StatisticsRecorder::FindHistogram("TestHistogram"));
    236 
    237   // Create a new global allocator using the same memory as the old one. Any
    238   // old one is kept around so the memory doesn't get released.
    239   old_global_allocator_ = GlobalHistogramAllocator::ReleaseForTesting();
    240   if (use_persistent_histogram_allocator_) {
    241     GlobalHistogramAllocator::CreateWithPersistentMemory(
    242         const_cast<void*>(old_global_allocator_->data()),
    243         old_global_allocator_->length(), 0, old_global_allocator_->Id(),
    244         old_global_allocator_->Name());
    245   }
    246 
    247   // Reset statistics-recorder to validate operation from a clean start.
    248   UninitializeStatisticsRecorder();
    249   InitializeStatisticsRecorder();
    250 
    251   if (use_persistent_histogram_allocator_) {
    252     EXPECT_TRUE(StatisticsRecorder::FindHistogram("TestHistogram1"));
    253     EXPECT_TRUE(StatisticsRecorder::FindHistogram("TestHistogram2"));
    254   } else {
    255     EXPECT_FALSE(StatisticsRecorder::FindHistogram("TestHistogram1"));
    256     EXPECT_FALSE(StatisticsRecorder::FindHistogram("TestHistogram2"));
    257   }
    258   EXPECT_FALSE(StatisticsRecorder::FindHistogram("TestHistogram"));
    259 }
    260 
    261 TEST_P(StatisticsRecorderTest, WithName) {
    262   Histogram::FactoryGet("TestHistogram1", 1, 1000, 10, Histogram::kNoFlags);
    263   Histogram::FactoryGet("TestHistogram2", 1, 1000, 10, Histogram::kNoFlags);
    264   Histogram::FactoryGet("TestHistogram3", 1, 1000, 10, Histogram::kNoFlags);
    265 
    266   const auto histograms = StatisticsRecorder::GetHistograms();
    267   EXPECT_THAT(histograms, SizeIs(3));
    268   EXPECT_THAT(StatisticsRecorder::WithName(histograms, ""), SizeIs(3));
    269   EXPECT_THAT(StatisticsRecorder::WithName(histograms, "Test"), SizeIs(3));
    270   EXPECT_THAT(StatisticsRecorder::WithName(histograms, "1"), SizeIs(1));
    271   EXPECT_THAT(StatisticsRecorder::WithName(histograms, "hello"), IsEmpty());
    272 }
    273 
    274 TEST_P(StatisticsRecorderTest, RegisterHistogramWithFactoryGet) {
    275   EXPECT_THAT(StatisticsRecorder::GetHistograms(), IsEmpty());
    276 
    277   // Create a histogram.
    278   HistogramBase* const histogram1 = Histogram::FactoryGet(
    279       "TestHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
    280   EXPECT_THAT(StatisticsRecorder::GetHistograms(),
    281               UnorderedElementsAre(histogram1));
    282 
    283   // Get an existing histogram.
    284   HistogramBase* const histogram2 = Histogram::FactoryGet(
    285       "TestHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
    286   EXPECT_EQ(histogram1, histogram2);
    287   EXPECT_THAT(StatisticsRecorder::GetHistograms(),
    288               UnorderedElementsAre(histogram1));
    289 
    290   // Create a LinearHistogram.
    291   HistogramBase* const histogram3 = LinearHistogram::FactoryGet(
    292       "TestLinearHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
    293   EXPECT_THAT(StatisticsRecorder::GetHistograms(),
    294               UnorderedElementsAre(histogram1, histogram3));
    295 
    296   // Create a BooleanHistogram.
    297   HistogramBase* const histogram4 = BooleanHistogram::FactoryGet(
    298       "TestBooleanHistogram", HistogramBase::kNoFlags);
    299   EXPECT_THAT(StatisticsRecorder::GetHistograms(),
    300               UnorderedElementsAre(histogram1, histogram3, histogram4));
    301 
    302   // Create a CustomHistogram.
    303   std::vector<int> custom_ranges;
    304   custom_ranges.push_back(1);
    305   custom_ranges.push_back(5);
    306   HistogramBase* const histogram5 = CustomHistogram::FactoryGet(
    307       "TestCustomHistogram", custom_ranges, HistogramBase::kNoFlags);
    308   EXPECT_THAT(
    309       StatisticsRecorder::GetHistograms(),
    310       UnorderedElementsAre(histogram1, histogram3, histogram4, histogram5));
    311 }
    312 
    313 TEST_P(StatisticsRecorderTest, RegisterHistogramWithMacros) {
    314   // Macros cache pointers and so tests that use them can only be run once.
    315   // Stop immediately if this test has run previously.
    316   static bool already_run = false;
    317   if (already_run)
    318     return;
    319   already_run = true;
    320 
    321   StatisticsRecorder::Histograms registered_histograms;
    322 
    323   HistogramBase* histogram = Histogram::FactoryGet(
    324       "TestHistogramCounts", 1, 1000000, 50, HistogramBase::kNoFlags);
    325 
    326   // The histogram we got from macro is the same as from FactoryGet.
    327   LOCAL_HISTOGRAM_COUNTS("TestHistogramCounts", 30);
    328   registered_histograms = StatisticsRecorder::GetHistograms();
    329   ASSERT_EQ(1u, registered_histograms.size());
    330   EXPECT_EQ(histogram, registered_histograms[0]);
    331 
    332   LOCAL_HISTOGRAM_TIMES("TestHistogramTimes", TimeDelta::FromDays(1));
    333   LOCAL_HISTOGRAM_ENUMERATION("TestHistogramEnumeration", 20, 200);
    334 
    335   EXPECT_THAT(StatisticsRecorder::GetHistograms(), SizeIs(3));
    336 }
    337 
    338 TEST_P(StatisticsRecorderTest, BucketRangesSharing) {
    339   EXPECT_THAT(StatisticsRecorder::GetBucketRanges(), IsEmpty());
    340 
    341   Histogram::FactoryGet("Histogram", 1, 64, 8, HistogramBase::kNoFlags);
    342   Histogram::FactoryGet("Histogram2", 1, 64, 8, HistogramBase::kNoFlags);
    343   EXPECT_THAT(StatisticsRecorder::GetBucketRanges(), SizeIs(1));
    344 
    345   Histogram::FactoryGet("Histogram3", 1, 64, 16, HistogramBase::kNoFlags);
    346   EXPECT_THAT(StatisticsRecorder::GetBucketRanges(), SizeIs(2));
    347 }
    348 
    349 TEST_P(StatisticsRecorderTest, ToJSON) {
    350   Histogram::FactoryGet("TestHistogram1", 1, 1000, 50, HistogramBase::kNoFlags)
    351       ->Add(30);
    352   Histogram::FactoryGet("TestHistogram1", 1, 1000, 50, HistogramBase::kNoFlags)
    353       ->Add(40);
    354   Histogram::FactoryGet("TestHistogram2", 1, 1000, 50, HistogramBase::kNoFlags)
    355       ->Add(30);
    356   Histogram::FactoryGet("TestHistogram2", 1, 1000, 50, HistogramBase::kNoFlags)
    357       ->Add(40);
    358 
    359   std::string json(StatisticsRecorder::ToJSON(JSON_VERBOSITY_LEVEL_FULL));
    360 
    361   // Check for valid JSON.
    362   std::unique_ptr<Value> root = JSONReader::Read(json);
    363   ASSERT_TRUE(root.get());
    364 
    365   DictionaryValue* root_dict = nullptr;
    366   ASSERT_TRUE(root->GetAsDictionary(&root_dict));
    367 
    368   // No query should be set.
    369   ASSERT_FALSE(root_dict->HasKey("query"));
    370 
    371   ListValue* histogram_list = nullptr;
    372   ASSERT_TRUE(root_dict->GetList("histograms", &histogram_list));
    373   ASSERT_EQ(2u, histogram_list->GetSize());
    374 
    375   // Examine the first histogram.
    376   DictionaryValue* histogram_dict = nullptr;
    377   ASSERT_TRUE(histogram_list->GetDictionary(0, &histogram_dict));
    378 
    379   int sample_count;
    380   ASSERT_TRUE(histogram_dict->GetInteger("count", &sample_count));
    381   EXPECT_EQ(2, sample_count);
    382 
    383   ListValue* buckets_list = nullptr;
    384   ASSERT_TRUE(histogram_dict->GetList("buckets", &buckets_list));
    385   EXPECT_EQ(2u, buckets_list->GetList().size());
    386 
    387   // Check the serialized JSON with a different verbosity level.
    388   json = StatisticsRecorder::ToJSON(JSON_VERBOSITY_LEVEL_OMIT_BUCKETS);
    389   root = JSONReader::Read(json);
    390   ASSERT_TRUE(root.get());
    391   root_dict = nullptr;
    392   ASSERT_TRUE(root->GetAsDictionary(&root_dict));
    393   histogram_list = nullptr;
    394   ASSERT_TRUE(root_dict->GetList("histograms", &histogram_list));
    395   ASSERT_EQ(2u, histogram_list->GetSize());
    396   histogram_dict = nullptr;
    397   ASSERT_TRUE(histogram_list->GetDictionary(0, &histogram_dict));
    398   sample_count = 0;
    399   ASSERT_TRUE(histogram_dict->GetInteger("count", &sample_count));
    400   EXPECT_EQ(2, sample_count);
    401   buckets_list = nullptr;
    402   // Bucket information should be omitted.
    403   ASSERT_FALSE(histogram_dict->GetList("buckets", &buckets_list));
    404 }
    405 
    406 TEST_P(StatisticsRecorderTest, IterationTest) {
    407   Histogram::FactoryGet("IterationTest1", 1, 64, 16, HistogramBase::kNoFlags);
    408   Histogram::FactoryGet("IterationTest2", 1, 64, 16, HistogramBase::kNoFlags);
    409 
    410   auto histograms = StatisticsRecorder::GetHistograms();
    411   EXPECT_THAT(histograms, SizeIs(2));
    412   histograms = StatisticsRecorder::NonPersistent(std::move(histograms));
    413   EXPECT_THAT(histograms, SizeIs(use_persistent_histogram_allocator_ ? 0 : 2));
    414 
    415   // Create a new global allocator using the same memory as the old one. Any
    416   // old one is kept around so the memory doesn't get released.
    417   old_global_allocator_ = GlobalHistogramAllocator::ReleaseForTesting();
    418   if (use_persistent_histogram_allocator_) {
    419     GlobalHistogramAllocator::CreateWithPersistentMemory(
    420         const_cast<void*>(old_global_allocator_->data()),
    421         old_global_allocator_->length(), 0, old_global_allocator_->Id(),
    422         old_global_allocator_->Name());
    423   }
    424 
    425   // Reset statistics-recorder to validate operation from a clean start.
    426   UninitializeStatisticsRecorder();
    427   InitializeStatisticsRecorder();
    428 
    429   histograms = StatisticsRecorder::GetHistograms();
    430   EXPECT_THAT(histograms, SizeIs(use_persistent_histogram_allocator_ ? 2 : 0));
    431   histograms = StatisticsRecorder::NonPersistent(std::move(histograms));
    432   EXPECT_THAT(histograms, IsEmpty());
    433 }
    434 
    435 namespace {
    436 
    437 // CallbackCheckWrapper is simply a convenient way to check and store that
    438 // a callback was actually run.
    439 struct CallbackCheckWrapper {
    440   CallbackCheckWrapper() : called(false), last_histogram_value(0) {}
    441 
    442   void OnHistogramChanged(base::HistogramBase::Sample histogram_value) {
    443     called = true;
    444     last_histogram_value = histogram_value;
    445   }
    446 
    447   bool called;
    448   base::HistogramBase::Sample last_histogram_value;
    449 };
    450 
    451 }  // namespace
    452 
    453 // Check that you can't overwrite the callback with another.
    454 TEST_P(StatisticsRecorderTest, SetCallbackFailsWithoutHistogramTest) {
    455   CallbackCheckWrapper callback_wrapper;
    456 
    457   bool result = base::StatisticsRecorder::SetCallback(
    458       "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
    459                                   base::Unretained(&callback_wrapper)));
    460   EXPECT_TRUE(result);
    461 
    462   result = base::StatisticsRecorder::SetCallback(
    463       "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
    464                                   base::Unretained(&callback_wrapper)));
    465   EXPECT_FALSE(result);
    466 }
    467 
    468 // Check that you can't overwrite the callback with another.
    469 TEST_P(StatisticsRecorderTest, SetCallbackFailsWithHistogramTest) {
    470   HistogramBase* histogram = Histogram::FactoryGet("TestHistogram", 1, 1000, 10,
    471                                                    HistogramBase::kNoFlags);
    472   EXPECT_TRUE(histogram);
    473 
    474   CallbackCheckWrapper callback_wrapper;
    475 
    476   bool result = base::StatisticsRecorder::SetCallback(
    477       "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
    478                                   base::Unretained(&callback_wrapper)));
    479   EXPECT_TRUE(result);
    480   EXPECT_EQ(histogram->flags() & base::HistogramBase::kCallbackExists,
    481             base::HistogramBase::kCallbackExists);
    482 
    483   result = base::StatisticsRecorder::SetCallback(
    484       "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
    485                                   base::Unretained(&callback_wrapper)));
    486   EXPECT_FALSE(result);
    487   EXPECT_EQ(histogram->flags() & base::HistogramBase::kCallbackExists,
    488             base::HistogramBase::kCallbackExists);
    489 
    490   histogram->Add(1);
    491 
    492   EXPECT_TRUE(callback_wrapper.called);
    493 }
    494 
    495 // Check that you can't overwrite the callback with another.
    496 TEST_P(StatisticsRecorderTest, ClearCallbackSuceedsWithHistogramTest) {
    497   HistogramBase* histogram = Histogram::FactoryGet("TestHistogram", 1, 1000, 10,
    498                                                    HistogramBase::kNoFlags);
    499   EXPECT_TRUE(histogram);
    500 
    501   CallbackCheckWrapper callback_wrapper;
    502 
    503   bool result = base::StatisticsRecorder::SetCallback(
    504       "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
    505                                   base::Unretained(&callback_wrapper)));
    506   EXPECT_TRUE(result);
    507   EXPECT_EQ(histogram->flags() & base::HistogramBase::kCallbackExists,
    508             base::HistogramBase::kCallbackExists);
    509 
    510   base::StatisticsRecorder::ClearCallback("TestHistogram");
    511   EXPECT_EQ(histogram->flags() & base::HistogramBase::kCallbackExists, 0);
    512 
    513   histogram->Add(1);
    514 
    515   EXPECT_FALSE(callback_wrapper.called);
    516 }
    517 
    518 // Check that callback is used.
    519 TEST_P(StatisticsRecorderTest, CallbackUsedTest) {
    520   {
    521     HistogramBase* histogram = Histogram::FactoryGet(
    522         "TestHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
    523     EXPECT_TRUE(histogram);
    524 
    525     CallbackCheckWrapper callback_wrapper;
    526 
    527     base::StatisticsRecorder::SetCallback(
    528         "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
    529                                     base::Unretained(&callback_wrapper)));
    530 
    531     histogram->Add(1);
    532 
    533     EXPECT_TRUE(callback_wrapper.called);
    534     EXPECT_EQ(callback_wrapper.last_histogram_value, 1);
    535   }
    536 
    537   {
    538     HistogramBase* linear_histogram = LinearHistogram::FactoryGet(
    539         "TestLinearHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
    540 
    541     CallbackCheckWrapper callback_wrapper;
    542 
    543     base::StatisticsRecorder::SetCallback(
    544         "TestLinearHistogram",
    545         base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
    546                    base::Unretained(&callback_wrapper)));
    547 
    548     linear_histogram->Add(1);
    549 
    550     EXPECT_TRUE(callback_wrapper.called);
    551     EXPECT_EQ(callback_wrapper.last_histogram_value, 1);
    552   }
    553 
    554   {
    555     std::vector<int> custom_ranges;
    556     custom_ranges.push_back(1);
    557     custom_ranges.push_back(5);
    558     HistogramBase* custom_histogram = CustomHistogram::FactoryGet(
    559         "TestCustomHistogram", custom_ranges, HistogramBase::kNoFlags);
    560 
    561     CallbackCheckWrapper callback_wrapper;
    562 
    563     base::StatisticsRecorder::SetCallback(
    564         "TestCustomHistogram",
    565         base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
    566                    base::Unretained(&callback_wrapper)));
    567 
    568     custom_histogram->Add(1);
    569 
    570     EXPECT_TRUE(callback_wrapper.called);
    571     EXPECT_EQ(callback_wrapper.last_histogram_value, 1);
    572   }
    573 
    574   {
    575     HistogramBase* custom_histogram = SparseHistogram::FactoryGet(
    576         "TestSparseHistogram", HistogramBase::kNoFlags);
    577 
    578     CallbackCheckWrapper callback_wrapper;
    579 
    580     base::StatisticsRecorder::SetCallback(
    581         "TestSparseHistogram",
    582         base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
    583                    base::Unretained(&callback_wrapper)));
    584 
    585     custom_histogram->Add(1);
    586 
    587     EXPECT_TRUE(callback_wrapper.called);
    588     EXPECT_EQ(callback_wrapper.last_histogram_value, 1);
    589   }
    590 }
    591 
    592 // Check that setting a callback before the histogram exists works.
    593 TEST_P(StatisticsRecorderTest, CallbackUsedBeforeHistogramCreatedTest) {
    594   CallbackCheckWrapper callback_wrapper;
    595 
    596   base::StatisticsRecorder::SetCallback(
    597       "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
    598                                   base::Unretained(&callback_wrapper)));
    599 
    600   HistogramBase* histogram = Histogram::FactoryGet("TestHistogram", 1, 1000, 10,
    601                                                    HistogramBase::kNoFlags);
    602   EXPECT_TRUE(histogram);
    603   histogram->Add(1);
    604 
    605   EXPECT_TRUE(callback_wrapper.called);
    606   EXPECT_EQ(callback_wrapper.last_histogram_value, 1);
    607 }
    608 
    609 TEST_P(StatisticsRecorderTest, LogOnShutdownNotInitialized) {
    610   ResetVLogInitialized();
    611   logging::SetMinLogLevel(logging::LOG_WARNING);
    612   InitializeStatisticsRecorder();
    613   EXPECT_FALSE(VLOG_IS_ON(1));
    614   EXPECT_FALSE(IsVLogInitialized());
    615   InitLogOnShutdown();
    616   EXPECT_FALSE(IsVLogInitialized());
    617 }
    618 
    619 TEST_P(StatisticsRecorderTest, LogOnShutdownInitializedExplicitly) {
    620   ResetVLogInitialized();
    621   logging::SetMinLogLevel(logging::LOG_WARNING);
    622   InitializeStatisticsRecorder();
    623   EXPECT_FALSE(VLOG_IS_ON(1));
    624   EXPECT_FALSE(IsVLogInitialized());
    625   logging::SetMinLogLevel(logging::LOG_VERBOSE);
    626   EXPECT_TRUE(VLOG_IS_ON(1));
    627   InitLogOnShutdown();
    628   EXPECT_TRUE(IsVLogInitialized());
    629 }
    630 
    631 TEST_P(StatisticsRecorderTest, LogOnShutdownInitialized) {
    632   ResetVLogInitialized();
    633   logging::SetMinLogLevel(logging::LOG_VERBOSE);
    634   InitializeStatisticsRecorder();
    635   EXPECT_TRUE(VLOG_IS_ON(1));
    636   EXPECT_TRUE(IsVLogInitialized());
    637 }
    638 
    639 class TestHistogramProvider : public StatisticsRecorder::HistogramProvider {
    640  public:
    641   TestHistogramProvider(std::unique_ptr<PersistentHistogramAllocator> allocator)
    642       : allocator_(std::move(allocator)), weak_factory_(this) {
    643     StatisticsRecorder::RegisterHistogramProvider(weak_factory_.GetWeakPtr());
    644   }
    645 
    646   void MergeHistogramDeltas() override {
    647     PersistentHistogramAllocator::Iterator hist_iter(allocator_.get());
    648     while (true) {
    649       std::unique_ptr<base::HistogramBase> histogram = hist_iter.GetNext();
    650       if (!histogram)
    651         break;
    652       allocator_->MergeHistogramDeltaToStatisticsRecorder(histogram.get());
    653     }
    654   }
    655 
    656  private:
    657   std::unique_ptr<PersistentHistogramAllocator> allocator_;
    658   WeakPtrFactory<TestHistogramProvider> weak_factory_;
    659 
    660   DISALLOW_COPY_AND_ASSIGN(TestHistogramProvider);
    661 };
    662 
    663 TEST_P(StatisticsRecorderTest, ImportHistogramsTest) {
    664   // Create a second SR to create some histograms for later import.
    665   std::unique_ptr<StatisticsRecorder> temp_sr =
    666       StatisticsRecorder::CreateTemporaryForTesting();
    667 
    668   // Extract any existing global allocator so a new one can be created.
    669   std::unique_ptr<GlobalHistogramAllocator> old_allocator =
    670       GlobalHistogramAllocator::ReleaseForTesting();
    671 
    672   // Create a histogram inside a new allocator for testing.
    673   GlobalHistogramAllocator::CreateWithLocalMemory(kAllocatorMemorySize, 0, "");
    674   HistogramBase* histogram = LinearHistogram::FactoryGet("Foo", 1, 10, 11, 0);
    675   histogram->Add(3);
    676 
    677   // Undo back to the starting point.
    678   std::unique_ptr<GlobalHistogramAllocator> new_allocator =
    679       GlobalHistogramAllocator::ReleaseForTesting();
    680   GlobalHistogramAllocator::Set(std::move(old_allocator));
    681   temp_sr.reset();
    682 
    683   // Create a provider that can supply histograms to the current SR.
    684   TestHistogramProvider provider(std::move(new_allocator));
    685 
    686   // Verify that the created histogram is no longer known.
    687   ASSERT_FALSE(StatisticsRecorder::FindHistogram(histogram->histogram_name()));
    688 
    689   // Now test that it merges.
    690   StatisticsRecorder::ImportProvidedHistograms();
    691   HistogramBase* found =
    692       StatisticsRecorder::FindHistogram(histogram->histogram_name());
    693   ASSERT_TRUE(found);
    694   EXPECT_NE(histogram, found);
    695   std::unique_ptr<HistogramSamples> snapshot = found->SnapshotSamples();
    696   EXPECT_EQ(1, snapshot->TotalCount());
    697   EXPECT_EQ(1, snapshot->GetCount(3));
    698 
    699   // Finally, verify that updates can also be merged.
    700   histogram->Add(3);
    701   histogram->Add(5);
    702   StatisticsRecorder::ImportProvidedHistograms();
    703   snapshot = found->SnapshotSamples();
    704   EXPECT_EQ(3, snapshot->TotalCount());
    705   EXPECT_EQ(2, snapshot->GetCount(3));
    706   EXPECT_EQ(1, snapshot->GetCount(5));
    707 }
    708 
    709 TEST_P(StatisticsRecorderTest, RecordHistogramChecker) {
    710   // Before record checker is set all histograms should be recorded.
    711   EXPECT_TRUE(StatisticsRecorder::ShouldRecordHistogram(1));
    712   EXPECT_TRUE(StatisticsRecorder::ShouldRecordHistogram(2));
    713 
    714   auto record_checker = std::make_unique<OddRecordHistogramChecker>();
    715   StatisticsRecorder::SetRecordChecker(std::move(record_checker));
    716   EXPECT_TRUE(StatisticsRecorder::ShouldRecordHistogram(1));
    717   EXPECT_FALSE(StatisticsRecorder::ShouldRecordHistogram(2));
    718 }
    719 
    720 }  // namespace base
    721