diff --git a/.github/workflows/cross-build.yml b/.github/workflows/cross-build.yml new file mode 100644 index 00000000000000..9a95f33c179b8f --- /dev/null +++ b/.github/workflows/cross-build.yml @@ -0,0 +1,44 @@ +name: Cross-Builds + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + cross-build: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.x' + + - name: Install dependencies + run: sudo apt-get install -y build-essential + + - name: Build host Python + run: | + ./configure --prefix=$PWD/workdir/host-python + make -j4 + make install + + - name: Configure cross-build + run: | + ./configure --with-build-python=$PWD/workdir/host-python/bin/python --prefix=$PWD/workdir/cross-python + make -j4 + + - name: Run tests in build directory + run: ./python -m test test_sysconfig test_site test_embed + + - name: Install cross-build + run: make install + + - name: Run tests with installed Python + run: $PWD/workdir/cross-python/bin/python -m test test_sysconfig test_site test_embed diff --git a/.github/workflows/jit.yml b/.github/workflows/jit.yml index 7dbbe71b2131e7..c6b18cb68fa64e 100644 --- a/.github/workflows/jit.yml +++ b/.github/workflows/jit.yml @@ -167,3 +167,38 @@ jobs: - name: Run tests run: | ./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3 + + cross-build: + name: Cross-Builds + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.x' + + - name: Install dependencies + run: sudo apt-get install -y build-essential + + - name: Build host Python + run: | + ./configure --prefix=$PWD/workdir/host-python + make -j4 + make install + + - name: Configure cross-build + run: | + ./configure --with-build-python=$PWD/workdir/host-python/bin/python --prefix=$PWD/workdir/cross-python + make -j4 + + - name: Run tests in build directory + run: ./python -m test test_sysconfig test_site test_embed + + - name: Install cross-build + run: make install + + - name: Run tests with installed Python + run: $PWD/workdir/cross-python/bin/python -m test test_sysconfig test_site test_embed diff --git a/Lib/test/test_dependencies.py b/Lib/test/test_dependencies.py new file mode 100644 index 00000000000000..4a22cf236bbd3b --- /dev/null +++ b/Lib/test/test_dependencies.py @@ -0,0 +1,36 @@ +import unittest +import os +import sys + +class TestDependencies(unittest.TestCase): + + def test_pyvenv_cfg_exists(self): + venv_path = os.path.join(sys.prefix, 'pyvenv.cfg') + self.assertTrue(os.path.exists(venv_path), f"{venv_path} does not exist") + + def test_shared_memory_access(self): + try: + import multiprocessing.shared_memory + except ImportError: + self.fail("multiprocessing.shared_memory module is not available") + + def test_ssl_module(self): + try: + import ssl + except ImportError: + self.fail("ssl module is not available") + + def test_pdb_module(self): + try: + import pdb + except ImportError: + self.fail("pdb module is not available") + + def test_warnings_module(self): + try: + import warnings + except ImportError: + self.fail("warnings module is not available") + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index 5c38b28322deb4..8c678e94ecb1e3 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -505,6 +505,30 @@ def test_getargs_reset_static_parser(self): out, err = self.run_embedded_interpreter("test_repeated_init_exec", code) self.assertEqual(out, '1\n2\n3\n' * INIT_LOOPS) + def test_cross_build(self): + # Build a host Python + host_build_dir = tempfile.mkdtemp() + host_install_dir = os.path.join(host_build_dir, 'host-python') + subprocess.run(['./configure', f'--prefix={host_install_dir}'], check=True) + subprocess.run(['make', 'install'], check=True) + + # Configure a new build using --with-build-python + cross_build_dir = tempfile.mkdtemp() + cross_install_dir = os.path.join(cross_build_dir, 'cross-python') + build_python = os.path.join(host_install_dir, 'bin', 'python') + subprocess.run(['./configure', f'--with-build-python={build_python}', f'--prefix={cross_install_dir}'], check=True) + subprocess.run(['make'], check=True) + + # Run the tests in the build directory + subprocess.run([os.path.join(cross_build_dir, 'python'), '-m', 'test', 'test_sysconfig', 'test_site', 'test_embed'], check=True) + + # Install the cross-build + subprocess.run(['make', 'install'], check=True) + + # Run the tests again with the installed Python + installed_python = os.path.join(cross_install_dir, 'bin', 'python') + subprocess.run([installed_python, '-m', 'test', 'test_sysconfig', 'test_site', 'test_embed'], check=True) + def config_dev_mode(preconfig, config): preconfig['allocator'] = PYMEM_ALLOCATOR_DEBUG diff --git a/Lib/test/test_multiprocessing_forkserver.py b/Lib/test/test_multiprocessing_forkserver.py new file mode 100644 index 00000000000000..16afa54091c18a --- /dev/null +++ b/Lib/test/test_multiprocessing_forkserver.py @@ -0,0 +1,48 @@ +import unittest +import multiprocessing +import os +import signal +import time + +class TestForkserver(unittest.TestCase): + + def setUp(self): + self.manager = multiprocessing.Manager() + self.shared_dict = self.manager.dict() + + def tearDown(self): + self.manager.shutdown() + + def test_shared_memory_access(self): + def worker(shared_dict): + shared_dict['key'] = 'value' + + process = multiprocessing.Process(target=worker, args=(self.shared_dict,)) + process.start() + process.join() + + self.assertEqual(self.shared_dict['key'], 'value') + + def test_forkserver_process_return_code(self): + def worker(): + os._exit(1) + + process = multiprocessing.Process(target=worker) + process.start() + process.join() + + self.assertEqual(process.exitcode, 1) + + def test_forkserver_signal_handling(self): + def worker(): + time.sleep(5) + + process = multiprocessing.Process(target=worker) + process.start() + os.kill(process.pid, signal.SIGTERM) + process.join() + + self.assertEqual(process.exitcode, -signal.SIGTERM) + +if __name__ == '__main__': + unittest.main()