blob: 1c6297ac7c098feab7690eab7199e02aa210d5bf [file] [log] [blame]
Christian Heimes77c02eb2008-02-09 02:18:51 +00001"""Test largefile support on system where this makes sense.
2"""
Trent Mickf29f47b2000-08-11 19:02:59 +00003
Christian Heimes77c02eb2008-02-09 02:18:51 +00004import os
5import stat
6import sys
7import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00008from test.support import run_unittest, TESTFN, verbose, requires, \
Benjamin Petersone549ead2009-03-28 21:42:05 +00009 unlink
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000010import io # C implementation of io
11import _pyio as pyio # Python implementation of io
Trent Mickf29f47b2000-08-11 19:02:59 +000012
Martin v. Löwisdf8adcd2001-12-11 17:57:26 +000013try:
14 import signal
15 # The default handler for SIGXFSZ is to abort the process.
16 # By ignoring it, system calls exceeding the file size resource
17 # limit will raise IOError instead of crashing the interpreter.
18 oldhandler = signal.signal(signal.SIGXFSZ, signal.SIG_IGN)
19except (ImportError, AttributeError):
20 pass
21
Guido van Rossuma31ddbb2001-09-10 15:03:18 +000022# create >2GB file (2GB = 2147483648 bytes)
Guido van Rossume2a383d2007-01-15 16:59:06 +000023size = 2500000000
Guido van Rossuma31ddbb2001-09-10 15:03:18 +000024
25
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000026class LargeFileTest(unittest.TestCase):
Christian Heimes77c02eb2008-02-09 02:18:51 +000027 """Test that each file function works as expected for a large
28 (i.e. > 2GB, do we have to check > 4GB) files.
Christian Heimes180510d2008-03-03 19:15:45 +000029
30 NOTE: the order of execution of the test methods is important! test_seek
31 must run first to create the test file. File cleanup must also be handled
32 outside the test instances because of this.
33
Christian Heimes77c02eb2008-02-09 02:18:51 +000034 """
35
36 def test_seek(self):
37 if verbose:
38 print('create large file via seek (may be sparse file) ...')
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000039 with self.open(TESTFN, 'wb') as f:
Alexandre Vassalottia351f772008-03-03 02:59:49 +000040 f.write(b'z')
Christian Heimes77c02eb2008-02-09 02:18:51 +000041 f.seek(0)
42 f.seek(size)
Alexandre Vassalottia351f772008-03-03 02:59:49 +000043 f.write(b'a')
Christian Heimes77c02eb2008-02-09 02:18:51 +000044 f.flush()
45 if verbose:
46 print('check file size with os.fstat')
47 self.assertEqual(os.fstat(f.fileno())[stat.ST_SIZE], size+1)
Christian Heimes77c02eb2008-02-09 02:18:51 +000048
49 def test_osstat(self):
50 if verbose:
51 print('check file size with os.stat')
52 self.assertEqual(os.stat(TESTFN)[stat.ST_SIZE], size+1)
53
54 def test_seek_read(self):
55 if verbose:
56 print('play around with seek() and read() with the built largefile')
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000057 with self.open(TESTFN, 'rb') as f:
Christian Heimes77c02eb2008-02-09 02:18:51 +000058 self.assertEqual(f.tell(), 0)
Alexandre Vassalottia351f772008-03-03 02:59:49 +000059 self.assertEqual(f.read(1), b'z')
Christian Heimes77c02eb2008-02-09 02:18:51 +000060 self.assertEqual(f.tell(), 1)
61 f.seek(0)
62 self.assertEqual(f.tell(), 0)
63 f.seek(0, 0)
64 self.assertEqual(f.tell(), 0)
65 f.seek(42)
66 self.assertEqual(f.tell(), 42)
67 f.seek(42, 0)
68 self.assertEqual(f.tell(), 42)
69 f.seek(42, 1)
70 self.assertEqual(f.tell(), 84)
71 f.seek(0, 1)
72 self.assertEqual(f.tell(), 84)
73 f.seek(0, 2) # seek from the end
74 self.assertEqual(f.tell(), size + 1 + 0)
75 f.seek(-10, 2)
76 self.assertEqual(f.tell(), size + 1 - 10)
77 f.seek(-size-1, 2)
78 self.assertEqual(f.tell(), 0)
79 f.seek(size)
80 self.assertEqual(f.tell(), size)
81 # the 'a' that was written at the end of file above
Alexandre Vassalottia351f772008-03-03 02:59:49 +000082 self.assertEqual(f.read(1), b'a')
Christian Heimes77c02eb2008-02-09 02:18:51 +000083 f.seek(-size-1, 1)
Alexandre Vassalottia351f772008-03-03 02:59:49 +000084 self.assertEqual(f.read(1), b'z')
Christian Heimes77c02eb2008-02-09 02:18:51 +000085 self.assertEqual(f.tell(), 1)
Christian Heimes77c02eb2008-02-09 02:18:51 +000086
87 def test_lseek(self):
88 if verbose:
89 print('play around with os.lseek() with the built largefile')
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000090 with self.open(TESTFN, 'rb') as f:
Christian Heimes77c02eb2008-02-09 02:18:51 +000091 self.assertEqual(os.lseek(f.fileno(), 0, 0), 0)
92 self.assertEqual(os.lseek(f.fileno(), 42, 0), 42)
93 self.assertEqual(os.lseek(f.fileno(), 42, 1), 84)
94 self.assertEqual(os.lseek(f.fileno(), 0, 1), 84)
95 self.assertEqual(os.lseek(f.fileno(), 0, 2), size+1+0)
96 self.assertEqual(os.lseek(f.fileno(), -10, 2), size+1-10)
97 self.assertEqual(os.lseek(f.fileno(), -size-1, 2), 0)
98 self.assertEqual(os.lseek(f.fileno(), size, 0), size)
99 # the 'a' that was written at the end of file above
Alexandre Vassalottia351f772008-03-03 02:59:49 +0000100 self.assertEqual(f.read(1), b'a')
Christian Heimes77c02eb2008-02-09 02:18:51 +0000101
102 def test_truncate(self):
103 if verbose:
104 print('try truncate')
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000105 with self.open(TESTFN, 'r+b') as f:
Christian Heimes180510d2008-03-03 19:15:45 +0000106 # this is already decided before start running the test suite
107 # but we do it anyway for extra protection
108 if not hasattr(f, 'truncate'):
Benjamin Petersone549ead2009-03-28 21:42:05 +0000109 raise unittest.SkipTest("open().truncate() not available on this system")
Christian Heimes77c02eb2008-02-09 02:18:51 +0000110 f.seek(0, 2)
111 # else we've lost track of the true size
112 self.assertEqual(f.tell(), size+1)
113 # Cut it back via seek + truncate with no argument.
114 newsize = size - 10
115 f.seek(newsize)
116 f.truncate()
117 self.assertEqual(f.tell(), newsize) # else pointer moved
118 f.seek(0, 2)
119 self.assertEqual(f.tell(), newsize) # else wasn't truncated
120 # Ensure that truncate(smaller than true size) shrinks
121 # the file.
122 newsize -= 1
123 f.seek(42)
124 f.truncate(newsize)
Antoine Pitrou905a2ff2010-01-31 22:47:27 +0000125 self.assertEqual(f.tell(), 42)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000126 f.seek(0, 2)
127 self.assertEqual(f.tell(), newsize)
Christian Heimes77c02eb2008-02-09 02:18:51 +0000128 # XXX truncate(larger than true size) is ill-defined
129 # across platform; cut it waaaaay back
130 f.seek(0)
131 f.truncate(1)
Antoine Pitrou905a2ff2010-01-31 22:47:27 +0000132 self.assertEqual(f.tell(), 0) # else pointer moved
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000133 f.seek(0)
Christian Heimes77c02eb2008-02-09 02:18:51 +0000134 self.assertEqual(len(f.read()), 1) # else wasn't truncated
Christian Heimes77c02eb2008-02-09 02:18:51 +0000135
Antoine Pitroua28fcfd2009-03-13 23:42:55 +0000136 def test_seekable(self):
137 # Issue #5016; seekable() can return False when the current position
138 # is negative when truncated to an int.
139 for pos in (2**31-1, 2**31, 2**31+1):
140 with self.open(TESTFN, 'rb') as f:
141 f.seek(pos)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000142 self.assertTrue(f.seekable())
Antoine Pitroua28fcfd2009-03-13 23:42:55 +0000143
144
Christian Heimes180510d2008-03-03 19:15:45 +0000145def test_main():
Christian Heimes77c02eb2008-02-09 02:18:51 +0000146 # On Windows and Mac OSX this test comsumes large resources; It
147 # takes a long time to build the >2GB file and takes >2GB of disk
148 # space therefore the resource must be enabled to run this test.
149 # If not, nothing after this line stanza will be executed.
150 if sys.platform[:3] == 'win' or sys.platform == 'darwin':
151 requires('largefile',
152 'test requires %s bytes and a long time to run' % str(size))
Guido van Rossum47f40342001-09-10 13:34:12 +0000153 else:
Christian Heimes77c02eb2008-02-09 02:18:51 +0000154 # Only run if the current filesystem supports large files.
155 # (Skip this test on Windows, since we now always support
156 # large files.)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000157 f = open(TESTFN, 'wb', buffering=0)
Christian Heimes77c02eb2008-02-09 02:18:51 +0000158 try:
159 # 2**31 == 2147483648
160 f.seek(2147483649)
161 # Seeking is not enough of a test: you must write and
162 # flush, too!
Alexandre Vassalottia351f772008-03-03 02:59:49 +0000163 f.write(b'x')
Christian Heimes77c02eb2008-02-09 02:18:51 +0000164 f.flush()
165 except (IOError, OverflowError):
166 f.close()
167 unlink(TESTFN)
Benjamin Petersone549ead2009-03-28 21:42:05 +0000168 raise unittest.SkipTest("filesystem does not have largefile support")
Christian Heimes77c02eb2008-02-09 02:18:51 +0000169 else:
170 f.close()
171 suite = unittest.TestSuite()
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000172 for _open, prefix in [(io.open, 'C'), (pyio.open, 'Py')]:
173 class TestCase(LargeFileTest):
174 pass
175 TestCase.open = staticmethod(_open)
176 TestCase.__name__ = prefix + LargeFileTest.__name__
177 suite.addTest(TestCase('test_seek'))
178 suite.addTest(TestCase('test_osstat'))
179 suite.addTest(TestCase('test_seek_read'))
180 suite.addTest(TestCase('test_lseek'))
181 with _open(TESTFN, 'wb') as f:
182 if hasattr(f, 'truncate'):
183 suite.addTest(TestCase('test_truncate'))
Antoine Pitroua28fcfd2009-03-13 23:42:55 +0000184 suite.addTest(TestCase('test_seekable'))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000185 unlink(TESTFN)
Christian Heimes180510d2008-03-03 19:15:45 +0000186 try:
187 run_unittest(suite)
188 finally:
189 unlink(TESTFN)
Guido van Rossum47f40342001-09-10 13:34:12 +0000190
Christian Heimes77c02eb2008-02-09 02:18:51 +0000191if __name__ == '__main__':
Christian Heimes180510d2008-03-03 19:15:45 +0000192 test_main()