blob: b6806622502d1fdc9aebac6183621e9da0efd8a0 [file] [log] [blame]
bcwhite33d95806a2016-03-16 02:37:451// 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
bcwhite2a27d742016-06-10 15:47:057#include "base/files/scoped_temp_dir.h"
bcwhite33d95806a2016-03-16 02:37:458#include "base/logging.h"
dcheng093de9b2016-04-04 21:25:519#include "base/memory/ptr_util.h"
bcwhite33d95806a2016-03-16 02:37:4510#include "base/metrics/bucket_ranges.h"
11#include "base/metrics/histogram_macros.h"
12#include "base/metrics/persistent_memory_allocator.h"
bcwhite05dc0922016-06-03 04:59:4413#include "base/metrics/statistics_recorder.h"
bcwhite33d95806a2016-03-16 02:37:4514#include "testing/gtest/include/gtest/gtest.h"
15
16namespace base {
17
18class PersistentHistogramAllocatorTest : public testing::Test {
19 protected:
20 const int32_t kAllocatorMemorySize = 64 << 10; // 64 KiB
21
bcwhite9e3835cc2016-06-03 17:56:3522 PersistentHistogramAllocatorTest()
23 : statistics_recorder_(StatisticsRecorder::CreateTemporaryForTesting()) {
24 CreatePersistentHistogramAllocator();
25 }
bcwhite33d95806a2016-03-16 02:37:4526 ~PersistentHistogramAllocatorTest() override {
27 DestroyPersistentHistogramAllocator();
28 }
29
30 void CreatePersistentHistogramAllocator() {
31 allocator_memory_.reset(new char[kAllocatorMemorySize]);
32
bcwhite5e748c62016-04-06 02:03:5333 GlobalHistogramAllocator::ReleaseForTesting();
bcwhite33d95806a2016-03-16 02:37:4534 memset(allocator_memory_.get(), 0, kAllocatorMemorySize);
bcwhite5e748c62016-04-06 02:03:5335 GlobalHistogramAllocator::GetCreateHistogramResultHistogram();
36 GlobalHistogramAllocator::CreateWithPersistentMemory(
bcwhite33d95806a2016-03-16 02:37:4537 allocator_memory_.get(), kAllocatorMemorySize, 0, 0,
38 "PersistentHistogramAllocatorTest");
bcwhite5e748c62016-04-06 02:03:5339 allocator_ = GlobalHistogramAllocator::Get()->memory_allocator();
bcwhite33d95806a2016-03-16 02:37:4540 }
41
42 void DestroyPersistentHistogramAllocator() {
43 allocator_ = nullptr;
bcwhite5e748c62016-04-06 02:03:5344 GlobalHistogramAllocator::ReleaseForTesting();
bcwhite33d95806a2016-03-16 02:37:4545 }
46
bcwhite9e3835cc2016-06-03 17:56:3547 std::unique_ptr<StatisticsRecorder> statistics_recorder_;
dcheng093de9b2016-04-04 21:25:5148 std::unique_ptr<char[]> allocator_memory_;
bcwhite33d95806a2016-03-16 02:37:4549 PersistentMemoryAllocator* allocator_ = nullptr;
50
51 private:
52 DISALLOW_COPY_AND_ASSIGN(PersistentHistogramAllocatorTest);
53};
54
55TEST_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
bcwhitef2462022016-04-06 15:39:0195 PersistentMemoryAllocator::Iterator iter(allocator_);
bcwhite33d95806a2016-03-16 02:37:4596 uint32_t type;
bcwhitef2462022016-04-06 15:39:0197 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));
bcwhite33d95806a2016-03-16 02:37:45102
103 // Create a second allocator and have it access the memory of the first.
dcheng093de9b2016-04-04 21:25:51104 std::unique_ptr<HistogramBase> recovered;
bcwhite33d95806a2016-03-16 02:37:45105 PersistentHistogramAllocator recovery(
dcheng093de9b2016-04-04 21:25:51106 WrapUnique(new PersistentMemoryAllocator(
bcwhite33d95806a2016-03-16 02:37:45107 allocator_memory_.get(), kAllocatorMemorySize, 0, 0, "", false)));
bcwhitef2462022016-04-06 15:39:01108 PersistentHistogramAllocator::Iterator histogram_iter(&recovery);
bcwhite33d95806a2016-03-16 02:37:45109
bcwhitef2462022016-04-06 15:39:01110 recovered = histogram_iter.GetNext();
bcwhite33d95806a2016-03-16 02:37:45111 ASSERT_TRUE(recovered);
112 recovered->CheckName("TestHistogram");
113
bcwhitef2462022016-04-06 15:39:01114 recovered = histogram_iter.GetNext();
bcwhite33d95806a2016-03-16 02:37:45115 ASSERT_TRUE(recovered);
116 recovered->CheckName("TestLinearHistogram");
117
bcwhitef2462022016-04-06 15:39:01118 recovered = histogram_iter.GetNext();
bcwhite33d95806a2016-03-16 02:37:45119 ASSERT_TRUE(recovered);
120 recovered->CheckName("TestBooleanHistogram");
121
bcwhitef2462022016-04-06 15:39:01122 recovered = histogram_iter.GetNext();
bcwhite33d95806a2016-03-16 02:37:45123 ASSERT_TRUE(recovered);
124 recovered->CheckName("TestCustomHistogram");
125
bcwhitef2462022016-04-06 15:39:01126 recovered = histogram_iter.GetNext();
bcwhite33d95806a2016-03-16 02:37:45127 EXPECT_FALSE(recovered);
128}
129
bcwhite2a27d742016-06-10 15:47:05130TEST_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
bcwhite05dc0922016-06-03 04:59:44159TEST_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 =
bcwhite9e3835cc2016-06-03 17:56:35165 StatisticsRecorder::CreateTemporaryForTesting();
bcwhite05dc0922016-06-03 04:59:44166 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.
bcwhite2a27d742016-06-10 15:47:05193 recovery.MergeHistogramDeltaToStatisticsRecorder(recovered.get());
bcwhite05dc0922016-06-03 04:59:44194 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
bcwhite33d95806a2016-03-16 02:37:45209} // namespace base