[pypy-svn] r49252 - in pypy/dist/pypy: module/posix module/posix/test rpython/module rpython/module/test
exarkun at codespeak.net
exarkun at codespeak.net
Sat Dec 1 18:05:47 CET 2007
Author: exarkun
Date: Sat Dec 1 18:05:46 2007
New Revision: 49252
Added:
pypy/dist/pypy/rpython/module/test/execve_tests.py
Modified:
pypy/dist/pypy/module/posix/__init__.py
pypy/dist/pypy/module/posix/test/test_posix2.py
pypy/dist/pypy/rpython/module/ll_os.py
pypy/dist/pypy/rpython/module/test/test_ll_os.py
Log:
llimpl for os.execve
Modified: pypy/dist/pypy/module/posix/__init__.py
==============================================================================
--- pypy/dist/pypy/module/posix/__init__.py (original)
+++ pypy/dist/pypy/module/posix/__init__.py Sat Dec 1 18:05:46 2007
@@ -75,7 +75,7 @@
interpleveldefs['waitpid'] = 'interp_posix.waitpid'
if hasattr(os, 'execv'):
interpleveldefs['execv'] = 'interp_posix.execv'
- if hasattr(os, 'execve') and 0: # XXX XXX in-progress
+ if hasattr(os, 'execve'):
interpleveldefs['execve'] = 'interp_posix.execve'
if False and hasattr(os, 'uname'):
interpleveldefs['uname'] = 'interp_posix.uname'
Modified: pypy/dist/pypy/module/posix/test/test_posix2.py
==============================================================================
--- pypy/dist/pypy/module/posix/test/test_posix2.py (original)
+++ pypy/dist/pypy/module/posix/test/test_posix2.py Sat Dec 1 18:05:46 2007
@@ -206,8 +206,9 @@
t([3, "a"])
def test_execve(self):
- skip("Not implemented")
os = self.posix
+ if not hasattr(os, "fork"):
+ skip("Need fork() to test execve()")
pid = os.fork()
if pid == 0:
os.execve("/usr/bin/env", ["env", "python", "-c", "import os; open('onefile', 'w').write(os.environ['ddd'])"], {'ddd':'xxx'})
Modified: pypy/dist/pypy/rpython/module/ll_os.py
==============================================================================
--- pypy/dist/pypy/rpython/module/ll_os.py (original)
+++ pypy/dist/pypy/rpython/module/ll_os.py Sat Dec 1 18:05:46 2007
@@ -137,6 +137,36 @@
return extdef([str, [str]], s_ImpossibleValue, llimpl=execv_llimpl,
export_name="ll_os.ll_os_execv")
+
+ @registering_if(os, 'execve')
+ def register_os_execve(self):
+ os_execve = self.llexternal(
+ 'execve', [rffi.CCHARP, rffi.CCHARPP, rffi.CCHARPP], rffi.INT)
+
+ def execve_llimpl(path, args, env):
+ # XXX Check path, args, env for \0 and raise TypeErrors as
+ # appropriate
+ envstrs = []
+ for item in env.iteritems():
+ envstrs.append("%s=%s" % item)
+
+ l_args = rffi.liststr2charpp(args)
+ l_env = rffi.liststr2charpp(envstrs)
+ os_execve(path, l_args, l_env)
+
+ # XXX untested
+ rffi.free_charpp(l_env)
+ rffi.free_charpp(l_args)
+
+ raise OSError(rposix.get_errno(), "execve failed")
+
+ return extdef(
+ [str, [str], {str: str}],
+ s_ImpossibleValue,
+ llimpl=execve_llimpl,
+ export_name="ll_os.ll_os_execve")
+
+
@registering_if(posix, 'spawnv')
def register_os_spawnv(self):
os_spawnv = self.llexternal('spawnv',
Added: pypy/dist/pypy/rpython/module/test/execve_tests.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/module/test/execve_tests.py Sat Dec 1 18:05:46 2007
@@ -0,0 +1,25 @@
+
+"""
+Functions which call the llimpl execve function with various arguments. Since
+execve replaces the process with a new one in the successful case, these are
+here to be run as a child process of the test process.
+"""
+
+import os, sys
+
+from pypy.rpython.module.test.test_ll_os import EXECVE_ENV, getllimpl
+
+execve = getllimpl(os.execve)
+
+
+def execve_true():
+ execve("/bin/true", ["/bin/true"], {})
+
+def execve_false():
+ execve("/bin/false", ["/bin/false"], {})
+
+def execve_env():
+ execve("/usr/bin/env", ["/usr/bin/env"], EXECVE_ENV)
+
+if __name__ == '__main__':
+ globals()[sys.argv[1]]()
Modified: pypy/dist/pypy/rpython/module/test/test_ll_os.py
==============================================================================
--- pypy/dist/pypy/rpython/module/test/test_ll_os.py (original)
+++ pypy/dist/pypy/rpython/module/test/test_ll_os.py Sat Dec 1 18:05:46 2007
@@ -1,8 +1,11 @@
import os
+from py.path import local
+
from pypy.tool.udir import udir
from pypy.translator.c.test.test_genc import compile
from pypy.rpython import extregistry
+import errno
import sys
import py
@@ -58,6 +61,43 @@
assert file(filename).read().strip() == '2'
os.unlink(filename)
+
+EXECVE_ENV = {"foo": "bar", "baz": "quux"}
+execve_tests = str(local(__file__).dirpath().join('execve_tests.py'))
+
+def test_execve():
+ if os.name != 'posix':
+ py.test.skip('posix specific function')
+ base = sys.executable + " " + execve_tests + " "
+
+ # Test exit status and code
+ result = os.system(base + "execve_true")
+ assert os.WIFEXITED(result)
+ assert os.WEXITSTATUS(result) == 0
+ result = os.system(base + "execve_false")
+ assert os.WIFEXITED(result)
+ assert os.WEXITSTATUS(result) == 1
+
+ # Test environment
+ result = os.popen(base + "execve_env").read()
+ assert dict([line.split('=') for line in result.splitlines()]) == EXECVE_ENV
+
+ # These won't actually execute anything, so they don't need a child process
+ # helper.
+ execve = getllimpl(os.execve)
+
+ # If the target does not exist, an OSError should result
+ info = py.test.raises(
+ OSError, execve, execve_tests + "-non-existent", [], {})
+ assert info.value.errno == errno.ENOENT
+
+ # If the target is not executable, an OSError should result
+ info = py.test.raises(
+ OSError, execve, execve_tests, [], {})
+ assert info.value.errno == errno.EACCES
+
+
+
class ExpectTestOs:
def setup_class(cls):
if not hasattr(os, 'ttyname'):
More information about the Pypy-commit
mailing list