Files
TheRock/rocm-libraries/projects/hipblaslt/tensilelite/Tensile/Tests/unit/characterization/conftest.py
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

183 lines
6.9 KiB
Python

################################################################################
# Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved.
# SPDX-License-Identifier: MIT
################################################################################
"""Characterization-suite shared configuration.
Adds the ``_codegen`` helper directory to ``sys.path`` so any characterization
suite can ``from codegen_harness import ...`` (the CPU-only assembly-emit
harness used by the codegen coverage suites), and exposes the cached
toolchain / cap-map / data-dir as session fixtures.
This file only *adds* an import path and read-only fixtures; it changes no
existing behavior.
"""
import os
import sys
import pytest
_CODEGEN_DIR = os.path.join(os.path.dirname(__file__), "_codegen")
if _CODEGEN_DIR not in sys.path:
sys.path.insert(0, _CODEGEN_DIR)
def _foreign_path_instantiable() -> bool:
"""Return True if a Windows-flavored ``pathlib.Path`` can be built here.
On POSIX, CPython refuses to instantiate ``WindowsPath`` (``NotImplementedError``
through 3.12, the ``NotImplementedError`` subclass ``UnsupportedOperation`` in
3.13+). Characterization tests that flip ``os.name`` to ``"nt"`` and let
production code construct a concrete ``pathlib.Path`` therefore raise inside the
function under test *and* inside pytest's own failure reporting, which builds
``Path(os.getcwd())`` while ``os.name`` is still ``"nt"`` -- taking down the
whole xdist worker with an INTERNALERROR. Detect the capability directly
rather than sniffing the interpreter version.
"""
from pathlib import Path
saved = os.name
try:
os.name = "nt"
Path("probe")
return True
except NotImplementedError:
return False
finally:
os.name = saved
def _snapshot_plugin_available() -> bool:
"""Return True if syrupy's ``snapshot`` fixture is available here.
The characterization suite asserts against syrupy snapshots via the
``snapshot`` fixture. The tox ``unit``/``coverage-unit`` environments install
syrupy, but the installed-artifact test tree (``share/hipblaslt/tensilelite``,
run by TheRock) executes against a leaner interpreter that does not ship
syrupy and does not receive this package's ``pyproject``/``tox`` dependency
declarations. There every ``snapshot``-using test errors at setup with
``fixture 'snapshot' not found``. Detect the capability directly so the suite
is cleanly skipped where the plugin is absent rather than erroring the run.
"""
import importlib.util
return importlib.util.find_spec("syrupy") is not None
def pytest_collection_modifyitems(config, items):
"""Skip capability-gated characterization tests where the env can't run them.
Two independent gates:
* ``nt_path_simulation`` tests flip ``os.name`` to ``"nt"`` and exercise
production code that constructs a ``pathlib.Path``. On any POSIX
interpreter this cannot succeed, so they run only where a Windows-flavored
``Path`` is instantiable.
* ``snapshot``-using tests require the syrupy plugin, which the
installed-artifact test environment does not provide; they run only where
syrupy is importable.
"""
skip_nt = None
if not _foreign_path_instantiable():
skip_nt = pytest.mark.skip(
reason="WindowsPath not instantiable on this interpreter; nt-path simulation skipped"
)
skip_snapshot = None
if not _snapshot_plugin_available():
skip_snapshot = pytest.mark.skip(
reason="syrupy not installed; snapshot characterization tests skipped"
)
if skip_nt is None and skip_snapshot is None:
return
for item in items:
if skip_nt is not None and "nt_path_simulation" in item.keywords:
item.add_marker(skip_nt)
if skip_snapshot is not None and "snapshot" in getattr(item, "fixturenames", ()):
item.add_marker(skip_snapshot)
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
"""Tag a failed snapshot test so the terminal summary can route the author to
the golden-update policy.
Keys off the real ``snapshot`` fixture usage (not failure-text heuristics) and
records the tag on ``report.user_properties`` so it survives xdist worker ->
controller serialization (a plain module global would be lost under ``-n``).
"""
outcome = yield
report = outcome.get_result()
if (
report.when == "call"
and report.failed
and "snapshot" in getattr(item, "fixturenames", ())
):
report.user_properties.append(("char_snapshot_failure", True))
def pytest_terminal_summary(terminalreporter, exitstatus, config):
"""When a characterization snapshot test fails, print the snapshot-update
policy so a failing author never reaches for a blanket ``--snapshot-update``.
Driven by the ``char_snapshot_failure`` tag set in ``pytest_runtest_makereport``,
which gates on ``report.when == "call"`` -- so this fires on a call-phase failure
of a ``snapshot``-fixture test (usually a golden mismatch, occasionally an
unrelated error in the test body; the guidance is harmless in the latter case).
Setup-/teardown-phase errors are not tagged and do not trigger this banner.
"""
failed = terminalreporter.stats.get("failed", [])
nodeids = [
rep.nodeid
for rep in failed
if any(k == "char_snapshot_failure" for k, _ in getattr(rep, "user_properties", []))
]
if not nodeids:
return
bar = "=" * 78
write = terminalreporter.write_line
write("")
write(bar)
write("Characterization snapshot test failed (likely a golden mismatch)")
write("-" * 78)
write("These goldens pin TensileLite's current behavior as a refactor safety net.")
write("")
write("If this behavior change was NOT intended, you found a regression -- fix")
write("your code; do NOT touch the .ambr files.")
write("")
write("If it WAS intended, update ONLY the affected node(s) and review the diff:")
for nodeid in nodeids[:10]:
write(" pytest '%s' --snapshot-update" % nodeid)
if len(nodeids) > 10:
write(" ... and %d more" % (len(nodeids) - 10))
write("")
write("NEVER run a bare, suite-wide 'pytest --snapshot-update' -- it silently")
write("rewrites every golden and destroys the net.")
write("")
write(
"Policy (single source of truth): "
"Tensile/Tests/unit/characterization/README.md "
"-- 'Snapshot / golden discipline (governance)'"
)
write(bar)
@pytest.fixture(scope="session")
def cg_assembler():
"""The CPU-only assembler (amdclang++); shared across codegen suites."""
from codegen_harness import get_assembler
return get_assembler()
@pytest.fixture(scope="session")
def cg_isa_info_map():
"""The ISA capability map; shared across codegen suites."""
from codegen_harness import get_isa_info_map
return get_isa_info_map()