Commit 90ab5cd6 authored by Jason Madden's avatar Jason Madden

Fix several more socket-related tests under Py3: test__examples, test__os,...

Fix several more socket-related tests under Py3: test__examples, test__os, test__fileobject, test__subprocess_poll, test__server, test__execmodules.
parent c71ebb60
...@@ -475,7 +475,7 @@ class _fileobject(object): ...@@ -475,7 +475,7 @@ class _fileobject(object):
def flush(self): def flush(self):
if self._wbuf: if self._wbuf:
data = "".join(self._wbuf) data = b"".join(self._wbuf)
self._wbuf = [] self._wbuf = []
self._wbuf_len = 0 self._wbuf_len = 0
buffer_size = max(self._rbufsize, self.default_bufsize) buffer_size = max(self._rbufsize, self.default_bufsize)
...@@ -497,13 +497,14 @@ class _fileobject(object): ...@@ -497,13 +497,14 @@ class _fileobject(object):
return self._sock.fileno() return self._sock.fileno()
def write(self, data): def write(self, data):
data = str(data) # XXX Should really reject non-string non-buffers if not isinstance(data, bytes):
raise TypeError("Non-bytes data")
if not data: if not data:
return return
self._wbuf.append(data) self._wbuf.append(data)
self._wbuf_len += len(data) self._wbuf_len += len(data)
if (self._wbufsize == 0 or if (self._wbufsize == 0 or
(self._wbufsize == 1 and '\n' in data) or (self._wbufsize == 1 and b'\n' in data) or
(self._wbufsize > 1 and self._wbuf_len >= self._wbufsize)): (self._wbufsize > 1 and self._wbuf_len >= self._wbufsize)):
self.flush() self.flush()
......
...@@ -3,6 +3,7 @@ import sys ...@@ -3,6 +3,7 @@ import sys
import os import os
from gevent.hub import get_hub from gevent.hub import get_hub
from gevent.hub import integer_types from gevent.hub import integer_types
from gevent.hub import PY3
from gevent.socket import EBADF from gevent.socket import EBADF
from gevent.os import _read, _write, ignored_errors from gevent.os import _read, _write, ignored_errors
from gevent.lock import Semaphore, DummySemaphore from gevent.lock import Semaphore, DummySemaphore
...@@ -10,6 +11,12 @@ from gevent.lock import Semaphore, DummySemaphore ...@@ -10,6 +11,12 @@ from gevent.lock import Semaphore, DummySemaphore
PYPY = hasattr(sys, 'pypy_version_info') PYPY = hasattr(sys, 'pypy_version_info')
if hasattr(sys, 'exc_clear'):
def _exc_clear():
sys.exc_clear()
else:
def _exc_clear():
return
try: try:
from fcntl import fcntl from fcntl import fcntl
...@@ -38,7 +45,10 @@ else: ...@@ -38,7 +45,10 @@ else:
SocketAdapter__del__ = None SocketAdapter__del__ = None
noop = None noop = None
from types import UnboundMethodType if PY3:
UnboundMethodType = None
else:
from types import UnboundMethodType
class NA(object): class NA(object):
...@@ -121,7 +131,7 @@ else: ...@@ -121,7 +131,7 @@ else:
code = ex.args[0] code = ex.args[0]
if code not in ignored_errors: if code not in ignored_errors:
raise raise
sys.exc_clear() _exc_clear()
if bytes_written >= bytes_total: if bytes_written >= bytes_total:
return return
self.hub.wait(self._write_event) self.hub.wait(self._write_event)
...@@ -134,24 +144,24 @@ else: ...@@ -134,24 +144,24 @@ else:
code = ex.args[0] code = ex.args[0]
if code not in ignored_errors: if code not in ignored_errors:
raise raise
sys.exc_clear() _exc_clear()
else: else:
if not self._translate or not data: if not self._translate or not data:
return data return data
if self._eat_newline: if self._eat_newline:
self._eat_newline = False self._eat_newline = False
if data.startswith('\n'): if data.startswith(b'\n'):
data = data[1:] data = data[1:]
if not data: if not data:
return self.recv(size) return self.recv(size)
if data.endswith('\r'): if data.endswith(b'\r'):
self._eat_newline = True self._eat_newline = True
return self._translate_newlines(data) return self._translate_newlines(data)
self.hub.wait(self._read_event) self.hub.wait(self._read_event)
def _translate_newlines(self, data): def _translate_newlines(self, data):
data = data.replace("\r\n", "\n") data = data.replace(b"\r\n", b"\n")
data = data.replace("\r", "\n") data = data.replace(b"\r", b"\n")
return data return data
if not SocketAdapter__del__: if not SocketAdapter__del__:
...@@ -160,13 +170,15 @@ else: ...@@ -160,13 +170,15 @@ else:
fileno = self._fileno fileno = self._fileno
if fileno is not None: if fileno is not None:
close(fileno) close(fileno)
elif PY3:
if SocketAdapter__del__: def __del__(self, close=os.close):
SocketAdapter__del__(self, close=close)
if SocketAdapter__del__ and not PY3:
SocketAdapter.__del__ = UnboundMethodType(SocketAdapter__del__, None, SocketAdapter) SocketAdapter.__del__ = UnboundMethodType(SocketAdapter__del__, None, SocketAdapter)
class FileObjectPosix(_fileobject): class FileObjectPosix(_fileobject):
def __init__(self, fobj, mode='rb', bufsize=-1, close=True): def __init__(self, fobj=None, mode='rb', bufsize=-1, close=True):
if isinstance(fobj, integer_types): if isinstance(fobj, integer_types):
fileno = fobj fileno = fobj
fobj = None fobj = None
...@@ -212,13 +224,13 @@ else: ...@@ -212,13 +224,13 @@ else:
raise FileObjectClosed raise FileObjectClosed
return getattr(self._fobj, item) return getattr(self._fobj, item)
if not noop: if not noop or PY3:
def __del__(self): def __del__(self):
# disable _fileobject's __del__ # disable _fileobject's __del__
pass pass
if noop: if noop and not PY3:
FileObjectPosix.__del__ = UnboundMethodType(FileObjectPosix, None, noop) FileObjectPosix.__del__ = UnboundMethodType(FileObjectPosix, None, noop)
......
...@@ -98,7 +98,7 @@ class StreamServer(BaseServer): ...@@ -98,7 +98,7 @@ class StreamServer(BaseServer):
try: try:
fd, address = sock._accept() fd, address = sock._accept()
except BlockingIOError: except BlockingIOError:
if sock.timeout == 0.0: if not sock.timeout:
return return
raise raise
sock = socket(sock.family, sock.type, sock.proto, fileno=fd) sock = socket(sock.family, sock.type, sock.proto, fileno=fd)
......
...@@ -24,24 +24,28 @@ def create_connection(address): ...@@ -24,24 +24,28 @@ def create_connection(address):
conn.connect(address) conn.connect(address)
return conn return conn
def readline(conn):
f = conn.makefile()
line = f.readline()
f.close()
return line
class Test(greentest.TestCase): class Test(greentest.TestCase):
def test(self): def test(self):
server = backdoor.BackdoorServer(('127.0.0.1', 0)) server = backdoor.BackdoorServer(('127.0.0.1', 0))
server.start()
def connect(): def connect():
conn = create_connection(('127.0.0.1', server.server_port)) conn = create_connection(('127.0.0.1', server.server_port))
try: try:
read_until(conn, '>>> ') read_until(conn, '>>> ')
conn.sendall(b'2+2\r\n') conn.sendall(b'2+2\r\n')
with conn.makefile() as f: line = readline(conn)
line = f.readline()
self.assertEqual(line.strip(), '4', repr(line)) self.assertEqual(line.strip(), '4', repr(line))
finally: finally:
conn.close() conn.close()
server.start()
try: try:
jobs = [gevent.spawn(connect) for _ in xrange(10)] jobs = [gevent.spawn(connect) for _ in xrange(10)]
gevent.joinall(jobs, raise_error=True) gevent.joinall(jobs, raise_error=True)
...@@ -56,8 +60,7 @@ class Test(greentest.TestCase): ...@@ -56,8 +60,7 @@ class Test(greentest.TestCase):
conn = create_connection(('127.0.0.1', server.server_port)) conn = create_connection(('127.0.0.1', server.server_port))
read_until(conn, '>>> ') read_until(conn, '>>> ')
conn.sendall(b'quit()\r\n') conn.sendall(b'quit()\r\n')
with conn.makefile() as f: line = readline(conn)
line = f.read()
self.assertEqual(line, '') self.assertEqual(line, '')
finally: finally:
conn.close() conn.close()
...@@ -70,8 +73,7 @@ class Test(greentest.TestCase): ...@@ -70,8 +73,7 @@ class Test(greentest.TestCase):
conn = create_connection(('127.0.0.1', server.server_port)) conn = create_connection(('127.0.0.1', server.server_port))
read_until(conn, b'>>> ') read_until(conn, b'>>> ')
conn.sendall(b'import sys; sys.exit(0)\r\n') conn.sendall(b'import sys; sys.exit(0)\r\n')
with conn.makefile() as f: line = readline(conn)
line = f.read()
self.assertEqual(line, '') self.assertEqual(line, '')
finally: finally:
conn.close() conn.close()
......
...@@ -13,7 +13,7 @@ class Test(greentest.TestCase): ...@@ -13,7 +13,7 @@ class Test(greentest.TestCase):
def _test_del(self, **kwargs): def _test_del(self, **kwargs):
r, w = os.pipe() r, w = os.pipe()
s = FileObject(w, 'wb') s = FileObject(w, 'wb')
s.write('x') s.write(b'x')
s.flush() s.flush()
if PYPY: if PYPY:
s.close() s.close()
...@@ -25,7 +25,7 @@ class Test(greentest.TestCase): ...@@ -25,7 +25,7 @@ class Test(greentest.TestCase):
pass # expected, because SocketAdapter already closed it pass # expected, because SocketAdapter already closed it
else: else:
raise AssertionError('os.close(%r) must not succeed' % w) raise AssertionError('os.close(%r) must not succeed' % w)
self.assertEqual(FileObject(r).read(), 'x') self.assertEqual(FileObject(r).read(), b'x')
def test_del(self): def test_del(self):
self._test_del() self._test_del()
...@@ -38,22 +38,22 @@ class Test(greentest.TestCase): ...@@ -38,22 +38,22 @@ class Test(greentest.TestCase):
def test_del_noclose(self): def test_del_noclose(self):
r, w = os.pipe() r, w = os.pipe()
s = FileObject(w, 'wb', close=False) s = FileObject(w, 'wb', close=False)
s.write('x') s.write(b'x')
s.flush() s.flush()
if PYPY: if PYPY:
s.close() s.close()
else: else:
del s del s
os.close(w) os.close(w)
self.assertEqual(FileObject(r).read(), 'x') self.assertEqual(FileObject(r).read(), b'x')
def test_newlines(self): def test_newlines(self):
r, w = os.pipe() r, w = os.pipe()
lines = ['line1\n', 'line2\r', 'line3\r\n', 'line4\r\nline5', '\nline6'] lines = [b'line1\n', b'line2\r', b'line3\r\n', b'line4\r\nline5', b'\nline6']
g = gevent.spawn(writer, FileObject(w, 'wb'), lines) g = gevent.spawn(writer, FileObject(w, 'wb'), lines)
try: try:
result = FileObject(r, 'rU').read() result = FileObject(r, 'rU').read()
self.assertEqual('line1\nline2\nline3\nline4\nline5\nline6', result) self.assertEqual(b'line1\nline2\nline3\nline4\nline5\nline6', result)
finally: finally:
g.kill() g.kill()
...@@ -76,7 +76,7 @@ else: ...@@ -76,7 +76,7 @@ else:
def _test_del(self, **kwargs): def _test_del(self, **kwargs):
r, w = os.pipe() r, w = os.pipe()
s = SocketAdapter(w) s = SocketAdapter(w)
s.sendall('x') s.sendall(b'x')
if PYPY: if PYPY:
s.close() s.close()
else: else:
...@@ -87,7 +87,7 @@ else: ...@@ -87,7 +87,7 @@ else:
pass # expected, because SocketAdapter already closed it pass # expected, because SocketAdapter already closed it
else: else:
raise AssertionError('os.close(%r) must not succeed' % w) raise AssertionError('os.close(%r) must not succeed' % w)
self.assertEqual(FileObject(r).read(), 'x') self.assertEqual(FileObject(r).read(), b'x')
def test_del(self): def test_del(self):
self._test_del() self._test_del()
...@@ -98,10 +98,10 @@ else: ...@@ -98,10 +98,10 @@ else:
def test_del_noclose(self): def test_del_noclose(self):
r, w = os.pipe() r, w = os.pipe()
s = SocketAdapter(w, close=False) s = SocketAdapter(w, close=False)
s.sendall('x') s.sendall(b'x')
del s del s
os.close(w) os.close(w)
self.assertEqual(FileObject(r).read(), 'x') self.assertEqual(FileObject(r).read(), b'x')
if __name__ == '__main__': if __name__ == '__main__':
......
...@@ -5,7 +5,7 @@ import sys ...@@ -5,7 +5,7 @@ import sys
if not sys.argv[1:]: if not sys.argv[1:]:
from subprocess import Popen, PIPE from subprocess import Popen, PIPE
p = Popen([sys.executable, __file__, 'subprocess'], stdin=PIPE, stdout=PIPE, stderr=PIPE) p = Popen([sys.executable, __file__, 'subprocess'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
out, err = p.communicate('hello world\n') out, err = p.communicate(b'hello world\n')
code = p.poll() code = p.poll()
assert p.poll() == 0, (out, err, code) assert p.poll() == 0, (out, err, code)
assert out.strip() == '11 chars.', (out, err, code) assert out.strip() == '11 chars.', (out, err, code)
......
...@@ -32,7 +32,7 @@ class TestOS_tp(TestCase): ...@@ -32,7 +32,7 @@ class TestOS_tp(TestCase):
r, w = self.pipe() r, w = self.pipe()
# set nbytes such that for sure it is > maximum pipe buffer # set nbytes such that for sure it is > maximum pipe buffer
nbytes = 1000000 nbytes = 1000000
block = 'x' * 4096 block = b'x' * 4096
buf = buffer_class(block) buf = buffer_class(block)
# Lack of "nonlocal" keyword in Python 2.x: # Lack of "nonlocal" keyword in Python 2.x:
bytesread = [0] bytesread = [0]
......
from __future__ import print_function from __future__ import print_function
import greentest import greentest
from gevent.hub import PY3
from gevent import socket from gevent import socket
import gevent import gevent
from gevent.server import StreamServer from gevent.server import StreamServer
...@@ -21,15 +22,15 @@ class SimpleStreamServer(StreamServer): ...@@ -21,15 +22,15 @@ class SimpleStreamServer(StreamServer):
print('Failed to parse request line: %r' % (request_line, )) print('Failed to parse request line: %r' % (request_line, ))
raise raise
if path == '/ping': if path == '/ping':
client_socket.sendall('HTTP/1.0 200 OK\r\n\r\nPONG') client_socket.sendall(b'HTTP/1.0 200 OK\r\n\r\nPONG')
elif path in ['/long', '/short']: elif path in ['/long', '/short']:
client_socket.sendall('hello') client_socket.sendall(b'hello')
while True: while True:
data = client_socket.recv(1) data = client_socket.recv(1)
if not data: if not data:
break break
else: else:
client_socket.sendall('HTTP/1.0 404 WTF?\r\n\r\n') client_socket.sendall(b'HTTP/1.0 404 WTF?\r\n\r\n')
finally: finally:
fd.close() fd.close()
...@@ -82,10 +83,35 @@ class TestCase(greentest.TestCase): ...@@ -82,10 +83,35 @@ class TestCase(greentest.TestCase):
def makefile(self, timeout=0.1, bufsize=1): def makefile(self, timeout=0.1, bufsize=1):
sock = socket.socket() sock = socket.socket()
sock.connect((self.server.server_host, self.server.server_port)) sock.connect((self.server.server_host, self.server.server_port))
fobj = sock.makefile(bufsize=bufsize)
fobj._sock.settimeout(timeout) if PY3:
kwargs = {'buffering': bufsize, 'mode': 'rb'}
else:
kwargs = {'bufsize': bufsize}
rconn = sock.makefile(**kwargs)
if PY3:
# Under Python3, you can't read and write to the same
# makefile() opened in r, and r+ is not allowed
kwargs['mode'] = 'wb'
wconn = sock.makefile(**kwargs)
rconn._sock = sock
_rconn_close = rconn.close
def write(data):
if isinstance(data, str):
data = data.encode('ascii')
return wconn.write(data)
def flush():
return wconn.flush()
def close():
_rconn_close()
wconn.close()
rconn.write = write
rconn.flush = flush
rconn.close = close
rconn._sock.settimeout(timeout)
sock.close() sock.close()
return fobj return rconn
def send_request(self, url='/', timeout=0.1, bufsize=1): def send_request(self, url='/', timeout=0.1, bufsize=1):
conn = self.makefile(timeout=timeout, bufsize=bufsize) conn = self.makefile(timeout=timeout, bufsize=bufsize)
...@@ -128,12 +154,14 @@ class TestCase(greentest.TestCase): ...@@ -128,12 +154,14 @@ class TestCase(greentest.TestCase):
assert not result, repr(result) assert not result, repr(result)
return return
assert result.startswith('HTTP/1.0 500 Internal Server Error'), repr(result) assert result.startswith('HTTP/1.0 500 Internal Server Error'), repr(result)
conn.close()
def assertRequestSucceeded(self, timeout=0.1): def assertRequestSucceeded(self, timeout=0.1):
conn = self.makefile(timeout=timeout) conn = self.makefile(timeout=timeout)
conn.write('GET /ping HTTP/1.0\r\n\r\n') conn.write(b'GET /ping HTTP/1.0\r\n\r\n')
result = conn.read() result = conn.read()
assert result.endswith('\r\n\r\nPONG'), repr(result) conn.close()
assert result.endswith(b'\r\n\r\nPONG'), repr(result)
def start_server(self): def start_server(self):
self.server.start() self.server.start()
...@@ -270,6 +298,7 @@ class TestDefaultSpawn(TestCase): ...@@ -270,6 +298,7 @@ class TestDefaultSpawn(TestCase):
raise raise
finally: finally:
timeout.cancel() timeout.cancel()
conn.close()
self.stop_server() self.stop_server()
def init_server(self): def init_server(self):
...@@ -319,6 +348,10 @@ class TestPoolSpawn(TestDefaultSpawn): ...@@ -319,6 +348,10 @@ class TestPoolSpawn(TestDefaultSpawn):
self.assertPoolFull() self.assertPoolFull()
self.assertPoolFull() self.assertPoolFull()
short_request._sock.close() short_request._sock.close()
if PY3:
# We use two makefiles to simulate reading/writing
# under py3
short_request.close()
# gevent.http and gevent.wsgi cannot detect socket close, so sleep a little # gevent.http and gevent.wsgi cannot detect socket close, so sleep a little
# to let /short request finish # to let /short request finish
gevent.sleep(0.1) gevent.sleep(0.1)
......
...@@ -84,27 +84,20 @@ if PY3: ...@@ -84,27 +84,20 @@ if PY3:
# No idea / TODO # No idea / TODO
FAILING_TESTS += ''' FAILING_TESTS += '''
test__example_udp_server.py test__example_udp_server.py
test__examples.py
test__pool.py test__pool.py
FLAKY test___example_servers.py FLAKY test___example_servers.py
test__example_udp_client.py
test__os.py
test_threading_2.py test_threading_2.py
test__refcount.py test__refcount.py
test__subprocess.py test__subprocess.py
test__all__.py test__all__.py
test__fileobject.py
test__pywsgi.py test__pywsgi.py
test__socket_ex.py test__socket_ex.py
test__example_echoserver.py test__example_echoserver.py
test__subprocess_poll.py
test__makefile_ref.py test__makefile_ref.py
test__socketpair.py test__socketpair.py
test__server_pywsgi.py test__server_pywsgi.py
test__core_stat.py test__core_stat.py
test__server.py
test__example_portforwarder.py test__example_portforwarder.py
test__execmodules.py
FLAKY test__greenio.py FLAKY test__greenio.py
FLAKY test__socket_dns.py FLAKY test__socket_dns.py
'''.strip().split('\n') '''.strip().split('\n')
......
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