class CommandFailureTests(CommandMixin, TestCase): """ Tests for correct failure of commands on a disconnected L{MemCacheProtocol}. """ def setUp(self): """ Create a disconnected memcache client, using a deterministic clock. """ self.proto = MemCacheProtocol() self.clock = Clock() self.proto.callLater = self.clock.callLater self.transport = StringTransportWithDisconnection() self.transport.protocol = self.proto self.proto.makeConnection(self.transport) self.transport.loseConnection() def _test(self, d, send, recv, result): """ Implementation of C{_test} which checks that the command fails with C{RuntimeError} because the transport is disconnected. All the parameters except C{d} are ignored. """ return self.assertFailure(d, RuntimeError)
def _testDataForward(self, data, method="GET", body=""): """ Build a fake proxy connection, and send C{data} over it, checking that it's forwarded to the originating request. """ # Connect everything clientTransport = StringTransportWithDisconnection() serverTransport = StringTransportWithDisconnection() channel = DummyChannel(serverTransport) parent = DummyParent(channel) serverTransport.protocol = channel client = ProxyClient(method, '/foo', 'HTTP/1.0', {"accept": "text/html"}, body, parent) clientTransport.protocol = client client.makeConnection(clientTransport) # Check data sent self.assertEquals(clientTransport.value(), "%s /foo HTTP/1.0\r\n" "connection: close\r\n" "accept: text/html\r\n\r\n%s" % (method, body)) # Fake an answer client.dataReceived(data) # Check that the data has been forwarded self.assertEquals(serverTransport.value(), data) clientTransport.loseConnection() self.assertIsInstance(channel.lostReason, ConnectionDone)
def _testDataForward(self, data, method="GET", body=""): """ Build a fake proxy connection, and send C{data} over it, checking that it's forwarded to the originating request. """ # Connect everything clientTransport = StringTransportWithDisconnection() serverTransport = StringTransportWithDisconnection() channel = DummyChannel(serverTransport) parent = DummyParent(channel) serverTransport.protocol = channel client = ProxyClient(method, '/foo', 'HTTP/1.0', {"accept": "text/html"}, body, parent) clientTransport.protocol = client client.makeConnection(clientTransport) # Check data sent self.assertEquals( clientTransport.value(), "%s /foo HTTP/1.0\r\n" "connection: close\r\n" "accept: text/html\r\n\r\n%s" % (method, body)) # Fake an answer client.dataReceived(data) # Check that the data has been forwarded self.assertEquals(serverTransport.value(), data) clientTransport.loseConnection() self.assertIsInstance(channel.lostReason, ConnectionDone)
class TestProtocol(common.TestCase): def setUp(self): self.transport = StringTransportWithDisconnection() self.protocol = httpclient.Protocol(self, owner=None) self.protocol.factory = MockFactory() self.protocol.makeConnection(self.transport) self.transport.protocol = self.protocol self.addCleanup(self._disconnect_protocol) @defer.inlineCallbacks def testSimpleRequest(self): self.assertTrue(self.protocol.factory.onConnectionMade_called) self.assertTrue(self.protocol.is_idle()) d = self.protocol.request(http.Methods.GET, '/', headers={'accept': 'text/html'}) self.assertEqual('GET / HTTP/1.1\r\n' 'Accept: text/html\r\n\r\n', self.transport.value()) self.assertFalse(self.protocol.is_idle()) self.protocol.dataReceived( self.protocol.delimiter.join([ "HTTP/1.1 200 OK", "Content-Type: text/html", "Content-Length: 12", "", "This is body", ])) response = yield d self.assertIsInstance(response, httpclient.Response) self.assertEqual(200, response.status) self.assertEqual({'content-type': 'text/html', 'content-length': '12'}, response.headers) self.assertEqual('This is body', response.body) self.assertTrue(self.protocol.is_idle()) self.assertTrue(self.protocol.factory.onConnectionReset_called) @defer.inlineCallbacks def testCancelledRequest(self): d = self.protocol.request(http.Methods.GET, '/', headers={'accept': 'text/html'}) d.cancel() self.assertFalse(self.transport.connected) self.assertFailure(d, httpclient.RequestCancelled) f = yield d exp = ('GET to http://10.0.0.1:12345/ was cancelled ' '0.(\d+)s after it was sent.') self.assertTrue(re.match(exp, str(f)), str(f)) def _disconnect_protocol(self): if self.transport.connected: self.transport.loseConnection() self.assertTrue(self.protocol.factory.onConnectionLost_called)
def _testDataForward(self, code, message, headers, body, method="GET", requestBody="", loseConnection=True): """ Build a fake proxy connection, and send C{data} over it, checking that it's forwarded to the originating request. """ request = DummyRequest(['foo']) # Connect a proxy client to a fake transport. clientTransport = StringTransportWithDisconnection() client = ProxyClient(method, '/foo', 'HTTP/1.0', {"accept": "text/html"}, requestBody, request) clientTransport.protocol = client client.makeConnection(clientTransport) # Check data sent self.assertEquals( clientTransport.value(), "%s /foo HTTP/1.0\r\n" "connection: close\r\n" "accept: text/html\r\n\r\n%s" % (method, requestBody)) # Fake an answer client.dataReceived("HTTP/1.0 %d %s\r\n" % (code, message)) for (header, values) in headers: for value in values: client.dataReceived("%s: %s\r\n" % (header, value)) client.dataReceived("\r\n" + body) # Check that the response data has been forwarded back to the original # requester. self.assertEquals(request.responseCode, code) self.assertEquals(request.responseMessage, message) receivedHeaders = list(request.responseHeaders.getAllRawHeaders()) receivedHeaders.sort() expectedHeaders = headers[:] expectedHeaders.sort() self.assertEquals(receivedHeaders, expectedHeaders) self.assertEquals(''.join(request.written), body) # Check that when the response is done, the request is finished. if loseConnection: clientTransport.loseConnection() # Even if we didn't call loseConnection, the transport should be # disconnected. This lets us not rely on the server to close our # sockets for us. self.assertFalse(clientTransport.connected) self.assertEquals(request.finished, 1)
def test_kill(self): """ L{OneShotPortMapperFactory.kill} should return a L{Deferred} that will be called back when the kill request is complete. """ d = self.factory.kill() transport = StringTransportWithDisconnection() proto = self.factory.buildProtocol(("127.0.01", 4369)) proto.makeConnection(transport) transport.protocol = proto self.assertEqual(transport.value(), "\x00\x01k") proto.dataReceived("OK") transport.loseConnection() return d.addCallback(self.assertEqual, "OK")
def test_names(self): """ L{OneShotPortMapperFactory.names} should return a L{Deferred} that will be called back when the names request is complete. """ d = self.factory.names() transport = StringTransportWithDisconnection() proto = self.factory.buildProtocol(("127.0.01", 4369)) proto.makeConnection(transport) transport.protocol = proto self.assertEqual(transport.value(), "\x00\x01n") proto.dataReceived("\x00\x00\x00\x01") proto.dataReceived("name %s at port %s\n" % ("foo", 1234)) transport.loseConnection() return d.addCallback(self.assertEqual, [("foo", 1234)])
def _testDataForward(self, code, message, headers, body, method="GET", requestBody="", loseConnection=True): """ Build a fake proxy connection, and send C{data} over it, checking that it's forwarded to the originating request. """ request = DummyRequest(['foo']) # Connect a proxy client to a fake transport. clientTransport = StringTransportWithDisconnection() client = ProxyClient(method, '/foo', 'HTTP/1.0', {"accept": "text/html"}, requestBody, request) clientTransport.protocol = client client.makeConnection(clientTransport) # Check data sent self.assertEquals(clientTransport.value(), "%s /foo HTTP/1.0\r\n" "connection: close\r\n" "accept: text/html\r\n\r\n%s" % (method, requestBody)) # Fake an answer client.dataReceived("HTTP/1.0 %d %s\r\n" % (code, message)) for (header, values) in headers: for value in values: client.dataReceived("%s: %s\r\n" % (header, value)) client.dataReceived("\r\n" + body) # Check that the response data has been forwarded back to the original # requester. self.assertEquals(request.responseCode, code) self.assertEquals(request.responseMessage, message) receivedHeaders = list(request.responseHeaders.getAllRawHeaders()) receivedHeaders.sort() expectedHeaders = headers[:] expectedHeaders.sort() self.assertEquals(receivedHeaders, expectedHeaders) self.assertEquals(''.join(request.written), body) # Check that when the response is done, the request is finished. if loseConnection: clientTransport.loseConnection() # Even if we didn't call loseConnection, the transport should be # disconnected. This lets us not rely on the server to close our # sockets for us. self.assertFalse(clientTransport.connected) self.assertEquals(request.finished, 1)
def test_breakReferenceCycle(self): """ L{policies.ProtocolWrapper.connectionLost} sets C{wrappedProtocol} to C{None} in order to break reference cycle between wrapper and wrapped protocols. :return: """ wrapper = policies.ProtocolWrapper(policies.WrappingFactory(Server()), protocol.Protocol()) transport = StringTransportWithDisconnection() transport.protocol = wrapper wrapper.makeConnection(transport) self.assertIsNotNone(wrapper.wrappedProtocol) transport.loseConnection() self.assertIsNone(wrapper.wrappedProtocol)
def test_names(self): """ L{Process.names} returns the list of nodes on a particular host. """ d = self.process.names("spam") epmd = self.process.oneShotEpmds["spam"] transport = StringTransportWithDisconnection() proto = epmd.buildProtocol(("127.0.01", 4369)) proto.makeConnection(transport) transport.protocol = proto self.assertEqual(transport.value(), "\x00\x01n") proto.dataReceived("\x00\x00\x00\x01") proto.dataReceived("name %s at port %s\n" % ("foo", 1234)) proto.dataReceived("name %s at port %s\n" % ("egg", 4321)) transport.loseConnection() return d.addCallback(self.assertEqual, [("foo", 1234), ("egg", 4321)])
def test_dump(self): """ L{OneShotPortMapperFactory.dump} should return a L{Deferred} that will be called back when the dump request is complete. """ d = self.factory.dump() transport = StringTransportWithDisconnection() proto = self.factory.buildProtocol(("127.0.01", 4369)) proto.makeConnection(transport) transport.protocol = proto self.assertEqual(transport.value(), "\x00\x01d") proto.dataReceived("\x00\x00\x00\x01") proto.dataReceived( "active name <%s> at port %s, fd = %s\n\x00" % ("foo", 1234, 3)) transport.loseConnection() return d.addCallback( self.assertEqual, {"active": [("foo", 1234, 3)], "old": []})
class TestClientProtocolReconnectionAttemps(TestCase): def setUp(self): CONNECTION_INFO = {'username': '******', 'password': '******', 'udpipsend': '172.19.51.145', 'baudrate': '500000', 'name': 'Universidade de Vigo', 'parameters': 'yes', 'tcpportsend': '1234', 'tcpipsend': '127.0.0.1', 'udpipreceive': '127.0.0.1', 'attempts': '10', 'serverip': '172.19.51.143', 'serialport': '/dev/ttyUSB0', 'tcpportreceive': 4321, 'connection': 'udp', 'udpportreceive': 57008, 'serverport': 25345, 'reconnection': 'no', 'udpportsend': '57009', 'tcpipreceive': '127.0.0.1'} GS = 'VigoTest' gsi = GroundStationInterface(CONNECTION_INFO, GS, AMP) threads = object self.sp = client_amp.ClientProtocol(CONNECTION_INFO, gsi, threads) self.sp.factory = MockFactory() self.transport = StringTransportWithDisconnection() self.sp.makeConnection(self.transport) self.transport.protocol = self.sp self.correctFrame = ("00:82:a0:00:00:53:45:52:50:2d:42:30:91:1d:1b:03:" + "8d:0b:5c:03:02:28:01:9c:01:ab:02:4c:02:98:01:da:" + "02:40:00:00:00:10:0a:46:58:10:00:c4:9d:cb:a2:21:39") self.wrongFrame = 9 def tearDown(self): pass # TODO Complete description def test_clientconnectionLost(self): """ @return: """ self.transport.loseConnection() return self.assertFalse(self.transport.connected) # TODO Complete description def test_clientConnectionFailed(self): """ @return: """ self.transport.loseConnection() return self.assertFalse(self.transport.connected) # TODO Complete description @patch.object(client_amp.ClientProtocol, 'callRemote') def test_clientEndConnection(self, callRemote): """ @param callRemote: @return: """ self.transport.loseConnection() self.sp.end_connection() return self.assertTrue(callRemote.called)
class TestServerProtocolConnectionEstablished(TestCase): """ Testing multiple client connections TDOD. Test multiple valid connections """ def setUp(self): self.sp = CredReceiver() self.sp.factory = CredAMPServerFactory() self.transport = StringTransportWithDisconnection() def tearDown(self): self.transport.loseConnection() def test_connectionProtocolEstablished(self): """ Checks if transport is working an clients list has the last client. :return: """ self.sp.makeConnection(self.transport) self.transport.protocol = self.sp return self.assertTrue(self.transport.connected),\ self.assertEqual(len(self.sp.factory.clients), 1)
class Network(unittest.TestCase): def setUp(self): self.proto = Redis() self.clock = Clock() self.proto.callLater = self.clock.callLater self.transport = StringTransportWithDisconnection() self.transport.protocol = self.proto self.proto.makeConnection(self.transport) def test_request_while_disconnected(self): # fake disconnect self.proto._disconnected = True d = self.proto.get('foo') self.assertFailure(d, RuntimeError) def checkMessage(error): self.assertEquals(str(error), 'Not connected') return d.addCallback(checkMessage) def test_disconnect_during_request(self): d1 = self.proto.get("foo") d2 = self.proto.get("bar") self.assertEquals(len(self.proto._request_queue), 2) self.transport.loseConnection() done = defer.DeferredList([d1, d2], consumeErrors=True) def checkFailures(results): self.assertEquals(len(self.proto._request_queue), 0) for success, result in results: self.assertFalse(success) result.trap(error.ConnectionDone) return done.addCallback(checkFailures)
class NetworkTestCase(unittest.TestCase): def setUp(self): self.proto = Redis() self.clock = Clock() self.proto.callLater = self.clock.callLater self.transport = StringTransportWithDisconnection() self.transport.protocol = self.proto self.proto.makeConnection(self.transport) def test_request_while_disconnected(self): # fake disconnect self.proto._disconnected = True d = self.proto.get('foo') self.assertFailure(d, RuntimeError) def checkMessage(error): self.assertEquals(str(error), 'Not connected') return d.addCallback(checkMessage) def test_disconnect_during_request(self): d1 = self.proto.get("foo") d2 = self.proto.get("bar") self.assertEquals(len(self.proto._request_queue), 2) self.transport.loseConnection() done = defer.DeferredList([d1, d2], consumeErrors=True) def checkFailures(results): self.assertEquals(len(self.proto._request_queue), 0) for success, result in results: self.assertFalse(success) result.trap(error.ConnectionDone) return done.addCallback(checkFailures)
class WebSocketsProtocolWrapperTest(MAASTestCase): """ Tests for L{WebSocketsProtocolWrapper}. """ def setUp(self): super(WebSocketsProtocolWrapperTest, self).setUp() self.accumulatingProtocol = AccumulatingProtocol() self.protocol = WebSocketsProtocolWrapper(self.accumulatingProtocol) self.transport = StringTransportWithDisconnection() self.protocol.makeConnection(self.transport) self.transport.protocol = self.protocol def test_dataReceived(self): """ L{WebSocketsProtocolWrapper.dataReceived} forwards frame content to the underlying protocol. """ self.protocol.dataReceived( _makeFrame(b"Hello", CONTROLS.TEXT, True, mask=b"abcd")) self.assertEqual(b"Hello", self.accumulatingProtocol.data) def test_controlFrames(self): """ L{WebSocketsProtocolWrapper} doesn't forward data from control frames to the underlying protocol. """ self.protocol.dataReceived( _makeFrame(b"Hello", CONTROLS.PING, True, mask=b"abcd")) self.protocol.dataReceived( _makeFrame(b"Hello", CONTROLS.PONG, True, mask=b"abcd")) self.protocol.dataReceived( _makeFrame(b"", CONTROLS.CLOSE, True, mask=b"abcd")) self.assertEqual(b"", self.accumulatingProtocol.data) def test_loseConnection(self): """ L{WebSocketsProtocolWrapper.loseConnection} sends a close frame and disconnects the transport. """ self.protocol.loseConnection() self.assertFalse(self.transport.connected) self.assertEqual(b"\x88\x02\x03\xe8", self.transport.value()) def test_write(self): """ L{WebSocketsProtocolWrapper.write} creates and writes a frame from the payload passed. """ self.accumulatingProtocol.transport.write(b"Hello") self.assertEqual(b"\x81\x05Hello", self.transport.value()) def test_writeSequence(self): """ L{WebSocketsProtocolWrapper.writeSequence} writes a frame for every chunk passed. """ self.accumulatingProtocol.transport.writeSequence([b"Hello", b"World"]) self.assertEqual(b"\x81\x05Hello\x81\x05World", self.transport.value()) def test_getHost(self): """ L{WebSocketsProtocolWrapper.getHost} returns the transport C{getHost}. """ self.assertEqual(self.transport.getHost(), self.accumulatingProtocol.transport.getHost()) def test_getPeer(self): """ L{WebSocketsProtocolWrapper.getPeer} returns the transport C{getPeer}. """ self.assertEqual(self.transport.getPeer(), self.accumulatingProtocol.transport.getPeer()) def test_connectionLost(self): """ L{WebSocketsProtocolWrapper.connectionLost} forwards the connection lost call to the underlying protocol. """ self.transport.loseConnection() self.assertTrue(self.accumulatingProtocol.closed)
class WebSocketsProtocolWrapperTest(TestCase): """ Tests for L{WebSocketsProtocolWrapper}. """ def setUp(self): self.accumulatingProtocol = AccumulatingProtocol() self.protocol = WebSocketsProtocolWrapper(self.accumulatingProtocol) self.transport = StringTransportWithDisconnection() self.protocol.makeConnection(self.transport) self.transport.protocol = self.protocol def test_dataReceived(self): """ L{WebSocketsProtocolWrapper.dataReceived} forwards frame content to the underlying protocol. """ self.protocol.dataReceived( _makeFrame("Hello", CONTROLS.TEXT, True, mask="abcd")) self.assertEqual("Hello", self.accumulatingProtocol.data) def test_controlFrames(self): """ L{WebSocketsProtocolWrapper} doesn't forward data from control frames to the underlying protocol. """ self.protocol.dataReceived( _makeFrame("Hello", CONTROLS.PING, True, mask="abcd")) self.protocol.dataReceived( _makeFrame("Hello", CONTROLS.PONG, True, mask="abcd")) self.protocol.dataReceived( _makeFrame("", CONTROLS.CLOSE, True, mask="abcd")) self.assertEqual("", self.accumulatingProtocol.data) def test_loseConnection(self): """ L{WebSocketsProtocolWrapper.loseConnection} sends a close frame and disconnects the transport. """ self.protocol.loseConnection() self.assertFalse(self.transport.connected) self.assertEqual("\x88\x02\x03\xe8", self.transport.value()) def test_write(self): """ L{WebSocketsProtocolWrapper.write} creates and writes a frame from the payload passed. """ self.accumulatingProtocol.transport.write("Hello") self.assertEqual("\x81\x05Hello", self.transport.value()) def test_writeSequence(self): """ L{WebSocketsProtocolWrapper.writeSequence} writes a frame for every chunk passed. """ self.accumulatingProtocol.transport.writeSequence(["Hello", "World"]) self.assertEqual("\x81\x05Hello\x81\x05World", self.transport.value()) def test_getHost(self): """ L{WebSocketsProtocolWrapper.getHost} returns the transport C{getHost}. """ self.assertEqual(self.transport.getHost(), self.accumulatingProtocol.transport.getHost()) def test_getPeer(self): """ L{WebSocketsProtocolWrapper.getPeer} returns the transport C{getPeer}. """ self.assertEqual(self.transport.getPeer(), self.accumulatingProtocol.transport.getPeer()) def test_connectionLost(self): """ L{WebSocketsProtocolWrapper.connectionLost} forwards the connection lost call to the underlying protocol. """ self.transport.loseConnection() self.assertTrue(self.accumulatingProtocol.closed)
class MemCacheTests(CommandMixin, TestCase): """ Test client protocol class L{MemCacheProtocol}. """ def setUp(self): """ Create a memcache client, connect it to a string protocol, and make it use a deterministic clock. """ self.proto = MemCacheProtocol() self.clock = Clock() self.proto.callLater = self.clock.callLater self.transport = StringTransportWithDisconnection() self.transport.protocol = self.proto self.proto.makeConnection(self.transport) def _test(self, d, send, recv, result): """ Implementation of C{_test} which checks that the command sends C{send} data, and that upon reception of C{recv} the result is C{result}. @param d: the resulting deferred from the memcache command. @type d: C{Deferred} @param send: the expected data to be sent. @type send: C{bytes} @param recv: the data to simulate as reception. @type recv: C{bytes} @param result: the expected result. @type result: C{any} """ def cb(res): self.assertEqual(res, result) self.assertEqual(self.transport.value(), send) d.addCallback(cb) self.proto.dataReceived(recv) return d def test_invalidGetResponse(self): """ If the value returned doesn't match the expected key of the current C{get} command, an error is raised in L{MemCacheProtocol.dataReceived}. """ self.proto.get(b"foo") self.assertRaises( RuntimeError, self.proto.dataReceived, b"VALUE bar 0 7\r\nspamegg\r\nEND\r\n", ) def test_invalidMultipleGetResponse(self): """ If the value returned doesn't match one the expected keys of the current multiple C{get} command, an error is raised error in L{MemCacheProtocol.dataReceived}. """ self.proto.getMultiple([b"foo", b"bar"]) self.assertRaises( RuntimeError, self.proto.dataReceived, b"VALUE egg 0 7\r\nspamegg\r\nEND\r\n", ) def test_invalidEndResponse(self): """ If an END is received in response to an operation that isn't C{get}, C{gets}, or C{stats}, an error is raised in L{MemCacheProtocol.dataReceived}. """ self.proto.set(b"key", b"value") self.assertRaises(RuntimeError, self.proto.dataReceived, b"END\r\n") def test_timeOut(self): """ Test the timeout on outgoing requests: when timeout is detected, all current commands fail with a L{TimeoutError}, and the connection is closed. """ d1 = self.proto.get(b"foo") d2 = self.proto.get(b"bar") d3 = Deferred() self.proto.connectionLost = d3.callback self.clock.advance(self.proto.persistentTimeOut) self.assertFailure(d1, TimeoutError) self.assertFailure(d2, TimeoutError) def checkMessage(error): self.assertEqual(str(error), "Connection timeout") d1.addCallback(checkMessage) self.assertFailure(d3, ConnectionDone) return gatherResults([d1, d2, d3]) def test_timeoutRemoved(self): """ When a request gets a response, no pending timeout call remains around. """ d = self.proto.get(b"foo") self.clock.advance(self.proto.persistentTimeOut - 1) self.proto.dataReceived(b"VALUE foo 0 3\r\nbar\r\nEND\r\n") def check(result): self.assertEqual(result, (0, b"bar")) self.assertEqual(len(self.clock.calls), 0) d.addCallback(check) return d def test_timeOutRaw(self): """ Test the timeout when raw mode was started: the timeout is not reset until all the data has been received, so we can have a L{TimeoutError} when waiting for raw data. """ d1 = self.proto.get(b"foo") d2 = Deferred() self.proto.connectionLost = d2.callback self.proto.dataReceived(b"VALUE foo 0 10\r\n12345") self.clock.advance(self.proto.persistentTimeOut) self.assertFailure(d1, TimeoutError) self.assertFailure(d2, ConnectionDone) return gatherResults([d1, d2]) def test_timeOutStat(self): """ Test the timeout when stat command has started: the timeout is not reset until the final B{END} is received. """ d1 = self.proto.stats() d2 = Deferred() self.proto.connectionLost = d2.callback self.proto.dataReceived(b"STAT foo bar\r\n") self.clock.advance(self.proto.persistentTimeOut) self.assertFailure(d1, TimeoutError) self.assertFailure(d2, ConnectionDone) return gatherResults([d1, d2]) def test_timeoutPipelining(self): """ When two requests are sent, a timeout call remains around for the second request, and its timeout time is correct. """ d1 = self.proto.get(b"foo") d2 = self.proto.get(b"bar") d3 = Deferred() self.proto.connectionLost = d3.callback self.clock.advance(self.proto.persistentTimeOut - 1) self.proto.dataReceived(b"VALUE foo 0 3\r\nbar\r\nEND\r\n") def check(result): self.assertEqual(result, (0, b"bar")) self.assertEqual(len(self.clock.calls), 1) for i in range(self.proto.persistentTimeOut): self.clock.advance(1) return self.assertFailure(d2, TimeoutError).addCallback(checkTime) def checkTime(ignored): # Check that the timeout happened C{self.proto.persistentTimeOut} # after the last response self.assertEqual(self.clock.seconds(), 2 * self.proto.persistentTimeOut - 1) d1.addCallback(check) self.assertFailure(d3, ConnectionDone) return d1 def test_timeoutNotReset(self): """ Check that timeout is not resetted for every command, but keep the timeout from the first command without response. """ d1 = self.proto.get(b"foo") d3 = Deferred() self.proto.connectionLost = d3.callback self.clock.advance(self.proto.persistentTimeOut - 1) d2 = self.proto.get(b"bar") self.clock.advance(1) self.assertFailure(d1, TimeoutError) self.assertFailure(d2, TimeoutError) self.assertFailure(d3, ConnectionDone) return gatherResults([d1, d2, d3]) def test_timeoutCleanDeferreds(self): """ C{timeoutConnection} cleans the list of commands that it fires with C{TimeoutError}: C{connectionLost} doesn't try to fire them again, but sets the disconnected state so that future commands fail with a C{RuntimeError}. """ d1 = self.proto.get(b"foo") self.clock.advance(self.proto.persistentTimeOut) self.assertFailure(d1, TimeoutError) d2 = self.proto.get(b"bar") self.assertFailure(d2, RuntimeError) return gatherResults([d1, d2]) def test_connectionLost(self): """ When disconnection occurs while commands are still outstanding, the commands fail. """ d1 = self.proto.get(b"foo") d2 = self.proto.get(b"bar") self.transport.loseConnection() done = DeferredList([d1, d2], consumeErrors=True) def checkFailures(results): for success, result in results: self.assertFalse(success) result.trap(ConnectionDone) return done.addCallback(checkFailures) def test_tooLongKey(self): """ An error is raised when trying to use a too long key: the called command returns a L{Deferred} which fails with a L{ClientError}. """ d1 = self.assertFailure(self.proto.set(b"a" * 500, b"bar"), ClientError) d2 = self.assertFailure(self.proto.increment(b"a" * 500), ClientError) d3 = self.assertFailure(self.proto.get(b"a" * 500), ClientError) d4 = self.assertFailure(self.proto.append(b"a" * 500, b"bar"), ClientError) d5 = self.assertFailure(self.proto.prepend(b"a" * 500, b"bar"), ClientError) d6 = self.assertFailure(self.proto.getMultiple([b"foo", b"a" * 500]), ClientError) return gatherResults([d1, d2, d3, d4, d5, d6]) def test_invalidCommand(self): """ When an unknown command is sent directly (not through public API), the server answers with an B{ERROR} token, and the command fails with L{NoSuchCommand}. """ d = self.proto._set(b"egg", b"foo", b"bar", 0, 0, b"") self.assertEqual(self.transport.value(), b"egg foo 0 0 3\r\nbar\r\n") self.assertFailure(d, NoSuchCommand) self.proto.dataReceived(b"ERROR\r\n") return d def test_clientError(self): """ Test the L{ClientError} error: when the server sends a B{CLIENT_ERROR} token, the originating command fails with L{ClientError}, and the error contains the text sent by the server. """ a = b"eggspamm" d = self.proto.set(b"foo", a) self.assertEqual(self.transport.value(), b"set foo 0 0 8\r\neggspamm\r\n") self.assertFailure(d, ClientError) def check(err): self.assertEqual(str(err), repr(b"We don't like egg and spam")) d.addCallback(check) self.proto.dataReceived(b"CLIENT_ERROR We don't like egg and spam\r\n") return d def test_serverError(self): """ Test the L{ServerError} error: when the server sends a B{SERVER_ERROR} token, the originating command fails with L{ServerError}, and the error contains the text sent by the server. """ a = b"eggspamm" d = self.proto.set(b"foo", a) self.assertEqual(self.transport.value(), b"set foo 0 0 8\r\neggspamm\r\n") self.assertFailure(d, ServerError) def check(err): self.assertEqual(str(err), repr(b"zomg")) d.addCallback(check) self.proto.dataReceived(b"SERVER_ERROR zomg\r\n") return d def test_unicodeKey(self): """ Using a non-string key as argument to commands raises an error. """ d1 = self.assertFailure(self.proto.set("foo", b"bar"), ClientError) d2 = self.assertFailure(self.proto.increment("egg"), ClientError) d3 = self.assertFailure(self.proto.get(1), ClientError) d4 = self.assertFailure(self.proto.delete("bar"), ClientError) d5 = self.assertFailure(self.proto.append("foo", b"bar"), ClientError) d6 = self.assertFailure(self.proto.prepend("foo", b"bar"), ClientError) d7 = self.assertFailure(self.proto.getMultiple([b"egg", 1]), ClientError) return gatherResults([d1, d2, d3, d4, d5, d6, d7]) def test_unicodeValue(self): """ Using a non-string value raises an error. """ return self.assertFailure(self.proto.set(b"foo", "bar"), ClientError) def test_pipelining(self): """ Multiple requests can be sent subsequently to the server, and the protocol orders the responses correctly and dispatch to the corresponding client command. """ d1 = self.proto.get(b"foo") d1.addCallback(self.assertEqual, (0, b"bar")) d2 = self.proto.set(b"bar", b"spamspamspam") d2.addCallback(self.assertEqual, True) d3 = self.proto.get(b"egg") d3.addCallback(self.assertEqual, (0, b"spam")) self.assertEqual( self.transport.value(), b"get foo\r\nset bar 0 0 12\r\nspamspamspam\r\nget egg\r\n", ) self.proto.dataReceived(b"VALUE foo 0 3\r\nbar\r\nEND\r\n" b"STORED\r\n" b"VALUE egg 0 4\r\nspam\r\nEND\r\n") return gatherResults([d1, d2, d3]) def test_getInChunks(self): """ If the value retrieved by a C{get} arrive in chunks, the protocol is able to reconstruct it and to produce the good value. """ d = self.proto.get(b"foo") d.addCallback(self.assertEqual, (0, b"0123456789")) self.assertEqual(self.transport.value(), b"get foo\r\n") self.proto.dataReceived(b"VALUE foo 0 10\r\n0123456") self.proto.dataReceived(b"789") self.proto.dataReceived(b"\r\nEND") self.proto.dataReceived(b"\r\n") return d def test_append(self): """ L{MemCacheProtocol.append} behaves like a L{MemCacheProtocol.set} method: it returns a L{Deferred} which is called back with C{True} when the operation succeeds. """ return self._test( self.proto.append(b"foo", b"bar"), b"append foo 0 0 3\r\nbar\r\n", b"STORED\r\n", True, ) def test_prepend(self): """ L{MemCacheProtocol.prepend} behaves like a L{MemCacheProtocol.set} method: it returns a L{Deferred} which is called back with C{True} when the operation succeeds. """ return self._test( self.proto.prepend(b"foo", b"bar"), b"prepend foo 0 0 3\r\nbar\r\n", b"STORED\r\n", True, ) def test_gets(self): """ L{MemCacheProtocol.get} handles an additional cas result when C{withIdentifier} is C{True} and forward it in the resulting L{Deferred}. """ return self._test( self.proto.get(b"foo", True), b"gets foo\r\n", b"VALUE foo 0 3 1234\r\nbar\r\nEND\r\n", (0, b"1234", b"bar"), ) def test_emptyGets(self): """ Test getting a non-available key with gets: it succeeds but return L{None} as value, C{0} as flag and an empty cas value. """ return self._test(self.proto.get(b"foo", True), b"gets foo\r\n", b"END\r\n", (0, b"", None)) def test_getsMultiple(self): """ L{MemCacheProtocol.getMultiple} handles an additional cas field in the returned tuples if C{withIdentifier} is C{True}. """ return self._test( self.proto.getMultiple([b"foo", b"bar"], True), b"gets foo bar\r\n", b"VALUE foo 0 3 1234\r\negg\r\n" b"VALUE bar 0 4 2345\r\nspam\r\nEND\r\n", { b"bar": (0, b"2345", b"spam"), b"foo": (0, b"1234", b"egg") }, ) def test_getsMultipleIterableKeys(self): """ L{MemCacheProtocol.getMultiple} accepts any iterable of keys. """ return self._test( self.proto.getMultiple(iter([b"foo", b"bar"]), True), b"gets foo bar\r\n", b"VALUE foo 0 3 1234\r\negg\r\n" b"VALUE bar 0 4 2345\r\nspam\r\nEND\r\n", { b"bar": (0, b"2345", b"spam"), b"foo": (0, b"1234", b"egg") }, ) def test_getsMultipleWithEmpty(self): """ When getting a non-available key with L{MemCacheProtocol.getMultiple} when C{withIdentifier} is C{True}, the other keys are retrieved correctly, and the non-available key gets a tuple of C{0} as flag, L{None} as value, and an empty cas value. """ return self._test( self.proto.getMultiple([b"foo", b"bar"], True), b"gets foo bar\r\n", b"VALUE foo 0 3 1234\r\negg\r\nEND\r\n", { b"bar": (0, b"", None), b"foo": (0, b"1234", b"egg") }, ) def test_checkAndSet(self): """ L{MemCacheProtocol.checkAndSet} passes an additional cas identifier that the server handles to check if the data has to be updated. """ return self._test( self.proto.checkAndSet(b"foo", b"bar", cas=b"1234"), b"cas foo 0 0 3 1234\r\nbar\r\n", b"STORED\r\n", True, ) def test_casUnknowKey(self): """ When L{MemCacheProtocol.checkAndSet} response is C{EXISTS}, the resulting L{Deferred} fires with C{False}. """ return self._test( self.proto.checkAndSet(b"foo", b"bar", cas=b"1234"), b"cas foo 0 0 3 1234\r\nbar\r\n", b"EXISTS\r\n", False, )
class PortMapperProtocolTestCase(TestCase): """ Tests for L{PortMapperProtocol}. """ def setUp(self): """ Create a protocol instance linked with a L{DummyPortMapperFactory}. """ self.proto = PortMapperProtocol() self.proto.factory = DummyPortMapperFactory() self.transport = StringTransportWithDisconnection() self.proto.makeConnection(self.transport) self.transport.protocol = self.proto def test_alive2Response(self): """ Test an successful alive2 response. """ def cb(res): self.assertEqual(res, 1) self.proto.factory._connectDeferred.addCallback(cb) self.proto.dataReceived("y") self.proto.dataReceived("\x00") self.proto.dataReceived("\x00\x01") return self.proto.factory._connectDeferred def test_alive2ResponseError(self): """ Test an erroneous alive2 response. """ def eb(res): res.trap(ValueError) self.proto.factory._connectDeferred.addErrback(eb) self.proto.dataReceived("y\x01\x00\x01") return self.proto.factory._connectDeferred def test_alive2Request(self): """ Test data sent by an alive2 request. """ self.proto.alive2Request(1234, 77, (1, 2), "foo@bar") self.assertEqual( self.transport.value(), "\x00\x14x\x04\xd2M\x00\x00\x01\x00\x02\x00\x07foo@bar\x00\x00") def test_port2Response(self): """ Test an successful port2 response. """ d = Deferred() d.addCallback(self.assertEqual, Node(9, 77, 1, (5, 5), "bar", "")) self.proto.deferred = d self.proto.dataReceived("w") self.proto.dataReceived("\x00") self.proto.dataReceived("\x00\x09M\x01\x00\x05\x00\x05\x00\x03bar\x00") self.assertEqual(self.proto.received, "") return d def test_port2ResponseWithExtra(self): """ Test an successful port2 response, with extra data. """ d = Deferred() d.addCallback( self.assertEqual, Node(9, 77, 1, (5, 5), "bar", "spam")) self.proto.deferred = d self.proto.dataReceived( "w\x00\x00\x09M\x01\x00\x05\x00\x05\x00\x03bar\x00\x04spam") self.assertEqual(self.proto.received, "") return d def test_port2ResponseNodeNotFound(self): """ Test a port2 not found response: the response deferred should be fired with a L{NodeNotFound} exception. """ d = Deferred() self.proto.deferred = d self.proto.dataReceived("w\x01") self.assertEqual(self.proto.received, "") return self.assertFailure(d, NodeNotFound) def test_port2Request(self): """ Test data sent by a port2 request. """ d = Deferred() self.proto.portPlease2Request(d, "egg@spam") self.assertEqual(self.transport.value(), "\x00\tzegg@spam") self.assertEqual(self.proto.deferred, d) def test_names(self): """ Test successful names request and response. """ d = Deferred() d.addCallback(self.assertEqual, [("foo", 1234), ("egg", 4321)]) self.proto.namesRequest(d) self.assertEqual(self.transport.value(), "\x00\x01n") self.proto.dataReceived("\x00\x00\x00\x01") self.proto.dataReceived("name %s at port %s\n" % ("foo", 1234)) self.proto.dataReceived("name %s at port %s\n" % ("egg", 4321)) self.transport.loseConnection() return d def test_dump(self): """ Test successful dump request and response. """ d = Deferred() d.addCallback( self.assertEqual, {"active": [("foo", 1234, 3)], "old": [("egg", 4321, 2)]}) self.proto.dumpRequest(d) self.assertEqual(self.transport.value(), "\x00\x01d") self.proto.dataReceived("\x00\x00\x00\x01") self.proto.dataReceived( "active name <%s> at port %s, fd = %s\n\x00" % ("foo", 1234, 3)) self.proto.dataReceived( "old/unused name, <%s>, at port %s, fd = %s\n\x00" % ("egg", 4321, 2)) self.transport.loseConnection() return d def test_kill(self): """ Test successful kill request and response. """ d = Deferred() d.addCallback(self.assertEqual, "OK") self.proto.killRequest(d) self.assertEqual(self.transport.value(), "\x00\x01k") self.proto.dataReceived("OK") self.transport.loseConnection() return d def test_invalidKillResponse(self): """ Test a kill request with an invalid response. """ d = Deferred() self.proto.killRequest(d) self.assertEqual(self.transport.value(), "\x00\x01k") self.proto.dataReceived("Wrong") self.transport.loseConnection() return self.assertFailure(d, ValueError) def test_connectionLostWithPendingDeferred(self): """ Test that connectionLost errbacks the action deferred if present. """ d = Deferred() self.proto.deferred = d self.transport.loseConnection() return self.assertFailure(d, ConnectionDone) def test_unhandledRequest(self): """ When a unhandled data is received, the protocol should log a C{RuntimeError}. """ self.proto.dataReceived("Wrong") errors = self.flushLoggedErrors() self.assertEqual(len(errors), 1) errors[0].trap(RuntimeError)
class MemCacheTestCase(CommandMixin, TestCase): """ Test client protocol class L{MemCacheProtocol}. """ def setUp(self): """ Create a memcache client, connect it to a string protocol, and make it use a deterministic clock. """ self.proto = MemCacheProtocol() self.clock = Clock() self.proto.callLater = self.clock.callLater self.transport = StringTransportWithDisconnection() self.transport.protocol = self.proto self.proto.makeConnection(self.transport) def _test(self, d, send, recv, result): """ Implementation of C{_test} which checks that the command sends C{send} data, and that upon reception of C{recv} the result is C{result}. @param d: the resulting deferred from the memcache command. @type d: C{Deferred} @param send: the expected data to be sent. @type send: C{str} @param recv: the data to simulate as reception. @type recv: C{str} @param result: the expected result. @type result: C{any} """ def cb(res): self.assertEquals(res, result) self.assertEquals(self.transport.value(), send) d.addCallback(cb) self.proto.dataReceived(recv) return d def test_invalidGetResponse(self): """ If the value returned doesn't match the expected key of the current C{get} command, an error is raised in L{MemCacheProtocol.dataReceived}. """ self.proto.get("foo") s = "spamegg" self.assertRaises(RuntimeError, self.proto.dataReceived, "VALUE bar 0 %s\r\n%s\r\nEND\r\n" % (len(s), s)) def test_invalidMultipleGetResponse(self): """ If the value returned doesn't match one the expected keys of the current multiple C{get} command, an error is raised error in L{MemCacheProtocol.dataReceived}. """ self.proto.getMultiple(["foo", "bar"]) s = "spamegg" self.assertRaises(RuntimeError, self.proto.dataReceived, "VALUE egg 0 %s\r\n%s\r\nEND\r\n" % (len(s), s)) def test_timeOut(self): """ Test the timeout on outgoing requests: when timeout is detected, all current commands fail with a L{TimeoutError}, and the connection is closed. """ d1 = self.proto.get("foo") d2 = self.proto.get("bar") d3 = Deferred() self.proto.connectionLost = d3.callback self.clock.advance(self.proto.persistentTimeOut) self.assertFailure(d1, TimeoutError) self.assertFailure(d2, TimeoutError) def checkMessage(error): self.assertEquals(str(error), "Connection timeout") d1.addCallback(checkMessage) return gatherResults([d1, d2, d3]) def test_timeoutRemoved(self): """ When a request gets a response, no pending timeout call remains around. """ d = self.proto.get("foo") self.clock.advance(self.proto.persistentTimeOut - 1) self.proto.dataReceived("VALUE foo 0 3\r\nbar\r\nEND\r\n") def check(result): self.assertEquals(result, (0, "bar")) self.assertEquals(len(self.clock.calls), 0) d.addCallback(check) return d def test_timeOutRaw(self): """ Test the timeout when raw mode was started: the timeout is not reset until all the data has been received, so we can have a L{TimeoutError} when waiting for raw data. """ d1 = self.proto.get("foo") d2 = Deferred() self.proto.connectionLost = d2.callback self.proto.dataReceived("VALUE foo 0 10\r\n12345") self.clock.advance(self.proto.persistentTimeOut) self.assertFailure(d1, TimeoutError) return gatherResults([d1, d2]) def test_timeOutStat(self): """ Test the timeout when stat command has started: the timeout is not reset until the final B{END} is received. """ d1 = self.proto.stats() d2 = Deferred() self.proto.connectionLost = d2.callback self.proto.dataReceived("STAT foo bar\r\n") self.clock.advance(self.proto.persistentTimeOut) self.assertFailure(d1, TimeoutError) return gatherResults([d1, d2]) def test_timeoutPipelining(self): """ When two requests are sent, a timeout call remains around for the second request, and its timeout time is correct. """ d1 = self.proto.get("foo") d2 = self.proto.get("bar") d3 = Deferred() self.proto.connectionLost = d3.callback self.clock.advance(self.proto.persistentTimeOut - 1) self.proto.dataReceived("VALUE foo 0 3\r\nbar\r\nEND\r\n") def check(result): self.assertEquals(result, (0, "bar")) self.assertEquals(len(self.clock.calls), 1) for i in range(self.proto.persistentTimeOut): self.clock.advance(1) return self.assertFailure(d2, TimeoutError).addCallback(checkTime) def checkTime(ignored): # Check that the timeout happened C{self.proto.persistentTimeOut} # after the last response self.assertEquals( self.clock.seconds(), 2 * self.proto.persistentTimeOut - 1) d1.addCallback(check) return d1 def test_timeoutNotReset(self): """ Check that timeout is not resetted for every command, but keep the timeout from the first command without response. """ d1 = self.proto.get("foo") d3 = Deferred() self.proto.connectionLost = d3.callback self.clock.advance(self.proto.persistentTimeOut - 1) d2 = self.proto.get("bar") self.clock.advance(1) self.assertFailure(d1, TimeoutError) self.assertFailure(d2, TimeoutError) return gatherResults([d1, d2, d3]) def test_timeoutCleanDeferreds(self): """ C{timeoutConnection} cleans the list of commands that it fires with C{TimeoutError}: C{connectionLost} doesn't try to fire them again, but sets the disconnected state so that future commands fail with a C{RuntimeError}. """ d1 = self.proto.get("foo") self.clock.advance(self.proto.persistentTimeOut) self.assertFailure(d1, TimeoutError) d2 = self.proto.get("bar") self.assertFailure(d2, RuntimeError) return gatherResults([d1, d2]) def test_connectionLost(self): """ When disconnection occurs while commands are still outstanding, the commands fail. """ d1 = self.proto.get("foo") d2 = self.proto.get("bar") self.transport.loseConnection() done = DeferredList([d1, d2], consumeErrors=True) def checkFailures(results): for success, result in results: self.assertFalse(success) result.trap(ConnectionDone) return done.addCallback(checkFailures) def test_tooLongKey(self): """ An error is raised when trying to use a too long key: the called command returns a L{Deferred} which fails with a L{ClientError}. """ d1 = self.assertFailure(self.proto.set("a" * 500, "bar"), ClientError) d2 = self.assertFailure(self.proto.increment("a" * 500), ClientError) d3 = self.assertFailure(self.proto.get("a" * 500), ClientError) d4 = self.assertFailure( self.proto.append("a" * 500, "bar"), ClientError) d5 = self.assertFailure( self.proto.prepend("a" * 500, "bar"), ClientError) d6 = self.assertFailure( self.proto.getMultiple(["foo", "a" * 500]), ClientError) return gatherResults([d1, d2, d3, d4, d5, d6]) def test_invalidCommand(self): """ When an unknown command is sent directly (not through public API), the server answers with an B{ERROR} token, and the command fails with L{NoSuchCommand}. """ d = self.proto._set("egg", "foo", "bar", 0, 0, "") self.assertEquals(self.transport.value(), "egg foo 0 0 3\r\nbar\r\n") self.assertFailure(d, NoSuchCommand) self.proto.dataReceived("ERROR\r\n") return d def test_clientError(self): """ Test the L{ClientError} error: when the server sends a B{CLIENT_ERROR} token, the originating command fails with L{ClientError}, and the error contains the text sent by the server. """ a = "eggspamm" d = self.proto.set("foo", a) self.assertEquals(self.transport.value(), "set foo 0 0 8\r\neggspamm\r\n") self.assertFailure(d, ClientError) def check(err): self.assertEquals(str(err), "We don't like egg and spam") d.addCallback(check) self.proto.dataReceived("CLIENT_ERROR We don't like egg and spam\r\n") return d def test_serverError(self): """ Test the L{ServerError} error: when the server sends a B{SERVER_ERROR} token, the originating command fails with L{ServerError}, and the error contains the text sent by the server. """ a = "eggspamm" d = self.proto.set("foo", a) self.assertEquals(self.transport.value(), "set foo 0 0 8\r\neggspamm\r\n") self.assertFailure(d, ServerError) def check(err): self.assertEquals(str(err), "zomg") d.addCallback(check) self.proto.dataReceived("SERVER_ERROR zomg\r\n") return d def test_unicodeKey(self): """ Using a non-string key as argument to commands raises an error. """ d1 = self.assertFailure(self.proto.set(u"foo", "bar"), ClientError) d2 = self.assertFailure(self.proto.increment(u"egg"), ClientError) d3 = self.assertFailure(self.proto.get(1), ClientError) d4 = self.assertFailure(self.proto.delete(u"bar"), ClientError) d5 = self.assertFailure(self.proto.append(u"foo", "bar"), ClientError) d6 = self.assertFailure(self.proto.prepend(u"foo", "bar"), ClientError) d7 = self.assertFailure( self.proto.getMultiple(["egg", 1]), ClientError) return gatherResults([d1, d2, d3, d4, d5, d6, d7]) def test_unicodeValue(self): """ Using a non-string value raises an error. """ return self.assertFailure(self.proto.set("foo", u"bar"), ClientError) def test_pipelining(self): """ Multiple requests can be sent subsequently to the server, and the protocol orders the responses correctly and dispatch to the corresponding client command. """ d1 = self.proto.get("foo") d1.addCallback(self.assertEquals, (0, "bar")) d2 = self.proto.set("bar", "spamspamspam") d2.addCallback(self.assertEquals, True) d3 = self.proto.get("egg") d3.addCallback(self.assertEquals, (0, "spam")) self.assertEquals(self.transport.value(), "get foo\r\nset bar 0 0 12\r\nspamspamspam\r\nget egg\r\n") self.proto.dataReceived("VALUE foo 0 3\r\nbar\r\nEND\r\n" "STORED\r\n" "VALUE egg 0 4\r\nspam\r\nEND\r\n") return gatherResults([d1, d2, d3]) def test_getInChunks(self): """ If the value retrieved by a C{get} arrive in chunks, the protocol is able to reconstruct it and to produce the good value. """ d = self.proto.get("foo") d.addCallback(self.assertEquals, (0, "0123456789")) self.assertEquals(self.transport.value(), "get foo\r\n") self.proto.dataReceived("VALUE foo 0 10\r\n0123456") self.proto.dataReceived("789") self.proto.dataReceived("\r\nEND") self.proto.dataReceived("\r\n") return d def test_append(self): """ L{MemCacheProtocol.append} behaves like a L{MemCacheProtocol.set} method: it returns a L{Deferred} which is called back with C{True} when the operation succeeds. """ return self._test(self.proto.append("foo", "bar"), "append foo 0 0 3\r\nbar\r\n", "STORED\r\n", True) def test_prepend(self): """ L{MemCacheProtocol.prepend} behaves like a L{MemCacheProtocol.set} method: it returns a L{Deferred} which is called back with C{True} when the operation succeeds. """ return self._test(self.proto.prepend("foo", "bar"), "prepend foo 0 0 3\r\nbar\r\n", "STORED\r\n", True) def test_gets(self): """ L{MemCacheProtocol.get} handles an additional cas result when C{withIdentifier} is C{True} and forward it in the resulting L{Deferred}. """ return self._test(self.proto.get("foo", True), "gets foo\r\n", "VALUE foo 0 3 1234\r\nbar\r\nEND\r\n", (0, "1234", "bar")) def test_emptyGets(self): """ Test getting a non-available key with gets: it succeeds but return C{None} as value, C{0} as flag and an empty cas value. """ return self._test(self.proto.get("foo", True), "gets foo\r\n", "END\r\n", (0, "", None)) def test_getsMultiple(self): """ L{MemCacheProtocol.getMultiple} handles an additional cas field in the returned tuples if C{withIdentifier} is C{True}. """ return self._test(self.proto.getMultiple(["foo", "bar"], True), "gets foo bar\r\n", "VALUE foo 0 3 1234\r\negg\r\nVALUE bar 0 4 2345\r\nspam\r\nEND\r\n", {'bar': (0, '2345', 'spam'), 'foo': (0, '1234', 'egg')}) def test_getsMultipleWithEmpty(self): """ When getting a non-available key with L{MemCacheProtocol.getMultiple} when C{withIdentifier} is C{True}, the other keys are retrieved correctly, and the non-available key gets a tuple of C{0} as flag, C{None} as value, and an empty cas value. """ return self._test(self.proto.getMultiple(["foo", "bar"], True), "gets foo bar\r\n", "VALUE foo 0 3 1234\r\negg\r\nEND\r\n", {'bar': (0, '', None), 'foo': (0, '1234', 'egg')}) def test_checkAndSet(self): """ L{MemCacheProtocol.checkAndSet} passes an additional cas identifier that the server handles to check if the data has to be updated. """ return self._test(self.proto.checkAndSet("foo", "bar", cas="1234"), "cas foo 0 0 3 1234\r\nbar\r\n", "STORED\r\n", True) def test_casUnknowKey(self): """ When L{MemCacheProtocol.checkAndSet} response is C{EXISTS}, the resulting L{Deferred} fires with C{False}. """ return self._test(self.proto.checkAndSet("foo", "bar", cas="1234"), "cas foo 0 0 3 1234\r\nbar\r\n", "EXISTS\r\n", False)
def loseConnection(self): """ Save the connection lost state, and forward the call. """ StringTransportWithDisconnection.loseConnection(self) self.closed = True