Commit c2d095f4 authored by Victor Stinner's avatar Victor Stinner

test_os: cleanup test_internal_execvpe() and os._execvpe() mockup

 * Replace os.defpath instead of os.get_exec_path() to test also
   os.get_exec_path()
 * Use contextlib.contextmanager, move the mockup outside the class, and
   the mockup returns directly the call list object
 * Use two different contexts for the two tests
 * Use more revelant values and names
parent 30474063
...@@ -12,6 +12,7 @@ import subprocess ...@@ -12,6 +12,7 @@ import subprocess
import time import time
import shutil import shutil
from test import support from test import support
import contextlib
# Detect whether we're on a Linux system that uses the (now outdated # Detect whether we're on a Linux system that uses the (now outdated
# and unmaintained) linuxthreads threading library. There's an issue # and unmaintained) linuxthreads threading library. There's an issue
...@@ -623,67 +624,71 @@ class URandomTests(unittest.TestCase): ...@@ -623,67 +624,71 @@ class URandomTests(unittest.TestCase):
except NotImplementedError: except NotImplementedError:
pass pass
class ExecTests(unittest.TestCase): @contextlib.contextmanager
@unittest.skipIf(USING_LINUXTHREADS, def _execvpe_mockup(defpath=None):
"avoid triggering a linuxthreads bug: see issue #4970")
def test_execvpe_with_bad_program(self):
self.assertRaises(OSError, os.execvpe, 'no such app-',
['no such app-'], None)
def test_execvpe_with_bad_arglist(self):
self.assertRaises(ValueError, os.execvpe, 'notepad', [], None)
class _stub_out_for_execvpe_test(object):
""" """
Stubs out execv, execve and get_exec_path functions when Stubs out execv and execve functions when used as context manager.
used as context manager. Records exec calls. The mock execv Records exec calls. The mock execv and execve functions always raise an
and execve functions always raise an exception as they would exception as they would normally never return.
normally never return.
""" """
def __init__(self):
# A list of tuples containing (function name, first arg, args) # A list of tuples containing (function name, first arg, args)
# of calls to execv or execve that have been made. # of calls to execv or execve that have been made.
self.calls = [] calls = []
def _mock_execv(self, name, *args):
self.calls.append(('execv', name, args)) def mock_execv(name, *args):
calls.append(('execv', name, args))
raise RuntimeError("execv called") raise RuntimeError("execv called")
def _mock_execve(self, name, *args): def mock_execve(name, *args):
self.calls.append(('execve', name, args)) calls.append(('execve', name, args))
raise OSError(errno.ENOTDIR, "execve called") raise OSError(errno.ENOTDIR, "execve called")
def _mock_get_exec_path(self, env=None): try:
return [os.sep+'p', os.sep+'pp'] orig_execv = os.execv
orig_execve = os.execve
orig_defpath = os.defpath
os.execv = mock_execv
os.execve = mock_execve
if defpath is not None:
os.defpath = defpath
yield calls
finally:
os.execv = orig_execv
os.execve = orig_execve
os.defpath = orig_defpath
def __enter__(self): class ExecTests(unittest.TestCase):
self.orig_execv = os.execv @unittest.skipIf(USING_LINUXTHREADS,
self.orig_execve = os.execve "avoid triggering a linuxthreads bug: see issue #4970")
self.orig_get_exec_path = os.get_exec_path def test_execvpe_with_bad_program(self):
os.execv = self._mock_execv self.assertRaises(OSError, os.execvpe, 'no such app-',
os.execve = self._mock_execve ['no such app-'], None)
os.get_exec_path = self._mock_get_exec_path
def __exit__(self, type, value, tb): def test_execvpe_with_bad_arglist(self):
os.execv = self.orig_execv self.assertRaises(ValueError, os.execvpe, 'notepad', [], None)
os.execve = self.orig_execve
os.get_exec_path = self.orig_get_exec_path
@unittest.skipUnless(hasattr(os, '_execvpe'), @unittest.skipUnless(hasattr(os, '_execvpe'),
"No internal os._execvpe function to test.") "No internal os._execvpe function to test.")
def test_internal_execvpe(self): def test_internal_execvpe(self):
exec_stubbed = self._stub_out_for_execvpe_test() program_path = os.sep+'absolutepath'
with exec_stubbed: program = 'executable'
self.assertRaises(RuntimeError, os._execvpe, os.sep+'f', ['-a']) fullpath = os.path.join(program_path, program)
self.assertEqual([('execv', os.sep+'f', (['-a'],))], arguments = ['progname', 'arg1', 'arg2']
exec_stubbed.calls) env = {'spam': 'beans'}
exec_stubbed.calls = []
self.assertRaises(OSError, os._execvpe, 'f', ['-a'], with _execvpe_mockup() as calls:
env={'spam': 'beans'}) self.assertRaises(RuntimeError, os._execvpe, fullpath, arguments)
self.assertEqual([('execve', os.sep+'p'+os.sep+'f', self.assertEqual(len(calls), 1)
(['-a'], {'spam': 'beans'})), self.assertEqual(calls[0], ('execv', fullpath, (arguments,)))
('execve', os.sep+'pp'+os.sep+'f',
(['-a'], {'spam': 'beans'}))], with _execvpe_mockup(defpath=program_path) as calls:
exec_stubbed.calls) self.assertRaises(OSError, os._execvpe, program, arguments, env=env)
self.assertEqual(len(calls), 1)
if os.name != "nt":
self.assertEqual(calls[0], ('execve', os.fsencode(fullpath), (arguments, env)))
else:
self.assertEqual(calls[0], ('execve', fullpath, (arguments, env)))
class Win32ErrorTests(unittest.TestCase): class Win32ErrorTests(unittest.TestCase):
def test_rename(self): def test_rename(self):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment