blob: 8060ea04e85526ac4cfcf9fed10a74182a7ce01b [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, \
Christian Heimes77c02eb2008-02-09 02:18:51 +00009 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.
Christian Heimes180510d2008-03-03 19:15:45 +000027
28 NOTE: the order of execution of the test methods is important! test_seek
29 must run first to create the test file. File cleanup must also be handled
30 outside the test instances because of this.
31
Christian Heimes77c02eb2008-02-09 02:18:51 +000032 """
33
34 def test_seek(self):
35 if verbose:
36 print('create large file via seek (may be sparse file) ...')
Christian Heimes180510d2008-03-03 19:15:45 +000037 with open(TESTFN, 'wb') as f:
Alexandre Vassalottia351f772008-03-03 02:59:49 +000038 f.write(b'z')
Christian Heimes77c02eb2008-02-09 02:18:51 +000039 f.seek(0)
40 f.seek(size)
Alexandre Vassalottia351f772008-03-03 02:59:49 +000041 f.write(b'a')
Christian Heimes77c02eb2008-02-09 02:18:51 +000042 f.flush()
43 if verbose:
44 print('check file size with os.fstat')
45 self.assertEqual(os.fstat(f.fileno())[stat.ST_SIZE], size+1)
Christian Heimes77c02eb2008-02-09 02:18:51 +000046
47 def test_osstat(self):
48 if verbose:
49 print('check file size with os.stat')
50 self.assertEqual(os.stat(TESTFN)[stat.ST_SIZE], size+1)
51
52 def test_seek_read(self):
53 if verbose:
54 print('play around with seek() and read() with the built largefile')
Christian Heimes180510d2008-03-03 19:15:45 +000055 with open(TESTFN, 'rb') as f:
Christian Heimes77c02eb2008-02-09 02:18:51 +000056 self.assertEqual(f.tell(), 0)
Alexandre Vassalottia351f772008-03-03 02:59:49 +000057 self.assertEqual(f.read(1), b'z')
Christian Heimes77c02eb2008-02-09 02:18:51 +000058 self.assertEqual(f.tell(), 1)
59 f.seek(0)
60 self.assertEqual(f.tell(), 0)
61 f.seek(0, 0)
62 self.assertEqual(f.tell(), 0)
63 f.seek(42)
64 self.assertEqual(f.tell(), 42)
65 f.seek(42, 0)
66 self.assertEqual(f.tell(), 42)
67 f.seek(42, 1)
68 self.assertEqual(f.tell(), 84)
69 f.seek(0, 1)
70 self.assertEqual(f.tell(), 84)
71 f.seek(0, 2) # seek from the end
72 self.assertEqual(f.tell(), size + 1 + 0)
73 f.seek(-10, 2)
74 self.assertEqual(f.tell(), size + 1 - 10)
75 f.seek(-size-1, 2)
76 self.assertEqual(f.tell(), 0)
77 f.seek(size)
78 self.assertEqual(f.tell(), size)
79 # the 'a' that was written at the end of file above
Alexandre Vassalottia351f772008-03-03 02:59:49 +000080 self.assertEqual(f.read(1), b'a')
Christian Heimes77c02eb2008-02-09 02:18:51 +000081 f.seek(-size-1, 1)
Alexandre Vassalottia351f772008-03-03 02:59:49 +000082 self.assertEqual(f.read(1), b'z')
Christian Heimes77c02eb2008-02-09 02:18:51 +000083 self.assertEqual(f.tell(), 1)
Christian Heimes77c02eb2008-02-09 02:18:51 +000084
85 def test_lseek(self):
86 if verbose:
87 print('play around with os.lseek() with the built largefile')
Christian Heimes180510d2008-03-03 19:15:45 +000088 with open(TESTFN, 'rb') as f:
Christian Heimes77c02eb2008-02-09 02:18:51 +000089 self.assertEqual(os.lseek(f.fileno(), 0, 0), 0)
90 self.assertEqual(os.lseek(f.fileno(), 42, 0), 42)
91 self.assertEqual(os.lseek(f.fileno(), 42, 1), 84)
92 self.assertEqual(os.lseek(f.fileno(), 0, 1), 84)
93 self.assertEqual(os.lseek(f.fileno(), 0, 2), size+1+0)
94 self.assertEqual(os.lseek(f.fileno(), -10, 2), size+1-10)
95 self.assertEqual(os.lseek(f.fileno(), -size-1, 2), 0)
96 self.assertEqual(os.lseek(f.fileno(), size, 0), size)
97 # the 'a' that was written at the end of file above
Alexandre Vassalottia351f772008-03-03 02:59:49 +000098 self.assertEqual(f.read(1), b'a')
Christian Heimes77c02eb2008-02-09 02:18:51 +000099
100 def test_truncate(self):
101 if verbose:
102 print('try truncate')
Christian Heimes180510d2008-03-03 19:15:45 +0000103 with open(TESTFN, 'r+b') as f:
104 # this is already decided before start running the test suite
105 # but we do it anyway for extra protection
106 if not hasattr(f, 'truncate'):
107 raise TestSkipped("open().truncate() not available on this system")
Christian Heimes77c02eb2008-02-09 02:18:51 +0000108 f.seek(0, 2)
109 # else we've lost track of the true size
110 self.assertEqual(f.tell(), size+1)
111 # Cut it back via seek + truncate with no argument.
112 newsize = size - 10
113 f.seek(newsize)
114 f.truncate()
115 self.assertEqual(f.tell(), newsize) # else pointer moved
116 f.seek(0, 2)
117 self.assertEqual(f.tell(), newsize) # else wasn't truncated
118 # Ensure that truncate(smaller than true size) shrinks
119 # the file.
120 newsize -= 1
121 f.seek(42)
122 f.truncate(newsize)
Christian Heimes77c02eb2008-02-09 02:18:51 +0000123 self.assertEqual(f.tell(), newsize) # else wasn't truncated
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000124 f.seek(0, 2)
125 self.assertEqual(f.tell(), newsize)
Christian Heimes77c02eb2008-02-09 02:18:51 +0000126 # XXX truncate(larger than true size) is ill-defined
127 # across platform; cut it waaaaay back
128 f.seek(0)
129 f.truncate(1)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000130 self.assertEqual(f.tell(), 1) # else pointer moved
131 f.seek(0)
Christian Heimes77c02eb2008-02-09 02:18:51 +0000132 self.assertEqual(len(f.read()), 1) # else wasn't truncated
Christian Heimes77c02eb2008-02-09 02:18:51 +0000133
Christian Heimes180510d2008-03-03 19:15:45 +0000134def test_main():
Christian Heimes77c02eb2008-02-09 02:18:51 +0000135 # On Windows and Mac OSX this test comsumes large resources; It
136 # takes a long time to build the >2GB file and takes >2GB of disk
137 # space therefore the resource must be enabled to run this test.
138 # If not, nothing after this line stanza will be executed.
139 if sys.platform[:3] == 'win' or sys.platform == 'darwin':
140 requires('largefile',
141 'test requires %s bytes and a long time to run' % str(size))
Guido van Rossum47f40342001-09-10 13:34:12 +0000142 else:
Christian Heimes77c02eb2008-02-09 02:18:51 +0000143 # Only run if the current filesystem supports large files.
144 # (Skip this test on Windows, since we now always support
145 # large files.)
146 f = open(TESTFN, 'wb')
147 try:
148 # 2**31 == 2147483648
149 f.seek(2147483649)
150 # Seeking is not enough of a test: you must write and
151 # flush, too!
Alexandre Vassalottia351f772008-03-03 02:59:49 +0000152 f.write(b'x')
Christian Heimes77c02eb2008-02-09 02:18:51 +0000153 f.flush()
154 except (IOError, OverflowError):
155 f.close()
156 unlink(TESTFN)
157 raise TestSkipped("filesystem does not have largefile support")
158 else:
159 f.close()
160 suite = unittest.TestSuite()
161 suite.addTest(TestCase('test_seek'))
162 suite.addTest(TestCase('test_osstat'))
163 suite.addTest(TestCase('test_seek_read'))
164 suite.addTest(TestCase('test_lseek'))
Christian Heimes180510d2008-03-03 19:15:45 +0000165 with open(TESTFN, 'w') as f:
166 if hasattr(f, 'truncate'):
167 suite.addTest(TestCase('test_truncate'))
Brett Cannon7f757ed2008-03-03 02:31:43 +0000168 unlink(TESTFN)
Christian Heimes180510d2008-03-03 19:15:45 +0000169 try:
170 run_unittest(suite)
171 finally:
172 unlink(TESTFN)
Guido van Rossum47f40342001-09-10 13:34:12 +0000173
Christian Heimes77c02eb2008-02-09 02:18:51 +0000174if __name__ == '__main__':
Christian Heimes180510d2008-03-03 19:15:45 +0000175 test_main()