class AMQFactory(protocol.ReconnectingClientFactory): VHOST = '/' def __init__(self, creds): self.spec = txamqp.spec.load(SPECFILE) self.creds = creds self.client = None self.channel = None def buildProtocol(self, addr): self.resetDelay() delegate = TwistedDelegate() self.client = AMQClient(delegate=delegate, vhost=self.VHOST, spec=self.spec) self.client.start(self.creds) return self.client @defer.inlineCallbacks def publish(self, exchange, msg, routing_key): if not self.client: raise NotImplementedError if not self.channel: yield self._createChannel() content = Content(msg) yield self.channel.basic_publish(exchange=exchange, content=content, routing_key=routing_key) @defer.inlineCallbacks def _createChannel(self): self.channel = yield self.client.channel(1) yield self.channel.channel_open()
class AMQPumpTest(TestCase): def setUp(self): super(AMQPumpTest, self).setUp() delegate = TwistedDelegate() spec = load(DEFAULT_SPEC) self.client = AMQClient(delegate, "/", spec, clock=Clock()) self.transport = AMQPump() self.transport.connect(self.client) def test_send_receive(self): """ Test sending and receiving frames. """ client_channel = self.successResultOf(self.client.channel(1)) server_channel = self.transport.channel(1) d = client_channel.basic_consume(queue="test-queue") server_channel.basic_consume_ok(consumer_tag="consumer") reply = self.successResultOf(d) queue = self.successResultOf(self.client.queue(reply.consumer_tag)) d = queue.get(timeout=1) server_channel.deliver("hello", consumer_tag="consumer") message = self.successResultOf(d) self.assertEqual(b"hello", message.content.body)
class AMQClientTest(TestCase): """Unit tests for the AMQClient protocol.""" def setUp(self): super(AMQClientTest, self).setUp() self.delegate = TwistedDelegate() self.clock = Clock() self.heartbeat = 1 self.protocol = AMQClient( self.delegate, "/", load(DEFAULT_SPEC), clock=self.clock, heartbeat=self.heartbeat) self.transport = AMQPump(Logger()) self.transport.connect(self.protocol) def test_connection_close(self): """Test handling a connection-close method sent by the broker.""" self.transport.channel(0).connection_close() # We send close-ok before shutting down the connection frame = self.transport.outgoing[0][0] self.assertEqual("close-ok", frame.payload.method.name) self.assertTrue(self.protocol.closed) channel0 = self.successResultOf(self.protocol.channel(0)) self.assertTrue(channel0.closed) def test_connection_close_raises_error(self): """Test receiving a connection-close method raises ConnectionClosed.""" channel = self.successResultOf(self.protocol.channel(0)) d = channel.basic_consume(queue="test-queue") self.transport.channel(0).connection_close(reply_code=320) failure = self.failureResultOf(d) self.assertIsInstance(failure.value, ConnectionClosed) def test_close(self): """Test explicitely closing a client.""" d = self.protocol.close() # Since 'within' defaults to 0, no outgoing 'close' frame is there. self.assertEqual({}, self.transport.outgoing) self.assertIsNone(self.successResultOf(d)) self.assertTrue(self.protocol.closed) def test_close_within(self): """Test closing a client cleanly.""" d = self.protocol.close(within=1) # Since we passed within=1, we have an outgoing 'close' frame. frame = self.transport.outgoing[0][0] self.assertEqual("close", frame.payload.method.name) # At this point the client is not yet closed, since we're waiting for # the 'close-ok' acknowledgement from the broker. self.assertFalse(self.protocol.closed) self.transport.channel(0).connection_close_ok() self.assertIsNone(self.successResultOf(d)) self.assertTrue(self.protocol.closed) self.assertEqual([], self.clock.calls) def test_close_within_hits_timeout(self): """Test trying to close a client cleanly but hitting the timeout.""" d = self.protocol.close(within=1) self.clock.advance(1) self.assertIsNone(self.successResultOf(d)) self.assertTrue(self.protocol.closed) def test_close_closes_channels(self): """Test closing a client also closes channels.""" channel = self.successResultOf(self.protocol.channel(0)) self.protocol.close() d = channel.basic_consume(queue="test-queue") failure = self.failureResultOf(d) self.assertIsInstance(failure.value, Closed) def test_close_closes_queues(self): """Test closing a client also closes queues.""" queue = self.successResultOf(self.protocol.queue("tag")) d = queue.get() self.protocol.close() failure = self.failureResultOf(d) self.assertIsInstance(failure.value, QueueClosed) def test_hearbeat_check_failure(self): """Test closing a client after a heartbeat check failure.""" self.protocol.started.fire() channel = self.successResultOf(self.protocol.channel(0)) d = channel.basic_consume(queue="test-queue") self.clock.advance(self.heartbeat * AMQClient.MAX_UNSEEN_HEARTBEAT) self.assertTrue(self.protocol.closed) failure = self.failureResultOf(d) self.assertIsInstance(failure.value, Closed) self.assertTrue(self.transport.aborted) def test_connection_lost(self): """Test closing a client after the connection is lost.""" channel = self.successResultOf(self.protocol.channel(0)) d = channel.basic_consume(queue="test-queue") self.transport.abortConnection() self.assertTrue(self.protocol.closed) failure = self.failureResultOf(d) self.assertIsInstance(failure.value, Closed) self.assertIsInstance(failure.value.args[0].value, ConnectionLost) def test_channel_close(self): """Test receiving a channel-close method raises ChannelClosed.""" channel = self.successResultOf(self.protocol.channel(0)) d = channel.basic_consume(queue="non-existing-queue") self.transport.channel(0).channel_close(reply_code=404) failure = self.failureResultOf(d) self.assertIsInstance(failure.value, ChannelClosed) def test_sending_method_on_closed_channel(self): """Sending a method on a closed channel fails immediately.""" channel = self.successResultOf(self.protocol.channel(0)) self.transport.channel(0).connection_close(reply_code=320) self.transport.outgoing.clear() d = channel.basic_consume(queue="test-queue") # No frames were sent self.assertEqual({}, self.transport.outgoing) failure = self.failureResultOf(d) self.assertIsInstance(failure.value, ConnectionClosed) def test_disconnected_event(self): """Test disconnected event fired after the connection is lost.""" deferred = self.protocol.disconnected.wait() self.protocol.close() self.assertTrue(self.successResultOf(deferred))