diff options
Diffstat (limited to 'Lib/test/test_mmap.py')
-rw-r--r-- | Lib/test/test_mmap.py | 394 |
1 files changed, 156 insertions, 238 deletions
diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py index d2a24770cf..0b53823076 100644 --- a/Lib/test/test_mmap.py +++ b/Lib/test/test_mmap.py @@ -1,190 +1,158 @@ -from test.test_support import verify, vereq, TESTFN +from test.test_support import TESTFN, run_unittest import mmap +import unittest import os, re PAGESIZE = mmap.PAGESIZE -def test_both(): - "Test mmap module on Unix systems and Windows" +class MmapTests(unittest.TestCase): - # Create a file to be mmap'ed. - if os.path.exists(TESTFN): - os.unlink(TESTFN) - f = open(TESTFN, 'w+') + def setUp(self): + if os.path.exists(TESTFN): + os.unlink(TESTFN) - try: # unlink TESTFN no matter what - # Write 2 pages worth of data to the file - f.write('\0'* PAGESIZE) - f.write('foo') - f.write('\0'* (PAGESIZE-3) ) - f.flush() - m = mmap.mmap(f.fileno(), 2 * PAGESIZE) - f.close() + def tearDown(self): + try: + os.unlink(TESTFN) + except OSError: + pass - # Simple sanity checks + def test_basic(self): + # Test mmap module on Unix systems and Windows - print type(m) # SF bug 128713: segfaulted on Linux - print ' Position of foo:', m.find('foo') / float(PAGESIZE), 'pages' - vereq(m.find('foo'), PAGESIZE) + # Create a file to be mmap'ed. + f = open(TESTFN, 'w+') + try: + # Write 2 pages worth of data to the file + f.write('\0'* PAGESIZE) + f.write('foo') + f.write('\0'* (PAGESIZE-3) ) + f.flush() + m = mmap.mmap(f.fileno(), 2 * PAGESIZE) + f.close() - print ' Length of file:', len(m) / float(PAGESIZE), 'pages' - vereq(len(m), 2*PAGESIZE) + # Simple sanity checks - print ' Contents of byte 0:', repr(m[0]) - vereq(m[0], '\0') - print ' Contents of first 3 bytes:', repr(m[0:3]) - vereq(m[0:3], '\0\0\0') + tp = str(type(m)) # SF bug 128713: segfaulted on Linux + self.assertEqual(m.find('foo'), PAGESIZE) - # Modify the file's content - print "\n Modifying file's content..." - m[0] = '3' - m[PAGESIZE +3: PAGESIZE +3+3] = 'bar' + self.assertEqual(len(m), 2*PAGESIZE) - # Check that the modification worked - print ' Contents of byte 0:', repr(m[0]) - vereq(m[0], '3') - print ' Contents of first 3 bytes:', repr(m[0:3]) - vereq(m[0:3], '3\0\0') - print ' Contents of second page:', repr(m[PAGESIZE-1 : PAGESIZE + 7]) - vereq(m[PAGESIZE-1 : PAGESIZE + 7], '\0foobar\0') + self.assertEqual(m[0], '\0') + self.assertEqual(m[0:3], '\0\0\0') - m.flush() + # Modify the file's content + m[0] = '3' + m[PAGESIZE +3: PAGESIZE +3+3] = 'bar' - # Test doing a regular expression match in an mmap'ed file - match = re.search('[A-Za-z]+', m) - if match is None: - print ' ERROR: regex match on mmap failed!' - else: - start, end = match.span(0) - length = end - start - - print ' Regex match on mmap (page start, length of match):', - print start / float(PAGESIZE), length - - vereq(start, PAGESIZE) - vereq(end, PAGESIZE + 6) - - # test seeking around (try to overflow the seek implementation) - m.seek(0,0) - print ' Seek to zeroth byte' - vereq(m.tell(), 0) - m.seek(42,1) - print ' Seek to 42nd byte' - vereq(m.tell(), 42) - m.seek(0,2) - print ' Seek to last byte' - vereq(m.tell(), len(m)) - - print ' Try to seek to negative position...' - try: - m.seek(-1) - except ValueError: - pass - else: - verify(0, 'expected a ValueError but did not get it') + # Check that the modification worked + self.assertEqual(m[0], '3') + self.assertEqual(m[0:3], '3\0\0') + self.assertEqual(m[PAGESIZE-1 : PAGESIZE + 7], '\0foobar\0') - print ' Try to seek beyond end of mmap...' - try: - m.seek(1,2) - except ValueError: - pass - else: - verify(0, 'expected a ValueError but did not get it') + m.flush() - print ' Try to seek to negative position...' - try: - m.seek(-len(m)-1,2) - except ValueError: - pass - else: - verify(0, 'expected a ValueError but did not get it') + # Test doing a regular expression match in an mmap'ed file + match = re.search('[A-Za-z]+', m) + if match is None: + self.fail('regex match on mmap failed!') + else: + start, end = match.span(0) + length = end - start - # Try resizing map - print ' Attempting resize()' - try: - m.resize(512) - except SystemError: - # resize() not supported - # No messages are printed, since the output of this test suite - # would then be different across platforms. - pass - else: - # resize() is supported - verify(len(m) == 512, - "len(m) is %d, but expecting 512" % (len(m),) ) - # Check that we can no longer seek beyond the new size. + self.assertEqual(start, PAGESIZE) + self.assertEqual(end, PAGESIZE + 6) + + # test seeking around (try to overflow the seek implementation) + m.seek(0,0) + self.assertEqual(m.tell(), 0) + m.seek(42,1) + self.assertEqual(m.tell(), 42) + m.seek(0,2) + self.assertEqual(m.tell(), len(m)) + + # Try to seek to negative position... + self.assertRaises(ValueError, m.seek, -1) + + # Try to seek beyond end of mmap... + self.assertRaises(ValueError, m.seek, 1, 2) + + # Try to seek to negative position... + self.assertRaises(ValueError, m.seek, -len(m)-1, 2) + + # Try resizing map try: - m.seek(513,0) - except ValueError: + m.resize(512) + except SystemError: + # resize() not supported + # No messages are printed, since the output of this test suite + # would then be different across platforms. pass else: - verify(0, 'Could seek beyond the new size') + # resize() is supported + self.assertEqual(len(m), 512) + # Check that we can no longer seek beyond the new size. + self.assertRaises(ValueError, m.seek, 513, 0) + + # Check that the underlying file is truncated too + # (bug #728515) + f = open(TESTFN) + f.seek(0, 2) + self.assertEqual(f.tell(), 512) + f.close() + self.assertEqual(m.size(), 512) - # Check that the underlying file is truncated too - # (bug #728515) - f = open(TESTFN) - f.seek(0, 2) - verify(f.tell() == 512, 'Underlying file not truncated') - f.close() - verify(m.size() == 512, 'New size not reflected in file') - - m.close() + m.close() - finally: - try: - f.close() - except OSError: - pass - try: - os.unlink(TESTFN) - except OSError: - pass + finally: + try: + f.close() + except OSError: + pass - # Test for "access" keyword parameter - try: + def test_access_parameter(self): + # Test for "access" keyword parameter mapsize = 10 - print " Creating", mapsize, "byte test data file." open(TESTFN, "wb").write("a"*mapsize) - print " Opening mmap with access=ACCESS_READ" f = open(TESTFN, "rb") m = mmap.mmap(f.fileno(), mapsize, access=mmap.ACCESS_READ) - verify(m[:] == 'a'*mapsize, "Readonly memory map data incorrect.") + self.assertEqual(m[:], 'a'*mapsize, "Readonly memory map data incorrect.") - print " Ensuring that readonly mmap can't be slice assigned." + # Ensuring that readonly mmap can't be slice assigned try: m[:] = 'b'*mapsize except TypeError: pass else: - verify(0, "Able to write to readonly memory map") + self.fail("Able to write to readonly memory map") - print " Ensuring that readonly mmap can't be item assigned." + # Ensuring that readonly mmap can't be item assigned try: m[0] = 'b' except TypeError: pass else: - verify(0, "Able to write to readonly memory map") + self.fail("Able to write to readonly memory map") - print " Ensuring that readonly mmap can't be write() to." + # Ensuring that readonly mmap can't be write() to try: m.seek(0,0) m.write('abc') except TypeError: pass else: - verify(0, "Able to write to readonly memory map") + self.fail("Able to write to readonly memory map") - print " Ensuring that readonly mmap can't be write_byte() to." + # Ensuring that readonly mmap can't be write_byte() to try: m.seek(0,0) m.write_byte('d') except TypeError: pass else: - verify(0, "Able to write to readonly memory map") + self.fail("Able to write to readonly memory map") - print " Ensuring that readonly mmap can't be resized." + # Ensuring that readonly mmap can't be resized try: m.resize(2*mapsize) except SystemError: # resize is not universally supported @@ -192,12 +160,12 @@ def test_both(): except TypeError: pass else: - verify(0, "Able to resize readonly memory map") + self.fail("Able to resize readonly memory map") del m, f - verify(open(TESTFN, "rb").read() == 'a'*mapsize, + self.assertEqual(open(TESTFN, "rb").read(), 'a'*mapsize, "Readonly memory map data file was modified") - print " Opening mmap with size too big" + # Opening mmap with size too big import sys f = open(TESTFN, "r+b") try: @@ -208,11 +176,11 @@ def test_both(): # later tests assume that the length hasn't changed. We need to # repair that. if sys.platform.startswith('win'): - verify(0, "Opening mmap with size+1 should work on Windows.") + self.fail("Opening mmap with size+1 should work on Windows.") else: # 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.") + self.fail("Opening mmap with size+1 should raise ValueError.") m.close() f.close() if sys.platform.startswith('win'): @@ -221,12 +189,12 @@ def test_both(): f.truncate(mapsize) f.close() - print " Opening mmap with access=ACCESS_WRITE" + # Opening mmap with access=ACCESS_WRITE f = open(TESTFN, "r+b") m = mmap.mmap(f.fileno(), mapsize, access=mmap.ACCESS_WRITE) - print " Modifying write-through memory map." + # Modifying write-through memory map m[:] = 'c'*mapsize - verify(m[:] == 'c'*mapsize, + self.assertEqual(m[:], 'c'*mapsize, "Write-through memory map memory not updated properly.") m.flush() m.close() @@ -234,66 +202,45 @@ def test_both(): f = open(TESTFN, 'rb') stuff = f.read() f.close() - verify(stuff == 'c'*mapsize, + self.assertEqual(stuff, 'c'*mapsize, "Write-through memory map data file not updated properly.") - print " Opening mmap with access=ACCESS_COPY" + # Opening mmap with access=ACCESS_COPY f = open(TESTFN, "r+b") m = mmap.mmap(f.fileno(), mapsize, access=mmap.ACCESS_COPY) - print " Modifying copy-on-write memory map." + # Modifying copy-on-write memory map m[:] = 'd'*mapsize - verify(m[:] == 'd' * mapsize, + self.assertEqual(m[:], 'd' * mapsize, "Copy-on-write memory map data not written correctly.") m.flush() - verify(open(TESTFN, "rb").read() == 'c'*mapsize, + self.assertEqual(open(TESTFN, "rb").read(), 'c'*mapsize, "Copy-on-write test data file should not be modified.") - try: - print " Ensuring copy-on-write maps cannot be resized." - m.resize(2*mapsize) - except TypeError: - pass - else: - verify(0, "Copy-on-write mmap resize did not raise exception.") + # Ensuring copy-on-write maps cannot be resized + self.assertRaises(TypeError, m.resize, 2*mapsize) del m, f - try: - print " Ensuring invalid access parameter raises exception." - f = open(TESTFN, "r+b") - m = mmap.mmap(f.fileno(), mapsize, access=4) - except ValueError: - pass - else: - verify(0, "Invalid access code should have raised exception.") + + # Ensuring invalid access parameter raises exception + f = open(TESTFN, "r+b") + self.assertRaises(ValueError, mmap.mmap, f.fileno(), mapsize, access=4) + f.close() if os.name == "posix": # Try incompatible flags, prot and access parameters. f = open(TESTFN, "r+b") - try: - m = mmap.mmap(f.fileno(), mapsize, flags=mmap.MAP_PRIVATE, + self.assertRaises(ValueError, mmap.mmap, f.fileno(), mapsize, + flags=mmap.MAP_PRIVATE, prot=mmap.PROT_READ, access=mmap.ACCESS_WRITE) - except ValueError: - pass - else: - verify(0, "Incompatible parameters should raise ValueError.") f.close() - finally: - try: - os.unlink(TESTFN) - except OSError: - pass - print ' Try opening a bad file descriptor...' - try: - mmap.mmap(-2, 4096) - except mmap.error: - pass - else: - verify(0, 'expected a mmap.error but did not get it') + def test_bad_file_desc(self): + # Try opening a bad file descriptor... + self.assertRaises(mmap.error, mmap.mmap, -2, 4096) - # Do a tougher .find() test. SF bug 515943 pointed out that, in 2.2, - # searching for data with embedded \0 bytes didn't work. - f = open(TESTFN, 'w+') + def test_tougher_find(self): + # Do a tougher .find() test. SF bug 515943 pointed out that, in 2.2, + # searching for data with embedded \0 bytes didn't work. + f = open(TESTFN, 'w+') - try: # unlink TESTFN no matter what data = 'aabaac\x00deef\x00\x00aa\x00' n = len(data) f.write(data) @@ -304,17 +251,14 @@ def test_both(): for start in range(n+1): for finish in range(start, n+1): slice = data[start : finish] - vereq(m.find(slice), data.find(slice)) - vereq(m.find(slice + 'x'), -1) + self.assertEqual(m.find(slice), data.find(slice)) + self.assertEqual(m.find(slice + 'x'), -1) m.close() - finally: - os.unlink(TESTFN) + def test_double_close(self): + # make sure a double close doesn't crash on Solaris (Bug# 665913) + f = open(TESTFN, 'w+') - # make sure a double close doesn't crash on Solaris (Bug# 665913) - f = open(TESTFN, 'w+') - - try: # unlink TESTFN no matter what f.write(2**16 * 'a') # Arbitrary character f.close() @@ -324,72 +268,46 @@ def test_both(): mf.close() f.close() - finally: - os.unlink(TESTFN) - - # test mapping of entire file by passing 0 for map length - if hasattr(os, "stat"): - print " Ensuring that passing 0 as map length sets map size to current file size." - f = open(TESTFN, "w+") + def test_entire_file(self): + # test mapping of entire file by passing 0 for map length + if hasattr(os, "stat"): + f = open(TESTFN, "w+") - try: f.write(2**16 * 'm') # Arbitrary character f.close() f = open(TESTFN, "rb+") mf = mmap.mmap(f.fileno(), 0) - verify(len(mf) == 2**16, "Map size should equal file size.") - vereq(mf.read(2**16), 2**16 * "m") + self.assertEqual(len(mf), 2**16, "Map size should equal file size.") + self.assertEqual(mf.read(2**16), 2**16 * "m") mf.close() f.close() - finally: - os.unlink(TESTFN) - - # test mapping of entire file by passing 0 for map length - if hasattr(os, "stat"): - print " Ensuring that passing 0 as map length sets map size to current file size." - f = open(TESTFN, "w+") - try: - f.write(2**16 * 'm') # Arbitrary character - f.close() - - f = open(TESTFN, "rb+") - mf = mmap.mmap(f.fileno(), 0) - verify(len(mf) == 2**16, "Map size should equal file size.") - vereq(mf.read(2**16), 2**16 * "m") - mf.close() - f.close() - - finally: - os.unlink(TESTFN) - - # make move works everywhere (64-bit format problem earlier) - f = open(TESTFN, 'w+') + def test_move(self): + # make move works everywhere (64-bit format problem earlier) + f = open(TESTFN, 'w+') - try: # unlink TESTFN no matter what f.write("ABCDEabcde") # Arbitrary character f.flush() mf = mmap.mmap(f.fileno(), 10) mf.move(5, 0, 5) - verify(mf[:] == "ABCDEABCDE", "Map move should have duplicated front 5") + self.assertEqual(mf[:], "ABCDEABCDE", "Map move should have duplicated front 5") mf.close() f.close() - finally: - os.unlink(TESTFN) + def test_anonymous(self): + # anonymous mmap.mmap(-1, PAGE) + m = mmap.mmap(-1, PAGESIZE) + for x in xrange(PAGESIZE): + self.assertEqual(m[x], '\0', "anonymously mmap'ed contents should be zero") -def test_anon(): - print " anonymous mmap.mmap(-1, PAGESIZE)..." - m = mmap.mmap(-1, PAGESIZE) - for x in xrange(PAGESIZE): - verify(m[x] == '\0', "anonymously mmap'ed contents should be zero") + for x in xrange(PAGESIZE): + m[x] = ch = chr(x & 255) + self.assertEqual(m[x], ch) - for x in xrange(PAGESIZE): - m[x] = ch = chr(x & 255) - vereq(m[x], ch) +def test_main(): + run_unittest(MmapTests) -test_both() -test_anon() -print ' Test passed' +if __name__ == '__main__': + test_main() |