blob: 0b5202a4a34bb1911d84040d514ac30fa2556ae9 [file] [log] [blame]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001from test.support import TESTFN, run_unittest
Andrew M. Kuchlinge81b9cf2000-03-30 21:15:29 +00002import mmap
Thomas Wouters89f507f2006-12-13 04:49:30 +00003import unittest
Fred Drake62787992001-05-11 14:29:21 +00004import os, re
Andrew M. Kuchlinge81b9cf2000-03-30 21:15:29 +00005
6PAGESIZE = mmap.PAGESIZE
7
Thomas Wouters89f507f2006-12-13 04:49:30 +00008class MmapTests(unittest.TestCase):
Fred Drake004d5e62000-10-23 17:22:08 +00009
Thomas Wouters89f507f2006-12-13 04:49:30 +000010 def setUp(self):
11 if os.path.exists(TESTFN):
12 os.unlink(TESTFN)
Fred Drake004d5e62000-10-23 17:22:08 +000013
Thomas Wouters89f507f2006-12-13 04:49:30 +000014 def tearDown(self):
Tim Petersfd692082001-05-10 20:03:04 +000015 try:
Fred Drake62787992001-05-11 14:29:21 +000016 os.unlink(TESTFN)
Tim Petersfd692082001-05-10 20:03:04 +000017 except OSError:
18 pass
19
Thomas Wouters89f507f2006-12-13 04:49:30 +000020 def test_basic(self):
21 # Test mmap module on Unix systems and Windows
22
23 # Create a file to be mmap'ed.
Guido van Rossumb358a2c2007-07-16 19:29:02 +000024 f = open(TESTFN, 'bw+')
Thomas Wouters89f507f2006-12-13 04:49:30 +000025 try:
26 # Write 2 pages worth of data to the file
Guido van Rossumb358a2c2007-07-16 19:29:02 +000027 f.write(b'\0'* PAGESIZE)
28 f.write(b'foo')
29 f.write(b'\0'* (PAGESIZE-3) )
Thomas Wouters89f507f2006-12-13 04:49:30 +000030 f.flush()
31 m = mmap.mmap(f.fileno(), 2 * PAGESIZE)
Guido van Rossum456fe5d2007-07-16 19:42:05 +000032 finally:
Thomas Wouters89f507f2006-12-13 04:49:30 +000033 f.close()
34
Guido van Rossum456fe5d2007-07-16 19:42:05 +000035 # Simple sanity checks
Thomas Wouters89f507f2006-12-13 04:49:30 +000036
Guido van Rossum456fe5d2007-07-16 19:42:05 +000037 tp = str(type(m)) # SF bug 128713: segfaulted on Linux
38 self.assertEqual(m.find('foo'), PAGESIZE)
Thomas Wouters89f507f2006-12-13 04:49:30 +000039
Guido van Rossum456fe5d2007-07-16 19:42:05 +000040 self.assertEqual(len(m), 2*PAGESIZE)
Thomas Wouters89f507f2006-12-13 04:49:30 +000041
Guido van Rossum98297ee2007-11-06 21:34:58 +000042 self.assertEqual(m[0], 0)
Guido van Rossum456fe5d2007-07-16 19:42:05 +000043 self.assertEqual(m[0:3], b'\0\0\0')
Thomas Wouters89f507f2006-12-13 04:49:30 +000044
Guido van Rossum456fe5d2007-07-16 19:42:05 +000045 # Modify the file's content
Guido van Rossum98297ee2007-11-06 21:34:58 +000046 m[0] = b'3'[0]
Guido van Rossum456fe5d2007-07-16 19:42:05 +000047 m[PAGESIZE +3: PAGESIZE +3+3] = b'bar'
Thomas Wouters89f507f2006-12-13 04:49:30 +000048
Guido van Rossum456fe5d2007-07-16 19:42:05 +000049 # Check that the modification worked
Guido van Rossum98297ee2007-11-06 21:34:58 +000050 self.assertEqual(m[0], b'3'[0])
Guido van Rossum456fe5d2007-07-16 19:42:05 +000051 self.assertEqual(m[0:3], b'3\0\0')
52 self.assertEqual(m[PAGESIZE-1 : PAGESIZE + 7], b'\0foobar\0')
Thomas Wouters89f507f2006-12-13 04:49:30 +000053
Guido van Rossum456fe5d2007-07-16 19:42:05 +000054 m.flush()
Thomas Wouters89f507f2006-12-13 04:49:30 +000055
Guido van Rossum456fe5d2007-07-16 19:42:05 +000056 # Test doing a regular expression match in an mmap'ed file
57 match = re.search('[A-Za-z]+', m)
58 if match is None:
59 self.fail('regex match on mmap failed!')
60 else:
61 start, end = match.span(0)
62 length = end - start
Thomas Wouters89f507f2006-12-13 04:49:30 +000063
Guido van Rossum456fe5d2007-07-16 19:42:05 +000064 self.assertEqual(start, PAGESIZE)
65 self.assertEqual(end, PAGESIZE + 6)
Thomas Wouters89f507f2006-12-13 04:49:30 +000066
Guido van Rossum456fe5d2007-07-16 19:42:05 +000067 # test seeking around (try to overflow the seek implementation)
68 m.seek(0,0)
69 self.assertEqual(m.tell(), 0)
70 m.seek(42,1)
71 self.assertEqual(m.tell(), 42)
72 m.seek(0,2)
73 self.assertEqual(m.tell(), len(m))
Thomas Wouters89f507f2006-12-13 04:49:30 +000074
Guido van Rossum456fe5d2007-07-16 19:42:05 +000075 # Try to seek to negative position...
76 self.assertRaises(ValueError, m.seek, -1)
Thomas Wouters89f507f2006-12-13 04:49:30 +000077
Guido van Rossum456fe5d2007-07-16 19:42:05 +000078 # Try to seek beyond end of mmap...
79 self.assertRaises(ValueError, m.seek, 1, 2)
Thomas Wouters89f507f2006-12-13 04:49:30 +000080
Guido van Rossum456fe5d2007-07-16 19:42:05 +000081 # Try to seek to negative position...
82 self.assertRaises(ValueError, m.seek, -len(m)-1, 2)
Thomas Wouters89f507f2006-12-13 04:49:30 +000083
Guido van Rossum456fe5d2007-07-16 19:42:05 +000084 # Try resizing map
85 try:
86 m.resize(512)
87 except SystemError:
88 # resize() not supported
89 # No messages are printed, since the output of this test suite
90 # would then be different across platforms.
91 pass
92 else:
93 # resize() is supported
94 self.assertEqual(len(m), 512)
95 # Check that we can no longer seek beyond the new size.
96 self.assertRaises(ValueError, m.seek, 513, 0)
97
98 # Check that the underlying file is truncated too
99 # (bug #728515)
100 f = open(TESTFN)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000101 try:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000102 f.seek(0, 2)
103 self.assertEqual(f.tell(), 512)
Guido van Rossum456fe5d2007-07-16 19:42:05 +0000104 finally:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000105 f.close()
Guido van Rossum456fe5d2007-07-16 19:42:05 +0000106 self.assertEqual(m.size(), 512)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000107
Guido van Rossum456fe5d2007-07-16 19:42:05 +0000108 m.close()
Thomas Wouters89f507f2006-12-13 04:49:30 +0000109
110 def test_access_parameter(self):
111 # Test for "access" keyword parameter
Tim Peters5ebfd362001-11-13 23:11:19 +0000112 mapsize = 10
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000113 open(TESTFN, "wb").write(b"a"*mapsize)
Tim Peters5ebfd362001-11-13 23:11:19 +0000114 f = open(TESTFN, "rb")
115 m = mmap.mmap(f.fileno(), mapsize, access=mmap.ACCESS_READ)
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000116 self.assertEqual(m[:], b'a'*mapsize, "Readonly memory map data incorrect.")
Tim Peters5ebfd362001-11-13 23:11:19 +0000117
Thomas Wouters89f507f2006-12-13 04:49:30 +0000118 # Ensuring that readonly mmap can't be slice assigned
Tim Peters5ebfd362001-11-13 23:11:19 +0000119 try:
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000120 m[:] = b'b'*mapsize
Tim Peters5ebfd362001-11-13 23:11:19 +0000121 except TypeError:
122 pass
123 else:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000124 self.fail("Able to write to readonly memory map")
Tim Peters5ebfd362001-11-13 23:11:19 +0000125
Thomas Wouters89f507f2006-12-13 04:49:30 +0000126 # Ensuring that readonly mmap can't be item assigned
Tim Peters5ebfd362001-11-13 23:11:19 +0000127 try:
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000128 m[0] = b'b'
Tim Peters5ebfd362001-11-13 23:11:19 +0000129 except TypeError:
130 pass
131 else:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000132 self.fail("Able to write to readonly memory map")
Tim Peters5ebfd362001-11-13 23:11:19 +0000133
Thomas Wouters89f507f2006-12-13 04:49:30 +0000134 # Ensuring that readonly mmap can't be write() to
Tim Peters5ebfd362001-11-13 23:11:19 +0000135 try:
136 m.seek(0,0)
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000137 m.write(b'abc')
Tim Peters5ebfd362001-11-13 23:11:19 +0000138 except TypeError:
139 pass
140 else:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000141 self.fail("Able to write to readonly memory map")
Tim Peters5ebfd362001-11-13 23:11:19 +0000142
Thomas Wouters89f507f2006-12-13 04:49:30 +0000143 # Ensuring that readonly mmap can't be write_byte() to
Tim Peters5ebfd362001-11-13 23:11:19 +0000144 try:
145 m.seek(0,0)
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000146 m.write_byte(b'd')
Tim Peters5ebfd362001-11-13 23:11:19 +0000147 except TypeError:
148 pass
149 else:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000150 self.fail("Able to write to readonly memory map")
Tim Peters5ebfd362001-11-13 23:11:19 +0000151
Thomas Wouters89f507f2006-12-13 04:49:30 +0000152 # Ensuring that readonly mmap can't be resized
Tim Peters5ebfd362001-11-13 23:11:19 +0000153 try:
154 m.resize(2*mapsize)
155 except SystemError: # resize is not universally supported
156 pass
157 except TypeError:
158 pass
159 else:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000160 self.fail("Able to resize readonly memory map")
Martin v. Löwise1e9f232008-04-01 06:17:46 +0000161 f.close()
Tim Peters5ebfd362001-11-13 23:11:19 +0000162 del m, f
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000163 self.assertEqual(open(TESTFN, "rb").read(), b'a'*mapsize,
Tim Peters5ebfd362001-11-13 23:11:19 +0000164 "Readonly memory map data file was modified")
165
Thomas Wouters89f507f2006-12-13 04:49:30 +0000166 # Opening mmap with size too big
Neal Norwitzb5673922002-09-05 21:48:07 +0000167 import sys
168 f = open(TESTFN, "r+b")
169 try:
170 m = mmap.mmap(f.fileno(), mapsize+1)
171 except ValueError:
172 # we do not expect a ValueError on Windows
Tim Peters4f4f4d72002-09-10 20:49:15 +0000173 # CAUTION: This also changes the size of the file on disk, and
174 # later tests assume that the length hasn't changed. We need to
175 # repair that.
Neal Norwitzb5673922002-09-05 21:48:07 +0000176 if sys.platform.startswith('win'):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000177 self.fail("Opening mmap with size+1 should work on Windows.")
Neal Norwitzb5673922002-09-05 21:48:07 +0000178 else:
179 # we expect a ValueError on Unix, but not on Windows
180 if not sys.platform.startswith('win'):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000181 self.fail("Opening mmap with size+1 should raise ValueError.")
Barry Warsawccd9e752002-09-11 02:56:42 +0000182 m.close()
Tim Peters4f4f4d72002-09-10 20:49:15 +0000183 f.close()
184 if sys.platform.startswith('win'):
185 # Repair damage from the resizing test.
186 f = open(TESTFN, 'r+b')
187 f.truncate(mapsize)
188 f.close()
Neal Norwitzb5673922002-09-05 21:48:07 +0000189
Thomas Wouters89f507f2006-12-13 04:49:30 +0000190 # Opening mmap with access=ACCESS_WRITE
Tim Peters5ebfd362001-11-13 23:11:19 +0000191 f = open(TESTFN, "r+b")
192 m = mmap.mmap(f.fileno(), mapsize, access=mmap.ACCESS_WRITE)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000193 # Modifying write-through memory map
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000194 m[:] = b'c'*mapsize
195 self.assertEqual(m[:], b'c'*mapsize,
Tim Peters5ebfd362001-11-13 23:11:19 +0000196 "Write-through memory map memory not updated properly.")
197 m.flush()
Tim Peters1b5112a2002-09-10 21:19:55 +0000198 m.close()
199 f.close()
Tim Peters4f4f4d72002-09-10 20:49:15 +0000200 f = open(TESTFN, 'rb')
201 stuff = f.read()
202 f.close()
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000203 self.assertEqual(stuff, b'c'*mapsize,
Tim Peters5ebfd362001-11-13 23:11:19 +0000204 "Write-through memory map data file not updated properly.")
205
Thomas Wouters89f507f2006-12-13 04:49:30 +0000206 # Opening mmap with access=ACCESS_COPY
Tim Peters5ebfd362001-11-13 23:11:19 +0000207 f = open(TESTFN, "r+b")
208 m = mmap.mmap(f.fileno(), mapsize, access=mmap.ACCESS_COPY)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000209 # Modifying copy-on-write memory map
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000210 m[:] = b'd'*mapsize
211 self.assertEqual(m[:], b'd' * mapsize,
Tim Peters5ebfd362001-11-13 23:11:19 +0000212 "Copy-on-write memory map data not written correctly.")
213 m.flush()
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000214 self.assertEqual(open(TESTFN, "rb").read(), b'c'*mapsize,
Tim Peters5ebfd362001-11-13 23:11:19 +0000215 "Copy-on-write test data file should not be modified.")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000216 # Ensuring copy-on-write maps cannot be resized
217 self.assertRaises(TypeError, m.resize, 2*mapsize)
Martin v. Löwise1e9f232008-04-01 06:17:46 +0000218 f.close()
Tim Peters5ebfd362001-11-13 23:11:19 +0000219 del m, f
Thomas Wouters89f507f2006-12-13 04:49:30 +0000220
221 # Ensuring invalid access parameter raises exception
222 f = open(TESTFN, "r+b")
223 self.assertRaises(ValueError, mmap.mmap, f.fileno(), mapsize, access=4)
224 f.close()
Tim Peters5ebfd362001-11-13 23:11:19 +0000225
226 if os.name == "posix":
Tim Peters00cafa02001-11-13 23:39:47 +0000227 # Try incompatible flags, prot and access parameters.
228 f = open(TESTFN, "r+b")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000229 self.assertRaises(ValueError, mmap.mmap, f.fileno(), mapsize,
230 flags=mmap.MAP_PRIVATE,
Tim Peters5ebfd362001-11-13 23:11:19 +0000231 prot=mmap.PROT_READ, access=mmap.ACCESS_WRITE)
Tim Peters5379dea2002-04-18 04:30:18 +0000232 f.close()
Tim Peters5ebfd362001-11-13 23:11:19 +0000233
Thomas Wouters89f507f2006-12-13 04:49:30 +0000234 def test_bad_file_desc(self):
235 # Try opening a bad file descriptor...
236 self.assertRaises(mmap.error, mmap.mmap, -2, 4096)
Neal Norwitz3b4fff82006-01-11 08:54:45 +0000237
Thomas Wouters89f507f2006-12-13 04:49:30 +0000238 def test_tougher_find(self):
239 # Do a tougher .find() test. SF bug 515943 pointed out that, in 2.2,
240 # searching for data with embedded \0 bytes didn't work.
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000241 f = open(TESTFN, 'wb+')
Tim Petersc9ffa062002-03-08 05:43:32 +0000242
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000243 data = b'aabaac\x00deef\x00\x00aa\x00'
Tim Petersc9ffa062002-03-08 05:43:32 +0000244 n = len(data)
245 f.write(data)
Tim Peters5379dea2002-04-18 04:30:18 +0000246 f.flush()
Tim Petersc9ffa062002-03-08 05:43:32 +0000247 m = mmap.mmap(f.fileno(), n)
248 f.close()
249
250 for start in range(n+1):
251 for finish in range(start, n+1):
252 slice = data[start : finish]
Thomas Wouters89f507f2006-12-13 04:49:30 +0000253 self.assertEqual(m.find(slice), data.find(slice))
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000254 self.assertEqual(m.find(slice + b'x'), -1)
Tim Petersddc82ea2003-01-13 21:38:45 +0000255 m.close()
Tim Petersc9ffa062002-03-08 05:43:32 +0000256
Georg Brandlfceab5a2008-01-19 20:08:23 +0000257 def test_find_end(self):
258 # test the new 'end' parameter works as expected
259 f = open(TESTFN, 'w+')
260 data = 'one two ones'
261 n = len(data)
262 f.write(data)
263 f.flush()
264 m = mmap.mmap(f.fileno(), n)
265 f.close()
266
267 self.assertEqual(m.find('one'), 0)
268 self.assertEqual(m.find('ones'), 8)
269 self.assertEqual(m.find('one', 0, -1), 0)
270 self.assertEqual(m.find('one', 1), 8)
271 self.assertEqual(m.find('one', 1, -1), 8)
272 self.assertEqual(m.find('one', 1, -2), -1)
273
274
275 def test_rfind(self):
276 # test the new 'end' parameter works as expected
277 f = open(TESTFN, 'w+')
278 data = 'one two ones'
279 n = len(data)
280 f.write(data)
281 f.flush()
282 m = mmap.mmap(f.fileno(), n)
283 f.close()
284
285 self.assertEqual(m.rfind('one'), 8)
286 self.assertEqual(m.rfind('one '), 0)
287 self.assertEqual(m.rfind('one', 0, -1), 8)
288 self.assertEqual(m.rfind('one', 0, -2), 0)
289 self.assertEqual(m.rfind('one', 1, -1), 8)
290 self.assertEqual(m.rfind('one', 1, -2), -1)
291
292
Thomas Wouters89f507f2006-12-13 04:49:30 +0000293 def test_double_close(self):
294 # make sure a double close doesn't crash on Solaris (Bug# 665913)
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000295 f = open(TESTFN, 'wb+')
Tim Petersc9ffa062002-03-08 05:43:32 +0000296
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000297 f.write(2**16 * b'a') # Arbitrary character
Neal Norwitze604c022003-01-10 20:52:16 +0000298 f.close()
299
300 f = open(TESTFN)
Tim Petersddc82ea2003-01-13 21:38:45 +0000301 mf = mmap.mmap(f.fileno(), 2**16, access=mmap.ACCESS_READ)
Neal Norwitze604c022003-01-10 20:52:16 +0000302 mf.close()
303 mf.close()
304 f.close()
305
Thomas Wouters89f507f2006-12-13 04:49:30 +0000306 def test_entire_file(self):
307 # test mapping of entire file by passing 0 for map length
308 if hasattr(os, "stat"):
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000309 f = open(TESTFN, "wb+")
Tim Petersc9ffa062002-03-08 05:43:32 +0000310
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000311 f.write(2**16 * b'm') # Arbitrary character
Martin v. Löwis7fe60c02005-03-03 11:22:44 +0000312 f.close()
313
314 f = open(TESTFN, "rb+")
Tim Peterseba28be2005-03-28 01:08:02 +0000315 mf = mmap.mmap(f.fileno(), 0)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000316 self.assertEqual(len(mf), 2**16, "Map size should equal file size.")
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000317 self.assertEqual(mf.read(2**16), 2**16 * b"m")
Martin v. Löwis7fe60c02005-03-03 11:22:44 +0000318 mf.close()
319 f.close()
320
Thomas Wouters89f507f2006-12-13 04:49:30 +0000321 def test_move(self):
322 # make move works everywhere (64-bit format problem earlier)
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000323 f = open(TESTFN, 'wb+')
Tim Peterseba28be2005-03-28 01:08:02 +0000324
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000325 f.write(b"ABCDEabcde") # Arbitrary character
Neal Norwitz8856fb72005-12-18 03:34:22 +0000326 f.flush()
327
328 mf = mmap.mmap(f.fileno(), 10)
329 mf.move(5, 0, 5)
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000330 self.assertEqual(mf[:], b"ABCDEABCDE", "Map move should have duplicated front 5")
Neal Norwitz8856fb72005-12-18 03:34:22 +0000331 mf.close()
332 f.close()
333
Thomas Wouters89f507f2006-12-13 04:49:30 +0000334 def test_anonymous(self):
335 # anonymous mmap.mmap(-1, PAGE)
336 m = mmap.mmap(-1, PAGESIZE)
Guido van Rossum805365e2007-05-07 22:24:25 +0000337 for x in range(PAGESIZE):
Guido van Rossum98297ee2007-11-06 21:34:58 +0000338 self.assertEqual(m[x], 0,
339 "anonymously mmap'ed contents should be zero")
Neal Norwitz8856fb72005-12-18 03:34:22 +0000340
Guido van Rossum805365e2007-05-07 22:24:25 +0000341 for x in range(PAGESIZE):
Guido van Rossum98297ee2007-11-06 21:34:58 +0000342 b = x & 0xff
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000343 m[x] = b
344 self.assertEqual(m[x], b)
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +0000345
Thomas Woutersed03b412007-08-28 21:37:11 +0000346 def test_extended_getslice(self):
347 # Test extended slicing by comparing with list slicing.
348 s = bytes(reversed(range(256)))
349 m = mmap.mmap(-1, len(s))
350 m[:] = s
351 self.assertEqual(m[:], s)
352 indices = (0, None, 1, 3, 19, 300, -1, -2, -31, -300)
353 for start in indices:
354 for stop in indices:
355 # Skip step 0 (invalid)
356 for step in indices[1:]:
357 self.assertEqual(m[start:stop:step],
358 s[start:stop:step])
359
360 def test_extended_set_del_slice(self):
361 # Test extended slicing by comparing with list slicing.
362 s = bytes(reversed(range(256)))
363 m = mmap.mmap(-1, len(s))
364 indices = (0, None, 1, 3, 19, 300, -1, -2, -31, -300)
365 for start in indices:
366 for stop in indices:
367 # Skip invalid step 0
368 for step in indices[1:]:
369 m[:] = s
370 self.assertEqual(m[:], s)
371 L = list(s)
372 # Make sure we have a slice of exactly the right length,
373 # but with different data.
374 data = L[start:stop:step]
375 data = bytes(reversed(data))
376 L[start:stop:step] = data
377 m[start:stop:step] = data
378 self.assertEquals(m[:], bytes(L))
379
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000380 def make_mmap_file (self, f, halfsize):
381 # Write 2 pages worth of data to the file
382 f.write (b'\0' * halfsize)
383 f.write (b'foo')
384 f.write (b'\0' * (halfsize - 3))
385 f.flush ()
386 return mmap.mmap (f.fileno(), 0)
387
388 def test_offset (self):
389 f = open (TESTFN, 'w+b')
390
391 try: # unlink TESTFN no matter what
392 halfsize = mmap.ALLOCATIONGRANULARITY
393 m = self.make_mmap_file (f, halfsize)
394 m.close ()
395 f.close ()
396
397 mapsize = halfsize * 2
398 # Try invalid offset
399 f = open(TESTFN, "r+b")
400 for offset in [-2, -1, None]:
401 try:
402 m = mmap.mmap(f.fileno(), mapsize, offset=offset)
403 self.assertEqual(0, 1)
404 except (ValueError, TypeError, OverflowError):
405 pass
406 else:
407 self.assertEqual(0, 0)
408 f.close()
409
410 # Try valid offset, hopefully 8192 works on all OSes
411 f = open(TESTFN, "r+b")
412 m = mmap.mmap(f.fileno(), mapsize - halfsize, offset=halfsize)
413 self.assertEqual(m[0:3], b'foo')
414 f.close()
415 m.close()
416
417 finally:
418 f.close()
419 try:
420 os.unlink(TESTFN)
421 except OSError:
422 pass
423
Christian Heimes1af737c2008-01-23 08:24:23 +0000424 def test_subclass(self):
425 class anon_mmap(mmap.mmap):
426 def __new__(klass, *args, **kwargs):
427 return mmap.mmap.__new__(klass, -1, *args, **kwargs)
428 anon_mmap(PAGESIZE)
429
Christian Heimesa156e092008-02-16 07:38:31 +0000430 def test_prot_readonly(self):
Christian Heimes18c66892008-02-17 13:31:39 +0000431 if not hasattr(mmap, 'PROT_READ'):
432 return
Christian Heimesa156e092008-02-16 07:38:31 +0000433 mapsize = 10
434 open(TESTFN, "wb").write(b"a"*mapsize)
435 f = open(TESTFN, "rb")
436 m = mmap.mmap(f.fileno(), mapsize, prot=mmap.PROT_READ)
437 self.assertRaises(TypeError, m.write, "foo")
Martin v. Löwise1e9f232008-04-01 06:17:46 +0000438 f.close()
Christian Heimes1af737c2008-01-23 08:24:23 +0000439
Christian Heimes7131fd92008-02-19 14:21:46 +0000440 def test_error(self):
441 self.assert_(issubclass(mmap.error, EnvironmentError))
442 self.assert_("mmap.error" in str(mmap.error))
443
444
Thomas Wouters89f507f2006-12-13 04:49:30 +0000445def test_main():
446 run_unittest(MmapTests)
Andrew M. Kuchlinge81b9cf2000-03-30 21:15:29 +0000447
Thomas Wouters89f507f2006-12-13 04:49:30 +0000448if __name__ == '__main__':
449 test_main()