1 // Copyright 2017 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/metrics/single_sample_metrics_factory_impl.h"
7 #include "base/functional/bind.h"
8 #include "base/memory/raw_ptr.h"
9 #include "base/metrics/dummy_histogram.h"
10 #include "base/run_loop.h"
11 #include "base/test/gtest_util.h"
12 #include "base/test/metrics/histogram_tester.h"
13 #include "base/test/task_environment.h"
14 #include "base/threading/thread.h"
15 #include "components/metrics/single_sample_metrics.h"
16 #include "mojo/public/cpp/bindings/pending_receiver.h"
17 #include "testing/gtest/include/gtest/gtest.h"
23 const base::HistogramBase::Sample kMin = 1;
24 const base::HistogramBase::Sample kMax = 10;
25 const uint32_t kBucketCount = 10;
26 const char kMetricName[] = "Single.Sample.Metric";
28 class SingleSampleMetricsFactoryImplTest : public testing::Test {
30 SingleSampleMetricsFactoryImplTest() : thread_("TestThread") {
31 InitializeSingleSampleMetricsFactory(
32 base::BindRepeating(&SingleSampleMetricsFactoryImplTest::CreateProvider,
33 base::Unretained(this)));
34 factory_ = static_cast<SingleSampleMetricsFactoryImpl*>(
35 base::SingleSampleMetricsFactory::Get());
38 SingleSampleMetricsFactoryImplTest(
39 const SingleSampleMetricsFactoryImplTest&) = delete;
40 SingleSampleMetricsFactoryImplTest& operator=(
41 const SingleSampleMetricsFactoryImplTest&) = delete;
43 ~SingleSampleMetricsFactoryImplTest() override {
44 factory_->DestroyProviderForTesting();
46 if (thread_.IsRunning())
48 base::SingleSampleMetricsFactory::DeleteFactoryForTesting();
52 void StartThread() { ASSERT_TRUE(thread_.Start()); }
54 void ShutdownThread() {
55 thread_.task_runner()->PostTask(
58 &SingleSampleMetricsFactoryImpl::DestroyProviderForTesting,
59 base::Unretained(factory_)));
64 mojo::PendingReceiver<mojom::SingleSampleMetricsProvider> receiver) {
65 CreateSingleSampleMetricsProvider(std::move(receiver));
69 std::unique_ptr<base::SingleSampleMetric> CreateMetricOnThread() {
70 std::unique_ptr<base::SingleSampleMetric> metric;
71 base::RunLoop run_loop;
72 thread_.task_runner()->PostTaskAndReply(
75 &SingleSampleMetricsFactoryImplTest::CreateAndStoreMetric,
76 base::Unretained(this), &metric),
77 run_loop.QuitClosure());
82 void CreateAndStoreMetric(std::unique_ptr<base::SingleSampleMetric>* metric) {
83 *metric = factory_->CreateCustomCountsMetric(kMetricName, kMin, kMax,
87 base::test::SingleThreadTaskEnvironment task_environment_;
88 raw_ptr<SingleSampleMetricsFactoryImpl> factory_;
90 size_t provider_count_ = 0;
95 TEST_F(SingleSampleMetricsFactoryImplTest, SingleProvider) {
96 std::unique_ptr<base::SingleSampleMetric> metric1 =
97 factory_->CreateCustomCountsMetric(kMetricName, kMin, kMax, kBucketCount);
99 std::unique_ptr<base::SingleSampleMetric> metric2 =
100 factory_->CreateCustomCountsMetric(kMetricName, kMin, kMax, kBucketCount);
102 // Verify that only a single provider is created for multiple metrics.
103 base::RunLoop().RunUntilIdle();
104 EXPECT_EQ(1u, provider_count_);
107 TEST_F(SingleSampleMetricsFactoryImplTest, DoesNothing) {
108 base::HistogramTester tester;
110 std::unique_ptr<base::SingleSampleMetric> metric =
111 factory_->CreateCustomCountsMetric(kMetricName, kMin, kMax, kBucketCount);
114 // Verify that no sample is recorded if SetSample() is never called.
115 base::RunLoop().RunUntilIdle();
116 tester.ExpectTotalCount(kMetricName, 0);
119 TEST_F(SingleSampleMetricsFactoryImplTest, DefaultSingleSampleMetricWithValue) {
120 base::HistogramTester tester;
121 std::unique_ptr<base::SingleSampleMetric> metric =
122 factory_->CreateCustomCountsMetric(kMetricName, kMin, kMax, kBucketCount);
124 const base::HistogramBase::Sample kLastSample = 9;
125 metric->SetSample(1);
126 metric->SetSample(3);
127 metric->SetSample(5);
128 metric->SetSample(kLastSample);
131 // Verify only the last sample sent to SetSample() is recorded.
132 base::RunLoop().RunUntilIdle();
133 tester.ExpectUniqueSample(kMetricName, kLastSample, 1);
135 // Verify construction implicitly by requesting a histogram with the same
136 // parameters; this test relies on the fact that histogram objects are unique
137 // per name. Different parameters will result in a Dummy histogram returned.
138 EXPECT_EQ(base::DummyHistogram::GetInstance(),
139 base::Histogram::FactoryGet(kMetricName, 1, 3, 3,
140 base::HistogramBase::kNoFlags));
141 EXPECT_NE(base::DummyHistogram::GetInstance(),
142 base::Histogram::FactoryGet(
143 kMetricName, kMin, kMax, kBucketCount,
144 base::HistogramBase::kUmaTargetedHistogramFlag));
147 TEST_F(SingleSampleMetricsFactoryImplTest, MultithreadedMetrics) {
148 // Allow EXPECT_DCHECK_DEATH for multiple threads.
149 // https://github.com/google/googletest/blob/main/docs/advanced.md#death-tests-and-threads
150 testing::FLAGS_gtest_death_test_style = "threadsafe";
152 base::HistogramTester tester;
153 std::unique_ptr<base::SingleSampleMetric> metric =
154 factory_->CreateCustomCountsMetric(kMetricName, kMin, kMax, kBucketCount);
155 EXPECT_EQ(1u, provider_count_);
159 std::unique_ptr<base::SingleSampleMetric> threaded_metric =
160 CreateMetricOnThread();
161 ASSERT_TRUE(threaded_metric);
163 // A second provider should be created to handle requests on our new thread.
164 EXPECT_EQ(2u, provider_count_);
166 // Calls from the wrong thread should DCHECK.
167 EXPECT_DCHECK_DEATH(threaded_metric->SetSample(5));
168 EXPECT_DCHECK_DEATH(threaded_metric.reset());
170 // Test that samples are set on each thread correctly.
171 const base::HistogramBase::Sample kSample = 7;
174 metric->SetSample(kSample);
176 base::RunLoop run_loop;
177 thread_.task_runner()->PostTaskAndReply(
179 base::BindOnce(&base::SingleSampleMetric::SetSample,
180 base::Unretained(threaded_metric.get()), kSample),
181 run_loop.QuitClosure());
185 // Release metrics and shutdown thread to ensure destruction completes.
186 thread_.task_runner()->DeleteSoon(FROM_HERE, threaded_metric.release());
190 base::RunLoop().RunUntilIdle();
192 tester.ExpectUniqueSample(kMetricName, kSample, 2);
195 } // namespace metrics