test_driver.py: Modify test driver files in a single pass

Signed-off-by: Ronald Cron <[email protected]>
This commit is contained in:
Ronald Cron
2025-12-09 01:04:25 +01:00
parent c5384feb27
commit a09ed59b15
+27 -43
View File
@@ -164,32 +164,25 @@ 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")
# Clone the source tree into `dst_dir`
for file in self.__iter_src_code_files(): for file in self.__iter_src_code_files():
dst = self.dst_dir / \ dst = self.dst_dir / \
self.__get_dst_relpath(file.relative_to(self.src_dir)) self.__get_dst_relpath(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)
# Modify the test driver files
test_driver_include_dir = self.dst_dir / "include" / self.driver test_driver_include_dir = self.dst_dir / "include" / self.driver
headers = { headers = {
f.relative_to(test_driver_include_dir).as_posix() \ f.relative_to(test_driver_include_dir).as_posix() \
for f in test_driver_include_dir.rglob("*.h") for f in test_driver_include_dir.rglob("*.h")
} }
for f in self.__iter_code_files(self.dst_dir):
self.__rewrite_inclusions_in_file(f, headers, \
src_include_dir_name, self.driver)
identifiers_to_prefix = self.get_identifiers_to_prefix(prefixes) identifiers_to_prefix = self.get_identifiers_to_prefix(prefixes)
self.__prefix_identifiers(identifiers_to_prefix)
def __prefix_identifiers(self, identifiers_to_prefix: Set[str]):
"""
In all test driver files, prefix each identifier in `identifiers_to_prefix`
with the test driver prefix: <DRIVER>_ for uppercase identifiers,
and <driver>_ for lowercase ones.
"""
for f in self.__iter_code_files(self.dst_dir): for f in self.__iter_code_files(self.dst_dir):
self.__prefix_identifiers_in_file(f, identifiers_to_prefix, self.driver) self.__rewrite_test_driver_file(f, headers,\
src_include_dir_name,
identifiers_to_prefix, self.driver)
@staticmethod @staticmethod
def __iter_code_files(root: Path) -> Iterable[Path]: def __iter_code_files(root: Path) -> Iterable[Path]:
@@ -264,57 +257,48 @@ class TestDriverGenerator:
return identifiers return identifiers
@staticmethod @staticmethod
def __rewrite_inclusions_in_file(file: Path, headers: Set[str], def __rewrite_test_driver_file(file: Path, headers: Set[str],
src_include_dir: str, driver: str,) -> None: src_include_dir: str,
identifiers_to_prefix: Set[str],
driver: str) -> None:
""" """
Rewrite `#include` directives in `file` that refer to `src_include_dir/...` Rewrite a test driver file:
so that they instead refer to `driver/...`. 1) Rewrite `#include` directives in `file` that refer to `src_include_dir/...`
so that they instead refer to `driver/...`.
For example: For example:
#include "mbedtls/private/aes.h" #include "mbedtls/private/aes.h"
becomes: becomes:
#include "libtestdriver1/private/aes.h" #include "libtestdriver1/private/aes.h"
2) Prefix each identifier in `identifiers` with the uppercase
form of `driver` if the identifier is uppercase, or with the lowercase
form of `driver` otherwise.
""" """
text = file.read_text(encoding="utf-8")
include_line_re = re.compile( include_line_re = re.compile(
fr'^\s*#\s*include\s*([<"])\s*{src_include_dir}/([^>"]+)\s*([>"])', fr'^\s*#\s*include\s*([<"])\s*{src_include_dir}/([^>"]+)\s*([>"])',
re.MULTILINE re.MULTILINE
) )
text = file.read_text(encoding="utf-8") def repl_header_inclusion(m: Match) -> str:
changed = False
def repl(m: Match) -> str:
nonlocal changed
header = m.group(2) header = m.group(2)
if header in headers: if header in headers:
changed = True
return f'#include {m.group(1)}{driver}/{header}{m.group(3)}' return f'#include {m.group(1)}{driver}/{header}{m.group(3)}'
return m.group(0) return m.group(0)
intermediate_text = include_line_re.sub(repl_header_inclusion, text)
new_text = include_line_re.sub(repl, text)
if changed:
file.write_text(new_text, encoding="utf-8")
@staticmethod
def __prefix_identifiers_in_file(file: Path, identifiers: Set[str], \
prefix: str) -> None:
"""
In `file`, prefix each identifier in `identifiers` with the uppercase
form of `prefix` if the identifier is uppercase, or with the lowercase
form of `prefix` otherwise.
"""
c_identifier_re = re.compile(r"\b[A-Za-z_][A-Za-z0-9_]*\b") c_identifier_re = re.compile(r"\b[A-Za-z_][A-Za-z0-9_]*\b")
text = file.read_text(encoding="utf-8") prefix_uppercased = driver.upper()
prefix_uppercased = prefix.upper() prefix_lowercased = driver.lower()
prefix_lowercased = prefix.lower()
def repl(m: Match) -> str: def repl(m: Match) -> str:
identifier = m.group(0) identifier = m.group(0)
if identifier in identifiers: if identifier in identifiers_to_prefix:
if identifier[0].isupper(): if identifier[0].isupper():
return f"{prefix_uppercased}_{identifier}" return f"{prefix_uppercased}_{identifier}"
else: else:
return f"{prefix_lowercased}_{identifier}" return f"{prefix_lowercased}_{identifier}"
return identifier return identifier
new_text = c_identifier_re.sub(repl, text) new_text = c_identifier_re.sub(repl, intermediate_text)
file.write_text(new_text, encoding="utf-8") file.write_text(new_text, encoding="utf-8")