| """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") |