// Copyright 2018 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 "src/logger/encoder.h"

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include <google/protobuf/repeated_field.h>
#include <gtest/gtest.h>

#include "src/lib/util/testing/test_with_files.h"
#include "src/local_aggregation/aggregation_utils.h"
#include "src/logger/project_context.h"
#include "src/logger/project_context_factory.h"
#include "src/logger/status.h"
#include "src/logger/test_registries/encoder_test_registry.cb.h"
#include "src/logging.h"
#include "src/pb/common.pb.h"
#include "src/pb/metadata_builder.h"
#include "src/pb/observation.pb.h"
#include "src/pb/observation_batch.pb.h"
#include "src/registry/packed_event_codes.h"
#include "src/system_data/fake_system_data.h"
#include "third_party/abseil-cpp/absl/strings/escaping.h"

namespace cobalt {

using google::protobuf::RepeatedPtrField;
using local_aggregation::MakeDayWindow;
using local_aggregation::MakeHourWindow;
using system_data::ClientSecret;
using system_data::FakeSystemData;
using system_data::SystemDataInterface;

namespace logger {

namespace {

namespace registry = testing::encoder_test_registry;

constexpr uint32_t kCustomerId = 1;
constexpr uint32_t kProjectId = 1;
constexpr uint32_t kDayIndex = 111;
constexpr uint32_t kAggregationDays = 7;
constexpr uint32_t kValue = 314159;

bool PopulateCobaltRegistry(CobaltRegistry* cobalt_registry) {
  std::string cobalt_registry_bytes;
  if (!absl::Base64Unescape(registry::kCobaltRegistryBase64, &cobalt_registry_bytes)) {
    return false;
  }
  return cobalt_registry->ParseFromString(cobalt_registry_bytes);
}

HistogramPtr NewHistogram(std::vector<uint32_t> indices, std::vector<uint32_t> counts) {
  CHECK(indices.size() == counts.size());
  HistogramPtr histogram = std::make_unique<RepeatedPtrField<HistogramBucket>>();
  for (auto i = 0u; i < indices.size(); i++) {
    auto* bucket = histogram->Add();
    bucket->set_index(indices[i]);
    bucket->set_count(counts[i]);
  }
  return histogram;
}

EventValuesPtr NewCustomEvent(std::vector<std::string> dimension_names,
                              std::vector<CustomDimensionValue> values) {
  CHECK(dimension_names.size() == values.size());
  EventValuesPtr custom_event =
      std::make_unique<google::protobuf::Map<std::string, CustomDimensionValue>>();
  for (auto i = 0u; i < values.size(); i++) {
    (*custom_event)[dimension_names[i]] = values[i];
  }
  return custom_event;
}

void CheckSystemProfile(const Encoder::Result& result, SystemProfile::OS expected_os,
                        SystemProfile::ARCH expected_arch, const std::string& expected_board_name,
                        const std::string& expected_product, const std::string& expected_channel,
                        const std::string& expected_realm) {
  EXPECT_TRUE(result.metadata->has_system_profile());
  EXPECT_EQ(expected_os, result.metadata->system_profile().os());
  EXPECT_EQ(expected_arch, result.metadata->system_profile().arch());
  EXPECT_EQ(expected_board_name, result.metadata->system_profile().board_name());
  EXPECT_EQ(expected_product, result.metadata->system_profile().product_name());
  EXPECT_EQ(expected_channel, result.metadata->system_profile().channel());
  EXPECT_EQ(expected_realm, result.metadata->system_profile().realm());
}

void CheckResult(const Encoder::Result& result, uint32_t expected_metric_id,
                 uint32_t expected_report_id, uint32_t expected_day_index) {
  EXPECT_EQ(kOK, result.status);
  EXPECT_EQ(kCustomerId, result.metadata->customer_id());
  EXPECT_EQ(kProjectId, result.metadata->project_id());
  EXPECT_EQ(expected_metric_id, result.metadata->metric_id());
  EXPECT_EQ(expected_report_id, result.metadata->report_id());
  EXPECT_EQ(result.observation->random_id().size(), 8u);
  EXPECT_EQ(expected_day_index, result.metadata->day_index());
}

}  // namespace

class EncoderTest : public util::testing::TestWithFiles {
 protected:
  void SetUp() override {
    MakeTestFolder();

    auto cobalt_registry = std::make_unique<CobaltRegistry>();
    ASSERT_TRUE(PopulateCobaltRegistry(cobalt_registry.get()));
    ProjectContextFactory project_context_factory(std::move(cobalt_registry));
    ASSERT_TRUE(project_context_factory.is_single_project());
    project_context_ = project_context_factory.TakeSingleProjectContext();
    system_data_ = std::make_unique<FakeSystemData>();
    metadata_builder_ =
        std::make_unique<MetadataBuilder>(system_data_.get(), system_data_cache_path(), fs());
    encoder_ =
        std::make_unique<Encoder>(ClientSecret::GenerateNewSecret(), metadata_builder_.get());
  }

  std::pair<const MetricDefinition*, const ReportDefinition*> GetMetricAndReport(
      const std::string& metric_name, const std::string& report_name) {
    const auto* metric = project_context_->GetMetric(metric_name);
    CHECK(metric) << "No such metric: " << metric_name;
    const ReportDefinition* report = nullptr;
    for (const auto& rept : metric->reports()) {
      if (rept.report_name() == report_name) {
        report = &rept;
        break;
      }
    }
    CHECK(report) << "No such report: " << report_name;
    return {metric, report};
  }

  std::unique_ptr<MetadataBuilder> metadata_builder_;
  std::unique_ptr<Encoder> encoder_;
  std::unique_ptr<ProjectContext> project_context_;

 private:
  std::unique_ptr<SystemDataInterface> system_data_;
};

TEST_F(EncoderTest, EncodeBasicRapporObservation) {
  const char kMetricName[] = "ErrorOccurred";
  const char kReportName[] = "ErrorCountsByType";
  const uint32_t kExpectedMetricId = 1;

  auto pair = GetMetricAndReport(kMetricName, kReportName);
  const uint32_t day_index = 111;
  {
    const uint32_t value_index = 9;
    const uint32_t num_categories = 8;
    // This should fail with kInvalidArguments because 9 > 8.
    auto result =
        encoder_->EncodeBasicRapporObservation(project_context_->RefMetric(pair.first), pair.second,
                                               day_index, value_index, num_categories);
    EXPECT_EQ(kInvalidArguments, result.status);
  }

  {
    // This should fail with kInvalidConfig because num_categories is too large.
    const uint32_t value_index = 9;
    const uint32_t num_categories = 999999;
    auto result =
        encoder_->EncodeBasicRapporObservation(project_context_->RefMetric(pair.first), pair.second,
                                               day_index, value_index, num_categories);
    EXPECT_EQ(kInvalidConfig, result.status);
  }

  {
    // If we use the wrong report, it won't have local_privacy_noise_level
    // set and we should get InvalidConfig
    const uint32_t num_categories = 128;
    const uint32_t value_index = 10;
    pair = GetMetricAndReport("ReadCacheHits", "ReadCacheHitCounts");
    auto result =
        encoder_->EncodeBasicRapporObservation(project_context_->RefMetric(pair.first), pair.second,
                                               day_index, value_index, num_categories);
    EXPECT_EQ(kInvalidConfig, result.status);

    // Finally we pass all valid parameters and the operation should succeed.
    pair = GetMetricAndReport(kMetricName, kReportName);
    result =
        encoder_->EncodeBasicRapporObservation(project_context_->RefMetric(pair.first), pair.second,
                                               day_index, value_index, num_categories);
    CheckResult(result, kExpectedMetricId, registry::kErrorOccurredErrorCountsByTypeReportId,
                day_index);
    CheckSystemProfile(result, SystemProfile::UNKNOWN_OS, SystemProfile::UNKNOWN_ARCH,
                       "Testing Board", "Testing Product", "Testing Channel", "Testing Realm");
    ASSERT_TRUE(result.observation->has_basic_rappor());
    EXPECT_FALSE(result.observation->basic_rappor().data().empty());
  }
}

TEST_F(EncoderTest, EncodeIntegerEventObservation) {
  const char kMetricName[] = "ReadCacheHits";
  const char kReportName[] = "ReadCacheHitCounts";
  const uint32_t kExpectedMetricId = 2;
  const char kComponent[] = "My Component";
  const uint32_t kEventCode = 9;
  google::protobuf::RepeatedField<uint32_t> event_codes;
  *event_codes.Add() = kEventCode;

  auto pair = GetMetricAndReport(kMetricName, kReportName);
  auto result =
      encoder_->EncodeIntegerEventObservation(project_context_->RefMetric(pair.first), pair.second,
                                              kDayIndex, event_codes, kComponent, kValue);
  CheckResult(result, kExpectedMetricId, registry::kReadCacheHitsReadCacheHitCountsReportId,
              kDayIndex);
  // In the SystemProfile only the OS should be set.
  CheckSystemProfile(result, SystemProfile::FUCHSIA, SystemProfile::UNKNOWN_ARCH, "", "", "", "");
  ASSERT_TRUE(result.observation->has_numeric_event());
  const IntegerEventObservation& obs = result.observation->numeric_event();
  EXPECT_EQ(kEventCode, obs.event_code());
  EXPECT_EQ(obs.component_name_hash().size(), 32u);
  EXPECT_EQ(kValue, obs.value());
}

TEST_F(EncoderTest, MultipleEventCodes) {
  const char kMetricName[] = "MultiEventCodeTest";
  const char kReportName[] = "MultiEventCodeCounts";
  const uint32_t kExpectedMetricId = 11;
  const char kComponent[] = "My Component";
  const uint32_t kEventCode1 = 7;
  const uint32_t kEventCode2 = 5;
  google::protobuf::RepeatedField<uint32_t> event_codes;
  *event_codes.Add() = kEventCode1;
  *event_codes.Add() = kEventCode2;

  auto pair = GetMetricAndReport(kMetricName, kReportName);
  auto result =
      encoder_->EncodeIntegerEventObservation(project_context_->RefMetric(pair.first), pair.second,
                                              kDayIndex, event_codes, kComponent, kValue);
  CheckResult(result, kExpectedMetricId, registry::kMultiEventCodeTestMultiEventCodeCountsReportId,
              kDayIndex);
  // In the SystemProfile only the OS should be set.
  CheckSystemProfile(result, SystemProfile::FUCHSIA, SystemProfile::UNKNOWN_ARCH, "", "", "", "");
  ASSERT_TRUE(result.observation->has_numeric_event());
  const IntegerEventObservation& obs = result.observation->numeric_event();
  auto codes = config::UnpackEventCodes(obs.event_code());
  EXPECT_EQ(kEventCode1, codes[0]);
  EXPECT_EQ(kEventCode2, codes[1]);
  EXPECT_EQ(obs.component_name_hash().size(), 32u);
  EXPECT_EQ(kValue, obs.value());
}

TEST_F(EncoderTest, EncodeHistogramObservation) {
  const char kMetricName[] = "FileSystemWriteTimes";
  const char kReportName[] = "FileSystemWriteTimes_Histogram";
  const uint32_t kExpectedMetricId = 6;
  const std::string kComponent;
  const uint32_t kEventCode = 9;
  google::protobuf::RepeatedField<uint32_t> event_codes;
  *event_codes.Add() = kEventCode;

  const std::vector<uint32_t> indices = {0, 1, 2};
  const std::vector<uint32_t> counts = {100, 200, 300};
  auto histogram = NewHistogram(indices, counts);
  auto pair = GetMetricAndReport(kMetricName, kReportName);
  auto result = encoder_->EncodeHistogramObservation(project_context_->RefMetric(pair.first),
                                                     pair.second, kDayIndex, event_codes,
                                                     kComponent, std::move(histogram));
  CheckResult(result, kExpectedMetricId,
              registry::kFileSystemWriteTimesFileSystemWriteTimesHistogramReportId, kDayIndex);
  // In the SystemProfile only the OS and ARCH should be set.
  CheckSystemProfile(result, SystemProfile::FUCHSIA, SystemProfile::ARM_64, "", "", "", "");
  ASSERT_TRUE(result.observation->has_histogram());
  const HistogramObservation& obs = result.observation->histogram();
  EXPECT_EQ(kEventCode, obs.event_code());
  EXPECT_TRUE(obs.component_name_hash().empty());
  EXPECT_EQ(static_cast<size_t>(obs.buckets_size()), indices.size());
  for (auto i = 0u; i < indices.size(); i++) {
    const auto& bucket = obs.buckets(i);
    EXPECT_EQ(bucket.index(), indices[i]);
    EXPECT_EQ(bucket.count(), counts[i]);
  }
}

TEST_F(EncoderTest, EncodeCustomObservation) {
  const char kMetricName[] = "ModuleInstalls";
  const char kReportName[] = "ModuleInstalls_DetailedData";
  const uint32_t kExpectedMetricId = 8;

  CustomDimensionValue module_value, number_value;
  module_value.set_string_value("gmail");
  number_value.set_int_value(3);
  std::vector<std::string> dimension_names = {"module", "number"};
  std::vector<CustomDimensionValue> values = {module_value, number_value};
  auto custom_event = NewCustomEvent(dimension_names, values);
  auto pair = GetMetricAndReport(kMetricName, kReportName);

  auto result = encoder_->EncodeCustomObservation(project_context_->RefMetric(pair.first),
                                                  pair.second, kDayIndex, std::move(custom_event));
  CheckResult(result, kExpectedMetricId,
              registry::kModuleInstallsModuleInstallsDetailedDataReportId, kDayIndex);
  // In the SystemProfile only the OS and ARCH should be set.
  CheckSystemProfile(result, SystemProfile::FUCHSIA, SystemProfile::ARM_64, "", "", "", "");
  ASSERT_TRUE(result.observation->has_custom());
  const CustomObservation& obs = result.observation->custom();
  for (auto i = 0u; i < values.size(); i++) {
    auto obs_dimension = obs.values().at(dimension_names[i]);
    EXPECT_EQ(obs_dimension.SerializeAsString(), values[i].SerializeAsString());
  }
}

TEST_F(EncoderTest, EncodeUniqueActivesObservation) {
  const char kMetricName[] = "DeviceBoots";
  const char kReportName[] = "DeviceBoots_UniqueDevices";
  const uint32_t kExpectedMetricId = 9;
  const uint32_t kEventCode = 0;
  const int kAggregationHours = 1;
  auto pair = GetMetricAndReport(kMetricName, kReportName);

  // Encode a valid UniqueActivesObservation of activity for a 7-day window.
  auto result_active = encoder_->EncodeUniqueActivesObservation(
      project_context_->RefMetric(pair.first), pair.second, kDayIndex, kEventCode, true,
      MakeDayWindow(kAggregationDays));
  CheckResult(result_active, kExpectedMetricId,
              registry::kDeviceBootsDeviceBootsUniqueDevicesReportId, kDayIndex);
  // In the SystemProfile only the OS and ARCH should be set.
  CheckSystemProfile(result_active, SystemProfile::FUCHSIA, SystemProfile::ARM_64, "", "", "", "");
  ASSERT_TRUE(result_active.observation->has_unique_actives());
  auto active_obs = result_active.observation->unique_actives();
  ASSERT_EQ(OnDeviceAggregationWindow::kDays, active_obs.aggregation_window().units_case());
  EXPECT_EQ(kAggregationDays, active_obs.aggregation_window().days());
  EXPECT_EQ(kEventCode, active_obs.event_code());
  ASSERT_TRUE(active_obs.has_basic_rappor_obs());
  EXPECT_EQ(1u, active_obs.basic_rappor_obs().data().size());

  // Encode a valid UniqueActivesObservation of inactivity for a 1-hour window.
  auto result_inactive = encoder_->EncodeUniqueActivesObservation(
      project_context_->RefMetric(pair.first), pair.second, kDayIndex, kEventCode, false,
      MakeHourWindow(kAggregationHours));
  CheckResult(result_inactive, kExpectedMetricId,
              registry::kDeviceBootsDeviceBootsUniqueDevicesReportId, kDayIndex);
  // In the SystemProfile only the OS and ARCH should be set.
  CheckSystemProfile(result_inactive, SystemProfile::FUCHSIA, SystemProfile::ARM_64, "", "", "",
                     "");
  ASSERT_TRUE(result_inactive.observation->has_unique_actives());
  auto inactive_obs = result_inactive.observation->unique_actives();
  ASSERT_EQ(OnDeviceAggregationWindow::kHours, inactive_obs.aggregation_window().units_case());
  EXPECT_EQ(kAggregationHours, inactive_obs.aggregation_window().hours());
  EXPECT_EQ(kEventCode, inactive_obs.event_code());
  ASSERT_TRUE(inactive_obs.has_basic_rappor_obs());
  EXPECT_EQ(1u, inactive_obs.basic_rappor_obs().data().size());
}

TEST_F(EncoderTest, EncodePerDeviceNumericObservation) {
  const char kMetricName[] = "ConnectionFailures";
  const char kReportName[] = "ConnectionFailures_PerDeviceCount";
  const uint32_t kExpectedMetricId = 10;
  const char kComponent[] = "Some Component";
  const uint32_t kEventCode = 0;
  const int64_t kCount = 1728;
  auto pair = GetMetricAndReport(kMetricName, kReportName);

  google::protobuf::RepeatedField<uint32_t> event_codes;
  *event_codes.Add() = kEventCode;

  auto result = encoder_->EncodePerDeviceNumericObservation(
      project_context_->RefMetric(pair.first), pair.second, kDayIndex, kComponent, event_codes,
      kCount, MakeDayWindow(kAggregationDays));
  CheckResult(result, kExpectedMetricId,
              registry::kConnectionFailuresConnectionFailuresPerDeviceCountReportId, kDayIndex);
  // In the SystemProfile only the OS and ARCH should be set.
  CheckSystemProfile(result, SystemProfile::FUCHSIA, SystemProfile::ARM_64, "", "", "", "");
  ASSERT_TRUE(result.observation->has_per_device_numeric());
  const auto& per_device_numeric_obs = result.observation->per_device_numeric();
  ASSERT_EQ(OnDeviceAggregationWindow::kDays,
            per_device_numeric_obs.aggregation_window().units_case());
  EXPECT_EQ(kAggregationDays, per_device_numeric_obs.aggregation_window().days());
  ASSERT_TRUE(per_device_numeric_obs.has_integer_event_obs());
  const auto& integer_obs = per_device_numeric_obs.integer_event_obs();
  EXPECT_EQ(kEventCode, integer_obs.event_code());
  EXPECT_EQ(32u, integer_obs.component_name_hash().size());
  EXPECT_EQ(kCount, integer_obs.value());
}

TEST_F(EncoderTest, EncodePerDeviceNumericHistogramObservation) {
  const char kMetricName[] = "ConnectionFailures";
  const char kReportName[] = "ConnectionFailures_PerDeviceHistogram";
  const uint32_t kExpectedMetricId = 10;
  const char kComponent[] = "Some Component";
  const uint32_t kEventCode = 0;
  const int64_t kCount = 41;
  const int64_t kExpectedBucket = 5;
  auto pair = GetMetricAndReport(kMetricName, kReportName);

  google::protobuf::RepeatedField<uint32_t> event_codes;
  *event_codes.Add() = kEventCode;

  auto result = encoder_->EncodePerDeviceHistogramObservation(
      project_context_->RefMetric(pair.first), pair.second, kDayIndex, kComponent, event_codes,
      kCount, MakeDayWindow(kAggregationDays));
  CheckResult(result, kExpectedMetricId,
              registry::kConnectionFailuresConnectionFailuresPerDeviceHistogramReportId, kDayIndex);
  // In the SystemProfile only the OS and ARCH should be set.
  CheckSystemProfile(result, SystemProfile::FUCHSIA, SystemProfile::ARM_64, "", "", "", "");
  ASSERT_TRUE(result.observation->has_per_device_histogram());
  auto per_device_histogram_obs = result.observation->per_device_histogram();
  ASSERT_EQ(OnDeviceAggregationWindow::kDays,
            per_device_histogram_obs.aggregation_window().units_case());
  EXPECT_EQ(kAggregationDays, per_device_histogram_obs.aggregation_window().days());
  ASSERT_TRUE(result.observation->per_device_histogram().has_histogram());
  auto histogram = result.observation->per_device_histogram().histogram();
  EXPECT_EQ(kEventCode, histogram.event_code());
  EXPECT_EQ(32u, histogram.component_name_hash().size());
  EXPECT_EQ(1, histogram.buckets_size());
  EXPECT_EQ(kExpectedBucket, histogram.buckets(0).index());
  EXPECT_EQ(1, histogram.buckets(0).count());
}

TEST_F(EncoderTest, EncodeReportParticipationObservation) {
  const char kMetricName[] = "ConnectionFailures";
  const char kReportName[] = "ConnectionFailures_PerDeviceCount";
  const uint32_t kExpectedMetricId = 10;
  auto pair = GetMetricAndReport(kMetricName, kReportName);

  auto result = encoder_->EncodeReportParticipationObservation(
      project_context_->RefMetric(pair.first), pair.second, kDayIndex);
  CheckResult(result, kExpectedMetricId,
              registry::kConnectionFailuresConnectionFailuresPerDeviceCountReportId, kDayIndex);
  // In the SystemProfile only the OS and ARCH should be set.
  CheckSystemProfile(result, SystemProfile::FUCHSIA, SystemProfile::ARM_64, "", "", "", "");
  ASSERT_TRUE(result.observation->has_report_participation());
}

}  // namespace logger
}  // namespace cobalt
