[Registry] Cleans up ProjectConfigs and adds some functionality.
CB-220
This is a follow-on to
https://fuchsia-review.googlesource.com/c/cobalt/+/251890
We clean up ProjectConfigs in a way that is similar to what we did
for ClientConfig. But what we needed to do here was simpler.
- Add comments
- Change terminology from "config" to "registry"
- Add the methods is_empty() and is_single_project().
Change-Id: I1f422ca930b3b78750ebcac7a119618a75fe61ef
diff --git a/config/client_config.h b/config/client_config.h
index 93bf1e2..0e31c93 100644
--- a/config/client_config.h
+++ b/config/client_config.h
@@ -47,7 +47,6 @@
// such a message, and then extracting the Metrics and EncodingConfigs from
// that.
//
- //
// Returns nullptr to indicate failure.
static std::unique_ptr<ClientConfig> CreateFromCobaltRegistryBase64(
const std::string& cobalt_registry_base64);
@@ -57,7 +56,6 @@
// contain the bytes of the binary serialization of such a message, and then
// extracting the Metrics and EncodingConfigs from that.
//
- //
// Returns nullptr to indicate failure.
static std::unique_ptr<ClientConfig> CreateFromCobaltRegistryBytes(
const std::string& cobalt_registry_bytes);
diff --git a/config/project_configs.cc b/config/project_configs.cc
index a765518..15bac1f 100644
--- a/config/project_configs.cc
+++ b/config/project_configs.cc
@@ -12,32 +12,45 @@
std::unique_ptr<ProjectConfigs> ProjectConfigs::CreateFromCobaltRegistryBase64(
const std::string& cobalt_registry_base64) {
- std::string cobalt_config_bytes;
- if (!crypto::Base64Decode(cobalt_registry_base64, &cobalt_config_bytes)) {
+ std::string cobalt_registry_bytes;
+ if (!crypto::Base64Decode(cobalt_registry_base64, &cobalt_registry_bytes)) {
LOG(ERROR) << "Unable to parse the provided string as base-64";
return nullptr;
}
- return CreateFromCobaltRegistryBytes(cobalt_config_bytes);
+ return CreateFromCobaltRegistryBytes(cobalt_registry_bytes);
}
std::unique_ptr<ProjectConfigs> ProjectConfigs::CreateFromCobaltRegistryBytes(
- const std::string& cobalt_config_bytes) {
- auto cobalt_config = std::make_unique<CobaltRegistry>();
- if (!cobalt_config->ParseFromString(cobalt_config_bytes)) {
+ const std::string& cobalt_registry_bytes) {
+ auto cobalt_registry = std::make_unique<CobaltRegistry>();
+ if (!cobalt_registry->ParseFromString(cobalt_registry_bytes)) {
LOG(ERROR) << "Unable to parse a CobaltRegistry from the provided bytes.";
return nullptr;
}
- return CreateFromCobaltRegistryProto(std::move(cobalt_config));
+ return CreateFromCobaltRegistryProto(std::move(cobalt_registry));
}
std::unique_ptr<ProjectConfigs> ProjectConfigs::CreateFromCobaltRegistryProto(
- std::unique_ptr<CobaltRegistry> cobalt_config) {
- return std::make_unique<ProjectConfigs>(std::move(cobalt_config));
+ std::unique_ptr<CobaltRegistry> cobalt_registry) {
+ return std::make_unique<ProjectConfigs>(std::move(cobalt_registry));
}
-ProjectConfigs::ProjectConfigs(std::unique_ptr<CobaltRegistry> cobalt_config)
- : cobalt_config_(std::move(cobalt_config)) {
- for (const auto& customer : cobalt_config_->customers()) {
+ProjectConfigs::ProjectConfigs(std::unique_ptr<CobaltRegistry> cobalt_registry)
+ : cobalt_registry_(std::move(cobalt_registry)) {
+ is_empty_ = cobalt_registry_->customers_size() == 0;
+ is_single_project_ = false;
+ if (cobalt_registry_->customers_size() == 1) {
+ auto customer = cobalt_registry_->customers(0);
+ if (customer.projects_size() == 1) {
+ auto project = customer.projects(0);
+ is_single_project_ = true;
+ single_customer_id_ = customer.customer_id();
+ single_customer_name_ = customer.customer_name();
+ single_project_id_ = project.project_id();
+ single_project_name_ = project.project_name();
+ }
+ }
+ for (const auto& customer : cobalt_registry_->customers()) {
customers_by_id_[customer.customer_id()] = &customer;
customers_by_name_[customer.customer_name()] = &customer;
for (const auto& project : customer.projects()) {
diff --git a/config/project_configs.h b/config/project_configs.h
index 752b549..7449abe 100644
--- a/config/project_configs.h
+++ b/config/project_configs.h
@@ -16,29 +16,53 @@
namespace cobalt {
namespace config {
-// ProjectConfigs wraps a CobaltRegistry and offers convenient and efficient
-// methods for looking up a project.
+// ProjectConfigs provides a convenient interface over a |CobaltRegistry|
+// that is intended to be used on Cobalt's client-side.
+//
+// A CobaltRegistry can be in one of three states:
+//
+// (1) It can contain data for a single Cobalt 0.1 project.
+// (2) It can contain data for a single Cobalt 1.0 project.
+// (3) It can contain data for multiple Cobalt projects. In this case it
+// may contain data for some Cobalt 0.1 projects and some Cobalt 1.0
+// projects.
+//
+// This class is part of Cobalt 1.0. and as such it ignores the Cobalt 0.1
+// data in a |CobaltRegistry| and gives access only to the Cobalt 1.0 data.
+// So an instance of this class can be in one of three states corresponding
+// to the three states above:
+//
+// (1) It can be empty
+// (2) It can contain data for a single Cobalt 1.0 project.
+// (3) It can contain data for multiple Cobalt 1.0 projects.
+//
+// See the class |ClientConfig| for the Cobalt 0.1 analogue of this class.
class ProjectConfigs {
public:
// Constructs and returns an instance of ProjectConfigs by first parsing
// a CobaltRegistry proto message from |cobalt_registry_base64|, which should
// contain the Base64 encoding of the bytes of the binary serialization of
// such a message.
+ //
+ // Returns nullptr to indicate failure.
static std::unique_ptr<ProjectConfigs> CreateFromCobaltRegistryBase64(
const std::string& cobalt_registry_base64);
// Constructs and returns an instance of ProjectConfigs by first parsing
- // a CobaltRegistry proto message from |cobalt_config_bytes|, which should
+ // a CobaltRegistry proto message from |cobalt_registry_bytes|, which should
// contain the bytes of the binary serialization of such a message.
+ //
+ // Returns nullptr to indicate failure.
static std::unique_ptr<ProjectConfigs> CreateFromCobaltRegistryBytes(
- const std::string& cobalt_config_bytes);
+ const std::string& cobalt_registry_bytes);
- // Constructs and returns and instance of ProjectConfigs from |cobalt_config|.
+ // Constructs and returns and instance of ProjectConfigs that contains the
+ // data from |cobalt_registry|.
static std::unique_ptr<ProjectConfigs> CreateFromCobaltRegistryProto(
- std::unique_ptr<CobaltRegistry> cobalt_config);
+ std::unique_ptr<CobaltRegistry> cobalt_registry);
- // Constructs a ProjectConfigs that wraps the given |cobalt_config|.
- explicit ProjectConfigs(std::unique_ptr<CobaltRegistry> cobalt_config);
+ // Constructs a ProjectConfigs that contains the data from |cobalt_registry|.
+ explicit ProjectConfigs(std::unique_ptr<CobaltRegistry> cobalt_registry);
// Returns the CustomerConfig for the customer with the given name, or
// nullptr if there is no such customer.
@@ -73,8 +97,32 @@
uint32_t metric_id,
uint32_t report_id) const;
+ // Returns whether or not this instance of ProjectConfigs contains data for
+ // exactly one project.
+ bool is_single_project() { return is_single_project_; }
+
+ // Returns whether or not this instance of ProjectConfigs contains no
+ // project data.
+ bool is_empty() { return is_empty_; }
+
+ // If is_single_project() is true then this returns the customer ID of
+ // the single project. Otherwise the return value is undefined.
+ uint32_t single_customer_id() { return single_customer_id_; }
+
+ // If is_single_project() is true then this returns the customer name of
+ // the single project. Otherwise the return value is undefined.
+ std::string single_customer_name() { return single_customer_name_; }
+
+ // If is_single_project() is true then this returns the project ID of
+ // the single project. Otherwise the return value is undefined.
+ uint32_t single_project_id() { return single_project_id_; }
+
+ // If is_single_project() is true then this returns the project name of
+ // the single project. Otherwise the return value is undefined.
+ std::string single_project_name() { return single_project_name_; }
+
private:
- std::unique_ptr<CobaltRegistry> cobalt_config_;
+ std::unique_ptr<CobaltRegistry> cobalt_registry_;
std::map<std::string, const CustomerConfig*> customers_by_name_;
@@ -92,6 +140,13 @@
std::map<std::tuple<uint32_t, uint32_t, uint32_t, uint32_t>,
const ReportDefinition*>
reports_by_id_;
+
+ bool is_single_project_;
+ bool is_empty_;
+ uint32_t single_customer_id_ = 0;
+ std::string single_customer_name_;
+ uint32_t single_project_id_ = 0;
+ std::string single_project_name_;
};
} // namespace config
diff --git a/config/project_configs_test.cc b/config/project_configs_test.cc
index 31fe192..414355f 100644
--- a/config/project_configs_test.cc
+++ b/config/project_configs_test.cc
@@ -19,23 +19,30 @@
const size_t kNumMetricsPerProject = 5;
const size_t kNumCustomers = 2;
-std::string NameForId(uint32_t id) {
+std::string NameForId(std::string prefix, uint32_t id) {
std::ostringstream stream;
- stream << "Name" << id;
+ 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(NameForId(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(NameForId(metric_id));
+ metric->set_metric_name(MetricNameForId(metric_id));
for (size_t i = 1u; i < kNumReportsPerMetric; i++) {
SetupReport(i, metric->add_reports());
}
@@ -43,7 +50,7 @@
void SetupProject(uint32_t project_id, ProjectConfig* project) {
project->set_project_id(project_id);
- project->set_project_name(NameForId(project_id));
+ project->set_project_name(ProjectNameForId(project_id));
for (size_t i = 1u; i <= kNumMetricsPerProject; i++) {
SetupMetric(i, project->add_metrics());
}
@@ -52,18 +59,35 @@
void SetupCustomer(uint32_t customer_id, size_t num_projects,
CustomerConfig* customer) {
customer->set_customer_id(customer_id);
- customer->set_customer_name(NameForId(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> NewTestConfig() {
- auto cobalt_config = std::make_unique<CobaltRegistry>();
- for (size_t i = 1u; i <= kNumCustomers; i++) {
- SetupCustomer(i, NumProjectsForCustomer(i), cobalt_config->add_customers());
+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_config;
+ 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
@@ -83,9 +107,10 @@
if (expected_customer_id != customer_id) {
return false;
}
- EXPECT_EQ(NameForId(expected_customer_id),
+ EXPECT_EQ(CustomerNameForId(expected_customer_id),
customer_config->customer_name());
- if (NameForId(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);
@@ -106,8 +131,10 @@
if (expected_project_id != project_config->project_id()) {
return false;
}
- EXPECT_EQ(NameForId(expected_project_id), project_config->project_name());
- if (NameForId(expected_project_id) != project_config->project_name()) {
+ 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();
@@ -119,7 +146,7 @@
bool CheckProjectConfigs(const ProjectConfigs& project_configs) {
for (uint32_t customer_id = 1; customer_id <= kNumCustomers;
customer_id++) {
- std::string expected_customer_name = NameForId(customer_id);
+ std::string expected_customer_name = CustomerNameForId(customer_id);
size_t expected_num_projects = NumProjectsForCustomer(customer_id);
// Check getting the customer by name.
@@ -141,7 +168,7 @@
for (uint32_t project_id = 1; project_id <= expected_num_projects;
project_id++) {
- std::string project_name = NameForId(project_id);
+ std::string project_name = ProjectNameForId(project_id);
// Check getting the project by name.
bool success =
@@ -183,7 +210,7 @@
// Test GetCustomerConfig by id.
TEST_F(ProjectConfigsTest, GetCustomerConfigById) {
- ProjectConfigs project_configs(NewTestConfig());
+ ProjectConfigs project_configs(NewTestRegistry());
const CustomerConfig* customer;
customer = project_configs.GetCustomerConfig(1);
@@ -201,7 +228,7 @@
// Test GetProjectConfig by id.
TEST_F(ProjectConfigsTest, GetProjectConfigById) {
- ProjectConfigs project_configs(NewTestConfig());
+ ProjectConfigs project_configs(NewTestRegistry());
const ProjectConfig* project;
project = project_configs.GetProjectConfig(1, 1);
@@ -223,7 +250,7 @@
// Test GetMetricDefintion.
TEST_F(ProjectConfigsTest, GetMetricDefinitionById) {
- ProjectConfigs project_configs(NewTestConfig());
+ ProjectConfigs project_configs(NewTestRegistry());
const MetricDefinition* metric;
metric = project_configs.GetMetricDefinition(1, 1, 1);
@@ -249,7 +276,7 @@
// Test GetReportDefinition.
TEST_F(ProjectConfigsTest, GetReportDefinitionById) {
- ProjectConfigs project_configs(NewTestConfig());
+ ProjectConfigs project_configs(NewTestRegistry());
const ReportDefinition* report;
report = project_configs.GetReportDefinition(1, 1, 1, 1);
@@ -280,24 +307,24 @@
// Tests using a ProjectConfigs constructed directly from a
// CobaltRegistry
TEST_F(ProjectConfigsTest, ConstructForCobaltRegistry) {
- ProjectConfigs project_configs(NewTestConfig());
+ ProjectConfigs project_configs(NewTestRegistry());
EXPECT_TRUE(CheckProjectConfigs(project_configs));
}
// Tests using a ProjectConfigs obtained via CreateFromCobaltRegistryBytes().
TEST_F(ProjectConfigsTest, CreateFromCobaltRegistryBytes) {
- auto cobalt_config = NewTestConfig();
+ auto cobalt_registry = NewTestRegistry();
std::string bytes;
- cobalt_config->SerializeToString(&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_config = NewTestConfig();
+ auto cobalt_registry = NewTestRegistry();
std::string bytes;
- cobalt_config->SerializeToString(&bytes);
+ cobalt_registry->SerializeToString(&bytes);
std::string cobalt_registry_base64;
crypto::Base64Encode(bytes, &cobalt_registry_base64);
auto project_configs =
@@ -305,5 +332,43 @@
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());
+
+ // 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());
+
+ // 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());
+
+ // 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());
+
+ // 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());
+}
+
} // namespace config
} // namespace cobalt