// Copyright 2019 The Fuchsia 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 "metrics.h"

#include <lib/async-testing/test_loop.h>

#include <memory>
#include <type_traits>
#include <utility>

#include <cobalt-client/cpp/collector.h>
#include <cobalt-client/cpp/in_memory_logger.h>
#include <fs/metrics/events.h>
#include <zxtest/zxtest.h>

namespace devmgr {
namespace {

using EventIntType = std::underlying_type<fs_metrics::Event>::type;

std::unique_ptr<cobalt_client::Collector> MakeCollector(cobalt_client::InMemoryLogger** logger) {
  std::unique_ptr<cobalt_client::InMemoryLogger> logger_ptr =
      std::make_unique<cobalt_client::InMemoryLogger>();
  *logger = logger_ptr.get();
  return std::make_unique<cobalt_client::Collector>(std::move(logger_ptr));
}

class MetricsTest : public zxtest::Test {
 public:
  void SetUp() override { collector_ = MakeCollector(&logger_); }
  void TearDown() override { logger_ = nullptr; }

 protected:
  cobalt_client::InMemoryLogger* logger_;
  std::unique_ptr<cobalt_client::Collector> collector_;
};

cobalt_client::MetricOptions MakeMetricOptionsFromId(uint32_t metric_id) {
  cobalt_client::MetricOptions info = {};
  info.metric_id = metric_id;
  info.metric_dimensions = 2;
  info.event_codes = {0};
  info.event_codes[0] = static_cast<uint32_t>(fs_metrics::CorruptionSource::kMinfs);
  info.event_codes[1] = static_cast<uint32_t>(fs_metrics::CorruptionType::kMetadata);
  return info;
}

constexpr auto kCorruptionMetricId = static_cast<EventIntType>(fs_metrics::Event::kDataCorruption);

TEST_F(MetricsTest, LogMinfsDataCorruption) {
  FsHostMetrics metrics(std::move(collector_));
  ASSERT_EQ(logger_->counters().find(MakeMetricOptionsFromId(kCorruptionMetricId)),
            logger_->counters().end());
  metrics.LogMinfsCorruption();
  // Nothing is logged until flushed.
  ASSERT_EQ(logger_->counters().find(MakeMetricOptionsFromId(kCorruptionMetricId)),
            logger_->counters().end());

  // Once we flush, we should see the logged event in the metrics.
  metrics.mutable_collector()->Flush();
  ASSERT_NE(logger_->counters().find(MakeMetricOptionsFromId(kCorruptionMetricId)),
            logger_->counters().end());

  EXPECT_EQ(logger_->counters().at(MakeMetricOptionsFromId(kCorruptionMetricId)), 1);
}

TEST_F(MetricsTest, FlushUntilSuccessWorks) {
  async::TestLoop loop;
  FsHostMetrics metrics(std::move(collector_));
  metrics.LogMinfsCorruption();

  // Logger is not working
  logger_->fail_logging(true);
  metrics.FlushUntilSuccess(loop.dispatcher());
  loop.RunFor(zx::sec(10));

  // After 10 seconds, nothing should be logged.
  ASSERT_EQ(logger_->counters().find(MakeMetricOptionsFromId(kCorruptionMetricId)),
            logger_->counters().end());
  loop.RunFor(zx::sec(10));

  // After 20 seconds, nothing should be logged.
  ASSERT_EQ(logger_->counters().find(MakeMetricOptionsFromId(kCorruptionMetricId)),
            logger_->counters().end());

  // Logger begins working.
  logger_->fail_logging(false);

  // Work should complete now.
  loop.RunFor(zx::sec(10));

  ASSERT_NE(logger_->counters().find(MakeMetricOptionsFromId(kCorruptionMetricId)),
            logger_->counters().end());
  EXPECT_EQ(logger_->counters().at(MakeMetricOptionsFromId(kCorruptionMetricId)), 1);
}

}  // namespace
}  // namespace devmgr
