2022-05-02 14:09:22 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								# gh-91321: Build a basic C++ test extension to check that the Python C API is
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								# compatible with C++ and does not emit C++ compiler warnings.
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-13 00:20:13 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								import os.path
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-19 15:03:27 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								import shlex
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-12 23:17:36 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								import shutil
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-13 00:20:13 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								import subprocess
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-19 15:03:27 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								import unittest
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-02 14:09:22 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from test import support
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-08-22 20:30:18 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								SOURCE = os.path.join(os.path.dirname(__file__), 'extension.cpp')
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								SETUP = os.path.join(os.path.dirname(__file__), 'setup.py')
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-02 14:09:22 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-19 15:03:27 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								# With MSVC on a debug build, the linker fails with: cannot open file
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								# 'python311.lib', it should look 'python311_d.lib'.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								@unittest.skipIf(support.MS_WINDOWS and support.Py_DEBUG,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                 'test fails on Windows debug build')
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-19 00:14:29 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								# Building and running an extension in clang sanitizing mode is not
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								# straightforward
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								@support.skip_if_sanitizer('test does not work with analyzing builds',
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                           address=True, memory=True, ub=True, thread=True)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								# the test uses venv+pip: skip if it's not available
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								@support.requires_venv_with_pip()
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-06 00:08:43 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								@support.requires_subprocess()
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-19 00:14:29 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								@support.requires_resource('cpu')
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-02 14:09:22 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								class TestCPPExt(unittest.TestCase):
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-19 15:03:27 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def test_build(self):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.check_build('_testcppext')
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-14 11:43:08 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def test_build_cpp03(self):
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-19 15:03:27 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.check_build('_testcpp03ext', std='c++03')
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    @unittest.skipIf(support.MS_WINDOWS, "MSVC doesn't support /std:c++11")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def test_build_cpp11(self):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.check_build('_testcpp11ext', std='c++11')
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-19 22:58:13 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # Only test C++14 on MSVC.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # On s390x RHEL7, GCC 4.8.5 doesn't support C++14.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    @unittest.skipIf(not support.MS_WINDOWS, "need Windows")
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-19 15:03:27 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def test_build_cpp14(self):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.check_build('_testcpp14ext', std='c++14')
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-14 11:43:08 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-19 15:03:27 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def check_build(self, extension_name, std=None):
							 | 
						
					
						
							
								
									
										
										
										
											2023-05-26 15:32:03 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        venv_dir = 'env'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        with support.setup_venv_with_pip_setuptools_wheel(venv_dir) as python_exe:
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-19 15:03:27 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            self._check_build(extension_name, python_exe, std=std)
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-13 00:20:13 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-19 15:03:27 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def _check_build(self, extension_name, python_exe, std):
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-12 23:17:36 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        pkg_dir = 'pkg'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        os.mkdir(pkg_dir)
							 | 
						
					
						
							
								
									
										
										
										
											2023-08-22 20:30:18 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        shutil.copy(SETUP, os.path.join(pkg_dir, os.path.basename(SETUP)))
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        shutil.copy(SOURCE, os.path.join(pkg_dir, os.path.basename(SOURCE)))
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-12 23:17:36 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-12 17:06:05 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        def run_cmd(operation, cmd):
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-12 23:17:36 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            env = os.environ.copy()
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-19 15:03:27 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            if std:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                env['CPYTHON_TEST_CPP_STD'] = std
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-12 23:17:36 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            env['CPYTHON_TEST_EXT_NAME'] = extension_name
							 | 
						
					
						
							
								
									
										
										
										
											2023-05-26 15:32:03 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            if support.verbose:
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-19 15:03:27 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                print('Run:', ' '.join(map(shlex.quote, cmd)))
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-12 23:17:36 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                subprocess.run(cmd, check=True, env=env)
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-12 17:06:05 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                proc = subprocess.run(cmd,
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-12 23:17:36 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                                      env=env,
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-12 17:06:05 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                                      stdout=subprocess.PIPE,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                      stderr=subprocess.STDOUT,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                      text=True)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if proc.returncode:
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-19 15:03:27 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    print('Run:', ' '.join(map(shlex.quote, cmd)))
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-12 17:06:05 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    print(proc.stdout, end='')
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    self.fail(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        f"{operation} failed with exit code {proc.returncode}")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-12 23:17:36 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        # Build and install the C++ extension
							 | 
						
					
						
							
								
									
										
										
										
											2023-05-26 15:32:03 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        cmd = [python_exe, '-X', 'dev',
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-12 23:17:36 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								               '-m', 'pip', 'install', '--no-build-isolation',
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								               os.path.abspath(pkg_dir)]
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-12 17:06:05 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        run_cmd('Install', cmd)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # Do a reference run. Until we test that running python
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # doesn't leak references (gh-94755), run it so one can manually check
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # -X showrefcount results against this baseline.
							 | 
						
					
						
							
								
									
										
										
										
											2023-05-26 15:32:03 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        cmd = [python_exe,
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-12 17:06:05 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								               '-X', 'dev',
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								               '-X', 'showrefcount',
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								               '-c', 'pass']
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        run_cmd('Reference run', cmd)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # Import the C++ extension
							 | 
						
					
						
							
								
									
										
										
										
											2023-05-26 15:32:03 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        cmd = [python_exe,
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-12 17:06:05 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								               '-X', 'dev',
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								               '-X', 'showrefcount',
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								               '-c', f"import {extension_name}"]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        run_cmd('Import', cmd)
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-02 14:09:22 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								if __name__ == "__main__":
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    unittest.main()
							 |