Home | History | Annotate | Download | only in metrics
      1 // Copyright 2016 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/persistent_histogram_allocator.h"
      6 
      7 #include "base/files/scoped_temp_dir.h"
      8 #include "base/logging.h"
      9 #include "base/memory/ptr_util.h"
     10 #include "base/metrics/bucket_ranges.h"
     11 #include "base/metrics/histogram_macros.h"
     12 #include "base/metrics/persistent_memory_allocator.h"
     13 #include "base/metrics/statistics_recorder.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 
     16 namespace base {
     17 
     18 class PersistentHistogramAllocatorTest : public testing::Test {
     19  protected:
     20   const int32_t kAllocatorMemorySize = 64 << 10;  // 64 KiB
     21 
     22   PersistentHistogramAllocatorTest()
     23       : statistics_recorder_(StatisticsRecorder::CreateTemporaryForTesting()) {
     24     CreatePersistentHistogramAllocator();
     25   }
     26   ~PersistentHistogramAllocatorTest() override {
     27     DestroyPersistentHistogramAllocator();
     28   }
     29 
     30   void CreatePersistentHistogramAllocator() {
     31     allocator_memory_.reset(new char[kAllocatorMemorySize]);
     32 
     33     GlobalHistogramAllocator::ReleaseForTesting();
     34     memset(allocator_memory_.get(), 0, kAllocatorMemorySize);
     35     GlobalHistogramAllocator::GetCreateHistogramResultHistogram();
     36     GlobalHistogramAllocator::CreateWithPersistentMemory(
     37         allocator_memory_.get(), kAllocatorMemorySize, 0, 0,
     38         "PersistentHistogramAllocatorTest");
     39     allocator_ = GlobalHistogramAllocator::Get()->memory_allocator();
     40   }
     41 
     42   void DestroyPersistentHistogramAllocator() {
     43     allocator_ = nullptr;
     44     GlobalHistogramAllocator::ReleaseForTesting();
     45   }
     46 
     47   std::unique_ptr<StatisticsRecorder> statistics_recorder_;
     48   std::unique_ptr<char[]> allocator_memory_;
     49   PersistentMemoryAllocator* allocator_ = nullptr;
     50 
     51  private:
     52   DISALLOW_COPY_AND_ASSIGN(PersistentHistogramAllocatorTest);
     53 };
     54 
     55 TEST_F(PersistentHistogramAllocatorTest, CreateAndIterateTest) {
     56   PersistentMemoryAllocator::MemoryInfo meminfo0;
     57   allocator_->GetMemoryInfo(&meminfo0);
     58 
     59   // Try basic construction
     60   HistogramBase* histogram = Histogram::FactoryGet(
     61       "TestHistogram", 1, 1000, 10, HistogramBase::kIsPersistent);
     62   EXPECT_TRUE(histogram);
     63   histogram->CheckName("TestHistogram");
     64   PersistentMemoryAllocator::MemoryInfo meminfo1;
     65   allocator_->GetMemoryInfo(&meminfo1);
     66   EXPECT_GT(meminfo0.free, meminfo1.free);
     67 
     68   HistogramBase* linear_histogram = LinearHistogram::FactoryGet(
     69       "TestLinearHistogram", 1, 1000, 10, HistogramBase::kIsPersistent);
     70   EXPECT_TRUE(linear_histogram);
     71   linear_histogram->CheckName("TestLinearHistogram");
     72   PersistentMemoryAllocator::MemoryInfo meminfo2;
     73   allocator_->GetMemoryInfo(&meminfo2);
     74   EXPECT_GT(meminfo1.free, meminfo2.free);
     75 
     76   HistogramBase* boolean_histogram = BooleanHistogram::FactoryGet(
     77       "TestBooleanHistogram", HistogramBase::kIsPersistent);
     78   EXPECT_TRUE(boolean_histogram);
     79   boolean_histogram->CheckName("TestBooleanHistogram");
     80   PersistentMemoryAllocator::MemoryInfo meminfo3;
     81   allocator_->GetMemoryInfo(&meminfo3);
     82   EXPECT_GT(meminfo2.free, meminfo3.free);
     83 
     84   std::vector<int> custom_ranges;
     85   custom_ranges.push_back(1);
     86   custom_ranges.push_back(5);
     87   HistogramBase* custom_histogram = CustomHistogram::FactoryGet(
     88       "TestCustomHistogram", custom_ranges, HistogramBase::kIsPersistent);
     89   EXPECT_TRUE(custom_histogram);
     90   custom_histogram->CheckName("TestCustomHistogram");
     91   PersistentMemoryAllocator::MemoryInfo meminfo4;
     92   allocator_->GetMemoryInfo(&meminfo4);
     93   EXPECT_GT(meminfo3.free, meminfo4.free);
     94 
     95   PersistentMemoryAllocator::Iterator iter(allocator_);
     96   uint32_t type;
     97   EXPECT_NE(0U, iter.GetNext(&type));  // Histogram
     98   EXPECT_NE(0U, iter.GetNext(&type));  // LinearHistogram
     99   EXPECT_NE(0U, iter.GetNext(&type));  // BooleanHistogram
    100   EXPECT_NE(0U, iter.GetNext(&type));  // CustomHistogram
    101   EXPECT_EQ(0U, iter.GetNext(&type));
    102 
    103   // Create a second allocator and have it access the memory of the first.
    104   std::unique_ptr<HistogramBase> recovered;
    105   PersistentHistogramAllocator recovery(
    106       WrapUnique(new PersistentMemoryAllocator(
    107           allocator_memory_.get(), kAllocatorMemorySize, 0, 0, "", false)));
    108   PersistentHistogramAllocator::Iterator histogram_iter(&recovery);
    109 
    110   recovered = histogram_iter.GetNext();
    111   ASSERT_TRUE(recovered);
    112   recovered->CheckName("TestHistogram");
    113 
    114   recovered = histogram_iter.GetNext();
    115   ASSERT_TRUE(recovered);
    116   recovered->CheckName("TestLinearHistogram");
    117 
    118   recovered = histogram_iter.GetNext();
    119   ASSERT_TRUE(recovered);
    120   recovered->CheckName("TestBooleanHistogram");
    121 
    122   recovered = histogram_iter.GetNext();
    123   ASSERT_TRUE(recovered);
    124   recovered->CheckName("TestCustomHistogram");
    125 
    126   recovered = histogram_iter.GetNext();
    127   EXPECT_FALSE(recovered);
    128 }
    129 
    130 TEST_F(PersistentHistogramAllocatorTest, CreateWithFileTest) {
    131   const char temp_name[] = "CreateWithFileTest";
    132   ScopedTempDir temp_dir;
    133   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    134   FilePath temp_file = temp_dir.path().AppendASCII(temp_name);
    135   const size_t temp_size = 64 << 10;  // 64 KiB
    136 
    137   // Test creation of a new file.
    138   GlobalHistogramAllocator::ReleaseForTesting();
    139   GlobalHistogramAllocator::CreateWithFile(temp_file, temp_size, 0, temp_name);
    140   EXPECT_EQ(std::string(temp_name),
    141             GlobalHistogramAllocator::Get()->memory_allocator()->Name());
    142 
    143   // Test re-open of a possibly-existing file.
    144   GlobalHistogramAllocator::ReleaseForTesting();
    145   GlobalHistogramAllocator::CreateWithFile(temp_file, temp_size, 0, "");
    146   EXPECT_EQ(std::string(temp_name),
    147             GlobalHistogramAllocator::Get()->memory_allocator()->Name());
    148 
    149   // Test re-open of an known-existing file.
    150   GlobalHistogramAllocator::ReleaseForTesting();
    151   GlobalHistogramAllocator::CreateWithFile(temp_file, 0, 0, "");
    152   EXPECT_EQ(std::string(temp_name),
    153             GlobalHistogramAllocator::Get()->memory_allocator()->Name());
    154 
    155   // Final release so file and temp-dir can be removed.
    156   GlobalHistogramAllocator::ReleaseForTesting();
    157 }
    158 
    159 TEST_F(PersistentHistogramAllocatorTest, StatisticsRecorderTest) {
    160   size_t starting_sr_count = StatisticsRecorder::GetHistogramCount();
    161 
    162   // Create a local StatisticsRecorder in which the newly created histogram
    163   // will be recorded.
    164   std::unique_ptr<StatisticsRecorder> local_sr =
    165       StatisticsRecorder::CreateTemporaryForTesting();
    166   EXPECT_EQ(0U, StatisticsRecorder::GetHistogramCount());
    167 
    168   HistogramBase* histogram = LinearHistogram::FactoryGet(
    169       "TestHistogram", 1, 10, 10, HistogramBase::kIsPersistent);
    170   EXPECT_TRUE(histogram);
    171   EXPECT_EQ(1U, StatisticsRecorder::GetHistogramCount());
    172   histogram->Add(3);
    173   histogram->Add(1);
    174   histogram->Add(4);
    175   histogram->Add(1);
    176   histogram->Add(6);
    177 
    178   // Destroy the local SR and ensure that we're back to the initial state.
    179   local_sr.reset();
    180   EXPECT_EQ(starting_sr_count, StatisticsRecorder::GetHistogramCount());
    181 
    182   // Create a second allocator and have it access the memory of the first.
    183   std::unique_ptr<HistogramBase> recovered;
    184   PersistentHistogramAllocator recovery(
    185       WrapUnique(new PersistentMemoryAllocator(
    186           allocator_memory_.get(), kAllocatorMemorySize, 0, 0, "", false)));
    187   PersistentHistogramAllocator::Iterator histogram_iter(&recovery);
    188 
    189   recovered = histogram_iter.GetNext();
    190   ASSERT_TRUE(recovered);
    191 
    192   // Merge the recovered histogram to the SR. It will always be a new object.
    193   recovery.MergeHistogramDeltaToStatisticsRecorder(recovered.get());
    194   EXPECT_EQ(starting_sr_count + 1, StatisticsRecorder::GetHistogramCount());
    195   HistogramBase* found =
    196       StatisticsRecorder::FindHistogram(recovered->histogram_name());
    197   ASSERT_TRUE(found);
    198   EXPECT_NE(recovered.get(), found);
    199 
    200   // Ensure that the data got merged, too.
    201   std::unique_ptr<HistogramSamples> snapshot = found->SnapshotSamples();
    202   EXPECT_EQ(recovered->SnapshotSamples()->TotalCount(), snapshot->TotalCount());
    203   EXPECT_EQ(1, snapshot->GetCount(3));
    204   EXPECT_EQ(2, snapshot->GetCount(1));
    205   EXPECT_EQ(1, snapshot->GetCount(4));
    206   EXPECT_EQ(1, snapshot->GetCount(6));
    207 }
    208 
    209 }  // namespace base
    210