blob: 5335e2c043d5200aeea311d427fa9dad71983a9e [file] [log] [blame]
Facundo Batista9521f082008-02-07 16:16:29 +00001"""Test largefile support on system where this makes sense.
2"""
Trent Mickf29f47b2000-08-11 19:02:59 +00003
Antoine Pitrou19690592009-06-12 20:14:08 +00004from __future__ import print_function
5
Facundo Batista9521f082008-02-07 16:16:29 +00006import os
7import stat
8import sys
9import unittest
10from test.test_support import run_unittest, TESTFN, verbose, requires, \
Benjamin Petersonbec087f2009-03-26 21:10:30 +000011 unlink
Antoine Pitrou19690592009-06-12 20:14:08 +000012import io # C implementation of io
13import _pyio as pyio # Python implementation of io
Trent Mickf29f47b2000-08-11 19:02:59 +000014
Martin v. Löwisdf8adcd2001-12-11 17:57:26 +000015try:
16 import signal
17 # The default handler for SIGXFSZ is to abort the process.
18 # By ignoring it, system calls exceeding the file size resource
19 # limit will raise IOError instead of crashing the interpreter.
20 oldhandler = signal.signal(signal.SIGXFSZ, signal.SIG_IGN)
21except (ImportError, AttributeError):
22 pass
23
Guido van Rossuma31ddbb2001-09-10 15:03:18 +000024# create >2GB file (2GB = 2147483648 bytes)
Antoine Pitrou19690592009-06-12 20:14:08 +000025size = 2500000000
Guido van Rossuma31ddbb2001-09-10 15:03:18 +000026
27
Antoine Pitrou19690592009-06-12 20:14:08 +000028class LargeFileTest(unittest.TestCase):
Facundo Batista9521f082008-02-07 16:16:29 +000029 """Test that each file function works as expected for a large
30 (i.e. > 2GB, do we have to check > 4GB) files.
Brett Cannon6382ffc2008-03-03 02:41:40 +000031
Brett Cannonbfbf5b32008-03-03 03:24:48 +000032 NOTE: the order of execution of the test methods is important! test_seek
33 must run first to create the test file. File cleanup must also be handled
34 outside the test instances because of this.
35
Facundo Batista9521f082008-02-07 16:16:29 +000036 """
37
38 def test_seek(self):
39 if verbose:
Antoine Pitrou19690592009-06-12 20:14:08 +000040 print('create large file via seek (may be sparse file) ...')
41 with self.open(TESTFN, 'wb') as f:
42 f.write(b'z')
Facundo Batista9521f082008-02-07 16:16:29 +000043 f.seek(0)
44 f.seek(size)
Antoine Pitrou19690592009-06-12 20:14:08 +000045 f.write(b'a')
Facundo Batista9521f082008-02-07 16:16:29 +000046 f.flush()
47 if verbose:
Antoine Pitrou19690592009-06-12 20:14:08 +000048 print('check file size with os.fstat')
Facundo Batista9521f082008-02-07 16:16:29 +000049 self.assertEqual(os.fstat(f.fileno())[stat.ST_SIZE], size+1)
Facundo Batista9521f082008-02-07 16:16:29 +000050
51 def test_osstat(self):
52 if verbose:
Antoine Pitrou19690592009-06-12 20:14:08 +000053 print('check file size with os.stat')
Facundo Batista9521f082008-02-07 16:16:29 +000054 self.assertEqual(os.stat(TESTFN)[stat.ST_SIZE], size+1)
55
56 def test_seek_read(self):
57 if verbose:
Antoine Pitrou19690592009-06-12 20:14:08 +000058 print('play around with seek() and read() with the built largefile')
59 with self.open(TESTFN, 'rb') as f:
Facundo Batista9521f082008-02-07 16:16:29 +000060 self.assertEqual(f.tell(), 0)
Antoine Pitrou19690592009-06-12 20:14:08 +000061 self.assertEqual(f.read(1), b'z')
Facundo Batista9521f082008-02-07 16:16:29 +000062 self.assertEqual(f.tell(), 1)
63 f.seek(0)
64 self.assertEqual(f.tell(), 0)
65 f.seek(0, 0)
66 self.assertEqual(f.tell(), 0)
67 f.seek(42)
68 self.assertEqual(f.tell(), 42)
69 f.seek(42, 0)
70 self.assertEqual(f.tell(), 42)
71 f.seek(42, 1)
72 self.assertEqual(f.tell(), 84)
73 f.seek(0, 1)
74 self.assertEqual(f.tell(), 84)
75 f.seek(0, 2) # seek from the end
76 self.assertEqual(f.tell(), size + 1 + 0)
77 f.seek(-10, 2)
78 self.assertEqual(f.tell(), size + 1 - 10)
79 f.seek(-size-1, 2)
80 self.assertEqual(f.tell(), 0)
81 f.seek(size)
82 self.assertEqual(f.tell(), size)
83 # the 'a' that was written at the end of file above
Antoine Pitrou19690592009-06-12 20:14:08 +000084 self.assertEqual(f.read(1), b'a')
Facundo Batista9521f082008-02-07 16:16:29 +000085 f.seek(-size-1, 1)
Antoine Pitrou19690592009-06-12 20:14:08 +000086 self.assertEqual(f.read(1), b'z')
Facundo Batista9521f082008-02-07 16:16:29 +000087 self.assertEqual(f.tell(), 1)
Facundo Batista9521f082008-02-07 16:16:29 +000088
89 def test_lseek(self):
90 if verbose:
Antoine Pitrou19690592009-06-12 20:14:08 +000091 print('play around with os.lseek() with the built largefile')
92 with self.open(TESTFN, 'rb') as f:
Facundo Batista9521f082008-02-07 16:16:29 +000093 self.assertEqual(os.lseek(f.fileno(), 0, 0), 0)
94 self.assertEqual(os.lseek(f.fileno(), 42, 0), 42)
95 self.assertEqual(os.lseek(f.fileno(), 42, 1), 84)
96 self.assertEqual(os.lseek(f.fileno(), 0, 1), 84)
97 self.assertEqual(os.lseek(f.fileno(), 0, 2), size+1+0)
98 self.assertEqual(os.lseek(f.fileno(), -10, 2), size+1-10)
99 self.assertEqual(os.lseek(f.fileno(), -size-1, 2), 0)
100 self.assertEqual(os.lseek(f.fileno(), size, 0), size)
101 # the 'a' that was written at the end of file above
Antoine Pitrou19690592009-06-12 20:14:08 +0000102 self.assertEqual(f.read(1), b'a')
Facundo Batista9521f082008-02-07 16:16:29 +0000103
104 def test_truncate(self):
105 if verbose:
Antoine Pitrou19690592009-06-12 20:14:08 +0000106 print('try truncate')
107 with self.open(TESTFN, 'r+b') as f:
Brett Cannon6382ffc2008-03-03 02:41:40 +0000108 # 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'):
Antoine Pitrou19690592009-06-12 20:14:08 +0000111 raise unittest.SkipTest("open().truncate() not available on this system")
Facundo Batista9521f082008-02-07 16:16:29 +0000112 f.seek(0, 2)
113 # else we've lost track of the true size
114 self.assertEqual(f.tell(), size+1)
115 # Cut it back via seek + truncate with no argument.
116 newsize = size - 10
117 f.seek(newsize)
118 f.truncate()
119 self.assertEqual(f.tell(), newsize) # else pointer moved
120 f.seek(0, 2)
121 self.assertEqual(f.tell(), newsize) # else wasn't truncated
122 # Ensure that truncate(smaller than true size) shrinks
123 # the file.
124 newsize -= 1
125 f.seek(42)
126 f.truncate(newsize)
Facundo Batista9521f082008-02-07 16:16:29 +0000127 self.assertEqual(f.tell(), newsize) # else wasn't truncated
Antoine Pitrou19690592009-06-12 20:14:08 +0000128 f.seek(0, 2)
129 self.assertEqual(f.tell(), newsize)
Facundo Batista9521f082008-02-07 16:16:29 +0000130 # XXX truncate(larger than true size) is ill-defined
131 # across platform; cut it waaaaay back
132 f.seek(0)
133 f.truncate(1)
Antoine Pitrou19690592009-06-12 20:14:08 +0000134 self.assertEqual(f.tell(), 1) # else pointer moved
135 f.seek(0)
Facundo Batista9521f082008-02-07 16:16:29 +0000136 self.assertEqual(len(f.read()), 1) # else wasn't truncated
Facundo Batista9521f082008-02-07 16:16:29 +0000137
Antoine Pitrou19690592009-06-12 20:14:08 +0000138 def test_seekable(self):
139 # Issue #5016; seekable() can return False when the current position
140 # is negative when truncated to an int.
141 for pos in (2**31-1, 2**31, 2**31+1):
142 with self.open(TESTFN, 'rb') as f:
143 f.seek(pos)
144 self.assert_(f.seekable())
145
Facundo Batista9521f082008-02-07 16:16:29 +0000146
Brett Cannon6382ffc2008-03-03 02:41:40 +0000147def test_main():
Facundo Batista9521f082008-02-07 16:16:29 +0000148 # On Windows and Mac OSX this test comsumes large resources; It
149 # takes a long time to build the >2GB file and takes >2GB of disk
150 # space therefore the resource must be enabled to run this test.
151 # If not, nothing after this line stanza will be executed.
152 if sys.platform[:3] == 'win' or sys.platform == 'darwin':
153 requires('largefile',
154 'test requires %s bytes and a long time to run' % str(size))
Guido van Rossum47f40342001-09-10 13:34:12 +0000155 else:
Facundo Batista9521f082008-02-07 16:16:29 +0000156 # Only run if the current filesystem supports large files.
157 # (Skip this test on Windows, since we now always support
158 # large files.)
Antoine Pitrou19690592009-06-12 20:14:08 +0000159 f = open(TESTFN, 'wb', buffering=0)
Facundo Batista9521f082008-02-07 16:16:29 +0000160 try:
161 # 2**31 == 2147483648
Antoine Pitrou19690592009-06-12 20:14:08 +0000162 f.seek(2147483649)
Facundo Batista9521f082008-02-07 16:16:29 +0000163 # Seeking is not enough of a test: you must write and
164 # flush, too!
Antoine Pitrou19690592009-06-12 20:14:08 +0000165 f.write(b'x')
Facundo Batista9521f082008-02-07 16:16:29 +0000166 f.flush()
167 except (IOError, OverflowError):
168 f.close()
169 unlink(TESTFN)
Antoine Pitrou19690592009-06-12 20:14:08 +0000170 raise unittest.SkipTest("filesystem does not have largefile support")
Facundo Batista9521f082008-02-07 16:16:29 +0000171 else:
172 f.close()
173 suite = unittest.TestSuite()
Antoine Pitrou19690592009-06-12 20:14:08 +0000174 for _open, prefix in [(io.open, 'C'), (pyio.open, 'Py')]:
175 class TestCase(LargeFileTest):
176 pass
177 TestCase.open = staticmethod(_open)
178 TestCase.__name__ = prefix + LargeFileTest.__name__
179 suite.addTest(TestCase('test_seek'))
180 suite.addTest(TestCase('test_osstat'))
181 suite.addTest(TestCase('test_seek_read'))
182 suite.addTest(TestCase('test_lseek'))
183 with _open(TESTFN, 'wb') as f:
184 if hasattr(f, 'truncate'):
185 suite.addTest(TestCase('test_truncate'))
186 suite.addTest(TestCase('test_seekable'))
187 unlink(TESTFN)
Brett Cannon6382ffc2008-03-03 02:41:40 +0000188 try:
189 run_unittest(suite)
190 finally:
191 unlink(TESTFN)
Trent Mickf29f47b2000-08-11 19:02:59 +0000192
Facundo Batista9521f082008-02-07 16:16:29 +0000193if __name__ == '__main__':
Brett Cannon6382ffc2008-03-03 02:41:40 +0000194 test_main()