# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ I{Private} test utilities for use throughout Twisted's test suite. Unlike C{proto_helpers}, this is no exception to the don't-use-it-outside-Twisted-we-won't-maintain-compatibility rule! @note: Maintainers be aware: things in this module should be gradually promoted to more full-featured test helpers and exposed as public API as your maintenance time permits. In order to be public API though, they need their own test cases. """ from io import BytesIO from xml.dom import minidom as dom from twisted.internet.protocol import FileWrapper class IOPump: """Utility to pump data between clients and servers for protocol testing. Perhaps this is a utility worthy of being in protocol.py? """ def __init__(self, client, server, clientIO, serverIO): self.client = client self.server = server self.clientIO = clientIO self.serverIO = serverIO def flush(self): "Pump until there is no more input or output." while self.pump(): pass def pump(self): """Move data back and forth. Returns whether any data was moved. """ self.clientIO.seek(0) self.serverIO.seek(0) cData = self.clientIO.read() sData = self.serverIO.read() self.clientIO.seek(0) self.serverIO.seek(0) self.clientIO.truncate() self.serverIO.truncate() for byte in cData: self.server.dataReceived(byte) for byte in sData: self.client.dataReceived(byte) if cData or sData: return 1 else: return 0 def returnConnected(server, client): """Take two Protocol instances and connect them.""" cio = BytesIO() sio = BytesIO() client.makeConnection(FileWrapper(cio)) server.makeConnection(FileWrapper(sio)) pump = IOPump(client, server, cio, sio) # Challenge-response authentication: pump.flush() # Uh... pump.flush() return pump class XMLAssertionMixin: """ Test mixin defining a method for comparing serialized XML documents. Must be mixed in to a L{test case}. """ def assertXMLEqual(self, first, second): """ Verify that two strings represent the same XML document. @param first: An XML string. @type first: L{bytes} @param second: An XML string that should match C{first}. @type second: L{bytes} """ self.assertEqual( dom.parseString(first).toxml(), dom.parseString(second).toxml() ) class _Equal: """ A class the instances of which are equal to anything and everything. """ def __eq__(self, other: object) -> bool: return True class _NotEqual: """ A class the instances of which are equal to nothing. """ def __eq__(self, other: object) -> bool: return False class ComparisonTestsMixin: """ A mixin which defines a method for making assertions about the correctness of an implementation of C{==} and C{!=}. Use this to unit test objects which follow the common convention for C{==} and C{!=}: - The object compares equal to itself - The object cooperates with unrecognized types to allow them to implement the comparison - The object implements not-equal as the opposite of equal """ def assertNormalEqualityImplementation( self, firstValueOne, secondValueOne, valueTwo ): """ Assert that C{firstValueOne} is equal to C{secondValueOne} but not equal to C{valueOne} and that it defines equality cooperatively with other types it doesn't know about. @param firstValueOne: An object which is expected to compare as equal to C{secondValueOne} and not equal to C{valueTwo}. @param secondValueOne: A different object than C{firstValueOne} but which is expected to compare equal to that object. @param valueTwo: An object which is expected to compare as not equal to C{firstValueOne}. """ # This doesn't use assertEqual and assertNotEqual because the exact # operator those functions use is not very well defined. The point # of these assertions is to check the results of the use of specific # operators (precisely to ensure that using different permutations # (eg "x == y" or "not (x != y)") which should yield the same results # actually does yield the same result). -exarkun self.assertTrue(firstValueOne == firstValueOne) self.assertTrue(firstValueOne == secondValueOne) self.assertFalse(firstValueOne == valueTwo) self.assertFalse(firstValueOne != firstValueOne) self.assertFalse(firstValueOne != secondValueOne) self.assertTrue(firstValueOne != valueTwo) self.assertTrue(firstValueOne == _Equal()) self.assertFalse(firstValueOne != _Equal()) self.assertFalse(firstValueOne == _NotEqual()) self.assertTrue(firstValueOne != _NotEqual())