1 from test
.test_support
import verify
, vereq
, TESTFN
5 PAGESIZE
= mmap
.PAGESIZE
8 "Test mmap module on Unix systems and Windows"
10 # Create a file to be mmap'ed.
11 if os
.path
.exists(TESTFN
):
13 f
= open(TESTFN
, 'w+')
15 try: # unlink TESTFN no matter what
16 # Write 2 pages worth of data to the file
17 f
.write('\0'* PAGESIZE
)
19 f
.write('\0'* (PAGESIZE
-3) )
21 m
= mmap
.mmap(f
.fileno(), 2 * PAGESIZE
)
24 # Simple sanity checks
26 print type(m
) # SF bug 128713: segfaulted on Linux
27 print ' Position of foo:', m
.find('foo') / float(PAGESIZE
), 'pages'
28 vereq(m
.find('foo'), PAGESIZE
)
30 print ' Length of file:', len(m
) / float(PAGESIZE
), 'pages'
31 vereq(len(m
), 2*PAGESIZE
)
33 print ' Contents of byte 0:', repr(m
[0])
35 print ' Contents of first 3 bytes:', repr(m
[0:3])
36 vereq(m
[0:3], '\0\0\0')
38 # Modify the file's content
39 print "\n Modifying file's content..."
41 m
[PAGESIZE
+3: PAGESIZE
+3+3] = 'bar'
43 # Check that the modification worked
44 print ' Contents of byte 0:', repr(m
[0])
46 print ' Contents of first 3 bytes:', repr(m
[0:3])
47 vereq(m
[0:3], '3\0\0')
48 print ' Contents of second page:', repr(m
[PAGESIZE
-1 : PAGESIZE
+ 7])
49 vereq(m
[PAGESIZE
-1 : PAGESIZE
+ 7], '\0foobar\0')
53 # Test doing a regular expression match in an mmap'ed file
54 match
= re
.search('[A-Za-z]+', m
)
56 print ' ERROR: regex match on mmap failed!'
58 start
, end
= match
.span(0)
61 print ' Regex match on mmap (page start, length of match):',
62 print start
/ float(PAGESIZE
), length
64 vereq(start
, PAGESIZE
)
65 vereq(end
, PAGESIZE
+ 6)
67 # test seeking around (try to overflow the seek implementation)
69 print ' Seek to zeroth byte'
72 print ' Seek to 42nd byte'
75 print ' Seek to last byte'
76 vereq(m
.tell(), len(m
))
78 print ' Try to seek to negative position...'
84 verify(0, 'expected a ValueError but did not get it')
86 print ' Try to seek beyond end of mmap...'
92 verify(0, 'expected a ValueError but did not get it')
94 print ' Try to seek to negative position...'
100 verify(0, 'expected a ValueError but did not get it')
103 print ' Attempting resize()'
107 # resize() not supported
108 # No messages are printed, since the output of this test suite
109 # would then be different across platforms.
112 # resize() is supported
113 verify(len(m
) == 512,
114 "len(m) is %d, but expecting 512" % (len(m
),) )
115 # Check that we can no longer seek beyond the new size.
121 verify(0, 'Could seek beyond the new size')
123 # Check that the underlying file is truncated too
127 verify(f
.tell() == 512, 'Underlying file not truncated')
129 verify(m
.size() == 512, 'New size not reflected in file')
143 # Test for "access" keyword parameter
146 print " Creating", mapsize
, "byte test data file."
147 open(TESTFN
, "wb").write("a"*mapsize
)
148 print " Opening mmap with access=ACCESS_READ"
149 f
= open(TESTFN
, "rb")
150 m
= mmap
.mmap(f
.fileno(), mapsize
, access
=mmap
.ACCESS_READ
)
151 verify(m
[:] == 'a'*mapsize
, "Readonly memory map data incorrect.")
153 print " Ensuring that readonly mmap can't be slice assigned."
159 verify(0, "Able to write to readonly memory map")
161 print " Ensuring that readonly mmap can't be item assigned."
167 verify(0, "Able to write to readonly memory map")
169 print " Ensuring that readonly mmap can't be write() to."
176 verify(0, "Able to write to readonly memory map")
178 print " Ensuring that readonly mmap can't be write_byte() to."
185 verify(0, "Able to write to readonly memory map")
187 print " Ensuring that readonly mmap can't be resized."
190 except SystemError: # resize is not universally supported
195 verify(0, "Able to resize readonly memory map")
197 verify(open(TESTFN
, "rb").read() == 'a'*mapsize
,
198 "Readonly memory map data file was modified")
200 print " Opening mmap with size too big"
202 f
= open(TESTFN
, "r+b")
204 m
= mmap
.mmap(f
.fileno(), mapsize
+1)
206 # we do not expect a ValueError on Windows
207 # CAUTION: This also changes the size of the file on disk, and
208 # later tests assume that the length hasn't changed. We need to
210 if sys
.platform
.startswith('win'):
211 verify(0, "Opening mmap with size+1 should work on Windows.")
213 # we expect a ValueError on Unix, but not on Windows
214 if not sys
.platform
.startswith('win'):
215 verify(0, "Opening mmap with size+1 should raise ValueError.")
218 if sys
.platform
.startswith('win'):
219 # Repair damage from the resizing test.
220 f
= open(TESTFN
, 'r+b')
224 print " Opening mmap with access=ACCESS_WRITE"
225 f
= open(TESTFN
, "r+b")
226 m
= mmap
.mmap(f
.fileno(), mapsize
, access
=mmap
.ACCESS_WRITE
)
227 print " Modifying write-through memory map."
229 verify(m
[:] == 'c'*mapsize
,
230 "Write-through memory map memory not updated properly.")
234 f
= open(TESTFN
, 'rb')
237 verify(stuff
== 'c'*mapsize
,
238 "Write-through memory map data file not updated properly.")
240 print " Opening mmap with access=ACCESS_COPY"
241 f
= open(TESTFN
, "r+b")
242 m
= mmap
.mmap(f
.fileno(), mapsize
, access
=mmap
.ACCESS_COPY
)
243 print " Modifying copy-on-write memory map."
245 verify(m
[:] == 'd' * mapsize
,
246 "Copy-on-write memory map data not written correctly.")
248 verify(open(TESTFN
, "rb").read() == 'c'*mapsize
,
249 "Copy-on-write test data file should not be modified.")
251 print " Ensuring copy-on-write maps cannot be resized."
256 verify(0, "Copy-on-write mmap resize did not raise exception.")
259 print " Ensuring invalid access parameter raises exception."
260 f
= open(TESTFN
, "r+b")
261 m
= mmap
.mmap(f
.fileno(), mapsize
, access
=4)
265 verify(0, "Invalid access code should have raised exception.")
267 if os
.name
== "posix":
268 # Try incompatible flags, prot and access parameters.
269 f
= open(TESTFN
, "r+b")
271 m
= mmap
.mmap(f
.fileno(), mapsize
, flags
=mmap
.MAP_PRIVATE
,
272 prot
=mmap
.PROT_READ
, access
=mmap
.ACCESS_WRITE
)
276 verify(0, "Incompatible parameters should raise ValueError.")
284 print ' Try opening a bad file descriptor...'
290 verify(0, 'expected a mmap.error but did not get it')
292 # Do a tougher .find() test. SF bug 515943 pointed out that, in 2.2,
293 # searching for data with embedded \0 bytes didn't work.
294 f
= open(TESTFN
, 'w+')
296 try: # unlink TESTFN no matter what
297 data
= 'aabaac\x00deef\x00\x00aa\x00'
301 m
= mmap
.mmap(f
.fileno(), n
)
304 for start
in range(n
+1):
305 for finish
in range(start
, n
+1):
306 slice = data
[start
: finish
]
307 vereq(m
.find(slice), data
.find(slice))
308 vereq(m
.find(slice + 'x'), -1)
314 # make sure a double close doesn't crash on Solaris (Bug# 665913)
315 f
= open(TESTFN
, 'w+')
317 try: # unlink TESTFN no matter what
318 f
.write(2**16 * 'a') # Arbitrary character
322 mf
= mmap
.mmap(f
.fileno(), 2**16, access
=mmap
.ACCESS_READ
)
330 # test mapping of entire file by passing 0 for map length
331 if hasattr(os
, "stat"):
332 print " Ensuring that passing 0 as map length sets map size to current file size."
333 f
= open(TESTFN
, "w+")
336 f
.write(2**16 * 'm') # Arbitrary character
339 f
= open(TESTFN
, "rb+")
340 mf
= mmap
.mmap(f
.fileno(), 0)
341 verify(len(mf
) == 2**16, "Map size should equal file size.")
342 vereq(mf
.read(2**16), 2**16 * "m")
349 # test mapping of entire file by passing 0 for map length
350 if hasattr(os
, "stat"):
351 print " Ensuring that passing 0 as map length sets map size to current file size."
352 f
= open(TESTFN
, "w+")
354 f
.write(2**16 * 'm') # Arbitrary character
357 f
= open(TESTFN
, "rb+")
358 mf
= mmap
.mmap(f
.fileno(), 0)
359 verify(len(mf
) == 2**16, "Map size should equal file size.")
360 vereq(mf
.read(2**16), 2**16 * "m")
367 # make move works everywhere (64-bit format problem earlier)
368 f
= open(TESTFN
, 'w+')
370 try: # unlink TESTFN no matter what
371 f
.write("ABCDEabcde") # Arbitrary character
374 mf
= mmap
.mmap(f
.fileno(), 10)
376 verify(mf
[:] == "ABCDEABCDE", "Map move should have duplicated front 5")