blob: d1e02ed01e0ca6ad6721790a5fec8759908e9c6c [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
8from test.test_support import run_unittest, TESTFN, verbose, requires, \
9 TestSkipped, unlink
Trent Mickf29f47b2000-08-11 19:02:59 +000010
Martin v. Löwisdf8adcd2001-12-11 17:57:26 +000011try:
12 import signal
13 # The default handler for SIGXFSZ is to abort the process.
14 # By ignoring it, system calls exceeding the file size resource
15 # limit will raise IOError instead of crashing the interpreter.
16 oldhandler = signal.signal(signal.SIGXFSZ, signal.SIG_IGN)
17except (ImportError, AttributeError):
18 pass
19
Guido van Rossuma31ddbb2001-09-10 15:03:18 +000020# create >2GB file (2GB = 2147483648 bytes)
Guido van Rossume2a383d2007-01-15 16:59:06 +000021size = 2500000000
Guido van Rossuma31ddbb2001-09-10 15:03:18 +000022
23
Christian Heimes77c02eb2008-02-09 02:18:51 +000024class TestCase(unittest.TestCase):
25 """Test that each file function works as expected for a large
26 (i.e. > 2GB, do we have to check > 4GB) files.
27 """
28
29 def test_seek(self):
30 if verbose:
31 print('create large file via seek (may be sparse file) ...')
32 f = open(TESTFN, 'wb')
33 try:
Alexandre Vassalottia351f772008-03-03 02:59:49 +000034 f.write(b'z')
Christian Heimes77c02eb2008-02-09 02:18:51 +000035 f.seek(0)
36 f.seek(size)
Alexandre Vassalottia351f772008-03-03 02:59:49 +000037 f.write(b'a')
Christian Heimes77c02eb2008-02-09 02:18:51 +000038 f.flush()
39 if verbose:
40 print('check file size with os.fstat')
41 self.assertEqual(os.fstat(f.fileno())[stat.ST_SIZE], size+1)
42 finally:
43 f.close()
44
45 def test_osstat(self):
46 if verbose:
47 print('check file size with os.stat')
48 self.assertEqual(os.stat(TESTFN)[stat.ST_SIZE], size+1)
49
50 def test_seek_read(self):
51 if verbose:
52 print('play around with seek() and read() with the built largefile')
53 f = open(TESTFN, 'rb')
54 try:
55 self.assertEqual(f.tell(), 0)
Alexandre Vassalottia351f772008-03-03 02:59:49 +000056 self.assertEqual(f.read(1), b'z')
Christian Heimes77c02eb2008-02-09 02:18:51 +000057 self.assertEqual(f.tell(), 1)
58 f.seek(0)
59 self.assertEqual(f.tell(), 0)
60 f.seek(0, 0)
61 self.assertEqual(f.tell(), 0)
62 f.seek(42)
63 self.assertEqual(f.tell(), 42)
64 f.seek(42, 0)
65 self.assertEqual(f.tell(), 42)
66 f.seek(42, 1)
67 self.assertEqual(f.tell(), 84)
68 f.seek(0, 1)
69 self.assertEqual(f.tell(), 84)
70 f.seek(0, 2) # seek from the end
71 self.assertEqual(f.tell(), size + 1 + 0)
72 f.seek(-10, 2)
73 self.assertEqual(f.tell(), size + 1 - 10)
74 f.seek(-size-1, 2)
75 self.assertEqual(f.tell(), 0)
76 f.seek(size)
77 self.assertEqual(f.tell(), size)
78 # the 'a' that was written at the end of file above
Alexandre Vassalottia351f772008-03-03 02:59:49 +000079 self.assertEqual(f.read(1), b'a')
Christian Heimes77c02eb2008-02-09 02:18:51 +000080 f.seek(-size-1, 1)
Alexandre Vassalottia351f772008-03-03 02:59:49 +000081 self.assertEqual(f.read(1), b'z')
Christian Heimes77c02eb2008-02-09 02:18:51 +000082 self.assertEqual(f.tell(), 1)
83 finally:
84 f.close()
85
86 def test_lseek(self):
87 if verbose:
88 print('play around with os.lseek() with the built largefile')
89 f = open(TESTFN, 'rb')
90 try:
91 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 finally:
102 f.close()
103
104 def test_truncate(self):
105 if verbose:
106 print('try truncate')
107 f = open(TESTFN, 'r+b')
108 # this is already decided before start running the test suite
109 # but we do it anyway for extra protection
110 if not hasattr(f, 'truncate'):
111 raise TestSkipped("open().truncate() not available on this system")
112 try:
113 f.seek(0, 2)
114 # else we've lost track of the true size
115 self.assertEqual(f.tell(), size+1)
116 # Cut it back via seek + truncate with no argument.
117 newsize = size - 10
118 f.seek(newsize)
119 f.truncate()
120 self.assertEqual(f.tell(), newsize) # else pointer moved
121 f.seek(0, 2)
122 self.assertEqual(f.tell(), newsize) # else wasn't truncated
123 # Ensure that truncate(smaller than true size) shrinks
124 # the file.
125 newsize -= 1
126 f.seek(42)
127 f.truncate(newsize)
128 self.assertEqual(f.tell(), 42) # else pointer moved
129 f.seek(0, 2)
130 self.assertEqual(f.tell(), newsize) # else wasn't truncated
131 # XXX truncate(larger than true size) is ill-defined
132 # across platform; cut it waaaaay back
133 f.seek(0)
134 f.truncate(1)
135 self.assertEqual(f.tell(), 0) # else pointer moved
136 self.assertEqual(len(f.read()), 1) # else wasn't truncated
137 finally:
138 f.close()
139
140def main_test():
141 # On Windows and Mac OSX this test comsumes large resources; It
142 # takes a long time to build the >2GB file and takes >2GB of disk
143 # space therefore the resource must be enabled to run this test.
144 # If not, nothing after this line stanza will be executed.
145 if sys.platform[:3] == 'win' or sys.platform == 'darwin':
146 requires('largefile',
147 'test requires %s bytes and a long time to run' % str(size))
Guido van Rossum47f40342001-09-10 13:34:12 +0000148 else:
Christian Heimes77c02eb2008-02-09 02:18:51 +0000149 # Only run if the current filesystem supports large files.
150 # (Skip this test on Windows, since we now always support
151 # large files.)
152 f = open(TESTFN, 'wb')
153 try:
154 # 2**31 == 2147483648
155 f.seek(2147483649)
156 # Seeking is not enough of a test: you must write and
157 # flush, too!
Alexandre Vassalottia351f772008-03-03 02:59:49 +0000158 f.write(b'x')
Christian Heimes77c02eb2008-02-09 02:18:51 +0000159 f.flush()
160 except (IOError, OverflowError):
161 f.close()
162 unlink(TESTFN)
163 raise TestSkipped("filesystem does not have largefile support")
164 else:
165 f.close()
166 suite = unittest.TestSuite()
167 suite.addTest(TestCase('test_seek'))
168 suite.addTest(TestCase('test_osstat'))
169 suite.addTest(TestCase('test_seek_read'))
170 suite.addTest(TestCase('test_lseek'))
171 f = open(TESTFN, 'w')
172 if hasattr(f, 'truncate'):
173 suite.addTest(TestCase('test_truncate'))
Brett Cannon7f757ed2008-03-03 02:31:43 +0000174 f.close()
175 unlink(TESTFN)
176 run_unittest(suite)
177 unlink(TESTFN)
Guido van Rossum47f40342001-09-10 13:34:12 +0000178
Christian Heimes77c02eb2008-02-09 02:18:51 +0000179if __name__ == '__main__':
180 main_test()