sTodo-m5paper-client/libraries/FastLED/ci/tests/test_no_banned_headers.py
2025-06-30 21:41:49 +02:00

181 lines
4.9 KiB
Python

import os
import unittest
from typing import Callable, List
from ci.check_files import (
EXCLUDED_FILES,
FileContent,
FileContentChecker,
MultiCheckerFileProcessor,
collect_files_to_check,
)
from ci.paths import PROJECT_ROOT
SRC_ROOT = PROJECT_ROOT / "src"
ENABLE_PARANOID_GNU_HEADER_INSPECTION = False
if ENABLE_PARANOID_GNU_HEADER_INSPECTION:
BANNED_HEADERS_ESP = ["esp32-hal.h"]
else:
BANNED_HEADERS_ESP = []
BANNED_HEADERS_COMMON = [
"assert.h",
"iostream",
"stdio.h",
"cstdio",
"cstdlib",
"vector",
"list",
"map",
"set",
"queue",
"deque",
"algorithm",
"memory",
"thread",
"mutex",
"chrono",
"fstream",
"sstream",
"iomanip",
"exception",
"stdexcept",
"typeinfo",
"ctime",
"cmath",
"complex",
"valarray",
"cfloat",
"cassert",
"cerrno",
"cctype",
"cwctype",
"cstring",
"cwchar",
"cuchar",
"cstdint",
"cstddef", # this certainally fails
"type_traits", # this certainally fails
]
BANNED_HEADERS_CORE = BANNED_HEADERS_COMMON + BANNED_HEADERS_ESP + ["Arduino.h"]
class BannedHeadersChecker(FileContentChecker):
"""Checker class for banned headers."""
def __init__(self, banned_headers_list: List[str]):
"""Initialize with the list of banned headers to check for."""
self.banned_headers_list = banned_headers_list
def should_process_file(self, file_path: str) -> bool:
"""Check if file should be processed for banned headers."""
# Check file extension
if not file_path.endswith((".cpp", ".h", ".hpp", ".ino")):
return False
# Check if file is in excluded list
if any(file_path.endswith(excluded) for excluded in EXCLUDED_FILES):
return False
return True
def check_file_content(self, file_content: FileContent) -> List[str]:
"""Check file content for banned headers."""
failings = []
if len(self.banned_headers_list) == 0:
return failings
# Check each line for banned headers
for line_number, line in enumerate(file_content.lines, 1):
if line.strip().startswith("//"):
continue
for header in self.banned_headers_list:
if (
f"#include <{header}>" in line or f'#include "{header}"' in line
) and "// ok include" not in line:
failings.append(
f"Found banned header '{header}' in {file_content.path}:{line_number}"
)
return failings
def _test_no_banned_headers(
test_directories: list[str],
banned_headers_list: List[str],
on_fail: Callable[[str], None],
) -> None:
"""Searches through the program files to check for banned headers."""
# Collect files to check
files_to_check = collect_files_to_check(test_directories)
# Create processor and checker
processor = MultiCheckerFileProcessor()
checker = BannedHeadersChecker(banned_headers_list)
# Process files
results = processor.process_files_with_checkers(files_to_check, [checker])
# Get results for banned headers checker
all_failings = results.get("BannedHeadersChecker", []) or []
if all_failings:
msg = f"Found {len(all_failings)} banned header(s): \n" + "\n".join(
all_failings
)
for failing in all_failings:
print(failing)
on_fail(msg)
else:
print("No banned headers found.")
class TestNoBannedHeaders(unittest.TestCase):
def test_no_banned_headers_src(self) -> None:
"""Searches through the program files to check for banned headers."""
def on_fail(msg: str) -> None:
self.fail(
msg + "\n"
"You can add '// ok include' at the end of the line to silence this error for specific inclusions."
)
# Test directories as requested
test_directories = [
os.path.join(SRC_ROOT, "fl"),
os.path.join(SRC_ROOT, "fx"),
os.path.join(SRC_ROOT, "sensors"),
]
_test_no_banned_headers(
test_directories=test_directories,
banned_headers_list=BANNED_HEADERS_CORE,
on_fail=on_fail,
)
def test_no_banned_headers_examples(self) -> None:
"""Searches through the program files to check for banned headers."""
def on_fail(msg: str) -> None:
self.fail(
msg + "\n"
"You can add '// ok include' at the end of the line to silence this error for specific inclusions."
)
test_directories = ["examples"]
_test_no_banned_headers(
test_directories=test_directories,
banned_headers_list=BANNED_HEADERS_COMMON,
on_fail=on_fail,
)
if __name__ == "__main__":
unittest.main()