mirror of
https://github.com/ammaraskar/pyCraft.git
synced 2024-11-22 02:08:56 +01:00
Add test case reproducing #146 (fixed to behave consistently)
This commit is contained in:
parent
7693961fb9
commit
93db454cb5
@ -479,6 +479,8 @@ class Connection(object):
|
|||||||
self.write_packet(handshake)
|
self.write_packet(handshake)
|
||||||
|
|
||||||
def _handle_exception(self, exc, exc_info):
|
def _handle_exception(self, exc, exc_info):
|
||||||
|
final_handler = self.handle_exception
|
||||||
|
|
||||||
# Call the current PacketReactor's exception handler.
|
# Call the current PacketReactor's exception handler.
|
||||||
try:
|
try:
|
||||||
if self.reactor.handle_exception(exc, exc_info):
|
if self.reactor.handle_exception(exc, exc_info):
|
||||||
@ -499,9 +501,9 @@ class Connection(object):
|
|||||||
caught = False
|
caught = False
|
||||||
|
|
||||||
# Call the user-specified final exception handler.
|
# Call the user-specified final exception handler.
|
||||||
if self.handle_exception not in (None, False):
|
if final_handler not in (None, False):
|
||||||
try:
|
try:
|
||||||
self.handle_exception(exc, exc_info)
|
final_handler(exc, exc_info)
|
||||||
except Exception as new_exc:
|
except Exception as new_exc:
|
||||||
exc, exc_info = new_exc, sys.exc_info()
|
exc, exc_info = new_exc, sys.exc_info()
|
||||||
|
|
||||||
@ -516,7 +518,7 @@ class Connection(object):
|
|||||||
self.disconnect(immediate=True)
|
self.disconnect(immediate=True)
|
||||||
|
|
||||||
# If allowed by the final exception handler, re-raise the exception.
|
# If allowed by the final exception handler, re-raise the exception.
|
||||||
if self.handle_exception is None and not caught:
|
if final_handler is None and not caught:
|
||||||
exc_value, exc_tb = exc_info[1:]
|
exc_value, exc_tb = exc_info[1:]
|
||||||
raise exc_value.with_traceback(exc_tb)
|
raise exc_value.with_traceback(exc_tb)
|
||||||
|
|
||||||
|
@ -70,11 +70,23 @@ class FakeClientHandler(object):
|
|||||||
# Communicate with the client until disconnected.
|
# Communicate with the client until disconnected.
|
||||||
try:
|
try:
|
||||||
self._run_handshake()
|
self._run_handshake()
|
||||||
self.socket.shutdown(socket.SHUT_RDWR)
|
try:
|
||||||
|
self.socket.shutdown(socket.SHUT_RDWR)
|
||||||
|
except IOError:
|
||||||
|
pass
|
||||||
|
except (FakeClientDisconnect, BrokenPipeError) as exc:
|
||||||
|
if not self.handle_abnormal_disconnect(exc):
|
||||||
|
raise
|
||||||
finally:
|
finally:
|
||||||
self.socket.close()
|
self.socket.close()
|
||||||
self.socket_file.close()
|
self.socket_file.close()
|
||||||
|
|
||||||
|
def handle_abnormal_disconnect(self, exc):
|
||||||
|
# Called when the client disconnects in an abnormal fashion. If this
|
||||||
|
# handler returns True, the error is ignored and is treated as a normal
|
||||||
|
# disconnection.
|
||||||
|
return False
|
||||||
|
|
||||||
def handle_connection(self):
|
def handle_connection(self):
|
||||||
# Called in the handshake state, just after the client connects,
|
# Called in the handshake state, just after the client connects,
|
||||||
# before any packets have been exchanged.
|
# before any packets have been exchanged.
|
||||||
@ -363,7 +375,7 @@ class FakeServer(object):
|
|||||||
'minecraft_version', 'client_handler_type', 'server_type', \
|
'minecraft_version', 'client_handler_type', 'server_type', \
|
||||||
'packets_handshake', 'packets_login', 'packets_playing', \
|
'packets_handshake', 'packets_login', 'packets_playing', \
|
||||||
'packets_status', 'lock', 'stopping', 'private_key', \
|
'packets_status', 'lock', 'stopping', 'private_key', \
|
||||||
'public_key_bytes', 'test_case',
|
'public_key_bytes', 'test_case'
|
||||||
|
|
||||||
def __init__(self, minecraft_version=None, compression_threshold=None,
|
def __init__(self, minecraft_version=None, compression_threshold=None,
|
||||||
client_handler_type=FakeClientHandler, private_key=None,
|
client_handler_type=FakeClientHandler, private_key=None,
|
||||||
@ -407,7 +419,7 @@ class FakeServer(object):
|
|||||||
self.listen_socket = socket.socket()
|
self.listen_socket = socket.socket()
|
||||||
self.listen_socket.settimeout(0.1)
|
self.listen_socket.settimeout(0.1)
|
||||||
self.listen_socket.bind(('localhost', 0))
|
self.listen_socket.bind(('localhost', 0))
|
||||||
self.listen_socket.listen(0)
|
self.listen_socket.listen(1)
|
||||||
|
|
||||||
self.lock = threading.Lock()
|
self.lock = threading.Lock()
|
||||||
self.stopping = False
|
self.stopping = False
|
||||||
@ -581,8 +593,6 @@ class _FakeServerTest(unittest.TestCase):
|
|||||||
if thread is not None and thread.is_alive():
|
if thread is not None and thread.is_alive():
|
||||||
errors.append({
|
errors.append({
|
||||||
'msg': 'Thread "%s" timed out.' % thread.name})
|
'msg': 'Thread "%s" timed out.' % thread.name})
|
||||||
if client_exc_info[0] is None:
|
|
||||||
client_exc_info[0] = client.exc_info
|
|
||||||
except Exception:
|
except Exception:
|
||||||
errors.insert(0, {
|
errors.insert(0, {
|
||||||
'msg': 'Exception in main thread',
|
'msg': 'Exception in main thread',
|
||||||
|
@ -360,6 +360,34 @@ class HandleExceptionTest(ConnectTest):
|
|||||||
client.connect()
|
client.connect()
|
||||||
|
|
||||||
|
|
||||||
|
class ExceptionReconnectTest(ConnectTest):
|
||||||
|
class CustomException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.phase = 0
|
||||||
|
|
||||||
|
def _start_client(self, client):
|
||||||
|
@client.listener(clientbound.play.JoinGamePacket)
|
||||||
|
def handle_join_game(packet):
|
||||||
|
if self.phase == 0:
|
||||||
|
self.phase += 1
|
||||||
|
raise self.CustomException
|
||||||
|
else:
|
||||||
|
raise fake_server.FakeServerTestSuccess
|
||||||
|
|
||||||
|
@client.exception_handler(self.CustomException, early=True)
|
||||||
|
def handle_custom_exception(exc, exc_info):
|
||||||
|
client.disconnect(immediate=True)
|
||||||
|
client.connect()
|
||||||
|
|
||||||
|
client.connect()
|
||||||
|
|
||||||
|
class client_handler_type(ConnectTest.client_handler_type):
|
||||||
|
def handle_abnormal_disconnect(self, exc):
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
class VersionNegotiationEdgeCases(fake_server._FakeServerTest):
|
class VersionNegotiationEdgeCases(fake_server._FakeServerTest):
|
||||||
earliest_version = SUPPORTED_PROTOCOL_VERSIONS[0]
|
earliest_version = SUPPORTED_PROTOCOL_VERSIONS[0]
|
||||||
latest_version = SUPPORTED_PROTOCOL_VERSIONS[-1]
|
latest_version = SUPPORTED_PROTOCOL_VERSIONS[-1]
|
||||||
|
Loading…
Reference in New Issue
Block a user