Home | History | Annotate | Download | only in test
      1 from test.test_support import (TESTFN, run_unittest, import_module, unlink,
      2                                requires, _2G, _4G, gc_collect, cpython_only)
      3 import unittest
      4 import os, re, itertools, socket, sys
      5 
      6 mmap = import_module('mmap')
      7 
      8 PAGESIZE = mmap.PAGESIZE
      9 
     10 class MmapTests(unittest.TestCase):
     11 
     12     def setUp(self):
     13         if os.path.exists(TESTFN):
     14             os.unlink(TESTFN)
     15 
     16     def tearDown(self):
     17         try:
     18             os.unlink(TESTFN)
     19         except OSError:
     20             pass
     21 
     22     def test_basic(self):
     23         # Test mmap module on Unix systems and Windows
     24 
     25         # Create a file to be mmap'ed.
     26         f = open(TESTFN, 'w+')
     27         try:
     28             # Write 2 pages worth of data to the file
     29             f.write('\0'* PAGESIZE)
     30             f.write('foo')
     31             f.write('\0'* (PAGESIZE-3) )
     32             f.flush()
     33             m = mmap.mmap(f.fileno(), 2 * PAGESIZE)
     34             f.close()
     35 
     36             # Simple sanity checks
     37 
     38             tp = str(type(m))  # SF bug 128713:  segfaulted on Linux
     39             self.assertEqual(m.find('foo'), PAGESIZE)
     40 
     41             self.assertEqual(len(m), 2*PAGESIZE)
     42 
     43             self.assertEqual(m[0], '\0')
     44             self.assertEqual(m[0:3], '\0\0\0')
     45 
     46             # Shouldn't crash on boundary (Issue #5292)
     47             self.assertRaises(IndexError, m.__getitem__, len(m))
     48             self.assertRaises(IndexError, m.__setitem__, len(m), '\0')
     49 
     50             # Modify the file's content
     51             m[0] = '3'
     52             m[PAGESIZE +3: PAGESIZE +3+3] = 'bar'
     53 
     54             # Check that the modification worked
     55             self.assertEqual(m[0], '3')
     56             self.assertEqual(m[0:3], '3\0\0')
     57             self.assertEqual(m[PAGESIZE-1 : PAGESIZE + 7], '\0foobar\0')
     58 
     59             m.flush()
     60 
     61             # Test doing a regular expression match in an mmap'ed file
     62             match = re.search('[A-Za-z]+', m)
     63             if match is None:
     64                 self.fail('regex match on mmap failed!')
     65             else:
     66                 start, end = match.span(0)
     67                 length = end - start
     68 
     69                 self.assertEqual(start, PAGESIZE)
     70                 self.assertEqual(end, PAGESIZE + 6)
     71 
     72             # test seeking around (try to overflow the seek implementation)
     73             m.seek(0,0)
     74             self.assertEqual(m.tell(), 0)
     75             m.seek(42,1)
     76             self.assertEqual(m.tell(), 42)
     77             m.seek(0,2)
     78             self.assertEqual(m.tell(), len(m))
     79 
     80             # Try to seek to negative position...
     81             self.assertRaises(ValueError, m.seek, -1)
     82 
     83             # Try to seek beyond end of mmap...
     84             self.assertRaises(ValueError, m.seek, 1, 2)
     85 
     86             # Try to seek to negative position...
     87             self.assertRaises(ValueError, m.seek, -len(m)-1, 2)
     88 
     89             # Try resizing map
     90             try:
     91                 m.resize(512)
     92             except SystemError:
     93                 # resize() not supported
     94                 # No messages are printed, since the output of this test suite
     95                 # would then be different across platforms.
     96                 pass
     97             else:
     98                 # resize() is supported
     99                 self.assertEqual(len(m), 512)
    100                 # Check that we can no longer seek beyond the new size.
    101                 self.assertRaises(ValueError, m.seek, 513, 0)
    102 
    103                 # Check that the underlying file is truncated too
    104                 # (bug #728515)
    105                 f = open(TESTFN)
    106                 f.seek(0, 2)
    107                 self.assertEqual(f.tell(), 512)
    108                 f.close()
    109                 self.assertEqual(m.size(), 512)
    110 
    111             m.close()
    112 
    113         finally:
    114             try:
    115                 f.close()
    116             except OSError:
    117                 pass
    118 
    119     def test_access_parameter(self):
    120         # Test for "access" keyword parameter
    121         mapsize = 10
    122         open(TESTFN, "wb").write("a"*mapsize)
    123         f = open(TESTFN, "rb")
    124         m = mmap.mmap(f.fileno(), mapsize, access=mmap.ACCESS_READ)
    125         self.assertEqual(m[:], 'a'*mapsize, "Readonly memory map data incorrect.")
    126 
    127         # Ensuring that readonly mmap can't be slice assigned
    128         try:
    129             m[:] = 'b'*mapsize
    130         except TypeError:
    131             pass
    132         else:
    133             self.fail("Able to write to readonly memory map")
    134 
    135         # Ensuring that readonly mmap can't be item assigned
    136         try:
    137             m[0] = 'b'
    138         except TypeError:
    139             pass
    140         else:
    141             self.fail("Able to write to readonly memory map")
    142 
    143         # Ensuring that readonly mmap can't be write() to
    144         try:
    145             m.seek(0,0)
    146             m.write('abc')
    147         except TypeError:
    148             pass
    149         else:
    150             self.fail("Able to write to readonly memory map")
    151 
    152         # Ensuring that readonly mmap can't be write_byte() to
    153         try:
    154             m.seek(0,0)
    155             m.write_byte('d')
    156         except TypeError:
    157             pass
    158         else:
    159             self.fail("Able to write to readonly memory map")
    160 
    161         # Ensuring that readonly mmap can't be resized
    162         try:
    163             m.resize(2*mapsize)
    164         except SystemError:   # resize is not universally supported
    165             pass
    166         except TypeError:
    167             pass
    168         else:
    169             self.fail("Able to resize readonly memory map")
    170         f.close()
    171         del m, f
    172         self.assertEqual(open(TESTFN, "rb").read(), 'a'*mapsize,
    173                "Readonly memory map data file was modified")
    174 
    175         # Opening mmap with size too big
    176         import sys
    177         f = open(TESTFN, "r+b")
    178         try:
    179             m = mmap.mmap(f.fileno(), mapsize+1)
    180         except ValueError:
    181             # we do not expect a ValueError on Windows
    182             # CAUTION:  This also changes the size of the file on disk, and
    183             # later tests assume that the length hasn't changed.  We need to
    184             # repair that.
    185             if sys.platform.startswith('win'):
    186                 self.fail("Opening mmap with size+1 should work on Windows.")
    187         else:
    188             # we expect a ValueError on Unix, but not on Windows
    189             if not sys.platform.startswith('win'):
    190                 self.fail("Opening mmap with size+1 should raise ValueError.")
    191             m.close()
    192         f.close()
    193         if sys.platform.startswith('win'):
    194             # Repair damage from the resizing test.
    195             f = open(TESTFN, 'r+b')
    196             f.truncate(mapsize)
    197             f.close()
    198 
    199         # Opening mmap with access=ACCESS_WRITE
    200         f = open(TESTFN, "r+b")
    201         m = mmap.mmap(f.fileno(), mapsize, access=mmap.ACCESS_WRITE)
    202         # Modifying write-through memory map
    203         m[:] = 'c'*mapsize
    204         self.assertEqual(m[:], 'c'*mapsize,
    205                "Write-through memory map memory not updated properly.")
    206         m.flush()
    207         m.close()
    208         f.close()
    209         f = open(TESTFN, 'rb')
    210         stuff = f.read()
    211         f.close()
    212         self.assertEqual(stuff, 'c'*mapsize,
    213                "Write-through memory map data file not updated properly.")
    214 
    215         # Opening mmap with access=ACCESS_COPY
    216         f = open(TESTFN, "r+b")
    217         m = mmap.mmap(f.fileno(), mapsize, access=mmap.ACCESS_COPY)
    218         # Modifying copy-on-write memory map
    219         m[:] = 'd'*mapsize
    220         self.assertEqual(m[:], 'd' * mapsize,
    221                "Copy-on-write memory map data not written correctly.")
    222         m.flush()
    223         self.assertEqual(open(TESTFN, "rb").read(), 'c'*mapsize,
    224                "Copy-on-write test data file should not be modified.")
    225         # Ensuring copy-on-write maps cannot be resized
    226         self.assertRaises(TypeError, m.resize, 2*mapsize)
    227         f.close()
    228         del m, f
    229 
    230         # Ensuring invalid access parameter raises exception
    231         f = open(TESTFN, "r+b")
    232         self.assertRaises(ValueError, mmap.mmap, f.fileno(), mapsize, access=4)
    233         f.close()
    234 
    235         if os.name == "posix":
    236             # Try incompatible flags, prot and access parameters.
    237             f = open(TESTFN, "r+b")
    238             self.assertRaises(ValueError, mmap.mmap, f.fileno(), mapsize,
    239                               flags=mmap.MAP_PRIVATE,
    240                               prot=mmap.PROT_READ, access=mmap.ACCESS_WRITE)
    241             f.close()
    242 
    243             # Try writing with PROT_EXEC and without PROT_WRITE
    244             prot = mmap.PROT_READ | getattr(mmap, 'PROT_EXEC', 0)
    245             with open(TESTFN, "r+b") as f:
    246                 m = mmap.mmap(f.fileno(), mapsize, prot=prot)
    247                 self.assertRaises(TypeError, m.write, b"abcdef")
    248                 self.assertRaises(TypeError, m.write_byte, 0)
    249                 m.close()
    250 
    251     def test_bad_file_desc(self):
    252         # Try opening a bad file descriptor...
    253         self.assertRaises(mmap.error, mmap.mmap, -2, 4096)
    254 
    255     def test_tougher_find(self):
    256         # Do a tougher .find() test.  SF bug 515943 pointed out that, in 2.2,
    257         # searching for data with embedded \0 bytes didn't work.
    258         f = open(TESTFN, 'w+')
    259 
    260         data = 'aabaac\x00deef\x00\x00aa\x00'
    261         n = len(data)
    262         f.write(data)
    263         f.flush()
    264         m = mmap.mmap(f.fileno(), n)
    265         f.close()
    266 
    267         for start in range(n+1):
    268             for finish in range(start, n+1):
    269                 slice = data[start : finish]
    270                 self.assertEqual(m.find(slice), data.find(slice))
    271                 self.assertEqual(m.find(slice + 'x'), -1)
    272         m.close()
    273 
    274     def test_find_end(self):
    275         # test the new 'end' parameter works as expected
    276         f = open(TESTFN, 'w+')
    277         data = 'one two ones'
    278         n = len(data)
    279         f.write(data)
    280         f.flush()
    281         m = mmap.mmap(f.fileno(), n)
    282         f.close()
    283 
    284         self.assertEqual(m.find('one'), 0)
    285         self.assertEqual(m.find('ones'), 8)
    286         self.assertEqual(m.find('one', 0, -1), 0)
    287         self.assertEqual(m.find('one', 1), 8)
    288         self.assertEqual(m.find('one', 1, -1), 8)
    289         self.assertEqual(m.find('one', 1, -2), -1)
    290 
    291 
    292     def test_rfind(self):
    293         # test the new 'end' parameter works as expected
    294         f = open(TESTFN, 'w+')
    295         data = 'one two ones'
    296         n = len(data)
    297         f.write(data)
    298         f.flush()
    299         m = mmap.mmap(f.fileno(), n)
    300         f.close()
    301 
    302         self.assertEqual(m.rfind('one'), 8)
    303         self.assertEqual(m.rfind('one '), 0)
    304         self.assertEqual(m.rfind('one', 0, -1), 8)
    305         self.assertEqual(m.rfind('one', 0, -2), 0)
    306         self.assertEqual(m.rfind('one', 1, -1), 8)
    307         self.assertEqual(m.rfind('one', 1, -2), -1)
    308 
    309 
    310     def test_double_close(self):
    311         # make sure a double close doesn't crash on Solaris (Bug# 665913)
    312         f = open(TESTFN, 'w+')
    313 
    314         f.write(2**16 * 'a') # Arbitrary character
    315         f.close()
    316 
    317         f = open(TESTFN)
    318         mf = mmap.mmap(f.fileno(), 2**16, access=mmap.ACCESS_READ)
    319         mf.close()
    320         mf.close()
    321         f.close()
    322 
    323     @unittest.skipUnless(hasattr(os, "stat"), "needs os.stat()")
    324     def test_entire_file(self):
    325         # test mapping of entire file by passing 0 for map length
    326         f = open(TESTFN, "w+")
    327 
    328         f.write(2**16 * 'm') # Arbitrary character
    329         f.close()
    330 
    331         f = open(TESTFN, "rb+")
    332         mf = mmap.mmap(f.fileno(), 0)
    333         self.assertEqual(len(mf), 2**16, "Map size should equal file size.")
    334         self.assertEqual(mf.read(2**16), 2**16 * "m")
    335         mf.close()
    336         f.close()
    337 
    338     @unittest.skipUnless(hasattr(os, "stat"), "needs os.stat()")
    339     def test_length_0_offset(self):
    340         # Issue #10916: test mapping of remainder of file by passing 0 for
    341         # map length with an offset doesn't cause a segfault.
    342         # NOTE: allocation granularity is currently 65536 under Win64,
    343         # and therefore the minimum offset alignment.
    344         with open(TESTFN, "wb") as f:
    345             f.write((65536 * 2) * b'm') # Arbitrary character
    346 
    347         with open(TESTFN, "rb") as f:
    348             mf = mmap.mmap(f.fileno(), 0, offset=65536, access=mmap.ACCESS_READ)
    349             try:
    350                 self.assertRaises(IndexError, mf.__getitem__, 80000)
    351             finally:
    352                 mf.close()
    353 
    354     @unittest.skipUnless(hasattr(os, "stat"), "needs os.stat()")
    355     def test_length_0_large_offset(self):
    356         # Issue #10959: test mapping of a file by passing 0 for
    357         # map length with a large offset doesn't cause a segfault.
    358         with open(TESTFN, "wb") as f:
    359             f.write(115699 * b'm') # Arbitrary character
    360 
    361         with open(TESTFN, "w+b") as f:
    362             self.assertRaises(ValueError, mmap.mmap, f.fileno(), 0,
    363                               offset=2147418112)
    364 
    365     def test_move(self):
    366         # make move works everywhere (64-bit format problem earlier)
    367         f = open(TESTFN, 'w+')
    368 
    369         f.write("ABCDEabcde") # Arbitrary character
    370         f.flush()
    371 
    372         mf = mmap.mmap(f.fileno(), 10)
    373         mf.move(5, 0, 5)
    374         self.assertEqual(mf[:], "ABCDEABCDE", "Map move should have duplicated front 5")
    375         mf.close()
    376         f.close()
    377 
    378         # more excessive test
    379         data = "0123456789"
    380         for dest in range(len(data)):
    381             for src in range(len(data)):
    382                 for count in range(len(data) - max(dest, src)):
    383                     expected = data[:dest] + data[src:src+count] + data[dest+count:]
    384                     m = mmap.mmap(-1, len(data))
    385                     m[:] = data
    386                     m.move(dest, src, count)
    387                     self.assertEqual(m[:], expected)
    388                     m.close()
    389 
    390         # segfault test (Issue 5387)
    391         m = mmap.mmap(-1, 100)
    392         offsets = [-100, -1, 0, 1, 100]
    393         for source, dest, size in itertools.product(offsets, offsets, offsets):
    394             try:
    395                 m.move(source, dest, size)
    396             except ValueError:
    397                 pass
    398 
    399         offsets = [(-1, -1, -1), (-1, -1, 0), (-1, 0, -1), (0, -1, -1),
    400                    (-1, 0, 0), (0, -1, 0), (0, 0, -1)]
    401         for source, dest, size in offsets:
    402             self.assertRaises(ValueError, m.move, source, dest, size)
    403 
    404         m.close()
    405 
    406         m = mmap.mmap(-1, 1) # single byte
    407         self.assertRaises(ValueError, m.move, 0, 0, 2)
    408         self.assertRaises(ValueError, m.move, 1, 0, 1)
    409         self.assertRaises(ValueError, m.move, 0, 1, 1)
    410         m.move(0, 0, 1)
    411         m.move(0, 0, 0)
    412 
    413 
    414     def test_anonymous(self):
    415         # anonymous mmap.mmap(-1, PAGE)
    416         m = mmap.mmap(-1, PAGESIZE)
    417         for x in xrange(PAGESIZE):
    418             self.assertEqual(m[x], '\0', "anonymously mmap'ed contents should be zero")
    419 
    420         for x in xrange(PAGESIZE):
    421             m[x] = ch = chr(x & 255)
    422             self.assertEqual(m[x], ch)
    423 
    424     def test_extended_getslice(self):
    425         # Test extended slicing by comparing with list slicing.
    426         s = "".join(chr(c) for c in reversed(range(256)))
    427         m = mmap.mmap(-1, len(s))
    428         m[:] = s
    429         self.assertEqual(m[:], s)
    430         indices = (0, None, 1, 3, 19, 300, -1, -2, -31, -300)
    431         for start in indices:
    432             for stop in indices:
    433                 # Skip step 0 (invalid)
    434                 for step in indices[1:]:
    435                     self.assertEqual(m[start:stop:step],
    436                                      s[start:stop:step])
    437 
    438     def test_extended_set_del_slice(self):
    439         # Test extended slicing by comparing with list slicing.
    440         s = "".join(chr(c) for c in reversed(range(256)))
    441         m = mmap.mmap(-1, len(s))
    442         indices = (0, None, 1, 3, 19, 300, -1, -2, -31, -300)
    443         for start in indices:
    444             for stop in indices:
    445                 # Skip invalid step 0
    446                 for step in indices[1:]:
    447                     m[:] = s
    448                     self.assertEqual(m[:], s)
    449                     L = list(s)
    450                     # Make sure we have a slice of exactly the right length,
    451                     # but with different data.
    452                     data = L[start:stop:step]
    453                     data = "".join(reversed(data))
    454                     L[start:stop:step] = data
    455                     m[start:stop:step] = data
    456                     self.assertEqual(m[:], "".join(L))
    457 
    458     def make_mmap_file (self, f, halfsize):
    459         # Write 2 pages worth of data to the file
    460         f.write ('\0' * halfsize)
    461         f.write ('foo')
    462         f.write ('\0' * (halfsize - 3))
    463         f.flush ()
    464         return mmap.mmap (f.fileno(), 0)
    465 
    466     def test_empty_file (self):
    467         f = open (TESTFN, 'w+b')
    468         f.close()
    469         with open(TESTFN, "rb") as f :
    470             self.assertRaisesRegexp(ValueError,
    471                                    "cannot mmap an empty file",
    472                                    mmap.mmap, f.fileno(), 0,
    473                                    access=mmap.ACCESS_READ)
    474 
    475     def test_offset (self):
    476         f = open (TESTFN, 'w+b')
    477 
    478         try: # unlink TESTFN no matter what
    479             halfsize = mmap.ALLOCATIONGRANULARITY
    480             m = self.make_mmap_file (f, halfsize)
    481             m.close ()
    482             f.close ()
    483 
    484             mapsize = halfsize * 2
    485             # Try invalid offset
    486             f = open(TESTFN, "r+b")
    487             for offset in [-2, -1, None]:
    488                 try:
    489                     m = mmap.mmap(f.fileno(), mapsize, offset=offset)
    490                     self.assertEqual(0, 1)
    491                 except (ValueError, TypeError, OverflowError):
    492                     pass
    493                 else:
    494                     self.assertEqual(0, 0)
    495             f.close()
    496 
    497             # Try valid offset, hopefully 8192 works on all OSes
    498             f = open(TESTFN, "r+b")
    499             m = mmap.mmap(f.fileno(), mapsize - halfsize, offset=halfsize)
    500             self.assertEqual(m[0:3], 'foo')
    501             f.close()
    502 
    503             # Try resizing map
    504             try:
    505                 m.resize(512)
    506             except SystemError:
    507                 pass
    508             else:
    509                 # resize() is supported
    510                 self.assertEqual(len(m), 512)
    511                 # Check that we can no longer seek beyond the new size.
    512                 self.assertRaises(ValueError, m.seek, 513, 0)
    513                 # Check that the content is not changed
    514                 self.assertEqual(m[0:3], 'foo')
    515 
    516                 # Check that the underlying file is truncated too
    517                 f = open(TESTFN)
    518                 f.seek(0, 2)
    519                 self.assertEqual(f.tell(), halfsize + 512)
    520                 f.close()
    521                 self.assertEqual(m.size(), halfsize + 512)
    522 
    523             m.close()
    524 
    525         finally:
    526             f.close()
    527             try:
    528                 os.unlink(TESTFN)
    529             except OSError:
    530                 pass
    531 
    532     def test_subclass(self):
    533         class anon_mmap(mmap.mmap):
    534             def __new__(klass, *args, **kwargs):
    535                 return mmap.mmap.__new__(klass, -1, *args, **kwargs)
    536         anon_mmap(PAGESIZE)
    537 
    538     @unittest.skipUnless(hasattr(mmap, 'PROT_READ'), "needs mmap.PROT_READ")
    539     def test_prot_readonly(self):
    540         mapsize = 10
    541         open(TESTFN, "wb").write("a"*mapsize)
    542         f = open(TESTFN, "rb")
    543         m = mmap.mmap(f.fileno(), mapsize, prot=mmap.PROT_READ)
    544         self.assertRaises(TypeError, m.write, "foo")
    545         f.close()
    546 
    547     def test_error(self):
    548         self.assertTrue(issubclass(mmap.error, EnvironmentError))
    549         self.assertIn("mmap.error", str(mmap.error))
    550 
    551     def test_io_methods(self):
    552         data = "0123456789"
    553         open(TESTFN, "wb").write("x"*len(data))
    554         f = open(TESTFN, "r+b")
    555         m = mmap.mmap(f.fileno(), len(data))
    556         f.close()
    557         # Test write_byte()
    558         for i in xrange(len(data)):
    559             self.assertEqual(m.tell(), i)
    560             m.write_byte(data[i])
    561             self.assertEqual(m.tell(), i+1)
    562         self.assertRaises(ValueError, m.write_byte, "x")
    563         self.assertEqual(m[:], data)
    564         # Test read_byte()
    565         m.seek(0)
    566         for i in xrange(len(data)):
    567             self.assertEqual(m.tell(), i)
    568             self.assertEqual(m.read_byte(), data[i])
    569             self.assertEqual(m.tell(), i+1)
    570         self.assertRaises(ValueError, m.read_byte)
    571         # Test read()
    572         m.seek(3)
    573         self.assertEqual(m.read(3), "345")
    574         self.assertEqual(m.tell(), 6)
    575         # Test write()
    576         m.seek(3)
    577         m.write("bar")
    578         self.assertEqual(m.tell(), 6)
    579         self.assertEqual(m[:], "012bar6789")
    580         m.seek(8)
    581         self.assertRaises(ValueError, m.write, "bar")
    582 
    583     @unittest.skipUnless(os.name == 'nt', 'requires Windows')
    584     def test_tagname(self):
    585         data1 = "0123456789"
    586         data2 = "abcdefghij"
    587         assert len(data1) == len(data2)
    588 
    589         # Test same tag
    590         m1 = mmap.mmap(-1, len(data1), tagname="foo")
    591         m1[:] = data1
    592         m2 = mmap.mmap(-1, len(data2), tagname="foo")
    593         m2[:] = data2
    594         self.assertEqual(m1[:], data2)
    595         self.assertEqual(m2[:], data2)
    596         m2.close()
    597         m1.close()
    598 
    599         # Test different tag
    600         m1 = mmap.mmap(-1, len(data1), tagname="foo")
    601         m1[:] = data1
    602         m2 = mmap.mmap(-1, len(data2), tagname="boo")
    603         m2[:] = data2
    604         self.assertEqual(m1[:], data1)
    605         self.assertEqual(m2[:], data2)
    606         m2.close()
    607         m1.close()
    608 
    609     @cpython_only
    610     @unittest.skipUnless(os.name == 'nt', 'requires Windows')
    611     def test_sizeof(self):
    612         m1 = mmap.mmap(-1, 100)
    613         tagname = "foo"
    614         m2 = mmap.mmap(-1, 100, tagname=tagname)
    615         self.assertEqual(sys.getsizeof(m2),
    616                          sys.getsizeof(m1) + len(tagname) + 1)
    617 
    618     @unittest.skipUnless(os.name == 'nt', 'requires Windows')
    619     def test_crasher_on_windows(self):
    620         # Should not crash (Issue 1733986)
    621         m = mmap.mmap(-1, 1000, tagname="foo")
    622         try:
    623             mmap.mmap(-1, 5000, tagname="foo")[:] # same tagname, but larger size
    624         except:
    625             pass
    626         m.close()
    627 
    628         # Should not crash (Issue 5385)
    629         open(TESTFN, "wb").write("x"*10)
    630         f = open(TESTFN, "r+b")
    631         m = mmap.mmap(f.fileno(), 0)
    632         f.close()
    633         try:
    634             m.resize(0) # will raise WindowsError
    635         except:
    636             pass
    637         try:
    638             m[:]
    639         except:
    640             pass
    641         m.close()
    642 
    643     @unittest.skipUnless(os.name == 'nt', 'requires Windows')
    644     def test_invalid_descriptor(self):
    645         # socket file descriptors are valid, but out of range
    646         # for _get_osfhandle, causing a crash when validating the
    647         # parameters to _get_osfhandle.
    648         s = socket.socket()
    649         try:
    650             with self.assertRaises(mmap.error):
    651                 m = mmap.mmap(s.fileno(), 10)
    652         finally:
    653             s.close()
    654 
    655     @unittest.skipIf(os.name == 'nt', 'cannot resize anonymous mmaps on Windows')
    656     def test_resize_past_pos(self):
    657         m = mmap.mmap(-1, 8192)
    658         self.addCleanup(m.close)
    659         m.read(5000)
    660         try:
    661             m.resize(4096)
    662         except SystemError:
    663             self.skipTest("resizing not supported")
    664         self.assertEqual(m.read(14), '')
    665         self.assertRaises(ValueError, m.read_byte)
    666         self.assertRaises(ValueError, m.write_byte, 'b')
    667         self.assertRaises(ValueError, m.write, 'abc')
    668 
    669 
    670 class LargeMmapTests(unittest.TestCase):
    671 
    672     def setUp(self):
    673         unlink(TESTFN)
    674 
    675     def tearDown(self):
    676         unlink(TESTFN)
    677 
    678     def _make_test_file(self, num_zeroes, tail):
    679         if sys.platform[:3] == 'win' or sys.platform == 'darwin':
    680             requires('largefile',
    681                 'test requires %s bytes and a long time to run' % str(0x180000000))
    682         f = open(TESTFN, 'w+b')
    683         try:
    684             f.seek(num_zeroes)
    685             f.write(tail)
    686             f.flush()
    687         except (IOError, OverflowError):
    688             f.close()
    689             raise unittest.SkipTest("filesystem does not have largefile support")
    690         return f
    691 
    692     def test_large_offset(self):
    693         with self._make_test_file(0x14FFFFFFF, b" ") as f:
    694             m = mmap.mmap(f.fileno(), 0, offset=0x140000000, access=mmap.ACCESS_READ)
    695             try:
    696                 self.assertEqual(m[0xFFFFFFF], b" ")
    697             finally:
    698                 m.close()
    699 
    700     def test_large_filesize(self):
    701         with self._make_test_file(0x17FFFFFFF, b" ") as f:
    702             if sys.maxsize < 0x180000000:
    703                 # On 32 bit platforms the file is larger than sys.maxsize so
    704                 # mapping the whole file should fail -- Issue #16743
    705                 with self.assertRaises(OverflowError):
    706                     mmap.mmap(f.fileno(), 0x180000000, access=mmap.ACCESS_READ)
    707                 with self.assertRaises(ValueError):
    708                     mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
    709             m = mmap.mmap(f.fileno(), 0x10000, access=mmap.ACCESS_READ)
    710             try:
    711                 self.assertEqual(m.size(), 0x180000000)
    712             finally:
    713                 m.close()
    714 
    715     # Issue 11277: mmap() with large (~4GB) sparse files crashes on OS X.
    716 
    717     def _test_around_boundary(self, boundary):
    718         tail = b'  DEARdear  '
    719         start = boundary - len(tail) // 2
    720         end = start + len(tail)
    721         with self._make_test_file(start, tail) as f:
    722             m = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
    723             try:
    724                 self.assertEqual(m[start:end], tail)
    725             finally:
    726                 m.close()
    727 
    728     @unittest.skipUnless(sys.maxsize > _4G, "test cannot run on 32-bit systems")
    729     def test_around_2GB(self):
    730         self._test_around_boundary(_2G)
    731 
    732     @unittest.skipUnless(sys.maxsize > _4G, "test cannot run on 32-bit systems")
    733     def test_around_4GB(self):
    734         self._test_around_boundary(_4G)
    735 
    736 
    737 def test_main():
    738     run_unittest(MmapTests, LargeMmapTests)
    739 
    740 if __name__ == '__main__':
    741     test_main()
    742