implement fixturemap

This commit is contained in:
Randy J. Spaulding
2026-02-02 21:20:28 -05:00
parent 3e77721755
commit f673e1fe99
3 changed files with 116 additions and 4 deletions

View File

@@ -66,6 +66,9 @@ def main():
parser_test.add_argument(
"--output", help="Output JSON file", default="tests_to_run.json"
)
parser_test.add_argument(
"--fixturemap", help="Optional path to file containing the test <-> gtest fixture mapping", default=""
)
# Code auditing
parser_audit = subparsers.add_parser(
@@ -95,6 +98,8 @@ def main():
filter_args.append("--all")
if args.output:
filter_args += ["--output", args.output]
if args.fixturemap:
filter_args += ["--fixturemap", args.fixturemap]
run_selective_test_filter(filter_args)
elif args.command == "audit":
run_selective_test_filter([args.depmap_json, "--audit"])

View File

@@ -0,0 +1,76 @@
#!/usr/bin/env python3
import os
import stat
import subprocess
import json
import sys
from pathlib import Path
def is_executable(file_path: Path) -> bool:
"""Check if a file is an executable (not a directory)."""
return (
file_path.is_file()
and os.access(file_path, os.X_OK)
and not file_path.name.startswith('.') # skip hidden files
)
def list_gtest_fixtures(executable: Path):
"""Run the executable with --gtest_list_tests and return fixture names."""
try:
# Run the command and capture output
result = subprocess.run(
[str(executable), "--gtest_list_tests"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
timeout=10 # prevent hanging
)
if result.returncode != 0:
print(f"Warning: {executable} returned non-zero exit code. Assuming it is not a gtest.", file=sys.stderr)
return []
fixtures = []
for line in result.stdout.splitlines():
if line.strip() and not line.startswith(" ") and line.endswith("."): # non-indented = fixture name
fixtures.append(line.strip())
return fixtures
except subprocess.TimeoutExpired:
print(f"Error: {executable} timed out", file=sys.stderr)
return []
except Exception as e:
print(f"Error running {executable}: {e}", file=sys.stderr)
return []
def main(directory: str, output_file: str):
dir_path = Path(directory)
if not dir_path.is_dir():
print(f"Error: {directory} is not a valid directory", file=sys.stderr)
sys.exit(1)
results = {}
fixture_count = 0
for file in dir_path.iterdir():
if is_executable(file):
fixtures = list_gtest_fixtures(file)
if fixtures:
# src_file = file.name[5:] + ".cpp" # For MIOpen gtests, src_file.cpp <-> test_src_file
src_file = file.name # however, we're currently using the exe's name
results[src_file] = fixtures
fixture_count += len(fixtures)
# Write results to JSON
try:
with open(output_file, "w", encoding="utf-8") as f:
json.dump(results, f, indent=4)
print(f"List of {fixture_count} fixtures from {len(results)} files written to {output_file}")
except Exception as e:
print(f"Error writing JSON file: {e}", file=sys.stderr)
if __name__ == "__main__":
if len(sys.argv) != 3:
print(f"Usage: {sys.argv[0]} <directory> <output.json>", file=sys.stderr)
sys.exit(1)
main(sys.argv[1], sys.argv[2])

View File

@@ -57,6 +57,13 @@ def load_depmap(depmap_json):
return data
def load_fixturemap(fixture_file):
"""Load the dependency mapping JSON."""
with open(fixture_file, "r") as f:
data = json.load(f)
return data
def select_tests(file_to_executables, changed_files, filter_mode):
"""Return a set of test executables affected by changed files."""
affected = set()
@@ -70,6 +77,18 @@ def select_tests(file_to_executables, changed_files, filter_mode):
return sorted(affected)
def get_gtest_filter(tests, fixturemap):
"""Maps the set of texts to be executed to a gtest_filter"""
gtest_filter = ""
for t in tests:
if t in fixturemap:
for f in t:
gtest_filter += fixturemap[t][f] + "*:"
if gtest_filter:
gtest_filter = gtest_filter[:-1]
return gtest_filter
def main():
if "--audit" in sys.argv:
if len(sys.argv) < 2:
@@ -127,7 +146,10 @@ def main():
idx = sys.argv.index("--output")
if idx + 1 < len(sys.argv):
output_json = sys.argv[idx + 1]
if "--fixturemap" in sys.argv:
idx = sys.argv.index("--fixturemap")
if idx + 1 < len(sys.argv):
fixture_file = sys.argv[idx + 1]
if not os.path.exists(depmap_json):
print(f"Dependency map JSON not found: {depmap_json}")
sys.exit(1)
@@ -139,11 +161,20 @@ def main():
else:
file_to_executables = load_depmap(depmap_json)
tests = select_tests(file_to_executables, changed_files, filter_mode)
gtest_filter = ""
if tests and os.path.exists(fixture_file):
tests_to_fixtures = load_fixturemap(fixture_file)
gtest_filter = get_gtest_filter(tests, tests_to_fixtures)
with open(output_json, "w") as f:
json.dump(
{"tests_to_run": tests, "changed_files": sorted(changed_files)}, f, indent=2
)
if gtest_filter:
json.dump(
{"tests_to_run": tests, "gtest_filter": gtest_filter, "changed_files": sorted(changed_files)}, f, indent=2
)
else:
json.dump(
{"tests_to_run": tests, "changed_files": sorted(changed_files)}, f, indent=2
)
print(f"Exported {len(tests)} tests to run to {output_json}")