diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py --- a/Lib/test/test_mmap.py +++ b/Lib/test/test_mmap.py @@ -1,4 +1,5 @@ -from test.test_support import TESTFN, run_unittest, import_module, unlink, requires +from test.test_support import TESTFN, run_unittest, import_module, unlink +from test.test_support import requires, _4G import unittest import os, re, itertools, socket, sys @@ -644,43 +645,80 @@ def tearDown(self): unlink(TESTFN) - def _working_largefile(self): - # Only run if the current filesystem supports large files. - f = open(TESTFN, 'wb', buffering=0) + def _test_splice(self, f, i): + # Test splicing with pages around "critical" values in respect to + # memory management + # Issue 11277: does mmap() force materialization of backing store? + m = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) try: - f.seek(0x80000001) - f.write(b'x') - f.flush() - except (IOError, OverflowError): - raise unittest.SkipTest("filesystem does not have largefile support") + # Memory page before xy + self.assertEqual(m[i+0:i+2], b' ') + # Memory page after xy + self.assertEqual(m[i+10:i+12], b' ') + # Cross pages + self.assertEqual(m[i+2:i+10], b'DEARdear') finally: - f.close() - unlink(TESTFN) + m.close() - def test_large_offset(self): + def _test_subscr(self, f, idx, expect): + # Test subscript for critical values like INT32_MAX, UINT32_MAX + m = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) + try: + self.assertEqual(m[idx], expect) + finally: + m.close() + + @unittest.skipUnless(sys.maxsize > _4G, "Can't run on a 32-bit system.") + def test_around_32bit_sbitflip(self): + start = 0x7FFFFFFA if sys.platform[:3] == 'win' or sys.platform == 'darwin': requires('largefile', - 'test requires %s bytes and a long time to run' % str(0x180000000)) - self._working_largefile() - with open(TESTFN, 'wb') as f: - f.seek(0x14FFFFFFF) - f.write(b" ") + 'test requires %s bytes and a long time to run' % + str(start+12)) + with open(TESTFN, 'w+b') as f: + try: + f.seek(start) + f.write(b' DEARdear ') + f.flush() + except (IOError, OverflowError): + raise unittest.SkipTest('filesystem does not have largefile ' + 'support') + self._test_splice(f, start) + self._test_subscr(f, start+len(b' DEA'), b'R') + self._test_subscr(f, start+len(b' DEARdea'), b'r') + unlink(TESTFN) - with open(TESTFN, 'rb') as f: - m = mmap.mmap(f.fileno(), 0, offset=0x140000000, access=mmap.ACCESS_READ) + @unittest.skipUnless(sys.maxsize > _4G, "Can't run on a 32-bit system.") + def test_around_32bit_excess(self): + start = 0xFFFFFFFA + if sys.platform[:3] == 'win' or sys.platform == 'darwin': + requires('largefile', + 'test requires %s bytes and a long time to run' % + str(start+12)) + with open(TESTFN, 'w+b') as f: try: - self.assertEqual(m[0xFFFFFFF], b" ") - finally: - m.close() + f.seek(start) + f.write(b' DEARdear ') + f.flush() + except (IOError, OverflowError): + raise unittest.SkipTest('filesystem does not have largefile ' + 'support') + self._test_splice(f, start) + self._test_subscr(f, start+len(b' DEA'), b'R') + self._test_subscr(f, start+len(b' DEARdea'), b'r') + unlink(TESTFN) def test_large_filesize(self): if sys.platform[:3] == 'win' or sys.platform == 'darwin': requires('largefile', 'test requires %s bytes and a long time to run' % str(0x180000000)) - self._working_largefile() with open(TESTFN, 'wb') as f: - f.seek(0x17FFFFFFF) - f.write(b" ") + try: + f.seek(0x17FFFFFFF) + f.write(b' ') + except (IOError, OverflowError): + raise unittest.SkipTest('filesystem does not have largefile ' + 'support') with open(TESTFN, 'rb') as f: m = mmap.mmap(f.fileno(), 0x10000, access=mmap.ACCESS_READ)