summaryrefslogtreecommitdiff
path: root/Lib/test/test_mmap.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/test/test_mmap.py')
-rw-r--r--Lib/test/test_mmap.py178
1 files changed, 148 insertions, 30 deletions
diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py
index 5506956eb6..2c2863ebbe 100644
--- a/Lib/test/test_mmap.py
+++ b/Lib/test/test_mmap.py
@@ -1,7 +1,9 @@
-from test.test_support import TESTFN, run_unittest
-import mmap
+from test.test_support import (TESTFN, run_unittest, import_module, unlink,
+ requires, _2G, _4G)
import unittest
-import os, re, itertools
+import os, re, itertools, socket, sys
+
+mmap = import_module('mmap')
PAGESIZE = mmap.PAGESIZE
@@ -238,6 +240,14 @@ class MmapTests(unittest.TestCase):
prot=mmap.PROT_READ, access=mmap.ACCESS_WRITE)
f.close()
+ # Try writing with PROT_EXEC and without PROT_WRITE
+ prot = mmap.PROT_READ | getattr(mmap, 'PROT_EXEC', 0)
+ with open(TESTFN, "r+b") as f:
+ m = mmap.mmap(f.fileno(), mapsize, prot=prot)
+ self.assertRaises(TypeError, m.write, b"abcdef")
+ self.assertRaises(TypeError, m.write_byte, 0)
+ m.close()
+
def test_bad_file_desc(self):
# Try opening a bad file descriptor...
self.assertRaises(mmap.error, mmap.mmap, -2, 4096)
@@ -325,6 +335,36 @@ class MmapTests(unittest.TestCase):
mf.close()
f.close()
+ def test_length_0_offset(self):
+ # Issue #10916: test mapping of remainder of file by passing 0 for
+ # map length with an offset doesn't cause a segfault.
+ if not hasattr(os, "stat"):
+ self.skipTest("needs os.stat")
+ # NOTE: allocation granularity is currently 65536 under Win64,
+ # and therefore the minimum offset alignment.
+ with open(TESTFN, "wb") as f:
+ f.write((65536 * 2) * b'm') # Arbitrary character
+
+ with open(TESTFN, "rb") as f:
+ mf = mmap.mmap(f.fileno(), 0, offset=65536, access=mmap.ACCESS_READ)
+ try:
+ self.assertRaises(IndexError, mf.__getitem__, 80000)
+ finally:
+ mf.close()
+
+ def test_length_0_large_offset(self):
+ # Issue #10959: test mapping of a file by passing 0 for
+ # map length with a large offset doesn't cause a segfault.
+ if not hasattr(os, "stat"):
+ self.skipTest("needs os.stat")
+
+ with open(TESTFN, "wb") as f:
+ f.write(115699 * b'm') # Arbitrary character
+
+ with open(TESTFN, "w+b") as f:
+ self.assertRaises(ValueError, mmap.mmap, f.fileno(), 0,
+ offset=2147418112)
+
def test_move(self):
# make move works everywhere (64-bit format problem earlier)
f = open(TESTFN, 'w+')
@@ -358,15 +398,22 @@ class MmapTests(unittest.TestCase):
m.move(source, dest, size)
except ValueError:
pass
- self.assertRaises(ValueError, m.move, -1, -1, -1)
- self.assertRaises(ValueError, m.move, -1, -1, 0)
- self.assertRaises(ValueError, m.move, -1, 0, -1)
- self.assertRaises(ValueError, m.move, 0, -1, -1)
- self.assertRaises(ValueError, m.move, -1, 0, 0)
- self.assertRaises(ValueError, m.move, 0, -1, 0)
- self.assertRaises(ValueError, m.move, 0, 0, -1)
+
+ offsets = [(-1, -1, -1), (-1, -1, 0), (-1, 0, -1), (0, -1, -1),
+ (-1, 0, 0), (0, -1, 0), (0, 0, -1)]
+ for source, dest, size in offsets:
+ self.assertRaises(ValueError, m.move, source, dest, size)
+
m.close()
+ m = mmap.mmap(-1, 1) # single byte
+ self.assertRaises(ValueError, m.move, 0, 0, 2)
+ self.assertRaises(ValueError, m.move, 1, 0, 1)
+ self.assertRaises(ValueError, m.move, 0, 1, 1)
+ m.move(0, 0, 1)
+ m.move(0, 0, 0)
+
+
def test_anonymous(self):
# anonymous mmap.mmap(-1, PAGE)
m = mmap.mmap(-1, PAGESIZE)
@@ -409,7 +456,7 @@ class MmapTests(unittest.TestCase):
data = "".join(reversed(data))
L[start:stop:step] = data
m[start:stop:step] = data
- self.assertEquals(m[:], "".join(L))
+ self.assertEqual(m[:], "".join(L))
def make_mmap_file (self, f, halfsize):
# Write 2 pages worth of data to the file
@@ -493,8 +540,8 @@ class MmapTests(unittest.TestCase):
f.close()
def test_error(self):
- self.assert_(issubclass(mmap.error, EnvironmentError))
- self.assert_("mmap.error" in str(mmap.error))
+ self.assertTrue(issubclass(mmap.error, EnvironmentError))
+ self.assertIn("mmap.error", str(mmap.error))
def test_io_methods(self):
data = "0123456789"
@@ -504,27 +551,27 @@ class MmapTests(unittest.TestCase):
f.close()
# Test write_byte()
for i in xrange(len(data)):
- self.assertEquals(m.tell(), i)
- m.write_byte(data[i:i+1])
- self.assertEquals(m.tell(), i+1)
+ self.assertEqual(m.tell(), i)
+ m.write_byte(data[i])
+ self.assertEqual(m.tell(), i+1)
self.assertRaises(ValueError, m.write_byte, "x")
- self.assertEquals(m[:], data)
+ self.assertEqual(m[:], data)
# Test read_byte()
m.seek(0)
for i in xrange(len(data)):
- self.assertEquals(m.tell(), i)
- self.assertEquals(m.read_byte(), data[i:i+1])
- self.assertEquals(m.tell(), i+1)
+ self.assertEqual(m.tell(), i)
+ self.assertEqual(m.read_byte(), data[i])
+ self.assertEqual(m.tell(), i+1)
self.assertRaises(ValueError, m.read_byte)
# Test read()
m.seek(3)
- self.assertEquals(m.read(3), "345")
- self.assertEquals(m.tell(), 6)
+ self.assertEqual(m.read(3), "345")
+ self.assertEqual(m.tell(), 6)
# Test write()
m.seek(3)
m.write("bar")
- self.assertEquals(m.tell(), 6)
- self.assertEquals(m[:], "012bar6789")
+ self.assertEqual(m.tell(), 6)
+ self.assertEqual(m[:], "012bar6789")
m.seek(8)
self.assertRaises(ValueError, m.write, "bar")
@@ -539,18 +586,18 @@ class MmapTests(unittest.TestCase):
m1[:] = data1
m2 = mmap.mmap(-1, len(data2), tagname="foo")
m2[:] = data2
- self.assertEquals(m1[:], data2)
- self.assertEquals(m2[:], data2)
+ self.assertEqual(m1[:], data2)
+ self.assertEqual(m2[:], data2)
m2.close()
m1.close()
- # Test differnt tag
+ # Test different tag
m1 = mmap.mmap(-1, len(data1), tagname="foo")
m1[:] = data1
m2 = mmap.mmap(-1, len(data2), tagname="boo")
m2[:] = data2
- self.assertEquals(m1[:], data1)
- self.assertEquals(m2[:], data2)
+ self.assertEqual(m1[:], data1)
+ self.assertEqual(m2[:], data2)
m2.close()
m1.close()
@@ -578,9 +625,80 @@ class MmapTests(unittest.TestCase):
pass
m.close()
+ def test_invalid_descriptor(self):
+ # socket file descriptors are valid, but out of range
+ # for _get_osfhandle, causing a crash when validating the
+ # parameters to _get_osfhandle.
+ s = socket.socket()
+ try:
+ with self.assertRaises(mmap.error):
+ m = mmap.mmap(s.fileno(), 10)
+ finally:
+ s.close()
+
+
+class LargeMmapTests(unittest.TestCase):
+
+ def setUp(self):
+ unlink(TESTFN)
+
+ def tearDown(self):
+ unlink(TESTFN)
+
+ def _make_test_file(self, num_zeroes, tail):
+ if sys.platform[:3] == 'win' or sys.platform == 'darwin':
+ requires('largefile',
+ 'test requires %s bytes and a long time to run' % str(0x180000000))
+ f = open(TESTFN, 'w+b')
+ try:
+ f.seek(num_zeroes)
+ f.write(tail)
+ f.flush()
+ except (IOError, OverflowError):
+ f.close()
+ raise unittest.SkipTest("filesystem does not have largefile support")
+ return f
+
+ def test_large_offset(self):
+ with self._make_test_file(0x14FFFFFFF, b" ") as f:
+ m = mmap.mmap(f.fileno(), 0, offset=0x140000000, access=mmap.ACCESS_READ)
+ try:
+ self.assertEqual(m[0xFFFFFFF], b" ")
+ finally:
+ m.close()
+
+ def test_large_filesize(self):
+ with self._make_test_file(0x17FFFFFFF, b" ") as f:
+ m = mmap.mmap(f.fileno(), 0x10000, access=mmap.ACCESS_READ)
+ try:
+ self.assertEqual(m.size(), 0x180000000)
+ finally:
+ m.close()
+
+ # Issue 11277: mmap() with large (~4GB) sparse files crashes on OS X.
+
+ def _test_around_boundary(self, boundary):
+ tail = b' DEARdear '
+ start = boundary - len(tail) // 2
+ end = start + len(tail)
+ with self._make_test_file(start, tail) as f:
+ m = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
+ try:
+ self.assertEqual(m[start:end], tail)
+ finally:
+ m.close()
+
+ @unittest.skipUnless(sys.maxsize > _4G, "test cannot run on 32-bit systems")
+ def test_around_2GB(self):
+ self._test_around_boundary(_2G)
+
+ @unittest.skipUnless(sys.maxsize > _4G, "test cannot run on 32-bit systems")
+ def test_around_4GB(self):
+ self._test_around_boundary(_4G)
+
def test_main():
- run_unittest(MmapTests)
+ run_unittest(MmapTests, LargeMmapTests)
if __name__ == '__main__':
test_main()