Update the test suite.
- monkey-patch our own monkey-patched idle_call to run events immediatly rather than adding them to the event queue, and add a fake transport with a fake socket. - remove the test file related to xep_0059 as it relies on blocking behavior, and comment out one xep_0030 test uses xep_0059 - remove many instances of threading and sleep()s because they do nothing except waste time and introduce race conditions. - keep exactly two sleep() in IoT xeps because they rely on timeouts
This commit is contained in:
@@ -6,6 +6,6 @@
|
||||
See the file LICENSE for copying permission.
|
||||
"""
|
||||
|
||||
from slixmpp.test.mocksocket import TestSocket
|
||||
from slixmpp.test.mocksocket import TestSocket, TestTransport
|
||||
from slixmpp.test.livesocket import TestLiveSocket
|
||||
from slixmpp.test.slixtest import *
|
||||
|
||||
@@ -150,3 +150,92 @@ class TestSocket(object):
|
||||
return self.recv_queue.get(block, timeout)
|
||||
except:
|
||||
return None
|
||||
|
||||
class TestTransport(object):
|
||||
|
||||
"""
|
||||
A transport socket that reads and writes to queues instead
|
||||
of an actual networking socket.
|
||||
|
||||
Methods:
|
||||
next_sent -- Return the next sent stanza.
|
||||
recv_data -- Make a stanza available to read next.
|
||||
recv -- Read the next stanza from the socket.
|
||||
send -- Write a stanza to the socket.
|
||||
makefile -- Dummy call, returns self.
|
||||
read -- Read the next stanza from the socket.
|
||||
"""
|
||||
|
||||
def __init__(self, xmpp):
|
||||
self.xmpp = xmpp
|
||||
self.socket = TestSocket()
|
||||
# ------------------------------------------------------------------
|
||||
# Testing Interface
|
||||
|
||||
def next_sent(self, timeout=None):
|
||||
"""
|
||||
Get the next stanza that has been 'sent'.
|
||||
|
||||
Arguments:
|
||||
timeout -- Optional timeout for waiting for a new value.
|
||||
"""
|
||||
return self.socket.next_sent()
|
||||
|
||||
def disconnect_error(self):
|
||||
"""
|
||||
Simulate a disconnect error by raising a socket.error exception
|
||||
for any current or further socket operations.
|
||||
"""
|
||||
self.socket.disconnect_error()
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Socket Interface
|
||||
|
||||
def recv(self, *args, **kwargs):
|
||||
"""
|
||||
Read a value from the received queue.
|
||||
|
||||
Arguments:
|
||||
Placeholders. Same as for socket.Socket.recv.
|
||||
"""
|
||||
return
|
||||
|
||||
def write(self, data):
|
||||
"""
|
||||
Send data by placing it in the send queue.
|
||||
|
||||
Arguments:
|
||||
data -- String value to write.
|
||||
"""
|
||||
self.socket.send(data)
|
||||
return len(data)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# File Socket
|
||||
|
||||
def makefile(self, *args, **kwargs):
|
||||
"""
|
||||
File socket version to use with ElementTree.
|
||||
|
||||
Arguments:
|
||||
Placeholders, same as socket.Socket.makefile()
|
||||
"""
|
||||
return self
|
||||
|
||||
def read(self, block=True, timeout=None, **kwargs):
|
||||
"""
|
||||
Implement the file socket interface.
|
||||
|
||||
Arguments:
|
||||
block -- Indicate if the read should block until a
|
||||
value is ready.
|
||||
timeout -- Time in seconds a block should last before
|
||||
returning None.
|
||||
"""
|
||||
return self.socket.recv(block, timeout, **kwargs)
|
||||
|
||||
def get_extra_info(self, *args, **kwargs):
|
||||
return self.socket
|
||||
|
||||
def abort(self, *args, **kwargs):
|
||||
return
|
||||
|
||||
@@ -10,15 +10,19 @@ import unittest
|
||||
from queue import Queue
|
||||
from xml.parsers.expat import ExpatError
|
||||
|
||||
from slixmpp.test import TestTransport
|
||||
from slixmpp import ClientXMPP, ComponentXMPP
|
||||
from slixmpp.stanza import Message, Iq, Presence
|
||||
from slixmpp.test import TestSocket, TestLiveSocket
|
||||
from slixmpp.xmlstream import ET
|
||||
from slixmpp.xmlstream import ElementBase
|
||||
from slixmpp.xmlstream.tostring import tostring
|
||||
from slixmpp.xmlstream.matcher import StanzaPath, MatcherId, MatchIDSender
|
||||
from slixmpp.xmlstream.matcher import MatchXMLMask, MatchXPath
|
||||
|
||||
import asyncio
|
||||
cls = asyncio.get_event_loop().__class__
|
||||
|
||||
cls.idle_call = lambda self, callback: callback()
|
||||
|
||||
class SlixTest(unittest.TestCase):
|
||||
|
||||
@@ -326,41 +330,27 @@ class SlixTest(unittest.TestCase):
|
||||
else:
|
||||
raise ValueError("Unknown XMPP connection mode.")
|
||||
|
||||
self.xmpp.connection_made(TestTransport(self.xmpp))
|
||||
self.xmpp.session_bind_event.set()
|
||||
# Remove unique ID prefix to make it easier to test
|
||||
self.xmpp._id_prefix = ''
|
||||
self.xmpp._disconnect_wait_for_threads = False
|
||||
self.xmpp.default_lang = None
|
||||
self.xmpp.peer_default_lang = None
|
||||
|
||||
# We will use this to wait for the session_start event
|
||||
# for live connections.
|
||||
skip_queue = Queue()
|
||||
# Simulate connecting for mock sockets.
|
||||
self.xmpp.auto_reconnect = False
|
||||
|
||||
if socket == 'mock':
|
||||
self.xmpp.set_socket(TestSocket())
|
||||
# Must have the stream header ready for xmpp.process() to work.
|
||||
if not header:
|
||||
header = self.xmpp.stream_header
|
||||
|
||||
# Simulate connecting for mock sockets.
|
||||
self.xmpp.auto_reconnect = False
|
||||
self.xmpp.state._set_state('connected')
|
||||
self.xmpp.data_received(header)
|
||||
|
||||
# Must have the stream header ready for xmpp.process() to work.
|
||||
if not header:
|
||||
header = self.xmpp.stream_header
|
||||
self.xmpp.socket.recv_data(header)
|
||||
elif socket == 'live':
|
||||
self.xmpp.socket_class = TestLiveSocket
|
||||
if skip:
|
||||
self.xmpp.socket.next_sent()
|
||||
if mode == 'component':
|
||||
self.xmpp.socket.next_sent()
|
||||
|
||||
def wait_for_session(x):
|
||||
self.xmpp.socket.clear()
|
||||
skip_queue.put('started')
|
||||
|
||||
self.xmpp.add_event_handler('session_start', wait_for_session)
|
||||
if server is not None:
|
||||
self.xmpp.connect((server, port))
|
||||
else:
|
||||
self.xmpp.connect()
|
||||
else:
|
||||
raise ValueError("Unknown socket type.")
|
||||
|
||||
if plugins is None:
|
||||
self.xmpp.register_plugins()
|
||||
@@ -372,19 +362,6 @@ class SlixTest(unittest.TestCase):
|
||||
# this to True in tests related to those plugins.
|
||||
self.xmpp.use_message_ids = False
|
||||
|
||||
self.xmpp.process(threaded=True)
|
||||
if skip:
|
||||
if socket != 'live':
|
||||
# Mark send queue as usable
|
||||
self.xmpp.session_bind_event.set()
|
||||
self.xmpp.session_started_event.set()
|
||||
# Clear startup stanzas
|
||||
self.xmpp.socket.next_sent(timeout=1)
|
||||
if mode == 'component':
|
||||
self.xmpp.socket.next_sent(timeout=1)
|
||||
else:
|
||||
skip_queue.get(block=True, timeout=10)
|
||||
|
||||
def make_header(self, sto='',
|
||||
sfrom='',
|
||||
sid='',
|
||||
@@ -447,24 +424,7 @@ class SlixTest(unittest.TestCase):
|
||||
timeout -- Time to wait in seconds for data to be received by
|
||||
a live connection.
|
||||
"""
|
||||
if self.xmpp.socket.is_live:
|
||||
# we are working with a live connection, so we should
|
||||
# verify what has been received instead of simulating
|
||||
# receiving data.
|
||||
recv_data = self.xmpp.socket.next_recv(timeout)
|
||||
if recv_data is None:
|
||||
self.fail("No stanza was received.")
|
||||
xml = self.parse_xml(recv_data)
|
||||
self.fix_namespaces(xml, 'jabber:client')
|
||||
stanza = self.xmpp._build_stanza(xml, 'jabber:client')
|
||||
self.check(stanza, data,
|
||||
method=method,
|
||||
defaults=defaults,
|
||||
use_values=use_values)
|
||||
else:
|
||||
# place the data in the dummy socket receiving queue.
|
||||
data = str(data)
|
||||
self.xmpp.socket.recv_data(data)
|
||||
self.xmpp.data_received(data)
|
||||
|
||||
def recv_header(self, sto='',
|
||||
sfrom='',
|
||||
@@ -522,7 +482,7 @@ class SlixTest(unittest.TestCase):
|
||||
if list(recv_xml):
|
||||
# We received more than just the header
|
||||
for xml in recv_xml:
|
||||
self.xmpp.socket.recv_data(tostring(xml))
|
||||
self.xmpp.data_received(tostring(xml))
|
||||
|
||||
attrib = recv_xml.attrib
|
||||
recv_xml.clear()
|
||||
@@ -540,31 +500,7 @@ class SlixTest(unittest.TestCase):
|
||||
if method is None and hasattr(self, 'match_method'):
|
||||
method = getattr(self, 'match_method')
|
||||
|
||||
if self.xmpp.socket.is_live:
|
||||
# we are working with a live connection, so we should
|
||||
# verify what has been received instead of simulating
|
||||
# receiving data.
|
||||
recv_data = self.xmpp.socket.next_recv(timeout)
|
||||
xml = self.parse_xml(data)
|
||||
recv_xml = self.parse_xml(recv_data)
|
||||
if recv_data is None:
|
||||
self.fail("No stanza was received.")
|
||||
if method == 'exact':
|
||||
self.failUnless(self.compare(xml, recv_xml),
|
||||
"Features do not match.\nDesired:\n%s\nReceived:\n%s" % (
|
||||
tostring(xml), tostring(recv_xml)))
|
||||
elif method == 'mask':
|
||||
matcher = MatchXMLMask(xml)
|
||||
self.failUnless(matcher.match(recv_xml),
|
||||
"Stanza did not match using %s method:\n" % method + \
|
||||
"Criteria:\n%s\n" % tostring(xml) + \
|
||||
"Stanza:\n%s" % tostring(recv_xml))
|
||||
else:
|
||||
raise ValueError("Uknown matching method: %s" % method)
|
||||
else:
|
||||
# place the data in the dummy socket receiving queue.
|
||||
data = str(data)
|
||||
self.xmpp.socket.recv_data(data)
|
||||
self.xmpp.socket.data_received(data)
|
||||
|
||||
def send_header(self, sto='',
|
||||
sfrom='',
|
||||
@@ -682,7 +618,7 @@ class SlixTest(unittest.TestCase):
|
||||
that the XMPP client is disconnected after an error.
|
||||
"""
|
||||
if hasattr(self, 'xmpp') and self.xmpp is not None:
|
||||
self.xmpp.socket.recv_data(self.xmpp.stream_footer)
|
||||
self.xmpp.data_received(self.xmpp.stream_footer)
|
||||
self.xmpp.disconnect()
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user