Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

test_serialization.py 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. from __future__ import absolute_import, unicode_literals
  4. import sys
  5. from base64 import b64decode
  6. from kombu.exceptions import ContentDisallowed, EncodeError, DecodeError
  7. from kombu.five import text_t, bytes_t
  8. from kombu.serialization import (
  9. registry, register, SerializerNotInstalled,
  10. raw_encode, register_yaml, register_msgpack,
  11. dumps, loads, pickle, pickle_protocol,
  12. unregister, register_pickle, enable_insecure_serializers,
  13. disable_insecure_serializers,
  14. )
  15. from kombu.utils.encoding import str_to_bytes
  16. from .case import Case, call, mask_modules, patch, skip_if_not_module
  17. # For content_encoding tests
  18. unicode_string = 'abcdé\u8463'
  19. unicode_string_as_utf8 = unicode_string.encode('utf-8')
  20. latin_string = 'abcdé'
  21. latin_string_as_latin1 = latin_string.encode('latin-1')
  22. latin_string_as_utf8 = latin_string.encode('utf-8')
  23. # For serialization tests
  24. py_data = {
  25. 'string': 'The quick brown fox jumps over the lazy dog',
  26. 'int': 10,
  27. 'float': 3.14159265,
  28. 'unicode': 'Thé quick brown fox jumps over thé lazy dog',
  29. 'list': ['george', 'jerry', 'elaine', 'cosmo'],
  30. }
  31. # JSON serialization tests
  32. json_data = """\
  33. {"int": 10, "float": 3.1415926500000002, \
  34. "list": ["george", "jerry", "elaine", "cosmo"], \
  35. "string": "The quick brown fox jumps over the lazy \
  36. dog", "unicode": "Th\\u00e9 quick brown fox jumps over \
  37. th\\u00e9 lazy dog"}\
  38. """
  39. # Pickle serialization tests
  40. pickle_data = pickle.dumps(py_data, protocol=pickle_protocol)
  41. # YAML serialization tests
  42. yaml_data = """\
  43. float: 3.1415926500000002
  44. int: 10
  45. list: [george, jerry, elaine, cosmo]
  46. string: The quick brown fox jumps over the lazy dog
  47. unicode: "Th\\xE9 quick brown fox jumps over th\\xE9 lazy dog"
  48. """
  49. msgpack_py_data = dict(py_data)
  50. msgpack_py_data['unicode'] = 'Th quick brown fox jumps over th lazy dog'
  51. # Unicode chars are lost in transmit :(
  52. msgpack_data = b64decode(str_to_bytes("""\
  53. haNpbnQKpWZsb2F0y0AJIftTyNTxpGxpc3SUpmdlb3JnZaVqZXJyeaZlbGFpbmWlY29zbW+mc3Rya\
  54. W5n2gArVGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZ6d1bmljb2Rl2g\
  55. ApVGggcXVpY2sgYnJvd24gZm94IGp1bXBzIG92ZXIgdGggbGF6eSBkb2c=\
  56. """))
  57. def say(m):
  58. sys.stderr.write('%s\n' % (m, ))
  59. registry.register('testS', lambda s: s, lambda s: 'decoded',
  60. 'application/testS', 'utf-8')
  61. class test_Serialization(Case):
  62. def test_disable(self):
  63. disabled = registry._disabled_content_types
  64. try:
  65. registry.disable('testS')
  66. self.assertIn('application/testS', disabled)
  67. disabled.clear()
  68. registry.disable('application/testS')
  69. self.assertIn('application/testS', disabled)
  70. finally:
  71. disabled.clear()
  72. def test_enable(self):
  73. registry._disabled_content_types.add('application/json')
  74. registry.enable('json')
  75. self.assertNotIn('application/json', registry._disabled_content_types)
  76. registry._disabled_content_types.add('application/json')
  77. registry.enable('application/json')
  78. self.assertNotIn('application/json', registry._disabled_content_types)
  79. def test_loads_when_disabled(self):
  80. disabled = registry._disabled_content_types
  81. try:
  82. registry.disable('testS')
  83. with self.assertRaises(SerializerNotInstalled):
  84. loads('xxd', 'application/testS', 'utf-8', force=False)
  85. ret = loads('xxd', 'application/testS', 'utf-8', force=True)
  86. self.assertEqual(ret, 'decoded')
  87. finally:
  88. disabled.clear()
  89. def test_loads_when_data_is_None(self):
  90. loads(None, 'application/testS', 'utf-8')
  91. def test_content_type_decoding(self):
  92. self.assertEqual(
  93. unicode_string,
  94. loads(unicode_string_as_utf8,
  95. content_type='plain/text', content_encoding='utf-8'),
  96. )
  97. self.assertEqual(
  98. latin_string,
  99. loads(latin_string_as_latin1,
  100. content_type='application/data', content_encoding='latin-1'),
  101. )
  102. def test_content_type_binary(self):
  103. self.assertIsInstance(
  104. loads(unicode_string_as_utf8,
  105. content_type='application/data', content_encoding='binary'),
  106. bytes_t,
  107. )
  108. self.assertEqual(
  109. unicode_string_as_utf8,
  110. loads(unicode_string_as_utf8,
  111. content_type='application/data', content_encoding='binary'),
  112. )
  113. def test_content_type_encoding(self):
  114. # Using the 'raw' serializer
  115. self.assertEqual(
  116. unicode_string_as_utf8,
  117. dumps(unicode_string, serializer='raw')[-1],
  118. )
  119. self.assertEqual(
  120. latin_string_as_utf8,
  121. dumps(latin_string, serializer='raw')[-1],
  122. )
  123. # And again w/o a specific serializer to check the
  124. # code where we force unicode objects into a string.
  125. self.assertEqual(
  126. unicode_string_as_utf8,
  127. dumps(unicode_string)[-1],
  128. )
  129. self.assertEqual(
  130. latin_string_as_utf8,
  131. dumps(latin_string)[-1],
  132. )
  133. def test_enable_insecure_serializers(self):
  134. with patch('kombu.serialization.registry') as registry:
  135. enable_insecure_serializers()
  136. registry.assert_has_calls([
  137. call.enable('pickle'), call.enable('yaml'),
  138. call.enable('msgpack'),
  139. ])
  140. registry.enable.side_effect = KeyError()
  141. enable_insecure_serializers()
  142. with patch('kombu.serialization.registry') as registry:
  143. enable_insecure_serializers(['msgpack'])
  144. registry.assert_has_calls([call.enable('msgpack')])
  145. def test_disable_insecure_serializers(self):
  146. with patch('kombu.serialization.registry') as registry:
  147. registry._decoders = ['pickle', 'yaml', 'doomsday']
  148. disable_insecure_serializers(allowed=['doomsday'])
  149. registry.disable.assert_has_calls([call('pickle'), call('yaml')])
  150. registry.enable.assert_has_calls([call('doomsday')])
  151. disable_insecure_serializers(allowed=None)
  152. registry.disable.assert_has_calls([
  153. call('pickle'), call('yaml'), call('doomsday')
  154. ])
  155. def test_reraises_EncodeError(self):
  156. with self.assertRaises(EncodeError):
  157. dumps([object()], serializer='json')
  158. def test_reraises_DecodeError(self):
  159. with self.assertRaises(DecodeError):
  160. loads(object(), content_type='application/json',
  161. content_encoding='utf-8')
  162. def test_json_loads(self):
  163. self.assertEqual(
  164. py_data,
  165. loads(json_data,
  166. content_type='application/json', content_encoding='utf-8'),
  167. )
  168. def test_json_dumps(self):
  169. self.assertEqual(
  170. loads(
  171. dumps(py_data, serializer='json')[-1],
  172. content_type='application/json',
  173. content_encoding='utf-8',
  174. ),
  175. loads(
  176. json_data,
  177. content_type='application/json',
  178. content_encoding='utf-8',
  179. ),
  180. )
  181. @skip_if_not_module('msgpack', (ImportError, ValueError))
  182. def test_msgpack_loads(self):
  183. register_msgpack()
  184. res = loads(msgpack_data,
  185. content_type='application/x-msgpack',
  186. content_encoding='binary')
  187. if sys.version_info[0] < 3:
  188. for k, v in res.items():
  189. if isinstance(v, text_t):
  190. res[k] = v.encode()
  191. if isinstance(v, (list, tuple)):
  192. res[k] = [i.encode() for i in v]
  193. self.assertEqual(
  194. msgpack_py_data,
  195. res,
  196. )
  197. @skip_if_not_module('msgpack', (ImportError, ValueError))
  198. def test_msgpack_dumps(self):
  199. register_msgpack()
  200. self.assertEqual(
  201. loads(
  202. dumps(msgpack_py_data, serializer='msgpack')[-1],
  203. content_type='application/x-msgpack',
  204. content_encoding='binary',
  205. ),
  206. loads(
  207. msgpack_data,
  208. content_type='application/x-msgpack',
  209. content_encoding='binary',
  210. ),
  211. )
  212. @skip_if_not_module('yaml')
  213. def test_yaml_loads(self):
  214. register_yaml()
  215. self.assertEqual(
  216. py_data,
  217. loads(yaml_data,
  218. content_type='application/x-yaml',
  219. content_encoding='utf-8'),
  220. )
  221. @skip_if_not_module('yaml')
  222. def test_yaml_dumps(self):
  223. register_yaml()
  224. self.assertEqual(
  225. loads(
  226. dumps(py_data, serializer='yaml')[-1],
  227. content_type='application/x-yaml',
  228. content_encoding='utf-8',
  229. ),
  230. loads(
  231. yaml_data,
  232. content_type='application/x-yaml',
  233. content_encoding='utf-8',
  234. ),
  235. )
  236. def test_pickle_loads(self):
  237. self.assertEqual(
  238. py_data,
  239. loads(pickle_data,
  240. content_type='application/x-python-serialize',
  241. content_encoding='binary'),
  242. )
  243. def test_pickle_dumps(self):
  244. self.assertEqual(
  245. pickle.loads(pickle_data),
  246. pickle.loads(dumps(py_data, serializer='pickle')[-1]),
  247. )
  248. def test_register(self):
  249. register(None, None, None, None)
  250. def test_unregister(self):
  251. with self.assertRaises(SerializerNotInstalled):
  252. unregister('nonexisting')
  253. dumps('foo', serializer='pickle')
  254. unregister('pickle')
  255. with self.assertRaises(SerializerNotInstalled):
  256. dumps('foo', serializer='pickle')
  257. register_pickle()
  258. def test_set_default_serializer_missing(self):
  259. with self.assertRaises(SerializerNotInstalled):
  260. registry._set_default_serializer('nonexisting')
  261. def test_dumps_missing(self):
  262. with self.assertRaises(SerializerNotInstalled):
  263. dumps('foo', serializer='nonexisting')
  264. def test_dumps__no_serializer(self):
  265. ctyp, cenc, data = dumps(str_to_bytes('foo'))
  266. self.assertEqual(ctyp, 'application/data')
  267. self.assertEqual(cenc, 'binary')
  268. def test_loads__trusted_content(self):
  269. loads('tainted', 'application/data', 'binary', accept=[])
  270. loads('tainted', 'application/text', 'utf-8', accept=[])
  271. def test_loads__not_accepted(self):
  272. with self.assertRaises(ContentDisallowed):
  273. loads('tainted', 'application/x-evil', 'binary', accept=[])
  274. with self.assertRaises(ContentDisallowed):
  275. loads('tainted', 'application/x-evil', 'binary',
  276. accept=['application/x-json'])
  277. self.assertTrue(
  278. loads('tainted', 'application/x-doomsday', 'binary',
  279. accept=['application/x-doomsday'])
  280. )
  281. def test_raw_encode(self):
  282. self.assertTupleEqual(
  283. raw_encode('foo'.encode('utf-8')),
  284. ('application/data', 'binary', 'foo'.encode('utf-8')),
  285. )
  286. @mask_modules('yaml')
  287. def test_register_yaml__no_yaml(self):
  288. register_yaml()
  289. with self.assertRaises(SerializerNotInstalled):
  290. loads('foo', 'application/x-yaml', 'utf-8')
  291. @mask_modules('msgpack')
  292. def test_register_msgpack__no_msgpack(self):
  293. register_msgpack()
  294. with self.assertRaises(SerializerNotInstalled):
  295. loads('foo', 'application/x-msgpack', 'utf-8')