def test_connect(self): # Test checking connection handshake frame_writer_cls_mock = Mock() on_open_mock = Mock() frame_writer_mock = frame_writer_cls_mock() conn = Connection(frame_writer=frame_writer_cls_mock, on_open=on_open_mock) with patch.object(conn, 'Transport') as transport_mock: handshake(conn, transport_mock) on_open_mock.assert_called_once_with(conn) security_mechanism = sasl.AMQPLAIN('guest', 'guest').start(conn).decode( 'utf-8', 'surrogatepass') # Expected responses from client frame_writer_mock.assert_has_calls([ call( 1, 0, spec.Connection.StartOk, # Due Table type, we cannot compare bytestream directly DataComparator('FsSs', (CLIENT_CAPABILITIES, 'AMQPLAIN', security_mechanism, 'en_US')), None), call( 1, 0, spec.Connection.TuneOk, dumps('BlB', (conn.channel_max, conn.frame_max, conn.heartbeat)), None), call(1, 0, spec.Connection.Open, dumps('ssb', (conn.virtual_host, '', False)), None) ])
def test_channel_open_close(self): # Test checking opening and closing channel frame_writer_cls_mock = Mock() conn = Connection(frame_writer=frame_writer_cls_mock) with patch.object(conn, 'Transport') as transport_mock: handshake(conn, transport_mock) channel_id = 1 transport_mock().read_frame.side_effect = [ # Inject Open Handshake build_frame_type_1(spec.Channel.OpenOk, channel=channel_id, args=(1, False), arg_format='Lb'), # Inject close method build_frame_type_1(spec.Channel.CloseOk, channel=channel_id) ] frame_writer_mock = frame_writer_cls_mock() frame_writer_mock.reset_mock() on_open_mock = Mock() ch = conn.channel(channel_id=channel_id, callback=on_open_mock) on_open_mock.assert_called_once_with(ch) assert ch.is_open is True ch.close() frame_writer_mock.assert_has_calls([ call(1, 1, spec.Channel.Open, dumps('s', ('', )), None), call(1, 1, spec.Channel.Close, dumps('BsBB', (0, '', 0, 0)), None) ]) assert ch.is_open is False
def test_table__unknown_type(self): table = { 'foo': object(), 'bar': 'baz', 'nil': None, 'array': [1, True, 'bar'] } with pytest.raises(FrameSyntaxError): dumps(b'F', [table])
def test_connect_no_capabilities(self): # Test checking connection handshake with broker # not supporting capabilities frame_writer_cls_mock = Mock() on_open_mock = Mock() frame_writer_mock = frame_writer_cls_mock() conn = Connection( frame_writer=frame_writer_cls_mock, on_open=on_open_mock ) with patch.object(conn, 'Transport') as transport_mock: server_properties = dict(SERVER_PROPERTIES) del server_properties['capabilities'] client_properties = dict(CLIENT_PROPERTIES) del client_properties['capabilities'] handshake( conn, transport_mock, server_properties=server_properties ) on_open_mock.assert_called_once_with(conn) security_mechanism = sasl.AMQPLAIN( 'guest', 'guest' ).start(conn).decode('utf-8', 'surrogatepass') # Expected responses from client frame_writer_mock.assert_has_calls( [ call( 1, 0, spec.Connection.StartOk, # Due Table type, we cannot compare bytestream directly DataComparator( 'FsSs', ( client_properties, 'AMQPLAIN', security_mechanism, 'en_US' ) ), None ), call( 1, 0, spec.Connection.TuneOk, dumps( 'BlB', (conn.channel_max, conn.frame_max, conn.heartbeat) ), None ), call( 1, 0, spec.Connection.Open, dumps('ssb', (conn.virtual_host, '', False)), None ) ] ) assert conn.client_properties == client_properties
def test_connect_missing_capabilities(self): # Test checking connection handshake with broker # supporting subset of capabilities frame_writer_cls_mock = Mock() on_open_mock = Mock() frame_writer_mock = frame_writer_cls_mock() conn = Connection(frame_writer=frame_writer_cls_mock, on_open=on_open_mock) with patch.object(conn, 'Transport') as transport_mock: server_properties = dict(SERVER_PROPERTIES) server_properties['capabilities'] = { # This capability is not supported by client 'basic.nack': True, 'consumer_cancel_notify': True, 'connection.blocked': False, # server does not support 'authentication_failure_close' # which is supported by client } client_properties = dict(CLIENT_PROPERTIES) client_properties['capabilities'] = { 'consumer_cancel_notify': True, } handshake(conn, transport_mock, server_properties=server_properties) on_open_mock.assert_called_once_with(conn) security_mechanism = sasl.AMQPLAIN('guest', 'guest').start(conn).decode( 'utf-8', 'surrogatepass') # Expected responses from client frame_writer_mock.assert_has_calls([ call( 1, 0, spec.Connection.StartOk, # Due Table type, we cannot compare bytestream directly DataComparator('FsSs', (client_properties, 'AMQPLAIN', security_mechanism, 'en_US')), None), call( 1, 0, spec.Connection.TuneOk, dumps('BlB', (conn.channel_max, conn.frame_max, conn.heartbeat)), None), call(1, 0, spec.Connection.Open, dumps('ssb', (conn.virtual_host, '', False)), None) ]) assert conn.client_properties == client_properties
def test_channel_ignore_methods_during_close(self): # Test checking that py-amqp will discard any received methods # except Close and Close-OK after sending Channel.Close method # to server. frame_writer_cls_mock = Mock() conn = Connection(frame_writer=frame_writer_cls_mock) consumer_tag = 'amq.ctag-PCmzXGkhCw_v0Zq7jXyvkg' with patch.object(conn, 'Transport') as transport_mock: handshake(conn, transport_mock) channel_id = 1 transport_mock().read_frame.side_effect = [ # Inject Open Handshake build_frame_type_1(spec.Channel.OpenOk, channel=channel_id, args=(1, False), arg_format='Lb'), # Inject basic-deliver response build_frame_type_1( spec.Basic.Deliver, channel=1, arg_format='sLbss', args=( # consumer-tag, delivery-tag, redelivered, consumer_tag, 1, False, # exchange-name, routing-key 'foo_exchange', 'routing-key')), build_frame_type_2(channel=1, body_len=12, properties=b'0\x00\x00\x00\x00\x00\x01'), build_frame_type_3(channel=1, body=b'Hello World!'), # Inject close method build_frame_type_1(spec.Channel.CloseOk, channel=channel_id), ] frame_writer_mock = frame_writer_cls_mock() frame_writer_mock.reset_mock() with patch('amqp.Channel._on_basic_deliver') as on_deliver_mock: ch = conn.channel(channel_id=channel_id) ch.close() on_deliver_mock.assert_not_called() frame_writer_mock.assert_has_calls([ call(1, 1, spec.Channel.Open, dumps('s', ('', )), None), call(1, 1, spec.Channel.Close, dumps('BsBB', (0, '', 0, 0)), None) ]) assert ch.is_open is False
def test_exchange_delete(self): # Test verifying declaring exchange frame_writer_cls_mock = Mock() conn = Connection(frame_writer=frame_writer_cls_mock) with patch.object(conn, 'Transport') as transport_mock: handshake(conn, transport_mock) ch = create_channel(1, conn, transport_mock) transport_mock().read_frame.return_value = build_frame_type_1( spec.Exchange.DeleteOk, channel=1) frame_writer_mock = frame_writer_cls_mock() frame_writer_mock.reset_mock() ret = ch.exchange_delete('foo') assert ret == () frame_writer_mock.assert_called_once_with( 1, 1, spec.Exchange.Delete, dumps( 'Bsbb', ( 0, # exchange, if-unused, no-wait 'foo', False, False)), None)
def test_roundtrip(self): format = b"bobBlLbsbST" x = dumps( format, [ True, 32, False, 3415, 4513134, 13241923419, True, b"thequickbrownfox", False, "jumpsoverthelazydog", datetime(2015, 3, 13, 10, 23), ], ) y = loads(format, x) self.assertListEqual( [ True, 32, False, 3415, 4513134, 13241923419, True, "thequickbrownfox", False, "jumpsoverthelazydog", ANY(), ], y[0], )
def test_exchange_declare(self): # Test verifying declaring exchange frame_writer_cls_mock = Mock() conn = Connection(frame_writer=frame_writer_cls_mock) with patch.object(conn, 'Transport') as transport_mock: handshake(conn, transport_mock) ch = create_channel(1, conn, transport_mock) transport_mock().read_frame.return_value = build_frame_type_1( spec.Exchange.DeclareOk, channel=1) frame_writer_mock = frame_writer_cls_mock() frame_writer_mock.reset_mock() ret = ch.exchange_declare('foo', 'fanout') assert ret is None frame_writer_mock.assert_called_once_with( 1, 1, spec.Exchange.Declare, dumps( 'BssbbbbbF', ( 0, # exchange, type, passive, durable, 'foo', 'fanout', False, False, # auto_delete, internal, nowait, arguments True, False, False, None)), None)
def test_consume_no_consumer_tag(self): # Test verifing starting consuming without specified consumer_tag callback_mock = Mock() frame_writer_cls_mock = Mock() conn = Connection(frame_writer=frame_writer_cls_mock) consumer_tag = 'amq.ctag-PCmzXGkhCw_v0Zq7jXyvkg' with patch.object(conn, 'Transport') as transport_mock: handshake(conn, transport_mock) ch = create_channel(1, conn, transport_mock) # Inject ConsumeOk response from Broker transport_mock().read_frame.return_value = build_frame_type_1( spec.Basic.ConsumeOk, channel=1, args=(consumer_tag, ), arg_format='s') frame_writer_mock = frame_writer_cls_mock() frame_writer_mock.reset_mock() ret = ch.basic_consume('my_queue', callback=callback_mock) frame_writer_mock.assert_called_once_with( 1, 1, spec.Basic.Consume, dumps('BssbbbbF', (0, 'my_queue', '', False, False, False, False, None)), None) assert ch.callbacks[consumer_tag] == callback_mock assert ret == 'amq.ctag-PCmzXGkhCw_v0Zq7jXyvkg'
def test_queue_get_empty(self): # Test verifying getting message from empty queue frame_writer_cls_mock = Mock() conn = Connection(frame_writer=frame_writer_cls_mock) with patch.object(conn, 'Transport') as transport_mock: handshake(conn, transport_mock) ch = create_channel(1, conn, transport_mock) transport_mock().read_frame.return_value = build_frame_type_1( spec.Basic.GetEmpty, channel=1, arg_format='s', args=('s') ) frame_writer_mock = frame_writer_cls_mock() frame_writer_mock.reset_mock() ret = ch.basic_get('foo') assert ret is None frame_writer_mock.assert_called_once_with( 1, 1, spec.Basic.Get, dumps( 'Bsb', # queue, nowait (0, 'foo', False) ), None )
def test_roundtrip(self): format = b'bobBlLbsbST' x = dumps(format, [ True, 32, False, 3415, 4513134, 13241923419, True, b'thequickbrownfox', False, 'jumpsoverthelazydog', datetime(2015, 3, 13, 10, 23), ]) y = loads(format, x) self.assertListEqual([ True, 32, False, 3415, 4513134, 13241923419, True, 'thequickbrownfox', False, 'jumpsoverthelazydog', ANY(), ], y[0])
def test_queue_purge(self): # Test verifying purging queue frame_writer_cls_mock = Mock() conn = Connection(frame_writer=frame_writer_cls_mock) with patch.object(conn, 'Transport') as transport_mock: handshake(conn, transport_mock) ch = create_channel(1, conn, transport_mock) transport_mock().read_frame.return_value = build_frame_type_1( spec.Queue.PurgeOk, channel=1, arg_format='l', args=(4,) ) frame_writer_mock = frame_writer_cls_mock() frame_writer_mock.reset_mock() msg_count = ch.queue_purge('foo') assert msg_count == 4 frame_writer_mock.assert_called_once_with( 1, 1, spec.Queue.Purge, dumps( 'Bsb', # queue, nowait (0, 'foo', False) ), None )
def test_queue_declare(self): # Test verifying declaring queue frame_writer_cls_mock = Mock() conn = Connection(frame_writer=frame_writer_cls_mock) with patch.object(conn, 'Transport') as transport_mock: handshake(conn, transport_mock) ch = create_channel(1, conn, transport_mock) transport_mock().read_frame.return_value = build_frame_type_1( spec.Queue.DeclareOk, channel=1, arg_format='sll', args=('foo', 1, 2) ) frame_writer_mock = frame_writer_cls_mock() frame_writer_mock.reset_mock() ret = ch.queue_declare('foo') assert ret == queue_declare_ok_t( queue='foo', message_count=1, consumer_count=2 ) frame_writer_mock.assert_called_once_with( 1, 1, spec.Queue.Declare, dumps( 'BsbbbbbF', ( 0, # queue, passive, durable, exclusive, 'foo', False, False, False, # auto_delete, nowait, arguments True, False, None ) ), None )
def ret_factory(method, channel=0, args=b'', arg_format=None): if len(args) > 0: args = dumps(arg_format, args) else: args = b'' frame = (b''.join([pack('>HH', *method), args])) return 1, channel, frame
def test_connecion_ignore_methods_during_close(self, on_blocked_mock): # Test checking that py-amqp will discard any received methods # except Close and Close-OK after sending Connecion.Close method # to server. frame_writer_cls_mock = Mock() frame_writer_mock = frame_writer_cls_mock() conn = Connection(frame_writer=frame_writer_cls_mock) with patch.object(conn, 'Transport') as transport_mock: handshake(conn, transport_mock) frame_writer_mock.reset_mock() # Inject CloseOk response from broker transport_mock().read_frame.side_effect = [ build_frame_type_1( spec.Connection.Blocked, channel=0 ), build_frame_type_1( spec.Connection.CloseOk ) ] t = conn.transport conn.close() on_blocked_mock.assert_not_called() frame_writer_mock.assert_called_once_with( 1, 0, spec.Connection.Close, dumps('BsBB', (0, '', 0, 0)), None ) t.close.assert_called_once_with()
def test_consume_with_consumer_tag(self): # Test verifing starting consuming with specified consumer_tag callback_mock = Mock() frame_writer_cls_mock = Mock() conn = Connection(frame_writer=frame_writer_cls_mock) with patch.object(conn, 'Transport') as transport_mock: handshake(conn, transport_mock) ch = create_channel(1, conn, transport_mock) # Inject ConcumeOk response from Broker transport_mock().read_frame.return_value = ret_factory( spec.Basic.ConsumeOk, channel=1, args=('my_tag', ), arg_format='s') frame_writer_mock = frame_writer_cls_mock() frame_writer_mock.reset_mock() ch.basic_consume('my_queue', callback=callback_mock, consumer_tag='my_tag') frame_writer_mock.assert_called_once_with( 1, 1, spec.Basic.Consume, dumps('BssbbbbF', (0, 'my_queue', 'my_tag', False, False, False, False, None)), None) assert ch.callbacks['my_tag'] == callback_mock
def test_table(self): table = { 'foo': 32, 'bar': 'baz', 'nil': None, 'array': [1, True, 'bar'] } assert loads(b'F', dumps(b'F', [table]), 0)[0][0] == table
def test_bit_offset_adjusted_correctly(self): expected = [ 50, "quick", "fox", True, False, False, True, True, { "prop1": True } ] buf = dumps('BssbbbbbF', expected) actual, _ = loads('BssbbbbbF', buf, 0) assert actual == expected
def test_send_method(self): self.c.send_method((50, 60), 'iB', (30, 0)) self.conn.frame_writer.assert_called_with( 1, self.channel_id, (50, 60), dumps('iB', (30, 0)), None, )
def test_int_boundaries(self): format = b'F' x = dumps(format, [ {'a': -2147483649, 'b': 2147483648}, # celery/celery#3121 ]) y = loads(format, x) assert y[0] == [{ 'a': -2147483649, 'b': 2147483648, # celery/celery#3121 }]
def test_table(self): table = { 'foo': 32, 'bar': 'baz', 'nil': None, 'array': [ 1, True, 'bar' ] } assert loads(b'F', dumps(b'F', [table]))[0][0] == table
def test_queue_get(self): # Test verifying getting message from queue frame_writer_cls_mock = Mock() conn = Connection(frame_writer=frame_writer_cls_mock) with patch.object(conn, 'Transport') as transport_mock: handshake(conn, transport_mock) ch = create_channel(1, conn, transport_mock) transport_mock().read_frame.side_effect = [ build_frame_type_1( spec.Basic.GetOk, channel=1, arg_format='Lbssl', args=( # delivery_tag, redelivered, exchange_name 1, False, 'foo_exchange', # routing_key, message_count 'routing_key', 1 ) ), build_frame_type_2( channel=1, body_len=12, properties=b'0\x00\x00\x00\x00\x00\x01' ), build_frame_type_3( channel=1, body=b'Hello World!' ) ] frame_writer_mock = frame_writer_cls_mock() frame_writer_mock.reset_mock() msg = ch.basic_get('foo') assert msg.body_size == 12 assert msg.body == b'Hello World!' assert msg.frame_method == spec.Basic.GetOk assert msg.delivery_tag == 1 assert msg.ready is True assert msg.delivery_info == { 'delivery_tag': 1, 'redelivered': False, 'exchange': 'foo_exchange', 'routing_key': 'routing_key', 'message_count': 1 } assert msg.properties == { 'application_headers': {}, 'delivery_mode': 1 } frame_writer_mock.assert_called_once_with( 1, 1, spec.Basic.Get, dumps( 'Bsb', # queue, nowait (0, 'foo', False) ), None )
def test_roundtrip(self): format = b'bobBlLbsbST' x = dumps(format, [ True, 32, False, 3415, 4513134, 13241923419, True, b'thequickbrownfox', False, 'jumpsoverthelazydog', datetime(2015, 3, 13, 10, 23), ]) y = loads(format, x) assert [ True, 32, False, 3415, 4513134, 13241923419, True, 'thequickbrownfox', False, 'jumpsoverthelazydog', datetime(2015, 3, 13, 10, 23), ] == y[0]
def test_roundtrip(self): format = b'bobBlLbsbSTx' x = dumps(format, [ True, 32, False, 3415, 4513134, 13241923419, True, b'thequickbrownfox', False, 'jumpsoverthelazydog', datetime(2015, 3, 13, 10, 23), b'thequick\xff' ]) y = loads(format, x) assert [ True, 32, False, 3415, 4513134, 13241923419, True, 'thequickbrownfox', False, 'jumpsoverthelazydog', datetime(2015, 3, 13, 10, 23), b'thequick\xff' ] == y[0]
def test_array(self): array = [ 'A', 1, True, 33.3, Decimal('55.5'), Decimal('-3.4'), datetime(2015, 3, 13, 10, 23), {'quick': 'fox', 'amount': 1}, [3, 'hens'], None, ] expected = list(array) expected[6] = _ANY() assert expected == loads('A', dumps('A', [array]))[0][0]
def test_basic_publish(self): # Test verifing publishing message. frame_writer_cls_mock = Mock() conn = Connection(frame_writer=frame_writer_cls_mock) with patch.object(conn, 'Transport') as transport_mock: handshake(conn, transport_mock) ch = create_channel(1, conn, transport_mock) frame_writer_mock = frame_writer_cls_mock() frame_writer_mock.reset_mock() msg = Message('test') ch.basic_publish(msg) frame_writer_mock.assert_called_once_with( 1, 1, spec.Basic.Publish, dumps('Bssbb', (0, '', '', False, False)), msg)
def test_connection_close(self): # Test checking closing connection frame_writer_cls_mock = Mock() frame_writer_mock = frame_writer_cls_mock() conn = Connection(frame_writer=frame_writer_cls_mock) with patch.object(conn, 'Transport') as transport_mock: handshake(conn, transport_mock) frame_writer_mock.reset_mock() # Inject CloseOk response from broker transport_mock().read_frame.return_value = ret_factory( spec.Connection.CloseOk, args=(1, False), arg_format='Lb') t = conn.transport conn.close() frame_writer_mock.assert_called_once_with( 1, 0, spec.Connection.Close, dumps('BsBB', (0, '', 0, 0)), None) t.close.assert_called_once_with()
def test_exchange_declare_error(self, reply_code, reply_text, exception): # Test verifying wrong declaring exchange frame_writer_cls_mock = Mock() conn = Connection(frame_writer=frame_writer_cls_mock) with patch.object(conn, 'Transport') as transport_mock: handshake(conn, transport_mock) ch = create_channel(1, conn, transport_mock) transport_mock().read_frame.return_value = build_frame_type_1( spec.Connection.Close, args=(reply_code, reply_text) + spec.Exchange.Declare, arg_format='BsBB') frame_writer_mock = frame_writer_cls_mock() frame_writer_mock.reset_mock() with pytest.raises(exception) as excinfo: ch.exchange_declare('exchange', 'exchange-type') assert excinfo.value.code == reply_code assert excinfo.value.message == reply_text assert excinfo.value.method == 'Exchange.declare' assert excinfo.value.method_name == 'Exchange.declare' assert excinfo.value.method_sig == spec.Exchange.Declare # Client is sending to broker: # 1. Exchange Declare # 2. Connection.CloseOk as reply to received Connecton.Close frame_writer_calls = [ call( 1, 1, spec.Exchange.Declare, dumps( 'BssbbbbbF', ( 0, # exchange, type, passive, durable, 'exchange', 'exchange-type', False, False, # auto_delete, internal, nowait, arguments True, False, False, None)), None), call(1, 0, spec.Connection.CloseOk, '', None), ] frame_writer_mock.assert_has_calls(frame_writer_calls)
def test_array(self): array = [ "A", 1, True, 33.3, Decimal("55.5"), Decimal("-3.4"), datetime(2015, 3, 13, 10, 23), {"quick": "fox", "amount": 1}, [3, "hens"], None, ] expected = list(array) expected[6] = ANY() self.assertListEqual(expected, loads("A", dumps("A", [array]))[0][0])
def test_int_boundaries(self): format = b'F' x = dumps( format, [ { 'a': -2147483649, 'b': 2147483648 }, # celery/celery#3121 ]) y = loads(format, x) self.assertListEqual( [ { 'a': -2147483649, 'b': 2147483648 }, # celery/celery#3121 ], y[0])
def test_basic_publish_confirm_nack(self): # test checking whether library is handling correctly Nack confirms # sent from RabbitMQ. Library must raise MessageNacked when server # sent Nack message. # Nack frame construction args = dumps('Lb', (1, False)) frame = (b''.join([pack('>HH', *spec.Basic.Nack), args])) def wait(method, *args, **kwargs): # Simple mock simulating registering callbacks of real wait method for m in method: self.c._pending[m] = kwargs['callback'] self.c._basic_publish = Mock(name='_basic_publish') self.c.wait = Mock(name='wait', side_effect=wait) self.c.basic_publish_confirm(1, 2, arg=1) with pytest.raises(MessageNacked): # Inject Nack to message handler self.c.dispatch_method(spec.Basic.Nack, frame, None)
def test_basic_publish_confirm_nack(self): # test checking whether library is handling correctly Nack confirms # sent from RabbitMQ. Library must raise MessageNacked when server # sent Nack message. # Nack frame construction args = dumps('Lb', (1, False)) frame = (b''.join([pack('>HH', *spec.Basic.Nack), args])) def wait(method, *args, **kwargs): # Simple mock simulating registering callbacks of real wait method for m in method: self.c._pending[m] = kwargs['callback'] self.c._basic_publish = Mock(name='_basic_publish') self.c.wait = Mock(name='wait', side_effect=wait) self.c.basic_publish_confirm(1, 2, arg=1) with pytest.raises(MessageNacked): # Inject Nack to message handler self.c.dispatch_method( spec.Basic.Nack, frame, None )
def test_array_unknown_type(self): with pytest.raises(FrameSyntaxError): dumps('A', [[object()]])
def test_float(self): assert (int(loads(b'fb', dumps(b'fb', [32.31, False]))[0][0] * 100) == 3231)
def test_float(self): self.assertEqual( int(loads(b'fb', dumps(b'fb', [32.31, False]))[0][0] * 100), 3231, )
def test_float(self): self.assertEqual(int(loads(b"fb", dumps(b"fb", [32.31, False]))[0][0] * 100), 3231)
def test_array_unknown_type(self): with self.assertRaises(FrameSyntaxError): dumps("A", [[object()]])
def test_table(self): table = {'foo': 32, 'bar': 'baz', 'nil': None} self.assertDictEqual( loads(b'F', dumps(b'F', [table]))[0][0], table, )
def test_table(self): table = {"foo": 32, "bar": "baz", "nil": None} self.assertDictEqual(loads(b"F", dumps(b"F", [table]))[0][0], table)
def test_bit_offset_adjusted_correctly(self): expected = [50, "quick", "fox", True, False, False, True, True, {"prop1": True}] buf = dumps('BssbbbbbF', expected) actual, _ = loads('BssbbbbbF', buf) assert actual == expected
def test_sixteen_bitflags(self): expected = [True, False] * 8 format = 'b' * len(expected) buf = dumps(format, expected) actual, _ = loads(format, buf) assert actual == expected