Checker class for test file path structure validation.
| 87 | |
| 88 | |
| 89 | class TestPathStructureChecker(FileContentChecker): |
| 90 | """Checker class for test file path structure validation.""" |
| 91 | |
| 92 | def __init__(self): |
| 93 | self.violations: dict[str, list[tuple[int, str]]] = {} |
| 94 | |
| 95 | def should_process_file(self, file_path: str) -> bool: |
| 96 | """Check if file should be processed for path structure validation.""" |
| 97 | # Only check files in tests directory |
| 98 | if not file_path.startswith(str(TESTS_ROOT)): |
| 99 | return False |
| 100 | |
| 101 | # Check .cpp and .hpp test files (sub-tests use .hpp extension) |
| 102 | if not file_path.endswith((".cpp", ".hpp")): |
| 103 | return False |
| 104 | |
| 105 | test_path = Path(file_path) |
| 106 | |
| 107 | # Skip excluded files (infrastructure/entry points) |
| 108 | if test_path.name in EXCLUDED_TEST_FILES: |
| 109 | return False |
| 110 | |
| 111 | # Skip tests/misc/ directory (these tests don't need to match source structure) |
| 112 | # Skip tests/profile/ directory (standalone performance benchmarks) |
| 113 | # Skip tests/shared/ directory (shared test infrastructure) |
| 114 | # Skip any test_utils/ directories (test utilities) |
| 115 | try: |
| 116 | rel_path = test_path.relative_to(TESTS_ROOT) |
| 117 | if rel_path.parts[0] in ("misc", "profile", "shared"): |
| 118 | return False |
| 119 | if "test_utils" in rel_path.parts: |
| 120 | return False |
| 121 | except (ValueError, IndexError): |
| 122 | pass |
| 123 | |
| 124 | # Skip files in EXCLUDED_TEST_DIRS (consolidated sub-test directories |
| 125 | # where .hpp files are #include'd from a parent .cpp test) |
| 126 | for excluded_dir in EXCLUDED_TEST_DIRS: |
| 127 | try: |
| 128 | test_path.relative_to(excluded_dir) |
| 129 | return False # File is inside an excluded test directory |
| 130 | except ValueError: |
| 131 | continue |
| 132 | |
| 133 | return True |
| 134 | |
| 135 | def check_file_content(self, file_content: FileContent) -> list[str]: |
| 136 | """Check if test file path matches the source file directory structure. |
| 137 | |
| 138 | Rule: tests/**/file.cpp must match src/**/file.h or src/**/file.hpp |
| 139 | Exception: Tests in tests/misc/ are exempt (don't need to match). |
| 140 | Exception: Tests with '// ok standalone' comment are exempt. |
| 141 | """ |
| 142 | test_path = Path(file_content.path) |
| 143 | |
| 144 | # Get the relative path from tests root: tests/fl/flat_map.cpp -> fl/flat_map |
| 145 | rel_from_tests = test_path.relative_to(TESTS_ROOT) |
| 146 | test_name_no_ext = rel_from_tests.with_suffix("") # Remove .cpp |
no outgoing calls