(root)/
Python-3.12.0/
Lib/
test/
test_marshal.py
       1  from test import support
       2  from test.support import os_helper, requires_debug_ranges
       3  from test.support.script_helper import assert_python_ok
       4  import array
       5  import io
       6  import marshal
       7  import sys
       8  import unittest
       9  import os
      10  import types
      11  import textwrap
      12  
      13  try:
      14      import _testcapi
      15  except ImportError:
      16      _testcapi = None
      17  
      18  class ESC[4;38;5;81mHelperMixin:
      19      def helper(self, sample, *extra):
      20          new = marshal.loads(marshal.dumps(sample, *extra))
      21          self.assertEqual(sample, new)
      22          try:
      23              with open(os_helper.TESTFN, "wb") as f:
      24                  marshal.dump(sample, f, *extra)
      25              with open(os_helper.TESTFN, "rb") as f:
      26                  new = marshal.load(f)
      27              self.assertEqual(sample, new)
      28          finally:
      29              os_helper.unlink(os_helper.TESTFN)
      30  
      31  class ESC[4;38;5;81mIntTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase, ESC[4;38;5;149mHelperMixin):
      32      def test_ints(self):
      33          # Test a range of Python ints larger than the machine word size.
      34          n = sys.maxsize ** 2
      35          while n:
      36              for expected in (-n, n):
      37                  self.helper(expected)
      38              n = n >> 1
      39  
      40      def test_int64(self):
      41          # Simulate int marshaling with TYPE_INT64.
      42          maxint64 = (1 << 63) - 1
      43          minint64 = -maxint64-1
      44          for base in maxint64, minint64, -maxint64, -(minint64 >> 1):
      45              while base:
      46                  s = b'I' + int.to_bytes(base, 8, 'little', signed=True)
      47                  got = marshal.loads(s)
      48                  self.assertEqual(base, got)
      49                  if base == -1:  # a fixed-point for shifting right 1
      50                      base = 0
      51                  else:
      52                      base >>= 1
      53  
      54          got = marshal.loads(b'I\xfe\xdc\xba\x98\x76\x54\x32\x10')
      55          self.assertEqual(got, 0x1032547698badcfe)
      56          got = marshal.loads(b'I\x01\x23\x45\x67\x89\xab\xcd\xef')
      57          self.assertEqual(got, -0x1032547698badcff)
      58          got = marshal.loads(b'I\x08\x19\x2a\x3b\x4c\x5d\x6e\x7f')
      59          self.assertEqual(got, 0x7f6e5d4c3b2a1908)
      60          got = marshal.loads(b'I\xf7\xe6\xd5\xc4\xb3\xa2\x91\x80')
      61          self.assertEqual(got, -0x7f6e5d4c3b2a1909)
      62  
      63      def test_bool(self):
      64          for b in (True, False):
      65              self.helper(b)
      66  
      67  class ESC[4;38;5;81mFloatTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase, ESC[4;38;5;149mHelperMixin):
      68      def test_floats(self):
      69          # Test a few floats
      70          small = 1e-25
      71          n = sys.maxsize * 3.7e250
      72          while n > small:
      73              for expected in (-n, n):
      74                  self.helper(float(expected))
      75              n /= 123.4567
      76  
      77          f = 0.0
      78          s = marshal.dumps(f, 2)
      79          got = marshal.loads(s)
      80          self.assertEqual(f, got)
      81          # and with version <= 1 (floats marshalled differently then)
      82          s = marshal.dumps(f, 1)
      83          got = marshal.loads(s)
      84          self.assertEqual(f, got)
      85  
      86          n = sys.maxsize * 3.7e-250
      87          while n < small:
      88              for expected in (-n, n):
      89                  f = float(expected)
      90                  self.helper(f)
      91                  self.helper(f, 1)
      92              n *= 123.4567
      93  
      94  class ESC[4;38;5;81mStringTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase, ESC[4;38;5;149mHelperMixin):
      95      def test_unicode(self):
      96          for s in ["", "Andr\xe8 Previn", "abc", " "*10000]:
      97              self.helper(marshal.loads(marshal.dumps(s)))
      98  
      99      def test_string(self):
     100          for s in ["", "Andr\xe8 Previn", "abc", " "*10000]:
     101              self.helper(s)
     102  
     103      def test_bytes(self):
     104          for s in [b"", b"Andr\xe8 Previn", b"abc", b" "*10000]:
     105              self.helper(s)
     106  
     107  class ESC[4;38;5;81mExceptionTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     108      def test_exceptions(self):
     109          new = marshal.loads(marshal.dumps(StopIteration))
     110          self.assertEqual(StopIteration, new)
     111  
     112  class ESC[4;38;5;81mCodeTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     113      def test_code(self):
     114          co = ExceptionTestCase.test_exceptions.__code__
     115          new = marshal.loads(marshal.dumps(co))
     116          self.assertEqual(co, new)
     117  
     118      def test_many_codeobjects(self):
     119          # Issue2957: bad recursion count on code objects
     120          # more than MAX_MARSHAL_STACK_DEPTH
     121          count = support.EXCEEDS_RECURSION_LIMIT
     122          codes = (ExceptionTestCase.test_exceptions.__code__,) * count
     123          marshal.loads(marshal.dumps(codes))
     124  
     125      def test_different_filenames(self):
     126          co1 = compile("x", "f1", "exec")
     127          co2 = compile("y", "f2", "exec")
     128          co1, co2 = marshal.loads(marshal.dumps((co1, co2)))
     129          self.assertEqual(co1.co_filename, "f1")
     130          self.assertEqual(co2.co_filename, "f2")
     131  
     132      @requires_debug_ranges()
     133      def test_minimal_linetable_with_no_debug_ranges(self):
     134          # Make sure when demarshalling objects with `-X no_debug_ranges`
     135          # that the columns are None.
     136          co = ExceptionTestCase.test_exceptions.__code__
     137          code = textwrap.dedent("""
     138          import sys
     139          import marshal
     140          with open(sys.argv[1], 'rb') as f:
     141              co = marshal.load(f)
     142              positions = list(co.co_positions())
     143              assert positions[0][2] is None
     144              assert positions[0][3] is None
     145          """)
     146  
     147          try:
     148              with open(os_helper.TESTFN, 'wb') as f:
     149                  marshal.dump(co, f)
     150  
     151              assert_python_ok('-X', 'no_debug_ranges',
     152                               '-c', code, os_helper.TESTFN)
     153          finally:
     154              os_helper.unlink(os_helper.TESTFN)
     155  
     156      @support.cpython_only
     157      def test_same_filename_used(self):
     158          s = """def f(): pass\ndef g(): pass"""
     159          co = compile(s, "myfile", "exec")
     160          co = marshal.loads(marshal.dumps(co))
     161          for obj in co.co_consts:
     162              if isinstance(obj, types.CodeType):
     163                  self.assertIs(co.co_filename, obj.co_filename)
     164  
     165  class ESC[4;38;5;81mContainerTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase, ESC[4;38;5;149mHelperMixin):
     166      d = {'astring': 'foo@bar.baz.spam',
     167           'afloat': 7283.43,
     168           'anint': 2**20,
     169           'ashortlong': 2,
     170           'alist': ['.zyx.41'],
     171           'atuple': ('.zyx.41',)*10,
     172           'aboolean': False,
     173           'aunicode': "Andr\xe8 Previn"
     174           }
     175  
     176      def test_dict(self):
     177          self.helper(self.d)
     178  
     179      def test_list(self):
     180          self.helper(list(self.d.items()))
     181  
     182      def test_tuple(self):
     183          self.helper(tuple(self.d.keys()))
     184  
     185      def test_sets(self):
     186          for constructor in (set, frozenset):
     187              self.helper(constructor(self.d.keys()))
     188  
     189  
     190  class ESC[4;38;5;81mBufferTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase, ESC[4;38;5;149mHelperMixin):
     191  
     192      def test_bytearray(self):
     193          b = bytearray(b"abc")
     194          self.helper(b)
     195          new = marshal.loads(marshal.dumps(b))
     196          self.assertEqual(type(new), bytes)
     197  
     198      def test_memoryview(self):
     199          b = memoryview(b"abc")
     200          self.helper(b)
     201          new = marshal.loads(marshal.dumps(b))
     202          self.assertEqual(type(new), bytes)
     203  
     204      def test_array(self):
     205          a = array.array('B', b"abc")
     206          new = marshal.loads(marshal.dumps(a))
     207          self.assertEqual(new, b"abc")
     208  
     209  
     210  class ESC[4;38;5;81mBugsTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     211      def test_bug_5888452(self):
     212          # Simple-minded check for SF 588452: Debug build crashes
     213          marshal.dumps([128] * 1000)
     214  
     215      def test_patch_873224(self):
     216          self.assertRaises(Exception, marshal.loads, b'0')
     217          self.assertRaises(Exception, marshal.loads, b'f')
     218          self.assertRaises(Exception, marshal.loads, marshal.dumps(2**65)[:-1])
     219  
     220      def test_version_argument(self):
     221          # Python 2.4.0 crashes for any call to marshal.dumps(x, y)
     222          self.assertEqual(marshal.loads(marshal.dumps(5, 0)), 5)
     223          self.assertEqual(marshal.loads(marshal.dumps(5, 1)), 5)
     224  
     225      def test_fuzz(self):
     226          # simple test that it's at least not *totally* trivial to
     227          # crash from bad marshal data
     228          for i in range(256):
     229              c = bytes([i])
     230              try:
     231                  marshal.loads(c)
     232              except Exception:
     233                  pass
     234  
     235      def test_loads_recursion(self):
     236          def run_tests(N, check):
     237              # (((...None...),),)
     238              check(b')\x01' * N + b'N')
     239              check(b'(\x01\x00\x00\x00' * N + b'N')
     240              # [[[...None...]]]
     241              check(b'[\x01\x00\x00\x00' * N + b'N')
     242              # {None: {None: {None: ...None...}}}
     243              check(b'{N' * N + b'N' + b'0' * N)
     244              # frozenset([frozenset([frozenset([...None...])])])
     245              check(b'>\x01\x00\x00\x00' * N + b'N')
     246          # Check that the generated marshal data is valid and marshal.loads()
     247          # works for moderately deep nesting
     248          run_tests(100, marshal.loads)
     249          # Very deeply nested structure shouldn't blow the stack
     250          def check(s):
     251              self.assertRaises(ValueError, marshal.loads, s)
     252          run_tests(2**20, check)
     253  
     254      def test_recursion_limit(self):
     255          # Create a deeply nested structure.
     256          head = last = []
     257          # The max stack depth should match the value in Python/marshal.c.
     258          # BUG: https://bugs.python.org/issue33720
     259          # Windows always limits the maximum depth on release and debug builds
     260          #if os.name == 'nt' and support.Py_DEBUG:
     261          if os.name == 'nt':
     262              MAX_MARSHAL_STACK_DEPTH = 1000
     263          elif sys.platform == 'wasi':
     264              MAX_MARSHAL_STACK_DEPTH = 1500
     265          else:
     266              MAX_MARSHAL_STACK_DEPTH = 2000
     267          for i in range(MAX_MARSHAL_STACK_DEPTH - 2):
     268              last.append([0])
     269              last = last[-1]
     270  
     271          # Verify we don't blow out the stack with dumps/load.
     272          data = marshal.dumps(head)
     273          new_head = marshal.loads(data)
     274          # Don't use == to compare objects, it can exceed the recursion limit.
     275          self.assertEqual(len(new_head), len(head))
     276          self.assertEqual(len(new_head[0]), len(head[0]))
     277          self.assertEqual(len(new_head[-1]), len(head[-1]))
     278  
     279          last.append([0])
     280          self.assertRaises(ValueError, marshal.dumps, head)
     281  
     282      def test_exact_type_match(self):
     283          # Former bug:
     284          #   >>> class Int(int): pass
     285          #   >>> type(loads(dumps(Int())))
     286          #   <type 'int'>
     287          for typ in (int, float, complex, tuple, list, dict, set, frozenset):
     288              # Note: str subclasses are not tested because they get handled
     289              # by marshal's routines for objects supporting the buffer API.
     290              subtyp = type('subtyp', (typ,), {})
     291              self.assertRaises(ValueError, marshal.dumps, subtyp())
     292  
     293      # Issue #1792 introduced a change in how marshal increases the size of its
     294      # internal buffer; this test ensures that the new code is exercised.
     295      def test_large_marshal(self):
     296          size = int(1e6)
     297          testString = 'abc' * size
     298          marshal.dumps(testString)
     299  
     300      def test_invalid_longs(self):
     301          # Issue #7019: marshal.loads shouldn't produce unnormalized PyLongs
     302          invalid_string = b'l\x02\x00\x00\x00\x00\x00\x00\x00'
     303          self.assertRaises(ValueError, marshal.loads, invalid_string)
     304  
     305      def test_multiple_dumps_and_loads(self):
     306          # Issue 12291: marshal.load() should be callable multiple times
     307          # with interleaved data written by non-marshal code
     308          # Adapted from a patch by Engelbert Gruber.
     309          data = (1, 'abc', b'def', 1.0, (2, 'a', ['b', b'c']))
     310          for interleaved in (b'', b'0123'):
     311              ilen = len(interleaved)
     312              positions = []
     313              try:
     314                  with open(os_helper.TESTFN, 'wb') as f:
     315                      for d in data:
     316                          marshal.dump(d, f)
     317                          if ilen:
     318                              f.write(interleaved)
     319                          positions.append(f.tell())
     320                  with open(os_helper.TESTFN, 'rb') as f:
     321                      for i, d in enumerate(data):
     322                          self.assertEqual(d, marshal.load(f))
     323                          if ilen:
     324                              f.read(ilen)
     325                          self.assertEqual(positions[i], f.tell())
     326              finally:
     327                  os_helper.unlink(os_helper.TESTFN)
     328  
     329      def test_loads_reject_unicode_strings(self):
     330          # Issue #14177: marshal.loads() should not accept unicode strings
     331          unicode_string = 'T'
     332          self.assertRaises(TypeError, marshal.loads, unicode_string)
     333  
     334      def test_bad_reader(self):
     335          class ESC[4;38;5;81mBadReader(ESC[4;38;5;149mioESC[4;38;5;149m.ESC[4;38;5;149mBytesIO):
     336              def readinto(self, buf):
     337                  n = super().readinto(buf)
     338                  if n is not None and n > 4:
     339                      n += 10**6
     340                  return n
     341          for value in (1.0, 1j, b'0123456789', '0123456789'):
     342              self.assertRaises(ValueError, marshal.load,
     343                                BadReader(marshal.dumps(value)))
     344  
     345      def test_eof(self):
     346          data = marshal.dumps(("hello", "dolly", None))
     347          for i in range(len(data)):
     348              self.assertRaises(EOFError, marshal.loads, data[0: i])
     349  
     350      def test_deterministic_sets(self):
     351          # bpo-37596: To support reproducible builds, sets and frozensets need to
     352          # have their elements serialized in a consistent order (even when they
     353          # have been scrambled by hash randomization):
     354          for kind in ("set", "frozenset"):
     355              for elements in (
     356                  "float('nan'), b'a', b'b', b'c', 'x', 'y', 'z'",
     357                  # Also test for bad interactions with backreferencing:
     358                  "('Spam', 0), ('Spam', 1), ('Spam', 2), ('Spam', 3), ('Spam', 4), ('Spam', 5)",
     359              ):
     360                  s = f"{kind}([{elements}])"
     361                  with self.subTest(s):
     362                      # First, make sure that our test case still has different
     363                      # orders under hash seeds 0 and 1. If this check fails, we
     364                      # need to update this test with different elements. Skip
     365                      # this part if we are configured to use any other hash
     366                      # algorithm (for example, using Py_HASH_EXTERNAL):
     367                      if sys.hash_info.algorithm in {"fnv", "siphash24"}:
     368                          args = ["-c", f"print({s})"]
     369                          _, repr_0, _ = assert_python_ok(*args, PYTHONHASHSEED="0")
     370                          _, repr_1, _ = assert_python_ok(*args, PYTHONHASHSEED="1")
     371                          self.assertNotEqual(repr_0, repr_1)
     372                      # Then, perform the actual test:
     373                      args = ["-c", f"import marshal; print(marshal.dumps({s}))"]
     374                      _, dump_0, _ = assert_python_ok(*args, PYTHONHASHSEED="0")
     375                      _, dump_1, _ = assert_python_ok(*args, PYTHONHASHSEED="1")
     376                      self.assertEqual(dump_0, dump_1)
     377  
     378  LARGE_SIZE = 2**31
     379  pointer_size = 8 if sys.maxsize > 0xFFFFFFFF else 4
     380  
     381  class ESC[4;38;5;81mNullWriter:
     382      def write(self, s):
     383          pass
     384  
     385  @unittest.skipIf(LARGE_SIZE > sys.maxsize, "test cannot run on 32-bit systems")
     386  class ESC[4;38;5;81mLargeValuesTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     387      def check_unmarshallable(self, data):
     388          self.assertRaises(ValueError, marshal.dump, data, NullWriter())
     389  
     390      @support.bigmemtest(size=LARGE_SIZE, memuse=2, dry_run=False)
     391      def test_bytes(self, size):
     392          self.check_unmarshallable(b'x' * size)
     393  
     394      @support.bigmemtest(size=LARGE_SIZE, memuse=2, dry_run=False)
     395      def test_str(self, size):
     396          self.check_unmarshallable('x' * size)
     397  
     398      @support.bigmemtest(size=LARGE_SIZE, memuse=pointer_size + 1, dry_run=False)
     399      def test_tuple(self, size):
     400          self.check_unmarshallable((None,) * size)
     401  
     402      @support.bigmemtest(size=LARGE_SIZE, memuse=pointer_size + 1, dry_run=False)
     403      def test_list(self, size):
     404          self.check_unmarshallable([None] * size)
     405  
     406      @support.bigmemtest(size=LARGE_SIZE,
     407              memuse=pointer_size*12 + sys.getsizeof(LARGE_SIZE-1),
     408              dry_run=False)
     409      def test_set(self, size):
     410          self.check_unmarshallable(set(range(size)))
     411  
     412      @support.bigmemtest(size=LARGE_SIZE,
     413              memuse=pointer_size*12 + sys.getsizeof(LARGE_SIZE-1),
     414              dry_run=False)
     415      def test_frozenset(self, size):
     416          self.check_unmarshallable(frozenset(range(size)))
     417  
     418      @support.bigmemtest(size=LARGE_SIZE, memuse=2, dry_run=False)
     419      def test_bytearray(self, size):
     420          self.check_unmarshallable(bytearray(size))
     421  
     422  def CollectObjectIDs(ids, obj):
     423      """Collect object ids seen in a structure"""
     424      if id(obj) in ids:
     425          return
     426      ids.add(id(obj))
     427      if isinstance(obj, (list, tuple, set, frozenset)):
     428          for e in obj:
     429              CollectObjectIDs(ids, e)
     430      elif isinstance(obj, dict):
     431          for k, v in obj.items():
     432              CollectObjectIDs(ids, k)
     433              CollectObjectIDs(ids, v)
     434      return len(ids)
     435  
     436  class ESC[4;38;5;81mInstancingTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase, ESC[4;38;5;149mHelperMixin):
     437      keys = (123, 1.2345, 'abc', (123, 'abc'), frozenset({123, 'abc'}))
     438  
     439      def helper3(self, rsample, recursive=False, simple=False):
     440          #we have two instances
     441          sample = (rsample, rsample)
     442  
     443          n0 = CollectObjectIDs(set(), sample)
     444  
     445          for v in range(3, marshal.version + 1):
     446              s3 = marshal.dumps(sample, v)
     447              n3 = CollectObjectIDs(set(), marshal.loads(s3))
     448  
     449              #same number of instances generated
     450              self.assertEqual(n3, n0)
     451  
     452          if not recursive:
     453              #can compare with version 2
     454              s2 = marshal.dumps(sample, 2)
     455              n2 = CollectObjectIDs(set(), marshal.loads(s2))
     456              #old format generated more instances
     457              self.assertGreater(n2, n0)
     458  
     459              #if complex objects are in there, old format is larger
     460              if not simple:
     461                  self.assertGreater(len(s2), len(s3))
     462              else:
     463                  self.assertGreaterEqual(len(s2), len(s3))
     464  
     465      def testInt(self):
     466          intobj = 123321
     467          self.helper(intobj)
     468          self.helper3(intobj, simple=True)
     469  
     470      def testFloat(self):
     471          floatobj = 1.2345
     472          self.helper(floatobj)
     473          self.helper3(floatobj)
     474  
     475      def testStr(self):
     476          strobj = "abcde"*3
     477          self.helper(strobj)
     478          self.helper3(strobj)
     479  
     480      def testBytes(self):
     481          bytesobj = b"abcde"*3
     482          self.helper(bytesobj)
     483          self.helper3(bytesobj)
     484  
     485      def testList(self):
     486          for obj in self.keys:
     487              listobj = [obj, obj]
     488              self.helper(listobj)
     489              self.helper3(listobj)
     490  
     491      def testTuple(self):
     492          for obj in self.keys:
     493              tupleobj = (obj, obj)
     494              self.helper(tupleobj)
     495              self.helper3(tupleobj)
     496  
     497      def testSet(self):
     498          for obj in self.keys:
     499              setobj = {(obj, 1), (obj, 2)}
     500              self.helper(setobj)
     501              self.helper3(setobj)
     502  
     503      def testFrozenSet(self):
     504          for obj in self.keys:
     505              frozensetobj = frozenset({(obj, 1), (obj, 2)})
     506              self.helper(frozensetobj)
     507              self.helper3(frozensetobj)
     508  
     509      def testDict(self):
     510          for obj in self.keys:
     511              dictobj = {"hello": obj, "goodbye": obj, obj: "hello"}
     512              self.helper(dictobj)
     513              self.helper3(dictobj)
     514  
     515      def testModule(self):
     516          with open(__file__, "rb") as f:
     517              code = f.read()
     518          if __file__.endswith(".py"):
     519              code = compile(code, __file__, "exec")
     520          self.helper(code)
     521          self.helper3(code)
     522  
     523      def testRecursion(self):
     524          obj = 1.2345
     525          d = {"hello": obj, "goodbye": obj, obj: "hello"}
     526          d["self"] = d
     527          self.helper3(d, recursive=True)
     528          l = [obj, obj]
     529          l.append(l)
     530          self.helper3(l, recursive=True)
     531  
     532  class ESC[4;38;5;81mCompatibilityTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     533      def _test(self, version):
     534          with open(__file__, "rb") as f:
     535              code = f.read()
     536          if __file__.endswith(".py"):
     537              code = compile(code, __file__, "exec")
     538          data = marshal.dumps(code, version)
     539          marshal.loads(data)
     540  
     541      def test0To3(self):
     542          self._test(0)
     543  
     544      def test1To3(self):
     545          self._test(1)
     546  
     547      def test2To3(self):
     548          self._test(2)
     549  
     550      def test3To3(self):
     551          self._test(3)
     552  
     553  class ESC[4;38;5;81mInterningTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase, ESC[4;38;5;149mHelperMixin):
     554      strobj = "this is an interned string"
     555      strobj = sys.intern(strobj)
     556  
     557      def testIntern(self):
     558          s = marshal.loads(marshal.dumps(self.strobj))
     559          self.assertEqual(s, self.strobj)
     560          self.assertEqual(id(s), id(self.strobj))
     561          s2 = sys.intern(s)
     562          self.assertEqual(id(s2), id(s))
     563  
     564      def testNoIntern(self):
     565          s = marshal.loads(marshal.dumps(self.strobj, 2))
     566          self.assertEqual(s, self.strobj)
     567          self.assertNotEqual(id(s), id(self.strobj))
     568          s2 = sys.intern(s)
     569          self.assertNotEqual(id(s2), id(s))
     570  
     571  @support.cpython_only
     572  @unittest.skipUnless(_testcapi, 'requires _testcapi')
     573  class ESC[4;38;5;81mCAPI_TestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase, ESC[4;38;5;149mHelperMixin):
     574  
     575      def test_write_long_to_file(self):
     576          for v in range(marshal.version + 1):
     577              _testcapi.pymarshal_write_long_to_file(0x12345678, os_helper.TESTFN, v)
     578              with open(os_helper.TESTFN, 'rb') as f:
     579                  data = f.read()
     580              os_helper.unlink(os_helper.TESTFN)
     581              self.assertEqual(data, b'\x78\x56\x34\x12')
     582  
     583      def test_write_object_to_file(self):
     584          obj = ('\u20ac', b'abc', 123, 45.6, 7+8j, 'long line '*1000)
     585          for v in range(marshal.version + 1):
     586              _testcapi.pymarshal_write_object_to_file(obj, os_helper.TESTFN, v)
     587              with open(os_helper.TESTFN, 'rb') as f:
     588                  data = f.read()
     589              os_helper.unlink(os_helper.TESTFN)
     590              self.assertEqual(marshal.loads(data), obj)
     591  
     592      def test_read_short_from_file(self):
     593          with open(os_helper.TESTFN, 'wb') as f:
     594              f.write(b'\x34\x12xxxx')
     595          r, p = _testcapi.pymarshal_read_short_from_file(os_helper.TESTFN)
     596          os_helper.unlink(os_helper.TESTFN)
     597          self.assertEqual(r, 0x1234)
     598          self.assertEqual(p, 2)
     599  
     600          with open(os_helper.TESTFN, 'wb') as f:
     601              f.write(b'\x12')
     602          with self.assertRaises(EOFError):
     603              _testcapi.pymarshal_read_short_from_file(os_helper.TESTFN)
     604          os_helper.unlink(os_helper.TESTFN)
     605  
     606      def test_read_long_from_file(self):
     607          with open(os_helper.TESTFN, 'wb') as f:
     608              f.write(b'\x78\x56\x34\x12xxxx')
     609          r, p = _testcapi.pymarshal_read_long_from_file(os_helper.TESTFN)
     610          os_helper.unlink(os_helper.TESTFN)
     611          self.assertEqual(r, 0x12345678)
     612          self.assertEqual(p, 4)
     613  
     614          with open(os_helper.TESTFN, 'wb') as f:
     615              f.write(b'\x56\x34\x12')
     616          with self.assertRaises(EOFError):
     617              _testcapi.pymarshal_read_long_from_file(os_helper.TESTFN)
     618          os_helper.unlink(os_helper.TESTFN)
     619  
     620      def test_read_last_object_from_file(self):
     621          obj = ('\u20ac', b'abc', 123, 45.6, 7+8j)
     622          for v in range(marshal.version + 1):
     623              data = marshal.dumps(obj, v)
     624              with open(os_helper.TESTFN, 'wb') as f:
     625                  f.write(data + b'xxxx')
     626              r, p = _testcapi.pymarshal_read_last_object_from_file(os_helper.TESTFN)
     627              os_helper.unlink(os_helper.TESTFN)
     628              self.assertEqual(r, obj)
     629  
     630              with open(os_helper.TESTFN, 'wb') as f:
     631                  f.write(data[:1])
     632              with self.assertRaises(EOFError):
     633                  _testcapi.pymarshal_read_last_object_from_file(os_helper.TESTFN)
     634              os_helper.unlink(os_helper.TESTFN)
     635  
     636      def test_read_object_from_file(self):
     637          obj = ('\u20ac', b'abc', 123, 45.6, 7+8j)
     638          for v in range(marshal.version + 1):
     639              data = marshal.dumps(obj, v)
     640              with open(os_helper.TESTFN, 'wb') as f:
     641                  f.write(data + b'xxxx')
     642              r, p = _testcapi.pymarshal_read_object_from_file(os_helper.TESTFN)
     643              os_helper.unlink(os_helper.TESTFN)
     644              self.assertEqual(r, obj)
     645              self.assertEqual(p, len(data))
     646  
     647              with open(os_helper.TESTFN, 'wb') as f:
     648                  f.write(data[:1])
     649              with self.assertRaises(EOFError):
     650                  _testcapi.pymarshal_read_object_from_file(os_helper.TESTFN)
     651              os_helper.unlink(os_helper.TESTFN)
     652  
     653  
     654  if __name__ == "__main__":
     655      unittest.main()