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