from test
.test_support
import verify
, vereq
, TESTFN
"Test mmap module on Unix systems and Windows"
# Create a file to be mmap'ed.
if os
.path
.exists(TESTFN
):
try: # unlink TESTFN no matter what
# Write 2 pages worth of data to the file
f
.write('\0'* (PAGESIZE
-3) )
m
= mmap
.mmap(f
.fileno(), 2 * PAGESIZE
)
print type(m
) # SF bug 128713: segfaulted on Linux
print ' Position of foo:', m
.find('foo') / float(PAGESIZE
), 'pages'
vereq(m
.find('foo'), PAGESIZE
)
print ' Length of file:', len(m
) / float(PAGESIZE
), 'pages'
vereq(len(m
), 2*PAGESIZE
)
print ' Contents of byte 0:', repr(m
[0])
print ' Contents of first 3 bytes:', repr(m
[0:3])
# Modify the file's content
print "\n Modifying file's content..."
m
[PAGESIZE
+3: PAGESIZE
+3+3] = 'bar'
# Check that the modification worked
print ' Contents of byte 0:', repr(m
[0])
print ' Contents of first 3 bytes:', repr(m
[0:3])
print ' Contents of second page:', repr(m
[PAGESIZE
-1 : PAGESIZE
+ 7])
vereq(m
[PAGESIZE
-1 : PAGESIZE
+ 7], '\0foobar\0')
# Test doing a regular expression match in an mmap'ed file
match
= re
.search('[A-Za-z]+', m
)
print ' ERROR: regex match on mmap failed!'
start
, end
= match
.span(0)
print ' Regex match on mmap (page start, length of match):',
print start
/ float(PAGESIZE
), length
# test seeking around (try to overflow the seek implementation)
print ' Seek to zeroth byte'
print ' Seek to 42nd byte'
print ' Seek to last byte'
print ' Try to seek to negative position...'
verify(0, 'expected a ValueError but did not get it')
print ' Try to seek beyond end of mmap...'
verify(0, 'expected a ValueError but did not get it')
print ' Try to seek to negative position...'
verify(0, 'expected a ValueError but did not get it')
print ' Attempting resize()'
# No messages are printed, since the output of this test suite
# would then be different across platforms.
"len(m) is %d, but expecting 512" % (len(m
),) )
# Check that we can no longer seek beyond the new size.
verify(0, 'Could seek beyond the new size')
# Check that the underlying file is truncated too
verify(f
.tell() == 512, 'Underlying file not truncated')
verify(m
.size() == 512, 'New size not reflected in file')
# Test for "access" keyword parameter
print " Creating", mapsize
, "byte test data file."
open(TESTFN
, "wb").write("a"*mapsize
)
print " Opening mmap with access=ACCESS_READ"
m
= mmap
.mmap(f
.fileno(), mapsize
, access
=mmap
.ACCESS_READ
)
verify(m
[:] == 'a'*mapsize
, "Readonly memory map data incorrect.")
print " Ensuring that readonly mmap can't be slice assigned."
verify(0, "Able to write to readonly memory map")
print " Ensuring that readonly mmap can't be item assigned."
verify(0, "Able to write to readonly memory map")
print " Ensuring that readonly mmap can't be write() to."
verify(0, "Able to write to readonly memory map")
print " Ensuring that readonly mmap can't be write_byte() to."
verify(0, "Able to write to readonly memory map")
print " Ensuring that readonly mmap can't be resized."
except SystemError: # resize is not universally supported
verify(0, "Able to resize readonly memory map")
verify(open(TESTFN
, "rb").read() == 'a'*mapsize
,
"Readonly memory map data file was modified")
print " Opening mmap with size too big"
m
= mmap
.mmap(f
.fileno(), mapsize
+1)
# we do not expect a ValueError on Windows
# CAUTION: This also changes the size of the file on disk, and
# later tests assume that the length hasn't changed. We need to
if sys
.platform
.startswith('win'):
verify(0, "Opening mmap with size+1 should work on Windows.")
# we expect a ValueError on Unix, but not on Windows
if not sys
.platform
.startswith('win'):
verify(0, "Opening mmap with size+1 should raise ValueError.")
if sys
.platform
.startswith('win'):
# Repair damage from the resizing test.
print " Opening mmap with access=ACCESS_WRITE"
m
= mmap
.mmap(f
.fileno(), mapsize
, access
=mmap
.ACCESS_WRITE
)
print " Modifying write-through memory map."
verify(m
[:] == 'c'*mapsize
,
"Write-through memory map memory not updated properly.")
verify(stuff
== 'c'*mapsize
,
"Write-through memory map data file not updated properly.")
print " Opening mmap with access=ACCESS_COPY"
m
= mmap
.mmap(f
.fileno(), mapsize
, access
=mmap
.ACCESS_COPY
)
print " Modifying copy-on-write memory map."
verify(m
[:] == 'd' * mapsize
,
"Copy-on-write memory map data not written correctly.")
verify(open(TESTFN
, "rb").read() == 'c'*mapsize
,
"Copy-on-write test data file should not be modified.")
print " Ensuring copy-on-write maps cannot be resized."
verify(0, "Copy-on-write mmap resize did not raise exception.")
print " Ensuring invalid access parameter raises exception."
m
= mmap
.mmap(f
.fileno(), mapsize
, access
=4)
verify(0, "Invalid access code should have raised exception.")
# Try incompatible flags, prot and access parameters.
m
= mmap
.mmap(f
.fileno(), mapsize
, flags
=mmap
.MAP_PRIVATE
,
prot
=mmap
.PROT_READ
, access
=mmap
.ACCESS_WRITE
)
verify(0, "Incompatible parameters should raise ValueError.")
# Do a tougher .find() test. SF bug 515943 pointed out that, in 2.2,
# searching for data with embedded \0 bytes didn't work.
try: # unlink TESTFN no matter what
data
= 'aabaac\x00deef\x00\x00aa\x00'
m
= mmap
.mmap(f
.fileno(), n
)
for finish
in range(start
, n
+1):
slice = data
[start
: finish
]
vereq(m
.find(slice), data
.find(slice))
vereq(m
.find(slice + 'x'), -1)
# make sure a double close doesn't crash on Solaris (Bug# 665913)
try: # unlink TESTFN no matter what
f
.write(2**16 * 'a') # Arbitrary character
mf
= mmap
.mmap(f
.fileno(), 2**16, access
=mmap
.ACCESS_READ
)