blob: 8f34c182f82eaff48d5381b6e68a1fdcf5852bf1 [file] [log] [blame]
Hai Shia7f5d932020-08-04 00:41:24 +08001from test.support import (requires, _2G, _4G, gc_collect, cpython_only)
2from test.support.import_helper import import_module
3from test.support.os_helper import TESTFN, unlink
Thomas Wouters89f507f2006-12-13 04:49:30 +00004import unittest
Benjamin Peterson5dc8fab2010-10-31 01:44:49 +00005import os
6import re
7import itertools
8import socket
9import sys
Antoine Pitrouc53204b2013-08-05 23:17:30 +020010import weakref
Andrew M. Kuchlinge81b9cf2000-03-30 21:15:29 +000011
R. David Murraya21e4ca2009-03-31 23:16:50 +000012# Skip test if we can't import mmap.
13mmap = import_module('mmap')
14
Andrew M. Kuchlinge81b9cf2000-03-30 21:15:29 +000015PAGESIZE = mmap.PAGESIZE
16
Antoine Pitrou695b1dd2019-05-27 19:57:23 +020017
Thomas Wouters89f507f2006-12-13 04:49:30 +000018class MmapTests(unittest.TestCase):
Fred Drake004d5e62000-10-23 17:22:08 +000019
Thomas Wouters89f507f2006-12-13 04:49:30 +000020 def setUp(self):
21 if os.path.exists(TESTFN):
22 os.unlink(TESTFN)
Fred Drake004d5e62000-10-23 17:22:08 +000023
Thomas Wouters89f507f2006-12-13 04:49:30 +000024 def tearDown(self):
Tim Petersfd692082001-05-10 20:03:04 +000025 try:
Fred Drake62787992001-05-11 14:29:21 +000026 os.unlink(TESTFN)
Tim Petersfd692082001-05-10 20:03:04 +000027 except OSError:
28 pass
29
Thomas Wouters89f507f2006-12-13 04:49:30 +000030 def test_basic(self):
31 # Test mmap module on Unix systems and Windows
32
33 # Create a file to be mmap'ed.
Guido van Rossumb358a2c2007-07-16 19:29:02 +000034 f = open(TESTFN, 'bw+')
Thomas Wouters89f507f2006-12-13 04:49:30 +000035 try:
36 # Write 2 pages worth of data to the file
Guido van Rossumb358a2c2007-07-16 19:29:02 +000037 f.write(b'\0'* PAGESIZE)
38 f.write(b'foo')
39 f.write(b'\0'* (PAGESIZE-3) )
Thomas Wouters89f507f2006-12-13 04:49:30 +000040 f.flush()
41 m = mmap.mmap(f.fileno(), 2 * PAGESIZE)
Guido van Rossum456fe5d2007-07-16 19:42:05 +000042 finally:
Thomas Wouters89f507f2006-12-13 04:49:30 +000043 f.close()
44
Guido van Rossum456fe5d2007-07-16 19:42:05 +000045 # Simple sanity checks
Thomas Wouters89f507f2006-12-13 04:49:30 +000046
Guido van Rossum456fe5d2007-07-16 19:42:05 +000047 tp = str(type(m)) # SF bug 128713: segfaulted on Linux
Benjamin Petersone099b372009-04-04 17:09:35 +000048 self.assertEqual(m.find(b'foo'), PAGESIZE)
Thomas Wouters89f507f2006-12-13 04:49:30 +000049
Guido van Rossum456fe5d2007-07-16 19:42:05 +000050 self.assertEqual(len(m), 2*PAGESIZE)
Thomas Wouters89f507f2006-12-13 04:49:30 +000051
Guido van Rossum98297ee2007-11-06 21:34:58 +000052 self.assertEqual(m[0], 0)
Guido van Rossum456fe5d2007-07-16 19:42:05 +000053 self.assertEqual(m[0:3], b'\0\0\0')
Thomas Wouters89f507f2006-12-13 04:49:30 +000054
Hirokazu Yamamoto0654ccd2009-02-18 16:38:00 +000055 # Shouldn't crash on boundary (Issue #5292)
56 self.assertRaises(IndexError, m.__getitem__, len(m))
57 self.assertRaises(IndexError, m.__setitem__, len(m), b'\0')
58
Guido van Rossum456fe5d2007-07-16 19:42:05 +000059 # Modify the file's content
Guido van Rossum98297ee2007-11-06 21:34:58 +000060 m[0] = b'3'[0]
Guido van Rossum456fe5d2007-07-16 19:42:05 +000061 m[PAGESIZE +3: PAGESIZE +3+3] = b'bar'
Thomas Wouters89f507f2006-12-13 04:49:30 +000062
Guido van Rossum456fe5d2007-07-16 19:42:05 +000063 # Check that the modification worked
Guido van Rossum98297ee2007-11-06 21:34:58 +000064 self.assertEqual(m[0], b'3'[0])
Guido van Rossum456fe5d2007-07-16 19:42:05 +000065 self.assertEqual(m[0:3], b'3\0\0')
66 self.assertEqual(m[PAGESIZE-1 : PAGESIZE + 7], b'\0foobar\0')
Thomas Wouters89f507f2006-12-13 04:49:30 +000067
Guido van Rossum456fe5d2007-07-16 19:42:05 +000068 m.flush()
Thomas Wouters89f507f2006-12-13 04:49:30 +000069
Guido van Rossum456fe5d2007-07-16 19:42:05 +000070 # Test doing a regular expression match in an mmap'ed file
Antoine Pitroufd036452008-08-19 17:56:33 +000071 match = re.search(b'[A-Za-z]+', m)
Guido van Rossum456fe5d2007-07-16 19:42:05 +000072 if match is None:
73 self.fail('regex match on mmap failed!')
74 else:
75 start, end = match.span(0)
76 length = end - start
Thomas Wouters89f507f2006-12-13 04:49:30 +000077
Guido van Rossum456fe5d2007-07-16 19:42:05 +000078 self.assertEqual(start, PAGESIZE)
79 self.assertEqual(end, PAGESIZE + 6)
Thomas Wouters89f507f2006-12-13 04:49:30 +000080
Guido van Rossum456fe5d2007-07-16 19:42:05 +000081 # test seeking around (try to overflow the seek implementation)
82 m.seek(0,0)
83 self.assertEqual(m.tell(), 0)
84 m.seek(42,1)
85 self.assertEqual(m.tell(), 42)
86 m.seek(0,2)
87 self.assertEqual(m.tell(), len(m))
Thomas Wouters89f507f2006-12-13 04:49:30 +000088
Guido van Rossum456fe5d2007-07-16 19:42:05 +000089 # Try to seek to negative position...
90 self.assertRaises(ValueError, m.seek, -1)
Thomas Wouters89f507f2006-12-13 04:49:30 +000091
Guido van Rossum456fe5d2007-07-16 19:42:05 +000092 # Try to seek beyond end of mmap...
93 self.assertRaises(ValueError, m.seek, 1, 2)
Thomas Wouters89f507f2006-12-13 04:49:30 +000094
Guido van Rossum456fe5d2007-07-16 19:42:05 +000095 # Try to seek to negative position...
96 self.assertRaises(ValueError, m.seek, -len(m)-1, 2)
Thomas Wouters89f507f2006-12-13 04:49:30 +000097
Guido van Rossum456fe5d2007-07-16 19:42:05 +000098 # Try resizing map
99 try:
100 m.resize(512)
101 except SystemError:
102 # resize() not supported
103 # No messages are printed, since the output of this test suite
104 # would then be different across platforms.
105 pass
106 else:
107 # resize() is supported
108 self.assertEqual(len(m), 512)
109 # Check that we can no longer seek beyond the new size.
110 self.assertRaises(ValueError, m.seek, 513, 0)
111
112 # Check that the underlying file is truncated too
113 # (bug #728515)
Victor Stinnera6d2c762011-06-30 18:20:11 +0200114 f = open(TESTFN, 'rb')
Thomas Wouters89f507f2006-12-13 04:49:30 +0000115 try:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000116 f.seek(0, 2)
117 self.assertEqual(f.tell(), 512)
Guido van Rossum456fe5d2007-07-16 19:42:05 +0000118 finally:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000119 f.close()
Guido van Rossum456fe5d2007-07-16 19:42:05 +0000120 self.assertEqual(m.size(), 512)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000121
Guido van Rossum456fe5d2007-07-16 19:42:05 +0000122 m.close()
Thomas Wouters89f507f2006-12-13 04:49:30 +0000123
124 def test_access_parameter(self):
125 # Test for "access" keyword parameter
Tim Peters5ebfd362001-11-13 23:11:19 +0000126 mapsize = 10
Benjamin Peterson5dc8fab2010-10-31 01:44:49 +0000127 with open(TESTFN, "wb") as fp:
128 fp.write(b"a"*mapsize)
129 with open(TESTFN, "rb") as f:
130 m = mmap.mmap(f.fileno(), mapsize, access=mmap.ACCESS_READ)
131 self.assertEqual(m[:], b'a'*mapsize, "Readonly memory map data incorrect.")
Tim Peters5ebfd362001-11-13 23:11:19 +0000132
Benjamin Peterson5dc8fab2010-10-31 01:44:49 +0000133 # Ensuring that readonly mmap can't be slice assigned
134 try:
135 m[:] = b'b'*mapsize
136 except TypeError:
137 pass
138 else:
139 self.fail("Able to write to readonly memory map")
Tim Peters5ebfd362001-11-13 23:11:19 +0000140
Benjamin Peterson5dc8fab2010-10-31 01:44:49 +0000141 # Ensuring that readonly mmap can't be item assigned
142 try:
143 m[0] = b'b'
144 except TypeError:
145 pass
146 else:
147 self.fail("Able to write to readonly memory map")
Tim Peters5ebfd362001-11-13 23:11:19 +0000148
Benjamin Peterson5dc8fab2010-10-31 01:44:49 +0000149 # Ensuring that readonly mmap can't be write() to
150 try:
151 m.seek(0,0)
152 m.write(b'abc')
153 except TypeError:
154 pass
155 else:
156 self.fail("Able to write to readonly memory map")
Tim Peters5ebfd362001-11-13 23:11:19 +0000157
Benjamin Peterson5dc8fab2010-10-31 01:44:49 +0000158 # Ensuring that readonly mmap can't be write_byte() to
159 try:
160 m.seek(0,0)
161 m.write_byte(b'd')
162 except TypeError:
163 pass
164 else:
165 self.fail("Able to write to readonly memory map")
Tim Peters5ebfd362001-11-13 23:11:19 +0000166
Benjamin Peterson5dc8fab2010-10-31 01:44:49 +0000167 # Ensuring that readonly mmap can't be resized
168 try:
169 m.resize(2*mapsize)
170 except SystemError: # resize is not universally supported
171 pass
172 except TypeError:
173 pass
174 else:
175 self.fail("Able to resize readonly memory map")
176 with open(TESTFN, "rb") as fp:
177 self.assertEqual(fp.read(), b'a'*mapsize,
178 "Readonly memory map data file was modified")
Tim Peters5ebfd362001-11-13 23:11:19 +0000179
Thomas Wouters89f507f2006-12-13 04:49:30 +0000180 # Opening mmap with size too big
Benjamin Peterson5dc8fab2010-10-31 01:44:49 +0000181 with open(TESTFN, "r+b") as f:
182 try:
183 m = mmap.mmap(f.fileno(), mapsize+1)
184 except ValueError:
185 # we do not expect a ValueError on Windows
186 # CAUTION: This also changes the size of the file on disk, and
187 # later tests assume that the length hasn't changed. We need to
188 # repair that.
189 if sys.platform.startswith('win'):
190 self.fail("Opening mmap with size+1 should work on Windows.")
191 else:
192 # we expect a ValueError on Unix, but not on Windows
193 if not sys.platform.startswith('win'):
194 self.fail("Opening mmap with size+1 should raise ValueError.")
195 m.close()
Neal Norwitzb5673922002-09-05 21:48:07 +0000196 if sys.platform.startswith('win'):
Benjamin Peterson5dc8fab2010-10-31 01:44:49 +0000197 # Repair damage from the resizing test.
198 with open(TESTFN, 'r+b') as f:
199 f.truncate(mapsize)
Neal Norwitzb5673922002-09-05 21:48:07 +0000200
Thomas Wouters89f507f2006-12-13 04:49:30 +0000201 # Opening mmap with access=ACCESS_WRITE
Benjamin Peterson5dc8fab2010-10-31 01:44:49 +0000202 with open(TESTFN, "r+b") as f:
203 m = mmap.mmap(f.fileno(), mapsize, access=mmap.ACCESS_WRITE)
204 # Modifying write-through memory map
205 m[:] = b'c'*mapsize
206 self.assertEqual(m[:], b'c'*mapsize,
207 "Write-through memory map memory not updated properly.")
208 m.flush()
209 m.close()
210 with open(TESTFN, 'rb') as f:
211 stuff = f.read()
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000212 self.assertEqual(stuff, b'c'*mapsize,
Tim Peters5ebfd362001-11-13 23:11:19 +0000213 "Write-through memory map data file not updated properly.")
214
Thomas Wouters89f507f2006-12-13 04:49:30 +0000215 # Opening mmap with access=ACCESS_COPY
Benjamin Peterson5dc8fab2010-10-31 01:44:49 +0000216 with open(TESTFN, "r+b") as f:
217 m = mmap.mmap(f.fileno(), mapsize, access=mmap.ACCESS_COPY)
218 # Modifying copy-on-write memory map
219 m[:] = b'd'*mapsize
220 self.assertEqual(m[:], b'd' * mapsize,
221 "Copy-on-write memory map data not written correctly.")
222 m.flush()
223 with open(TESTFN, "rb") as fp:
224 self.assertEqual(fp.read(), b'c'*mapsize,
225 "Copy-on-write test data file should not be modified.")
226 # Ensuring copy-on-write maps cannot be resized
227 self.assertRaises(TypeError, m.resize, 2*mapsize)
228 m.close()
Thomas Wouters89f507f2006-12-13 04:49:30 +0000229
230 # Ensuring invalid access parameter raises exception
Benjamin Peterson5dc8fab2010-10-31 01:44:49 +0000231 with open(TESTFN, "r+b") as f:
232 self.assertRaises(ValueError, mmap.mmap, f.fileno(), mapsize, access=4)
Tim Peters5ebfd362001-11-13 23:11:19 +0000233
234 if os.name == "posix":
Tim Peters00cafa02001-11-13 23:39:47 +0000235 # Try incompatible flags, prot and access parameters.
Benjamin Peterson5dc8fab2010-10-31 01:44:49 +0000236 with open(TESTFN, "r+b") as f:
237 self.assertRaises(ValueError, mmap.mmap, f.fileno(), mapsize,
238 flags=mmap.MAP_PRIVATE,
239 prot=mmap.PROT_READ, access=mmap.ACCESS_WRITE)
Tim Peters5ebfd362001-11-13 23:11:19 +0000240
Antoine Pitrou7b50c2c2011-03-06 01:47:18 +0100241 # Try writing with PROT_EXEC and without PROT_WRITE
242 prot = mmap.PROT_READ | getattr(mmap, 'PROT_EXEC', 0)
Antoine Pitrou16a0a0b2011-03-06 01:11:03 +0100243 with open(TESTFN, "r+b") as f:
Antoine Pitrou7b50c2c2011-03-06 01:47:18 +0100244 m = mmap.mmap(f.fileno(), mapsize, prot=prot)
Antoine Pitrou16a0a0b2011-03-06 01:11:03 +0100245 self.assertRaises(TypeError, m.write, b"abcdef")
246 self.assertRaises(TypeError, m.write_byte, 0)
247 m.close()
248
Thomas Wouters89f507f2006-12-13 04:49:30 +0000249 def test_bad_file_desc(self):
250 # Try opening a bad file descriptor...
Andrew Svetlov6eda46d2012-12-17 22:55:31 +0200251 self.assertRaises(OSError, mmap.mmap, -2, 4096)
Neal Norwitz3b4fff82006-01-11 08:54:45 +0000252
Thomas Wouters89f507f2006-12-13 04:49:30 +0000253 def test_tougher_find(self):
254 # Do a tougher .find() test. SF bug 515943 pointed out that, in 2.2,
255 # searching for data with embedded \0 bytes didn't work.
Benjamin Peterson5dc8fab2010-10-31 01:44:49 +0000256 with open(TESTFN, 'wb+') as f:
Tim Petersc9ffa062002-03-08 05:43:32 +0000257
Benjamin Peterson5dc8fab2010-10-31 01:44:49 +0000258 data = b'aabaac\x00deef\x00\x00aa\x00'
259 n = len(data)
260 f.write(data)
261 f.flush()
262 m = mmap.mmap(f.fileno(), n)
Tim Petersc9ffa062002-03-08 05:43:32 +0000263
264 for start in range(n+1):
265 for finish in range(start, n+1):
266 slice = data[start : finish]
Thomas Wouters89f507f2006-12-13 04:49:30 +0000267 self.assertEqual(m.find(slice), data.find(slice))
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000268 self.assertEqual(m.find(slice + b'x'), -1)
Tim Petersddc82ea2003-01-13 21:38:45 +0000269 m.close()
Tim Petersc9ffa062002-03-08 05:43:32 +0000270
Georg Brandlfceab5a2008-01-19 20:08:23 +0000271 def test_find_end(self):
272 # test the new 'end' parameter works as expected
Serhiy Storchaka9e4861f2019-03-05 10:05:57 +0200273 with open(TESTFN, 'wb+') as f:
274 data = b'one two ones'
275 n = len(data)
276 f.write(data)
277 f.flush()
278 m = mmap.mmap(f.fileno(), n)
Georg Brandlfceab5a2008-01-19 20:08:23 +0000279
Benjamin Petersone099b372009-04-04 17:09:35 +0000280 self.assertEqual(m.find(b'one'), 0)
281 self.assertEqual(m.find(b'ones'), 8)
282 self.assertEqual(m.find(b'one', 0, -1), 0)
283 self.assertEqual(m.find(b'one', 1), 8)
284 self.assertEqual(m.find(b'one', 1, -1), 8)
285 self.assertEqual(m.find(b'one', 1, -2), -1)
Serhiy Storchaka8490f5a2015-03-20 09:00:36 +0200286 self.assertEqual(m.find(bytearray(b'one')), 0)
Georg Brandlfceab5a2008-01-19 20:08:23 +0000287
288
289 def test_rfind(self):
290 # test the new 'end' parameter works as expected
Serhiy Storchaka9e4861f2019-03-05 10:05:57 +0200291 with open(TESTFN, 'wb+') as f:
292 data = b'one two ones'
293 n = len(data)
294 f.write(data)
295 f.flush()
296 m = mmap.mmap(f.fileno(), n)
Georg Brandlfceab5a2008-01-19 20:08:23 +0000297
Benjamin Petersone099b372009-04-04 17:09:35 +0000298 self.assertEqual(m.rfind(b'one'), 8)
299 self.assertEqual(m.rfind(b'one '), 0)
300 self.assertEqual(m.rfind(b'one', 0, -1), 8)
301 self.assertEqual(m.rfind(b'one', 0, -2), 0)
302 self.assertEqual(m.rfind(b'one', 1, -1), 8)
303 self.assertEqual(m.rfind(b'one', 1, -2), -1)
Serhiy Storchaka8490f5a2015-03-20 09:00:36 +0200304 self.assertEqual(m.rfind(bytearray(b'one')), 8)
Georg Brandlfceab5a2008-01-19 20:08:23 +0000305
306
Thomas Wouters89f507f2006-12-13 04:49:30 +0000307 def test_double_close(self):
308 # make sure a double close doesn't crash on Solaris (Bug# 665913)
Serhiy Storchaka9e4861f2019-03-05 10:05:57 +0200309 with open(TESTFN, 'wb+') as f:
310 f.write(2**16 * b'a') # Arbitrary character
Tim Petersc9ffa062002-03-08 05:43:32 +0000311
Serhiy Storchaka9e4861f2019-03-05 10:05:57 +0200312 with open(TESTFN, 'rb') as f:
313 mf = mmap.mmap(f.fileno(), 2**16, access=mmap.ACCESS_READ)
314 mf.close()
315 mf.close()
Neal Norwitze604c022003-01-10 20:52:16 +0000316
Thomas Wouters89f507f2006-12-13 04:49:30 +0000317 def test_entire_file(self):
318 # test mapping of entire file by passing 0 for map length
Serhiy Storchaka9e4861f2019-03-05 10:05:57 +0200319 with open(TESTFN, "wb+") as f:
320 f.write(2**16 * b'm') # Arbitrary character
Tim Petersc9ffa062002-03-08 05:43:32 +0000321
Serhiy Storchaka9e4861f2019-03-05 10:05:57 +0200322 with open(TESTFN, "rb+") as f, \
323 mmap.mmap(f.fileno(), 0) as mf:
324 self.assertEqual(len(mf), 2**16, "Map size should equal file size.")
325 self.assertEqual(mf.read(2**16), 2**16 * b"m")
Martin v. Löwis7fe60c02005-03-03 11:22:44 +0000326
Antoine Pitrou85f46152011-01-15 16:17:07 +0000327 def test_length_0_offset(self):
328 # Issue #10916: test mapping of remainder of file by passing 0 for
329 # map length with an offset doesn't cause a segfault.
Antoine Pitroud0ebc752011-01-15 17:25:58 +0000330 # NOTE: allocation granularity is currently 65536 under Win64,
331 # and therefore the minimum offset alignment.
332 with open(TESTFN, "wb") as f:
333 f.write((65536 * 2) * b'm') # Arbitrary character
Antoine Pitrou85f46152011-01-15 16:17:07 +0000334
335 with open(TESTFN, "rb") as f:
Antoine Pitroud0ebc752011-01-15 17:25:58 +0000336 with mmap.mmap(f.fileno(), 0, offset=65536, access=mmap.ACCESS_READ) as mf:
337 self.assertRaises(IndexError, mf.__getitem__, 80000)
Antoine Pitrou85f46152011-01-15 16:17:07 +0000338
Antoine Pitrou305bc9e2011-01-20 21:07:24 +0000339 def test_length_0_large_offset(self):
340 # Issue #10959: test mapping of a file by passing 0 for
341 # map length with a large offset doesn't cause a segfault.
Antoine Pitrou305bc9e2011-01-20 21:07:24 +0000342 with open(TESTFN, "wb") as f:
343 f.write(115699 * b'm') # Arbitrary character
344
345 with open(TESTFN, "w+b") as f:
346 self.assertRaises(ValueError, mmap.mmap, f.fileno(), 0,
347 offset=2147418112)
348
Thomas Wouters89f507f2006-12-13 04:49:30 +0000349 def test_move(self):
350 # make move works everywhere (64-bit format problem earlier)
Serhiy Storchaka9e4861f2019-03-05 10:05:57 +0200351 with open(TESTFN, 'wb+') as f:
Tim Peterseba28be2005-03-28 01:08:02 +0000352
Serhiy Storchaka9e4861f2019-03-05 10:05:57 +0200353 f.write(b"ABCDEabcde") # Arbitrary character
354 f.flush()
Neal Norwitz8856fb72005-12-18 03:34:22 +0000355
Serhiy Storchaka9e4861f2019-03-05 10:05:57 +0200356 mf = mmap.mmap(f.fileno(), 10)
357 mf.move(5, 0, 5)
358 self.assertEqual(mf[:], b"ABCDEABCDE", "Map move should have duplicated front 5")
359 mf.close()
Neal Norwitz8856fb72005-12-18 03:34:22 +0000360
Hirokazu Yamamoto16caab02009-03-31 13:44:06 +0000361 # more excessive test
362 data = b"0123456789"
363 for dest in range(len(data)):
364 for src in range(len(data)):
365 for count in range(len(data) - max(dest, src)):
366 expected = data[:dest] + data[src:src+count] + data[dest+count:]
367 m = mmap.mmap(-1, len(data))
368 m[:] = data
369 m.move(dest, src, count)
370 self.assertEqual(m[:], expected)
371 m.close()
372
Hirokazu Yamamoto2ca15012009-03-31 20:43:56 +0000373 # segfault test (Issue 5387)
374 m = mmap.mmap(-1, 100)
375 offsets = [-100, -1, 0, 1, 100]
376 for source, dest, size in itertools.product(offsets, offsets, offsets):
377 try:
378 m.move(source, dest, size)
379 except ValueError:
380 pass
Benjamin Petersonef3e4c22009-04-11 19:48:14 +0000381
382 offsets = [(-1, -1, -1), (-1, -1, 0), (-1, 0, -1), (0, -1, -1),
383 (-1, 0, 0), (0, -1, 0), (0, 0, -1)]
384 for source, dest, size in offsets:
385 self.assertRaises(ValueError, m.move, source, dest, size)
386
Hirokazu Yamamoto16caab02009-03-31 13:44:06 +0000387 m.close()
388
Benjamin Petersonef3e4c22009-04-11 19:48:14 +0000389 m = mmap.mmap(-1, 1) # single byte
390 self.assertRaises(ValueError, m.move, 0, 0, 2)
391 self.assertRaises(ValueError, m.move, 1, 0, 1)
392 self.assertRaises(ValueError, m.move, 0, 1, 1)
393 m.move(0, 0, 1)
394 m.move(0, 0, 0)
395
396
Thomas Wouters89f507f2006-12-13 04:49:30 +0000397 def test_anonymous(self):
398 # anonymous mmap.mmap(-1, PAGE)
399 m = mmap.mmap(-1, PAGESIZE)
Guido van Rossum805365e2007-05-07 22:24:25 +0000400 for x in range(PAGESIZE):
Guido van Rossum98297ee2007-11-06 21:34:58 +0000401 self.assertEqual(m[x], 0,
402 "anonymously mmap'ed contents should be zero")
Neal Norwitz8856fb72005-12-18 03:34:22 +0000403
Guido van Rossum805365e2007-05-07 22:24:25 +0000404 for x in range(PAGESIZE):
Guido van Rossum98297ee2007-11-06 21:34:58 +0000405 b = x & 0xff
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000406 m[x] = b
407 self.assertEqual(m[x], b)
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +0000408
Charles-François Natali4dd453c2011-06-08 19:18:14 +0200409 def test_read_all(self):
410 m = mmap.mmap(-1, 16)
411 self.addCleanup(m.close)
412
413 # With no parameters, or None or a negative argument, reads all
414 m.write(bytes(range(16)))
415 m.seek(0)
416 self.assertEqual(m.read(), bytes(range(16)))
417 m.seek(8)
418 self.assertEqual(m.read(), bytes(range(8, 16)))
419 m.seek(16)
420 self.assertEqual(m.read(), b'')
421 m.seek(3)
422 self.assertEqual(m.read(None), bytes(range(3, 16)))
423 m.seek(4)
424 self.assertEqual(m.read(-1), bytes(range(4, 16)))
425 m.seek(5)
426 self.assertEqual(m.read(-2), bytes(range(5, 16)))
427 m.seek(9)
428 self.assertEqual(m.read(-42), bytes(range(9, 16)))
429
430 def test_read_invalid_arg(self):
431 m = mmap.mmap(-1, 16)
432 self.addCleanup(m.close)
433
434 self.assertRaises(TypeError, m.read, 'foo')
435 self.assertRaises(TypeError, m.read, 5.5)
436 self.assertRaises(TypeError, m.read, [1, 2, 3])
437
Thomas Woutersed03b412007-08-28 21:37:11 +0000438 def test_extended_getslice(self):
439 # Test extended slicing by comparing with list slicing.
440 s = bytes(reversed(range(256)))
441 m = mmap.mmap(-1, len(s))
442 m[:] = s
443 self.assertEqual(m[:], s)
Zackery Spytz14514d92019-05-17 01:13:03 -0600444 indices = (0, None, 1, 3, 19, 300, sys.maxsize, -1, -2, -31, -300)
Thomas Woutersed03b412007-08-28 21:37:11 +0000445 for start in indices:
446 for stop in indices:
447 # Skip step 0 (invalid)
448 for step in indices[1:]:
449 self.assertEqual(m[start:stop:step],
450 s[start:stop:step])
451
452 def test_extended_set_del_slice(self):
453 # Test extended slicing by comparing with list slicing.
454 s = bytes(reversed(range(256)))
455 m = mmap.mmap(-1, len(s))
Zackery Spytz14514d92019-05-17 01:13:03 -0600456 indices = (0, None, 1, 3, 19, 300, sys.maxsize, -1, -2, -31, -300)
Thomas Woutersed03b412007-08-28 21:37:11 +0000457 for start in indices:
458 for stop in indices:
459 # Skip invalid step 0
460 for step in indices[1:]:
461 m[:] = s
462 self.assertEqual(m[:], s)
463 L = list(s)
464 # Make sure we have a slice of exactly the right length,
465 # but with different data.
466 data = L[start:stop:step]
467 data = bytes(reversed(data))
468 L[start:stop:step] = data
469 m[start:stop:step] = data
Ezio Melottib3aedd42010-11-20 19:04:17 +0000470 self.assertEqual(m[:], bytes(L))
Thomas Woutersed03b412007-08-28 21:37:11 +0000471
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000472 def make_mmap_file (self, f, halfsize):
473 # Write 2 pages worth of data to the file
474 f.write (b'\0' * halfsize)
475 f.write (b'foo')
476 f.write (b'\0' * (halfsize - 3))
477 f.flush ()
478 return mmap.mmap (f.fileno(), 0)
479
Jesus Cea941bfcc2012-09-10 00:27:55 +0200480 def test_empty_file (self):
481 f = open (TESTFN, 'w+b')
482 f.close()
Jesus Cea1f2799b2012-09-10 22:49:50 +0200483 with open(TESTFN, "rb") as f :
484 self.assertRaisesRegex(ValueError,
485 "cannot mmap an empty file",
486 mmap.mmap, f.fileno(), 0,
487 access=mmap.ACCESS_READ)
Jesus Cea941bfcc2012-09-10 00:27:55 +0200488
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000489 def test_offset (self):
490 f = open (TESTFN, 'w+b')
491
492 try: # unlink TESTFN no matter what
493 halfsize = mmap.ALLOCATIONGRANULARITY
494 m = self.make_mmap_file (f, halfsize)
495 m.close ()
496 f.close ()
497
498 mapsize = halfsize * 2
499 # Try invalid offset
500 f = open(TESTFN, "r+b")
501 for offset in [-2, -1, None]:
502 try:
503 m = mmap.mmap(f.fileno(), mapsize, offset=offset)
504 self.assertEqual(0, 1)
505 except (ValueError, TypeError, OverflowError):
506 pass
507 else:
508 self.assertEqual(0, 0)
509 f.close()
510
511 # Try valid offset, hopefully 8192 works on all OSes
512 f = open(TESTFN, "r+b")
513 m = mmap.mmap(f.fileno(), mapsize - halfsize, offset=halfsize)
514 self.assertEqual(m[0:3], b'foo')
515 f.close()
Hirokazu Yamamoto0654ccd2009-02-18 16:38:00 +0000516
517 # Try resizing map
518 try:
519 m.resize(512)
520 except SystemError:
521 pass
522 else:
523 # resize() is supported
524 self.assertEqual(len(m), 512)
525 # Check that we can no longer seek beyond the new size.
526 self.assertRaises(ValueError, m.seek, 513, 0)
527 # Check that the content is not changed
528 self.assertEqual(m[0:3], b'foo')
529
530 # Check that the underlying file is truncated too
Victor Stinnera6d2c762011-06-30 18:20:11 +0200531 f = open(TESTFN, 'rb')
Hirokazu Yamamoto0654ccd2009-02-18 16:38:00 +0000532 f.seek(0, 2)
533 self.assertEqual(f.tell(), halfsize + 512)
534 f.close()
535 self.assertEqual(m.size(), halfsize + 512)
536
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000537 m.close()
538
539 finally:
540 f.close()
541 try:
542 os.unlink(TESTFN)
543 except OSError:
544 pass
545
Christian Heimes1af737c2008-01-23 08:24:23 +0000546 def test_subclass(self):
547 class anon_mmap(mmap.mmap):
548 def __new__(klass, *args, **kwargs):
549 return mmap.mmap.__new__(klass, -1, *args, **kwargs)
550 anon_mmap(PAGESIZE)
551
Serhiy Storchaka43767632013-11-03 21:31:38 +0200552 @unittest.skipUnless(hasattr(mmap, 'PROT_READ'), "needs mmap.PROT_READ")
Christian Heimesa156e092008-02-16 07:38:31 +0000553 def test_prot_readonly(self):
554 mapsize = 10
Benjamin Peterson5dc8fab2010-10-31 01:44:49 +0000555 with open(TESTFN, "wb") as fp:
556 fp.write(b"a"*mapsize)
Serhiy Storchaka9e4861f2019-03-05 10:05:57 +0200557 with open(TESTFN, "rb") as f:
558 m = mmap.mmap(f.fileno(), mapsize, prot=mmap.PROT_READ)
559 self.assertRaises(TypeError, m.write, "foo")
Christian Heimes1af737c2008-01-23 08:24:23 +0000560
Christian Heimes7131fd92008-02-19 14:21:46 +0000561 def test_error(self):
Antoine Pitrou6b4883d2011-10-12 02:54:14 +0200562 self.assertIs(mmap.error, OSError)
Christian Heimes7131fd92008-02-19 14:21:46 +0000563
Hirokazu Yamamoto39c6dea2009-02-28 10:56:50 +0000564 def test_io_methods(self):
565 data = b"0123456789"
Benjamin Peterson5dc8fab2010-10-31 01:44:49 +0000566 with open(TESTFN, "wb") as fp:
567 fp.write(b"x"*len(data))
Serhiy Storchaka9e4861f2019-03-05 10:05:57 +0200568 with open(TESTFN, "r+b") as f:
569 m = mmap.mmap(f.fileno(), len(data))
Hirokazu Yamamoto39c6dea2009-02-28 10:56:50 +0000570 # Test write_byte()
571 for i in range(len(data)):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000572 self.assertEqual(m.tell(), i)
Benjamin Petersone099b372009-04-04 17:09:35 +0000573 m.write_byte(data[i])
Ezio Melottib3aedd42010-11-20 19:04:17 +0000574 self.assertEqual(m.tell(), i+1)
Benjamin Petersone099b372009-04-04 17:09:35 +0000575 self.assertRaises(ValueError, m.write_byte, b"x"[0])
Ezio Melottib3aedd42010-11-20 19:04:17 +0000576 self.assertEqual(m[:], data)
Hirokazu Yamamoto39c6dea2009-02-28 10:56:50 +0000577 # Test read_byte()
578 m.seek(0)
579 for i in range(len(data)):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000580 self.assertEqual(m.tell(), i)
581 self.assertEqual(m.read_byte(), data[i])
582 self.assertEqual(m.tell(), i+1)
Hirokazu Yamamoto39c6dea2009-02-28 10:56:50 +0000583 self.assertRaises(ValueError, m.read_byte)
584 # Test read()
585 m.seek(3)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000586 self.assertEqual(m.read(3), b"345")
587 self.assertEqual(m.tell(), 6)
Hirokazu Yamamoto39c6dea2009-02-28 10:56:50 +0000588 # Test write()
589 m.seek(3)
590 m.write(b"bar")
Ezio Melottib3aedd42010-11-20 19:04:17 +0000591 self.assertEqual(m.tell(), 6)
592 self.assertEqual(m[:], b"012bar6789")
Serhiy Storchaka8490f5a2015-03-20 09:00:36 +0200593 m.write(bytearray(b"baz"))
594 self.assertEqual(m.tell(), 9)
595 self.assertEqual(m[:], b"012barbaz9")
596 self.assertRaises(ValueError, m.write, b"ba")
Hirokazu Yamamoto39c6dea2009-02-28 10:56:50 +0000597
Hirokazu Yamamoto3cdd5cb2010-11-04 12:09:08 +0000598 def test_non_ascii_byte(self):
599 for b in (129, 200, 255): # > 128
600 m = mmap.mmap(-1, 1)
601 m.write_byte(b)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000602 self.assertEqual(m[0], b)
Hirokazu Yamamoto3cdd5cb2010-11-04 12:09:08 +0000603 m.seek(0)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000604 self.assertEqual(m.read_byte(), b)
Hirokazu Yamamoto3cdd5cb2010-11-04 12:09:08 +0000605 m.close()
606
Serhiy Storchaka43767632013-11-03 21:31:38 +0200607 @unittest.skipUnless(os.name == 'nt', 'requires Windows')
608 def test_tagname(self):
609 data1 = b"0123456789"
610 data2 = b"abcdefghij"
611 assert len(data1) == len(data2)
Hirokazu Yamamoto8e722bc2009-03-05 14:33:01 +0000612
Serhiy Storchaka43767632013-11-03 21:31:38 +0200613 # Test same tag
614 m1 = mmap.mmap(-1, len(data1), tagname="foo")
615 m1[:] = data1
616 m2 = mmap.mmap(-1, len(data2), tagname="foo")
617 m2[:] = data2
618 self.assertEqual(m1[:], data2)
619 self.assertEqual(m2[:], data2)
620 m2.close()
621 m1.close()
Hirokazu Yamamoto8e722bc2009-03-05 14:33:01 +0000622
Serhiy Storchaka43767632013-11-03 21:31:38 +0200623 # Test different tag
624 m1 = mmap.mmap(-1, len(data1), tagname="foo")
625 m1[:] = data1
626 m2 = mmap.mmap(-1, len(data2), tagname="boo")
627 m2[:] = data2
628 self.assertEqual(m1[:], data1)
629 self.assertEqual(m2[:], data2)
630 m2.close()
631 m1.close()
Hirokazu Yamamoto10c99372009-02-28 12:21:53 +0000632
Serhiy Storchaka76b47652014-08-19 17:11:20 +0300633 @cpython_only
634 @unittest.skipUnless(os.name == 'nt', 'requires Windows')
635 def test_sizeof(self):
636 m1 = mmap.mmap(-1, 100)
637 tagname = "foo"
638 m2 = mmap.mmap(-1, 100, tagname=tagname)
Serhiy Storchaka996c3de2014-08-19 18:20:23 +0300639 self.assertEqual(sys.getsizeof(m2),
640 sys.getsizeof(m1) + len(tagname) + 1)
Serhiy Storchaka76b47652014-08-19 17:11:20 +0300641
Serhiy Storchaka43767632013-11-03 21:31:38 +0200642 @unittest.skipUnless(os.name == 'nt', 'requires Windows')
643 def test_crasher_on_windows(self):
644 # Should not crash (Issue 1733986)
645 m = mmap.mmap(-1, 1000, tagname="foo")
646 try:
647 mmap.mmap(-1, 5000, tagname="foo")[:] # same tagname, but larger size
648 except:
649 pass
650 m.close()
Hirokazu Yamamoto8e722bc2009-03-05 14:33:01 +0000651
Serhiy Storchaka43767632013-11-03 21:31:38 +0200652 # Should not crash (Issue 5385)
653 with open(TESTFN, "wb") as fp:
654 fp.write(b"x"*10)
655 f = open(TESTFN, "r+b")
656 m = mmap.mmap(f.fileno(), 0)
657 f.close()
658 try:
659 m.resize(0) # will raise OSError
660 except:
661 pass
662 try:
663 m[:]
664 except:
665 pass
666 m.close()
Hirokazu Yamamoto8e722bc2009-03-05 14:33:01 +0000667
Serhiy Storchaka43767632013-11-03 21:31:38 +0200668 @unittest.skipUnless(os.name == 'nt', 'requires Windows')
669 def test_invalid_descriptor(self):
670 # socket file descriptors are valid, but out of range
671 # for _get_osfhandle, causing a crash when validating the
672 # parameters to _get_osfhandle.
673 s = socket.socket()
674 try:
675 with self.assertRaises(OSError):
676 m = mmap.mmap(s.fileno(), 10)
677 finally:
678 s.close()
Brian Curtinea47eaa2010-08-01 15:26:26 +0000679
Georg Brandl0bccc182010-08-01 14:50:00 +0000680 def test_context_manager(self):
681 with mmap.mmap(-1, 10) as m:
682 self.assertFalse(m.closed)
683 self.assertTrue(m.closed)
684
685 def test_context_manager_exception(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200686 # Test that the OSError gets passed through
Georg Brandl0bccc182010-08-01 14:50:00 +0000687 with self.assertRaises(Exception) as exc:
688 with mmap.mmap(-1, 10) as m:
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200689 raise OSError
690 self.assertIsInstance(exc.exception, OSError,
Georg Brandl0bccc182010-08-01 14:50:00 +0000691 "wrong exception raised in context manager")
692 self.assertTrue(m.closed, "context manager failed")
693
Antoine Pitrouc53204b2013-08-05 23:17:30 +0200694 def test_weakref(self):
695 # Check mmap objects are weakrefable
696 mm = mmap.mmap(-1, 16)
697 wr = weakref.ref(mm)
698 self.assertIs(wr(), mm)
699 del mm
700 gc_collect()
701 self.assertIs(wr(), None)
702
Berker Peksag6282e652016-03-02 19:30:18 +0200703 def test_write_returning_the_number_of_bytes_written(self):
704 mm = mmap.mmap(-1, 16)
705 self.assertEqual(mm.write(b""), 0)
706 self.assertEqual(mm.write(b"x"), 1)
707 self.assertEqual(mm.write(b"yz"), 2)
708 self.assertEqual(mm.write(b"python"), 6)
709
Benjamin Peterson4c8b2cd2016-10-05 22:09:31 -0700710 @unittest.skipIf(os.name == 'nt', 'cannot resize anonymous mmaps on Windows')
Benjamin Petersoncd04db02016-10-05 21:45:48 -0700711 def test_resize_past_pos(self):
712 m = mmap.mmap(-1, 8192)
713 self.addCleanup(m.close)
714 m.read(5000)
Benjamin Petersone06cc672016-10-05 22:00:05 -0700715 try:
716 m.resize(4096)
717 except SystemError:
718 self.skipTest("resizing not supported")
Benjamin Petersoncd04db02016-10-05 21:45:48 -0700719 self.assertEqual(m.read(14), b'')
Benjamin Petersoncf0b9da2016-10-05 22:00:24 -0700720 self.assertRaises(ValueError, m.read_byte)
Benjamin Petersoncd04db02016-10-05 21:45:48 -0700721 self.assertRaises(ValueError, m.write_byte, 42)
722 self.assertRaises(ValueError, m.write, b'abc')
723
Zackery Spytze9e39762018-06-05 06:59:41 -0600724 def test_concat_repeat_exception(self):
725 m = mmap.mmap(-1, 16)
726 with self.assertRaises(TypeError):
727 m + m
728 with self.assertRaises(TypeError):
729 m * 2
730
Berker Peksage7d4b2f2018-08-22 21:21:05 +0300731 def test_flush_return_value(self):
732 # mm.flush() should return None on success, raise an
733 # exception on error under all platforms.
734 mm = mmap.mmap(-1, 16)
735 self.addCleanup(mm.close)
736 mm.write(b'python')
737 result = mm.flush()
738 self.assertIsNone(result)
Berker Peksagbc854752018-09-20 19:53:06 +0300739 if sys.platform.startswith('linux'):
740 # 'offset' must be a multiple of mmap.PAGESIZE on Linux.
741 # See bpo-34754 for details.
Berker Peksage7d4b2f2018-08-22 21:21:05 +0300742 self.assertRaises(OSError, mm.flush, 1, len(b'python'))
743
Taine Zhaod8ca2352019-10-17 18:41:35 +0800744 def test_repr(self):
745 open_mmap_repr_pat = re.compile(
746 r"<mmap.mmap closed=False, "
747 r"access=(?P<access>\S+), "
748 r"length=(?P<length>\d+), "
749 r"pos=(?P<pos>\d+), "
750 r"offset=(?P<offset>\d+)>")
751 closed_mmap_repr_pat = re.compile(r"<mmap.mmap closed=True>")
752 mapsizes = (50, 100, 1_000, 1_000_000, 10_000_000)
753 offsets = tuple((mapsize // 2 // mmap.ALLOCATIONGRANULARITY)
754 * mmap.ALLOCATIONGRANULARITY for mapsize in mapsizes)
755 for offset, mapsize in zip(offsets, mapsizes):
756 data = b'a' * mapsize
757 length = mapsize - offset
758 accesses = ('ACCESS_DEFAULT', 'ACCESS_READ',
759 'ACCESS_COPY', 'ACCESS_WRITE')
760 positions = (0, length//10, length//5, length//4)
761 with open(TESTFN, "wb+") as fp:
762 fp.write(data)
763 fp.flush()
764 for access, pos in itertools.product(accesses, positions):
765 accint = getattr(mmap, access)
766 with mmap.mmap(fp.fileno(),
767 length,
768 access=accint,
769 offset=offset) as mm:
770 mm.seek(pos)
771 match = open_mmap_repr_pat.match(repr(mm))
772 self.assertIsNotNone(match)
773 self.assertEqual(match.group('access'), access)
774 self.assertEqual(match.group('length'), str(length))
775 self.assertEqual(match.group('pos'), str(pos))
776 self.assertEqual(match.group('offset'), str(offset))
777 match = closed_mmap_repr_pat.match(repr(mm))
778 self.assertIsNotNone(match)
779
Zackery Spytz02db6962019-05-27 10:48:17 -0600780 @unittest.skipUnless(hasattr(mmap.mmap, 'madvise'), 'needs madvise')
781 def test_madvise(self):
Antoine Pitrou695b1dd2019-05-27 19:57:23 +0200782 size = 2 * PAGESIZE
Zackery Spytz02db6962019-05-27 10:48:17 -0600783 m = mmap.mmap(-1, size)
784
785 with self.assertRaisesRegex(ValueError, "madvise start out of bounds"):
786 m.madvise(mmap.MADV_NORMAL, size)
787 with self.assertRaisesRegex(ValueError, "madvise start out of bounds"):
788 m.madvise(mmap.MADV_NORMAL, -1)
789 with self.assertRaisesRegex(ValueError, "madvise length invalid"):
790 m.madvise(mmap.MADV_NORMAL, 0, -1)
791 with self.assertRaisesRegex(OverflowError, "madvise length too large"):
792 m.madvise(mmap.MADV_NORMAL, PAGESIZE, sys.maxsize)
793 self.assertEqual(m.madvise(mmap.MADV_NORMAL), None)
794 self.assertEqual(m.madvise(mmap.MADV_NORMAL, PAGESIZE), None)
795 self.assertEqual(m.madvise(mmap.MADV_NORMAL, PAGESIZE, size), None)
796 self.assertEqual(m.madvise(mmap.MADV_NORMAL, 0, 2), None)
797 self.assertEqual(m.madvise(mmap.MADV_NORMAL, 0, size), None)
798
Berker Peksag6282e652016-03-02 19:30:18 +0200799
Antoine Pitrou97696cb2011-02-21 23:46:27 +0000800class LargeMmapTests(unittest.TestCase):
801
802 def setUp(self):
803 unlink(TESTFN)
804
805 def tearDown(self):
806 unlink(TESTFN)
807
Nadeem Vawda909f6d22011-05-07 14:14:53 +0200808 def _make_test_file(self, num_zeroes, tail):
Antoine Pitrou97696cb2011-02-21 23:46:27 +0000809 if sys.platform[:3] == 'win' or sys.platform == 'darwin':
810 requires('largefile',
811 'test requires %s bytes and a long time to run' % str(0x180000000))
Nadeem Vawda909f6d22011-05-07 14:14:53 +0200812 f = open(TESTFN, 'w+b')
813 try:
814 f.seek(num_zeroes)
815 f.write(tail)
816 f.flush()
Serhiy Storchaka05d39212016-05-23 08:41:48 +0300817 except (OSError, OverflowError, ValueError):
Martin Pantere8d58d12015-09-07 02:57:47 +0000818 try:
819 f.close()
820 except (OSError, OverflowError):
821 pass
Nadeem Vawda909f6d22011-05-07 14:14:53 +0200822 raise unittest.SkipTest("filesystem does not have largefile support")
823 return f
Antoine Pitrou97696cb2011-02-21 23:46:27 +0000824
Nadeem Vawdaced10562011-05-07 13:01:50 +0200825 def test_large_offset(self):
Nadeem Vawda909f6d22011-05-07 14:14:53 +0200826 with self._make_test_file(0x14FFFFFFF, b" ") as f:
Antoine Pitrou97696cb2011-02-21 23:46:27 +0000827 with mmap.mmap(f.fileno(), 0, offset=0x140000000, access=mmap.ACCESS_READ) as m:
828 self.assertEqual(m[0xFFFFFFF], 32)
829
830 def test_large_filesize(self):
Nadeem Vawda909f6d22011-05-07 14:14:53 +0200831 with self._make_test_file(0x17FFFFFFF, b" ") as f:
Richard Oudkerk0d09ba82013-02-13 12:18:03 +0000832 if sys.maxsize < 0x180000000:
833 # On 32 bit platforms the file is larger than sys.maxsize so
834 # mapping the whole file should fail -- Issue #16743
835 with self.assertRaises(OverflowError):
836 mmap.mmap(f.fileno(), 0x180000000, access=mmap.ACCESS_READ)
837 with self.assertRaises(ValueError):
838 mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
Antoine Pitrou97696cb2011-02-21 23:46:27 +0000839 with mmap.mmap(f.fileno(), 0x10000, access=mmap.ACCESS_READ) as m:
840 self.assertEqual(m.size(), 0x180000000)
841
Victor Stinner8c663fd2017-11-08 14:44:44 -0800842 # Issue 11277: mmap() with large (~4 GiB) sparse files crashes on OS X.
Nadeem Vawdaced10562011-05-07 13:01:50 +0200843
844 def _test_around_boundary(self, boundary):
845 tail = b' DEARdear '
846 start = boundary - len(tail) // 2
847 end = start + len(tail)
Nadeem Vawda909f6d22011-05-07 14:14:53 +0200848 with self._make_test_file(start, tail) as f:
Nadeem Vawdac2bb0732011-05-07 13:08:54 +0200849 with mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as m:
Nadeem Vawdaced10562011-05-07 13:01:50 +0200850 self.assertEqual(m[start:end], tail)
Nadeem Vawdaced10562011-05-07 13:01:50 +0200851
852 @unittest.skipUnless(sys.maxsize > _4G, "test cannot run on 32-bit systems")
853 def test_around_2GB(self):
854 self._test_around_boundary(_2G)
855
856 @unittest.skipUnless(sys.maxsize > _4G, "test cannot run on 32-bit systems")
857 def test_around_4GB(self):
858 self._test_around_boundary(_4G)
859
Christian Heimes7131fd92008-02-19 14:21:46 +0000860
Thomas Wouters89f507f2006-12-13 04:49:30 +0000861if __name__ == '__main__':
Berker Peksage7d4b2f2018-08-22 21:21:05 +0300862 unittest.main()