// 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/metrics/dummy_histogram.h"
#include "base/run_loop.h"
#include "base/test/gtest_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/threading/thread.h"
#include "components/metrics/single_sample_metrics.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())
      ShutdownThread();
    base::SingleSampleMetricsFactory::DeleteFactoryForTesting();
  }

 protected:
  void StartThread() { ASSERT_TRUE(thread_.Start()); }

  void ShutdownThread() {
    thread_.task_runner()->PostTask(
        FROM_HERE,
        base::Bind(&SingleSampleMetricsFactoryImpl::DestroyProviderForTesting,
                   base::Unretained(factory_)));
    thread_.Stop();
  }

  void CreateProvider(mojom::SingleSampleMetricsProviderRequest request) {
    CreateSingleSampleMetricsProvider(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 Dummy histogram returned.
  EXPECT_EQ(base::DummyHistogram::GetInstance(),
            base::Histogram::FactoryGet(kMetricName, 1, 3, 3,
                                        base::HistogramBase::kNoFlags));
  EXPECT_NE(base::DummyHistogram::GetInstance(),
            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 shutdown thread to ensure destruction completes.
  thread_.task_runner()->DeleteSoon(FROM_HERE, threaded_metric.release());
  ShutdownThread();

  metric.reset();
  base::RunLoop().RunUntilIdle();

  tester.ExpectUniqueSample(kMetricName, kSample, 2);
}

}  // namespace metrics
