Home | History | Annotate | Download | only in test
      1 from test.test_support import (TESTFN, run_unittest, import_module, unlink,
      2                                requires, _2G, _4G)
      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     def test_entire_file(self):
    324         # test mapping of entire file by passing 0 for map length

    325         if hasattr(os, "stat"):
    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     def test_length_0_offset(self):
    339         # Issue #10916: test mapping of remainder of file by passing 0 for

    340         # map length with an offset doesn't cause a segfault.

    341         if not hasattr(os, "stat"):
    342             self.skipTest("needs os.stat")
    343         # NOTE: allocation granularity is currently 65536 under Win64,

    344         # and therefore the minimum offset alignment.

    345         with open(TESTFN, "wb") as f:
    346             f.write((65536 * 2) * b'm') # Arbitrary character

    347 
    348         with open(TESTFN, "rb") as f:
    349             mf = mmap.mmap(f.fileno(), 0, offset=65536, access=mmap.ACCESS_READ)
    350             try:
    351                 self.assertRaises(IndexError, mf.__getitem__, 80000)
    352             finally:
    353                 mf.close()
    354 
    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         if not hasattr(os, "stat"):
    359             self.skipTest("needs os.stat")
    360 
    361         with open(TESTFN, "wb") as f:
    362             f.write(115699 * b'm') # Arbitrary character

    363 
    364         with open(TESTFN, "w+b") as f:
    365             self.assertRaises(ValueError, mmap.mmap, f.fileno(), 0,
    366                               offset=2147418112)
    367 
    368     def test_move(self):
    369         # make move works everywhere (64-bit format problem earlier)

    370         f = open(TESTFN, 'w+')
    371 
    372         f.write("ABCDEabcde") # Arbitrary character

    373         f.flush()
    374 
    375         mf = mmap.mmap(f.fileno(), 10)
    376         mf.move(5, 0, 5)
    377         self.assertEqual(mf[:], "ABCDEABCDE", "Map move should have duplicated front 5")
    378         mf.close()
    379         f.close()
    380 
    381         # more excessive test

    382         data = "0123456789"
    383         for dest in range(len(data)):
    384             for src in range(len(data)):
    385                 for count in range(len(data) - max(dest, src)):
    386                     expected = data[:dest] + data[src:src+count] + data[dest+count:]
    387                     m = mmap.mmap(-1, len(data))
    388                     m[:] = data
    389                     m.move(dest, src, count)
    390                     self.assertEqual(m[:], expected)
    391                     m.close()
    392 
    393         # segfault test (Issue 5387)

    394         m = mmap.mmap(-1, 100)
    395         offsets = [-100, -1, 0, 1, 100]
    396         for source, dest, size in itertools.product(offsets, offsets, offsets):
    397             try:
    398                 m.move(source, dest, size)
    399             except ValueError:
    400                 pass
    401 
    402         offsets = [(-1, -1, -1), (-1, -1, 0), (-1, 0, -1), (0, -1, -1),
    403                    (-1, 0, 0), (0, -1, 0), (0, 0, -1)]
    404         for source, dest, size in offsets:
    405             self.assertRaises(ValueError, m.move, source, dest, size)
    406 
    407         m.close()
    408 
    409         m = mmap.mmap(-1, 1) # single byte

    410         self.assertRaises(ValueError, m.move, 0, 0, 2)
    411         self.assertRaises(ValueError, m.move, 1, 0, 1)
    412         self.assertRaises(ValueError, m.move, 0, 1, 1)
    413         m.move(0, 0, 1)
    414         m.move(0, 0, 0)
    415 
    416 
    417     def test_anonymous(self):
    418         # anonymous mmap.mmap(-1, PAGE)

    419         m = mmap.mmap(-1, PAGESIZE)
    420         for x in xrange(PAGESIZE):
    421             self.assertEqual(m[x], '\0', "anonymously mmap'ed contents should be zero")
    422 
    423         for x in xrange(PAGESIZE):
    424             m[x] = ch = chr(x & 255)
    425             self.assertEqual(m[x], ch)
    426 
    427     def test_extended_getslice(self):
    428         # Test extended slicing by comparing with list slicing.

    429         s = "".join(chr(c) for c in reversed(range(256)))
    430         m = mmap.mmap(-1, len(s))
    431         m[:] = s
    432         self.assertEqual(m[:], s)
    433         indices = (0, None, 1, 3, 19, 300, -1, -2, -31, -300)
    434         for start in indices:
    435             for stop in indices:
    436                 # Skip step 0 (invalid)

    437                 for step in indices[1:]:
    438                     self.assertEqual(m[start:stop:step],
    439                                      s[start:stop:step])
    440 
    441     def test_extended_set_del_slice(self):
    442         # Test extended slicing by comparing with list slicing.

    443         s = "".join(chr(c) for c in reversed(range(256)))
    444         m = mmap.mmap(-1, len(s))
    445         indices = (0, None, 1, 3, 19, 300, -1, -2, -31, -300)
    446         for start in indices:
    447             for stop in indices:
    448                 # Skip invalid step 0

    449                 for step in indices[1:]:
    450                     m[:] = s
    451                     self.assertEqual(m[:], s)
    452                     L = list(s)
    453                     # Make sure we have a slice of exactly the right length,

    454                     # but with different data.

    455                     data = L[start:stop:step]
    456                     data = "".join(reversed(data))
    457                     L[start:stop:step] = data
    458                     m[start:stop:step] = data
    459                     self.assertEqual(m[:], "".join(L))
    460 
    461     def make_mmap_file (self, f, halfsize):
    462         # Write 2 pages worth of data to the file

    463         f.write ('\0' * halfsize)
    464         f.write ('foo')
    465         f.write ('\0' * (halfsize - 3))
    466         f.flush ()
    467         return mmap.mmap (f.fileno(), 0)
    468 
    469     def test_offset (self):
    470         f = open (TESTFN, 'w+b')
    471 
    472         try: # unlink TESTFN no matter what

    473             halfsize = mmap.ALLOCATIONGRANULARITY
    474             m = self.make_mmap_file (f, halfsize)
    475             m.close ()
    476             f.close ()
    477 
    478             mapsize = halfsize * 2
    479             # Try invalid offset

    480             f = open(TESTFN, "r+b")
    481             for offset in [-2, -1, None]:
    482                 try:
    483                     m = mmap.mmap(f.fileno(), mapsize, offset=offset)
    484                     self.assertEqual(0, 1)
    485                 except (ValueError, TypeError, OverflowError):
    486                     pass
    487                 else:
    488                     self.assertEqual(0, 0)
    489             f.close()
    490 
    491             # Try valid offset, hopefully 8192 works on all OSes

    492             f = open(TESTFN, "r+b")
    493             m = mmap.mmap(f.fileno(), mapsize - halfsize, offset=halfsize)
    494             self.assertEqual(m[0:3], 'foo')
    495             f.close()
    496 
    497             # Try resizing map

    498             try:
    499                 m.resize(512)
    500             except SystemError:
    501                 pass
    502             else:
    503                 # resize() is supported

    504                 self.assertEqual(len(m), 512)
    505                 # Check that we can no longer seek beyond the new size.

    506                 self.assertRaises(ValueError, m.seek, 513, 0)
    507                 # Check that the content is not changed

    508                 self.assertEqual(m[0:3], 'foo')
    509 
    510                 # Check that the underlying file is truncated too

    511                 f = open(TESTFN)
    512                 f.seek(0, 2)
    513                 self.assertEqual(f.tell(), halfsize + 512)
    514                 f.close()
    515                 self.assertEqual(m.size(), halfsize + 512)
    516 
    517             m.close()
    518 
    519         finally:
    520             f.close()
    521             try:
    522                 os.unlink(TESTFN)
    523             except OSError:
    524                 pass
    525 
    526     def test_subclass(self):
    527         class anon_mmap(mmap.mmap):
    528             def __new__(klass, *args, **kwargs):
    529                 return mmap.mmap.__new__(klass, -1, *args, **kwargs)
    530         anon_mmap(PAGESIZE)
    531 
    532     def test_prot_readonly(self):
    533         if not hasattr(mmap, 'PROT_READ'):
    534             return
    535         mapsize = 10
    536         open(TESTFN, "wb").write("a"*mapsize)
    537         f = open(TESTFN, "rb")
    538         m = mmap.mmap(f.fileno(), mapsize, prot=mmap.PROT_READ)
    539         self.assertRaises(TypeError, m.write, "foo")
    540         f.close()
    541 
    542     def test_error(self):
    543         self.assertTrue(issubclass(mmap.error, EnvironmentError))
    544         self.assertIn("mmap.error", str(mmap.error))
    545 
    546     def test_io_methods(self):
    547         data = "0123456789"
    548         open(TESTFN, "wb").write("x"*len(data))
    549         f = open(TESTFN, "r+b")
    550         m = mmap.mmap(f.fileno(), len(data))
    551         f.close()
    552         # Test write_byte()

    553         for i in xrange(len(data)):
    554             self.assertEqual(m.tell(), i)
    555             m.write_byte(data[i])
    556             self.assertEqual(m.tell(), i+1)
    557         self.assertRaises(ValueError, m.write_byte, "x")
    558         self.assertEqual(m[:], data)
    559         # Test read_byte()

    560         m.seek(0)
    561         for i in xrange(len(data)):
    562             self.assertEqual(m.tell(), i)
    563             self.assertEqual(m.read_byte(), data[i])
    564             self.assertEqual(m.tell(), i+1)
    565         self.assertRaises(ValueError, m.read_byte)
    566         # Test read()

    567         m.seek(3)
    568         self.assertEqual(m.read(3), "345")
    569         self.assertEqual(m.tell(), 6)
    570         # Test write()

    571         m.seek(3)
    572         m.write("bar")
    573         self.assertEqual(m.tell(), 6)
    574         self.assertEqual(m[:], "012bar6789")
    575         m.seek(8)
    576         self.assertRaises(ValueError, m.write, "bar")
    577 
    578     if os.name == 'nt':
    579         def test_tagname(self):
    580             data1 = "0123456789"
    581             data2 = "abcdefghij"
    582             assert len(data1) == len(data2)
    583 
    584             # Test same tag

    585             m1 = mmap.mmap(-1, len(data1), tagname="foo")
    586             m1[:] = data1
    587             m2 = mmap.mmap(-1, len(data2), tagname="foo")
    588             m2[:] = data2
    589             self.assertEqual(m1[:], data2)
    590             self.assertEqual(m2[:], data2)
    591             m2.close()
    592             m1.close()
    593 
    594             # Test different tag

    595             m1 = mmap.mmap(-1, len(data1), tagname="foo")
    596             m1[:] = data1
    597             m2 = mmap.mmap(-1, len(data2), tagname="boo")
    598             m2[:] = data2
    599             self.assertEqual(m1[:], data1)
    600             self.assertEqual(m2[:], data2)
    601             m2.close()
    602             m1.close()
    603 
    604         def test_crasher_on_windows(self):
    605             # Should not crash (Issue 1733986)

    606             m = mmap.mmap(-1, 1000, tagname="foo")
    607             try:
    608                 mmap.mmap(-1, 5000, tagname="foo")[:] # same tagname, but larger size

    609             except:
    610                 pass
    611             m.close()
    612 
    613             # Should not crash (Issue 5385)

    614             open(TESTFN, "wb").write("x"*10)
    615             f = open(TESTFN, "r+b")
    616             m = mmap.mmap(f.fileno(), 0)
    617             f.close()
    618             try:
    619                 m.resize(0) # will raise WindowsError

    620             except:
    621                 pass
    622             try:
    623                 m[:]
    624             except:
    625                 pass
    626             m.close()
    627 
    628         def test_invalid_descriptor(self):
    629             # socket file descriptors are valid, but out of range

    630             # for _get_osfhandle, causing a crash when validating the

    631             # parameters to _get_osfhandle.

    632             s = socket.socket()
    633             try:
    634                 with self.assertRaises(mmap.error):
    635                     m = mmap.mmap(s.fileno(), 10)
    636             finally:
    637                 s.close()
    638 
    639 
    640 class LargeMmapTests(unittest.TestCase):
    641 
    642     def setUp(self):
    643         unlink(TESTFN)
    644 
    645     def tearDown(self):
    646         unlink(TESTFN)
    647 
    648     def _make_test_file(self, num_zeroes, tail):
    649         if sys.platform[:3] == 'win' or sys.platform == 'darwin':
    650             requires('largefile',
    651                 'test requires %s bytes and a long time to run' % str(0x180000000))
    652         f = open(TESTFN, 'w+b')
    653         try:
    654             f.seek(num_zeroes)
    655             f.write(tail)
    656             f.flush()
    657         except (IOError, OverflowError):
    658             f.close()
    659             raise unittest.SkipTest("filesystem does not have largefile support")
    660         return f
    661 
    662     def test_large_offset(self):
    663         with self._make_test_file(0x14FFFFFFF, b" ") as f:
    664             m = mmap.mmap(f.fileno(), 0, offset=0x140000000, access=mmap.ACCESS_READ)
    665             try:
    666                 self.assertEqual(m[0xFFFFFFF], b" ")
    667             finally:
    668                 m.close()
    669 
    670     def test_large_filesize(self):
    671         with self._make_test_file(0x17FFFFFFF, b" ") as f:
    672             m = mmap.mmap(f.fileno(), 0x10000, access=mmap.ACCESS_READ)
    673             try:
    674                 self.assertEqual(m.size(), 0x180000000)
    675             finally:
    676                 m.close()
    677 
    678     # Issue 11277: mmap() with large (~4GB) sparse files crashes on OS X.

    679 
    680     def _test_around_boundary(self, boundary):
    681         tail = b'  DEARdear  '
    682         start = boundary - len(tail) // 2
    683         end = start + len(tail)
    684         with self._make_test_file(start, tail) as f:
    685             m = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
    686             try:
    687                 self.assertEqual(m[start:end], tail)
    688             finally:
    689                 m.close()
    690 
    691     @unittest.skipUnless(sys.maxsize > _4G, "test cannot run on 32-bit systems")
    692     def test_around_2GB(self):
    693         self._test_around_boundary(_2G)
    694 
    695     @unittest.skipUnless(sys.maxsize > _4G, "test cannot run on 32-bit systems")
    696     def test_around_4GB(self):
    697         self._test_around_boundary(_4G)
    698 
    699 
    700 def test_main():
    701     run_unittest(MmapTests, LargeMmapTests)
    702 
    703 if __name__ == '__main__':
    704     test_main()
    705