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