/Lib/test/test_largefile.py

http://unladen-swallow.googlecode.com/ · Python · 177 lines · 128 code · 15 blank · 34 comment · 24 complexity · 84e96c99e8c06e16c7b0e616366eacd5 MD5 · raw file

  1. """Test largefile support on system where this makes sense.
  2. """
  3. import os
  4. import stat
  5. import sys
  6. import unittest
  7. from test.test_support import run_unittest, TESTFN, verbose, requires, \
  8. TestSkipped, unlink
  9. try:
  10. import signal
  11. # The default handler for SIGXFSZ is to abort the process.
  12. # By ignoring it, system calls exceeding the file size resource
  13. # limit will raise IOError instead of crashing the interpreter.
  14. oldhandler = signal.signal(signal.SIGXFSZ, signal.SIG_IGN)
  15. except (ImportError, AttributeError):
  16. pass
  17. # create >2GB file (2GB = 2147483648 bytes)
  18. size = 2500000000L
  19. class TestCase(unittest.TestCase):
  20. """Test that each file function works as expected for a large
  21. (i.e. > 2GB, do we have to check > 4GB) files.
  22. NOTE: the order of execution of the test methods is important! test_seek
  23. must run first to create the test file. File cleanup must also be handled
  24. outside the test instances because of this.
  25. """
  26. def test_seek(self):
  27. if verbose:
  28. print 'create large file via seek (may be sparse file) ...'
  29. with open(TESTFN, 'wb') as f:
  30. f.write('z')
  31. f.seek(0)
  32. f.seek(size)
  33. f.write('a')
  34. f.flush()
  35. if verbose:
  36. print 'check file size with os.fstat'
  37. self.assertEqual(os.fstat(f.fileno())[stat.ST_SIZE], size+1)
  38. def test_osstat(self):
  39. if verbose:
  40. print 'check file size with os.stat'
  41. self.assertEqual(os.stat(TESTFN)[stat.ST_SIZE], size+1)
  42. def test_seek_read(self):
  43. if verbose:
  44. print 'play around with seek() and read() with the built largefile'
  45. with open(TESTFN, 'rb') as f:
  46. self.assertEqual(f.tell(), 0)
  47. self.assertEqual(f.read(1), 'z')
  48. self.assertEqual(f.tell(), 1)
  49. f.seek(0)
  50. self.assertEqual(f.tell(), 0)
  51. f.seek(0, 0)
  52. self.assertEqual(f.tell(), 0)
  53. f.seek(42)
  54. self.assertEqual(f.tell(), 42)
  55. f.seek(42, 0)
  56. self.assertEqual(f.tell(), 42)
  57. f.seek(42, 1)
  58. self.assertEqual(f.tell(), 84)
  59. f.seek(0, 1)
  60. self.assertEqual(f.tell(), 84)
  61. f.seek(0, 2) # seek from the end
  62. self.assertEqual(f.tell(), size + 1 + 0)
  63. f.seek(-10, 2)
  64. self.assertEqual(f.tell(), size + 1 - 10)
  65. f.seek(-size-1, 2)
  66. self.assertEqual(f.tell(), 0)
  67. f.seek(size)
  68. self.assertEqual(f.tell(), size)
  69. # the 'a' that was written at the end of file above
  70. self.assertEqual(f.read(1), 'a')
  71. f.seek(-size-1, 1)
  72. self.assertEqual(f.read(1), 'z')
  73. self.assertEqual(f.tell(), 1)
  74. def test_lseek(self):
  75. if verbose:
  76. print 'play around with os.lseek() with the built largefile'
  77. with open(TESTFN, 'rb') as f:
  78. self.assertEqual(os.lseek(f.fileno(), 0, 0), 0)
  79. self.assertEqual(os.lseek(f.fileno(), 42, 0), 42)
  80. self.assertEqual(os.lseek(f.fileno(), 42, 1), 84)
  81. self.assertEqual(os.lseek(f.fileno(), 0, 1), 84)
  82. self.assertEqual(os.lseek(f.fileno(), 0, 2), size+1+0)
  83. self.assertEqual(os.lseek(f.fileno(), -10, 2), size+1-10)
  84. self.assertEqual(os.lseek(f.fileno(), -size-1, 2), 0)
  85. self.assertEqual(os.lseek(f.fileno(), size, 0), size)
  86. # the 'a' that was written at the end of file above
  87. self.assertEqual(f.read(1), 'a')
  88. def test_truncate(self):
  89. if verbose:
  90. print 'try truncate'
  91. with open(TESTFN, 'r+b') as f:
  92. # this is already decided before start running the test suite
  93. # but we do it anyway for extra protection
  94. if not hasattr(f, 'truncate'):
  95. raise TestSkipped, "open().truncate() not available on this system"
  96. f.seek(0, 2)
  97. # else we've lost track of the true size
  98. self.assertEqual(f.tell(), size+1)
  99. # Cut it back via seek + truncate with no argument.
  100. newsize = size - 10
  101. f.seek(newsize)
  102. f.truncate()
  103. self.assertEqual(f.tell(), newsize) # else pointer moved
  104. f.seek(0, 2)
  105. self.assertEqual(f.tell(), newsize) # else wasn't truncated
  106. # Ensure that truncate(smaller than true size) shrinks
  107. # the file.
  108. newsize -= 1
  109. f.seek(42)
  110. f.truncate(newsize)
  111. self.assertEqual(f.tell(), 42) # else pointer moved
  112. f.seek(0, 2)
  113. self.assertEqual(f.tell(), newsize) # else wasn't truncated
  114. # XXX truncate(larger than true size) is ill-defined
  115. # across platform; cut it waaaaay back
  116. f.seek(0)
  117. f.truncate(1)
  118. self.assertEqual(f.tell(), 0) # else pointer moved
  119. self.assertEqual(len(f.read()), 1) # else wasn't truncated
  120. def test_main():
  121. # On Windows and Mac OSX this test comsumes large resources; It
  122. # takes a long time to build the >2GB file and takes >2GB of disk
  123. # space therefore the resource must be enabled to run this test.
  124. # If not, nothing after this line stanza will be executed.
  125. if sys.platform[:3] == 'win' or sys.platform == 'darwin':
  126. requires('largefile',
  127. 'test requires %s bytes and a long time to run' % str(size))
  128. else:
  129. # Only run if the current filesystem supports large files.
  130. # (Skip this test on Windows, since we now always support
  131. # large files.)
  132. f = open(TESTFN, 'wb')
  133. try:
  134. # 2**31 == 2147483648
  135. f.seek(2147483649L)
  136. # Seeking is not enough of a test: you must write and
  137. # flush, too!
  138. f.write("x")
  139. f.flush()
  140. except (IOError, OverflowError):
  141. f.close()
  142. unlink(TESTFN)
  143. raise TestSkipped, "filesystem does not have largefile support"
  144. else:
  145. f.close()
  146. suite = unittest.TestSuite()
  147. suite.addTest(TestCase('test_seek'))
  148. suite.addTest(TestCase('test_osstat'))
  149. suite.addTest(TestCase('test_seek_read'))
  150. suite.addTest(TestCase('test_lseek'))
  151. with open(TESTFN, 'w') as f:
  152. if hasattr(f, 'truncate'):
  153. suite.addTest(TestCase('test_truncate'))
  154. unlink(TESTFN)
  155. try:
  156. run_unittest(suite)
  157. finally:
  158. unlink(TESTFN)
  159. if __name__ == '__main__':
  160. test_main()