blob: 02eee1e70671322cdaa79929c6e0e22afa7abced [file] [log] [blame]
// Copyright 2019 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.
package validator
import (
"config"
"fmt"
)
func CompareMetrics(oldMetric, newMetric *config.MetricDefinition, ignoreCompatChecks bool) error {
// Debug metrics are ignored for the purposes of change validation.
if oldMetric.MetaData != nil && oldMetric.MetaData.MaxReleaseStage <= config.ReleaseStage_DEBUG {
return nil
}
if newMetric.MetaData != nil && newMetric.MetaData.MaxReleaseStage <= config.ReleaseStage_DEBUG {
return nil
}
oldDimensions := map[int]*config.MetricDefinition_MetricDimension{}
newDimensions := map[int]*config.MetricDefinition_MetricDimension{}
for ix, dim := range oldMetric.MetricDimensions {
oldDimensions[ix] = dim
}
for ix, dim := range newMetric.MetricDimensions {
newDimensions[ix] = dim
}
for ix, oldDimension := range oldDimensions {
newDimension, ok := newDimensions[ix]
if ok {
err := CompareDimensions(oldDimension, newDimension, ignoreCompatChecks)
if err != nil {
return fmt.Errorf("for dimension index '%d': %v", ix, err)
}
if oldMetric.MetricType == config.MetricDefinition_EVENT_OCCURRED || newMetric.MetricType == config.MetricDefinition_EVENT_OCCURRED {
if oldDimension.MaxEventCode != newDimension.MaxEventCode && !ignoreCompatChecks {
return fmt.Errorf("for dimension index '%d': changing max_event_code is not allowed for EVENT_OCCURRED metrics", ix)
}
}
}
}
newReports := map[string]*config.ReportDefinition{}
newReportIds := map[uint32]bool{}
for _, report := range newMetric.Reports {
newReports[report.ReportName] = report
newReportIds[report.Id] = true
}
oldReports := map[string]*config.ReportDefinition{}
newlyDeletedReportIds := map[uint32]string{}
for _, report := range oldMetric.Reports {
oldReports[report.ReportName] = report
_, ok := newReportIds[report.Id]
if !ok {
newlyDeletedReportIds[report.Id] = report.ReportName
}
}
for name, oldReport := range oldReports {
newReport, ok := newReports[name]
if ok {
err := CompareReports(oldReport, newReport, ignoreCompatChecks)
if err != nil {
return fmt.Errorf("for report named '%s': %v", name, err)
}
}
}
for newlyDeletedReportId, newlyDeletedReportName := range newlyDeletedReportIds {
found := false
for _, deletedReportId := range newMetric.DeletedReportIds {
if deletedReportId == newlyDeletedReportId {
found = true
break
}
}
if !found && !ignoreCompatChecks {
return fmt.Errorf("for report named '%s': the deleted report's ID %v must be added to the deleted_reports for the metric", newlyDeletedReportName, newlyDeletedReportId)
}
}
return nil
}
func CompareDimensions(oldDimension, newDimension *config.MetricDefinition_MetricDimension, ignoreCompatChecks bool) error {
for code, oldName := range oldDimension.EventCodes {
_, ok := newDimension.EventCodes[code]
if !ok && !ignoreCompatChecks {
return fmt.Errorf("removing an event code is not allowed: %d: %s", code, oldName)
}
}
return nil
}