summaryrefslogtreecommitdiff
path: root/testing
diff options
context:
space:
mode:
authorArmin Rigo <arigo@tunes.org>2015-11-18 12:28:44 +0100
committerArmin Rigo <arigo@tunes.org>2015-11-18 12:28:44 +0100
commitd995bf5eda3cd8dae5c86206ee44f4ccd77d70bb (patch)
tree14a0060a9d11803d4e629f4aa86bd668bd94faba /testing
parent1b266852f4dc07efdca37f2fe495cc42b60c1a31 (diff)
downloadcffi-d995bf5eda3cd8dae5c86206ee44f4ccd77d70bb.tar.gz
Write one error message directly to stderr instead of sys.stderr. This
lets us avoid taking the GIL, which might crash in case the Python interpreter is not initialized at all.
Diffstat (limited to 'testing')
-rw-r--r--testing/cffi0/test_function.py32
-rw-r--r--testing/cffi1/test_recompiler.py12
-rw-r--r--testing/support.py37
3 files changed, 44 insertions, 37 deletions
diff --git a/testing/cffi0/test_function.py b/testing/cffi0/test_function.py
index b4c98e7..8fdcc86 100644
--- a/testing/cffi0/test_function.py
+++ b/testing/cffi0/test_function.py
@@ -4,6 +4,7 @@ import math, os, sys
import ctypes.util
from cffi.backend_ctypes import CTypesBackend
from testing.udir import udir
+from testing.support import FdWriteCapture
try:
from StringIO import StringIO
@@ -11,29 +12,6 @@ except ImportError:
from io import StringIO
-class FdWriteCapture(object):
- """xxx limited to capture at most 512 bytes of output, according
- to the Posix manual."""
-
- def __init__(self, capture_fd):
- self.capture_fd = capture_fd
-
- def __enter__(self):
- self.read_fd, self.write_fd = os.pipe()
- self.copy_fd = os.dup(self.capture_fd)
- os.dup2(self.write_fd, self.capture_fd)
- return self
-
- def __exit__(self, *args):
- os.dup2(self.copy_fd, self.capture_fd)
- os.close(self.copy_fd)
- os.close(self.write_fd)
- self._value = os.read(self.read_fd, 512)
- os.close(self.read_fd)
-
- def getvalue(self):
- return self._value
-
lib_m = 'm'
if sys.platform == 'win32':
#there is a small chance this fails on Mingw via environ $CC
@@ -135,7 +113,7 @@ class TestFunction(object):
""")
ffi.C = ffi.dlopen(None)
ffi.C.fputs # fetch before capturing, for easier debugging
- with FdWriteCapture(2) as fd:
+ with FdWriteCapture() as fd:
ffi.C.fputs(b"hello\n", ffi.C.stderr)
ffi.C.fputs(b" world\n", ffi.C.stderr)
res = fd.getvalue()
@@ -151,7 +129,7 @@ class TestFunction(object):
""")
ffi.C = ffi.dlopen(None)
ffi.C.fputs # fetch before capturing, for easier debugging
- with FdWriteCapture(2) as fd:
+ with FdWriteCapture() as fd:
ffi.C.fputs(b"hello\n", ffi.C.stderr)
ffi.C.fputs(b" world\n", ffi.C.stderr)
res = fd.getvalue()
@@ -166,7 +144,7 @@ class TestFunction(object):
void *stderr;
""")
ffi.C = ffi.dlopen(None)
- with FdWriteCapture(2) as fd:
+ with FdWriteCapture() as fd:
ffi.C.fprintf(ffi.C.stderr, b"hello with no arguments\n")
ffi.C.fprintf(ffi.C.stderr,
b"hello, %s!\n", ffi.new("char[]", b"world"))
@@ -228,7 +206,7 @@ class TestFunction(object):
fptr = ffi.cast("int(*)(const char *txt, void *)", ffi.C.fputs)
assert fptr == ffi.C.fputs
assert repr(fptr).startswith("<cdata 'int(*)(char *, void *)' 0x")
- with FdWriteCapture(2) as fd:
+ with FdWriteCapture() as fd:
fptr(b"world\n", ffi.C.stderr)
res = fd.getvalue()
assert res == b'world\n'
diff --git a/testing/cffi1/test_recompiler.py b/testing/cffi1/test_recompiler.py
index ee77c5c..81c43ef 100644
--- a/testing/cffi1/test_recompiler.py
+++ b/testing/cffi1/test_recompiler.py
@@ -4,7 +4,7 @@ from cffi import FFI, VerificationError, FFIError
from cffi import recompiler
from testing.udir import udir
from testing.support import u
-from StringIO import StringIO
+from testing.support import FdWriteCapture, StdErrCapture
def check_type_table(input, expected_output, included=None):
@@ -1486,14 +1486,6 @@ def test_win32_calling_convention_3():
pt = ptr_call2(ffi.addressof(lib, 'cb2'))
assert (pt.x, pt.y) == (99*500*999, -99*500*999)
-class StdErrCapture(object):
- def __enter__(self):
- self.old_stderr = sys.stderr
- sys.stderr = f = StringIO()
- return f
- def __exit__(self, *args):
- sys.stderr = self.old_stderr
-
def test_extern_python_1():
ffi = FFI()
ffi.cdef("""
@@ -1506,7 +1498,7 @@ def test_extern_python_1():
""")
lib = verify(ffi, 'test_extern_python_1', "")
assert ffi.typeof(lib.bar) == ffi.typeof("int(*)(int, int)")
- with StdErrCapture() as f:
+ with FdWriteCapture() as f:
res = lib.bar(4, 5)
assert res == 0
assert f.getvalue() == (
diff --git a/testing/support.py b/testing/support.py
index 17c56cd..17ee621 100644
--- a/testing/support.py
+++ b/testing/support.py
@@ -17,3 +17,40 @@ else:
u = ""
unicode = str
long = int
+
+
+class StdErrCapture(object):
+ """Capture writes to sys.stderr (not to the underlying file descriptor)."""
+ def __enter__(self):
+ import StringIO
+ self.old_stderr = sys.stderr
+ sys.stderr = f = StringIO.StringIO()
+ return f
+ def __exit__(self, *args):
+ sys.stderr = self.old_stderr
+
+
+class FdWriteCapture(object):
+ """xxx limited to capture at most 512 bytes of output, according
+ to the Posix manual."""
+
+ def __init__(self, capture_fd=2): # stderr by default
+ self.capture_fd = capture_fd
+
+ def __enter__(self):
+ import os
+ self.read_fd, self.write_fd = os.pipe()
+ self.copy_fd = os.dup(self.capture_fd)
+ os.dup2(self.write_fd, self.capture_fd)
+ return self
+
+ def __exit__(self, *args):
+ import os
+ os.dup2(self.copy_fd, self.capture_fd)
+ os.close(self.copy_fd)
+ os.close(self.write_fd)
+ self._value = os.read(self.read_fd, 512)
+ os.close(self.read_fd)
+
+ def getvalue(self):
+ return self._value