From 1e2665df19a866d5676abec566b9d8f190ecdc80 Mon Sep 17 00:00:00 2001 From: mathieui Date: Thu, 12 Feb 2015 12:23:47 +0100 Subject: 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 --- slixmpp/test/__init__.py | 2 +- slixmpp/test/mocksocket.py | 89 +++++++++++++++++++++++++++++++++++++ slixmpp/test/slixtest.py | 106 +++++++++------------------------------------ 3 files changed, 111 insertions(+), 86 deletions(-) (limited to 'slixmpp/test') diff --git a/slixmpp/test/__init__.py b/slixmpp/test/__init__.py index 0804e4aa..0244afe3 100644 --- a/slixmpp/test/__init__.py +++ b/slixmpp/test/__init__.py @@ -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 * diff --git a/slixmpp/test/mocksocket.py b/slixmpp/test/mocksocket.py index 79961279..9583231e 100644 --- a/slixmpp/test/mocksocket.py +++ b/slixmpp/test/mocksocket.py @@ -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 diff --git a/slixmpp/test/slixtest.py b/slixmpp/test/slixtest.py index 4f14d721..36d880a1 100644 --- a/slixmpp/test/slixtest.py +++ b/slixmpp/test/slixtest.py @@ -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() # ------------------------------------------------------------------ -- cgit v1.2.3