def test_eventlet_per_channel(self): from eventlet import spawn, sleep from eventlet.event import Event conn = Connection(**settings.connect_args) start_engines = Event() messages_to_send = 75 def make_message(routing_key, i): return Message(u'%s message #%d' % (routing_key, i)) def writer(channel_id, routing_key, read_ready): start_engines.wait() chan = conn.channel(channel_id) read_ready.wait() for i in range(messages_to_send): msg = make_message(routing_key, i) chan.basic_publish(msg, 'amq.direct', routing_key=routing_key) sleep(0) def reader(channel_id, routing_key, read_ready): messages = [] def got_message(m): messages.append(m) sleep(0) start_engines.wait() chan = conn.channel(channel_id) chan.queue_declare(queue=routing_key, exclusive=True) chan.queue_bind(routing_key, exchange='amq.direct', routing_key=routing_key) chan.basic_consume(queue=routing_key, callback=got_message) read_ready.send(True) while(True): chan.wait() if len(messages) == messages_to_send: break # set up a bunch of pairs of readers # and writers that are all sending # and recieving on the same connection # via separate channels. pairs = 25 procs = [] ch = conn.channel(pairs*2 + 2) for i in range(1, pairs + 1): key = 'q_%d' % i read_ready = Event() procs.append(spawn(writer, i, key, read_ready)) procs.append(spawn(reader, i + pairs, key, read_ready)) # tell them to begin... start_engines.send(True) for proc in procs: proc.wait() conn.close()
class TestConnection(unittest.TestCase): def setUp(self): self.conn = Connection(**settings.connect_args) def tearDown(self): if self.conn: self.conn.close() def test_channel(self): ch = self.conn.channel(1) self.assertEqual(ch.channel_id, 1) ch2 = self.conn.channel() self.assertNotEqual(ch2.channel_id, 1) ch.close() ch2.close() def test_close(self): """ Make sure we've broken various references when closing channels and connections, to help with GC. """ # # Create a channel and make sure it's linked as we'd expect # ch = self.conn.channel() self.assertEqual(1 in self.conn.channels, True) self.assertEqual(ch.connection, self.conn) self.assertEqual(ch.is_open, True) # # Close the channel and make sure the references are broken # that we expect. # ch.close() self.assertEqual(ch.connection, None) self.assertEqual(1 in self.conn.channels, False) self.assertEqual(ch.callbacks, {}) self.assertEqual(ch.is_open, False) # # Close the connection and make sure the references we expect # are gone. # self.conn.close() self.assertEqual(self.conn.connection, None) self.assertEqual(self.conn.channels, None) def test_gc_closed(self): """ Make sure we've broken various references when closing channels and connections, to help with GC. gc.garbage: http://docs.python.org/library/gc.html#gc.garbage "A list of objects which the collector found to be unreachable but could not be freed (uncollectable objects)." """ unreachable_before = len(gc.garbage) # # Create a channel and make sure it's linked as we'd expect # ch = self.conn.channel() self.assertEqual(1 in self.conn.channels, True) # # Close the connection and make sure the references we expect # are gone. # self.conn.close() gc.collect() gc.collect() gc.collect() self.assertEqual(unreachable_before, len(gc.garbage)) def test_gc_forget(self): """ Make sure the connection gets gc'ed when there is no more references to it. """ unreachable_before = len(gc.garbage) ch = self.conn.channel() self.assertEqual(1 in self.conn.channels, True) # remove all the references self.conn = None ch = None gc.collect() gc.collect() gc.collect() self.assertEqual(unreachable_before, len(gc.garbage))
class TestChannel(unittest.TestCase): def setUp(self): self.conn = Connection(**settings.connect_args) self.ch = self.conn.channel() def tearDown(self): self.ch.close() self.conn.close() def test_defaults(self): """ Test how a queue defaults to being bound to an AMQP default exchange, and how publishing defaults to the default exchange, and basic_get defaults to getting from the most recently declared queue, and queue_delete defaults to deleting the most recently declared queue. """ self.ch.access_request('/data', active=True, write=True, read=True) msg = Message('unittest message', content_type='text/plain', application_headers={'foo': 7, 'bar': 'baz'}) qname, _, _ = self.ch.queue_declare() self.ch.basic_publish(msg, routing_key=qname) msg2 = self.ch.basic_get(no_ack=True) self.assertEqual(msg, msg2) n = self.ch.queue_purge() self.assertEqual(n, 0) n = self.ch.queue_delete() self.assertEqual(n, 0) def test_encoding(self): self.ch.access_request('/data', active=True, write=True, read=True) my_routing_key = 'unittest.test_queue' qname, _, _ = self.ch.queue_declare() self.ch.queue_bind(qname, 'amq.direct', routing_key=my_routing_key) # # No encoding, body passed through unchanged # msg = Message('hello world') self.ch.basic_publish(msg, 'amq.direct', routing_key=my_routing_key) msg2 = self.ch.basic_get(qname, no_ack=True) self.assertFalse(hasattr(msg2, 'content_encoding')) self.assertTrue(isinstance(msg2.body, str)) self.assertEqual(msg2.body, 'hello world') # # Default UTF-8 encoding of unicode body, returned as unicode # msg = Message(u'hello world') self.ch.basic_publish(msg, 'amq.direct', routing_key=my_routing_key) msg2 = self.ch.basic_get(qname, no_ack=True) self.assertEqual(msg2.content_encoding, 'UTF-8') self.assertTrue(isinstance(msg2.body, unicode)) self.assertEqual(msg2.body, u'hello world') # # Explicit latin1 encoding, still comes back as unicode # msg = Message(u'hello world', content_encoding='latin1') self.ch.basic_publish(msg, 'amq.direct', routing_key=my_routing_key) msg2 = self.ch.basic_get(qname, no_ack=True) self.assertEqual(msg2.content_encoding, 'latin1') self.assertTrue(isinstance(msg2.body, unicode)) self.assertEqual(msg2.body, u'hello world') # # Plain string with specified encoding comes back as unicode # msg = Message('hello w\xf6rld', content_encoding='latin1') self.ch.basic_publish(msg, 'amq.direct', routing_key=my_routing_key) msg2 = self.ch.basic_get(qname, no_ack=True) self.assertEqual(msg2.content_encoding, 'latin1') self.assertTrue(isinstance(msg2.body, unicode)) self.assertEqual(msg2.body, u'hello w\u00f6rld') # # Plain string with bogus encoding # msg = Message('hello w\xf6rld', content_encoding='I made this up') self.ch.basic_publish(msg, 'amq.direct', routing_key=my_routing_key) msg2 = self.ch.basic_get(qname, no_ack=True) self.assertEqual(msg2.content_encoding, 'I made this up') self.assertTrue(isinstance(msg2.body, str)) self.assertEqual(msg2.body, 'hello w\xf6rld') # # Turn off auto_decode for remaining tests # self.ch.auto_decode = False # # Unicode body comes back as utf-8 encoded str # msg = Message(u'hello w\u00f6rld') self.ch.basic_publish(msg, 'amq.direct', routing_key=my_routing_key) msg2 = self.ch.basic_get(qname, no_ack=True) self.assertEqual(msg2.content_encoding, 'UTF-8') self.assertTrue(isinstance(msg2.body, str)) self.assertEqual(msg2.body, 'hello w\xc3\xb6rld') # # Plain string with specified encoding stays plain string # msg = Message('hello w\xf6rld', content_encoding='latin1') self.ch.basic_publish(msg, 'amq.direct', routing_key=my_routing_key) msg2 = self.ch.basic_get(qname, no_ack=True) self.assertEqual(msg2.content_encoding, 'latin1') self.assertTrue(isinstance(msg2.body, str)) self.assertEqual(msg2.body, 'hello w\xf6rld') # # Explicit latin1 encoding, comes back as str # msg = Message(u'hello w\u00f6rld', content_encoding='latin1') self.ch.basic_publish(msg, 'amq.direct', routing_key=my_routing_key) msg2 = self.ch.basic_get(qname, no_ack=True) self.assertEqual(msg2.content_encoding, 'latin1') self.assertTrue(isinstance(msg2.body, str)) self.assertEqual(msg2.body, 'hello w\xf6rld') def test_exception(self): """ Check that Channel exceptions are actually raised as Python exceptions. """ self.assertRaises(AMQPChannelException, self.ch.queue_delete, 'bogus_queue_that_does_not_exist') def test_large(self): """ Test sending some extra large messages. """ self.ch.access_request('/data', active=True, write=True, read=True) qname, _, _ = self.ch.queue_declare() for multiplier in [100, 1000, 10000]: msg = Message('unittest message' * multiplier, content_type='text/plain', application_headers={'foo': 7, 'bar': 'baz'}) self.ch.basic_publish(msg, routing_key=qname) msg2 = self.ch.basic_get(no_ack=True) self.assertEqual(msg, msg2) def test_publish(self): tkt = self.ch.access_request('/data', active=True, write=True) self.assertEqual(tkt, self.ch.default_ticket) self.ch.exchange_declare('unittest.fanout', 'fanout', auto_delete=True) msg = Message('unittest message', content_type='text/plain', application_headers={'foo': 7, 'bar': 'baz'}) self.ch.basic_publish(msg, 'unittest.fanout') def test_queue(self): self.ch.access_request('/data', active=True, write=True, read=True) my_routing_key = 'unittest.test_queue' msg = Message('unittest message', content_type='text/plain', application_headers={'foo': 7, 'bar': 'baz'}) qname, _, _ = self.ch.queue_declare() self.ch.queue_bind(qname, 'amq.direct', routing_key=my_routing_key) self.ch.basic_publish(msg, 'amq.direct', routing_key=my_routing_key) msg2 = self.ch.basic_get(qname, no_ack=True) self.assertEqual(msg, msg2)