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] [run]
branch = True branch = True
source = eventlet source = eventlet
concurrency = eventlet # concurrency=eventlet gives 0% report on CPython and start error on pypy
#concurrency = eventlet
omit = omit =
eventlet/support/dns/* eventlet/support/dns/*
eventlet/support/six.py eventlet/support/six.py

1
.gitignore vendored
View File

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

View File

@@ -1,31 +1,42 @@
sudo: false sudo: false
language: python 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: matrix:
fast_finish: true 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: 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-epolls
- env: TOX_ENV=pypy-poll - env: TOX_ENV=pypy-poll
- env: TOX_ENV=pypy-selects - env: TOX_ENV=pypy-selects
@@ -51,7 +62,7 @@ before_script:
- "export PATH=/usr/lib/ccache:$PATH" - "export PATH=/usr/lib/ccache:$PATH"
script: script:
- tox -v -v -e $TOX_ENV - tox -v -v -e $TOX_ENV
- codecov - codecov --flags=$(echo $TOX_ENV |tr -d '-.')
after_failure: after_failure:
- for X in .tox/$TOX_ENV/log/*; do echo "$X\n"; cat "$X"; echo "\n\n"; done - 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 - echo "pip.log\n"; cat $HOME/.pip/pip.log

View File

@@ -1,2 +1,6 @@
codecov: codecov:
token: 2a926756-1923-42a1-89c7-97925ea0e17a 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 = client.makefile()
wrap_rfile.read(1) wrap_rfile.read(1)
self.fail() self.fail()
except eventlet.TimeoutError: except eventlet.Timeout:
pass pass
result = evt.wait() result = evt.wait()

View File

@@ -1,14 +1,12 @@
from __future__ import with_statement from __future__ import with_statement
import sys import sys
import time
import tests 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 from tests.patcher_test import ProcessBase
import time
import eventlet import eventlet
from eventlet import hubs from eventlet import hubs
from eventlet.event import Event
from eventlet.semaphore import Semaphore
from eventlet.support import greenlets, six from eventlet.support import greenlets, six
@@ -19,7 +17,7 @@ def noop():
pass pass
class TestTimerCleanup(LimitedTestCase): class TestTimerCleanup(tests.LimitedTestCase):
TEST_TIMEOUT = 2 TEST_TIMEOUT = 2
@skip_with_pyevent @skip_with_pyevent
@@ -85,7 +83,7 @@ class TestTimerCleanup(LimitedTestCase):
eventlet.sleep() eventlet.sleep()
class TestScheduleCall(LimitedTestCase): class TestScheduleCall(tests.LimitedTestCase):
def test_local(self): def test_local(self):
lst = [1] lst = [1]
@@ -111,7 +109,7 @@ class TestScheduleCall(LimitedTestCase):
self.assertEqual(lst, [1, 2, 3]) self.assertEqual(lst, [1, 2, 3])
class TestDebug(LimitedTestCase): class TestDebug(tests.LimitedTestCase):
def test_debug_listeners(self): def test_debug_listeners(self):
hubs.get_hub().set_debug_listeners(True) hubs.get_hub().set_debug_listeners(True)
@@ -122,7 +120,7 @@ class TestDebug(LimitedTestCase):
hubs.get_hub().set_timer_exceptions(False) hubs.get_hub().set_timer_exceptions(False)
class TestExceptionInMainloop(LimitedTestCase): class TestExceptionInMainloop(tests.LimitedTestCase):
def test_sleep(self): def test_sleep(self):
# even if there was an error in the mainloop, the hub should continue # even if there was an error in the mainloop, the hub should continue
@@ -149,13 +147,13 @@ class TestExceptionInMainloop(LimitedTestCase):
delay, DELAY) delay, DELAY)
class TestExceptionInGreenthread(LimitedTestCase): class TestExceptionInGreenthread(tests.LimitedTestCase):
@skip_unless(greenlets.preserves_excinfo) @skip_unless(greenlets.preserves_excinfo)
def test_exceptionpreservation(self): def test_exceptionpreservation(self):
# events for controlling execution order # events for controlling execution order
gt1event = Event() gt1event = eventlet.Event()
gt2event = Event() gt2event = eventlet.Event()
def test_gt1(): def test_gt1():
try: try:
@@ -196,7 +194,7 @@ class TestExceptionInGreenthread(LimitedTestCase):
hubs.get_hub().switch() hubs.get_hub().switch()
# semaphores for controlling execution order # semaphores for controlling execution order
sem = Semaphore() sem = eventlet.Semaphore()
sem.acquire() sem.acquire()
g = eventlet.spawn(test_gt, sem) g = eventlet.spawn(test_gt, sem)
try: try:
@@ -206,7 +204,7 @@ class TestExceptionInGreenthread(LimitedTestCase):
g.kill() g.kill()
class TestHubSelection(LimitedTestCase): class TestHubSelection(tests.LimitedTestCase):
def test_explicit_hub(self): def test_explicit_hub(self):
oldhub = hubs.get_hub() oldhub = hubs.get_hub()
@@ -217,7 +215,7 @@ class TestHubSelection(LimitedTestCase):
hubs._threadlocal.hub = oldhub hubs._threadlocal.hub = oldhub
class TestHubBlockingDetector(LimitedTestCase): class TestHubBlockingDetector(tests.LimitedTestCase):
TEST_TIMEOUT = 10 TEST_TIMEOUT = 10
@skip_with_pyevent @skip_with_pyevent
@@ -245,7 +243,7 @@ class TestHubBlockingDetector(LimitedTestCase):
debug.hub_blocking_detection(False) debug.hub_blocking_detection(False)
class TestSuspend(LimitedTestCase): class TestSuspend(tests.LimitedTestCase):
TEST_TIMEOUT = 4 TEST_TIMEOUT = 4
longMessage = True longMessage = True
maxDiff = None maxDiff = None
@@ -283,25 +281,30 @@ except eventlet.Timeout:
shutil.rmtree(self.tempdir) shutil.rmtree(self.tempdir)
class TestBadFilenos(LimitedTestCase): def test_repeated_select_bad_fd():
from eventlet.green import select
@skip_with_pyevent def once():
def test_repeated_selects(self): try:
from eventlet.green import select select.select([-1], [], [])
self.assertRaises(ValueError, select.select, [-1], [], []) assert False, 'Expected ValueError'
self.assertRaises(ValueError, select.select, [-1], [], []) except ValueError:
pass
once()
once()
class TestFork(LimitedTestCase): @skip_with_pyevent
def test_fork():
@skip_with_pyevent tests.run_isolated('hub_fork.py')
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)
class TestDeadRunLoop(LimitedTestCase): def test_fork_simple():
tests.run_isolated('hub_fork_simple.py')
class TestDeadRunLoop(tests.LimitedTestCase):
TEST_TIMEOUT = 2 TEST_TIMEOUT = 2
class CustomException(Exception): class CustomException(Exception):
@@ -397,7 +400,3 @@ print('ok')
self.write_to_tempfile('newmod', module_source) self.write_to_tempfile('newmod', module_source)
output, _ = self.launch_subprocess('newmod.py') output, _ = self.launch_subprocess('newmod.py')
self.assertEqual(output, 'kqueue tried\nok\n') 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. are not leaked by the hub.
""" """
import gc import gc
from pprint import pformat import pprint
import sys
import weakref import weakref
from eventlet.support import clear_sys_exc_info import eventlet
from eventlet.green import socket from eventlet.green import socket
from eventlet.green.thread import start_new_thread
from eventlet.green.time import sleep
SOCKET_TIMEOUT = 0.1 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): def handle_request(s, raise_on_timeout):
try: try:
conn, address = s.accept() conn, address = s.accept()
except socket.timeout: except socket.timeout:
print('handle_request: server accept timeout')
if raise_on_timeout: if raise_on_timeout:
raise raise
else: else:
return return
# print('handle_request - accepted') print('handle_request: accepted')
res = conn.recv(100) res = conn.recv(100)
assert res == b'hello', repr(res) assert res == b'hello', repr(res)
# print('handle_request - recvd %r' % res) # print('handle_request: recvd %r' % res)
res = conn.send(b'bye') res = conn.sendall(b'bye')
# print('handle_request - sent %r' % res) # print('handle_request: sent %r' % res)
# print('handle_request - conn refcount: %s' % sys.getrefcount(conn)) # print('handle_request: conn refcount: %s' % sys.getrefcount(conn))
# conn.close()
def make_request(port): def make_request(addr):
# print('make_request') # print('make_request')
s = socket.socket() s = eventlet.connect(addr)
s.connect(('localhost', port))
# print('make_request - connected') # print('make_request - connected')
res = s.send(b'hello') res = s.sendall(b'hello')
# print('make_request - sent %s' % res) # print('make_request - sent %s' % res)
res = s.recv(100) res = s.recv(100)
assert res == b'bye', repr(res) assert res == b'bye', repr(res)
# print('make_request - recvd %r' % res) # print('make_request - recvd %r' % res)
# s.close()
def run_interaction(run_client): def run_interaction(run_client):
s, port = init_server() s = eventlet.listen(('127.0.0.1', 0))
start_new_thread(handle_request, (s, run_client)) s.settimeout(SOCKET_TIMEOUT)
addr = s.getsockname()
print('run_interaction: addr:', addr)
eventlet.spawn(handle_request, s, run_client)
if run_client: if run_client:
start_new_thread(make_request, (port,)) eventlet.spawn(make_request, addr)
sleep(0.1 + SOCKET_TIMEOUT) eventlet.sleep(0.1 + SOCKET_TIMEOUT)
# print(sys.getrefcount(s.fd)) print('run_interaction: refcount(s.fd)', sys.getrefcount(s.fd))
# s.close()
return weakref.ref(s.fd) return weakref.ref(s.fd)
def run_and_check(run_client): def run_and_check(run_client):
w = run_interaction(run_client=run_client) w = run_interaction(run_client=run_client)
clear_sys_exc_info() # clear_sys_exc_info()
gc.collect() gc.collect()
if w(): fd = w()
print(pformat(gc.get_referrers(w()))) print('run_and_check: weakref fd:', fd)
for x in gc.get_referrers(w()): if fd:
print(pformat(x)) 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): 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') raise AssertionError('server should be dead by now')

View File

@@ -56,7 +56,7 @@ class TestSocketErrors(unittest.TestCase):
def test_create_connection_refused(): def test_create_connection_refused():
errno = None errno = None
try: try:
socket.create_connection(('127.0.0.1', 0)) socket.create_connection(('127.0.0.1', 1))
except socket.error as ex: except socket.error as ex:
errno = ex.errno errno = ex.errno
assert errno in [111, 61, 10061], 'Expected socket.error ECONNREFUSED, got {0}'.format(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 time
import eventlet import eventlet
from eventlet import tpool, debug, event from eventlet import tpool
from eventlet.support import six from eventlet.support import six
import tests import tests
@@ -218,10 +218,13 @@ class TestTpool(tests.LimitedTestCase):
@tests.skip_with_pyevent @tests.skip_with_pyevent
def test_timeout(self): def test_timeout(self):
import time blocking = eventlet.patcher.original('time')
eventlet.Timeout(0.1, eventlet.TimeoutError()) eventlet.Timeout(0.1, eventlet.Timeout())
self.assertRaises(eventlet.TimeoutError, try:
tpool.execute, time.sleep, 0.3) tpool.execute(blocking.sleep, 0.3)
assert False, 'Expected Timeout'
except eventlet.Timeout:
pass
@tests.skip_with_pyevent @tests.skip_with_pyevent
def test_killall(self): def test_killall(self):
@@ -230,7 +233,7 @@ class TestTpool(tests.LimitedTestCase):
@tests.skip_with_pyevent @tests.skip_with_pyevent
def test_killall_remaining_results(self): def test_killall_remaining_results(self):
semaphore = event.Event() semaphore = eventlet.Event()
def native_fun(): def native_fun():
time.sleep(.5) time.sleep(.5)

View File

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