mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-28 00:35:47 +00:00
102 lines
5.9 KiB
Python
102 lines
5.9 KiB
Python
import os
|
|
import shlex
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
|
import check_compile
|
|
|
|
|
|
class CheckCompilePreprocessorTests(unittest.TestCase):
|
|
def test_forwarded_dependencies_preserve_outputs_and_compiler_errors(self):
|
|
self.check_forwarded_dependencies(shutil.which("clang") or shutil.which("gcc"), ("-MD", "-MMD"))
|
|
|
|
def test_gcc_dependency_aliases_preserve_outputs_and_compiler_errors(self):
|
|
compiler = shutil.which("gcc")
|
|
if compiler is not None:
|
|
version = subprocess.run([compiler, "--version"], capture_output=True, text=True)
|
|
if "clang" in version.stdout.lower():
|
|
self.skipTest("GCC dependency aliases are not supported by Clang")
|
|
self.check_forwarded_dependencies(compiler, ("--write-dependencies", "--write-user-dependencies"))
|
|
|
|
def check_forwarded_dependencies(self, compiler, options):
|
|
if compiler is None:
|
|
self.skipTest("needs a C compiler")
|
|
with tempfile.TemporaryDirectory(prefix="syntax check ") as folder:
|
|
root = Path(folder).resolve()
|
|
source = root / "unit source.c"
|
|
dependency = root / "unit deps.d"
|
|
object_file = root / "unit.o"
|
|
valid = "#ifndef REQUIRED\n#error lost_preprocessor_definition\n#endif\nint value;\n"
|
|
for option in options:
|
|
for field in ("arguments", "command"):
|
|
with self.subTest(option=option, field=field):
|
|
source.write_text(valid, encoding="utf-8")
|
|
forwarded = [f"-Wp,{option},{dependency}", "-Wp,-DREQUIRED,-MP,-MT,custom_target,-UUNUSED"]
|
|
arguments = [compiler, "-Werror", "-c", str(source), *forwarded, "-o", str(object_file)]
|
|
original = subprocess.run(arguments, cwd=root, capture_output=True, text=True)
|
|
self.assertEqual(original.returncode, 0, original.stderr)
|
|
preserved = {path: path.read_bytes() for path in (dependency, object_file)}
|
|
command = (subprocess.list2cmdline(arguments) if os.name == "nt" else
|
|
" ".join(shlex.quote(argument) for argument in arguments))
|
|
entry = {"directory": str(root), "file": str(source),
|
|
field: arguments if field == "arguments" else command}
|
|
for text, failures in ((valid, 0), (valid + "#error syntax_check_must_fail\n", 1)):
|
|
source.write_text(text, encoding="utf-8")
|
|
checked, failed, diagnostics = check_compile.check_source(
|
|
(source, source.name, root, [entry]))
|
|
self.assertEqual((checked, failed), (1, failures), diagnostics)
|
|
if failures:
|
|
self.assertIn("syntax_check_must_fail", diagnostics)
|
|
for path, content in preserved.items():
|
|
self.assertEqual(path.read_bytes(), content, str(path))
|
|
self.assertEqual(set(root.iterdir()), {source, dependency, object_file})
|
|
dependency.unlink()
|
|
object_file.unlink()
|
|
source.write_text(valid, encoding="utf-8")
|
|
self.assertEqual(check_compile.check_source((source, source.name, root, [entry]))[:2], (1, 0))
|
|
self.assertEqual(set(root.iterdir()), {source})
|
|
|
|
def test_dependency_only_arguments_are_removed(self):
|
|
source = Path("unit.c").resolve()
|
|
flags = ["-Wp,-MD,unit.d", "-Wp,-MMD,unit.d,-MP", "-Wp,-MF,unit.d,-MT,target,-MQ,quoted",
|
|
"-Wp,-MFunit.d,-MTtarget,-MQquoted", "-Wp,-M,-MM,-MG,-MP",
|
|
"-Wp,--write-dependencies,unit.d,--dependencies,--user-dependencies,--print-missing-file-dependencies",
|
|
"-Wp,--write-user-dependencies,unit.d"]
|
|
for flag in flags:
|
|
with self.subTest(flag=flag):
|
|
self.assertEqual(check_compile.syntax_arguments(["cc", flag, "-c", str(source)], Path.cwd(), source),
|
|
["cc", "-fsyntax-only", str(source)])
|
|
|
|
def test_other_preprocessor_arguments_are_preserved(self):
|
|
source = Path("unit.c").resolve()
|
|
for flag, expected in (("-Wp,-DNAME=value,-MD,unit.d,-I,include files", "-Wp,-DNAME=value,-I,include files"),
|
|
("-Wp,-include,-MD,-MMD,unit.d", "-Wp,-include,-MD"),
|
|
("-Wp,--include,-MD,--write-dependencies,unit.d", "-Wp,--include,-MD")):
|
|
with self.subTest(flag=flag):
|
|
self.assertEqual(check_compile.syntax_arguments(["cc", flag, str(source)], Path.cwd(), source),
|
|
["cc", "-fsyntax-only", expected, str(source)])
|
|
|
|
def test_unsupported_options_and_response_operands_are_still_rejected(self):
|
|
source = Path("unit.c").resolve()
|
|
for flag in ("-Wp,-unknown-option", "-Wp,-MD,unit.d,-E", "-Wp,-MD,unit.d,-I,@operand.rsp",
|
|
"-Wp,-MD,@operand.rsp"):
|
|
with self.subTest(flag=flag):
|
|
with self.assertRaisesRegex(ValueError, "unsupported forwarded compiler option"):
|
|
check_compile.syntax_arguments(["cc", flag, str(source)], Path.cwd(), source)
|
|
|
|
def test_missing_dependency_values_are_rejected(self):
|
|
source = Path("unit.c").resolve()
|
|
for option in ("-MD", "-MMD", "-MF", "-MT", "-MQ", "--write-dependencies", "--write-user-dependencies"):
|
|
with self.subTest(option=option):
|
|
with self.assertRaisesRegex(ValueError, "missing value"):
|
|
check_compile.syntax_arguments(["cc", f"-Wp,{option}", str(source)], Path.cwd(), source)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|