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