blob: 3d30109f5fec7cafc6b1eb445cfb0f0da43f61d1 [file] [log] [blame]
Thomas Wouters89f507f2006-12-13 04:49:30 +00001from test.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")
Tim Peters5ebfd362001-11-13 23:11:19 +0000161 del m, f
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000162 self.assertEqual(open(TESTFN, "rb").read(), b'a'*mapsize,
Tim Peters5ebfd362001-11-13 23:11:19 +0000163 "Readonly memory map data file was modified")
164
Thomas Wouters89f507f2006-12-13 04:49:30 +0000165 # Opening mmap with size too big
Neal Norwitzb5673922002-09-05 21:48:07 +0000166 import sys
167 f = open(TESTFN, "r+b")
168 try:
169 m = mmap.mmap(f.fileno(), mapsize+1)
170 except ValueError:
171 # we do not expect a ValueError on Windows
Tim Peters4f4f4d72002-09-10 20:49:15 +0000172 # CAUTION: This also changes the size of the file on disk, and
173 # later tests assume that the length hasn't changed. We need to
174 # repair that.
Neal Norwitzb5673922002-09-05 21:48:07 +0000175 if sys.platform.startswith('win'):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000176 self.fail("Opening mmap with size+1 should work on Windows.")
Neal Norwitzb5673922002-09-05 21:48:07 +0000177 else:
178 # we expect a ValueError on Unix, but not on Windows
179 if not sys.platform.startswith('win'):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000180 self.fail("Opening mmap with size+1 should raise ValueError.")
Barry Warsawccd9e752002-09-11 02:56:42 +0000181 m.close()
Tim Peters4f4f4d72002-09-10 20:49:15 +0000182 f.close()
183 if sys.platform.startswith('win'):
184 # Repair damage from the resizing test.
185 f = open(TESTFN, 'r+b')
186 f.truncate(mapsize)
187 f.close()
Neal Norwitzb5673922002-09-05 21:48:07 +0000188
Thomas Wouters89f507f2006-12-13 04:49:30 +0000189 # Opening mmap with access=ACCESS_WRITE
Tim Peters5ebfd362001-11-13 23:11:19 +0000190 f = open(TESTFN, "r+b")
191 m = mmap.mmap(f.fileno(), mapsize, access=mmap.ACCESS_WRITE)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000192 # Modifying write-through memory map
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000193 m[:] = b'c'*mapsize
194 self.assertEqual(m[:], b'c'*mapsize,
Tim Peters5ebfd362001-11-13 23:11:19 +0000195 "Write-through memory map memory not updated properly.")
196 m.flush()
Tim Peters1b5112a2002-09-10 21:19:55 +0000197 m.close()
198 f.close()
Tim Peters4f4f4d72002-09-10 20:49:15 +0000199 f = open(TESTFN, 'rb')
200 stuff = f.read()
201 f.close()
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000202 self.assertEqual(stuff, b'c'*mapsize,
Tim Peters5ebfd362001-11-13 23:11:19 +0000203 "Write-through memory map data file not updated properly.")
204
Thomas Wouters89f507f2006-12-13 04:49:30 +0000205 # Opening mmap with access=ACCESS_COPY
Tim Peters5ebfd362001-11-13 23:11:19 +0000206 f = open(TESTFN, "r+b")
207 m = mmap.mmap(f.fileno(), mapsize, access=mmap.ACCESS_COPY)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000208 # Modifying copy-on-write memory map
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000209 m[:] = b'd'*mapsize
210 self.assertEqual(m[:], b'd' * mapsize,
Tim Peters5ebfd362001-11-13 23:11:19 +0000211 "Copy-on-write memory map data not written correctly.")
212 m.flush()
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000213 self.assertEqual(open(TESTFN, "rb").read(), b'c'*mapsize,
Tim Peters5ebfd362001-11-13 23:11:19 +0000214 "Copy-on-write test data file should not be modified.")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000215 # Ensuring copy-on-write maps cannot be resized
216 self.assertRaises(TypeError, m.resize, 2*mapsize)
Tim Peters5ebfd362001-11-13 23:11:19 +0000217 del m, f
Thomas Wouters89f507f2006-12-13 04:49:30 +0000218
219 # Ensuring invalid access parameter raises exception
220 f = open(TESTFN, "r+b")
221 self.assertRaises(ValueError, mmap.mmap, f.fileno(), mapsize, access=4)
222 f.close()
Tim Peters5ebfd362001-11-13 23:11:19 +0000223
224 if os.name == "posix":
Tim Peters00cafa02001-11-13 23:39:47 +0000225 # Try incompatible flags, prot and access parameters.
226 f = open(TESTFN, "r+b")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000227 self.assertRaises(ValueError, mmap.mmap, f.fileno(), mapsize,
228 flags=mmap.MAP_PRIVATE,
Tim Peters5ebfd362001-11-13 23:11:19 +0000229 prot=mmap.PROT_READ, access=mmap.ACCESS_WRITE)
Tim Peters5379dea2002-04-18 04:30:18 +0000230 f.close()
Tim Peters5ebfd362001-11-13 23:11:19 +0000231
Thomas Wouters89f507f2006-12-13 04:49:30 +0000232 def test_bad_file_desc(self):
233 # Try opening a bad file descriptor...
234 self.assertRaises(mmap.error, mmap.mmap, -2, 4096)
Neal Norwitz3b4fff82006-01-11 08:54:45 +0000235
Thomas Wouters89f507f2006-12-13 04:49:30 +0000236 def test_tougher_find(self):
237 # Do a tougher .find() test. SF bug 515943 pointed out that, in 2.2,
238 # searching for data with embedded \0 bytes didn't work.
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000239 f = open(TESTFN, 'wb+')
Tim Petersc9ffa062002-03-08 05:43:32 +0000240
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000241 data = b'aabaac\x00deef\x00\x00aa\x00'
Tim Petersc9ffa062002-03-08 05:43:32 +0000242 n = len(data)
243 f.write(data)
Tim Peters5379dea2002-04-18 04:30:18 +0000244 f.flush()
Tim Petersc9ffa062002-03-08 05:43:32 +0000245 m = mmap.mmap(f.fileno(), n)
246 f.close()
247
248 for start in range(n+1):
249 for finish in range(start, n+1):
250 slice = data[start : finish]
Thomas Wouters89f507f2006-12-13 04:49:30 +0000251 self.assertEqual(m.find(slice), data.find(slice))
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000252 self.assertEqual(m.find(slice + b'x'), -1)
Tim Petersddc82ea2003-01-13 21:38:45 +0000253 m.close()
Tim Petersc9ffa062002-03-08 05:43:32 +0000254
Thomas Wouters89f507f2006-12-13 04:49:30 +0000255 def test_double_close(self):
256 # make sure a double close doesn't crash on Solaris (Bug# 665913)
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000257 f = open(TESTFN, 'wb+')
Tim Petersc9ffa062002-03-08 05:43:32 +0000258
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000259 f.write(2**16 * b'a') # Arbitrary character
Neal Norwitze604c022003-01-10 20:52:16 +0000260 f.close()
261
262 f = open(TESTFN)
Tim Petersddc82ea2003-01-13 21:38:45 +0000263 mf = mmap.mmap(f.fileno(), 2**16, access=mmap.ACCESS_READ)
Neal Norwitze604c022003-01-10 20:52:16 +0000264 mf.close()
265 mf.close()
266 f.close()
267
Thomas Wouters89f507f2006-12-13 04:49:30 +0000268 def test_entire_file(self):
269 # test mapping of entire file by passing 0 for map length
270 if hasattr(os, "stat"):
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000271 f = open(TESTFN, "wb+")
Tim Petersc9ffa062002-03-08 05:43:32 +0000272
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000273 f.write(2**16 * b'm') # Arbitrary character
Martin v. Löwis7fe60c02005-03-03 11:22:44 +0000274 f.close()
275
276 f = open(TESTFN, "rb+")
Tim Peterseba28be2005-03-28 01:08:02 +0000277 mf = mmap.mmap(f.fileno(), 0)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000278 self.assertEqual(len(mf), 2**16, "Map size should equal file size.")
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000279 self.assertEqual(mf.read(2**16), 2**16 * b"m")
Martin v. Löwis7fe60c02005-03-03 11:22:44 +0000280 mf.close()
281 f.close()
282
Thomas Wouters89f507f2006-12-13 04:49:30 +0000283 def test_move(self):
284 # make move works everywhere (64-bit format problem earlier)
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000285 f = open(TESTFN, 'wb+')
Tim Peterseba28be2005-03-28 01:08:02 +0000286
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000287 f.write(b"ABCDEabcde") # Arbitrary character
Neal Norwitz8856fb72005-12-18 03:34:22 +0000288 f.flush()
289
290 mf = mmap.mmap(f.fileno(), 10)
291 mf.move(5, 0, 5)
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000292 self.assertEqual(mf[:], b"ABCDEABCDE", "Map move should have duplicated front 5")
Neal Norwitz8856fb72005-12-18 03:34:22 +0000293 mf.close()
294 f.close()
295
Thomas Wouters89f507f2006-12-13 04:49:30 +0000296 def test_anonymous(self):
297 # anonymous mmap.mmap(-1, PAGE)
298 m = mmap.mmap(-1, PAGESIZE)
Guido van Rossum805365e2007-05-07 22:24:25 +0000299 for x in range(PAGESIZE):
Guido van Rossum98297ee2007-11-06 21:34:58 +0000300 self.assertEqual(m[x], 0,
301 "anonymously mmap'ed contents should be zero")
Neal Norwitz8856fb72005-12-18 03:34:22 +0000302
Guido van Rossum805365e2007-05-07 22:24:25 +0000303 for x in range(PAGESIZE):
Guido van Rossum98297ee2007-11-06 21:34:58 +0000304 b = x & 0xff
Guido van Rossumb358a2c2007-07-16 19:29:02 +0000305 m[x] = b
306 self.assertEqual(m[x], b)
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +0000307
Thomas Woutersed03b412007-08-28 21:37:11 +0000308 def test_extended_getslice(self):
309 # Test extended slicing by comparing with list slicing.
310 s = bytes(reversed(range(256)))
311 m = mmap.mmap(-1, len(s))
312 m[:] = s
313 self.assertEqual(m[:], s)
314 indices = (0, None, 1, 3, 19, 300, -1, -2, -31, -300)
315 for start in indices:
316 for stop in indices:
317 # Skip step 0 (invalid)
318 for step in indices[1:]:
319 self.assertEqual(m[start:stop:step],
320 s[start:stop:step])
321
322 def test_extended_set_del_slice(self):
323 # Test extended slicing by comparing with list slicing.
324 s = bytes(reversed(range(256)))
325 m = mmap.mmap(-1, len(s))
326 indices = (0, None, 1, 3, 19, 300, -1, -2, -31, -300)
327 for start in indices:
328 for stop in indices:
329 # Skip invalid step 0
330 for step in indices[1:]:
331 m[:] = s
332 self.assertEqual(m[:], s)
333 L = list(s)
334 # Make sure we have a slice of exactly the right length,
335 # but with different data.
336 data = L[start:stop:step]
337 data = bytes(reversed(data))
338 L[start:stop:step] = data
339 m[start:stop:step] = data
340 self.assertEquals(m[:], bytes(L))
341
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000342 def make_mmap_file (self, f, halfsize):
343 # Write 2 pages worth of data to the file
344 f.write (b'\0' * halfsize)
345 f.write (b'foo')
346 f.write (b'\0' * (halfsize - 3))
347 f.flush ()
348 return mmap.mmap (f.fileno(), 0)
349
350 def test_offset (self):
351 f = open (TESTFN, 'w+b')
352
353 try: # unlink TESTFN no matter what
354 halfsize = mmap.ALLOCATIONGRANULARITY
355 m = self.make_mmap_file (f, halfsize)
356 m.close ()
357 f.close ()
358
359 mapsize = halfsize * 2
360 # Try invalid offset
361 f = open(TESTFN, "r+b")
362 for offset in [-2, -1, None]:
363 try:
364 m = mmap.mmap(f.fileno(), mapsize, offset=offset)
365 self.assertEqual(0, 1)
366 except (ValueError, TypeError, OverflowError):
367 pass
368 else:
369 self.assertEqual(0, 0)
370 f.close()
371
372 # Try valid offset, hopefully 8192 works on all OSes
373 f = open(TESTFN, "r+b")
374 m = mmap.mmap(f.fileno(), mapsize - halfsize, offset=halfsize)
375 self.assertEqual(m[0:3], b'foo')
376 f.close()
377 m.close()
378
379 finally:
380 f.close()
381 try:
382 os.unlink(TESTFN)
383 except OSError:
384 pass
385
Thomas Wouters89f507f2006-12-13 04:49:30 +0000386def test_main():
387 run_unittest(MmapTests)
Andrew M. Kuchlinge81b9cf2000-03-30 21:15:29 +0000388
Thomas Wouters89f507f2006-12-13 04:49:30 +0000389if __name__ == '__main__':
390 test_main()