| package config_validator |
| |
| import ( |
| "config" |
| "config_parser" |
| "fmt" |
| "testing" |
| "time" |
| |
| "github.com/google/go-cmp/cmp" |
| ) |
| |
| func TestEmptyValidationErrors(t *testing.T) { |
| if newValidationErrors("err").err() != nil { |
| t.Errorf("Empty validation errors .err() should return nil") |
| } |
| } |
| |
| func TestSingleValidationErrors(t *testing.T) { |
| errs := newValidationErrors("err") |
| errs.addError("an", fmt.Errorf("error")) |
| expectedError := "err `an`: error" |
| if diff := cmp.Diff(errs.err().Error(), expectedError); diff != "" { |
| t.Errorf("Output error does not match expected error: %s", diff) |
| } |
| } |
| |
| func TestMultipleValidationErrors(t *testing.T) { |
| errs := newValidationErrors("err") |
| errs.addError("an", fmt.Errorf("error")) |
| errs.addError("another", fmt.Errorf("error")) |
| expectedError := "err `an`: error\nerr `another`: error" |
| if diff := cmp.Diff(errs.err().Error(), expectedError); diff != "" { |
| t.Errorf("Output error does not match expected error: %s", diff) |
| } |
| } |
| |
| func TestNestedValidationErrors(t *testing.T) { |
| innerErr := newValidationErrors("inner") |
| innerErr.addError("an", fmt.Errorf("error")) |
| errs := newValidationErrors("err") |
| errs.addError("nested", innerErr.err()) |
| expectedError := "err `nested`:\n inner `an`: error" |
| if diff := cmp.Diff(errs.err().Error(), expectedError); diff != "" { |
| t.Errorf("Output error does not match expected error: %s", diff) |
| } |
| } |
| |
| func TestMultipleNestedValidationErrors(t *testing.T) { |
| innerErr := newValidationErrors("inner") |
| innerErr.addError("an", fmt.Errorf("error")) |
| errs := newValidationErrors("err") |
| errs.addError("nested2", innerErr.err()) |
| errs.addError("nested1", innerErr.err()) |
| expectedError := "err `nested1`:\n inner `an`: error\nerr `nested2`:\n inner `an`: error" |
| if diff := cmp.Diff(errs.err().Error(), expectedError); diff != "" { |
| t.Errorf("Output error does not match expected error: %s", diff) |
| } |
| } |
| |
| func TestMultipleErrorsForLevel(t *testing.T) { |
| errs := newValidationErrors("err") |
| errs.addError("an", fmt.Errorf("error")) |
| errs.addError("an", fmt.Errorf("error")) |
| expectedError := "err `an`:\n error\n error" |
| if diff := cmp.Diff(errs.err().Error(), expectedError); diff != "" { |
| t.Errorf("Output error does not match expected error: %s", diff) |
| } |
| } |
| |
| func TestValidateProjectConfigDatasWithDeletedCustomerIds(t *testing.T) { |
| projectConfigFile := config.ProjectConfigFile{ |
| MetricDefinitions: []*config.MetricDefinition{ |
| { |
| CustomerId: 5, |
| ProjectId: 3, |
| MetricName: "the_metric_name", |
| Id: 1, |
| TimeZonePolicy: config.MetricDefinition_UTC, |
| MetricSemantics: []config.MetricSemantics{ |
| config.MetricSemantics_METRIC_SEMANTICS_UNSPECIFIED, |
| }, |
| MetricType: config.MetricDefinition_OCCURRENCE, |
| Reports: []*config.ReportDefinition{ |
| { |
| ReportName: "the_report", |
| Id: 10, |
| ReportType: config.ReportDefinition_FLEETWIDE_OCCURRENCE_COUNTS, |
| PrivacyLevel: config.ReportDefinition_NO_ADDED_PRIVACY, |
| PrivacyMechanism: config.ReportDefinition_DE_IDENTIFICATION, |
| SystemProfileSelection: config.SystemProfileSelectionPolicy_REPORT_ALL, |
| }, |
| { |
| ReportName: "the_other_report", |
| Id: 20, |
| ReportType: config.ReportDefinition_HOURLY_VALUE_NUMERIC_STATS, |
| PrivacyLevel: config.ReportDefinition_NO_ADDED_PRIVACY, |
| PrivacyMechanism: config.ReportDefinition_DE_IDENTIFICATION, |
| SystemProfileSelection: config.SystemProfileSelectionPolicy_REPORT_ALL, |
| }, |
| }, |
| MetaData: &config.MetricDefinition_Metadata{ |
| ExpirationDate: time.Now().AddDate(1, 0, 0).Format(dateFormat), |
| MaxReleaseStage: config.ReleaseStage_DEBUG, |
| }, |
| }, |
| }, |
| } |
| configs := []config_parser.ProjectConfigData{ |
| { |
| CustomerName: "customer5", |
| CustomerId: 5, |
| ProjectName: "project3", |
| ProjectId: 3, |
| Contact: "project3@customer5.com", |
| ProjectConfigFile: &projectConfigFile, |
| }, |
| { |
| CustomerName: "customer5", |
| CustomerId: 5, |
| ProjectName: "project4", |
| ProjectId: 4, |
| Contact: "project4@customer5.com", |
| ProjectConfigFile: &projectConfigFile, |
| }, |
| { |
| CustomerId: 1, |
| IsDeletedCustomer: true, |
| }, |
| { |
| CustomerId: 2, |
| IsDeletedCustomer: true, |
| }, |
| } |
| err := ValidateProjectConfigDatas(configs) |
| if err != nil { |
| t.Errorf("Validation incorrectly rejected deleted customer IDs: %v", err) |
| } |
| } |
| |
| func TestValidateProjectConfigDatasWithReusedDeletedCustomerIds(t *testing.T) { |
| projectConfigFile := config.ProjectConfigFile{ |
| MetricDefinitions: []*config.MetricDefinition{ |
| { |
| CustomerId: 5, |
| ProjectId: 3, |
| MetricName: "the_metric_name", |
| Id: 1, |
| TimeZonePolicy: config.MetricDefinition_UTC, |
| MetricSemantics: []config.MetricSemantics{ |
| config.MetricSemantics_METRIC_SEMANTICS_UNSPECIFIED, |
| }, |
| MetricType: config.MetricDefinition_OCCURRENCE, |
| Reports: []*config.ReportDefinition{ |
| { |
| ReportName: "the_report", |
| Id: 10, |
| ReportType: config.ReportDefinition_FLEETWIDE_OCCURRENCE_COUNTS, |
| PrivacyLevel: config.ReportDefinition_NO_ADDED_PRIVACY, |
| PrivacyMechanism: config.ReportDefinition_DE_IDENTIFICATION, |
| SystemProfileSelection: config.SystemProfileSelectionPolicy_REPORT_ALL, |
| }, |
| { |
| ReportName: "the_other_report", |
| Id: 20, |
| ReportType: config.ReportDefinition_HOURLY_VALUE_NUMERIC_STATS, |
| PrivacyLevel: config.ReportDefinition_NO_ADDED_PRIVACY, |
| PrivacyMechanism: config.ReportDefinition_DE_IDENTIFICATION, |
| SystemProfileSelection: config.SystemProfileSelectionPolicy_REPORT_ALL, |
| }, |
| }, |
| MetaData: &config.MetricDefinition_Metadata{ |
| ExpirationDate: time.Now().AddDate(1, 0, 0).Format(dateFormat), |
| MaxReleaseStage: config.ReleaseStage_DEBUG, |
| }, |
| }, |
| }, |
| } |
| configs := []config_parser.ProjectConfigData{ |
| { |
| CustomerName: "customer5", |
| CustomerId: 5, |
| ProjectName: "project3", |
| ProjectId: 3, |
| Contact: "project3@customer5.com", |
| ProjectConfigFile: &projectConfigFile, |
| }, |
| { |
| CustomerName: "customer5", |
| CustomerId: 5, |
| ProjectName: "project4", |
| ProjectId: 4, |
| Contact: "project4@customer5.com", |
| ProjectConfigFile: &projectConfigFile, |
| }, |
| { |
| CustomerId: 1, |
| IsDeletedCustomer: true, |
| }, |
| { |
| CustomerId: 5, |
| IsDeletedCustomer: true, |
| }, |
| } |
| err := ValidateProjectConfigDatas(configs) |
| if err == nil { |
| t.Errorf("Validation did not catch expected error for reusing deleted customer IDs") |
| } |
| } |
| |
| func TestValidateProjectConfigDatasCustomerExperimentNamespaces(t *testing.T) { |
| configs := []config_parser.ProjectConfigData{ |
| { |
| CustomerName: "cobalt_internal", |
| CustomerId: 2147483647, |
| ProjectName: "project3", |
| ProjectId: 3, |
| Contact: "project3@customer5.com", |
| CustomerExperimentsNamespaces: []interface{}{"customer_experiment_namespace"}, |
| }, |
| } |
| err := ValidateProjectConfigDatas(configs) |
| if err == nil { |
| t.Errorf("Validation did not catch expected error for experiments in internal customers") |
| } |
| } |
| |
| func TestValidateProjectConfigDatasProjectExperimentNamespaces(t *testing.T) { |
| configs := []config_parser.ProjectConfigData{ |
| { |
| CustomerName: "cobalt_internal", |
| CustomerId: 2147483647, |
| ProjectName: "project3", |
| ProjectId: 3, |
| Contact: "project3@customer5.com", |
| ProjectExperimentsNamespaces: []interface{}{"customer_experiment_namespace"}, |
| }, |
| } |
| err := ValidateProjectConfigDatas(configs) |
| if err == nil { |
| t.Errorf("Validation did not catch expected error for experiments in internal projects") |
| } |
| } |
| |
| func TestValidateProjectConfigDatasDeletedProject(t *testing.T) { |
| projectConfigFile := config.ProjectConfigFile{ |
| MetricDefinitions: []*config.MetricDefinition{ |
| { |
| CustomerId: 5, |
| ProjectId: 3, |
| MetricName: "the_metric_name", |
| Id: 1, |
| TimeZonePolicy: config.MetricDefinition_UTC, |
| Reports: []*config.ReportDefinition{ |
| { |
| ReportName: "the_report", |
| Id: 10, |
| ReportType: config.ReportDefinition_FLEETWIDE_OCCURRENCE_COUNTS, |
| }, |
| { |
| ReportName: "the_other_report", |
| Id: 20, |
| ReportType: config.ReportDefinition_HOURLY_VALUE_NUMERIC_STATS, |
| }, |
| }, |
| }, |
| }, |
| } |
| configs := []config_parser.ProjectConfigData{ |
| { |
| CustomerName: "customer5", |
| CustomerId: 5, |
| ProjectName: "project3", |
| ProjectId: 3, |
| Contact: "project3@customer5.com", |
| DeletedProjectIds: []uint32{4, 5}, |
| ProjectConfigFile: &projectConfigFile, |
| }, |
| { |
| CustomerName: "customer5", |
| CustomerId: 5, |
| ProjectName: "project4", |
| ProjectId: 4, |
| Contact: "project4@customer5.com", |
| DeletedProjectIds: []uint32{4, 5}, |
| ProjectConfigFile: &projectConfigFile, |
| }, |
| } |
| err := ValidateProjectConfigDatas(configs) |
| if err == nil { |
| t.Errorf("Validation did not catch expected error for reusing deleted project ID") |
| } |
| } |
| |
| func TestValidateProjectConfigDatasDeletedMetric(t *testing.T) { |
| projectConfigFile := config.ProjectConfigFile{ |
| MetricDefinitions: []*config.MetricDefinition{ |
| { |
| CustomerId: 5, |
| ProjectId: 3, |
| MetricName: "the_metric_name", |
| Id: 1, |
| TimeZonePolicy: config.MetricDefinition_UTC, |
| Reports: []*config.ReportDefinition{ |
| { |
| ReportName: "the_report", |
| Id: 10, |
| ReportType: config.ReportDefinition_FLEETWIDE_OCCURRENCE_COUNTS, |
| }, |
| { |
| ReportName: "the_other_report", |
| Id: 20, |
| ReportType: config.ReportDefinition_HOURLY_VALUE_NUMERIC_STATS, |
| }, |
| }, |
| }, |
| { |
| CustomerId: 5, |
| ProjectId: 3, |
| MetricName: "the_other_metric_name", |
| Id: 2, |
| TimeZonePolicy: config.MetricDefinition_LOCAL, |
| Reports: []*config.ReportDefinition{ |
| { |
| ReportName: "the_report", |
| Id: 10, |
| ReportType: config.ReportDefinition_HOURLY_VALUE_NUMERIC_STATS, |
| }, |
| }, |
| }, |
| }, |
| DeletedMetricIds: []uint32{2}, |
| } |
| configs := []config_parser.ProjectConfigData{ |
| { |
| CustomerName: "customer5", |
| CustomerId: 5, |
| ProjectName: "project3", |
| ProjectId: 3, |
| Contact: "project3@customer5.com", |
| ProjectConfigFile: &projectConfigFile, |
| }, |
| } |
| err := ValidateProjectConfigDatas(configs) |
| if err == nil { |
| t.Errorf("Validation did not catch expected error for reusing deleted metric ID") |
| } |
| } |