Skip to content

Commit d7dd72a

Browse files
committed
Test remote_exec with deleted static Python executable
1 parent 0430c62 commit d7dd72a

1 file changed

Lines changed: 55 additions & 2 deletions

File tree

Lib/test/test_sys.py

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1984,7 +1984,8 @@ def tearDown(self):
19841984
test.support.reap_children()
19851985

19861986
def _run_remote_exec_test(self, script_code, python_args=None, env=None,
1987-
prologue='', after_ready=None,
1987+
python_executable=None, prologue='',
1988+
after_ready=None,
19881989
script_path=os_helper.TESTFN + '_remote.py'):
19891990
# Create the script that will be remotely executed
19901991
self.addCleanup(os_helper.unlink, script_path)
@@ -2032,7 +2033,10 @@ def _run_remote_exec_test(self, script_code, python_args=None, env=None,
20322033
''')
20332034

20342035
# Start the target process and capture its output
2035-
cmd = [sys.executable]
2036+
if python_executable is None:
2037+
python_executable = sys.executable
2038+
2039+
cmd = [python_executable]
20362040
if python_args:
20372041
cmd.extend(python_args)
20382042
cmd.append(target)
@@ -2248,6 +2252,55 @@ def delete_loaded_libpython(proc):
22482252
self.assertIn(b"Remote script executed successfully!", stdout)
22492253
self.assertEqual(stderr, b"")
22502254

2255+
@unittest.skipUnless(sys.platform == 'linux', 'Linux-only regression test')
2256+
@unittest.skipUnless(
2257+
sysconfig.get_config_var('Py_ENABLE_SHARED') == 0,
2258+
'requires a static Python build')
2259+
def test_remote_exec_deleted_static_executable(self):
2260+
"""Test remote exec when the target static executable was deleted."""
2261+
build_dir = sysconfig.get_config_var('abs_builddir')
2262+
srcdir = sysconfig.get_config_var('srcdir')
2263+
if not build_dir or not srcdir:
2264+
self.skipTest('cannot determine build-tree locations')
2265+
2266+
pybuilddir_txt = os.path.join(build_dir, 'pybuilddir.txt')
2267+
if not os.path.exists(pybuilddir_txt):
2268+
self.skipTest(f'{pybuilddir_txt!r} does not exist')
2269+
2270+
with open(pybuilddir_txt, encoding='utf-8') as pybuilddir_file:
2271+
pybuilddir = pybuilddir_file.read().strip()
2272+
source_ext_dir = os.path.join(build_dir, pybuilddir)
2273+
if not os.path.isdir(source_ext_dir):
2274+
self.skipTest(f'{source_ext_dir!r} does not exist')
2275+
2276+
with os_helper.temp_dir() as copied_root:
2277+
copied_build_dir = os.path.join(copied_root, 'build')
2278+
copied_pybuilddir = os.path.join(copied_build_dir, pybuilddir)
2279+
os.makedirs(os.path.dirname(copied_pybuilddir))
2280+
os.symlink(os.path.join(srcdir, 'Lib'),
2281+
os.path.join(copied_root, 'Lib'))
2282+
os.symlink(source_ext_dir, copied_pybuilddir)
2283+
shutil.copy2(pybuilddir_txt,
2284+
os.path.join(copied_build_dir, 'pybuilddir.txt'))
2285+
2286+
copied_python = os.path.join(copied_build_dir,
2287+
os.path.basename(sys.executable))
2288+
shutil.copy2(sys.executable, copied_python)
2289+
2290+
def delete_loaded_executable(proc):
2291+
os_helper.unlink(copied_python)
2292+
with open(f'/proc/{proc.pid}/maps', encoding='utf-8') as maps:
2293+
self.assertIn(f'{copied_python} (deleted)',
2294+
maps.read())
2295+
2296+
script = 'print("Remote script executed successfully!")'
2297+
returncode, stdout, stderr = self._run_remote_exec_test(
2298+
script, python_args=['-S'], python_executable=copied_python,
2299+
after_ready=delete_loaded_executable)
2300+
self.assertEqual(returncode, 0)
2301+
self.assertIn(b"Remote script executed successfully!", stdout)
2302+
self.assertEqual(stderr, b"")
2303+
22512304
def test_remote_exec_in_process_without_debug_fails_envvar(self):
22522305
"""Test remote exec in a process without remote debugging enabled"""
22532306
script = os_helper.TESTFN + '_remote.py'

0 commit comments

Comments
 (0)