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
254 lines
9.3 KiB
Python
254 lines
9.3 KiB
Python
################################################################################
|
|
#
|
|
# Copyright (C) 2022-2025 Advanced Micro Devices, Inc. All rights reserved.
|
|
#
|
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
# of this software and associated documentation files (the "Software"), to deal
|
|
# in the Software without restriction, including without limitation the rights
|
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
# copies of the Software, and to permit persons to whom the Software is
|
|
# furnished to do so, subject to the following conditions:
|
|
#
|
|
# The above copyright notice and this permission notice shall be included in
|
|
# all copies or substantial portions of the Software.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
# SOFTWARE.
|
|
#
|
|
################################################################################
|
|
|
|
"""Pytest-specific test configuration helpers.
|
|
|
|
For artifact compression/extraction utilities (no pytest dependency),
|
|
see artifact_helpers.py.
|
|
"""
|
|
|
|
import os
|
|
import re
|
|
|
|
import pytest
|
|
import yaml
|
|
|
|
from Tensile.Common.DataType import DataType
|
|
|
|
_TESTS_ROOT_DIR = os.path.dirname(os.path.dirname(__file__))
|
|
|
|
try:
|
|
DEFAULT_YAML_LOADER = yaml.CSafeLoader
|
|
except AttributeError:
|
|
DEFAULT_YAML_LOADER = yaml.SafeLoader
|
|
|
|
|
|
def get_rocm_version_or_none():
|
|
"""Gets the ROCm version from the version file."""
|
|
try:
|
|
rocmpath = os.environ.get("ROCM_PATH", "/opt/rocm")
|
|
version_file_path = os.path.join(rocmpath, ".info/version")
|
|
|
|
with open(version_file_path, 'r') as f:
|
|
version_string = f.readline().strip()
|
|
return version_string
|
|
except (FileNotFoundError, IOError):
|
|
return None
|
|
|
|
|
|
def walkDict(root, path=""):
|
|
"""
|
|
Recursively walks a structure which may consist of dictionaries, lists,
|
|
and other objects. Yields (object, path) for each object in the
|
|
structure.
|
|
"""
|
|
yield root, path
|
|
if isinstance(root, dict):
|
|
for key, value in root.items():
|
|
keypath = key
|
|
if path != "":
|
|
keypath = path + "." + str(keypath)
|
|
yield from walkDict(value, keypath)
|
|
elif isinstance(root, list):
|
|
for i, obj in enumerate(root):
|
|
keypath = str(i)
|
|
if path != "":
|
|
keypath = path + "." + keypath
|
|
yield from walkDict(obj, keypath)
|
|
|
|
|
|
def markNamed(name):
|
|
"""
|
|
Gets a mark by a name contained in a variable.
|
|
"""
|
|
return getattr(pytest.mark, name)
|
|
|
|
|
|
def configMarks(filepath, rootDir, availableArchs):
|
|
"""
|
|
Returns a list of marks to add to a particular YAML config path. Currently gets a mark for:
|
|
|
|
- Root directory name. This separates tests into pre_checkin, nightly, etc.
|
|
- Expected failures. Include 'xfail' in the name of the YAML file.
|
|
- Anything in yaml["TestParameters"]["marks"]
|
|
- Architecture from GlobalParameters.Architecture (e.g. gfx1250)
|
|
- Architecture from filename (e.g. bf16_gfx1250.yaml -> gfx1250)
|
|
- validate / validateAll - whether the test validates (all?) results.
|
|
- Data type(s) used in the YAML
|
|
- Problem type(s) used in the YAML
|
|
- Kernel language(s) used in the YAML
|
|
"""
|
|
relpath = os.path.relpath(filepath, rootDir)
|
|
components = relpath.split(os.path.sep)
|
|
|
|
# First part of directory - nightly, pre-checkin, etc.
|
|
# Skip underscore-prefixed path components (e.g. characterization's _codegen
|
|
# fixture dir): pytest rejects marks starting with "_", and such dirs hold
|
|
# library logic YAMLs that are filtered out below by the not-dict guard anyway.
|
|
marks = list([markNamed(c) for c in components[:-1] if not c.startswith("_")])
|
|
|
|
if 'xfail' in relpath or 'wip' in relpath:
|
|
marks.append(pytest.mark.xfail)
|
|
if 'disabled' in relpath:
|
|
marks.append(pytest.mark.skip)
|
|
|
|
try:
|
|
with open(filepath) as f:
|
|
doc = yaml.load(f, DEFAULT_YAML_LOADER)
|
|
except yaml.parser.ParserError:
|
|
marks.append(pytest.mark.syntax_error)
|
|
return marks
|
|
|
|
# A Tensile config is a mapping (GlobalParameters/BenchmarkProblems/...).
|
|
# Top-level sequences are library logic YAMLs (e.g. characterization data
|
|
# files), which are not standalone Tensile.py configs. Signal the caller to
|
|
# skip them rather than crashing on doc["BenchmarkProblems"].
|
|
if not isinstance(doc, dict):
|
|
return None
|
|
|
|
if "TestParameters" in doc:
|
|
if "marks" in doc["TestParameters"]:
|
|
marks += [markNamed(m) for m in doc["TestParameters"]["marks"]]
|
|
|
|
arch_val = doc.get("GlobalParameters", {}).get("Architecture")
|
|
if arch_val and markNamed(arch_val) not in marks:
|
|
marks.append(markNamed(arch_val))
|
|
|
|
arch_in_name = re.search(r'(gfx\d+)', components[-1])
|
|
if arch_in_name and markNamed(arch_in_name.group(1)) not in marks:
|
|
marks.append(markNamed(arch_in_name.group(1)))
|
|
|
|
# Architecture specific xfail marks
|
|
for arch in availableArchs:
|
|
ArchFail = "xfail-%s" % arch
|
|
if markNamed(ArchFail) in marks:
|
|
marks.append(pytest.mark.xfail)
|
|
ArchSkip = "skip-%s" % arch
|
|
if markNamed(ArchSkip) in marks:
|
|
marks.append(pytest.mark.skip)
|
|
|
|
validate = True
|
|
validateAll = False
|
|
try:
|
|
if doc["GlobalParameters"]['NumElementsToValidate'] == 0:
|
|
validate = False
|
|
if doc["GlobalParameters"]['NumElementsToValidate'] == -1:
|
|
validateAll = True
|
|
except KeyError:
|
|
pass
|
|
|
|
if validate:
|
|
marks.append(pytest.mark.validate)
|
|
if validateAll:
|
|
marks.append(pytest.mark.validateAll)
|
|
|
|
dataTypes = set([problem[0]["DataType"] for problem in doc["BenchmarkProblems"]])
|
|
operationTypes = set([problem[0]["OperationType"] for problem in doc["BenchmarkProblems"]])
|
|
|
|
languages = set()
|
|
for obj, path in walkDict(doc):
|
|
if "KernelLanguage" in path and isinstance(obj, str):
|
|
languages.add(obj)
|
|
|
|
for l in languages:
|
|
marks.append(markNamed(l))
|
|
|
|
for dt in dataTypes:
|
|
dataType = DataType(dt)
|
|
marks.append(markNamed(dataType.toName()))
|
|
|
|
for operationType in operationTypes:
|
|
marks.append(markNamed(operationType))
|
|
|
|
return marks
|
|
|
|
def findAvailableArchs(gpu_targets=None):
|
|
"""Detect available GPU architectures, or use an explicit override.
|
|
|
|
Args:
|
|
gpu_targets: Semicolon-separated GPU targets (e.g. "gfx942").
|
|
When provided, skips hardware detection entirely.
|
|
|
|
Returns:
|
|
List of architecture strings (e.g. ["gfx942"]).
|
|
"""
|
|
if gpu_targets:
|
|
return [t.strip() for t in gpu_targets.split(";") if t.strip()]
|
|
|
|
from Tensile.Tests.gpu_detection import get_available_archs
|
|
return get_available_archs()
|
|
|
|
|
|
def findConfigs(rootDir=None, availableArchs=None):
|
|
"""
|
|
Walks rootDir (defaults to trying to find Tensile/Tests) and returns a
|
|
list of test parameters, one for each YAML file.
|
|
|
|
Args:
|
|
rootDir: Directory to walk for YAML configs. Defaults to Tensile/Tests.
|
|
availableArchs: Pre-resolved list of GPU architectures.
|
|
When None, calls findAvailableArchs() to auto-detect.
|
|
"""
|
|
if rootDir is None:
|
|
rootDir = _TESTS_ROOT_DIR
|
|
printRoot = os.path.dirname(os.path.dirname(rootDir))
|
|
else:
|
|
printRoot = rootDir
|
|
|
|
if availableArchs is None:
|
|
availableArchs = findAvailableArchs()
|
|
globalParamArchsStr = ';'.join(availableArchs)
|
|
os.environ["PyTestBuildArchNames"] = globalParamArchsStr
|
|
|
|
rocm_version = get_rocm_version_or_none()
|
|
|
|
params = []
|
|
for (dirpath, dirnames, filenames) in os.walk(rootDir):
|
|
for filename in filenames:
|
|
# Conditionally skip icache_flush.yaml on rocm 7.1 due to ROCm bug.
|
|
if filename == "icache_flush.yaml" and rocm_version and rocm_version.startswith("7.1"):
|
|
print(f"INFO: Skipping '{filename}' on ROCm {rocm_version}.")
|
|
continue
|
|
|
|
# Skip build client script
|
|
if filename == "build_client.yaml":
|
|
continue
|
|
# filter out yamls in logic_yaml since they are not meant for Tensile.py
|
|
elif filename.endswith('.yaml') and "logic_yaml" not in dirpath:
|
|
filepath = os.path.join(rootDir, dirpath, filename)
|
|
if not "test_data" in filepath:
|
|
marks = configMarks(filepath, rootDir, availableArchs)
|
|
if marks is None:
|
|
# Not a Tensile config (e.g. a library logic YAML); skip.
|
|
continue
|
|
|
|
# Conditionally xfail icache_flush.yaml on rocm 7.1 due to ROCm bug.
|
|
if filename == "icache_flush.yaml" and rocm_version and rocm_version.startswith("7.1"):
|
|
reason = "Test is expected to fail on ROCm 7.1 due to a known bug."
|
|
marks.append(pytest.mark.xfail(reason=reason, strict=True))
|
|
|
|
relpath = os.path.relpath(filepath, printRoot)
|
|
params.append(pytest.param(filepath, marks=marks, id=relpath))
|
|
return params
|