You've already forked open-source-firmware-validation
mirror of
https://github.com/Dasharo/open-source-firmware-validation.git
synced 2026-03-06 14:51:55 -08:00
81144456ce
Signed-off-by: Filip Gołaś <filip.golas@3mdeb.com>
156 lines
5.1 KiB
Python
Executable File
156 lines
5.1 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
# SPDX-FileCopyrightText: 2026 3mdeb <contact@3mdeb.com>
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
from robot.api import ExecutionResult
|
|
|
|
GREEN = "\033[92m"
|
|
RESET = "\033[0m"
|
|
RED = "\033[31m"
|
|
YELLOW = "\033[33m"
|
|
|
|
|
|
def safe_dir_name(name: str) -> str:
|
|
# Windows + Linux safe-ish folder name
|
|
name = name.strip()
|
|
name = re.sub(r"[<>:\"/\\|?*\x00-\x1F]", "_", name)
|
|
name = re.sub(r"\s+", " ", name)
|
|
return name[:150] if len(name) > 150 else name
|
|
|
|
|
|
def get_recovered_path(out_xml: Path) -> Path:
|
|
return out_xml.with_name(out_xml.name + "_recovered")
|
|
|
|
|
|
def main() -> None:
|
|
if len(sys.argv) < 3:
|
|
print(f"Usage: {sys.argv[0]} <out.xml> <output_dir>")
|
|
exit(1)
|
|
|
|
input_xml = Path(sys.argv[1]).resolve()
|
|
if not input_xml.exists():
|
|
raise SystemExit(f"ERROR: {input_xml} not found")
|
|
|
|
out_root = Path(sys.argv[2]).resolve()
|
|
out_root.mkdir(parents=True, exist_ok=True)
|
|
|
|
try:
|
|
result = ExecutionResult(input_xml)
|
|
except:
|
|
print(f"{YELLOW}WARNING{RESET}: invalid xml: {input_xml}")
|
|
try:
|
|
recovered_path = get_recovered_path(input_xml)
|
|
out = subprocess.run(
|
|
[
|
|
"xmllint",
|
|
f"{input_xml}",
|
|
"--recover",
|
|
"--output",
|
|
f"{recovered_path}",
|
|
],
|
|
capture_output=True,
|
|
)
|
|
print(out.stderr.decode("utf-8"))
|
|
input_xml = recovered_path
|
|
result = ExecutionResult(recovered_path)
|
|
except Exception as e:
|
|
print(
|
|
f"{RED}WARNING{RESET}: could not recover xml, skipping suite: {input_xml}"
|
|
)
|
|
print(e)
|
|
return 0
|
|
top = result.suite
|
|
top_suites = list(top.suites)
|
|
|
|
run_date = sys.argv[3]
|
|
if not top_suites:
|
|
print("No top-level suites found. Treating the available suite as top-level.")
|
|
suite_dir = input_xml.parent
|
|
new_suite_dir_name = safe_dir_name(top.name) + f"_{run_date}"
|
|
new_suite_dir = suite_dir.parent / new_suite_dir_name
|
|
shutil.move(str(suite_dir), str(new_suite_dir))
|
|
# Rename the log, report, and output files
|
|
for file in new_suite_dir.glob("*"):
|
|
new_file_name = file.name
|
|
# Modify the file names if they match the output files
|
|
if "_out.xml" in file.name:
|
|
new_file_name = f"{top.name}_{run_date}_out.xml"
|
|
elif "_log.html" in file.name:
|
|
new_file_name = f"{top.name}_{run_date}_log.html"
|
|
elif "_report.html" in file.name:
|
|
new_file_name = f"{top.name}_{run_date}_report.html"
|
|
elif "_debug.log" in file.name:
|
|
new_file_name = f"{top.name}_{run_date}_debug.log"
|
|
|
|
new_file = new_suite_dir / new_file_name
|
|
file.rename(new_file)
|
|
print(f"{GREEN}Results under:{RESET} {new_suite_dir}")
|
|
return 0
|
|
|
|
run_date = sys.argv[3]
|
|
if not top_suites:
|
|
print("No top-level suites found. Treating the available suite as top-level.")
|
|
suite_dir = input_xml.parent
|
|
new_suite_dir_name = safe_dir_name(top.name) + f"_{run_date}"
|
|
new_suite_dir = suite_dir.parent / new_suite_dir_name
|
|
shutil.move(str(suite_dir), str(new_suite_dir))
|
|
# Rename the log, report, and output files
|
|
for file in new_suite_dir.glob("*"):
|
|
new_file_name = file.name
|
|
# Modify the file names if they match the output files
|
|
if "_out.xml" in file.name:
|
|
new_file_name = f"{top.name}_{run_date}_output.xml"
|
|
elif "_log.html" in file.name:
|
|
new_file_name = f"{top.name}_{run_date}_log.html"
|
|
elif "_report.html" in file.name:
|
|
new_file_name = f"{top.name}_{run_date}_report.html"
|
|
elif "_debug.log" in file.name:
|
|
new_file_name = f"{top.name}_{run_date}_debug.log"
|
|
|
|
new_file = new_suite_dir / new_file_name
|
|
file.rename(new_file)
|
|
|
|
for suite in top_suites:
|
|
suite_name = suite.name
|
|
suite_dir = out_root / (safe_dir_name(suite_name) + f"_{run_date}")
|
|
suite_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
# One rebot run per suite:
|
|
# - filter with --suite
|
|
# - write output.xml/log.html/report.html into the suite folder
|
|
cmd = [
|
|
"rebot",
|
|
"--nostatusrc",
|
|
"--suite",
|
|
suite_name,
|
|
"--outputdir",
|
|
str(suite_dir),
|
|
"--output",
|
|
f"{suite_name}_{run_date}_output.xml",
|
|
"--log",
|
|
f"{suite_name}_{run_date}_log.html",
|
|
"--report",
|
|
f"{suite_name}_{run_date}_report.html",
|
|
str(input_xml),
|
|
]
|
|
|
|
print(f"{GREEN}{suite_name}{RESET} -> {suite_dir}")
|
|
subprocess.run(cmd, check=True)
|
|
|
|
print(f"{GREEN}Merged results under:{RESET} {input_xml.parent}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|