kombu/t/unit/test_serialization.py

314 lines
10 KiB
Python
Raw Normal View History

2010-06-29 15:31:56 +00:00
#!/usr/bin/python
2013-01-17 13:16:32 +00:00
import pytest
2013-01-17 13:16:32 +00:00
import sys
2013-06-25 14:10:04 +00:00
from base64 import b64decode
from case import call, mock, patch, skip
2013-12-16 16:53:54 +00:00
from kombu.exceptions import ContentDisallowed, EncodeError, DecodeError
from kombu.serialization import (
registry, register, SerializerNotInstalled,
raw_encode, register_yaml, register_msgpack,
dumps, loads, pickle, pickle_protocol,
2013-09-12 12:10:42 +00:00
unregister, register_pickle, enable_insecure_serializers,
disable_insecure_serializers,
)
from kombu.utils.encoding import str_to_bytes
2010-06-29 15:31:56 +00:00
# For content_encoding tests
2013-02-12 16:37:01 +00:00
unicode_string = 'abcdé\u8463'
2010-06-29 15:31:56 +00:00
unicode_string_as_utf8 = unicode_string.encode('utf-8')
2013-02-12 16:37:01 +00:00
latin_string = 'abcdé'
2010-06-29 15:31:56 +00:00
latin_string_as_latin1 = latin_string.encode('latin-1')
latin_string_as_utf8 = latin_string.encode('utf-8')
# For serialization tests
2013-01-17 13:50:01 +00:00
py_data = {
'string': 'The quick brown fox jumps over the lazy dog',
'int': 10,
'float': 3.14159265,
2013-02-12 16:37:01 +00:00
'unicode': 'Thé quick brown fox jumps over thé lazy dog',
2013-01-17 13:50:01 +00:00
'list': ['george', 'jerry', 'elaine', 'cosmo'],
2010-06-29 15:31:56 +00:00
}
# JSON serialization tests
2013-01-17 13:50:01 +00:00
json_data = """\
{"int": 10, "float": 3.1415926500000002, \
"list": ["george", "jerry", "elaine", "cosmo"], \
"string": "The quick brown fox jumps over the lazy \
dog", "unicode": "Th\\u00e9 quick brown fox jumps over \
th\\u00e9 lazy dog"}\
"""
2010-06-29 15:31:56 +00:00
# Pickle serialization tests
pickle_data = pickle.dumps(py_data, protocol=pickle_protocol)
2010-06-29 15:31:56 +00:00
# YAML serialization tests
2013-01-17 13:50:01 +00:00
yaml_data = """\
float: 3.1415926500000002
int: 10
list: [george, jerry, elaine, cosmo]
string: The quick brown fox jumps over the lazy dog
unicode: "Th\\xE9 quick brown fox jumps over th\\xE9 lazy dog"
"""
2010-06-29 15:31:56 +00:00
2013-01-17 13:16:32 +00:00
msgpack_py_data = dict(py_data)
msgpack_py_data['unicode'] = 'Th quick brown fox jumps over th lazy dog'
2010-06-29 15:31:56 +00:00
# Unicode chars are lost in transmit :(
msgpack_data = b64decode(str_to_bytes("""\
2013-06-25 14:10:04 +00:00
haNpbnQKpWZsb2F0y0AJIftTyNTxpGxpc3SUpmdlb3JnZaVqZXJyeaZlbGFpbmWlY29zbW+mc3Rya\
W5n2gArVGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZ6d1bmljb2Rl2g\
ApVGggcXVpY2sgYnJvd24gZm94IGp1bXBzIG92ZXIgdGggbGF6eSBkb2c=\
"""))
2013-01-17 13:16:32 +00:00
2012-06-15 17:32:40 +00:00
registry.register('testS', lambda s: s, lambda s: 'decoded',
'application/testS', 'utf-8')
2012-01-13 19:04:49 +00:00
class test_Serialization:
2010-06-29 15:31:56 +00:00
2012-01-13 19:04:49 +00:00
def test_disable(self):
disabled = registry._disabled_content_types
try:
2012-06-15 17:32:40 +00:00
registry.disable('testS')
assert 'application/testS' in disabled
2012-01-13 19:04:49 +00:00
disabled.clear()
2012-06-15 17:32:40 +00:00
registry.disable('application/testS')
assert 'application/testS' in disabled
2012-01-13 19:04:49 +00:00
finally:
disabled.clear()
2013-09-12 12:10:42 +00:00
def test_enable(self):
registry._disabled_content_types.add('application/json')
registry.enable('json')
assert 'application/json' not in registry._disabled_content_types
2013-09-12 12:10:42 +00:00
registry._disabled_content_types.add('application/json')
registry.enable('application/json')
assert 'application/json' not in registry._disabled_content_types
2013-09-12 12:10:42 +00:00
def test_loads_when_disabled(self):
2012-01-13 19:04:49 +00:00
disabled = registry._disabled_content_types
try:
2012-06-15 17:32:40 +00:00
registry.disable('testS')
2012-01-13 19:04:49 +00:00
with pytest.raises(SerializerNotInstalled):
loads('xxd', 'application/testS', 'utf-8', force=False)
2012-01-13 19:04:49 +00:00
ret = loads('xxd', 'application/testS', 'utf-8', force=True)
assert ret == 'decoded'
2012-01-13 19:04:49 +00:00
finally:
disabled.clear()
def test_loads_when_data_is_None(self):
loads(None, 'application/testS', 'utf-8')
2012-01-13 19:04:49 +00:00
2010-06-29 15:31:56 +00:00
def test_content_type_decoding(self):
assert loads(
unicode_string_as_utf8,
content_type='plain/text',
content_encoding='utf-8') == unicode_string
assert loads(
latin_string_as_latin1,
content_type='application/data',
content_encoding='latin-1') == latin_string
2010-06-29 15:31:56 +00:00
def test_content_type_binary(self):
assert isinstance(
loads(unicode_string_as_utf8,
content_type='application/data', content_encoding='binary'),
2020-07-23 13:33:40 +00:00
bytes)
2013-01-17 13:50:01 +00:00
assert loads(
2013-01-17 13:50:01 +00:00
unicode_string_as_utf8,
content_type='application/data',
content_encoding='binary') == unicode_string_as_utf8
2010-06-29 15:31:56 +00:00
def test_content_type_encoding(self):
2012-06-15 17:32:40 +00:00
# Using the 'raw' serializer
assert (dumps(unicode_string, serializer='raw')[-1] ==
unicode_string_as_utf8)
assert (dumps(latin_string, serializer='raw')[-1] ==
latin_string_as_utf8)
2010-06-29 15:31:56 +00:00
# And again w/o a specific serializer to check the
# code where we force unicode objects into a string.
assert dumps(unicode_string)[-1] == unicode_string_as_utf8
assert dumps(latin_string)[-1] == latin_string_as_utf8
2010-06-29 15:31:56 +00:00
2013-09-12 12:10:42 +00:00
def test_enable_insecure_serializers(self):
with patch('kombu.serialization.registry') as registry:
enable_insecure_serializers()
registry.assert_has_calls([
2013-09-12 16:32:25 +00:00
call.enable('pickle'), call.enable('yaml'),
call.enable('msgpack'),
2013-09-12 12:10:42 +00:00
])
registry.enable.side_effect = KeyError()
enable_insecure_serializers()
with patch('kombu.serialization.registry') as registry:
enable_insecure_serializers(['msgpack'])
registry.assert_has_calls([call.enable('msgpack')])
def test_disable_insecure_serializers(self):
with patch('kombu.serialization.registry') as registry:
registry._decoders = ['pickle', 'yaml', 'doomsday']
disable_insecure_serializers(allowed=['doomsday'])
registry.disable.assert_has_calls([call('pickle'), call('yaml')])
registry.enable.assert_has_calls([call('doomsday')])
disable_insecure_serializers(allowed=None)
registry.disable.assert_has_calls([
call('pickle'), call('yaml'), call('doomsday')
])
2013-12-16 16:53:54 +00:00
def test_reraises_EncodeError(self):
with pytest.raises(EncodeError):
2013-12-16 16:53:54 +00:00
dumps([object()], serializer='json')
def test_reraises_DecodeError(self):
with pytest.raises(DecodeError):
2013-12-16 16:53:54 +00:00
loads(object(), content_type='application/json',
content_encoding='utf-8')
def test_json_loads(self):
assert loads(json_data,
content_type='application/json',
content_encoding='utf-8') == py_data
2010-06-29 15:31:56 +00:00
def test_json_dumps(self):
a = loads(
dumps(py_data, serializer='json')[-1],
content_type='application/json',
content_encoding='utf-8',
)
b = loads(
json_data,
content_type='application/json',
content_encoding='utf-8',
2013-01-17 13:50:01 +00:00
)
assert a == b
2010-06-29 15:31:56 +00:00
2016-04-05 21:57:00 +00:00
@skip.if_pypy()
@skip.unless_module('msgpack', (ImportError, ValueError))
def test_msgpack_loads(self):
register_msgpack()
res = loads(msgpack_data,
content_type='application/x-msgpack',
content_encoding='binary')
if sys.version_info[0] < 3:
for k, v in res.items():
2020-07-23 13:33:40 +00:00
if isinstance(v, str):
res[k] = v.encode()
if isinstance(v, (list, tuple)):
res[k] = [i.encode() for i in v]
assert res == msgpack_py_data
2013-01-17 13:16:32 +00:00
2016-04-05 21:57:00 +00:00
@skip.if_pypy()
@skip.unless_module('msgpack', (ImportError, ValueError))
def test_msgpack_dumps(self):
2013-01-17 13:16:32 +00:00
register_msgpack()
a = loads(
dumps(msgpack_py_data, serializer='msgpack')[-1],
content_type='application/x-msgpack',
content_encoding='binary',
2013-01-17 13:50:01 +00:00
)
b = loads(
msgpack_data,
content_type='application/x-msgpack',
content_encoding='binary',
)
assert a == b
2010-06-29 15:31:56 +00:00
2016-04-05 21:57:00 +00:00
@skip.unless_module('yaml')
def test_yaml_loads(self):
register_yaml()
assert loads(
yaml_data,
content_type='application/x-yaml',
content_encoding='utf-8') == py_data
2010-06-29 15:31:56 +00:00
2016-04-05 21:57:00 +00:00
@skip.unless_module('yaml')
def test_yaml_dumps(self):
register_yaml()
a = loads(
dumps(py_data, serializer='yaml')[-1],
content_type='application/x-yaml',
content_encoding='utf-8',
)
b = loads(
yaml_data,
content_type='application/x-yaml',
content_encoding='utf-8',
2013-01-17 13:50:01 +00:00
)
assert a == b
2010-06-29 15:31:56 +00:00
def test_pickle_loads(self):
assert loads(
pickle_data,
content_type='application/x-python-serialize',
content_encoding='binary') == py_data
2010-06-29 15:31:56 +00:00
def test_pickle_dumps(self):
a = pickle.loads(pickle_data),
b = pickle.loads(dumps(py_data, serializer='pickle')[-1]),
assert a == b
2010-06-29 15:31:56 +00:00
def test_register(self):
register(None, None, None, None)
2011-07-19 13:44:01 +00:00
def test_unregister(self):
with pytest.raises(SerializerNotInstalled):
2012-06-15 17:32:40 +00:00
unregister('nonexisting')
dumps('foo', serializer='pickle')
2012-06-15 17:32:40 +00:00
unregister('pickle')
with pytest.raises(SerializerNotInstalled):
dumps('foo', serializer='pickle')
2011-07-19 13:44:01 +00:00
register_pickle()
def test_set_default_serializer_missing(self):
with pytest.raises(SerializerNotInstalled):
2012-06-15 17:32:40 +00:00
registry._set_default_serializer('nonexisting')
def test_dumps_missing(self):
with pytest.raises(SerializerNotInstalled):
dumps('foo', serializer='nonexisting')
def test_dumps__no_serializer(self):
ctyp, cenc, data = dumps(str_to_bytes('foo'))
assert ctyp == 'application/data'
assert cenc == 'binary'
2013-09-12 12:10:42 +00:00
def test_loads__trusted_content(self):
loads('tainted', 'application/data', 'binary', accept=[])
loads('tainted', 'application/text', 'utf-8', accept=[])
def test_loads__not_accepted(self):
with pytest.raises(ContentDisallowed):
loads('tainted', 'application/x-evil', 'binary', accept=[])
with pytest.raises(ContentDisallowed):
loads('tainted', 'application/x-evil', 'binary',
accept=['application/x-json'])
assert loads('tainted', 'application/x-doomsday', 'binary',
accept=['application/x-doomsday'])
2013-09-12 12:10:42 +00:00
def test_raw_encode(self):
2020-07-13 13:58:06 +00:00
assert raw_encode(b'foo') == (
'application/data', 'binary', b'foo',
2013-01-17 13:50:01 +00:00
)
2016-04-05 21:57:00 +00:00
@mock.mask_modules('yaml')
def test_register_yaml__no_yaml(self):
register_yaml()
with pytest.raises(SerializerNotInstalled):
loads('foo', 'application/x-yaml', 'utf-8')
2016-04-05 21:57:00 +00:00
@mock.mask_modules('msgpack')
def test_register_msgpack__no_msgpack(self):
register_msgpack()
with pytest.raises(SerializerNotInstalled):
loads('foo', 'application/x-msgpack', 'utf-8')