/Lib/test/pickletester.py

http://unladen-swallow.googlecode.com/ · Python · 1370 lines · 1071 code · 175 blank · 124 comment · 94 complexity · ead9090d9a1e59a06636b3430235882e MD5 · raw file

  1. import unittest
  2. import pickle
  3. import cPickle
  4. import cStringIO
  5. import pickletools
  6. import copy_reg
  7. from test.test_support import TestFailed, have_unicode, TESTFN
  8. # Tests that try a number of pickle protocols should have a
  9. # for proto in protocols:
  10. # kind of outer loop.
  11. assert pickle.HIGHEST_PROTOCOL == cPickle.HIGHEST_PROTOCOL == 2
  12. protocols = range(pickle.HIGHEST_PROTOCOL + 1)
  13. # Copy of test.test_support.run_with_locale. This is needed to support Python
  14. # 2.4, which didn't include it.
  15. def run_with_locale(catstr, *locales):
  16. def decorator(func):
  17. def inner(*args, **kwds):
  18. try:
  19. import locale
  20. category = getattr(locale, catstr)
  21. orig_locale = locale.setlocale(category)
  22. except AttributeError:
  23. # if the test author gives us an invalid category string
  24. raise
  25. except:
  26. # cannot retrieve original locale, so do nothing
  27. locale = orig_locale = None
  28. else:
  29. for loc in locales:
  30. try:
  31. locale.setlocale(category, loc)
  32. break
  33. except:
  34. pass
  35. # now run the function, resetting the locale on exceptions
  36. try:
  37. return func(*args, **kwds)
  38. finally:
  39. if locale and orig_locale:
  40. locale.setlocale(category, orig_locale)
  41. inner.func_name = func.func_name
  42. inner.__doc__ = func.__doc__
  43. return inner
  44. return decorator
  45. # Return True if opcode code appears in the pickle, else False.
  46. def opcode_in_pickle(code, pickle):
  47. for op, dummy, dummy in pickletools.genops(pickle):
  48. if op.code == code:
  49. return True
  50. return False
  51. # Return the number of times opcode code appears in pickle.
  52. def count_opcode(code, pickle):
  53. n = 0
  54. for op, dummy, dummy in pickletools.genops(pickle):
  55. if op.code == code:
  56. n += 1
  57. return n
  58. # We can't very well test the extension registry without putting known stuff
  59. # in it, but we have to be careful to restore its original state. Code
  60. # should do this:
  61. #
  62. # e = ExtensionSaver(extension_code)
  63. # try:
  64. # fiddle w/ the extension registry's stuff for extension_code
  65. # finally:
  66. # e.restore()
  67. class ExtensionSaver:
  68. # Remember current registration for code (if any), and remove it (if
  69. # there is one).
  70. def __init__(self, code):
  71. self.code = code
  72. if code in copy_reg._inverted_registry:
  73. self.pair = copy_reg._inverted_registry[code]
  74. copy_reg.remove_extension(self.pair[0], self.pair[1], code)
  75. else:
  76. self.pair = None
  77. # Restore previous registration for code.
  78. def restore(self):
  79. code = self.code
  80. curpair = copy_reg._inverted_registry.get(code)
  81. if curpair is not None:
  82. copy_reg.remove_extension(curpair[0], curpair[1], code)
  83. pair = self.pair
  84. if pair is not None:
  85. copy_reg.add_extension(pair[0], pair[1], code)
  86. class C:
  87. def __cmp__(self, other):
  88. return cmp(self.__dict__, other.__dict__)
  89. import __main__
  90. __main__.C = C
  91. C.__module__ = "__main__"
  92. class myint(int):
  93. def __init__(self, x):
  94. self.str = str(x)
  95. class initarg(C):
  96. def __init__(self, a, b):
  97. self.a = a
  98. self.b = b
  99. def __getinitargs__(self):
  100. return self.a, self.b
  101. class metaclass(type):
  102. pass
  103. class use_metaclass(object):
  104. __metaclass__ = metaclass
  105. # DATA0 .. DATA2 are the pickles we expect under the various protocols, for
  106. # the object returned by create_data().
  107. # break into multiple strings to avoid confusing font-lock-mode
  108. DATA0 = """(lp1
  109. I0
  110. aL1L
  111. aF2
  112. ac__builtin__
  113. complex
  114. p2
  115. """ + \
  116. """(F3
  117. F0
  118. tRp3
  119. aI1
  120. aI-1
  121. aI255
  122. aI-255
  123. aI-256
  124. aI65535
  125. aI-65535
  126. aI-65536
  127. aI2147483647
  128. aI-2147483647
  129. aI-2147483648
  130. a""" + \
  131. """(S'abc'
  132. p4
  133. g4
  134. """ + \
  135. """(i__main__
  136. C
  137. p5
  138. """ + \
  139. """(dp6
  140. S'foo'
  141. p7
  142. I1
  143. sS'bar'
  144. p8
  145. I2
  146. sbg5
  147. tp9
  148. ag9
  149. aI5
  150. a.
  151. """
  152. # Disassembly of DATA0.
  153. DATA0_DIS = """\
  154. 0: ( MARK
  155. 1: l LIST (MARK at 0)
  156. 2: p PUT 1
  157. 5: I INT 0
  158. 8: a APPEND
  159. 9: L LONG 1L
  160. 13: a APPEND
  161. 14: F FLOAT 2.0
  162. 17: a APPEND
  163. 18: c GLOBAL '__builtin__ complex'
  164. 39: p PUT 2
  165. 42: ( MARK
  166. 43: F FLOAT 3.0
  167. 46: F FLOAT 0.0
  168. 49: t TUPLE (MARK at 42)
  169. 50: R REDUCE
  170. 51: p PUT 3
  171. 54: a APPEND
  172. 55: I INT 1
  173. 58: a APPEND
  174. 59: I INT -1
  175. 63: a APPEND
  176. 64: I INT 255
  177. 69: a APPEND
  178. 70: I INT -255
  179. 76: a APPEND
  180. 77: I INT -256
  181. 83: a APPEND
  182. 84: I INT 65535
  183. 91: a APPEND
  184. 92: I INT -65535
  185. 100: a APPEND
  186. 101: I INT -65536
  187. 109: a APPEND
  188. 110: I INT 2147483647
  189. 122: a APPEND
  190. 123: I INT -2147483647
  191. 136: a APPEND
  192. 137: I INT -2147483648
  193. 150: a APPEND
  194. 151: ( MARK
  195. 152: S STRING 'abc'
  196. 159: p PUT 4
  197. 162: g GET 4
  198. 165: ( MARK
  199. 166: i INST '__main__ C' (MARK at 165)
  200. 178: p PUT 5
  201. 181: ( MARK
  202. 182: d DICT (MARK at 181)
  203. 183: p PUT 6
  204. 186: S STRING 'foo'
  205. 193: p PUT 7
  206. 196: I INT 1
  207. 199: s SETITEM
  208. 200: S STRING 'bar'
  209. 207: p PUT 8
  210. 210: I INT 2
  211. 213: s SETITEM
  212. 214: b BUILD
  213. 215: g GET 5
  214. 218: t TUPLE (MARK at 151)
  215. 219: p PUT 9
  216. 222: a APPEND
  217. 223: g GET 9
  218. 226: a APPEND
  219. 227: I INT 5
  220. 230: a APPEND
  221. 231: . STOP
  222. highest protocol among opcodes = 0
  223. """
  224. DATA1 = (']q\x01(K\x00L1L\nG@\x00\x00\x00\x00\x00\x00\x00'
  225. 'c__builtin__\ncomplex\nq\x02(G@\x08\x00\x00\x00\x00\x00'
  226. '\x00G\x00\x00\x00\x00\x00\x00\x00\x00tRq\x03K\x01J\xff\xff'
  227. '\xff\xffK\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xff'
  228. 'J\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00'
  229. '\x00\x80J\x00\x00\x00\x80(U\x03abcq\x04h\x04(c__main__\n'
  230. 'C\nq\x05oq\x06}q\x07(U\x03fooq\x08K\x01U\x03barq\tK\x02ubh'
  231. '\x06tq\nh\nK\x05e.'
  232. )
  233. # Disassembly of DATA1.
  234. DATA1_DIS = """\
  235. 0: ] EMPTY_LIST
  236. 1: q BINPUT 1
  237. 3: ( MARK
  238. 4: K BININT1 0
  239. 6: L LONG 1L
  240. 10: G BINFLOAT 2.0
  241. 19: c GLOBAL '__builtin__ complex'
  242. 40: q BINPUT 2
  243. 42: ( MARK
  244. 43: G BINFLOAT 3.0
  245. 52: G BINFLOAT 0.0
  246. 61: t TUPLE (MARK at 42)
  247. 62: R REDUCE
  248. 63: q BINPUT 3
  249. 65: K BININT1 1
  250. 67: J BININT -1
  251. 72: K BININT1 255
  252. 74: J BININT -255
  253. 79: J BININT -256
  254. 84: M BININT2 65535
  255. 87: J BININT -65535
  256. 92: J BININT -65536
  257. 97: J BININT 2147483647
  258. 102: J BININT -2147483647
  259. 107: J BININT -2147483648
  260. 112: ( MARK
  261. 113: U SHORT_BINSTRING 'abc'
  262. 118: q BINPUT 4
  263. 120: h BINGET 4
  264. 122: ( MARK
  265. 123: c GLOBAL '__main__ C'
  266. 135: q BINPUT 5
  267. 137: o OBJ (MARK at 122)
  268. 138: q BINPUT 6
  269. 140: } EMPTY_DICT
  270. 141: q BINPUT 7
  271. 143: ( MARK
  272. 144: U SHORT_BINSTRING 'foo'
  273. 149: q BINPUT 8
  274. 151: K BININT1 1
  275. 153: U SHORT_BINSTRING 'bar'
  276. 158: q BINPUT 9
  277. 160: K BININT1 2
  278. 162: u SETITEMS (MARK at 143)
  279. 163: b BUILD
  280. 164: h BINGET 6
  281. 166: t TUPLE (MARK at 112)
  282. 167: q BINPUT 10
  283. 169: h BINGET 10
  284. 171: K BININT1 5
  285. 173: e APPENDS (MARK at 3)
  286. 174: . STOP
  287. highest protocol among opcodes = 1
  288. """
  289. DATA2 = ('\x80\x02]q\x01(K\x00\x8a\x01\x01G@\x00\x00\x00\x00\x00\x00\x00'
  290. 'c__builtin__\ncomplex\nq\x02G@\x08\x00\x00\x00\x00\x00\x00G\x00'
  291. '\x00\x00\x00\x00\x00\x00\x00\x86Rq\x03K\x01J\xff\xff\xff\xffK'
  292. '\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xff'
  293. 'J\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00'
  294. '\x80(U\x03abcq\x04h\x04(c__main__\nC\nq\x05oq\x06}q\x07(U\x03foo'
  295. 'q\x08K\x01U\x03barq\tK\x02ubh\x06tq\nh\nK\x05e.')
  296. # Disassembly of DATA2.
  297. DATA2_DIS = """\
  298. 0: \x80 PROTO 2
  299. 2: ] EMPTY_LIST
  300. 3: q BINPUT 1
  301. 5: ( MARK
  302. 6: K BININT1 0
  303. 8: \x8a LONG1 1L
  304. 11: G BINFLOAT 2.0
  305. 20: c GLOBAL '__builtin__ complex'
  306. 41: q BINPUT 2
  307. 43: G BINFLOAT 3.0
  308. 52: G BINFLOAT 0.0
  309. 61: \x86 TUPLE2
  310. 62: R REDUCE
  311. 63: q BINPUT 3
  312. 65: K BININT1 1
  313. 67: J BININT -1
  314. 72: K BININT1 255
  315. 74: J BININT -255
  316. 79: J BININT -256
  317. 84: M BININT2 65535
  318. 87: J BININT -65535
  319. 92: J BININT -65536
  320. 97: J BININT 2147483647
  321. 102: J BININT -2147483647
  322. 107: J BININT -2147483648
  323. 112: ( MARK
  324. 113: U SHORT_BINSTRING 'abc'
  325. 118: q BINPUT 4
  326. 120: h BINGET 4
  327. 122: ( MARK
  328. 123: c GLOBAL '__main__ C'
  329. 135: q BINPUT 5
  330. 137: o OBJ (MARK at 122)
  331. 138: q BINPUT 6
  332. 140: } EMPTY_DICT
  333. 141: q BINPUT 7
  334. 143: ( MARK
  335. 144: U SHORT_BINSTRING 'foo'
  336. 149: q BINPUT 8
  337. 151: K BININT1 1
  338. 153: U SHORT_BINSTRING 'bar'
  339. 158: q BINPUT 9
  340. 160: K BININT1 2
  341. 162: u SETITEMS (MARK at 143)
  342. 163: b BUILD
  343. 164: h BINGET 6
  344. 166: t TUPLE (MARK at 112)
  345. 167: q BINPUT 10
  346. 169: h BINGET 10
  347. 171: K BININT1 5
  348. 173: e APPENDS (MARK at 5)
  349. 174: . STOP
  350. highest protocol among opcodes = 2
  351. """
  352. def create_data():
  353. c = C()
  354. c.foo = 1
  355. c.bar = 2
  356. x = [0, 1L, 2.0, 3.0+0j]
  357. # Append some integer test cases at cPickle.c's internal size
  358. # cutoffs.
  359. uint1max = 0xff
  360. uint2max = 0xffff
  361. int4max = 0x7fffffff
  362. x.extend([1, -1,
  363. uint1max, -uint1max, -uint1max-1,
  364. uint2max, -uint2max, -uint2max-1,
  365. int4max, -int4max, -int4max-1])
  366. y = ('abc', 'abc', c, c)
  367. x.append(y)
  368. x.append(y)
  369. x.append(5)
  370. return x
  371. class AbstractPickleTests(unittest.TestCase):
  372. # Subclass must define self.dumps, self.loads, self.error.
  373. _testdata = create_data()
  374. def setUp(self):
  375. pass
  376. def dump(self, arg, buf, proto=0):
  377. data = self.dumps(arg, proto)
  378. buf.write(data)
  379. def test_misc(self):
  380. # test various datatypes not tested by testdata
  381. for proto in protocols:
  382. x = myint(4)
  383. s = self.dumps(x, proto)
  384. y = self.loads(s)
  385. self.assertEqual(x, y)
  386. x = (1, ())
  387. s = self.dumps(x, proto)
  388. y = self.loads(s)
  389. self.assertEqual(x, y)
  390. x = initarg(1, x)
  391. s = self.dumps(x, proto)
  392. y = self.loads(s)
  393. self.assertEqual(x, y)
  394. # XXX test __reduce__ protocol?
  395. def test_roundtrip_equality(self):
  396. expected = self._testdata
  397. for proto in protocols:
  398. s = self.dumps(expected, proto)
  399. got = self.loads(s)
  400. self.assertEqual(expected, got)
  401. def test_load_from_canned_string(self):
  402. expected = self._testdata
  403. for canned in DATA0, DATA1, DATA2:
  404. got = self.loads(canned)
  405. self.assertEqual(expected, got)
  406. # There are gratuitous differences between pickles produced by
  407. # pickle and cPickle, largely because cPickle starts PUT indices at
  408. # 1 and pickle starts them at 0. See XXX comment in cPickle's put2() --
  409. # there's a comment with an exclamation point there whose meaning
  410. # is a mystery. cPickle also suppresses PUT for objects with a refcount
  411. # of 1.
  412. def dont_test_disassembly(self):
  413. from pickletools import dis
  414. for proto, expected in (0, DATA0_DIS), (1, DATA1_DIS):
  415. s = self.dumps(self._testdata, proto)
  416. filelike = cStringIO.StringIO()
  417. dis(s, out=filelike)
  418. got = filelike.getvalue()
  419. self.assertEqual(expected, got)
  420. def test_recursive_list(self):
  421. l = []
  422. l.append(l)
  423. for proto in protocols:
  424. s = self.dumps(l, proto)
  425. x = self.loads(s)
  426. self.assertEqual(len(x), 1)
  427. self.assert_(x is x[0])
  428. def test_recursive_tuple(self):
  429. t = ([],)
  430. t[0].append(t)
  431. for proto in protocols:
  432. s = self.dumps(t, proto)
  433. x = self.loads(s)
  434. self.assertEqual(len(x), 1)
  435. self.assertEqual(len(x[0]), 1)
  436. self.assert_(x is x[0][0])
  437. def test_recursive_dict(self):
  438. d = {}
  439. d[1] = d
  440. for proto in protocols:
  441. s = self.dumps(d, proto)
  442. x = self.loads(s)
  443. self.assertEqual(x.keys(), [1])
  444. self.assert_(x[1] is x)
  445. def test_recursive_inst(self):
  446. i = C()
  447. i.attr = i
  448. for proto in protocols:
  449. s = self.dumps(i, 2)
  450. x = self.loads(s)
  451. self.assertEqual(dir(x), dir(i))
  452. self.assert_(x.attr is x)
  453. def test_recursive_multi(self):
  454. l = []
  455. d = {1:l}
  456. i = C()
  457. i.attr = d
  458. l.append(i)
  459. for proto in protocols:
  460. s = self.dumps(l, proto)
  461. x = self.loads(s)
  462. self.assertEqual(len(x), 1)
  463. self.assertEqual(dir(x[0]), dir(i))
  464. self.assertEqual(x[0].attr.keys(), [1])
  465. self.assert_(x[0].attr[1] is x)
  466. def test_garyp(self):
  467. self.assertRaises(self.error, self.loads, 'garyp')
  468. def test_insecure_strings(self):
  469. insecure = ["abc", "2 + 2", # not quoted
  470. #"'abc' + 'def'", # not a single quoted string
  471. "'abc", # quote is not closed
  472. "'abc\"", # open quote and close quote don't match
  473. "'abc' ?", # junk after close quote
  474. "'\\'", # trailing backslash
  475. # some tests of the quoting rules
  476. #"'abc\"\''",
  477. #"'\\\\a\'\'\'\\\'\\\\\''",
  478. ]
  479. for s in insecure:
  480. buf = "S" + s + "\012p0\012."
  481. self.assertRaises(ValueError, self.loads, buf)
  482. if have_unicode:
  483. def test_unicode(self):
  484. endcases = [u'', u'<\\u>', u'<\\\u1234>', u'<\n>',
  485. u'<\\>', u'<\\\U00012345>']
  486. for proto in protocols:
  487. for u in endcases:
  488. p = self.dumps(u, proto)
  489. u2 = self.loads(p)
  490. self.assertEqual(u2, u)
  491. def test_unicode_high_plane(self):
  492. t = u'\U00012345'
  493. for proto in protocols:
  494. p = self.dumps(t, proto)
  495. t2 = self.loads(p)
  496. self.assertEqual(t2, t)
  497. def test_ints(self):
  498. import sys
  499. for proto in protocols:
  500. n = sys.maxint
  501. while n:
  502. for expected in (-n, n):
  503. s = self.dumps(expected, proto)
  504. n2 = self.loads(s)
  505. self.assertEqual(expected, n2)
  506. n = n >> 1
  507. def test_maxint64(self):
  508. maxint64 = (1L << 63) - 1
  509. data = 'I' + str(maxint64) + '\n.'
  510. got = self.loads(data)
  511. self.assertEqual(got, maxint64)
  512. # Try too with a bogus literal.
  513. data = 'I' + str(maxint64) + 'JUNK\n.'
  514. self.assertRaises(ValueError, self.loads, data)
  515. def test_long(self):
  516. for proto in protocols:
  517. # 256 bytes is where LONG4 begins.
  518. for nbits in 1, 8, 8*254, 8*255, 8*256, 8*257:
  519. nbase = 1L << nbits
  520. for npos in nbase-1, nbase, nbase+1:
  521. for n in npos, -npos:
  522. pickle = self.dumps(n, proto)
  523. got = self.loads(pickle)
  524. self.assertEqual(n, got)
  525. # Try a monster. This is quadratic-time in protos 0 & 1, so don't
  526. # bother with those.
  527. nbase = long("deadbeeffeedface", 16)
  528. nbase += nbase << 1000000
  529. for n in nbase, -nbase:
  530. p = self.dumps(n, 2)
  531. got = self.loads(p)
  532. self.assertEqual(n, got)
  533. def test_float(self):
  534. test_values = [0.0, 4.94e-324, 1e-310, 7e-308, 6.626e-34, 0.1, 0.5,
  535. 3.14, 263.44582062374053, 6.022e23, 1e30]
  536. test_values = test_values + [-x for x in test_values]
  537. for proto in protocols:
  538. for value in test_values:
  539. pickle = self.dumps(value, proto)
  540. got = self.loads(pickle)
  541. self.assertEqual(value, got)
  542. @run_with_locale('LC_ALL', 'de_DE', 'fr_FR')
  543. def test_float_format(self):
  544. # make sure that floats are formatted locale independent
  545. self.assertEqual(self.dumps(1.2)[0:3], 'F1.')
  546. def test_reduce(self):
  547. pass
  548. def test_getinitargs(self):
  549. pass
  550. def test_metaclass(self):
  551. a = use_metaclass()
  552. for proto in protocols:
  553. s = self.dumps(a, proto)
  554. b = self.loads(s)
  555. self.assertEqual(a.__class__, b.__class__)
  556. def test_structseq(self):
  557. import time
  558. import os
  559. t = time.localtime()
  560. for proto in protocols:
  561. s = self.dumps(t, proto)
  562. u = self.loads(s)
  563. self.assertEqual(t, u)
  564. if hasattr(os, "stat"):
  565. t = os.stat(os.curdir)
  566. s = self.dumps(t, proto)
  567. u = self.loads(s)
  568. self.assertEqual(t, u)
  569. if hasattr(os, "statvfs"):
  570. t = os.statvfs(os.curdir)
  571. s = self.dumps(t, proto)
  572. u = self.loads(s)
  573. self.assertEqual(t, u)
  574. # Tests for protocol 2
  575. def test_proto(self):
  576. build_none = pickle.NONE + pickle.STOP
  577. for proto in protocols:
  578. expected = build_none
  579. if proto >= 2:
  580. expected = pickle.PROTO + chr(proto) + expected
  581. p = self.dumps(None, proto)
  582. self.assertEqual(p, expected)
  583. oob = protocols[-1] + 1 # a future protocol
  584. badpickle = pickle.PROTO + chr(oob) + build_none
  585. try:
  586. self.loads(badpickle)
  587. except ValueError, detail:
  588. self.failUnless(str(detail).startswith(
  589. "unsupported pickle protocol"))
  590. else:
  591. self.fail("expected bad protocol number to raise ValueError")
  592. def test_long1(self):
  593. x = 12345678910111213141516178920L
  594. for proto in protocols:
  595. s = self.dumps(x, proto)
  596. y = self.loads(s)
  597. self.assertEqual(x, y)
  598. self.assertEqual(opcode_in_pickle(pickle.LONG1, s), proto >= 2)
  599. def test_long4(self):
  600. x = 12345678910111213141516178920L << (256*8)
  601. for proto in protocols:
  602. s = self.dumps(x, proto)
  603. y = self.loads(s)
  604. self.assertEqual(x, y)
  605. self.assertEqual(opcode_in_pickle(pickle.LONG4, s), proto >= 2)
  606. def test_short_tuples(self):
  607. # Map (proto, len(tuple)) to expected opcode.
  608. expected_opcode = {(0, 0): pickle.TUPLE,
  609. (0, 1): pickle.TUPLE,
  610. (0, 2): pickle.TUPLE,
  611. (0, 3): pickle.TUPLE,
  612. (0, 4): pickle.TUPLE,
  613. (1, 0): pickle.EMPTY_TUPLE,
  614. (1, 1): pickle.TUPLE,
  615. (1, 2): pickle.TUPLE,
  616. (1, 3): pickle.TUPLE,
  617. (1, 4): pickle.TUPLE,
  618. (2, 0): pickle.EMPTY_TUPLE,
  619. (2, 1): pickle.TUPLE1,
  620. (2, 2): pickle.TUPLE2,
  621. (2, 3): pickle.TUPLE3,
  622. (2, 4): pickle.TUPLE,
  623. }
  624. a = ()
  625. b = (1,)
  626. c = (1, 2)
  627. d = (1, 2, 3)
  628. e = (1, 2, 3, 4)
  629. for proto in protocols:
  630. for x in a, b, c, d, e:
  631. s = self.dumps(x, proto)
  632. y = self.loads(s)
  633. self.assertEqual(x, y, (proto, x, s, y))
  634. expected = expected_opcode[proto, len(x)]
  635. self.assertEqual(opcode_in_pickle(expected, s), True)
  636. def test_singletons(self):
  637. # Map (proto, singleton) to expected opcode.
  638. expected_opcode = {(0, None): pickle.NONE,
  639. (1, None): pickle.NONE,
  640. (2, None): pickle.NONE,
  641. (0, True): pickle.INT,
  642. (1, True): pickle.INT,
  643. (2, True): pickle.NEWTRUE,
  644. (0, False): pickle.INT,
  645. (1, False): pickle.INT,
  646. (2, False): pickle.NEWFALSE,
  647. }
  648. for proto in protocols:
  649. for x in None, False, True:
  650. s = self.dumps(x, proto)
  651. y = self.loads(s)
  652. self.assert_(x is y, (proto, x, s, y))
  653. expected = expected_opcode[proto, x]
  654. self.assertEqual(opcode_in_pickle(expected, s), True)
  655. def test_newobj_tuple(self):
  656. x = MyTuple([1, 2, 3])
  657. x.foo = 42
  658. x.bar = "hello"
  659. for proto in protocols:
  660. s = self.dumps(x, proto)
  661. y = self.loads(s)
  662. self.assertEqual(tuple(x), tuple(y))
  663. self.assertEqual(x.__dict__, y.__dict__)
  664. def test_newobj_list(self):
  665. x = MyList([1, 2, 3])
  666. x.foo = 42
  667. x.bar = "hello"
  668. for proto in protocols:
  669. s = self.dumps(x, proto)
  670. y = self.loads(s)
  671. self.assertEqual(list(x), list(y))
  672. self.assertEqual(x.__dict__, y.__dict__)
  673. def test_newobj_generic(self):
  674. for proto in protocols:
  675. for C in myclasses:
  676. B = C.__base__
  677. x = C(C.sample)
  678. x.foo = 42
  679. s = self.dumps(x, proto)
  680. y = self.loads(s)
  681. detail = (proto, C, B, x, y, type(y))
  682. self.assertEqual(B(x), B(y), detail)
  683. self.assertEqual(x.__dict__, y.__dict__, detail)
  684. # Register a type with copy_reg, with extension code extcode. Pickle
  685. # an object of that type. Check that the resulting pickle uses opcode
  686. # (EXT[124]) under proto 2, and not in proto 1.
  687. def produce_global_ext(self, extcode, opcode):
  688. e = ExtensionSaver(extcode)
  689. try:
  690. copy_reg.add_extension(__name__, "MyList", extcode)
  691. x = MyList([1, 2, 3])
  692. x.foo = 42
  693. x.bar = "hello"
  694. # Dump using protocol 1 for comparison.
  695. s1 = self.dumps(x, 1)
  696. self.assert_(__name__ in s1)
  697. self.assert_("MyList" in s1)
  698. self.assertEqual(opcode_in_pickle(opcode, s1), False)
  699. y = self.loads(s1)
  700. self.assertEqual(list(x), list(y))
  701. self.assertEqual(x.__dict__, y.__dict__)
  702. # Dump using protocol 2 for test.
  703. s2 = self.dumps(x, 2)
  704. self.assert_(__name__ not in s2)
  705. self.assert_("MyList" not in s2)
  706. self.assertEqual(opcode_in_pickle(opcode, s2), True)
  707. y = self.loads(s2)
  708. self.assertEqual(list(x), list(y))
  709. self.assertEqual(x.__dict__, y.__dict__)
  710. finally:
  711. e.restore()
  712. def test_global_ext1(self):
  713. self.produce_global_ext(0x00000001, pickle.EXT1) # smallest EXT1 code
  714. self.produce_global_ext(0x000000ff, pickle.EXT1) # largest EXT1 code
  715. def test_global_ext2(self):
  716. self.produce_global_ext(0x00000100, pickle.EXT2) # smallest EXT2 code
  717. self.produce_global_ext(0x0000ffff, pickle.EXT2) # largest EXT2 code
  718. self.produce_global_ext(0x0000abcd, pickle.EXT2) # check endianness
  719. def test_global_ext4(self):
  720. self.produce_global_ext(0x00010000, pickle.EXT4) # smallest EXT4 code
  721. self.produce_global_ext(0x7fffffff, pickle.EXT4) # largest EXT4 code
  722. self.produce_global_ext(0x12abcdef, pickle.EXT4) # check endianness
  723. def test_list_chunking(self):
  724. n = 10 # too small to chunk
  725. x = range(n)
  726. for proto in protocols:
  727. s = self.dumps(x, proto)
  728. y = self.loads(s)
  729. self.assertEqual(x, y)
  730. num_appends = count_opcode(pickle.APPENDS, s)
  731. self.assertEqual(num_appends, proto > 0)
  732. n = 2500 # expect at least two chunks when proto > 0
  733. x = range(n)
  734. for proto in protocols:
  735. s = self.dumps(x, proto)
  736. y = self.loads(s)
  737. self.assertEqual(x, y)
  738. num_appends = count_opcode(pickle.APPENDS, s)
  739. if proto == 0:
  740. self.assertEqual(num_appends, 0)
  741. else:
  742. self.failUnless(num_appends >= 2)
  743. def test_dict_chunking(self):
  744. n = 10 # too small to chunk
  745. x = dict.fromkeys(range(n))
  746. for proto in protocols:
  747. s = self.dumps(x, proto)
  748. y = self.loads(s)
  749. self.assertEqual(x, y)
  750. num_setitems = count_opcode(pickle.SETITEMS, s)
  751. self.assertEqual(num_setitems, proto > 0)
  752. n = 2500 # expect at least two chunks when proto > 0
  753. x = dict.fromkeys(range(n))
  754. for proto in protocols:
  755. s = self.dumps(x, proto)
  756. y = self.loads(s)
  757. self.assertEqual(x, y)
  758. num_setitems = count_opcode(pickle.SETITEMS, s)
  759. if proto == 0:
  760. self.assertEqual(num_setitems, 0)
  761. else:
  762. self.failUnless(num_setitems >= 2)
  763. def test_load_empty_string(self):
  764. self.assertRaises(EOFError, self.loads, "")
  765. def test_simple_newobj(self):
  766. x = object.__new__(SimpleNewObj) # avoid __init__
  767. x.abc = 666
  768. for proto in protocols:
  769. s = self.dumps(x, proto)
  770. self.assertEqual(opcode_in_pickle(pickle.NEWOBJ, s), proto >= 2)
  771. y = self.loads(s) # will raise TypeError if __init__ called
  772. self.assertEqual(y.abc, 666)
  773. self.assertEqual(x.__dict__, y.__dict__)
  774. def test_newobj_list_slots(self):
  775. x = SlotList([1, 2, 3])
  776. x.foo = 42
  777. x.bar = "hello"
  778. s = self.dumps(x, 2)
  779. y = self.loads(s)
  780. self.assertEqual(list(x), list(y))
  781. self.assertEqual(x.__dict__, y.__dict__)
  782. self.assertEqual(x.foo, y.foo)
  783. self.assertEqual(x.bar, y.bar)
  784. def test_reduce_overrides_default_reduce_ex(self):
  785. for proto in 0, 1, 2:
  786. x = REX_one()
  787. self.assertEqual(x._reduce_called, 0)
  788. s = self.dumps(x, proto)
  789. self.assertEqual(x._reduce_called, 1)
  790. y = self.loads(s)
  791. self.assertEqual(y._reduce_called, 0)
  792. def test_reduce_ex_called(self):
  793. for proto in 0, 1, 2:
  794. x = REX_two()
  795. self.assertEqual(x._proto, None)
  796. s = self.dumps(x, proto)
  797. self.assertEqual(x._proto, proto)
  798. y = self.loads(s)
  799. self.assertEqual(y._proto, None)
  800. def test_reduce_ex_overrides_reduce(self):
  801. for proto in 0, 1, 2:
  802. x = REX_three()
  803. self.assertEqual(x._proto, None)
  804. s = self.dumps(x, proto)
  805. self.assertEqual(x._proto, proto)
  806. y = self.loads(s)
  807. self.assertEqual(y._proto, None)
  808. def test_reduce_ex_calls_base(self):
  809. for proto in 0, 1, 2:
  810. x = REX_four()
  811. self.assertEqual(x._proto, None)
  812. s = self.dumps(x, proto)
  813. self.assertEqual(x._proto, proto)
  814. y = self.loads(s)
  815. self.assertEqual(y._proto, proto)
  816. def test_reduce_calls_base(self):
  817. for proto in 0, 1, 2:
  818. x = REX_five()
  819. self.assertEqual(x._reduce_called, 0)
  820. s = self.dumps(x, proto)
  821. self.assertEqual(x._reduce_called, 1)
  822. y = self.loads(s)
  823. self.assertEqual(y._reduce_called, 1)
  824. def test_reduce_bad_iterator(self):
  825. # Issue4176: crash when 4th and 5th items of __reduce__()
  826. # are not iterators
  827. class C(object):
  828. def __reduce__(self):
  829. # 4th item is not an iterator
  830. return list, (), None, [], None
  831. class D(object):
  832. def __reduce__(self):
  833. # 5th item is not an iterator
  834. return dict, (), None, None, []
  835. # Protocol 0 is less strict and also accept iterables.
  836. for proto in 0, 1, 2:
  837. try:
  838. self.dumps(C(), proto)
  839. except (AttributeError, pickle.PickleError, cPickle.PickleError):
  840. pass
  841. try:
  842. self.dumps(D(), proto)
  843. except (AttributeError, pickle.PickleError, cPickle.PickleError):
  844. pass
  845. def test_many_puts_and_gets(self):
  846. # Test that internal data structures correctly deal with lots of
  847. # puts/gets. There were once bugs in cPickle related to this.
  848. keys = ("aaa" + str(i) for i in xrange(100))
  849. large_dict = dict((k, [4, 5, 6]) for k in keys)
  850. obj = [dict(large_dict), dict(large_dict), dict(large_dict)]
  851. for proto in [0, 1, 2]:
  852. dumped = self.dumps(obj, proto)
  853. loaded = self.loads(dumped)
  854. self.assertEqual(loaded, obj,
  855. "Failed protocol %d: %r != %r"
  856. % (proto, obj, loaded))
  857. def test_unpickle_multiple_objs_from_same_file(self):
  858. data1 = ["abcdefg", "abcdefg", 44]
  859. data2 = range(10)
  860. f = cStringIO.StringIO()
  861. self.dump(data1, f)
  862. self.dump(data2, f)
  863. f.seek(0)
  864. self.assertEqual(self.load(f), data1)
  865. self.assertEqual(self.load(f), data2)
  866. # Test classes for reduce_ex
  867. class REX_one(object):
  868. _reduce_called = 0
  869. def __reduce__(self):
  870. self._reduce_called = 1
  871. return REX_one, ()
  872. # No __reduce_ex__ here, but inheriting it from object
  873. class REX_two(object):
  874. _proto = None
  875. def __reduce_ex__(self, proto):
  876. self._proto = proto
  877. return REX_two, ()
  878. # No __reduce__ here, but inheriting it from object
  879. class REX_three(object):
  880. _proto = None
  881. def __reduce_ex__(self, proto):
  882. self._proto = proto
  883. return REX_two, ()
  884. def __reduce__(self):
  885. raise TestFailed, "This __reduce__ shouldn't be called"
  886. class REX_four(object):
  887. _proto = None
  888. def __reduce_ex__(self, proto):
  889. self._proto = proto
  890. return object.__reduce_ex__(self, proto)
  891. # Calling base class method should succeed
  892. class REX_five(object):
  893. _reduce_called = 0
  894. def __reduce__(self):
  895. self._reduce_called = 1
  896. return object.__reduce__(self)
  897. # This one used to fail with infinite recursion
  898. # Test classes for newobj
  899. class MyInt(int):
  900. sample = 1
  901. class MyLong(long):
  902. sample = 1L
  903. class MyFloat(float):
  904. sample = 1.0
  905. class MyComplex(complex):
  906. sample = 1.0 + 0.0j
  907. class MyStr(str):
  908. sample = "hello"
  909. class MyUnicode(unicode):
  910. sample = u"hello \u1234"
  911. class MyTuple(tuple):
  912. sample = (1, 2, 3)
  913. class MyList(list):
  914. sample = [1, 2, 3]
  915. class MyDict(dict):
  916. sample = {"a": 1, "b": 2}
  917. myclasses = [MyInt, MyLong, MyFloat,
  918. MyComplex,
  919. MyStr, MyUnicode,
  920. MyTuple, MyList, MyDict]
  921. class SlotList(MyList):
  922. __slots__ = ["foo"]
  923. class SimpleNewObj(object):
  924. def __init__(self, a, b, c):
  925. # raise an error, to make sure this isn't called
  926. raise TypeError("SimpleNewObj.__init__() didn't expect to get called")
  927. class AbstractPickleModuleTests(unittest.TestCase):
  928. def test_dump_closed_file(self):
  929. import os
  930. f = open(TESTFN, "w")
  931. try:
  932. f.close()
  933. self.assertRaises(ValueError, self.module.dump, 123, f)
  934. finally:
  935. os.remove(TESTFN)
  936. def test_load_closed_file(self):
  937. import os
  938. f = open(TESTFN, "w")
  939. try:
  940. f.close()
  941. self.assertRaises(ValueError, self.module.dump, 123, f)
  942. finally:
  943. os.remove(TESTFN)
  944. def test_load_from_and_dump_to_file(self):
  945. stream = cStringIO.StringIO()
  946. data = [123, {}, 124]
  947. self.module.dump(data, stream)
  948. stream.seek(0)
  949. unpickled = self.module.load(stream)
  950. self.assertEqual(unpickled, data)
  951. def test_highest_protocol(self):
  952. # Of course this needs to be changed when HIGHEST_PROTOCOL changes.
  953. self.assertEqual(self.module.HIGHEST_PROTOCOL, 2)
  954. def test_callapi(self):
  955. f = cStringIO.StringIO()
  956. # With and without keyword arguments
  957. self.module.dump(123, f, -1)
  958. self.module.dump(123, file=f, protocol=-1)
  959. self.module.dumps(123, -1)
  960. self.module.dumps(123, protocol=-1)
  961. self.module.Pickler(f, -1)
  962. self.module.Pickler(f, protocol=-1)
  963. def test_incomplete_input(self):
  964. s = cStringIO.StringIO("X''.")
  965. self.assertRaises(EOFError, self.module.load, s)
  966. class AbstractPersistentPicklerTests(unittest.TestCase):
  967. # This class defines persistent_id() and persistent_load()
  968. # functions that should be used by the pickler. All even integers
  969. # are pickled using persistent ids.
  970. def persistent_id(self, object):
  971. if isinstance(object, int) and object % 2 == 0:
  972. self.id_count += 1
  973. return str(object)
  974. else:
  975. return None
  976. def persistent_load(self, oid):
  977. self.load_count += 1
  978. object = int(oid)
  979. assert object % 2 == 0
  980. return object
  981. def test_persistence(self):
  982. self.id_count = 0
  983. self.load_count = 0
  984. L = range(10)
  985. self.assertEqual(self.loads(self.dumps(L)), L)
  986. self.assertEqual(self.id_count, 5)
  987. self.assertEqual(self.load_count, 5)
  988. def test_bin_persistence(self):
  989. self.id_count = 0
  990. self.load_count = 0
  991. L = range(10)
  992. self.assertEqual(self.loads(self.dumps(L, 1)), L)
  993. self.assertEqual(self.id_count, 5)
  994. self.assertEqual(self.load_count, 5)
  995. class AbstractPicklerUnpicklerObjectTests(unittest.TestCase):
  996. pickler_class = None
  997. unpickler_class = None
  998. def setUp(self):
  999. assert self.pickler_class
  1000. assert self.unpickler_class
  1001. def dumps(self, obj, proto=0):
  1002. buf = cStringIO.StringIO()
  1003. pickler = self.pickler_class(buf, proto)
  1004. pickler.dump(obj)
  1005. return buf.getvalue()
  1006. def loads(self, input):
  1007. unpickler = self.unpickler_class(cStringIO.StringIO(input))
  1008. return unpickler.load()
  1009. def test_clear_pickler_memo(self):
  1010. # To test whether clear_memo() has any effect, we pickle an object,
  1011. # then pickle it again without clearing the memo; the two serialized
  1012. # forms should be different. If we clear_memo() and then pickle the
  1013. # object again, the third serialized form should be identical to the
  1014. # first one we obtained.
  1015. data = ["abcdefg", "abcdefg", 44]
  1016. f = cStringIO.StringIO()
  1017. pickler = self.pickler_class(f)
  1018. pickler.dump(data)
  1019. first_pickled = f.getvalue()
  1020. # Reset StringIO object.
  1021. f.seek(0)
  1022. f.truncate()
  1023. pickler.dump(data)
  1024. second_pickled = f.getvalue()
  1025. # Reset the Pickler and StringIO objects.
  1026. pickler.clear_memo()
  1027. f.seek(0)
  1028. f.truncate()
  1029. pickler.dump(data)
  1030. third_pickled = f.getvalue()
  1031. self.assertNotEqual(first_pickled, second_pickled)
  1032. self.assertEqual(first_pickled, third_pickled)
  1033. def test_priming_pickler_memo(self):
  1034. # Verify that we can set the Pickler's memo attribute.
  1035. data = ["abcdefg", "abcdefg", 44]
  1036. f = cStringIO.StringIO()
  1037. pickler = self.pickler_class(f)
  1038. pickler.dump(data)
  1039. first_pickled = f.getvalue()
  1040. f = cStringIO.StringIO()
  1041. primed = self.pickler_class(f)
  1042. primed.memo = pickler.memo
  1043. primed.dump(data)
  1044. primed_pickled = f.getvalue()
  1045. self.assertNotEqual(first_pickled, primed_pickled)
  1046. def test_priming_unpickler_memo(self):
  1047. # Verify that we can set the Unpickler's memo attribute.
  1048. data = ["abcdefg", "abcdefg", 44]
  1049. f = cStringIO.StringIO()
  1050. pickler = self.pickler_class(f)
  1051. pickler.dump(data)
  1052. first_pickled = f.getvalue()
  1053. f = cStringIO.StringIO()
  1054. primed = self.pickler_class(f)
  1055. primed.memo = pickler.memo
  1056. primed.dump(data)
  1057. primed_pickled = f.getvalue()
  1058. unpickler = self.unpickler_class(cStringIO.StringIO(first_pickled))
  1059. unpickled_data1 = unpickler.load()
  1060. self.assertEqual(unpickled_data1, data)
  1061. primed = self.unpickler_class(cStringIO.StringIO(primed_pickled))
  1062. primed.memo = unpickler.memo
  1063. unpickled_data2 = primed.load()
  1064. # TODO(collinwinter): add dedicated tests for memo.clear(). This will
  1065. # require implementing stream support for unpickling.
  1066. primed.memo.clear()
  1067. self.assertEqual(unpickled_data2, data)
  1068. self.assertTrue(unpickled_data2 is unpickled_data1)
  1069. def test_reusing_unpickler_objects(self):
  1070. data1 = ["abcdefg", "abcdefg", 44]
  1071. f = cStringIO.StringIO()
  1072. pickler = self.pickler_class(f)
  1073. pickler.dump(data1)
  1074. pickled1 = f.getvalue()
  1075. data2 = ["abcdefg", 44, 44]
  1076. f = cStringIO.StringIO()
  1077. pickler = self.pickler_class(f)
  1078. pickler.dump(data2)
  1079. pickled2 = f.getvalue()
  1080. f = cStringIO.StringIO()
  1081. f.write(pickled1)
  1082. f.seek(0)
  1083. unpickler = self.unpickler_class(f)
  1084. self.assertEqual(unpickler.load(), data1)
  1085. f.seek(0)
  1086. f.truncate()
  1087. f.write(pickled2)
  1088. f.seek(0)
  1089. self.assertEqual(unpickler.load(), data2)
  1090. def test_pickle_multiple_objects_to_the_same_stream(self):
  1091. # Test that we don't optimize out necessary PUT opcodes from the first
  1092. # pickle. Even though *that individual pickle* may not need the memo
  1093. # state, subsequent pickles written with the same Pickler object are
  1094. # relying on the memo state.
  1095. val1 = "this is a string"
  1096. data = [(val1, 1), (val1, 2), (val1, 3)]
  1097. f = cStringIO.StringIO()
  1098. pickler = self.pickler_class(f)
  1099. for obj in data:
  1100. pickler.dump(obj)
  1101. f.seek(0)
  1102. unpickler = self.unpickler_class(f)
  1103. for obj in data:
  1104. got_obj = unpickler.load()
  1105. self.assertEqual(obj, got_obj)
  1106. def test_copy_pickler_memo(self):
  1107. pickler = self.pickler_class(cStringIO.StringIO())
  1108. pickler.dump("abadsfasd")
  1109. memo = pickler.memo.copy()
  1110. pickler.memo.clear()
  1111. self.assertEqual(len(memo), 1)
  1112. def test_copy_unpickler_memo(self):
  1113. string = "abasdfasdf"
  1114. sample_data = self.dumps([string, string])
  1115. unpickler = self.unpickler_class(cStringIO.StringIO(sample_data))
  1116. unpickler.load()
  1117. memo = unpickler.memo.copy()
  1118. self.assertTrue(string in memo.values(), memo)
  1119. unpickler.memo.clear()
  1120. self.assertTrue(string in memo.values(), memo)
  1121. # Make sure we can call copy() and that the unpickler accepts the
  1122. # returned object.
  1123. unpickler.memo = memo.copy()
  1124. def test_priming_picklers_unpicklers(self):
  1125. # This test is distilled from the cvs2svn tool. In order to save space
  1126. # in their pickle database, cvs2svn "primes" the pickler/unpickler memos
  1127. # with common objects so that these objects are represented by GET
  1128. # opcodes in the pickles, rather than the much longer sequences they
  1129. # would otherwise generate. In order to make use of the priming memos,
  1130. # the memos themselves are pickled to the front of the data stream.
  1131. # We simulate this process here. Consider this a large integration test,
  1132. # while the tests above are intended to be more fine-grained.
  1133. # Objects we want to share between pickles.
  1134. common1 = "asdfasdfasdfa"
  1135. common2 = "asdfadfadfshdifu"
  1136. common3 = (5, 6)
  1137. common_objects = [common1, common2, common3]
  1138. # Combinations of the above objects. These will be sent through
  1139. # the data stream.
  1140. combo1 = (common1, common2)
  1141. combo2 = (6, common3)
  1142. combo3 = (common1, common2, common3)
  1143. data_stream = cStringIO.StringIO()
  1144. # 1. Pickle the common objects, extract the Pickler's memo.
  1145. f = cStringIO.StringIO()
  1146. pickler = self.pickler_class(f)
  1147. pickler.dump(common_objects)
  1148. pickler_memo = pickler.memo.copy()
  1149. priming_data = f.getvalue()
  1150. # 2. Unpickle the common objects, extract the Unpickler's memo.
  1151. unpickler = self.unpickler_class(cStringIO.StringIO(priming_data))
  1152. unpickler.load()
  1153. unpickler_memo = unpickler.memo.copy()
  1154. # 3. Write the pickler and unpickler memos to the data stream. These
  1155. # will be used to retrieve data from the stream.
  1156. pickler = self.pickler_class(data_stream)
  1157. pickler.dump(pickler_memo)
  1158. pickler.dump(unpickler_memo)
  1159. # 4. Pickle some more data to the data stream, using the priming memos.
  1160. # cvs2svn resets the memo before every object.
  1161. pickler = self.pickler_class(data_stream)
  1162. pickler.memo = pickler_memo.copy()
  1163. pickler.dump(combo1)
  1164. pickler.memo = pickler_memo.copy()
  1165. pickler.dump(combo2)
  1166. # 5. Now start reading the data. We read the priming memos first.
  1167. data_stream.seek(0)
  1168. unpickler = self.unpickler_class(data_stream)
  1169. recv_pickler_memo = unpickler.load()
  1170. recv_unpickler_memo = unpickler.load()
  1171. self.assertEqual(recv_pickler_memo, pickler_memo)
  1172. self.assertEqual(recv_unpickler_memo, unpickler_memo)
  1173. # 6. Using the received unpickling primer memo, unpickle the rest of
  1174. # the data stream. cvs2svn resets the memo before every object.
  1175. unpickler = self.unpickler_class(data_stream)
  1176. unpickler.memo = recv_unpickler_memo.copy()
  1177. self.assertEqual(unpickler.load(), combo1)
  1178. unpickler.memo = recv_unpickler_memo.copy()
  1179. self.assertEqual(unpickler.load(), combo2)
  1180. # 7. Pickle something using the received pickler memo, then unpickle it
  1181. # to make sure that the pickler memo works.
  1182. f = cStringIO.StringIO()
  1183. pickler = self.pickler_class(f)
  1184. pickler.memo = recv_pickler_memo.copy()
  1185. pickler.dump(combo3)
  1186. f.seek(0)
  1187. unpickler = self.unpickler_class(f)
  1188. unpickler.memo = recv_unpickler_memo.copy()
  1189. self.assertEqual(unpickler.load(), combo3)