/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "reporter.h"

#include "gtest/gtest.h"

#include "common_runtime_test.h"
#include "base/metrics/metrics.h"

#pragma clang diagnostic push
#pragma clang diagnostic error "-Wconversion"

namespace art HIDDEN {
namespace metrics {

// Helper class to verify the metrics reporter.
// The functionality is identical to the MetricsReporter with the exception of
// the metrics source. Instead of taking its metrics from the current Runtime,
// this class will keep its own copy so that it does not get interference from
// other runtime setup logic.
class MockMetricsReporter : public MetricsReporter {
 protected:
  MockMetricsReporter(const ReportingConfig& config, Runtime* runtime)
      : MetricsReporter(config, runtime), art_metrics_(std::make_unique<ArtMetrics>()) {}

  ArtMetrics* GetMetrics() override { return art_metrics_.get(); }

  std::unique_ptr<ArtMetrics> art_metrics_;

  friend class MetricsReporterTest;
};

// A test backend which keeps track of all metrics reporting.
class TestBackend : public MetricsBackend {
 public:
  struct Report {
    uint64_t timestamp_millis;
    SafeMap<DatumId, uint64_t> data;
  };

  void BeginOrUpdateSession(const SessionData& session_data) override {
    session_data_ = session_data;
  }

  void BeginReport(uint64_t timestamp_millis) override {
    current_report_.reset(new Report());
    current_report_->timestamp_millis = timestamp_millis;
  }

  void ReportCounter(DatumId counter_type, uint64_t value) override {
    current_report_->data.Put(counter_type, value);
  }

  void ReportHistogram([[maybe_unused]] DatumId histogram_type,
                       [[maybe_unused]] int64_t low_value,
                       [[maybe_unused]] int64_t high_value,
                       [[maybe_unused]] const std::vector<uint32_t>& buckets) override {
    // TODO: nothing yet. We should implement and test histograms as well.
  }

  void EndReport() override {
    reports_.push_back(*current_report_);
    current_report_ = nullptr;
  }

  const std::vector<Report>& GetReports() {
    return reports_;
  }

  const SessionData& GetSessionData() {
    return session_data_;
  }

 private:
  SessionData session_data_;
  std::vector<Report> reports_;
  std::unique_ptr<Report> current_report_;
};

// The actual metrics test class
class MetricsReporterTest : public CommonRuntimeTest {
 protected:
  void SetUp() override {
    // Do the normal setup.
    CommonRuntimeTest::SetUp();

    // We need to start the runtime in order to run threads.
    Thread::Current()->TransitionFromSuspendedToRunnable();
    bool started = runtime_->Start();
    CHECK(started);
  }

  // Configures the metric reporting.
  void SetupReporter(const char* period_spec,
                     uint32_t session_id = 1,
                     uint32_t reporting_mods = 100) {
    ReportingConfig config;
    if (period_spec != nullptr) {
      std::string error;
      config.reporting_mods = reporting_mods;
      config.period_spec = ReportingPeriodSpec::Parse(period_spec, &error);
      ASSERT_TRUE(config.period_spec.has_value());
    }

    reporter_.reset(new MockMetricsReporter(std::move(config), Runtime::Current()));
    backend_ = new TestBackend();
    reporter_->backends_.emplace_back(backend_);

    session_data_ = metrics::SessionData::CreateDefault();
    session_data_.session_id = session_id;
  }

  void TearDown() override {
    reporter_ = nullptr;
    backend_ = nullptr;
  }

  bool ShouldReportAtStartup() {
    return reporter_->ShouldReportAtStartup();
  }

  bool ShouldContinueReporting() {
    return reporter_->ShouldContinueReporting();
  }

  uint32_t GetNextPeriodSeconds() {
    return reporter_->GetNextPeriodSeconds();
  }

  void ReportMetrics() {
    reporter_->ReportMetrics();
  }

  void NotifyStartupCompleted() {
    reporter_->NotifyStartupCompleted();
  }

  // Starts the reporting thread and adds some metrics if necessary.
  bool MaybeStartBackgroundThread(bool add_metrics) {
    // TODO: set session_data.compilation_reason and session_data.compiler_filter
    bool result = reporter_->MaybeStartBackgroundThread(session_data_);
    if (add_metrics) {
      reporter_->art_metrics_->JitMethodCompileCount()->Add(1);
      reporter_->art_metrics_->ClassVerificationCount()->Add(2);
    }
    return result;
  }

  // Right now we either:
  //   1) don't add metrics (with_metrics = false)
  //   2) or always add the same metrics (see MaybeStartBackgroundThread)
  // So we can write a global verify method.
  void VerifyReports(
        uint32_t size,
        bool with_metrics,
        CompilerFilterReporting filter = CompilerFilterReporting::kUnknown,
        CompilationReason reason = CompilationReason::kUnknown) {
    // TODO: we should iterate through all the other metrics to make sure they were not
    // reported. However, we don't have an easy to use iteration mechanism over metrics yet.
    // We should add one
    ASSERT_EQ(backend_->GetReports().size(), size);
    for (const TestBackend::Report& report : backend_->GetReports()) {
      ASSERT_EQ(report.data.Get(DatumId::kClassVerificationCount), with_metrics ? 2u : 0u);
      ASSERT_EQ(report.data.Get(DatumId::kJitMethodCompileCount), with_metrics ? 1u : 0u);
    }

    ASSERT_EQ(backend_->GetSessionData().compiler_filter, filter);
    ASSERT_EQ(backend_->GetSessionData().compilation_reason, reason);
  }

  // Sleeps until the backend received the give number of reports.
  void WaitForReport(uint32_t report_count, uint32_t sleep_period_ms) {
    while (true) {
      if (backend_->GetReports().size() == report_count) {
        return;
      }
      usleep(sleep_period_ms * 1000);
    }
  }

  void NotifyAppInfoUpdated(AppInfo* app_info) {
    reporter_->NotifyAppInfoUpdated(app_info);
  }

 private:
  std::unique_ptr<MockMetricsReporter> reporter_;
  TestBackend* backend_;
  metrics::SessionData session_data_;
};

// Verifies startup reporting.
TEST_F(MetricsReporterTest, StartupOnly) {
  SetupReporter("S");

  // Verify startup conditions
  ASSERT_TRUE(ShouldReportAtStartup());
  ASSERT_FALSE(ShouldContinueReporting());

  // Start the thread and notify the startup. This will advance the state.
  MaybeStartBackgroundThread(/*add_metrics=*/ true);

  NotifyStartupCompleted();
  WaitForReport(/*report_count=*/ 1, /*sleep_period_ms=*/ 50);
  VerifyReports(/*size=*/ 1, /*with_metrics*/ true);

  // We should still not report continuously.
  ASSERT_FALSE(ShouldContinueReporting());
}

// LARGE TEST: This test takes 1s to run.
// Verifies startup reporting, followed by a fixed, one time only reporting.
TEST_F(MetricsReporterTest, StartupAndPeriod) {
  SetupReporter("S,1");

  // Verify startup conditions
  ASSERT_TRUE(ShouldReportAtStartup());
  ASSERT_FALSE(ShouldContinueReporting());

  // Start the thread and notify the startup. This will advance the state.
  MaybeStartBackgroundThread(/*add_metrics=*/ true);
  NotifyStartupCompleted();

  // We're waiting for 2 reports: the startup one, and the 1s one.
  WaitForReport(/*report_count=*/ 2, /*sleep_period_ms=*/ 500);
  VerifyReports(/*size=*/ 2, /*with_metrics*/ true);

  // We should no longer report continuously.
  ASSERT_FALSE(ShouldContinueReporting());
}

// LARGE TEST: This test take 2s to run.
// Verifies startup reporting, followed by continuous reporting.
TEST_F(MetricsReporterTest, StartupAndPeriodContinuous) {
  SetupReporter("S,1,*");

  // Verify startup conditions
  ASSERT_TRUE(ShouldReportAtStartup());
  ASSERT_FALSE(ShouldContinueReporting());

  // Start the thread and notify the startup. This will advance the state.
  MaybeStartBackgroundThread(/*add_metrics=*/ true);
  NotifyStartupCompleted();

  // We're waiting for 3 reports: the startup one, and the 1s one.
  WaitForReport(/*report_count=*/ 3, /*sleep_period_ms=*/ 500);
  VerifyReports(/*size=*/ 3, /*with_metrics*/ true);

  // We should keep reporting continuously.
  ASSERT_TRUE(ShouldContinueReporting());
}

// LARGE TEST: This test takes 1s to run.
// Verifies a fixed, one time only reporting.
TEST_F(MetricsReporterTest, OneTime) {
  SetupReporter("1");

  // Verify startup conditions
  ASSERT_FALSE(ShouldReportAtStartup());
  ASSERT_TRUE(ShouldContinueReporting());

  // Start the thread and notify the startup. This will advance the state.
  MaybeStartBackgroundThread(/*add_metrics=*/ true);

  // We're waiting for 1 report
  WaitForReport(/*report_count=*/ 1, /*sleep_period_ms=*/ 500);
  VerifyReports(/*size=*/ 1, /*with_metrics*/ true);

  // We should no longer report continuously.
  ASSERT_FALSE(ShouldContinueReporting());
}

// LARGE TEST: This test takes 5s to run.
// Verifies a sequence of reporting, at different interval of times.
TEST_F(MetricsReporterTest, PeriodContinuous) {
  SetupReporter("1,2,*");

  // Verify startup conditions
  ASSERT_FALSE(ShouldReportAtStartup());
  ASSERT_TRUE(ShouldContinueReporting());

  // Start the thread and notify the startup. This will advance the state.
  MaybeStartBackgroundThread(/*add_metrics=*/ true);
  NotifyStartupCompleted();

  // We're waiting for 2 reports: the startup one, and the 1s one.
  WaitForReport(/*report_count=*/ 3, /*sleep_period_ms=*/ 500);
  VerifyReports(/*size=*/ 3, /*with_metrics*/ true);

  // We should keep reporting continuously.
  ASSERT_TRUE(ShouldContinueReporting());
}

// LARGE TEST: This test takes 1s to run.
// Verifies reporting when no metrics where recorded.
TEST_F(MetricsReporterTest, NoMetrics) {
  SetupReporter("1");

  // Verify startup conditions
  ASSERT_FALSE(ShouldReportAtStartup());
  ASSERT_TRUE(ShouldContinueReporting());

  // Start the thread and notify the startup. This will advance the state.
  MaybeStartBackgroundThread(/*add_metrics=*/ false);

  // We're waiting for 1 report
  WaitForReport(/*report_count=*/ 1, /*sleep_period_ms=*/ 500);
  VerifyReports(/*size=*/ 1, /*with_metrics*/ false);

  // We should no longer report continuously.
  ASSERT_FALSE(ShouldContinueReporting());
}

// Verify we don't start reporting if the sample rate is set to 0.
TEST_F(MetricsReporterTest, SampleRateDisable) {
  SetupReporter("1,*", /*session_id=*/ 1, /*reporting_mods=*/ 0);

  // The background thread should not start.
  ASSERT_FALSE(MaybeStartBackgroundThread(/*add_metrics=*/ false));

  ASSERT_FALSE(ShouldReportAtStartup());
  ASSERT_FALSE(ShouldContinueReporting());
}

// Verify we don't start reporting if the sample rate is low and the session does
// not meet conditions.
TEST_F(MetricsReporterTest, SampleRateDisable24) {
  SetupReporter("1,*", /*session_id=*/ 125, /*reporting_mods=*/ 24);

  // The background thread should not start.
  ASSERT_FALSE(MaybeStartBackgroundThread(/*add_metrics=*/ false));

  ASSERT_FALSE(ShouldReportAtStartup());
  ASSERT_FALSE(ShouldContinueReporting());
}

// Verify we start reporting if the sample rate and the session meet
// reporting conditions
TEST_F(MetricsReporterTest, SampleRateEnable50) {
  SetupReporter("1,*", /*session_id=*/ 125, /*reporting_mods=*/ 50);

  // The background thread should start.
  ASSERT_TRUE(MaybeStartBackgroundThread(/*add_metrics=*/ false));

  ASSERT_FALSE(ShouldReportAtStartup());
  ASSERT_TRUE(ShouldContinueReporting());
}

// Verify we start reporting if the sample rate and the session meet
// reporting conditions
TEST_F(MetricsReporterTest, SampleRateEnableAll) {
  SetupReporter("1,*", /*session_id=*/ 1099, /*reporting_mods=*/ 100);

  // The background thread should start.
  ASSERT_TRUE(MaybeStartBackgroundThread(/*add_metrics=*/ false));

  ASSERT_FALSE(ShouldReportAtStartup());
  ASSERT_TRUE(ShouldContinueReporting());
}

TEST_F(MetricsReporterTest, CompilerFilter) {
  SetupReporter("1", /*session_id=*/ 1099, /*reporting_mods=*/ 100);
  ASSERT_TRUE(MaybeStartBackgroundThread(/*add_metrics=*/ true));

  AppInfo app_info;
  app_info.RegisterOdexStatus(
      "code_location",
      "verify",
      "install",
      "odex_status");
  app_info.RegisterAppInfo(
      "package_name",
      std::vector<std::string>({"code_location"}),
      "",
      "",
      AppInfo::CodeType::kPrimaryApk);
  NotifyAppInfoUpdated(&app_info);

  WaitForReport(/*report_count=*/ 1, /*sleep_period_ms=*/ 500);
  VerifyReports(
      /*size=*/ 1,
      /*with_metrics*/ true,
      CompilerFilterReporting::kVerify,
      CompilationReason::kInstall);
}

// Test class for period spec parsing
class ReportingPeriodSpecTest : public testing::Test {
 public:
  void VerifyFalse(const std::string& spec_str) {
    Verify(spec_str, false, false, false, {});
  }

  void VerifyTrue(
      const std::string& spec_str,
      bool startup_first,
      bool continuous,
      const std::vector<uint32_t>& periods) {
    Verify(spec_str, true, startup_first, continuous, periods);
  }

  void Verify(
      const std::string& spec_str,
      bool valid,
      bool startup_first,
      bool continuous,
      const std::vector<uint32_t>& periods) {
    std::string error_msg;
    std::optional<ReportingPeriodSpec> spec = ReportingPeriodSpec::Parse(spec_str, &error_msg);

    ASSERT_EQ(valid, spec.has_value()) << spec_str;
    if (valid) {
        ASSERT_EQ(spec->spec, spec_str) << spec_str;
        ASSERT_EQ(spec->report_startup_first, startup_first) << spec_str;
        ASSERT_EQ(spec->continuous_reporting, continuous) << spec_str;
        ASSERT_EQ(spec->periods_seconds, periods) << spec_str;
    }
  }
};

TEST_F(ReportingPeriodSpecTest, ParseTestsInvalid) {
  VerifyFalse("");
  VerifyFalse("*");
  VerifyFalse("S,*");
  VerifyFalse("foo");
  VerifyFalse("-1");
  VerifyFalse("1,S");
  VerifyFalse("*,1");
  VerifyFalse("1,2,3,-1,3");
  VerifyFalse("1,*,2");
  VerifyFalse("1,S,2");
}

TEST_F(ReportingPeriodSpecTest, ParseTestsValid) {
  VerifyTrue("S", true, false, {});
  VerifyTrue("S,1", true, false, {1});
  VerifyTrue("S,1,2,3,4", true, false, {1, 2, 3, 4});
  VerifyTrue("S,1,*", true, true, {1});
  VerifyTrue("S,1,2,3,4,*", true, true, {1, 2, 3, 4});

  VerifyTrue("1", false, false, {1});
  VerifyTrue("1,2,3,4", false, false, {1, 2, 3, 4});
  VerifyTrue("1,*", false, true, {1});
  VerifyTrue("1,2,3,4,*", false, true, {1, 2, 3, 4});
}

}  // namespace metrics
}  // namespace art

#pragma clang diagnostic pop  // -Wconversion
