mirror of
https://github.com/Mbed-TLS/mbedtls-framework.git
synced 2026-10-14 04:37:22 +00:00
test_driver.py: Add support for the list-vars-for-cmake option
Signed-off-by: Ronald Cron <[email protected]>
This commit is contained in:
@@ -12,7 +12,7 @@ import subprocess
|
|||||||
|
|
||||||
from fnmatch import fnmatch
|
from fnmatch import fnmatch
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Iterable, Match, Optional, Set
|
from typing import Iterable, List, Match, Optional, Set
|
||||||
|
|
||||||
def get_parsearg_base() -> argparse.ArgumentParser:
|
def get_parsearg_base() -> argparse.ArgumentParser:
|
||||||
""" Get base arguments for scripts building a TF-PSA-Crypto test driver """
|
""" Get base arguments for scripts building a TF-PSA-Crypto test driver """
|
||||||
@@ -26,6 +26,11 @@ def get_parsearg_base() -> argparse.ArgumentParser:
|
|||||||
" - If relative, interpreted relative to the repository root.\n")
|
" - If relative, interpreted relative to the repository root.\n")
|
||||||
parser.add_argument("--driver", default="libtestdriver1", metavar="DRIVER",
|
parser.add_argument("--driver", default="libtestdriver1", metavar="DRIVER",
|
||||||
help="Test driver name (default: %(default)s).")
|
help="Test driver name (default: %(default)s).")
|
||||||
|
parser.add_argument('--list-vars-for-cmake', nargs="?", const="__AUTO__", metavar="FILE",
|
||||||
|
help="Generate a file to be included from a CMakeLists.txt.\n"
|
||||||
|
"The file defines CMake list variables with the script's\n"
|
||||||
|
"inputs/outputs files. If FILE is omitted, the output \n"
|
||||||
|
"name defaults to '<DRIVER>-list-vars.cmake'.")
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def iter_code_files(root: Path) -> Iterable[Path]:
|
def iter_code_files(root: Path) -> Iterable[Path]:
|
||||||
@@ -38,6 +43,40 @@ def iter_code_files(root: Path) -> Iterable[Path]:
|
|||||||
for ext in (".c", ".h"):
|
for ext in (".c", ".h"):
|
||||||
yield from directory_path.rglob(f"*{ext}")
|
yield from directory_path.rglob(f"*{ext}")
|
||||||
|
|
||||||
|
def get_src_relpaths(builtin: Path, exclude_files: Set[str]) -> List[Path]:
|
||||||
|
"""
|
||||||
|
Return the relative paths of all *.c and *.h files under `builtin`,
|
||||||
|
excluding those whose names match any of the patterns in `exclude_files`.
|
||||||
|
|
||||||
|
The returned paths are relative to `builtin`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
out = []
|
||||||
|
for file in iter_code_files(builtin):
|
||||||
|
if not any(fnmatch(file.name, pattern) for pattern in exclude_files):
|
||||||
|
out.append(file.relative_to(builtin))
|
||||||
|
out.sort()
|
||||||
|
return out
|
||||||
|
|
||||||
|
def get_dst_relpaths(src_relpaths: List[Path], driver: str) -> List[Path]:
|
||||||
|
"""
|
||||||
|
Return the relative paths of the *.c and *.h files generated by the script.
|
||||||
|
|
||||||
|
These paths are the same as in `src_relpaths`, except that occurrences of
|
||||||
|
`mbedtls` in `include/mbedtls/...` paths are replaced with `driver`.
|
||||||
|
|
||||||
|
The returned paths are relative to `dst_dir`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
out = []
|
||||||
|
for path in src_relpaths:
|
||||||
|
parts = list(path.parts)
|
||||||
|
if parts[0] == "include" and parts[1] == "mbedtls":
|
||||||
|
parts[1] = driver
|
||||||
|
out.append(Path(*parts))
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
def run_ctags(file: Path) -> Set[str]:
|
def run_ctags(file: Path) -> Set[str]:
|
||||||
"""
|
"""
|
||||||
Extract the C identifiers in `file` using ctags.
|
Extract the C identifiers in `file` using ctags.
|
||||||
@@ -71,20 +110,65 @@ def run_ctags(file: Path) -> Set[str]:
|
|||||||
|
|
||||||
class TestDriverGenerator:
|
class TestDriverGenerator:
|
||||||
"""A TF-PSA-Crypto test driver generator"""
|
"""A TF-PSA-Crypto test driver generator"""
|
||||||
def __init__(self, dst_dir: Path, driver: str):
|
def __init__(self, src_dir: Path, dst_dir: Path, driver: str, \
|
||||||
|
exclude_files: Optional[Set[str]] = None) -> None:
|
||||||
|
"""
|
||||||
|
Initialize a test driver generator.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
src_dir (Path):
|
||||||
|
Path to the source directory that contains the built-in driver.
|
||||||
|
If this path is relative, it should be relative to the repository
|
||||||
|
root so that the source paths returned by `write_list_vars_for_cmake`
|
||||||
|
are correct.
|
||||||
|
|
||||||
|
The source directory is expected to contain:
|
||||||
|
- an `include` directory
|
||||||
|
- an `src` directory
|
||||||
|
- the `include/` directory contains exactly one subdirectory
|
||||||
|
|
||||||
|
dst_dir (Path):
|
||||||
|
Path to the destination directory where the rewritten tree will
|
||||||
|
be created.
|
||||||
|
|
||||||
|
driver (str):
|
||||||
|
Name of the driver. This is used as a prefix when rewritting
|
||||||
|
the tree.
|
||||||
|
|
||||||
|
exclude_files (Optional[Set[str]]):
|
||||||
|
Glob patterns for the basename of the files to be excluded from
|
||||||
|
the source directory.
|
||||||
|
"""
|
||||||
|
self.src_dir = src_dir
|
||||||
self.dst_dir = dst_dir
|
self.dst_dir = dst_dir
|
||||||
self.driver = driver
|
self.driver = driver
|
||||||
|
self.exclude_files = set()
|
||||||
|
if exclude_files is not None:
|
||||||
|
self.exclude_files = exclude_files
|
||||||
# Path of 'dst_dir'/include/'driver'
|
# Path of 'dst_dir'/include/'driver'
|
||||||
self.test_driver_include_dir = None #type: Path | None
|
self.test_driver_include_dir = None #type: Path | None
|
||||||
|
|
||||||
def build_tree(self, src_dir: Path, exclude_files: Optional[Set[str]] = None) -> None:
|
if not (src_dir / "include").is_dir():
|
||||||
"""
|
raise RuntimeError(f'"include" directory in {src_dir} not found')
|
||||||
Build a test driver tree from `src_dir`.
|
|
||||||
|
|
||||||
The source directory `src_dir` is expected to have the following structure:
|
if not (src_dir / "src").is_dir():
|
||||||
- an `include` directory
|
raise RuntimeError(f'"src" directory in {src_dir} not found')
|
||||||
- an `src` directory
|
|
||||||
- the `include` directory contains exactly one subdirectory
|
def write_list_vars_for_cmake(self, fname: str) -> None:
|
||||||
|
src_relpaths = get_src_relpaths(self.src_dir, self.exclude_files)
|
||||||
|
with open(self.dst_dir / fname, "w") as f:
|
||||||
|
f.write(f"set({self.driver}_input_files " + \
|
||||||
|
" ".join(str(path) for path in src_relpaths) + ")\n\n")
|
||||||
|
f.write(f"set({self.driver}_files " + \
|
||||||
|
" ".join(str(path) \
|
||||||
|
for path in get_dst_relpaths(src_relpaths, self.driver)) + ")\n\n")
|
||||||
|
f.write(f"set({self.driver}_src_files " + \
|
||||||
|
" ".join(str(path) \
|
||||||
|
for path in src_relpaths if path.suffix == ".c") + ")")
|
||||||
|
|
||||||
|
def build_tree(self) -> None:
|
||||||
|
"""
|
||||||
|
Build a test driver tree from `self.src_dir`.
|
||||||
|
|
||||||
Only the `include` and `src` directories from `src_dir` are used to build
|
Only the `include` and `src` directories from `src_dir` are used to build
|
||||||
the test driver tree, and their directory structure is preserved.
|
the test driver tree, and their directory structure is preserved.
|
||||||
@@ -95,14 +179,9 @@ class TestDriverGenerator:
|
|||||||
The subdirectory inside `include` is renamed to `driver` in the test driver
|
The subdirectory inside `include` is renamed to `driver` in the test driver
|
||||||
tree, and header inclusions are adjusted accordingly.
|
tree, and header inclusions are adjusted accordingly.
|
||||||
"""
|
"""
|
||||||
include = src_dir / "include"
|
|
||||||
if not include.is_dir():
|
|
||||||
raise RuntimeError(f'Do not find "include" directory in {src_dir}')
|
|
||||||
|
|
||||||
src = src_dir / "src"
|
|
||||||
if not src.is_dir():
|
|
||||||
raise RuntimeError(f'Do not find "src" directory in {src_dir}')
|
|
||||||
|
|
||||||
|
include = self.src_dir / "include"
|
||||||
entries = list(include.iterdir())
|
entries = list(include.iterdir())
|
||||||
if len(entries) != 1 or not entries[0].is_dir():
|
if len(entries) != 1 or not entries[0].is_dir():
|
||||||
raise RuntimeError(f"Found more than one directory in {include}")
|
raise RuntimeError(f"Found more than one directory in {include}")
|
||||||
@@ -115,13 +194,10 @@ class TestDriverGenerator:
|
|||||||
if (self.dst_dir / "src").exists():
|
if (self.dst_dir / "src").exists():
|
||||||
shutil.rmtree(self.dst_dir / "src")
|
shutil.rmtree(self.dst_dir / "src")
|
||||||
|
|
||||||
if exclude_files is None:
|
for file in iter_code_files(self.src_dir):
|
||||||
exclude_files = set()
|
if any(fnmatch(file.name, pattern) for pattern in self.exclude_files):
|
||||||
|
|
||||||
for file in iter_code_files(src_dir):
|
|
||||||
if any(fnmatch(file.name, pattern) for pattern in exclude_files):
|
|
||||||
continue
|
continue
|
||||||
dst = self.dst_dir / file.relative_to(src_dir)
|
dst = self.dst_dir / file.relative_to(self.src_dir)
|
||||||
dst.parent.mkdir(parents=True, exist_ok=True)
|
dst.parent.mkdir(parents=True, exist_ok=True)
|
||||||
shutil.copy2(file, dst)
|
shutil.copy2(file, dst)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user