Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gevent
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
gevent
Commits
9d3f00d7
Commit
9d3f00d7
authored
Mar 21, 2019
by
Jason Madden
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Even more care with socket lifetimes. Getting a clean 3.7, 2.7 and 2.7pypy run locally now.
parent
c6cb4a41
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
97 additions
and
102 deletions
+97
-102
src/gevent/testing/patched_tests_setup.py
src/gevent/testing/patched_tests_setup.py
+21
-5
src/gevent/testing/testcase.py
src/gevent/testing/testcase.py
+0
-1
src/gevent/tests/test__server.py
src/gevent/tests/test__server.py
+72
-83
src/gevent/tests/test__server_pywsgi.py
src/gevent/tests/test__server_pywsgi.py
+4
-13
No files found.
src/gevent/testing/patched_tests_setup.py
View file @
9d3f00d7
...
@@ -113,6 +113,11 @@ def get_switch_expected(fullname):
...
@@ -113,6 +113,11 @@ def get_switch_expected(fullname):
disabled_tests = [
disabled_tests = [
# The server side takes awhile to shut down
# The server side takes awhile to shut down
'
test_httplib
.
HTTPSTest
.
test_local_bad_hostname
',
'
test_httplib
.
HTTPSTest
.
test_local_bad_hostname
',
# These were previously 3.5+ issues (same as above)
# but have been backported.
'
test_httplib
.
HTTPSTest
.
test_local_good_hostname
',
'
test_httplib
.
HTTPSTest
.
test_local_unknown_cert
',
'
test_threading
.
ThreadTests
.
test_PyThreadState_SetAsyncExc
',
'
test_threading
.
ThreadTests
.
test_PyThreadState_SetAsyncExc
',
# uses some internal C API of threads not available when threads are emulated with greenlets
# uses some internal C API of threads not available when threads are emulated with greenlets
...
@@ -232,14 +237,21 @@ if PY2 and PYPY:
...
@@ -232,14 +237,21 @@ if PY2 and PYPY:
'test_httpservers.BaseHTTPServerTestCase.test_head_keep_alive'
,
'test_httpservers.BaseHTTPServerTestCase.test_head_keep_alive'
,
'test_httpservers.BaseHTTPServerTestCase.test_send_blank'
,
'test_httpservers.BaseHTTPServerTestCase.test_send_blank'
,
'test_httpservers.BaseHTTPServerTestCase.test_send_error'
,
'test_httpservers.BaseHTTPServerTestCase.test_send_error'
,
'test_httpservers.BaseHTTPServerTestCase.test_command'
,
'test_httpservers.BaseHTTPServerTestCase.test_handler'
,
'test_httpservers.CGIHTTPServerTestcase.test_post'
,
'test_httpservers.CGIHTTPServerTestcase.test_post'
,
'test_httpservers.CGIHTTPServerTestCase.test_query_with_continuous_slashes'
,
'test_httpservers.CGIHTTPServerTestCase.test_query_with_continuous_slashes'
,
'test_httpservers.CGIHTTPServerTestCase.test_query_with_multiple_question_mark'
,
'test_httpservers.CGIHTTPServerTestCase.test_query_with_multiple_question_mark'
,
'test_httpservers.CGIHTTPServerTestCase.test_os_environ_is_not_altered'
,
'test_httpservers.CGIHTTPServerTestCase.test_os_environ_is_not_altered'
,
# Th
is is
flaxy, apparently a race condition? Began with PyPy 2.7-7
# Th
ese are
flaxy, apparently a race condition? Began with PyPy 2.7-7
'test_asyncore.TestAPI_UsePoll.test_handle_error'
,
'test_asyncore.TestAPI_UsePoll.test_handle_error'
,
'test_asyncore.TestAPI_UsePoll.test_handle_read'
,
'test_asyncore.TestAPI_UsePoll.test_handle_read'
,
# This one sometimes results on connection refused
'test_urllib2_localnet.TestUrlopen.test_info'
,
# Sometimes hangs
'test_ssl.ThreadedTests.test_socketserver'
,
]
]
if
LIBUV
:
if
LIBUV
:
...
@@ -856,6 +868,9 @@ if PYPY:
...
@@ -856,6 +868,9 @@ if PYPY:
'test_httpservers.CGIHTTPServerTestCase.test_invaliduri'
:
_gc_at_end
,
'test_httpservers.CGIHTTPServerTestCase.test_invaliduri'
:
_gc_at_end
,
'test_httpservers.CGIHTTPServerTestCase.test_issue19435'
:
_gc_at_end
,
'test_httpservers.CGIHTTPServerTestCase.test_issue19435'
:
_gc_at_end
,
'test_httplib.TunnelTests.test_connect'
:
_gc_at_end
,
'test_httplib.SourceAddressTest.testHTTPConnectionSourceAddress'
:
_gc_at_end
,
# Unclear
# Unclear
'test_urllib2_localnet.ProxyAuthTests.test_proxy_with_bad_password_raises_httperror'
:
_gc_at_end
,
'test_urllib2_localnet.ProxyAuthTests.test_proxy_with_bad_password_raises_httperror'
:
_gc_at_end
,
'test_urllib2_localnet.ProxyAuthTests.test_proxy_with_no_password_raises_httperror'
:
_gc_at_end
,
'test_urllib2_localnet.ProxyAuthTests.test_proxy_with_no_password_raises_httperror'
:
_gc_at_end
,
...
@@ -898,10 +913,6 @@ if PY35:
...
@@ -898,10 +913,6 @@ if PY35:
# it should be found at runtime.
# it should be found at runtime.
'test_socket.GeneralModuleTests.test_sock_ioctl'
,
'test_socket.GeneralModuleTests.test_sock_ioctl'
,
# See comments for 2.7; these hang
'test_httplib.HTTPSTest.test_local_good_hostname'
,
'test_httplib.HTTPSTest.test_local_unknown_cert'
,
# XXX This fails for an unknown reason
# XXX This fails for an unknown reason
'test_httplib.HeaderTests.test_parse_all_octets'
,
'test_httplib.HeaderTests.test_parse_all_octets'
,
]
]
...
@@ -1042,6 +1053,11 @@ if PY37:
...
@@ -1042,6 +1053,11 @@ if PY37:
# but it passes when they run it and fails when we do. It's not
# but it passes when they run it and fails when we do. It's not
# clear why.
# clear why.
'test_ssl.ThreadedTests.test_check_hostname_idn'
,
'test_ssl.ThreadedTests.test_check_hostname_idn'
,
# These appear to hang, haven't investigated why
'test_ssl.SimpleBackgroundTests.test_get_server_certificate'
,
# Probably the same as NetworkConnectionNoServer.test_create_connection_timeout
'test_socket.NetworkConnectionNoServer.test_create_connection'
,
]
]
if
APPVEYOR
:
if
APPVEYOR
:
...
...
src/gevent/testing/testcase.py
View file @
9d3f00d7
...
@@ -203,7 +203,6 @@ class TestCase(TestCaseMetaClass("NewBase",
...
@@ -203,7 +203,6 @@ class TestCase(TestCaseMetaClass("NewBase",
self
.
close_on_teardown
=
[]
self
.
close_on_teardown
=
[]
for
x
in
to_close
:
for
x
in
to_close
:
print
(
"Closing"
,
x
)
close
=
getattr
(
x
,
'close'
,
x
)
close
=
getattr
(
x
,
'close'
,
x
)
try
:
try
:
close
()
close
()
...
...
src/gevent/tests/test__server.py
View file @
9d3f00d7
from
__future__
import
print_function
,
division
from
__future__
import
print_function
,
division
from
contextlib
import
contextmanager
import
unittest
import
unittest
import
errno
import
errno
import
os
import
os
...
@@ -47,8 +48,8 @@ class Settings(object):
...
@@ -47,8 +48,8 @@ class Settings(object):
@
staticmethod
@
staticmethod
def
assertAcceptedConnectionError
(
inst
):
def
assertAcceptedConnectionError
(
inst
):
conn
=
inst
.
makefile
()
with
inst
.
makefile
()
as
conn
:
result
=
conn
.
read
()
result
=
conn
.
read
()
inst
.
assertFalse
(
result
)
inst
.
assertFalse
(
result
)
assert500
=
assertAcceptedConnectionError
assert500
=
assertAcceptedConnectionError
...
@@ -107,6 +108,7 @@ class TestCase(greentest.TestCase):
...
@@ -107,6 +108,7 @@ class TestCase(greentest.TestCase):
return
server_host
,
self
.
server
.
server_port
,
family
return
server_host
,
self
.
server
.
server_port
,
family
@
contextmanager
def
makefile
(
self
,
timeout
=
_DEFAULT_SOCKET_TIMEOUT
,
bufsize
=
1
):
def
makefile
(
self
,
timeout
=
_DEFAULT_SOCKET_TIMEOUT
,
bufsize
=
1
):
server_host
,
server_port
,
family
=
self
.
get_server_host_port_family
()
server_host
,
server_port
,
family
=
self
.
get_server_host_port_family
()
bufarg
=
'buffering'
if
PY3
else
'bufsize'
bufarg
=
'buffering'
if
PY3
else
'bufsize'
...
@@ -116,41 +118,35 @@ class TestCase(greentest.TestCase):
...
@@ -116,41 +118,35 @@ class TestCase(greentest.TestCase):
# makefile() opened in r, and r+ is not allowed
# makefile() opened in r, and r+ is not allowed
makefile_kwargs
[
'mode'
]
=
'rwb'
makefile_kwargs
[
'mode'
]
=
'rwb'
sock
=
socket
.
socket
(
family
=
family
)
with
socket
.
socket
(
family
=
family
)
as
sock
:
self
.
_close_on_teardown
(
sock
)
rconn
=
None
rconn
=
None
try
:
#print("Connecting to", self.server, self.server.started, server_host, server_port)
sock
.
connect
((
server_host
,
server_port
))
sock
.
connect
((
server_host
,
server_port
))
sock
.
settimeout
(
timeout
)
rconn
=
sock
.
makefile
(
**
makefile_kwargs
)
with
sock
.
makefile
(
**
makefile_kwargs
)
as
rconn
:
self
.
_close_on_teardown
(
rconn
)
# We want the socket to be accessible from the fileobject
if
PY3
:
# XXX: Why do we do this?
# we return. On Python 2, natively this is available as
self
.
_close_on_teardown
(
rconn
.
_sock
)
# _sock, but Python 3 doesn't have that.
rconn
.
_sock
=
sock
# We emulate it by assigning to a new attribute; note that this
rconn
.
_sock
.
settimeout
(
timeout
)
# (probably) introduces a cycle on Python 3, so we are careful
except
Exception
:
# to clear it.
#print("Failed to connect to", self.server)
rconn
.
gevent_sock
=
sock
# avoid ResourceWarning under Py3/PyPy
try
:
sock
.
close
()
yield
rconn
if
rconn
is
not
None
:
finally
:
rconn
.
close
()
del
rconn
.
gevent_sock
del
rconn
del
sock
raise
sock
.
close
()
return
rconn
def
send_request
(
self
,
url
=
'/'
,
timeout
=
_DEFAULT_SOCKET_TIMEOUT
,
bufsize
=
1
):
def
send_request
(
self
,
url
=
'/'
,
timeout
=
_DEFAULT_SOCKET_TIMEOUT
,
bufsize
=
1
):
conn
=
self
.
makefile
(
timeout
=
timeout
,
bufsize
=
bufsize
)
with
self
.
makefile
(
timeout
=
timeout
,
bufsize
=
bufsize
)
as
conn
:
conn
.
write
((
'GET %s HTTP/1.0
\
r
\
n
\
r
\
n
'
%
url
).
encode
(
'latin-1'
))
self
.
send_request_to_fd
(
conn
,
url
)
conn
.
flush
()
return
conn
def
send_request_to_fd
(
self
,
fd
,
url
=
'/'
):
fd
.
write
((
'GET %s HTTP/1.0
\
r
\
n
\
r
\
n
'
%
url
).
encode
(
'latin-1'
))
fd
.
flush
()
def
assertConnectionRefused
(
self
):
def
assertConnectionRefused
(
self
):
with
self
.
assertRaises
(
socket
.
error
)
as
exc
:
with
self
.
assertRaises
(
socket
.
error
)
as
exc
:
conn
=
self
.
makefile
()
with
self
.
makefile
()
as
conn
:
conn
.
close
()
conn
.
close
()
ex
=
exc
.
exception
ex
=
exc
.
exception
self
.
assertIn
(
ex
.
args
[
0
],
(
errno
.
ECONNREFUSED
,
errno
.
EADDRNOTAVAIL
),
ex
)
self
.
assertIn
(
ex
.
args
[
0
],
(
errno
.
ECONNREFUSED
,
errno
.
EADDRNOTAVAIL
),
ex
)
...
@@ -168,31 +164,28 @@ class TestCase(greentest.TestCase):
...
@@ -168,31 +164,28 @@ class TestCase(greentest.TestCase):
self
.
Settings
.
assertPoolFull
(
self
)
self
.
Settings
.
assertPoolFull
(
self
)
def
assertNotAccepted
(
self
):
def
assertNotAccepted
(
self
):
conn
=
self
.
makefile
()
with
self
.
makefile
()
as
conn
:
conn
.
write
(
b'GET / HTTP/1.0
\
r
\
n
\
r
\
n
'
)
conn
.
write
(
b'GET / HTTP/1.0
\
r
\
n
\
r
\
n
'
)
conn
.
flush
()
conn
.
flush
()
result
=
b''
result
=
b''
try
:
try
:
while
True
:
while
True
:
data
=
conn
.
_sock
.
recv
(
1
)
data
=
conn
.
gevent_sock
.
recv
(
1
)
if
not
data
:
if
not
data
:
break
break
result
+=
data
result
+=
data
except
socket
.
timeout
:
except
socket
.
timeout
:
self
.
assertFalse
(
result
)
self
.
assertFalse
(
result
)
return
return
finally
:
conn
.
close
()
self
.
assertTrue
(
result
.
startswith
(
b'HTTP/1.0 500 Internal Server Error'
),
repr
(
result
))
self
.
assertTrue
(
result
.
startswith
(
b'HTTP/1.0 500 Internal Server Error'
),
repr
(
result
))
def
assertRequestSucceeded
(
self
,
timeout
=
_DEFAULT_SOCKET_TIMEOUT
):
def
assertRequestSucceeded
(
self
,
timeout
=
_DEFAULT_SOCKET_TIMEOUT
):
conn
=
self
.
makefile
(
timeout
=
timeout
)
with
self
.
makefile
(
timeout
=
timeout
)
as
conn
:
try
:
conn
.
write
(
b'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
()
finally
:
conn
.
close
()
self
.
assertTrue
(
result
.
endswith
(
b'
\
r
\
n
\
r
\
n
PONG'
),
repr
(
result
))
self
.
assertTrue
(
result
.
endswith
(
b'
\
r
\
n
\
r
\
n
PONG'
),
repr
(
result
))
def
start_server
(
self
):
def
start_server
(
self
):
...
@@ -330,22 +323,21 @@ class TestDefaultSpawn(TestCase):
...
@@ -330,22 +323,21 @@ class TestDefaultSpawn(TestCase):
def
test_server_closes_client_sockets
(
self
):
def
test_server_closes_client_sockets
(
self
):
self
.
server
=
self
.
ServerClass
((
greentest
.
DEFAULT_BIND_ADDR
,
0
),
lambda
*
args
:
[])
self
.
server
=
self
.
ServerClass
((
greentest
.
DEFAULT_BIND_ADDR
,
0
),
lambda
*
args
:
[])
self
.
server
.
start
()
self
.
server
.
start
()
conn
=
self
.
send_request
()
with
self
.
makefile
()
as
conn
:
# use assert500 below?
self
.
send_request_to_fd
(
conn
)
with
gevent
.
Timeout
.
_start_new_or_dummy
(
1
):
# use assert500 below?
try
:
with
gevent
.
Timeout
.
_start_new_or_dummy
(
1
):
result
=
conn
.
read
()
try
:
if
result
:
result
=
conn
.
read
()
assert
result
.
startswith
(
'HTTP/1.0 500 Internal Server Error'
),
repr
(
result
)
if
result
:
except
socket
.
error
as
ex
:
assert
result
.
startswith
(
'HTTP/1.0 500 Internal Server Error'
),
repr
(
result
)
if
ex
.
args
[
0
]
==
10053
:
except
socket
.
error
as
ex
:
pass
# "established connection was aborted by the software in your host machine"
if
ex
.
args
[
0
]
==
10053
:
elif
ex
.
args
[
0
]
==
errno
.
ECONNRESET
:
pass
# "established connection was aborted by the software in your host machine"
pass
elif
ex
.
args
[
0
]
==
errno
.
ECONNRESET
:
else
:
pass
raise
else
:
finally
:
raise
conn
.
close
()
self
.
stop_server
()
self
.
stop_server
()
...
@@ -403,21 +395,20 @@ class TestPoolSpawn(TestDefaultSpawn):
...
@@ -403,21 +395,20 @@ class TestPoolSpawn(TestDefaultSpawn):
"requests in the pool be full."
)
"requests in the pool be full."
)
def
test_pool_full
(
self
):
def
test_pool_full
(
self
):
self
.
init_server
()
self
.
init_server
()
short_request
=
self
.
send_request
(
'/short'
)
with
self
.
makefile
()
as
long_request
:
long_request
=
self
.
send_request
(
'/long'
)
with
self
.
makefile
()
as
short_request
:
# keep long_request in scope, otherwise the connection will be closed
self
.
send_request_to_fd
(
short_request
,
'/short'
)
gevent
.
get_hub
().
loop
.
update_now
()
self
.
send_request_to_fd
(
long_request
,
'/long'
)
gevent
.
sleep
(
_DEFAULT_SOCKET_TIMEOUT
/
10.0
)
self
.
assertPoolFull
()
# keep long_request in scope, otherwise the connection will be closed
self
.
assertPoolFull
()
gevent
.
get_hub
().
loop
.
update_now
()
# XXX Not entirely clear why this fails (timeout) on appveyor;
gevent
.
sleep
(
_DEFAULT_SOCKET_TIMEOUT
/
10.0
)
# underlying socket timeout causing the long_request to close?
self
.
assertPoolFull
()
self
.
assertPoolFull
()
self
.
assertPoolFull
()
short_request
.
_sock
.
close
()
# XXX Not entirely clear why this fails (timeout) on appveyor;
if
PY3
:
# underlying socket timeout causing the long_request to close?
# We use two makefiles to simulate reading/writing
self
.
assertPoolFull
()
# 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
(
_DEFAULT_SOCKET_TIMEOUT
)
gevent
.
sleep
(
_DEFAULT_SOCKET_TIMEOUT
)
...
@@ -429,8 +420,6 @@ class TestPoolSpawn(TestDefaultSpawn):
...
@@ -429,8 +420,6 @@ class TestPoolSpawn(TestDefaultSpawn):
except
socket
.
timeout
:
except
socket
.
timeout
:
greentest
.
reraiseFlakyTestTimeout
()
greentest
.
reraiseFlakyTestTimeout
()
del
long_request
test_pool_full
.
error_fatal
=
False
test_pool_full
.
error_fatal
=
False
...
...
src/gevent/tests/test__server_pywsgi.py
View file @
9d3f00d7
...
@@ -4,7 +4,7 @@ import gevent.testing as greentest
...
@@ -4,7 +4,7 @@ import gevent.testing as greentest
import
gevent
import
gevent
from
gevent
import
pywsgi
from
gevent
import
pywsgi
import
test__server
from
gevent.tests
import
test__server
def
application
(
environ
,
start_response
):
def
application
(
environ
,
start_response
):
...
@@ -51,26 +51,20 @@ class Settings(test__server.Settings):
...
@@ -51,26 +51,20 @@ class Settings(test__server.Settings):
@
staticmethod
@
staticmethod
def
assert500
(
inst
):
def
assert500
(
inst
):
conn
=
inst
.
makefile
()
with
inst
.
makefile
()
as
conn
:
try
:
conn
.
write
(
b'GET / HTTP/1.0
\
r
\
n
\
r
\
n
'
)
conn
.
write
(
b'GET / HTTP/1.0
\
r
\
n
\
r
\
n
'
)
result
=
conn
.
read
()
result
=
conn
.
read
()
inst
.
assertTrue
(
result
.
startswith
(
internal_error_start
),
inst
.
assertTrue
(
result
.
startswith
(
internal_error_start
),
(
result
,
internal_error_start
))
(
result
,
internal_error_start
))
inst
.
assertTrue
(
result
.
endswith
(
internal_error_end
),
inst
.
assertTrue
(
result
.
endswith
(
internal_error_end
),
(
result
,
internal_error_end
))
(
result
,
internal_error_end
))
finally
:
conn
.
close
()
@
staticmethod
@
staticmethod
def
assert503
(
inst
):
def
assert503
(
inst
):
conn
=
inst
.
makefile
()
with
inst
.
makefile
()
as
conn
:
try
:
conn
.
write
(
b'GET / HTTP/1.0
\
r
\
n
\
r
\
n
'
)
conn
.
write
(
b'GET / HTTP/1.0
\
r
\
n
\
r
\
n
'
)
result
=
conn
.
read
()
result
=
conn
.
read
()
inst
.
assertEqual
(
result
,
internal_error503
)
inst
.
assertEqual
(
result
,
internal_error503
)
finally
:
conn
.
close
()
@
staticmethod
@
staticmethod
def
assertPoolFull
(
inst
):
def
assertPoolFull
(
inst
):
...
@@ -79,12 +73,9 @@ class Settings(test__server.Settings):
...
@@ -79,12 +73,9 @@ class Settings(test__server.Settings):
@
staticmethod
@
staticmethod
def
assertAcceptedConnectionError
(
inst
):
def
assertAcceptedConnectionError
(
inst
):
conn
=
inst
.
makefile
()
with
inst
.
makefile
()
as
conn
:
try
:
result
=
conn
.
read
()
result
=
conn
.
read
()
inst
.
assertFalse
(
result
)
inst
.
assertFalse
(
result
)
finally
:
conn
.
close
()
@
staticmethod
@
staticmethod
def
fill_default_server_args
(
inst
,
kwargs
):
def
fill_default_server_args
(
inst
,
kwargs
):
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment