0001 from test.test_support import verify, vereq, TESTFN 0002 import mmap 0003 import os, re 0004 0005 PAGESIZE = mmap.PAGESIZE 0006 0007 def test_both(): 0008 "Test mmap module on Unix systems and Windows" 0009 0010 # Create a file to be mmap'ed. 0011 if os.path.exists(TESTFN): 0012 os.unlink(TESTFN) 0013 f = open(TESTFN, 'w+') 0014 0015 try: # unlink TESTFN no matter what 0016 # Write 2 pages worth of data to the file 0017 f.write('\0'* PAGESIZE) 0018 f.write('foo') 0019 f.write('\0'* (PAGESIZE-3) ) 0020 f.flush() 0021 m = mmap.mmap(f.fileno(), 2 * PAGESIZE) 0022 f.close() 0023 0024 # Simple sanity checks 0025 0026 print type(m) # SF bug 128713: segfaulted on Linux 0027 print ' Position of foo:', m.find('foo') / float(PAGESIZE), 'pages' 0028 vereq(m.find('foo'), PAGESIZE) 0029 0030 print ' Length of file:', len(m) / float(PAGESIZE), 'pages' 0031 vereq(len(m), 2*PAGESIZE) 0032 0033 print ' Contents of byte 0:', repr(m[0]) 0034 vereq(m[0], '\0') 0035 print ' Contents of first 3 bytes:', repr(m[0:3]) 0036 vereq(m[0:3], '\0\0\0') 0037 0038 # Modify the file's content 0039 print "\n Modifying file's content..." 0040 m[0] = '3' 0041 m[PAGESIZE +3: PAGESIZE +3+3] = 'bar' 0042 0043 # Check that the modification worked 0044 print ' Contents of byte 0:', repr(m[0]) 0045 vereq(m[0], '3') 0046 print ' Contents of first 3 bytes:', repr(m[0:3]) 0047 vereq(m[0:3], '3\0\0') 0048 print ' Contents of second page:', repr(m[PAGESIZE-1 : PAGESIZE + 7]) 0049 vereq(m[PAGESIZE-1 : PAGESIZE + 7], '\0foobar\0') 0050 0051 m.flush() 0052 0053 # Test doing a regular expression match in an mmap'ed file 0054 match = re.search('[A-Za-z]+', m) 0055 if match is None: 0056 print ' ERROR: regex match on mmap failed!' 0057 else: 0058 start, end = match.span(0) 0059 length = end - start 0060 0061 print ' Regex match on mmap (page start, length of match):', 0062 print start / float(PAGESIZE), length 0063 0064 vereq(start, PAGESIZE) 0065 vereq(end, PAGESIZE + 6) 0066 0067 # test seeking around (try to overflow the seek implementation) 0068 m.seek(0,0) 0069 print ' Seek to zeroth byte' 0070 vereq(m.tell(), 0) 0071 m.seek(42,1) 0072 print ' Seek to 42nd byte' 0073 vereq(m.tell(), 42) 0074 m.seek(0,2) 0075 print ' Seek to last byte' 0076 vereq(m.tell(), len(m)) 0077 0078 print ' Try to seek to negative position...' 0079 try: 0080 m.seek(-1) 0081 except ValueError: 0082 pass 0083 else: 0084 verify(0, 'expected a ValueError but did not get it') 0085 0086 print ' Try to seek beyond end of mmap...' 0087 try: 0088 m.seek(1,2) 0089 except ValueError: 0090 pass 0091 else: 0092 verify(0, 'expected a ValueError but did not get it') 0093 0094 print ' Try to seek to negative position...' 0095 try: 0096 m.seek(-len(m)-1,2) 0097 except ValueError: 0098 pass 0099 else: 0100 verify(0, 'expected a ValueError but did not get it') 0101 0102 # Try resizing map 0103 print ' Attempting resize()' 0104 try: 0105 m.resize(512) 0106 except SystemError: 0107 # resize() not supported 0108 # No messages are printed, since the output of this test suite 0109 # would then be different across platforms. 0110 pass 0111 else: 0112 # resize() is supported 0113 verify(len(m) == 512, 0114 "len(m) is %d, but expecting 512" % (len(m),) ) 0115 # Check that we can no longer seek beyond the new size. 0116 try: 0117 m.seek(513,0) 0118 except ValueError: 0119 pass 0120 else: 0121 verify(0, 'Could seek beyond the new size') 0122 0123 m.close() 0124 0125 finally: 0126 try: 0127 f.close() 0128 except OSError: 0129 pass 0130 try: 0131 os.unlink(TESTFN) 0132 except OSError: 0133 pass 0134 0135 # Test for "access" keyword parameter 0136 try: 0137 mapsize = 10 0138 print " Creating", mapsize, "byte test data file." 0139 open(TESTFN, "wb").write("a"*mapsize) 0140 print " Opening mmap with access=ACCESS_READ" 0141 f = open(TESTFN, "rb") 0142 m = mmap.mmap(f.fileno(), mapsize, access=mmap.ACCESS_READ) 0143 verify(m[:] == 'a'*mapsize, "Readonly memory map data incorrect.") 0144 0145 print " Ensuring that readonly mmap can't be slice assigned." 0146 try: 0147 m[:] = 'b'*mapsize 0148 except TypeError: 0149 pass 0150 else: 0151 verify(0, "Able to write to readonly memory map") 0152 0153 print " Ensuring that readonly mmap can't be item assigned." 0154 try: 0155 m[0] = 'b' 0156 except TypeError: 0157 pass 0158 else: 0159 verify(0, "Able to write to readonly memory map") 0160 0161 print " Ensuring that readonly mmap can't be write() to." 0162 try: 0163 m.seek(0,0) 0164 m.write('abc') 0165 except TypeError: 0166 pass 0167 else: 0168 verify(0, "Able to write to readonly memory map") 0169 0170 print " Ensuring that readonly mmap can't be write_byte() to." 0171 try: 0172 m.seek(0,0) 0173 m.write_byte('d') 0174 except TypeError: 0175 pass 0176 else: 0177 verify(0, "Able to write to readonly memory map") 0178 0179 print " Ensuring that readonly mmap can't be resized." 0180 try: 0181 m.resize(2*mapsize) 0182 except SystemError: # resize is not universally supported 0183 pass 0184 except TypeError: 0185 pass 0186 else: 0187 verify(0, "Able to resize readonly memory map") 0188 del m, f 0189 verify(open(TESTFN, "rb").read() == 'a'*mapsize, 0190 "Readonly memory map data file was modified") 0191 0192 print " Opening mmap with size too big" 0193 import sys 0194 f = open(TESTFN, "r+b") 0195 try: 0196 m = mmap.mmap(f.fileno(), mapsize+1) 0197 except ValueError: 0198 # we do not expect a ValueError on Windows 0199 # CAUTION: This also changes the size of the file on disk, and 0200 # later tests assume that the length hasn't changed. We need to 0201 # repair that. 0202 if sys.platform.startswith('win'): 0203 verify(0, "Opening mmap with size+1 should work on Windows.") 0204 else: 0205 # we expect a ValueError on Unix, but not on Windows 0206 if not sys.platform.startswith('win'): 0207 verify(0, "Opening mmap with size+1 should raise ValueError.") 0208 m.close() 0209 f.close() 0210 if sys.platform.startswith('win'): 0211 # Repair damage from the resizing test. 0212 f = open(TESTFN, 'r+b') 0213 f.truncate(mapsize) 0214 f.close() 0215 0216 print " Opening mmap with access=ACCESS_WRITE" 0217 f = open(TESTFN, "r+b") 0218 m = mmap.mmap(f.fileno(), mapsize, access=mmap.ACCESS_WRITE) 0219 print " Modifying write-through memory map." 0220 m[:] = 'c'*mapsize 0221 verify(m[:] == 'c'*mapsize, 0222 "Write-through memory map memory not updated properly.") 0223 m.flush() 0224 m.close() 0225 f.close() 0226 f = open(TESTFN, 'rb') 0227 stuff = f.read() 0228 f.close() 0229 verify(stuff == 'c'*mapsize, 0230 "Write-through memory map data file not updated properly.") 0231 0232 print " Opening mmap with access=ACCESS_COPY" 0233 f = open(TESTFN, "r+b") 0234 m = mmap.mmap(f.fileno(), mapsize, access=mmap.ACCESS_COPY) 0235 print " Modifying copy-on-write memory map." 0236 m[:] = 'd'*mapsize 0237 verify(m[:] == 'd' * mapsize, 0238 "Copy-on-write memory map data not written correctly.") 0239 m.flush() 0240 verify(open(TESTFN, "rb").read() == 'c'*mapsize, 0241 "Copy-on-write test data file should not be modified.") 0242 try: 0243 print " Ensuring copy-on-write maps cannot be resized." 0244 m.resize(2*mapsize) 0245 except TypeError: 0246 pass 0247 else: 0248 verify(0, "Copy-on-write mmap resize did not raise exception.") 0249 del m, f 0250 try: 0251 print " Ensuring invalid access parameter raises exception." 0252 f = open(TESTFN, "r+b") 0253 m = mmap.mmap(f.fileno(), mapsize, access=4) 0254 except ValueError: 0255 pass 0256 else: 0257 verify(0, "Invalid access code should have raised exception.") 0258 0259 if os.name == "posix": 0260 # Try incompatible flags, prot and access parameters. 0261 f = open(TESTFN, "r+b") 0262 try: 0263 m = mmap.mmap(f.fileno(), mapsize, flags=mmap.MAP_PRIVATE, 0264 prot=mmap.PROT_READ, access=mmap.ACCESS_WRITE) 0265 except ValueError: 0266 pass 0267 else: 0268 verify(0, "Incompatible parameters should raise ValueError.") 0269 f.close() 0270 finally: 0271 try: 0272 os.unlink(TESTFN) 0273 except OSError: 0274 pass 0275 0276 # Do a tougher .find() test. SF bug 515943 pointed out that, in 2.2, 0277 # searching for data with embedded \0 bytes didn't work. 0278 f = open(TESTFN, 'w+') 0279 0280 try: # unlink TESTFN no matter what 0281 data = 'aabaac\x00deef\x00\x00aa\x00' 0282 n = len(data) 0283 f.write(data) 0284 f.flush() 0285 m = mmap.mmap(f.fileno(), n) 0286 f.close() 0287 0288 for start in range(n+1): 0289 for finish in range(start, n+1): 0290 slice = data[start : finish] 0291 vereq(m.find(slice), data.find(slice)) 0292 vereq(m.find(slice + 'x'), -1) 0293 m.close() 0294 0295 finally: 0296 os.unlink(TESTFN) 0297 0298 # make sure a double close doesn't crash on Solaris (Bug# 665913) 0299 f = open(TESTFN, 'w+') 0300 0301 try: # unlink TESTFN no matter what 0302 f.write(2**16 * 'a') # Arbitrary character 0303 f.close() 0304 0305 f = open(TESTFN) 0306 mf = mmap.mmap(f.fileno(), 2**16, access=mmap.ACCESS_READ) 0307 mf.close() 0308 mf.close() 0309 f.close() 0310 0311 finally: 0312 os.unlink(TESTFN) 0313 0314 0315 print ' Test passed' 0316 0317 test_both() 0318
Generated by PyXR 0.9.4