test_marshal.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. # -*- coding: iso-8859-1 -*-
  2. from test import test_support
  3. import marshal
  4. import sys
  5. import unittest
  6. import os
  7. try:
  8. import _testcapi
  9. except ImportError:
  10. _testcapi = None
  11. class IntTestCase(unittest.TestCase):
  12. def test_ints(self):
  13. # Test the full range of Python ints.
  14. n = sys.maxint
  15. while n:
  16. for expected in (-n, n):
  17. s = marshal.dumps(expected)
  18. got = marshal.loads(s)
  19. self.assertEqual(expected, got)
  20. marshal.dump(expected, file(test_support.TESTFN, "wb"))
  21. got = marshal.load(file(test_support.TESTFN, "rb"))
  22. self.assertEqual(expected, got)
  23. n = n >> 1
  24. os.unlink(test_support.TESTFN)
  25. def test_int64(self):
  26. # Simulate int marshaling on a 64-bit box. This is most interesting if
  27. # we're running the test on a 32-bit box, of course.
  28. def to_little_endian_string(value, nbytes):
  29. bytes = []
  30. for i in range(nbytes):
  31. bytes.append(chr(value & 0xff))
  32. value >>= 8
  33. return ''.join(bytes)
  34. maxint64 = (1L << 63) - 1
  35. minint64 = -maxint64-1
  36. for base in maxint64, minint64, -maxint64, -(minint64 >> 1):
  37. while base:
  38. s = 'I' + to_little_endian_string(base, 8)
  39. got = marshal.loads(s)
  40. self.assertEqual(base, got)
  41. if base == -1: # a fixed-point for shifting right 1
  42. base = 0
  43. else:
  44. base >>= 1
  45. def test_bool(self):
  46. for b in (True, False):
  47. new = marshal.loads(marshal.dumps(b))
  48. self.assertEqual(b, new)
  49. self.assertEqual(type(b), type(new))
  50. marshal.dump(b, file(test_support.TESTFN, "wb"))
  51. new = marshal.load(file(test_support.TESTFN, "rb"))
  52. self.assertEqual(b, new)
  53. self.assertEqual(type(b), type(new))
  54. class FloatTestCase(unittest.TestCase):
  55. def test_floats(self):
  56. # Test a few floats
  57. small = 1e-25
  58. n = sys.maxint * 3.7e250
  59. while n > small:
  60. for expected in (-n, n):
  61. f = float(expected)
  62. s = marshal.dumps(f)
  63. got = marshal.loads(s)
  64. self.assertEqual(f, got)
  65. marshal.dump(f, file(test_support.TESTFN, "wb"))
  66. got = marshal.load(file(test_support.TESTFN, "rb"))
  67. self.assertEqual(f, got)
  68. n /= 123.4567
  69. f = 0.0
  70. s = marshal.dumps(f, 2)
  71. got = marshal.loads(s)
  72. self.assertEqual(f, got)
  73. # and with version <= 1 (floats marshalled differently then)
  74. s = marshal.dumps(f, 1)
  75. got = marshal.loads(s)
  76. self.assertEqual(f, got)
  77. n = sys.maxint * 3.7e-250
  78. while n < small:
  79. for expected in (-n, n):
  80. f = float(expected)
  81. s = marshal.dumps(f)
  82. got = marshal.loads(s)
  83. self.assertEqual(f, got)
  84. s = marshal.dumps(f, 1)
  85. got = marshal.loads(s)
  86. self.assertEqual(f, got)
  87. marshal.dump(f, file(test_support.TESTFN, "wb"))
  88. got = marshal.load(file(test_support.TESTFN, "rb"))
  89. self.assertEqual(f, got)
  90. marshal.dump(f, file(test_support.TESTFN, "wb"), 1)
  91. got = marshal.load(file(test_support.TESTFN, "rb"))
  92. self.assertEqual(f, got)
  93. n *= 123.4567
  94. os.unlink(test_support.TESTFN)
  95. class StringTestCase(unittest.TestCase):
  96. def test_unicode(self):
  97. for s in [u"", u"Andrè Previn", u"abc", u" "*10000]:
  98. new = marshal.loads(marshal.dumps(s))
  99. self.assertEqual(s, new)
  100. self.assertEqual(type(s), type(new))
  101. marshal.dump(s, file(test_support.TESTFN, "wb"))
  102. new = marshal.load(file(test_support.TESTFN, "rb"))
  103. self.assertEqual(s, new)
  104. self.assertEqual(type(s), type(new))
  105. os.unlink(test_support.TESTFN)
  106. def test_string(self):
  107. for s in ["", "Andrè Previn", "abc", " "*10000]:
  108. new = marshal.loads(marshal.dumps(s))
  109. self.assertEqual(s, new)
  110. self.assertEqual(type(s), type(new))
  111. marshal.dump(s, file(test_support.TESTFN, "wb"))
  112. new = marshal.load(file(test_support.TESTFN, "rb"))
  113. self.assertEqual(s, new)
  114. self.assertEqual(type(s), type(new))
  115. os.unlink(test_support.TESTFN)
  116. def test_buffer(self):
  117. for s in ["", "Andrè Previn", "abc", " "*10000]:
  118. with test_support.check_py3k_warnings(("buffer.. not supported",
  119. DeprecationWarning)):
  120. b = buffer(s)
  121. new = marshal.loads(marshal.dumps(b))
  122. self.assertEqual(s, new)
  123. marshal.dump(b, file(test_support.TESTFN, "wb"))
  124. new = marshal.load(file(test_support.TESTFN, "rb"))
  125. self.assertEqual(s, new)
  126. os.unlink(test_support.TESTFN)
  127. class ExceptionTestCase(unittest.TestCase):
  128. def test_exceptions(self):
  129. new = marshal.loads(marshal.dumps(StopIteration))
  130. self.assertEqual(StopIteration, new)
  131. class CodeTestCase(unittest.TestCase):
  132. def test_code(self):
  133. co = ExceptionTestCase.test_exceptions.func_code
  134. new = marshal.loads(marshal.dumps(co))
  135. self.assertEqual(co, new)
  136. class ContainerTestCase(unittest.TestCase):
  137. d = {'astring': 'foo@bar.baz.spam',
  138. 'afloat': 7283.43,
  139. 'anint': 2**20,
  140. 'ashortlong': 2L,
  141. 'alist': ['.zyx.41'],
  142. 'atuple': ('.zyx.41',)*10,
  143. 'aboolean': False,
  144. 'aunicode': u"Andrè Previn"
  145. }
  146. def test_dict(self):
  147. new = marshal.loads(marshal.dumps(self.d))
  148. self.assertEqual(self.d, new)
  149. marshal.dump(self.d, file(test_support.TESTFN, "wb"))
  150. new = marshal.load(file(test_support.TESTFN, "rb"))
  151. self.assertEqual(self.d, new)
  152. os.unlink(test_support.TESTFN)
  153. def test_list(self):
  154. lst = self.d.items()
  155. new = marshal.loads(marshal.dumps(lst))
  156. self.assertEqual(lst, new)
  157. marshal.dump(lst, file(test_support.TESTFN, "wb"))
  158. new = marshal.load(file(test_support.TESTFN, "rb"))
  159. self.assertEqual(lst, new)
  160. os.unlink(test_support.TESTFN)
  161. def test_tuple(self):
  162. t = tuple(self.d.keys())
  163. new = marshal.loads(marshal.dumps(t))
  164. self.assertEqual(t, new)
  165. marshal.dump(t, file(test_support.TESTFN, "wb"))
  166. new = marshal.load(file(test_support.TESTFN, "rb"))
  167. self.assertEqual(t, new)
  168. os.unlink(test_support.TESTFN)
  169. def test_sets(self):
  170. for constructor in (set, frozenset):
  171. t = constructor(self.d.keys())
  172. new = marshal.loads(marshal.dumps(t))
  173. self.assertEqual(t, new)
  174. self.assertTrue(isinstance(new, constructor))
  175. self.assertNotEqual(id(t), id(new))
  176. marshal.dump(t, file(test_support.TESTFN, "wb"))
  177. new = marshal.load(file(test_support.TESTFN, "rb"))
  178. self.assertEqual(t, new)
  179. os.unlink(test_support.TESTFN)
  180. class BugsTestCase(unittest.TestCase):
  181. def test_bug_5888452(self):
  182. # Simple-minded check for SF 588452: Debug build crashes
  183. marshal.dumps([128] * 1000)
  184. def test_patch_873224(self):
  185. self.assertRaises(Exception, marshal.loads, '0')
  186. self.assertRaises(Exception, marshal.loads, 'f')
  187. self.assertRaises(Exception, marshal.loads, marshal.dumps(5L)[:-1])
  188. def test_version_argument(self):
  189. # Python 2.4.0 crashes for any call to marshal.dumps(x, y)
  190. self.assertEqual(marshal.loads(marshal.dumps(5, 0)), 5)
  191. self.assertEqual(marshal.loads(marshal.dumps(5, 1)), 5)
  192. def test_fuzz(self):
  193. # simple test that it's at least not *totally* trivial to
  194. # crash from bad marshal data
  195. for c in [chr(i) for i in range(256)]:
  196. try:
  197. marshal.loads(c)
  198. except Exception:
  199. pass
  200. def test_loads_recursion(self):
  201. s = 'c' + ('X' * 4*4) + '{' * 2**20
  202. self.assertRaises(ValueError, marshal.loads, s)
  203. def test_recursion_limit(self):
  204. # Create a deeply nested structure.
  205. head = last = []
  206. # The max stack depth should match the value in Python/marshal.c.
  207. MAX_MARSHAL_STACK_DEPTH = 2000
  208. for i in range(MAX_MARSHAL_STACK_DEPTH - 2):
  209. last.append([0])
  210. last = last[-1]
  211. # Verify we don't blow out the stack with dumps/load.
  212. data = marshal.dumps(head)
  213. new_head = marshal.loads(data)
  214. # Don't use == to compare objects, it can exceed the recursion limit.
  215. self.assertEqual(len(new_head), len(head))
  216. self.assertEqual(len(new_head[0]), len(head[0]))
  217. self.assertEqual(len(new_head[-1]), len(head[-1]))
  218. last.append([0])
  219. self.assertRaises(ValueError, marshal.dumps, head)
  220. def test_exact_type_match(self):
  221. # Former bug:
  222. # >>> class Int(int): pass
  223. # >>> type(loads(dumps(Int())))
  224. # <type 'int'>
  225. for typ in (int, long, float, complex, tuple, list, dict, set, frozenset):
  226. # Note: str and unicode subclasses are not tested because they get handled
  227. # by marshal's routines for objects supporting the buffer API.
  228. subtyp = type('subtyp', (typ,), {})
  229. self.assertRaises(ValueError, marshal.dumps, subtyp())
  230. # Issue #1792 introduced a change in how marshal increases the size of its
  231. # internal buffer; this test ensures that the new code is exercised.
  232. def test_large_marshal(self):
  233. size = int(1e6)
  234. testString = 'abc' * size
  235. marshal.dumps(testString)
  236. def test_invalid_longs(self):
  237. # Issue #7019: marshal.loads shouldn't produce unnormalized PyLongs
  238. invalid_string = 'l\x02\x00\x00\x00\x00\x00\x00\x00'
  239. self.assertRaises(ValueError, marshal.loads, invalid_string)
  240. LARGE_SIZE = 2**31
  241. character_size = 4 if sys.maxunicode > 0xFFFF else 2
  242. pointer_size = 8 if sys.maxsize > 0xFFFFFFFF else 4
  243. @unittest.skipIf(LARGE_SIZE > sys.maxsize, "test cannot run on 32-bit systems")
  244. class LargeValuesTestCase(unittest.TestCase):
  245. def check_unmarshallable(self, data):
  246. f = open(test_support.TESTFN, 'wb')
  247. self.addCleanup(test_support.unlink, test_support.TESTFN)
  248. with f:
  249. self.assertRaises(ValueError, marshal.dump, data, f)
  250. @test_support.precisionbigmemtest(size=LARGE_SIZE, memuse=1, dry_run=False)
  251. def test_string(self, size):
  252. self.check_unmarshallable('x' * size)
  253. @test_support.precisionbigmemtest(size=LARGE_SIZE,
  254. memuse=character_size + 2, dry_run=False)
  255. def test_unicode(self, size):
  256. self.check_unmarshallable(u'x' * size)
  257. @test_support.precisionbigmemtest(size=LARGE_SIZE,
  258. memuse=pointer_size, dry_run=False)
  259. def test_tuple(self, size):
  260. self.check_unmarshallable((None,) * size)
  261. @test_support.precisionbigmemtest(size=LARGE_SIZE,
  262. memuse=pointer_size, dry_run=False)
  263. def test_list(self, size):
  264. self.check_unmarshallable([None] * size)
  265. @test_support.precisionbigmemtest(size=LARGE_SIZE,
  266. memuse=pointer_size*12 + sys.getsizeof(LARGE_SIZE-1),
  267. dry_run=False)
  268. def test_set(self, size):
  269. self.check_unmarshallable(set(range(size)))
  270. @test_support.precisionbigmemtest(size=LARGE_SIZE,
  271. memuse=pointer_size*12 + sys.getsizeof(LARGE_SIZE-1),
  272. dry_run=False)
  273. def test_frozenset(self, size):
  274. self.check_unmarshallable(frozenset(range(size)))
  275. @test_support.precisionbigmemtest(size=LARGE_SIZE, memuse=1, dry_run=False)
  276. def test_bytearray(self, size):
  277. self.check_unmarshallable(bytearray(size))
  278. @test_support.cpython_only
  279. @unittest.skipUnless(_testcapi, 'requires _testcapi')
  280. class CAPI_TestCase(unittest.TestCase):
  281. def test_write_long_to_file(self):
  282. for v in range(marshal.version + 1):
  283. _testcapi.pymarshal_write_long_to_file(0x12345678, test_support.TESTFN, v)
  284. with open(test_support.TESTFN, 'rb') as f:
  285. data = f.read()
  286. test_support.unlink(test_support.TESTFN)
  287. self.assertEqual(data, b'\x78\x56\x34\x12')
  288. def test_write_object_to_file(self):
  289. obj = ('\u20ac', b'abc', 123, 45.6, 7+8j, 'long line '*1000)
  290. for v in range(marshal.version + 1):
  291. _testcapi.pymarshal_write_object_to_file(obj, test_support.TESTFN, v)
  292. with open(test_support.TESTFN, 'rb') as f:
  293. data = f.read()
  294. test_support.unlink(test_support.TESTFN)
  295. self.assertEqual(marshal.loads(data), obj)
  296. def test_read_short_from_file(self):
  297. with open(test_support.TESTFN, 'wb') as f:
  298. f.write(b'\x34\x12xxxx')
  299. r, p = _testcapi.pymarshal_read_short_from_file(test_support.TESTFN)
  300. test_support.unlink(test_support.TESTFN)
  301. self.assertEqual(r, 0x1234)
  302. self.assertEqual(p, 2)
  303. def test_read_long_from_file(self):
  304. with open(test_support.TESTFN, 'wb') as f:
  305. f.write(b'\x78\x56\x34\x12xxxx')
  306. r, p = _testcapi.pymarshal_read_long_from_file(test_support.TESTFN)
  307. test_support.unlink(test_support.TESTFN)
  308. self.assertEqual(r, 0x12345678)
  309. self.assertEqual(p, 4)
  310. def test_read_last_object_from_file(self):
  311. obj = ('\u20ac', b'abc', 123, 45.6, 7+8j)
  312. for v in range(marshal.version + 1):
  313. data = marshal.dumps(obj, v)
  314. with open(test_support.TESTFN, 'wb') as f:
  315. f.write(data + b'xxxx')
  316. r, p = _testcapi.pymarshal_read_last_object_from_file(test_support.TESTFN)
  317. test_support.unlink(test_support.TESTFN)
  318. self.assertEqual(r, obj)
  319. def test_read_object_from_file(self):
  320. obj = ('\u20ac', b'abc', 123, 45.6, 7+8j)
  321. for v in range(marshal.version + 1):
  322. data = marshal.dumps(obj, v)
  323. with open(test_support.TESTFN, 'wb') as f:
  324. f.write(data + b'xxxx')
  325. r, p = _testcapi.pymarshal_read_object_from_file(test_support.TESTFN)
  326. test_support.unlink(test_support.TESTFN)
  327. self.assertEqual(r, obj)
  328. self.assertEqual(p, len(data))
  329. def test_main():
  330. test_support.run_unittest(IntTestCase,
  331. FloatTestCase,
  332. StringTestCase,
  333. CodeTestCase,
  334. ContainerTestCase,
  335. ExceptionTestCase,
  336. BugsTestCase,
  337. LargeValuesTestCase,
  338. CAPI_TestCase,
  339. )
  340. if __name__ == "__main__":
  341. test_main()