"""Test cases that run tests as subprocesses.""" from __future__ import annotations import os import subprocess import sys import tempfile import unittest from distutils import ccompiler, sysconfig from typing import Any from mypyc.build import get_cflags, include_dir from .config import PREFIX EXCLUDED_LIB_RT_COMPILE_FILES = ["static_data.c"] class TestExternal(unittest.TestCase): def test_lib_rt_c_files_compile_individually(self) -> None: """Compile each top-level lib-rt C file as its own translation unit.""" lib_rt_dir = include_dir() source_names = sorted( name for name in os.listdir(lib_rt_dir) if name.endswith(".c") and os.path.isfile(os.path.join(lib_rt_dir, name)) and name not in EXCLUDED_LIB_RT_COMPILE_FILES ) compiler: Any = ccompiler.new_compiler() sysconfig.customize_compiler(compiler) include_dirs = [lib_rt_dir] for plat_specific in (False, True): path = sysconfig.get_python_inc(plat_specific=plat_specific) if path and path not in include_dirs: include_dirs.append(path) with tempfile.TemporaryDirectory() as tmpdir: for experimental_features in (False, True): cflags = get_cflags( compiler_type=compiler.compiler_type, opt_level="0", experimental_features=experimental_features, ) output_dir = os.path.join( tmpdir, "experimental" if experimental_features else "default" ) for source_name in source_names: source_path = os.path.join(lib_rt_dir, source_name) with self.subTest(source=source_name, experimental=experimental_features): try: compiler.compile( [source_path], output_dir=output_dir, include_dirs=include_dirs, extra_postargs=cflags, ) except Exception as err: raise AssertionError( f"failed to compile {source_name} " f"(experimental={experimental_features})" ) from err # TODO: Get this to work on Windows. # (Or don't. It is probably not a good use of time.) @unittest.skipIf(sys.platform.startswith("win"), "rt tests don't work on windows") def test_c_unit_test(self) -> None: """Run C unit tests in a subprocess.""" cppflags: list[str] = [] env = os.environ.copy() if sys.platform == "darwin": cppflags += ["-O0", "-mmacosx-version-min=10.10", "-stdlib=libc++"] elif sys.platform == "linux": cppflags += ["-O0"] env["CPPFLAGS"] = " ".join(cppflags) # Build Python wrapper for C unit tests. with tempfile.TemporaryDirectory() as tmpdir: status = subprocess.check_call( [ sys.executable, "setup.py", "build_ext", f"--build-lib={tmpdir}", f"--build-temp={tmpdir}", "--run-capi-tests", ], env=env, cwd=os.path.join(PREFIX, "mypyc", "lib-rt"), ) # Run C unit tests. env = os.environ.copy() if "GTEST_COLOR" not in os.environ: env["GTEST_COLOR"] = "yes" # Use fancy colors status = subprocess.call( [sys.executable, "-c", "import sys, test_capi; sys.exit(test_capi.run_tests())"], env=env, cwd=tmpdir, ) if status != 0: raise AssertionError("make test: C unit test failure")