blob: 0a6eb232b3b64b744c72a0d3402f447699a69255 [file] [log] [blame]
# Copyright 2023 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.
"""Provides an abstraction to assert that a set of metrics matches the expected one."""
import os
_OPTIONAL_SUFFIX: str = " [optional]"
class MetricsAllowlist:
def __init__(self, file_path: str | os.PathLike[str]):
"""Creates a new metric allowlist.
Args:
file_path: path to the file containing the expected metrics.
"""
self.file_path = file_path
self.optional_metrics: set[str] = set()
self.expected_metrics: set[str] = set()
self._should_summarize = True
allow_command = True
with open(self.file_path) as f:
for line in f:
line = line.rstrip("\n")
if line.strip() == "[no-summarize-metrics]":
if not allow_command:
raise ValueError(
"[no-summarize-metrics] can only appear at the beginning of the file"
)
self._should_summarize = False
continue
if line.strip().startswith("#") or line.strip() == "":
continue
if line.endswith(_OPTIONAL_SUFFIX):
self.optional_metrics.add(
line.removesuffix(_OPTIONAL_SUFFIX)
)
else:
self.expected_metrics.add(line)
allow_command = False
@property
def should_summarize(self) -> bool:
return self._should_summarize
def check(self, actual_metrics: set[str]) -> None:
"""Checks that the given `actual_metrics` matches the expected metrics.
Args:
actual_metrics: the set of metrics to check.
Raises:
ValueError: when the metrics don't match. Includes the diff.
"""
actual_minus_optional: set[str] = actual_metrics.difference(
self.optional_metrics
)
if self.expected_metrics == actual_minus_optional:
return
union: list[str] = sorted(
actual_metrics.union(self.expected_metrics).union(
self.optional_metrics
)
)
lines: list[str] = []
for entry in union:
prefix: str = " "
suffix: str = ""
if entry in self.optional_metrics:
suffix = _OPTIONAL_SUFFIX
elif entry in actual_metrics:
if entry not in self.expected_metrics:
prefix = "+"
else:
prefix = "-"
lines.append(prefix + entry + suffix)
diff = "\n".join(lines)
raise ValueError(
(
f"Metric names produced by the test differ from the expectations in "
f"{self.file_path}: {diff}\n\n"
"One way to update the expectation file is to run the test locally with this "
"environment variable set:\n"
"FUCHSIA_EXPECTED_METRIC_NAMES_DEST_DIR="
"$(pwd)/src/tests/end_to_end/perf/expected_metric_names\n\n"
"See https://fuchsia.dev/fuchsia-src/development/performance/metric_name_expectations"
)
)