// 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 "config/project_configs.h"

#include <sstream>

#include "./logging.h"
#include "third_party/googletest/googletest/include/gtest/gtest.h"
#include "util/crypto_util/base64.h"

namespace cobalt {
namespace config {

namespace {

const size_t kNumReportsPerMetric = 3;
const size_t kNumMetricsPerProject = 5;
const size_t kNumCustomers = 2;

std::string NameForId(std::string prefix, uint32_t id) {
  std::ostringstream stream;
  stream << prefix << "Name" << id;
  return stream.str();
}

std::string CustomerNameForId(uint32_t id) {
  return NameForId("Customer-", id);
}
std::string ProjectNameForId(uint32_t id) { return NameForId("Project-", id); }
std::string ReportNameForId(uint32_t id) { return NameForId("Report-", id); }
std::string MetricNameForId(uint32_t id) { return NameForId("Metric-", id); }

// We create 3n projects for customer n.
size_t NumProjectsForCustomer(uint32_t customer_id) { return 3 * customer_id; }

void SetupReport(uint32_t report_id, ReportDefinition* report) {
  report->set_id(report_id);
  report->set_report_name(ReportNameForId(report_id));
}

void SetupMetric(uint32_t metric_id, MetricDefinition* metric) {
  metric->set_id(metric_id);
  metric->set_metric_name(MetricNameForId(metric_id));
  for (size_t i = 1u; i < kNumReportsPerMetric; i++) {
    SetupReport(i, metric->add_reports());
  }
}

void SetupProject(uint32_t project_id, ProjectConfig* project) {
  project->set_project_id(project_id);
  project->set_project_name(ProjectNameForId(project_id));
  for (size_t i = 1u; i <= kNumMetricsPerProject; i++) {
    SetupMetric(i, project->add_metrics());
  }
}

void SetupCustomer(uint32_t customer_id, size_t num_projects,
                   CustomerConfig* customer) {
  customer->set_customer_id(customer_id);
  customer->set_customer_name(CustomerNameForId(customer_id));
  for (auto i = 1u; i <= num_projects; i++) {
    SetupProject(i, customer->add_projects());
  }
}

std::unique_ptr<CobaltRegistry> NewTestRegistry(
    size_t num_customers,
    std::function<size_t(uint32_t)> num_projects_for_customer_fn) {
  auto cobalt_registry = std::make_unique<CobaltRegistry>();
  for (size_t i = 1u; i <= num_customers; i++) {
    SetupCustomer(i, num_projects_for_customer_fn(i),
                  cobalt_registry->add_customers());
  }
  return cobalt_registry;
}

std::unique_ptr<CobaltRegistry> NewTestRegistry() {
  return NewTestRegistry(kNumCustomers, NumProjectsForCustomer);
}

// Constructs a ProjectConfigs that wraps a CobaltRegistry with the
// specified number of customers and projects-per-customer.
std::unique_ptr<ProjectConfigs> NewProjectConfigs(
    size_t num_customers, size_t num_projects_per_customer) {
  return std::make_unique<ProjectConfigs>(
      NewTestRegistry(num_customers, [num_projects_per_customer](uint32_t) {
        return num_projects_per_customer;
      }));
}

}  // namespace

class ProjectConfigsTest : public ::testing::Test {
 protected:
  // Checks that |*customer_config| is as expected.
  bool CheckCustomer(uint32_t expected_customer_id,
                     const CustomerConfig* customer_config) {
    EXPECT_NE(nullptr, customer_config);
    if (customer_config == nullptr) {
      return false;
    }

    auto customer_id = customer_config->customer_id();
    EXPECT_EQ(expected_customer_id, customer_id);
    if (expected_customer_id != customer_id) {
      return false;
    }
    EXPECT_EQ(CustomerNameForId(expected_customer_id),
              customer_config->customer_name());
    if (CustomerNameForId(expected_customer_id) !=
        customer_config->customer_name()) {
      return false;
    }
    size_t expected_num_projects = NumProjectsForCustomer(customer_id);
    size_t num_projects = customer_config->projects_size();
    EXPECT_EQ(expected_num_projects, num_projects);
    return num_projects == expected_num_projects;
  }

  // Checks that |*project_config| is as expected.
  bool CheckProject(uint32_t expected_project_id,
                    const ProjectConfig* project_config) {
    EXPECT_NE(nullptr, project_config);
    if (project_config == nullptr) {
      return false;
    }

    EXPECT_EQ(expected_project_id, project_config->project_id());
    if (expected_project_id != project_config->project_id()) {
      return false;
    }
    EXPECT_EQ(ProjectNameForId(expected_project_id),
              project_config->project_name());
    if (ProjectNameForId(expected_project_id) !=
        project_config->project_name()) {
      return false;
    }
    size_t num_metrics = project_config->metrics_size();
    EXPECT_EQ(kNumMetricsPerProject, num_metrics);
    return num_metrics == kNumMetricsPerProject;
  }

  // Checks that |project_configs| is as expected.
  bool CheckProjectConfigs(const ProjectConfigs& project_configs) {
    for (uint32_t customer_id = 1; customer_id <= kNumCustomers;
         customer_id++) {
      std::string expected_customer_name = CustomerNameForId(customer_id);
      size_t expected_num_projects = NumProjectsForCustomer(customer_id);

      // Check getting the customer by name.
      bool success = CheckCustomer(
          customer_id,
          project_configs.GetCustomerConfig(expected_customer_name));
      EXPECT_TRUE(success);
      if (!success) {
        return false;
      }

      // Check getting the customer by ID.
      success = CheckCustomer(customer_id,
                              project_configs.GetCustomerConfig(customer_id));
      EXPECT_TRUE(success);
      if (!success) {
        return false;
      }

      for (uint32_t project_id = 1; project_id <= expected_num_projects;
           project_id++) {
        std::string project_name = ProjectNameForId(project_id);

        // Check getting the project by name.
        bool success =
            CheckProject(project_id, project_configs.GetProjectConfig(
                                         expected_customer_name, project_name));
        EXPECT_TRUE(success);
        if (!success) {
          return false;
        }

        // Check getting the project by ID.
        success = CheckProject(project_id, project_configs.GetProjectConfig(
                                               customer_id, project_id));
        EXPECT_TRUE(success);
        if (!success) {
          return false;
        }

        // Check using an invalid project name
        auto* project = project_configs.GetProjectConfig(expected_customer_name,
                                                         "InvalidName");
        EXPECT_EQ(nullptr, project);
        if (project != nullptr) {
          return false;
        }

        // Check using an invalid project_id.
        project = project_configs.GetProjectConfig(
            customer_id, expected_num_projects + project_id);
        EXPECT_EQ(nullptr, project);
        if (project != nullptr) {
          return false;
        }
      }
    }
    return true;
  }
};

// Test GetCustomerConfig by id.
TEST_F(ProjectConfigsTest, GetCustomerConfigById) {
  ProjectConfigs project_configs(NewTestRegistry());
  const CustomerConfig* customer;

  customer = project_configs.GetCustomerConfig(1);
  EXPECT_NE(customer, nullptr);
  EXPECT_EQ(customer->customer_id(), 1u);

  customer = project_configs.GetCustomerConfig(2);
  EXPECT_NE(customer, nullptr);
  EXPECT_EQ(customer->customer_id(), 2u);

  // Customer does not exist.
  customer = project_configs.GetCustomerConfig(20);
  EXPECT_EQ(customer, nullptr);
}

// Test GetProjectConfig by id.
TEST_F(ProjectConfigsTest, GetProjectConfigById) {
  ProjectConfigs project_configs(NewTestRegistry());
  const ProjectConfig* project;

  project = project_configs.GetProjectConfig(1, 1);
  EXPECT_NE(project, nullptr);
  EXPECT_EQ(project->project_id(), 1u);

  project = project_configs.GetProjectConfig(1, 2);
  EXPECT_NE(project, nullptr);
  EXPECT_EQ(project->project_id(), 2u);

  // Customer does not exist.
  project = project_configs.GetProjectConfig(20, 2);
  EXPECT_EQ(project, nullptr);

  // Customer exists, project does not exist.
  project = project_configs.GetProjectConfig(1, 20);
  EXPECT_EQ(project, nullptr);
}

// Test GetMetricDefintion.
TEST_F(ProjectConfigsTest, GetMetricDefinitionById) {
  ProjectConfigs project_configs(NewTestRegistry());
  const MetricDefinition* metric;

  metric = project_configs.GetMetricDefinition(1, 1, 1);
  EXPECT_NE(metric, nullptr);
  EXPECT_EQ(metric->id(), 1u);

  metric = project_configs.GetMetricDefinition(1, 1, 2);
  EXPECT_NE(metric, nullptr);
  EXPECT_EQ(metric->id(), 2u);

  // Customer does not exist.
  metric = project_configs.GetMetricDefinition(20, 1, 2);
  EXPECT_EQ(metric, nullptr);

  // Customer exists, project does not exist.
  metric = project_configs.GetMetricDefinition(1, 20, 2);
  EXPECT_EQ(metric, nullptr);

  // Customer exists, project exists, metric does not exist.
  metric = project_configs.GetMetricDefinition(1, 1, 20);
  EXPECT_EQ(metric, nullptr);
}

// Test GetReportDefinition.
TEST_F(ProjectConfigsTest, GetReportDefinitionById) {
  ProjectConfigs project_configs(NewTestRegistry());
  const ReportDefinition* report;

  report = project_configs.GetReportDefinition(1, 1, 1, 1);
  EXPECT_NE(report, nullptr);
  EXPECT_EQ(report->id(), 1u);

  report = project_configs.GetReportDefinition(1, 1, 1, 2);
  EXPECT_NE(report, nullptr);
  EXPECT_EQ(report->id(), 2u);

  // Customer does not exist.
  report = project_configs.GetReportDefinition(20, 1, 2, 2);
  EXPECT_EQ(report, nullptr);

  // Customer exists, project does not exist.
  report = project_configs.GetReportDefinition(1, 20, 2, 2);
  EXPECT_EQ(report, nullptr);

  // Customer exists, project exists, metric does not exist.
  report = project_configs.GetReportDefinition(1, 1, 20, 2);
  EXPECT_EQ(report, nullptr);

  // Customer exists, project exists, metric exist, report does not exist.
  report = project_configs.GetReportDefinition(1, 1, 1, 20);
  EXPECT_EQ(report, nullptr);
}

// Tests using a ProjectConfigs constructed directly from a
// CobaltRegistry
TEST_F(ProjectConfigsTest, ConstructForCobaltRegistry) {
  ProjectConfigs project_configs(NewTestRegistry());
  EXPECT_TRUE(CheckProjectConfigs(project_configs));
}

// Tests using a ProjectConfigs obtained via CreateFromCobaltRegistryBytes().
TEST_F(ProjectConfigsTest, CreateFromCobaltRegistryBytes) {
  auto cobalt_registry = NewTestRegistry();
  std::string bytes;
  cobalt_registry->SerializeToString(&bytes);
  auto project_configs = ProjectConfigs::CreateFromCobaltRegistryBytes(bytes);
  EXPECT_TRUE(CheckProjectConfigs(*project_configs));
}

// Tests using a ProjectConfigs obtained via CreateFromCobaltRegistryBase64().
TEST_F(ProjectConfigsTest, CreateFromCobaltRegistryBase64) {
  auto cobalt_registry = NewTestRegistry();
  std::string bytes;
  cobalt_registry->SerializeToString(&bytes);
  std::string cobalt_registry_base64;
  crypto::Base64Encode(bytes, &cobalt_registry_base64);
  auto project_configs =
      ProjectConfigs::CreateFromCobaltRegistryBase64(cobalt_registry_base64);
  EXPECT_TRUE(CheckProjectConfigs(*project_configs));
}

// Tests the logic that determines whether or not a ProjectConfigs is empty
// or contains a single project.
TEST_F(ProjectConfigsTest, IsSingleProject) {
  // An ProjectConfigs constructed from an empty CobaltRegistry is empty but is
  // not a single project.
  auto project_configs = NewProjectConfigs(0, 0);
  EXPECT_FALSE(project_configs->is_single_project());
  EXPECT_TRUE(project_configs->is_empty());
  EXPECT_TRUE(project_configs->TakeSingleProjectConfig() == nullptr);

  // A ProjectConfigs constructed from a CobaltRegistry with 1 customer with no
  // projects is not empty and is not a single project.
  project_configs = NewProjectConfigs(1, 0);
  EXPECT_FALSE(project_configs->is_single_project());
  EXPECT_FALSE(project_configs->is_empty());
  EXPECT_TRUE(project_configs->TakeSingleProjectConfig() == nullptr);

  // A ProjectConfigs constructed from a CobaltRegistry with 1 customer with 1
  // project is not empty and is a single project.
  project_configs = NewProjectConfigs(1, 1);
  EXPECT_TRUE(project_configs->is_single_project());
  EXPECT_FALSE(project_configs->is_empty());
  EXPECT_EQ(1u, project_configs->single_customer_id());
  EXPECT_EQ("Customer-Name1", project_configs->single_customer_name());
  EXPECT_EQ(1u, project_configs->single_project_id());
  EXPECT_EQ("Project-Name1", project_configs->single_project_name());
  // Test TakeSingleProjectConfg() in the case that there is a single project.
  EXPECT_NE(
      project_configs->GetProjectConfig("Customer-Name1", "Project-Name1"),
      nullptr);
  auto project_config = project_configs->TakeSingleProjectConfig();
  EXPECT_TRUE(project_config != nullptr);
  EXPECT_EQ("Project-Name1", project_config->project_name());
  EXPECT_FALSE(project_configs->is_single_project());
  EXPECT_TRUE(project_configs->is_empty());
  EXPECT_EQ(
      project_configs->GetProjectConfig("Customer-Name1", "Project-Name1"),
      nullptr);

  // A ProjectConfigs constructed from a CobaltRegistry with 1 customer with 2
  // projects is not empty and is not a single project.
  project_configs = NewProjectConfigs(1, 2);
  EXPECT_FALSE(project_configs->is_single_project());
  EXPECT_FALSE(project_configs->is_empty());
  EXPECT_TRUE(project_configs->TakeSingleProjectConfig() == nullptr);

  // A ProjectConfigs constructed from a CobaltRegistry with 2 customers with 1
  // project each is not empty and is not a single project.
  project_configs = NewProjectConfigs(2, 1);
  EXPECT_FALSE(project_configs->is_single_project());
  EXPECT_FALSE(project_configs->is_empty());
  EXPECT_TRUE(project_configs->TakeSingleProjectConfig() == nullptr);
}

}  // namespace config
}  // namespace cobalt
