// 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 <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 <zxtest/zxtest.h>

#include "src/lib/storage/vfs/cpp/metrics/events.h"
#include "src/storage/fshost/metrics_cobalt.h"

namespace fshost {
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, LogDataDataCorruption) {
  FsHostMetricsCobalt metrics(std::move(collector_));
  ASSERT_EQ(logger_->counters().find(MakeMetricOptionsFromId(kCorruptionMetricId)),
            logger_->counters().end());
  metrics.LogDataCorruption();
  // 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, MultipleFlushWorks) {
  FsHostMetricsCobalt metrics(std::move(collector_));
  metrics.LogDataCorruption();

  // Logger is not working
  logger_->fail_logging(true);
  metrics.Flush();

  ASSERT_EQ(logger_->counters().find(MakeMetricOptionsFromId(kCorruptionMetricId)),
            logger_->counters().end());

  // After 1 second, nothing should be logged. Sleep allows some time for the flushing
  // thread to run.
  sleep(1);
  ASSERT_EQ(logger_->counters().find(MakeMetricOptionsFromId(kCorruptionMetricId)),
            logger_->counters().end());

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

  // After calling flush, metrics should be available now.
  // Block till counters change. Timed sleep without while loop is not sufficient because
  // it make make test flake in virtual environment.
  // The test may timeout and fail if the counter is never seen.
  while (logger_->counters().find(MakeMetricOptionsFromId(kCorruptionMetricId)) ==
         logger_->counters().end()) {
    // Rather than busy waiting, sleep for a second to let other threads to run.
    sleep(1);
  }
  EXPECT_EQ(logger_->counters().at(MakeMetricOptionsFromId(kCorruptionMetricId)), 1);
}

TEST_F(MetricsTest, FlushDoesNotHangIfLoggerNotWorking) {
  FsHostMetricsCobalt metrics(std::move(collector_));
  metrics.LogDataCorruption();

  // Logger is not working
  logger_->fail_logging(true);
  metrics.Flush();

  ASSERT_EQ(logger_->counters().find(MakeMetricOptionsFromId(kCorruptionMetricId)),
            logger_->counters().end());

  // After 1 second, nothing should be logged. Sleep allows some time for the flushing
  // thread to run.
  sleep(1);
  ASSERT_EQ(logger_->counters().find(MakeMetricOptionsFromId(kCorruptionMetricId)),
            logger_->counters().end());

  // Try to flush again.
  metrics.Flush();

  // Metrics should still be unavailable now.
  ASSERT_EQ(logger_->counters().find(MakeMetricOptionsFromId(kCorruptionMetricId)),
            logger_->counters().end());
}

TEST_F(MetricsTest, DestroyImmediatelySucceeds) {
  FsHostMetricsCobalt metrics(std::move(collector_));
  metrics.LogDataCorruption();
}

TEST_F(MetricsTest, SuccessWithNullCollector) {
  FsHostMetricsCobalt metrics(nullptr);
  metrics.LogDataCorruption();
  // Sleep allows some time for thread to run.
  sleep(1);
  metrics.Flush();
}

}  // namespace
}  // namespace fshost
