single_sample_metrics_factory_impl_unittest.cc 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. // Copyright 2017 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. #include "components/metrics/single_sample_metrics_factory_impl.h"
  5. #include "base/bind.h"
  6. #include "base/memory/raw_ptr.h"
  7. #include "base/metrics/dummy_histogram.h"
  8. #include "base/run_loop.h"
  9. #include "base/test/gtest_util.h"
  10. #include "base/test/metrics/histogram_tester.h"
  11. #include "base/test/task_environment.h"
  12. #include "base/threading/thread.h"
  13. #include "components/metrics/single_sample_metrics.h"
  14. #include "mojo/public/cpp/bindings/pending_receiver.h"
  15. #include "testing/gtest/include/gtest/gtest.h"
  16. namespace metrics {
  17. namespace {
  18. const base::HistogramBase::Sample kMin = 1;
  19. const base::HistogramBase::Sample kMax = 10;
  20. const uint32_t kBucketCount = 10;
  21. const char kMetricName[] = "Single.Sample.Metric";
  22. class SingleSampleMetricsFactoryImplTest : public testing::Test {
  23. public:
  24. SingleSampleMetricsFactoryImplTest() : thread_("TestThread") {
  25. InitializeSingleSampleMetricsFactory(
  26. base::BindRepeating(&SingleSampleMetricsFactoryImplTest::CreateProvider,
  27. base::Unretained(this)));
  28. factory_ = static_cast<SingleSampleMetricsFactoryImpl*>(
  29. base::SingleSampleMetricsFactory::Get());
  30. }
  31. SingleSampleMetricsFactoryImplTest(
  32. const SingleSampleMetricsFactoryImplTest&) = delete;
  33. SingleSampleMetricsFactoryImplTest& operator=(
  34. const SingleSampleMetricsFactoryImplTest&) = delete;
  35. ~SingleSampleMetricsFactoryImplTest() override {
  36. factory_->DestroyProviderForTesting();
  37. if (thread_.IsRunning())
  38. ShutdownThread();
  39. base::SingleSampleMetricsFactory::DeleteFactoryForTesting();
  40. }
  41. protected:
  42. void StartThread() { ASSERT_TRUE(thread_.Start()); }
  43. void ShutdownThread() {
  44. thread_.task_runner()->PostTask(
  45. FROM_HERE,
  46. base::BindOnce(
  47. &SingleSampleMetricsFactoryImpl::DestroyProviderForTesting,
  48. base::Unretained(factory_)));
  49. thread_.Stop();
  50. }
  51. void CreateProvider(
  52. mojo::PendingReceiver<mojom::SingleSampleMetricsProvider> receiver) {
  53. CreateSingleSampleMetricsProvider(std::move(receiver));
  54. provider_count_++;
  55. }
  56. std::unique_ptr<base::SingleSampleMetric> CreateMetricOnThread() {
  57. std::unique_ptr<base::SingleSampleMetric> metric;
  58. base::RunLoop run_loop;
  59. thread_.task_runner()->PostTaskAndReply(
  60. FROM_HERE,
  61. base::BindOnce(
  62. &SingleSampleMetricsFactoryImplTest::CreateAndStoreMetric,
  63. base::Unretained(this), &metric),
  64. run_loop.QuitClosure());
  65. run_loop.Run();
  66. return metric;
  67. }
  68. void CreateAndStoreMetric(std::unique_ptr<base::SingleSampleMetric>* metric) {
  69. *metric = factory_->CreateCustomCountsMetric(kMetricName, kMin, kMax,
  70. kBucketCount);
  71. }
  72. base::test::SingleThreadTaskEnvironment task_environment_;
  73. raw_ptr<SingleSampleMetricsFactoryImpl> factory_;
  74. base::Thread thread_;
  75. size_t provider_count_ = 0;
  76. };
  77. } // namespace
  78. TEST_F(SingleSampleMetricsFactoryImplTest, SingleProvider) {
  79. std::unique_ptr<base::SingleSampleMetric> metric1 =
  80. factory_->CreateCustomCountsMetric(kMetricName, kMin, kMax, kBucketCount);
  81. std::unique_ptr<base::SingleSampleMetric> metric2 =
  82. factory_->CreateCustomCountsMetric(kMetricName, kMin, kMax, kBucketCount);
  83. // Verify that only a single provider is created for multiple metrics.
  84. base::RunLoop().RunUntilIdle();
  85. EXPECT_EQ(1u, provider_count_);
  86. }
  87. TEST_F(SingleSampleMetricsFactoryImplTest, DoesNothing) {
  88. base::HistogramTester tester;
  89. std::unique_ptr<base::SingleSampleMetric> metric =
  90. factory_->CreateCustomCountsMetric(kMetricName, kMin, kMax, kBucketCount);
  91. metric.reset();
  92. // Verify that no sample is recorded if SetSample() is never called.
  93. base::RunLoop().RunUntilIdle();
  94. tester.ExpectTotalCount(kMetricName, 0);
  95. }
  96. TEST_F(SingleSampleMetricsFactoryImplTest, DefaultSingleSampleMetricWithValue) {
  97. base::HistogramTester tester;
  98. std::unique_ptr<base::SingleSampleMetric> metric =
  99. factory_->CreateCustomCountsMetric(kMetricName, kMin, kMax, kBucketCount);
  100. const base::HistogramBase::Sample kLastSample = 9;
  101. metric->SetSample(1);
  102. metric->SetSample(3);
  103. metric->SetSample(5);
  104. metric->SetSample(kLastSample);
  105. metric.reset();
  106. // Verify only the last sample sent to SetSample() is recorded.
  107. base::RunLoop().RunUntilIdle();
  108. tester.ExpectUniqueSample(kMetricName, kLastSample, 1);
  109. // Verify construction implicitly by requesting a histogram with the same
  110. // parameters; this test relies on the fact that histogram objects are unique
  111. // per name. Different parameters will result in a Dummy histogram returned.
  112. EXPECT_EQ(base::DummyHistogram::GetInstance(),
  113. base::Histogram::FactoryGet(kMetricName, 1, 3, 3,
  114. base::HistogramBase::kNoFlags));
  115. EXPECT_NE(base::DummyHistogram::GetInstance(),
  116. base::Histogram::FactoryGet(
  117. kMetricName, kMin, kMax, kBucketCount,
  118. base::HistogramBase::kUmaTargetedHistogramFlag));
  119. }
  120. TEST_F(SingleSampleMetricsFactoryImplTest, MultithreadedMetrics) {
  121. // Allow EXPECT_DCHECK_DEATH for multiple threads.
  122. // https://github.com/google/googletest/blob/main/docs/advanced.md#death-tests-and-threads
  123. testing::FLAGS_gtest_death_test_style = "threadsafe";
  124. base::HistogramTester tester;
  125. std::unique_ptr<base::SingleSampleMetric> metric =
  126. factory_->CreateCustomCountsMetric(kMetricName, kMin, kMax, kBucketCount);
  127. EXPECT_EQ(1u, provider_count_);
  128. StartThread();
  129. std::unique_ptr<base::SingleSampleMetric> threaded_metric =
  130. CreateMetricOnThread();
  131. ASSERT_TRUE(threaded_metric);
  132. // A second provider should be created to handle requests on our new thread.
  133. EXPECT_EQ(2u, provider_count_);
  134. // Calls from the wrong thread should DCHECK.
  135. EXPECT_DCHECK_DEATH(threaded_metric->SetSample(5));
  136. EXPECT_DCHECK_DEATH(threaded_metric.reset());
  137. // Test that samples are set on each thread correctly.
  138. const base::HistogramBase::Sample kSample = 7;
  139. {
  140. metric->SetSample(kSample);
  141. base::RunLoop run_loop;
  142. thread_.task_runner()->PostTaskAndReply(
  143. FROM_HERE,
  144. base::BindOnce(&base::SingleSampleMetric::SetSample,
  145. base::Unretained(threaded_metric.get()), kSample),
  146. run_loop.QuitClosure());
  147. run_loop.Run();
  148. }
  149. // Release metrics and shutdown thread to ensure destruction completes.
  150. thread_.task_runner()->DeleteSoon(FROM_HERE, threaded_metric.release());
  151. ShutdownThread();
  152. metric.reset();
  153. base::RunLoop().RunUntilIdle();
  154. tester.ExpectUniqueSample(kMetricName, kSample, 2);
  155. }
  156. } // namespace metrics