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:
mathieui
2015-02-12 12:23:47 +01:00
parent 4d063e287e
commit 1e2665df19
25 changed files with 211 additions and 684 deletions

View File

@@ -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 *

View File

@@ -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

View File

@@ -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()
# ------------------------------------------------------------------