14710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom test.test_support import (TESTFN, run_unittest, import_module, unlink,
24710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                               requires, _2G, _4G)
34710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport unittest
44710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport os, re, itertools, socket, sys
54710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
64710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmmap = import_module('mmap')
74710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
84710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPAGESIZE = mmap.PAGESIZE
94710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass MmapTests(unittest.TestCase):
114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def setUp(self):
134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if os.path.exists(TESTFN):
144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            os.unlink(TESTFN)
154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def tearDown(self):
174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            os.unlink(TESTFN)
194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except OSError:
204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            pass
214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_basic(self):
234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Test mmap module on Unix systems and Windows
244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Create a file to be mmap'ed.
264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f = open(TESTFN, 'w+')
274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Write 2 pages worth of data to the file
294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f.write('\0'* PAGESIZE)
304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f.write('foo')
314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f.write('\0'* (PAGESIZE-3) )
324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f.flush()
334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m = mmap.mmap(f.fileno(), 2 * PAGESIZE)
344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f.close()
354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Simple sanity checks
374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            tp = str(type(m))  # SF bug 128713:  segfaulted on Linux
394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(m.find('foo'), PAGESIZE)
404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(len(m), 2*PAGESIZE)
424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(m[0], '\0')
444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(m[0:3], '\0\0\0')
454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Shouldn't crash on boundary (Issue #5292)
474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(IndexError, m.__getitem__, len(m))
484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(IndexError, m.__setitem__, len(m), '\0')
494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Modify the file's content
514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m[0] = '3'
524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m[PAGESIZE +3: PAGESIZE +3+3] = 'bar'
534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Check that the modification worked
554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(m[0], '3')
564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(m[0:3], '3\0\0')
574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(m[PAGESIZE-1 : PAGESIZE + 7], '\0foobar\0')
584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m.flush()
604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Test doing a regular expression match in an mmap'ed file
624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            match = re.search('[A-Za-z]+', m)
634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if match is None:
644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.fail('regex match on mmap failed!')
654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            else:
664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                start, end = match.span(0)
674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                length = end - start
684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(start, PAGESIZE)
704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(end, PAGESIZE + 6)
714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # test seeking around (try to overflow the seek implementation)
734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m.seek(0,0)
744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(m.tell(), 0)
754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m.seek(42,1)
764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(m.tell(), 42)
774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m.seek(0,2)
784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(m.tell(), len(m))
794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Try to seek to negative position...
814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(ValueError, m.seek, -1)
824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Try to seek beyond end of mmap...
844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(ValueError, m.seek, 1, 2)
854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Try to seek to negative position...
874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(ValueError, m.seek, -len(m)-1, 2)
884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Try resizing map
904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                m.resize(512)
924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            except SystemError:
934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # resize() not supported
944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # No messages are printed, since the output of this test suite
954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # would then be different across platforms.
964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                pass
974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            else:
984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # resize() is supported
994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(len(m), 512)
1004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # Check that we can no longer seek beyond the new size.
1014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertRaises(ValueError, m.seek, 513, 0)
1024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # Check that the underlying file is truncated too
1044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # (bug #728515)
1054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                f = open(TESTFN)
1064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                f.seek(0, 2)
1074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(f.tell(), 512)
1084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                f.close()
1094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(m.size(), 512)
1104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m.close()
1124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        finally:
1144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
1154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                f.close()
1164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            except OSError:
1174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                pass
1184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_access_parameter(self):
1204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Test for "access" keyword parameter
1214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        mapsize = 10
1224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        open(TESTFN, "wb").write("a"*mapsize)
1234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f = open(TESTFN, "rb")
1244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m = mmap.mmap(f.fileno(), mapsize, access=mmap.ACCESS_READ)
1254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(m[:], 'a'*mapsize, "Readonly memory map data incorrect.")
1264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Ensuring that readonly mmap can't be slice assigned
1284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
1294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m[:] = 'b'*mapsize
1304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except TypeError:
1314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            pass
1324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
1334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.fail("Able to write to readonly memory map")
1344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Ensuring that readonly mmap can't be item assigned
1364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
1374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m[0] = 'b'
1384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except TypeError:
1394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            pass
1404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
1414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.fail("Able to write to readonly memory map")
1424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Ensuring that readonly mmap can't be write() to
1444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
1454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m.seek(0,0)
1464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m.write('abc')
1474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except TypeError:
1484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            pass
1494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
1504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.fail("Able to write to readonly memory map")
1514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Ensuring that readonly mmap can't be write_byte() to
1534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
1544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m.seek(0,0)
1554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m.write_byte('d')
1564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except TypeError:
1574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            pass
1584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
1594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.fail("Able to write to readonly memory map")
1604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Ensuring that readonly mmap can't be resized
1624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
1634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m.resize(2*mapsize)
1644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except SystemError:   # resize is not universally supported
1654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            pass
1664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except TypeError:
1674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            pass
1684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
1694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.fail("Able to resize readonly memory map")
1704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.close()
1714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        del m, f
1724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(open(TESTFN, "rb").read(), 'a'*mapsize,
1734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm               "Readonly memory map data file was modified")
1744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Opening mmap with size too big
1764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        import sys
1774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f = open(TESTFN, "r+b")
1784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
1794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m = mmap.mmap(f.fileno(), mapsize+1)
1804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except ValueError:
1814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # we do not expect a ValueError on Windows
1824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # CAUTION:  This also changes the size of the file on disk, and
1834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # later tests assume that the length hasn't changed.  We need to
1844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # repair that.
1854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if sys.platform.startswith('win'):
1864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.fail("Opening mmap with size+1 should work on Windows.")
1874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
1884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # we expect a ValueError on Unix, but not on Windows
1894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if not sys.platform.startswith('win'):
1904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.fail("Opening mmap with size+1 should raise ValueError.")
1914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m.close()
1924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.close()
1934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if sys.platform.startswith('win'):
1944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Repair damage from the resizing test.
1954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f = open(TESTFN, 'r+b')
1964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f.truncate(mapsize)
1974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f.close()
1984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Opening mmap with access=ACCESS_WRITE
2004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f = open(TESTFN, "r+b")
2014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m = mmap.mmap(f.fileno(), mapsize, access=mmap.ACCESS_WRITE)
2024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Modifying write-through memory map
2034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m[:] = 'c'*mapsize
2044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(m[:], 'c'*mapsize,
2054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm               "Write-through memory map memory not updated properly.")
2064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m.flush()
2074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m.close()
2084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.close()
2094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f = open(TESTFN, 'rb')
2104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        stuff = f.read()
2114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.close()
2124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(stuff, 'c'*mapsize,
2134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm               "Write-through memory map data file not updated properly.")
2144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Opening mmap with access=ACCESS_COPY
2164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f = open(TESTFN, "r+b")
2174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m = mmap.mmap(f.fileno(), mapsize, access=mmap.ACCESS_COPY)
2184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Modifying copy-on-write memory map
2194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m[:] = 'd'*mapsize
2204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(m[:], 'd' * mapsize,
2214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm               "Copy-on-write memory map data not written correctly.")
2224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m.flush()
2234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(open(TESTFN, "rb").read(), 'c'*mapsize,
2244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm               "Copy-on-write test data file should not be modified.")
2254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Ensuring copy-on-write maps cannot be resized
2264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, m.resize, 2*mapsize)
2274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.close()
2284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        del m, f
2294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Ensuring invalid access parameter raises exception
2314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f = open(TESTFN, "r+b")
2324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, mmap.mmap, f.fileno(), mapsize, access=4)
2334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.close()
2344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if os.name == "posix":
2364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Try incompatible flags, prot and access parameters.
2374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f = open(TESTFN, "r+b")
2384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(ValueError, mmap.mmap, f.fileno(), mapsize,
2394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                              flags=mmap.MAP_PRIVATE,
2404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                              prot=mmap.PROT_READ, access=mmap.ACCESS_WRITE)
2414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f.close()
2424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Try writing with PROT_EXEC and without PROT_WRITE
2444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            prot = mmap.PROT_READ | getattr(mmap, 'PROT_EXEC', 0)
2454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            with open(TESTFN, "r+b") as f:
2464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                m = mmap.mmap(f.fileno(), mapsize, prot=prot)
2474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertRaises(TypeError, m.write, b"abcdef")
2484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertRaises(TypeError, m.write_byte, 0)
2494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                m.close()
2504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_bad_file_desc(self):
2524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Try opening a bad file descriptor...
2534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(mmap.error, mmap.mmap, -2, 4096)
2544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_tougher_find(self):
2564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Do a tougher .find() test.  SF bug 515943 pointed out that, in 2.2,
2574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # searching for data with embedded \0 bytes didn't work.
2584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f = open(TESTFN, 'w+')
2594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        data = 'aabaac\x00deef\x00\x00aa\x00'
2614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        n = len(data)
2624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.write(data)
2634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.flush()
2644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m = mmap.mmap(f.fileno(), n)
2654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.close()
2664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for start in range(n+1):
2684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            for finish in range(start, n+1):
2694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                slice = data[start : finish]
2704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(m.find(slice), data.find(slice))
2714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(m.find(slice + 'x'), -1)
2724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m.close()
2734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_find_end(self):
2754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # test the new 'end' parameter works as expected
2764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f = open(TESTFN, 'w+')
2774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        data = 'one two ones'
2784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        n = len(data)
2794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.write(data)
2804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.flush()
2814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m = mmap.mmap(f.fileno(), n)
2824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.close()
2834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(m.find('one'), 0)
2854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(m.find('ones'), 8)
2864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(m.find('one', 0, -1), 0)
2874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(m.find('one', 1), 8)
2884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(m.find('one', 1, -1), 8)
2894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(m.find('one', 1, -2), -1)
2904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_rfind(self):
2934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # test the new 'end' parameter works as expected
2944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f = open(TESTFN, 'w+')
2954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        data = 'one two ones'
2964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        n = len(data)
2974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.write(data)
2984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.flush()
2994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m = mmap.mmap(f.fileno(), n)
3004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.close()
3014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(m.rfind('one'), 8)
3034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(m.rfind('one '), 0)
3044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(m.rfind('one', 0, -1), 8)
3054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(m.rfind('one', 0, -2), 0)
3064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(m.rfind('one', 1, -1), 8)
3074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(m.rfind('one', 1, -2), -1)
3084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_double_close(self):
3114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # make sure a double close doesn't crash on Solaris (Bug# 665913)
3124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f = open(TESTFN, 'w+')
3134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.write(2**16 * 'a') # Arbitrary character
3154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.close()
3164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f = open(TESTFN)
3184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        mf = mmap.mmap(f.fileno(), 2**16, access=mmap.ACCESS_READ)
3194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        mf.close()
3204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        mf.close()
3214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.close()
3224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_entire_file(self):
3244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # test mapping of entire file by passing 0 for map length
3254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if hasattr(os, "stat"):
3264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f = open(TESTFN, "w+")
3274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f.write(2**16 * 'm') # Arbitrary character
3294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f.close()
3304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f = open(TESTFN, "rb+")
3324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            mf = mmap.mmap(f.fileno(), 0)
3334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(len(mf), 2**16, "Map size should equal file size.")
3344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(mf.read(2**16), 2**16 * "m")
3354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            mf.close()
3364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f.close()
3374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_length_0_offset(self):
3394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Issue #10916: test mapping of remainder of file by passing 0 for
3404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # map length with an offset doesn't cause a segfault.
3414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if not hasattr(os, "stat"):
3424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.skipTest("needs os.stat")
3434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # NOTE: allocation granularity is currently 65536 under Win64,
3444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # and therefore the minimum offset alignment.
3454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with open(TESTFN, "wb") as f:
3464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f.write((65536 * 2) * b'm') # Arbitrary character
3474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with open(TESTFN, "rb") as f:
3494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            mf = mmap.mmap(f.fileno(), 0, offset=65536, access=mmap.ACCESS_READ)
3504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
3514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertRaises(IndexError, mf.__getitem__, 80000)
3524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            finally:
3534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                mf.close()
3544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_length_0_large_offset(self):
3564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Issue #10959: test mapping of a file by passing 0 for
3574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # map length with a large offset doesn't cause a segfault.
3584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if not hasattr(os, "stat"):
3594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.skipTest("needs os.stat")
3604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with open(TESTFN, "wb") as f:
3624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f.write(115699 * b'm') # Arbitrary character
3634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with open(TESTFN, "w+b") as f:
3654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(ValueError, mmap.mmap, f.fileno(), 0,
3664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                              offset=2147418112)
3674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_move(self):
3694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # make move works everywhere (64-bit format problem earlier)
3704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f = open(TESTFN, 'w+')
3714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.write("ABCDEabcde") # Arbitrary character
3734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.flush()
3744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        mf = mmap.mmap(f.fileno(), 10)
3764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        mf.move(5, 0, 5)
3774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(mf[:], "ABCDEABCDE", "Map move should have duplicated front 5")
3784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        mf.close()
3794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.close()
3804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # more excessive test
3824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        data = "0123456789"
3834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for dest in range(len(data)):
3844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            for src in range(len(data)):
3854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                for count in range(len(data) - max(dest, src)):
3864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    expected = data[:dest] + data[src:src+count] + data[dest+count:]
3874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    m = mmap.mmap(-1, len(data))
3884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    m[:] = data
3894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    m.move(dest, src, count)
3904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    self.assertEqual(m[:], expected)
3914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    m.close()
3924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # segfault test (Issue 5387)
3944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m = mmap.mmap(-1, 100)
3954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        offsets = [-100, -1, 0, 1, 100]
3964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for source, dest, size in itertools.product(offsets, offsets, offsets):
3974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
3984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                m.move(source, dest, size)
3994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            except ValueError:
4004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                pass
4014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        offsets = [(-1, -1, -1), (-1, -1, 0), (-1, 0, -1), (0, -1, -1),
4034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                   (-1, 0, 0), (0, -1, 0), (0, 0, -1)]
4044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for source, dest, size in offsets:
4054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(ValueError, m.move, source, dest, size)
4064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m.close()
4084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m = mmap.mmap(-1, 1) # single byte
4104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, m.move, 0, 0, 2)
4114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, m.move, 1, 0, 1)
4124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, m.move, 0, 1, 1)
4134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m.move(0, 0, 1)
4144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m.move(0, 0, 0)
4154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_anonymous(self):
4184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # anonymous mmap.mmap(-1, PAGE)
4194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m = mmap.mmap(-1, PAGESIZE)
4204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for x in xrange(PAGESIZE):
4214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(m[x], '\0', "anonymously mmap'ed contents should be zero")
4224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for x in xrange(PAGESIZE):
4244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m[x] = ch = chr(x & 255)
4254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(m[x], ch)
4264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_extended_getslice(self):
4284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Test extended slicing by comparing with list slicing.
4294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        s = "".join(chr(c) for c in reversed(range(256)))
4304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m = mmap.mmap(-1, len(s))
4314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m[:] = s
4324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(m[:], s)
4334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        indices = (0, None, 1, 3, 19, 300, -1, -2, -31, -300)
4344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for start in indices:
4354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            for stop in indices:
4364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # Skip step 0 (invalid)
4374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                for step in indices[1:]:
4384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    self.assertEqual(m[start:stop:step],
4394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                     s[start:stop:step])
4404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_extended_set_del_slice(self):
4424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Test extended slicing by comparing with list slicing.
4434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        s = "".join(chr(c) for c in reversed(range(256)))
4444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m = mmap.mmap(-1, len(s))
4454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        indices = (0, None, 1, 3, 19, 300, -1, -2, -31, -300)
4464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for start in indices:
4474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            for stop in indices:
4484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # Skip invalid step 0
4494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                for step in indices[1:]:
4504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    m[:] = s
4514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    self.assertEqual(m[:], s)
4524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    L = list(s)
4534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    # Make sure we have a slice of exactly the right length,
4544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    # but with different data.
4554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    data = L[start:stop:step]
4564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    data = "".join(reversed(data))
4574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    L[start:stop:step] = data
4584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    m[start:stop:step] = data
4594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    self.assertEqual(m[:], "".join(L))
4604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def make_mmap_file (self, f, halfsize):
4624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Write 2 pages worth of data to the file
4634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.write ('\0' * halfsize)
4644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.write ('foo')
4654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.write ('\0' * (halfsize - 3))
4664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.flush ()
4674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return mmap.mmap (f.fileno(), 0)
4684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_offset (self):
4704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f = open (TESTFN, 'w+b')
4714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try: # unlink TESTFN no matter what
4734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            halfsize = mmap.ALLOCATIONGRANULARITY
4744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m = self.make_mmap_file (f, halfsize)
4754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m.close ()
4764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f.close ()
4774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            mapsize = halfsize * 2
4794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Try invalid offset
4804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f = open(TESTFN, "r+b")
4814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            for offset in [-2, -1, None]:
4824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                try:
4834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    m = mmap.mmap(f.fileno(), mapsize, offset=offset)
4844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    self.assertEqual(0, 1)
4854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                except (ValueError, TypeError, OverflowError):
4864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    pass
4874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                else:
4884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    self.assertEqual(0, 0)
4894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f.close()
4904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Try valid offset, hopefully 8192 works on all OSes
4924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f = open(TESTFN, "r+b")
4934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m = mmap.mmap(f.fileno(), mapsize - halfsize, offset=halfsize)
4944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(m[0:3], 'foo')
4954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f.close()
4964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Try resizing map
4984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
4994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                m.resize(512)
5004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            except SystemError:
5014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                pass
5024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            else:
5034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # resize() is supported
5044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(len(m), 512)
5054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # Check that we can no longer seek beyond the new size.
5064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertRaises(ValueError, m.seek, 513, 0)
5074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # Check that the content is not changed
5084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(m[0:3], 'foo')
5094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # Check that the underlying file is truncated too
5114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                f = open(TESTFN)
5124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                f.seek(0, 2)
5134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(f.tell(), halfsize + 512)
5144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                f.close()
5154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(m.size(), halfsize + 512)
5164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m.close()
5184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        finally:
5204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f.close()
5214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
5224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                os.unlink(TESTFN)
5234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            except OSError:
5244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                pass
5254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_subclass(self):
5274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class anon_mmap(mmap.mmap):
5284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def __new__(klass, *args, **kwargs):
5294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return mmap.mmap.__new__(klass, -1, *args, **kwargs)
5304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        anon_mmap(PAGESIZE)
5314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_prot_readonly(self):
5334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if not hasattr(mmap, 'PROT_READ'):
5344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return
5354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        mapsize = 10
5364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        open(TESTFN, "wb").write("a"*mapsize)
5374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f = open(TESTFN, "rb")
5384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m = mmap.mmap(f.fileno(), mapsize, prot=mmap.PROT_READ)
5394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, m.write, "foo")
5404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.close()
5414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_error(self):
5434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(issubclass(mmap.error, EnvironmentError))
5444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertIn("mmap.error", str(mmap.error))
5454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_io_methods(self):
5474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        data = "0123456789"
5484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        open(TESTFN, "wb").write("x"*len(data))
5494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f = open(TESTFN, "r+b")
5504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m = mmap.mmap(f.fileno(), len(data))
5514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f.close()
5524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Test write_byte()
5534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for i in xrange(len(data)):
5544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(m.tell(), i)
5554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m.write_byte(data[i])
5564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(m.tell(), i+1)
5574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, m.write_byte, "x")
5584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(m[:], data)
5594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Test read_byte()
5604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m.seek(0)
5614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for i in xrange(len(data)):
5624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(m.tell(), i)
5634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(m.read_byte(), data[i])
5644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(m.tell(), i+1)
5654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, m.read_byte)
5664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Test read()
5674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m.seek(3)
5684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(m.read(3), "345")
5694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(m.tell(), 6)
5704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Test write()
5714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m.seek(3)
5724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m.write("bar")
5734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(m.tell(), 6)
5744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(m[:], "012bar6789")
5754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m.seek(8)
5764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, m.write, "bar")
5774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if os.name == 'nt':
5794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        def test_tagname(self):
5804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            data1 = "0123456789"
5814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            data2 = "abcdefghij"
5824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            assert len(data1) == len(data2)
5834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Test same tag
5854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m1 = mmap.mmap(-1, len(data1), tagname="foo")
5864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m1[:] = data1
5874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m2 = mmap.mmap(-1, len(data2), tagname="foo")
5884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m2[:] = data2
5894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(m1[:], data2)
5904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(m2[:], data2)
5914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m2.close()
5924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m1.close()
5934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Test different tag
5954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m1 = mmap.mmap(-1, len(data1), tagname="foo")
5964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m1[:] = data1
5974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m2 = mmap.mmap(-1, len(data2), tagname="boo")
5984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m2[:] = data2
5994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(m1[:], data1)
6004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(m2[:], data2)
6014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m2.close()
6024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m1.close()
6034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        def test_crasher_on_windows(self):
6054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Should not crash (Issue 1733986)
6064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m = mmap.mmap(-1, 1000, tagname="foo")
6074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
6084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                mmap.mmap(-1, 5000, tagname="foo")[:] # same tagname, but larger size
6094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            except:
6104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                pass
6114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m.close()
6124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Should not crash (Issue 5385)
6144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            open(TESTFN, "wb").write("x"*10)
6154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f = open(TESTFN, "r+b")
6164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m = mmap.mmap(f.fileno(), 0)
6174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f.close()
6184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
6194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                m.resize(0) # will raise WindowsError
6204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            except:
6214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                pass
6224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
6234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                m[:]
6244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            except:
6254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                pass
6264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m.close()
6274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        def test_invalid_descriptor(self):
6294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # socket file descriptors are valid, but out of range
6304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # for _get_osfhandle, causing a crash when validating the
6314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # parameters to _get_osfhandle.
6324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            s = socket.socket()
6334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
6344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                with self.assertRaises(mmap.error):
6354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    m = mmap.mmap(s.fileno(), 10)
6364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            finally:
6374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                s.close()
6384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass LargeMmapTests(unittest.TestCase):
6414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def setUp(self):
6434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        unlink(TESTFN)
6444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def tearDown(self):
6464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        unlink(TESTFN)
6474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def _make_test_file(self, num_zeroes, tail):
6494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if sys.platform[:3] == 'win' or sys.platform == 'darwin':
6504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            requires('largefile',
6514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'test requires %s bytes and a long time to run' % str(0x180000000))
6524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f = open(TESTFN, 'w+b')
6534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
6544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f.seek(num_zeroes)
6554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f.write(tail)
6564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f.flush()
6574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except (IOError, OverflowError):
6584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            f.close()
6594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            raise unittest.SkipTest("filesystem does not have largefile support")
6604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return f
6614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_large_offset(self):
6634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with self._make_test_file(0x14FFFFFFF, b" ") as f:
6644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m = mmap.mmap(f.fileno(), 0, offset=0x140000000, access=mmap.ACCESS_READ)
6654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
6664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(m[0xFFFFFFF], b" ")
6674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            finally:
6684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                m.close()
6694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_large_filesize(self):
6714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with self._make_test_file(0x17FFFFFFF, b" ") as f:
6724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m = mmap.mmap(f.fileno(), 0x10000, access=mmap.ACCESS_READ)
6734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
6744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(m.size(), 0x180000000)
6754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            finally:
6764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                m.close()
6774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # Issue 11277: mmap() with large (~4GB) sparse files crashes on OS X.
6794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def _test_around_boundary(self, boundary):
6814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        tail = b'  DEARdear  '
6824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        start = boundary - len(tail) // 2
6834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        end = start + len(tail)
6844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with self._make_test_file(start, tail) as f:
6854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            m = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
6864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
6874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(m[start:end], tail)
6884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            finally:
6894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                m.close()
6904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    @unittest.skipUnless(sys.maxsize > _4G, "test cannot run on 32-bit systems")
6924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_around_2GB(self):
6934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._test_around_boundary(_2G)
6944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    @unittest.skipUnless(sys.maxsize > _4G, "test cannot run on 32-bit systems")
6964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_around_4GB(self):
6974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._test_around_boundary(_4G)
6984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef test_main():
7014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    run_unittest(MmapTests, LargeMmapTests)
7024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmif __name__ == '__main__':
7044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    test_main()
705