Index: components/metrics/single_sample_metrics_factory_impl_unittest.cc |
diff --git a/components/metrics/single_sample_metrics_factory_impl_unittest.cc b/components/metrics/single_sample_metrics_factory_impl_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..0ef75be789851849150efcea49c5b78823994600 |
--- /dev/null |
+++ b/components/metrics/single_sample_metrics_factory_impl_unittest.cc |
@@ -0,0 +1,183 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "components/metrics/single_sample_metrics_factory_impl.h" |
+ |
+#include "base/message_loop/message_loop.h" |
+#include "base/run_loop.h" |
+#include "base/test/gtest_util.h" |
+#include "base/test/histogram_tester.h" |
+#include "base/threading/thread.h" |
+#include "components/metrics/single_sample_metrics.h" |
+#include "services/service_manager/public/cpp/bind_source_info.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace metrics { |
+ |
+namespace { |
+ |
+const base::HistogramBase::Sample kMin = 1; |
+const base::HistogramBase::Sample kMax = 10; |
+const uint32_t kBucketCount = 10; |
+const char kMetricName[] = "Single.Sample.Metric"; |
+ |
+class SingleSampleMetricsFactoryImplTest : public testing::Test { |
+ public: |
+ SingleSampleMetricsFactoryImplTest() : thread_("TestThread") { |
+ InitializeSingleSampleMetricsFactory( |
+ base::BindRepeating(&SingleSampleMetricsFactoryImplTest::CreateProvider, |
+ base::Unretained(this))); |
+ factory_ = static_cast<SingleSampleMetricsFactoryImpl*>( |
+ base::SingleSampleMetricsFactory::Get()); |
+ } |
+ |
+ ~SingleSampleMetricsFactoryImplTest() override { |
+ factory_->DestroyProviderForTesting(); |
+ if (thread_.IsRunning()) { |
+ thread_.task_runner()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&SingleSampleMetricsFactoryImpl::DestroyProviderForTesting, |
+ base::Unretained(factory_))); |
+ thread_.Stop(); |
+ } |
+ base::SingleSampleMetricsFactory::DeleteFactoryForTesting(); |
+ } |
+ |
+ protected: |
+ void StartThread() { ASSERT_TRUE(thread_.Start()); } |
+ |
+ void CreateProvider(mojom::SingleSampleMetricsProviderRequest request) { |
+ CreateSingleSampleMetricsProvider(service_manager::BindSourceInfo(), |
+ std::move(request)); |
+ provider_count_++; |
+ } |
+ |
+ std::unique_ptr<base::SingleSampleMetric> CreateMetricOnThread() { |
+ std::unique_ptr<base::SingleSampleMetric> metric; |
+ base::RunLoop run_loop; |
+ thread_.task_runner()->PostTaskAndReply( |
+ FROM_HERE, |
+ base::Bind(&SingleSampleMetricsFactoryImplTest::CreateAndStoreMetric, |
+ base::Unretained(this), &metric), |
+ run_loop.QuitClosure()); |
+ run_loop.Run(); |
+ return metric; |
+ } |
+ |
+ void CreateAndStoreMetric(std::unique_ptr<base::SingleSampleMetric>* metric) { |
+ *metric = factory_->CreateCustomCountsMetric(kMetricName, kMin, kMax, |
+ kBucketCount); |
+ } |
+ |
+ base::MessageLoop message_looqp_; |
+ SingleSampleMetricsFactoryImpl* factory_; |
+ base::Thread thread_; |
+ size_t provider_count_ = 0; |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(SingleSampleMetricsFactoryImplTest); |
+}; |
+ |
+} // namespace |
+ |
+TEST_F(SingleSampleMetricsFactoryImplTest, SingleProvider) { |
+ std::unique_ptr<base::SingleSampleMetric> metric1 = |
+ factory_->CreateCustomCountsMetric(kMetricName, kMin, kMax, kBucketCount); |
+ |
+ std::unique_ptr<base::SingleSampleMetric> metric2 = |
+ factory_->CreateCustomCountsMetric(kMetricName, kMin, kMax, kBucketCount); |
+ |
+ // Verify that only a single provider is created for multiple metrics. |
+ base::RunLoop().RunUntilIdle(); |
+ EXPECT_EQ(1u, provider_count_); |
+} |
+ |
+TEST_F(SingleSampleMetricsFactoryImplTest, DoesNothing) { |
+ base::HistogramTester tester; |
+ |
+ std::unique_ptr<base::SingleSampleMetric> metric = |
+ factory_->CreateCustomCountsMetric(kMetricName, kMin, kMax, kBucketCount); |
+ metric.reset(); |
+ |
+ // Verify that no sample is recorded if SetSample() is never called. |
+ base::RunLoop().RunUntilIdle(); |
+ tester.ExpectTotalCount(kMetricName, 0); |
+} |
+ |
+TEST_F(SingleSampleMetricsFactoryImplTest, DefaultSingleSampleMetricWithValue) { |
+ base::HistogramTester tester; |
+ std::unique_ptr<base::SingleSampleMetric> metric = |
+ factory_->CreateCustomCountsMetric(kMetricName, kMin, kMax, kBucketCount); |
+ |
+ const base::HistogramBase::Sample kLastSample = 9; |
+ metric->SetSample(1); |
+ metric->SetSample(3); |
+ metric->SetSample(5); |
+ metric->SetSample(kLastSample); |
+ metric.reset(); |
+ |
+ // Verify only the last sample sent to SetSample() is recorded. |
+ base::RunLoop().RunUntilIdle(); |
+ tester.ExpectUniqueSample(kMetricName, kLastSample, 1); |
+ |
+ // Verify construction implicitly by requesting a histogram with the same |
+ // parameters; this test relies on the fact that histogram objects are unique |
+ // per name. Different parameters will result in a nullptr being returned. |
+ EXPECT_FALSE(base::Histogram::FactoryGet(kMetricName, 1, 3, 3, |
+ base::HistogramBase::kNoFlags)); |
+ EXPECT_TRUE(base::Histogram::FactoryGet( |
+ kMetricName, kMin, kMax, kBucketCount, |
+ base::HistogramBase::kUmaTargetedHistogramFlag)); |
+} |
+ |
+TEST_F(SingleSampleMetricsFactoryImplTest, MultithreadedMetrics) { |
+ base::HistogramTester tester; |
+ std::unique_ptr<base::SingleSampleMetric> metric = |
+ factory_->CreateCustomCountsMetric(kMetricName, kMin, kMax, kBucketCount); |
+ EXPECT_EQ(1u, provider_count_); |
+ |
+ StartThread(); |
+ |
+ std::unique_ptr<base::SingleSampleMetric> threaded_metric = |
+ CreateMetricOnThread(); |
+ ASSERT_TRUE(threaded_metric); |
+ |
+ // A second provider should be created to handle requests on our new thread. |
+ EXPECT_EQ(2u, provider_count_); |
+ |
+ // Calls from the wrong thread should DCHECK. |
+ EXPECT_DCHECK_DEATH(threaded_metric->SetSample(5)); |
+ EXPECT_DCHECK_DEATH(threaded_metric.reset()); |
+ |
+ // Test that samples are set on each thread correctly. |
+ const base::HistogramBase::Sample kSample = 7; |
+ |
+ { |
+ metric->SetSample(kSample); |
+ |
+ base::RunLoop run_loop; |
+ thread_.task_runner()->PostTaskAndReply( |
+ FROM_HERE, |
+ base::Bind(&base::SingleSampleMetric::SetSample, |
+ base::Unretained(threaded_metric.get()), kSample), |
+ run_loop.QuitClosure()); |
+ run_loop.Run(); |
+ } |
+ |
+ // Release metrics and cycle threads to ensure destruction completes. |
+ { |
+ thread_.task_runner()->DeleteSoon(FROM_HERE, threaded_metric.release()); |
+ |
+ base::RunLoop run_loop; |
+ thread_.task_runner()->PostTaskAndReply( |
+ FROM_HERE, base::Bind(&base::DoNothing), run_loop.QuitClosure()); |
+ run_loop.Run(); |
+ } |
+ |
+ metric.reset(); |
+ base::RunLoop().RunUntilIdle(); |
+ tester.ExpectUniqueSample(kMetricName, kSample, 2); |
+} |
+ |
+} // namespace metrics |