tests cleanup, CI with Python 3.6

This commit is contained in:
Sergey Shepelev
2017-01-05 05:08:38 +03:00
parent 461348f9a8
commit ed79125c65
14 changed files with 209 additions and 181 deletions

View File

@@ -1,7 +1,8 @@
[run]
branch = True
source = eventlet
concurrency = eventlet
# concurrency=eventlet gives 0% report on CPython and start error on pypy
#concurrency = eventlet
omit =
eventlet/support/dns/*
eventlet/support/six.py

1
.gitignore vendored
View File

@@ -3,6 +3,7 @@
*.pyc
.*
build/
.coverage
coverage.xml
dist/
doc/changelog.rst

View File

@@ -1,31 +1,42 @@
sudo: false
language: python
python: 3.5
env:
matrix:
- TOX_ENV=pep8
- TOX_ENV=py26-epolls
- TOX_ENV=py26-poll
- TOX_ENV=py26-selects
- TOX_ENV=py27-epolls
- TOX_ENV=py27-poll
- TOX_ENV=py27-selects
- TOX_ENV=py33-epolls
- TOX_ENV=py33-poll
- TOX_ENV=py33-selects
- TOX_ENV=py34-epolls
- TOX_ENV=py34-poll
- TOX_ENV=py34-selects
- TOX_ENV=py35-epolls
- TOX_ENV=py35-poll
- TOX_ENV=py35-selects
- TOX_ENV=pypy-epolls
- TOX_ENV=pypy-poll
- TOX_ENV=pypy-selects
matrix:
fast_finish: true
include:
- {python: 3.5, env: TOX_ENV=pep8}
- {python: 2.6, env: TOX_ENV=py26-epolls}
- {python: 2.6, env: TOX_ENV=py26-poll}
- {python: 2.6, env: TOX_ENV=py26-selects}
- {python: 2.7, env: TOX_ENV=py27-epolls}
- {python: 2.7, env: TOX_ENV=py27-poll}
- {python: 2.7, env: TOX_ENV=py27-selects}
- {python: 3.3, env: TOX_ENV=py33-epolls}
- {python: 3.3, env: TOX_ENV=py33-poll}
- {python: 3.3, env: TOX_ENV=py33-selects}
- {python: 3.4, env: TOX_ENV=py34-epolls}
- {python: 3.4, env: TOX_ENV=py34-poll}
- {python: 3.4, env: TOX_ENV=py34-selects}
- {python: 3.5, env: TOX_ENV=py35-epolls}
- {python: 3.5, env: TOX_ENV=py35-poll}
- {python: 3.5, env: TOX_ENV=py35-selects}
- {python: 3.6-dev, env: TOX_ENV=py36-epolls}
- {python: 3.6-dev, env: TOX_ENV=py36-poll}
- {python: 3.6-dev, env: TOX_ENV=py36-selects}
- {python: pypy, env: TOX_ENV=pypy-epolls}
- {python: pypy, env: TOX_ENV=pypy-poll}
- {python: pypy, env: TOX_ENV=pypy-selects}
allow_failures:
- env: TOX_ENV=py26-epolls
- env: TOX_ENV=py26-poll
- env: TOX_ENV=py26-selects
- env: TOX_ENV=pypy-epolls
- env: TOX_ENV=pypy-poll
- env: TOX_ENV=pypy-selects
@@ -51,7 +62,7 @@ before_script:
- "export PATH=/usr/lib/ccache:$PATH"
script:
- tox -v -v -e $TOX_ENV
- codecov
- codecov --flags=$(echo $TOX_ENV |tr -d '-.')
after_failure:
- for X in .tox/$TOX_ENV/log/*; do echo "$X\n"; cat "$X"; echo "\n\n"; done
- echo "pip.log\n"; cat $HOME/.pip/pip.log

View File

@@ -1,2 +1,6 @@
codecov:
token: 2a926756-1923-42a1-89c7-97925ea0e17a
coverage:
precision: 0
round: down

View File

@@ -1,52 +0,0 @@
from tests.patcher_test import ProcessBase
class ForkTest(ProcessBase):
def test_simple(self):
newmod = '''
import eventlet
import os
import sys
import signal
from eventlet.support import bytes_to_str, six
mydir = %r
signal_file = os.path.join(mydir, "output.txt")
pid = os.fork()
if (pid != 0):
eventlet.Timeout(10)
try:
port = None
while True:
try:
contents = open(signal_file, "rb").read()
port = int(contents.split()[0])
break
except (IOError, IndexError, ValueError, TypeError):
eventlet.sleep(0.1)
eventlet.connect(('127.0.0.1', port))
while True:
try:
contents = open(signal_file, "rb").read()
result = contents.split()[1]
break
except (IOError, IndexError):
eventlet.sleep(0.1)
print('result {0}'.format(bytes_to_str(result)))
finally:
os.kill(pid, signal.SIGTERM)
else:
try:
s = eventlet.listen(('', 0))
fd = open(signal_file, "wb")
fd.write(six.b(str(s.getsockname()[1])))
fd.write(b"\\n")
fd.flush()
s.accept()
fd.write(b"done")
fd.flush()
finally:
fd.close()
'''
self.write_to_tempfile("newmod", newmod % self.tempdir)
output, lines = self.launch_subprocess('newmod.py')
self.assertEqual(lines[0], "result done", output)

View File

@@ -443,7 +443,7 @@ class TestGreenSocket(tests.LimitedTestCase):
wrap_rfile = client.makefile()
wrap_rfile.read(1)
self.fail()
except eventlet.TimeoutError:
except eventlet.Timeout:
pass
result = evt.wait()

View File

@@ -1,14 +1,12 @@
from __future__ import with_statement
import sys
import time
import tests
from tests import LimitedTestCase, main, skip_with_pyevent, skip_if_no_itimer, skip_unless
from tests import skip_with_pyevent, skip_if_no_itimer, skip_unless
from tests.patcher_test import ProcessBase
import time
import eventlet
from eventlet import hubs
from eventlet.event import Event
from eventlet.semaphore import Semaphore
from eventlet.support import greenlets, six
@@ -19,7 +17,7 @@ def noop():
pass
class TestTimerCleanup(LimitedTestCase):
class TestTimerCleanup(tests.LimitedTestCase):
TEST_TIMEOUT = 2
@skip_with_pyevent
@@ -85,7 +83,7 @@ class TestTimerCleanup(LimitedTestCase):
eventlet.sleep()
class TestScheduleCall(LimitedTestCase):
class TestScheduleCall(tests.LimitedTestCase):
def test_local(self):
lst = [1]
@@ -111,7 +109,7 @@ class TestScheduleCall(LimitedTestCase):
self.assertEqual(lst, [1, 2, 3])
class TestDebug(LimitedTestCase):
class TestDebug(tests.LimitedTestCase):
def test_debug_listeners(self):
hubs.get_hub().set_debug_listeners(True)
@@ -122,7 +120,7 @@ class TestDebug(LimitedTestCase):
hubs.get_hub().set_timer_exceptions(False)
class TestExceptionInMainloop(LimitedTestCase):
class TestExceptionInMainloop(tests.LimitedTestCase):
def test_sleep(self):
# even if there was an error in the mainloop, the hub should continue
@@ -149,13 +147,13 @@ class TestExceptionInMainloop(LimitedTestCase):
delay, DELAY)
class TestExceptionInGreenthread(LimitedTestCase):
class TestExceptionInGreenthread(tests.LimitedTestCase):
@skip_unless(greenlets.preserves_excinfo)
def test_exceptionpreservation(self):
# events for controlling execution order
gt1event = Event()
gt2event = Event()
gt1event = eventlet.Event()
gt2event = eventlet.Event()
def test_gt1():
try:
@@ -196,7 +194,7 @@ class TestExceptionInGreenthread(LimitedTestCase):
hubs.get_hub().switch()
# semaphores for controlling execution order
sem = Semaphore()
sem = eventlet.Semaphore()
sem.acquire()
g = eventlet.spawn(test_gt, sem)
try:
@@ -206,7 +204,7 @@ class TestExceptionInGreenthread(LimitedTestCase):
g.kill()
class TestHubSelection(LimitedTestCase):
class TestHubSelection(tests.LimitedTestCase):
def test_explicit_hub(self):
oldhub = hubs.get_hub()
@@ -217,7 +215,7 @@ class TestHubSelection(LimitedTestCase):
hubs._threadlocal.hub = oldhub
class TestHubBlockingDetector(LimitedTestCase):
class TestHubBlockingDetector(tests.LimitedTestCase):
TEST_TIMEOUT = 10
@skip_with_pyevent
@@ -245,7 +243,7 @@ class TestHubBlockingDetector(LimitedTestCase):
debug.hub_blocking_detection(False)
class TestSuspend(LimitedTestCase):
class TestSuspend(tests.LimitedTestCase):
TEST_TIMEOUT = 4
longMessage = True
maxDiff = None
@@ -283,25 +281,30 @@ except eventlet.Timeout:
shutil.rmtree(self.tempdir)
class TestBadFilenos(LimitedTestCase):
def test_repeated_select_bad_fd():
from eventlet.green import select
@skip_with_pyevent
def test_repeated_selects(self):
from eventlet.green import select
self.assertRaises(ValueError, select.select, [-1], [], [])
self.assertRaises(ValueError, select.select, [-1], [], [])
def once():
try:
select.select([-1], [], [])
assert False, 'Expected ValueError'
except ValueError:
pass
once()
once()
class TestFork(LimitedTestCase):
@skip_with_pyevent
def test_fork(self):
output = tests.run_python('tests/hub_test_fork.py')
lines = output.splitlines()
self.assertEqual(lines, [b"accept blocked", b"child died ok"], output)
@skip_with_pyevent
def test_fork():
tests.run_isolated('hub_fork.py')
class TestDeadRunLoop(LimitedTestCase):
def test_fork_simple():
tests.run_isolated('hub_fork_simple.py')
class TestDeadRunLoop(tests.LimitedTestCase):
TEST_TIMEOUT = 2
class CustomException(Exception):
@@ -397,7 +400,3 @@ print('ok')
self.write_to_tempfile('newmod', module_source)
output, _ = self.launch_subprocess('newmod.py')
self.assertEqual(output, 'kqueue tried\nok\n')
if __name__ == '__main__':
main()

View File

@@ -1,25 +0,0 @@
# no standard tests in this file, ignore
__test__ = False
if __name__ == '__main__':
import os
import eventlet
server = eventlet.listen(('localhost', 12345))
t = eventlet.Timeout(0.01)
try:
new_sock, address = server.accept()
except eventlet.Timeout as t:
pass
pid = os.fork()
if not pid:
t = eventlet.Timeout(0.1)
try:
new_sock, address = server.accept()
except eventlet.Timeout as t:
print("accept blocked")
else:
kpid, status = os.wait()
assert kpid == pid
assert status == 0
print("child died ok")

View File

@@ -0,0 +1,33 @@
# verify eventlet.listen() accepts in forked children
__test__ = False
if __name__ == '__main__':
import os
import sys
import eventlet
server = eventlet.listen(('127.0.0.1', 0))
result = eventlet.with_timeout(0.01, server.accept, timeout_value=True)
assert result is True, 'Expected timeout'
pid = os.fork()
if pid < 0:
print('fork error')
sys.exit(1)
elif pid == 0:
with eventlet.Timeout(1):
sock, _ = server.accept()
sock.sendall('ok {0}'.format(os.getpid()).encode())
sock.close()
sys.exit(0)
elif pid > 0:
with eventlet.Timeout(1):
sock = eventlet.connect(server.getsockname())
data = sock.recv(20).decode()
assert data.startswith('ok ')
spid = int(data[3:].strip())
assert spid == pid
kpid, status = os.wait()
assert kpid == pid
assert status == 0
print('pass')

View File

@@ -0,0 +1,58 @@
import os
import signal
import sys
import tempfile
__test__ = False
def parent(signal_path, pid):
eventlet.Timeout(5)
port = None
while True:
try:
contents = open(signal_path, 'rb').read()
port = int(contents.strip())
break
except Exception:
eventlet.sleep(0.1)
eventlet.connect(('127.0.0.1', port))
while True:
try:
contents = open(signal_path, 'rb').read()
result = contents.split()[1]
break
except Exception:
eventlet.sleep(0.1)
assert result == b'done', repr(result)
print('pass')
def child(signal_path):
eventlet.Timeout(5)
s = eventlet.listen(('127.0.0.1', 0))
with open(signal_path, 'wb') as f:
f.write(str(s.getsockname()[1]).encode() + b'\n')
f.flush()
s.accept()
f.write(b'done\n')
f.flush()
if __name__ == '__main__':
import eventlet
with tempfile.NamedTemporaryFile() as signal_file:
signal_path = signal_file.name
pid = os.fork()
if pid < 0:
sys.stderr.write('fork error\n')
sys.exit(1)
elif pid == 0:
child(signal_path)
sys.exit(0)
elif pid > 0:
try:
parent(signal_path, pid)
except Exception:
os.kill(pid, signal.SIGTERM)

View File

@@ -2,78 +2,71 @@
are not leaked by the hub.
"""
import gc
from pprint import pformat
import pprint
import sys
import weakref
from eventlet.support import clear_sys_exc_info
import eventlet
from eventlet.green import socket
from eventlet.green.thread import start_new_thread
from eventlet.green.time import sleep
SOCKET_TIMEOUT = 0.1
def init_server():
s = socket.socket()
s.settimeout(SOCKET_TIMEOUT)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('localhost', 0))
s.listen(5)
return s, s.getsockname()[1]
def handle_request(s, raise_on_timeout):
try:
conn, address = s.accept()
except socket.timeout:
print('handle_request: server accept timeout')
if raise_on_timeout:
raise
else:
return
# print('handle_request - accepted')
print('handle_request: accepted')
res = conn.recv(100)
assert res == b'hello', repr(res)
# print('handle_request - recvd %r' % res)
res = conn.send(b'bye')
# print('handle_request - sent %r' % res)
# print('handle_request - conn refcount: %s' % sys.getrefcount(conn))
# conn.close()
# print('handle_request: recvd %r' % res)
res = conn.sendall(b'bye')
# print('handle_request: sent %r' % res)
# print('handle_request: conn refcount: %s' % sys.getrefcount(conn))
def make_request(port):
def make_request(addr):
# print('make_request')
s = socket.socket()
s.connect(('localhost', port))
s = eventlet.connect(addr)
# print('make_request - connected')
res = s.send(b'hello')
res = s.sendall(b'hello')
# print('make_request - sent %s' % res)
res = s.recv(100)
assert res == b'bye', repr(res)
# print('make_request - recvd %r' % res)
# s.close()
def run_interaction(run_client):
s, port = init_server()
start_new_thread(handle_request, (s, run_client))
s = eventlet.listen(('127.0.0.1', 0))
s.settimeout(SOCKET_TIMEOUT)
addr = s.getsockname()
print('run_interaction: addr:', addr)
eventlet.spawn(handle_request, s, run_client)
if run_client:
start_new_thread(make_request, (port,))
sleep(0.1 + SOCKET_TIMEOUT)
# print(sys.getrefcount(s.fd))
# s.close()
eventlet.spawn(make_request, addr)
eventlet.sleep(0.1 + SOCKET_TIMEOUT)
print('run_interaction: refcount(s.fd)', sys.getrefcount(s.fd))
return weakref.ref(s.fd)
def run_and_check(run_client):
w = run_interaction(run_client=run_client)
clear_sys_exc_info()
# clear_sys_exc_info()
gc.collect()
if w():
print(pformat(gc.get_referrers(w())))
for x in gc.get_referrers(w()):
print(pformat(x))
fd = w()
print('run_and_check: weakref fd:', fd)
if fd:
print(pprint.pformat(gc.get_referrers(fd)))
for x in gc.get_referrers(fd):
print(pprint.pformat(x))
for y in gc.get_referrers(x):
print('- {0}'.format(pformat(y)))
print('- {0}'.format(pprint.pformat(y)))
raise AssertionError('server should be dead by now')

View File

@@ -56,7 +56,7 @@ class TestSocketErrors(unittest.TestCase):
def test_create_connection_refused():
errno = None
try:
socket.create_connection(('127.0.0.1', 0))
socket.create_connection(('127.0.0.1', 1))
except socket.error as ex:
errno = ex.errno
assert errno in [111, 61, 10061], 'Expected socket.error ECONNREFUSED, got {0}'.format(errno)

View File

@@ -20,7 +20,7 @@ import re
import time
import eventlet
from eventlet import tpool, debug, event
from eventlet import tpool
from eventlet.support import six
import tests
@@ -218,10 +218,13 @@ class TestTpool(tests.LimitedTestCase):
@tests.skip_with_pyevent
def test_timeout(self):
import time
eventlet.Timeout(0.1, eventlet.TimeoutError())
self.assertRaises(eventlet.TimeoutError,
tpool.execute, time.sleep, 0.3)
blocking = eventlet.patcher.original('time')
eventlet.Timeout(0.1, eventlet.Timeout())
try:
tpool.execute(blocking.sleep, 0.3)
assert False, 'Expected Timeout'
except eventlet.Timeout:
pass
@tests.skip_with_pyevent
def test_killall(self):
@@ -230,7 +233,7 @@ class TestTpool(tests.LimitedTestCase):
@tests.skip_with_pyevent
def test_killall_remaining_results(self):
semaphore = event.Event()
semaphore = eventlet.Event()
def native_fun():
time.sleep(.5)

View File

@@ -14,9 +14,9 @@ show-source = 1
statistics = 1
[tox]
minversion=1.8
minversion=2.5
envlist =
pep8, py{26,27,33,34,35,py}-{selects,poll,epolls}
pep8, py{26,27,33,34,35,36,py}-{selects,poll,epolls}
[testenv:pep8]
basepython = python2.7
@@ -34,12 +34,14 @@ setenv =
selects: EVENTLET_HUB = selects
poll: EVENTLET_HUB = poll
epolls: EVENTLET_HUB = epolls
tox_cover_args = --with-coverage --cover-erase --cover-package=eventlet
basepython =
py26: python2.6
py27: python2.7
py33: python3.3
py34: python3.4
py35: python3.5
py36: python3.6
pypy: pypy
deps =
coverage==4.3.1
@@ -52,5 +54,5 @@ deps =
{selects,poll,epolls}: psycopg2cffi-compat==1.1
{selects,poll,epolls}: pyzmq==13.1.0
commands =
nosetests --verbose --with-coverage --cover-erase --cover-package=eventlet {posargs:tests/}
nosetests --verbose {env:tox_cover_args} {posargs:tests/}
coverage xml -i