Commit 747630a1 authored by Denis Bilenko's avatar Denis Bilenko

backport testrunner from master branch

parent 9474ca75
[pep8]
ignore=E702,E265
max_line_length=160
exclude=.git,build,2.5,2.6,2.7,test_support.py,test_queue.py,patched_tests_setup.py,test_threading_2.py,lock_tests.py
language: python
python:
- "2.6"
- "2.7"
env:
- EXTRA=1
matrix:
include:
- python: 2.6
- python: 2.5
- python: 2.7
env: DEBUGPY=-dbg GEVENTSETUP_EV_VERIFY=3
- python: 2.6
env: DEBUGPY=-dbg GEVENTSETUP_EV_VERIFY=3
- python: 2.7
env: DEBUGPY=-dbg GEVENTSETUP_EV_VERIFY=3 GEVENT_FILE=thread
install:
- pip install --use-mirrors cython
- cython --version
- pip install --use-mirrors greenlet psycopg2 pysendfile web.py
- if [ "x$TRAVIS_PYTHON_VERSION" == "x2.5" ]; then sudo apt-get install libssl-dev libkrb5-dev libbluetooth-dev; pip install --use-mirrors sslfix; fi
- if [ "x$TRAVIS_PYTHON_VERSION" == "x2.7" ]; then pip install --use-mirrors -q pep8; fi
- python -c 'import greenlet; print greenlet, greenlet.__version__; import psycopg2; print psycopg2, psycopg2.__version__; import web; print web, web.__version__'
- export CYTHON=`which cython`
- python setup.py install
# work around travis not supporting 2.5
- python: "2.6"
env: PYTHON=python2.5
script:
- cd greentest && python testrunner.py --full --expected ../known_failures.txt
- if [[ $PYTHON == 'python2.5' ]]; then NWORKERS=4 PYTHON=python2.5 make travis_cpython_25; fi
- if [[ $PYTHON != 'python2.5' ]]; then NWORKERS=4 PYTHON=python$TRAVIS_PYTHON_VERSION make travis_cpython; fi
notifications:
email:
recipients:
- denis.bilenko@gmail.com
on_success: change
on_failure: change
email: false
......@@ -12,4 +12,4 @@ include changelog.rst
include MANIFEST.in
include AUTHORS
include Makefile.ext
include known_failures.txt
include known_failures.py
# This file is renamed to "Makefile.ext" in release tarballs so that setup.py won't try to
# run it. If you want setup.py to run "make" automatically, rename it back to "Makefile".
PYTHON ?= python
PYTHON ?= python${TRAVIS_PYTHON_VERSION}
CYTHON ?= cython
all: gevent/gevent.core.c gevent/gevent.ares.c gevent/gevent._semaphore.c gevent/gevent._util.c
......@@ -33,5 +33,83 @@ clean:
doc:
cd doc && PYTHONPATH=.. make html
whitespace:
! find . -not -path "./.git/*" -not -path "./build/*" -not -path "./libev/*" -not -path "./c-ares/*" -not -path "./doc/_build/*" -type f | xargs egrep -l " $$"
.PHONY: clean all doc
pep8:
${PYTHON} `which pep8` .
pyflakes:
${PYTHON} util/pyflakes.py
lint: whitespace pep8 pyflakes
travistest:
which ${PYTHON} || true
${PYTHON} --version
cd greenlet-* && ${PYTHON} setup.py install -q
${PYTHON} -c 'import greenlet; print (greenlet, greenlet.__version__)'
${PYTHON} setup.py install
make bench
cd greentest && GEVENT_RESOLVER=thread ${PYTHON} testrunner.py --config ../known_failures.py
cd greentest && GEVENT_RESOLVER=ares GEVENTARES_SERVERS=8.8.8.8 ${PYTHON} testrunner.py --config ../known_failures.py --ignore tests_that_dont_use_resolver.txt
cd greentest && GEVENT_FILE=thread ${PYTHON} testrunner.py --config ../known_failures.py `grep -l subprocess test_*.py`
bench:
${PYTHON} greentest/bench_sendall.py
travis_cpython:
make whitespace
pip install -q pep8
PYTHON=python make pep8
pip install -q pyflakes
PYTHON=python make pyflakes
sudo add-apt-repository -y ppa:chris-lea/cython
sudo add-apt-repository -y ppa:fkrull/deadsnakes
sudo apt-get -qq -y update
sudo -E apt-get -qq -y install ${PYTHON} ${PYTHON}-dev
sudo apt-get -qq -y install cython
cython --version
pip install -q --download . greenlet
unzip -q greenlet-*.zip
sudo -E make travistest
sudo -E apt-get -qq -y install ${PYTHON}-dbg
sudo -E PYTHON=${PYTHON}-dbg GEVENTSETUP_EV_VERIFY=3 make travistest
travis_cpython_25:
sudo add-apt-repository -y ppa:fkrull/deadsnakes
sudo add-apt-repository -y ppa:chris-lea/cython
sudo apt-get -qq -y update
sudo -E apt-get -qq -y install ${PYTHON} ${PYTHON}-dev
sudo apt-get -qq -y install cython
cython --version
pip install -q --download . greenlet
unzip -q greenlet-*.zip
pip install -q --download . multiprocessing
tar -xf multiprocessing*tar.gz
cd multiprocessing* && sudo ${PYTHON} setup.py install
sudo apt-get install libssl-dev libkrb5-dev libbluetooth-dev
pip install -q --download . ssl || true
tar -xf ssl*tar.gz
cd ssl* && sudo ${PYTHON} setup.py install
sudo -E make travistest
.PHONY: clean all doc pep8 whitespace pyflakes lint travistest travis
......@@ -44,7 +44,7 @@ running tests
cd greentest
PYTHONPATH=.. python testrunner.py --expected ../known_failures.txt
PYTHONPATH=.. python testrunner.py --config ../known_failures.py
.. _gevent: http://www.gevent.org
......
import sys
import time
#import time
from unittest import main
if sys.version_info[0] == 3:
from urllib import request as urllib2
......@@ -50,22 +50,22 @@ class Test_webproxy(Test_wsgiserver):
assert 'google' in data.lower(), repr(data)
class Test_webpy(Test_wsgiserver):
server = 'webpy.py'
not_found_message = 'not found'
def _test_hello(self):
status, data = self.read('/')
self.assertEqual(status, '200 OK')
assert "Hello, world" in data, repr(data)
def _test_long(self):
start = time.time()
status, data = self.read('/long')
delay = time.time() - start
assert 10 - 0.5 < delay < 10 + 0.5, delay
self.assertEqual(status, '200 OK')
self.assertEqual(data, 'Hello, 10 seconds later')
# class Test_webpy(Test_wsgiserver):
# server = 'webpy.py'
# not_found_message = 'not found'
#
# def _test_hello(self):
# status, data = self.read('/')
# self.assertEqual(status, '200 OK')
# assert "Hello, world" in data, repr(data)
#
# def _test_long(self):
# start = time.time()
# status, data = self.read('/long')
# delay = time.time() - start
# assert 10 - 0.5 < delay < 10 + 0.5, delay
# self.assertEqual(status, '200 OK')
# self.assertEqual(data, 'Hello, 10 seconds later')
if __name__ == '__main__':
......
......@@ -3,6 +3,7 @@ import os
import glob
import util
import atexit
# subprocess: include in subprocess tests
TIMEOUT = 120
......
from __future__ import with_statement
from gevent import monkey; monkey.patch_all()
from gevent import monkey; monkey.patch_all(subprocess=True)
import sys
import socket
from time import sleep
......
from gevent import monkey; monkey.patch_all()
from gevent import monkey; monkey.patch_all(subprocess=True)
import sys
from gevent.server import DatagramServer
from unittest import TestCase, main
......
......@@ -6,15 +6,19 @@ import util
cwd = '../examples/'
ignore = ['wsgiserver.py', 'wsgiserver_ssl.py', 'webproxy.py', 'webpy.py', 'unixsocket_server.py', 'unixsocket_client.py']
if sys.platform == 'win32':
ignore += ['geventsendfile.py', 'psycopg2_pool.py']
ignore = ['wsgiserver.py',
'wsgiserver_ssl.py',
'webproxy.py',
'webpy.py',
'unixsocket_server.py',
'unixsocket_client.py',
'psycopg2_pool.py',
'geventsendfile.py']
ignore += [x[14:] for x in glob.glob('test__example_*.py')]
default_time_range = (2, 4)
time_ranges = {
'concurrent_download.py': (0, 30),
'geventsendfile.py': (0, 4),
'processes.py': (0, 4)}
......
......@@ -44,9 +44,9 @@ class Test(greentest.TestCase):
def test_communicate(self):
p = subprocess.Popen([sys.executable, "-c",
'import sys,os;'
'sys.stderr.write("pineapple");'
'sys.stdout.write(sys.stdin.read())'],
'import sys,os;'
'sys.stderr.write("pineapple");'
'sys.stdout.write(sys.stdin.read())'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
......@@ -59,18 +59,18 @@ class Test(greentest.TestCase):
def test_universal1(self):
p = subprocess.Popen([sys.executable, "-c",
'import sys,os;' + SETBINARY +
'sys.stdout.write("line1\\n");'
'sys.stdout.flush();'
'sys.stdout.write("line2\\r");'
'sys.stdout.flush();'
'sys.stdout.write("line3\\r\\n");'
'sys.stdout.flush();'
'sys.stdout.write("line4\\r");'
'sys.stdout.flush();'
'sys.stdout.write("\\nline5");'
'sys.stdout.flush();'
'sys.stdout.write("\\nline6");'],
'import sys,os;' + SETBINARY +
'sys.stdout.write("line1\\n");'
'sys.stdout.flush();'
'sys.stdout.write("line2\\r");'
'sys.stdout.flush();'
'sys.stdout.write("line3\\r\\n");'
'sys.stdout.flush();'
'sys.stdout.write("line4\\r");'
'sys.stdout.flush();'
'sys.stdout.write("\\nline5");'
'sys.stdout.flush();'
'sys.stdout.write("\\nline6");'],
stdout=subprocess.PIPE,
universal_newlines=1)
try:
......@@ -88,16 +88,16 @@ class Test(greentest.TestCase):
def test_universal2(self):
p = subprocess.Popen([sys.executable, "-c",
'import sys,os;' + SETBINARY +
'sys.stdout.write("line1\\n");'
'sys.stdout.flush();'
'sys.stdout.write("line2\\r");'
'sys.stdout.flush();'
'sys.stdout.write("line3\\r\\n");'
'sys.stdout.flush();'
'sys.stdout.write("line4\\r\\nline5");'
'sys.stdout.flush();'
'sys.stdout.write("\\nline6");'],
'import sys,os;' + SETBINARY +
'sys.stdout.write("line1\\n");'
'sys.stdout.flush();'
'sys.stdout.write("line2\\r");'
'sys.stdout.flush();'
'sys.stdout.write("line3\\r\\n");'
'sys.stdout.flush();'
'sys.stdout.write("line4\\r\\nline5");'
'sys.stdout.flush();'
'sys.stdout.write("\\nline6");'],
stdout=subprocess.PIPE,
universal_newlines=1)
try:
......
#!/usr/bin/env python
import gevent
gevent.get_hub('select') # this is just to make sure we don't pass any fds to children
from gevent import monkey; monkey.patch_all()
import six
import sys
import os
import glob
import traceback
from time import time
import time
from datetime import timedelta
from gevent.pool import Pool
from multiprocessing.pool import ThreadPool
import util
from util import log
TIMEOUT = 180
NWORKERS = int(os.environ.get('NWORKERS') or 8)
pool = None
def spawn(*args, **kwargs):
g = pool.spawn(*args, **kwargs)
g.link_exception(lambda *args: sys.exit('Internal error in testrunner.py: %s %s' % (g, g.exception)))
return g
# tests that don't do well when run on busy box
RUN_ALONE = [
'test__threadpool.py',
'test__examples.py'
]
def run_many(tests, expected=None, failfast=False):
global NWORKERS, pool
start = time()
global NWORKERS
start = time.time()
total = 0
failed = {}
passed = {}
NWORKERS = min(len(tests), NWORKERS)
pool = Pool(NWORKERS)
NWORKERS = min(len(tests), NWORKERS) or 1
print('thread pool size: %s' % NWORKERS)
pool = ThreadPool(NWORKERS)
util.BUFFER_OUTPUT = NWORKERS > 1
def run_one(cmd, **kwargs):
......@@ -38,48 +40,69 @@ def run_many(tests, expected=None, failfast=False):
if result:
if failfast:
sys.exit(1)
# the tests containing AssertionError might have failed because
# we spawned more workers than CPUs
# we therefore will retry them sequentially
failed[result.name] = [cmd, kwargs, 'AssertionError' in (result.output or '')]
failed[result.name] = [cmd, kwargs]
else:
passed[result.name] = True
results = []
def reap():
for r in results[:]:
if not r.ready():
continue
if r.successful():
results.remove(r)
else:
r.get()
sys.exit('Internal error in testrunner.py: %r' % (r, ))
return len(results)
def reap_all():
while reap() > 0:
time.sleep(0.1)
def spawn(args, kwargs):
while True:
if reap() < NWORKERS:
r = pool.apply_async(run_one, (cmd, ), options or {})
results.append(r)
return
else:
time.sleep(0.1)
run_alone = []
try:
try:
for cmd, options in tests:
total += 1
spawn(run_one, cmd, **(options or {}))
gevent.wait()
options = options or {}
if matches(RUN_ALONE, cmd):
run_alone.append((cmd, options))
else:
spawn((cmd, ), options)
pool.close()
pool.join()
for cmd, options in run_alone:
run_one(cmd, **options)
except KeyboardInterrupt:
try:
if pool:
util.log('Waiting for currently running to finish...')
pool.join()
log('Waiting for currently running to finish...')
reap_all()
except KeyboardInterrupt:
util.report(total, failed, exit=False, took=time() - start, expected=expected)
util.log('(partial results)\n')
pool.terminate()
report(total, failed, passed, exit=False, took=time.time() - start, expected=expected)
log('(partial results)\n')
raise
except:
traceback.print_exc()
pool.kill() # this needed to kill the processes
pool.terminate()
raise
toretry = [key for (key, (cmd, kwargs, can_retry)) in failed.items() if can_retry]
failed_then_succeeded = []
if NWORKERS > 1 and toretry:
util.log('\nWill retry %s failed tests sequentially:\n- %s\n', len(toretry), '\n- '.join(toretry))
for name, (cmd, kwargs, _ignore) in failed.items():
if not util.run(cmd, buffer_output=False, **kwargs):
failed.pop(name)
failed_then_succeeded.append(name)
if failed_then_succeeded:
util.log('\n%s tests failed during concurrent run but succeeded when ran sequentially:', len(failed_then_succeeded))
util.log('- ' + '\n- '.join(failed_then_succeeded))
util.log('gevent version %s from %s', gevent.__version__, gevent.__file__)
util.report(total, failed, took=time() - start, expected=expected)
assert not pool, pool
reap_all()
report(total, failed, passed, took=time.time() - start, expected=expected)
def discover(tests=None, ignore=None):
......@@ -124,22 +147,83 @@ def load_list_from_file(filename):
return result
def full(args=None):
tests = []
def matches(expected, command, include_flaky=True):
if isinstance(command, list):
command = ' '.join(command)
for line in expected:
if not include_flaky and line.startswith('FLAKY '):
continue
if command.endswith(' ' + line.replace('FLAKY ', '')):
return True
return False
def format_seconds(seconds):
if seconds < 20:
return '%.1fs' % seconds
seconds = str(timedelta(seconds=round(seconds)))
if seconds.startswith('0:'):
seconds = seconds[2:]
return seconds
def report(total, failed, passed, exit=True, took=None, expected=None):
runtimelog = util.runtimelog
if runtimelog:
log('\nLongest-running tests:')
runtimelog.sort()
length = len('%.1f' % -runtimelog[0][0])
frmt = '%' + str(length) + '.1f seconds: %s'
for delta, name in runtimelog[:5]:
log(frmt, -delta, name)
if took:
took = ' in %s' % format_seconds(took)
else:
took = ''
failed_expected = []
failed_unexpected = []
passed_unexpected = []
for name in passed:
if matches(expected, name, include_flaky=False):
passed_unexpected.append(name)
if passed_unexpected:
log('\n%s/%s unexpected passes', len(passed_unexpected), total)
print_list(passed_unexpected)
if failed:
log('\n%s/%s tests failed%s', len(failed), total, took)
expected = set(expected or [])
for name in failed:
if matches(expected, name, include_flaky=True):
failed_expected.append(name)
else:
failed_unexpected.append(name)
if failed_expected:
log('\n%s/%s expected failures', len(failed_expected), total)
print_list(failed_expected)
if failed_unexpected:
log('\n%s/%s unexpected failures', len(failed_unexpected), total)
print_list(failed_unexpected)
else:
log('\n%s tests passed%s', total, took)
for setenv, ignore in [('GEVENT_RESOLVER=thread', None),
('GEVENT_RESOLVER=ares GEVENTARES_SERVERS=8.8.8.8', 'tests_that_dont_use_resolver.txt')]:
setenv = dict(x.split('=') for x in setenv.split())
for cmd, options in discover(args, ignore=ignore):
my_setenv = options.get('setenv', {})
my_setenv.update(setenv)
options['setenv'] = my_setenv
tests.append((cmd, options))
if exit:
if failed_unexpected:
sys.exit(min(100, len(failed_unexpected)))
if passed_unexpected:
sys.exit(101)
if total <= 0:
sys.exit('No tests found.')
if sys.version_info[:2] == (2, 7) and os.environ.get('EXTRA'):
tests.append(([sys.executable, '-u', 'xtest_pep8.py'], None))
return tests
def print_list(lst):
for name in lst:
log(' - %s', name)
def main():
......@@ -148,21 +232,21 @@ def main():
parser.add_option('--ignore')
parser.add_option('--discover', action='store_true')
parser.add_option('--full', action='store_true')
parser.add_option('--expected')
parser.add_option('--config')
parser.add_option('--failfast', action='store_true')
options, args = parser.parse_args()
options.expected = load_list_from_file(options.expected)
if options.full:
assert options.ignore is None, '--ignore and --full are not compatible'
tests = full(args)
else:
tests = discover(args, options.ignore)
FAILING_TESTS = []
if options.config:
config = {}
six.exec_(open(options.config).read(), config)
FAILING_TESTS = config['FAILING_TESTS']
tests = discover(args, options.ignore)
if options.discover:
for cmd, options in tests:
print util.getname(cmd, env=options.get('env'), setenv=options.get('setenv'))
print '%s tests found.' % len(tests)
print (util.getname(cmd, env=options.get('env'), setenv=options.get('setenv')))
print ('%s tests found.' % len(tests))
else:
run_many(tests, expected=options.expected, failfast=options.failfast)
run_many(tests, expected=FAILING_TESTS, failfast=options.failfast)
if __name__ == '__main__':
......
from __future__ import with_statement
import sys
import os
import re
import traceback
import unittest
import threading
import subprocess
import time
from datetime import timedelta
from gevent import subprocess, sleep, spawn_later
runtimelog = []
......@@ -81,6 +79,11 @@ def _kill(popen):
def kill(popen):
if popen.timer is not None:
popen.timer.cancel()
if popen.poll() is not None:
return
popen.was_killed = True
try:
if getattr(popen, 'setpgrp_enabled', None):
killpg(popen.pid)
......@@ -137,11 +140,13 @@ def start(command, **kwargs):
popen = Popen(command, preexec_fn=preexec_fn, env=env, **kwargs)
popen.name = name
popen.setpgrp_enabled = preexec_fn is not None
popen.was_killed = False
popen.timer = None
if timeout is not None:
popen._killer = spawn_later(timeout, kill, popen)
popen._killer._start_event.ref = False # XXX add 'ref' property to greenlet
else:
popen._killer = None
t = threading.Timer(timeout, kill, args=(popen, ))
t.setDaemon(True)
t.start()
popen.timer = t
return popen
......@@ -159,6 +164,9 @@ class RunResult(object):
return self.code
lock = threading.Lock()
def run(command, **kwargs):
buffer_output = kwargs.pop('buffer_output', BUFFER_OUTPUT)
if buffer_output:
......@@ -171,195 +179,30 @@ def run(command, **kwargs):
time_start = time.time()
out, err = popen.communicate()
took = time.time() - time_start
if popen.poll() is None:
if popen.was_killed or popen.poll() is None:
result = 'TIMEOUT'
else:
result = popen.poll()
finally:
if popen._killer is not None:
popen._killer.kill(block=False)
kill(popen)
assert not err
if out:
out = out.strip()
with lock:
if out:
out = ' ' + out.replace('\n', '\n ')
out = out.rstrip()
out += '\n'
log('| %s\n%s', name, out)
if result:
log('! %s [code %s] [took %.1fs]', name, result, took)
else:
log('- %s [took %.1fs]', name, took)
out = out.strip().decode('utf-8', 'ignore')
if out:
out = ' ' + out.replace('\n', '\n ')
out = out.rstrip()
out += '\n'
log('| %s\n%s', name, out)
if result:
log('! %s [code %s] [took %.1fs]', name, result, took)
else:
log('- %s [took %.1fs]', name, took)
if took >= MIN_RUNTIME:
runtimelog.append((-took, name))
return RunResult(result, out, name)
def parse_command(parts):
if isinstance(parts, basestring):
parts = parts.split()
environ = []
if parts[0] == '-':
del parts[0]
elif parts[0] == '*':
del parts[0]
environ = None
elif '=' in parts[0]:
while parts[0].count('='):
environ.append(parts[0])
del parts[0]
exe = parts[0]
del parts[0]
if exe == '*':
exe = None
else:
assert exe
assert not exe.startswith('-'), repr(exe)
return environ, exe, parts
def parse_line(line):
"""
>>> parse_line("* - /usr/bin/python -u test.py")
(None, [], '/usr/bin/python', ['-u', 'test.py'])
>>> parse_line("win32 * C:\\Python27\\python.exe -u -m monkey_test --Event test_subprocess.py")
('win32', None, 'C:\\\\Python27\\\\python.exe', ['-u', '-m', 'monkey_test', '--Event', 'test_subprocess.py'])
>>> parse_line("* GEVENTARES_SERVERS=8.8.8.8 GEVENT_RESOLVER=ares * -u test__socket_dns.py")
(None, ['GEVENTARES_SERVERS=8.8.8.8', 'GEVENT_RESOLVER=ares'], None, ['-u', 'test__socket_dns.py'])
"""
parts = line.split()
if len(parts) < 4:
raise ValueError('Expected "platform environ executable arguments", got %r' % line)
platform = parts[0]
if platform == '*':
platform = None
return (platform, ) + parse_command(parts[1:])
def match_word(pattern, word):
if isinstance(pattern, str) and isinstance(word, str) and '(' in pattern or '*' in pattern or '?' in pattern or '[' in pattern:
return re.match(pattern, word)
return pattern == word
def match_environ(expected_environ, actual_environ):
"""
>>> match_environ('GEVENT_RESOLVER=ares GEVENTARES_SERVERS=8.8.8.8',
... 'GEVENT_RESOLVER=ares GEVENTARES_SERVERS=8.8.8.8 GEVENT_FILE=thread')
True
>>> match_environ('GEVENT_RESOLVER=ares GEVENTARES_SERVERS=8.8.8.7',
... 'GEVENT_RESOLVER=ares GEVENTARES_SERVERS=8.8.8.8 GEVENT_FILE=thread')
False
>>> match_environ('GEVENT_RESOLVER=ares GEVENTARES_SERVERS=8.8.8.8 GEVENT_FILE=',
... 'GEVENT_RESOLVER=ares GEVENTARES_SERVERS=8.8.8.8 GEVENT_FILE=thread')
False
"""
if expected_environ is None:
return True
if isinstance(expected_environ, basestring):
expected_environ = expected_environ.split()
if isinstance(actual_environ, basestring):
actual_environ = actual_environ.split()
expected_environ = dict(x.split('=') for x in expected_environ)
actual_environ = dict(x.split('=') for x in actual_environ)
for key, expected_value in expected_environ.items():
value = actual_environ.pop(key, None)
if value is not None and value != expected_value:
return False
return True
def match_line(line, command):
expected_platform, expected_environ, expected_exe, expected_arguments = parse_line(line)
if expected_platform is not None and expected_platform != sys.platform:
return
environ, exe, arguments = parse_command(command)
if not match_environ(expected_environ, environ):
return
if expected_exe is not None and not match_word(expected_exe, exe):
return
return expected_arguments == arguments
def matches(expected, command):
"""
>>> matches(["* * C:\Python27\python.exe -u -m monkey_test --Event test_threading.py"],
... "C:\Python27\python.exe -u -m monkey_test --Event test_threading.py")
True
>>> matches(['* * /usr/bin/python2.5(-dbg)? -u -m monkey_test --Event test_urllib2net.py'],
... "/usr/bin/python2.5-dbg -u -m monkey_test --Event test_urllib2net.py")
True
>>> matches(['* * /usr/bin/python2.5(-dbg)? -u -m monkey_test --Event test_urllib2net.py'],
... "/usr/bin/python2.5 -u -m monkey_test --Event test_urllib2net.py")
True
>>> matches(['* * /usr/bin/python2.5(-dbg)? -u -m monkey_test --Event test_urllib2net.py'],
... "/usr/bin/python2.6 -u -m monkey_test --Event test_urllib2net.py")
False
>>> matches(['* GEVENT_RESOLVER=ares GEVENTARES_SERVERS=8.8.8.8 python -u test__subprocess.py'],
... "GEVENT_RESOLVER=ares GEVENTARES_SERVERS=8.8.8.8 GEVENT_FILE=thread python -u test__subprocess.py")
True
"""
for line in expected:
if match_line(line, command):
return True
return False
def format_seconds(seconds):
if seconds < 20:
return '%.1fs' % seconds
seconds = str(timedelta(seconds=round(seconds)))
if seconds.startswith('0:'):
seconds = seconds[2:]
return seconds
def report(total, failed, exit=True, took=None, expected=None):
if runtimelog:
log('\nLongest-running tests:')
runtimelog.sort()
length = len('%.1f' % -runtimelog[0][0])
frmt = '%' + str(length) + '.1f seconds: %s'
for delta, name in runtimelog[:5]:
log(frmt, -delta, name)
if took:
took = ' in %s' % format_seconds(took)
else:
took = ''
failed_expected = []
failed_unexpected = []
if failed:
log('\n%s/%s tests failed%s', len(failed), total, took)
expected = set(expected or [])
for name in failed:
if matches(expected, name):
failed_expected.append(name)
else:
failed_unexpected.append(name)
if failed_expected:
log('\n%s/%s expected failures', len(failed_expected), total)
for name in failed_expected:
log(' - %s', name)
if failed_unexpected:
log('\n%s/%s unexpected failures', len(failed_unexpected), total)
for name in failed_unexpected:
log(' - %s', name)
else:
log('\n%s tests passed%s', total, took)
if exit:
if failed_unexpected:
sys.exit(min(100, len(failed_unexpected)))
if total <= 0:
sys.exit('No tests found.')
class TestServer(unittest.TestCase):
cwd = '../examples/'
args = []
......@@ -375,12 +218,12 @@ class TestServer(unittest.TestCase):
def before(self):
if self.before_delay is not None:
sleep(self.before_delay)
time.sleep(self.before_delay)
assert self.popen.poll() is None, '%s died with code %s' % (self.server, self.popen.poll(), )
def after(self):
if self.after_delay is not None:
sleep(self.after_delay)
time.sleep(self.after_delay)
assert self.popen.poll() is None, '%s died with code %s' % (self.server, self.popen.poll(), )
def _run_all_tests(self):
......
import sys
import os
sys.stderr.write('pep8 --version: ')
if os.system('pep8 --version'):
sys.exit('ERROR: pep8 script not found')
if not os.path.exists('gevent') and not os.path.exists('setup.py'):
os.chdir('..')
commands = [
'pep8 --show-source --max-line-length=160 gevent/ setup.py',
'pep8 --show-source --max-line-length=160 --ignore E702 examples/*.py',
'pep8 --show-source --max-line-length=160 --ignore E702,E128 examples/webchat',
'pep8 --show-source --max-line-length=160 doc/',
"pep8 --max-line-length=200 --exclude 'test_support.py,test_queue.py,lock_tests.py,patched_tests_setup.py,test_threading_2.py' --ignore E702 greentest/*.py",
'pep8 --show-source --max-line-length=160 --ignore E203,E128,E124,E201 greentest/patched_tests_setup.py']
failures = 0
for command in commands:
sys.stderr.write('+ %s\n' % command)
if os.system(command):
failures += 1
sys.exit(failures)
# This is a list of known failures (=bugs).
# The tests listed there must fail (or testrunner.py will report error) unless they are prefixed with FLAKY
# in which cases the result of them is simply ignored
import os
import sys
CPYTHON_DBG = hasattr(sys, 'gettotalrefcount')
PYPY = hasattr(sys, 'pypy_version_info')
FAILING_TESTS = [
# needs investigating
'FLAKY test__issue6.py',
# bunch of SSLError: [Errno 1] _ssl.c:504: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
# seems to be Python/OpenSSL problem, not gevent's
'monkey_test --Event test_ssl.py',
'monkey_test test_ssl.py',
# Sometimes fails with AssertionError: ...\nIOError: close() called during concurrent operation on the same file object.\n'
# Sometimes it contains "\nUnhandled exception in thread started by \nsys.excepthook is missing\nlost sys.stderr\n"
"FLAKY test__subprocess_interrupted.py",
]
if os.environ.get('GEVENT_RESOLVER') == 'ares' or CPYTHON_DBG:
# XXX fix this
FAILING_TESTS += [
'FLAKY test__socket_dns.py',
'FLAKY test__socket_dns6.py',
]
if sys.platform == 'win32':
# currently gevent.core.stat watcher does not implement 'prev' and 'attr' attributes on Windows
FAILING_TESTS += ['test__core_stat.py']
# other Windows-related issues (need investigating)
FAILING_TESTS += [
'monkey_test test_threading.py',
'monkey_test --Event test_threading.py',
'monkey_test test_subprocess.py',
'monkey_test --Event test_subprocess.py'
]
if CPYTHON_DBG:
FAILING_TESTS += ['FLAKY test__backdoor.py']
if sys.version_info[:2] == (2, 5):
# no idea
FAILING_TESTS += [
'test_urllib2net.py',
'test_timeout.py',
'FLAKY test_urllib2_localnet.py',
'test_urllib2net.py',
'test__threading_vs_settrace.py',
'test__example_portforwarder.py',
'test__socket_close.py',
'test_timeout.py',
]
if __name__ == '__main__':
import pprint
pprint.pprint(FAILING_TESTS)
# This is a list of known failures (=bugs).
# format: platform environ executable arguments
# A star ("*") can be used instead of platform, environ or executable (means "any").
* GEVENTARES_SERVERS=8.8.8.8 GEVENT_RESOLVER=ares * -u test__socket_dns.py
* GEVENTARES_SERVERS=8.8.8.8 GEVENT_RESOLVER=ares * -u test__socket_dns6.py
# currently gevent.core.stat watcher does not implement 'prev' and 'attr' attributes on Windows
win32 * C:\Python27\python.exe -u test__core_stat.py
# other Windows-related issues (need investigating)
win32 * C:\Python27\python.exe -u -m monkey_test test_threading.py
win32 * C:\Python27\python.exe -u -m monkey_test --Event test_threading.py
win32 * C:\Python27\python.exe -u -m monkey_test test_subprocess.py
win32 * C:\Python27\python.exe -u -m monkey_test --Event test_subprocess.py
# these need investigating:
* * .*/python2.5(-dbg)? -u -m monkey_test --Event test_urllib2net.py
* * .*/python2.5(-dbg)? -u -m monkey_test test_urllib2net.py
* * .*/python2.5(-dbg)? -u test__threading_vs_settrace.py
* * .*/python2.5(-dbg)? -u test__example_portforwarder.py
* * .*/python2.5(-dbg)? -u test__socket_close.py
* * * -u test__issue6.py
# bunch of SSLError: [Errno 1] _ssl.c:504: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
# seems to be Python/OpenSSL problem, not gevent's
* * * -u -m monkey_test --Event test_ssl.py
* * * -u -m monkey_test test_ssl.py
* * /usr/bin/python2.[567]-dbg -u test__backdoor.py
#!/usr/bin/python
import sys
import re
import subprocess
IGNORED = r'''
gevent/socket.py:\d+: undefined name
gevent/socket.py:\d+: 'sslerror' imported but unused
gevent/socket.py:\d+: 'SSLType' imported but unused
gevent/socket.py:\d+: 'ssl' imported but unused
gevent/subprocess.py:\d+: undefined name
gevent/ssl.py:\d+: undefined name
gevent/__init__.py:\d+:.*imported but unused
gevent/__init__.py:\d+: redefinition of unused 'signal' from line
gevent/coros.py:\d+: 'from gevent.lock import *' used; unable to detect undefined names
gevent/coros.py:\d+: '__all__' imported but unused
gevent/thread.py:\d+: '_local' imported but unused
gevent/threading.py:\d+: '\w+' imported but unused
gevent/wsgi.py:1: 'from gevent.pywsgi import *' used; unable to detect undefined names
examples/webchat/urls.py:1: 'from django.conf.urls.defaults import *' used; unable to detect undefined names
greentest/test__queue.py:\d+: undefined name 'GenericGetTestCase'
greentest/test__server_pywsgi.py:
'''
IGNORED = IGNORED.strip().replace(' *', ' \\*').split('\n')
def is_ignored(line):
for pattern in IGNORED:
if re.match(pattern, line):
return True
popen = subprocess.Popen('%s `which pyflakes` gevent/ examples/ greentest/*.py util/ *.py' % sys.executable,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
output, errors = popen.communicate()
if errors:
sys.stderr.write(errors.decode())
if popen.poll() != 1:
sys.stderr.write(output + '\n')
sys.exit('pyflakes returned %r' % popen.poll())
if errors:
sys.exit(1)
assert output
output = output.strip().split('\n')
failed = False
for line in output:
line = line.strip()
if not is_ignored(line):
print 'E %s' % line
failed = True
#else:
# print 'I %s' % line
if failed:
sys.exit(1)
......@@ -39,7 +39,7 @@ if args[0:1] == ['test']:
system('%s setup.py build' % sys.executable)
os.chdir('greentest')
os.environ['PYTHONPATH'] = '.;..;../..'
system('%s testrunner.py --expected ../known_failures.txt' % sys.executable)
system('%s testrunner.py --config ../known_failures.py' % sys.executable)
elif args[0:1] == ['dist']:
prepare()
success = 0
......
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