blob: 5b276e76ff2ec76ec6ac4c4d52fb5266bfe45da1 [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
Serhiy Storchakac406a122013-07-17 13:42:24 +03008from test.support import TESTFN, requires, unlink
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00009import io # C implementation of io
10import _pyio as pyio # Python implementation of io
Trent Mickf29f47b2000-08-11 19:02:59 +000011
Serhiy Storchakac406a122013-07-17 13:42:24 +030012# size of file to create (>2GB; 2GB == 2147483648 bytes)
Guido van Rossume2a383d2007-01-15 16:59:06 +000013size = 2500000000
Guido van Rossuma31ddbb2001-09-10 15:03:18 +000014
Serhiy Storchakac406a122013-07-17 13:42:24 +030015class LargeFileTest:
16 """Test that each file function works as expected for large
17 (i.e. > 2GB) files.
Christian Heimes77c02eb2008-02-09 02:18:51 +000018 """
19
Serhiy Storchakac406a122013-07-17 13:42:24 +030020 def setUp(self):
21 if os.path.exists(TESTFN):
22 mode = 'r+b'
23 else:
24 mode = 'w+b'
25
26 with self.open(TESTFN, mode) as f:
27 current_size = os.fstat(f.fileno())[stat.ST_SIZE]
28 if current_size == size+1:
29 return
30
31 if current_size == 0:
32 f.write(b'z')
33
Christian Heimes77c02eb2008-02-09 02:18:51 +000034 f.seek(0)
35 f.seek(size)
Alexandre Vassalottia351f772008-03-03 02:59:49 +000036 f.write(b'a')
Christian Heimes77c02eb2008-02-09 02:18:51 +000037 f.flush()
Christian Heimes77c02eb2008-02-09 02:18:51 +000038 self.assertEqual(os.fstat(f.fileno())[stat.ST_SIZE], size+1)
Christian Heimes77c02eb2008-02-09 02:18:51 +000039
Serhiy Storchakac406a122013-07-17 13:42:24 +030040 @classmethod
41 def tearDownClass(cls):
42 with cls.open(TESTFN, 'wb'):
43 pass
44 if not os.stat(TESTFN)[stat.ST_SIZE] == 0:
45 raise cls.failureException('File was not truncated by opening '
46 'with mode "wb"')
47
Christian Heimes77c02eb2008-02-09 02:18:51 +000048 def test_osstat(self):
Christian Heimes77c02eb2008-02-09 02:18:51 +000049 self.assertEqual(os.stat(TESTFN)[stat.ST_SIZE], size+1)
50
51 def test_seek_read(self):
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000052 with self.open(TESTFN, 'rb') as f:
Christian Heimes77c02eb2008-02-09 02:18:51 +000053 self.assertEqual(f.tell(), 0)
Alexandre Vassalottia351f772008-03-03 02:59:49 +000054 self.assertEqual(f.read(1), b'z')
Christian Heimes77c02eb2008-02-09 02:18:51 +000055 self.assertEqual(f.tell(), 1)
56 f.seek(0)
57 self.assertEqual(f.tell(), 0)
58 f.seek(0, 0)
59 self.assertEqual(f.tell(), 0)
60 f.seek(42)
61 self.assertEqual(f.tell(), 42)
62 f.seek(42, 0)
63 self.assertEqual(f.tell(), 42)
64 f.seek(42, 1)
65 self.assertEqual(f.tell(), 84)
66 f.seek(0, 1)
67 self.assertEqual(f.tell(), 84)
68 f.seek(0, 2) # seek from the end
69 self.assertEqual(f.tell(), size + 1 + 0)
70 f.seek(-10, 2)
71 self.assertEqual(f.tell(), size + 1 - 10)
72 f.seek(-size-1, 2)
73 self.assertEqual(f.tell(), 0)
74 f.seek(size)
75 self.assertEqual(f.tell(), size)
76 # the 'a' that was written at the end of file above
Alexandre Vassalottia351f772008-03-03 02:59:49 +000077 self.assertEqual(f.read(1), b'a')
Christian Heimes77c02eb2008-02-09 02:18:51 +000078 f.seek(-size-1, 1)
Alexandre Vassalottia351f772008-03-03 02:59:49 +000079 self.assertEqual(f.read(1), b'z')
Christian Heimes77c02eb2008-02-09 02:18:51 +000080 self.assertEqual(f.tell(), 1)
Christian Heimes77c02eb2008-02-09 02:18:51 +000081
82 def test_lseek(self):
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000083 with self.open(TESTFN, 'rb') as f:
Christian Heimes77c02eb2008-02-09 02:18:51 +000084 self.assertEqual(os.lseek(f.fileno(), 0, 0), 0)
85 self.assertEqual(os.lseek(f.fileno(), 42, 0), 42)
86 self.assertEqual(os.lseek(f.fileno(), 42, 1), 84)
87 self.assertEqual(os.lseek(f.fileno(), 0, 1), 84)
88 self.assertEqual(os.lseek(f.fileno(), 0, 2), size+1+0)
89 self.assertEqual(os.lseek(f.fileno(), -10, 2), size+1-10)
90 self.assertEqual(os.lseek(f.fileno(), -size-1, 2), 0)
91 self.assertEqual(os.lseek(f.fileno(), size, 0), size)
92 # the 'a' that was written at the end of file above
Alexandre Vassalottia351f772008-03-03 02:59:49 +000093 self.assertEqual(f.read(1), b'a')
Christian Heimes77c02eb2008-02-09 02:18:51 +000094
95 def test_truncate(self):
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000096 with self.open(TESTFN, 'r+b') as f:
Christian Heimes180510d2008-03-03 19:15:45 +000097 if not hasattr(f, 'truncate'):
Serhiy Storchakac406a122013-07-17 13:42:24 +030098 raise unittest.SkipTest("open().truncate() not available "
99 "on this system")
Christian Heimes77c02eb2008-02-09 02:18:51 +0000100 f.seek(0, 2)
101 # else we've lost track of the true size
102 self.assertEqual(f.tell(), size+1)
103 # Cut it back via seek + truncate with no argument.
104 newsize = size - 10
105 f.seek(newsize)
106 f.truncate()
107 self.assertEqual(f.tell(), newsize) # else pointer moved
108 f.seek(0, 2)
109 self.assertEqual(f.tell(), newsize) # else wasn't truncated
110 # Ensure that truncate(smaller than true size) shrinks
111 # the file.
112 newsize -= 1
113 f.seek(42)
114 f.truncate(newsize)
Antoine Pitrou905a2ff2010-01-31 22:47:27 +0000115 self.assertEqual(f.tell(), 42)
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000116 f.seek(0, 2)
117 self.assertEqual(f.tell(), newsize)
Christian Heimes77c02eb2008-02-09 02:18:51 +0000118 # XXX truncate(larger than true size) is ill-defined
119 # across platform; cut it waaaaay back
120 f.seek(0)
121 f.truncate(1)
Antoine Pitrou905a2ff2010-01-31 22:47:27 +0000122 self.assertEqual(f.tell(), 0) # else pointer moved
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000123 f.seek(0)
Christian Heimes77c02eb2008-02-09 02:18:51 +0000124 self.assertEqual(len(f.read()), 1) # else wasn't truncated
Christian Heimes77c02eb2008-02-09 02:18:51 +0000125
Antoine Pitroua28fcfd2009-03-13 23:42:55 +0000126 def test_seekable(self):
127 # Issue #5016; seekable() can return False when the current position
128 # is negative when truncated to an int.
129 for pos in (2**31-1, 2**31, 2**31+1):
130 with self.open(TESTFN, 'rb') as f:
131 f.seek(pos)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000132 self.assertTrue(f.seekable())
Antoine Pitroua28fcfd2009-03-13 23:42:55 +0000133
Serhiy Storchakac406a122013-07-17 13:42:24 +0300134def setUpModule():
135 try:
136 import signal
137 # The default handler for SIGXFSZ is to abort the process.
138 # By ignoring it, system calls exceeding the file size resource
139 # limit will raise OSError instead of crashing the interpreter.
140 signal.signal(signal.SIGXFSZ, signal.SIG_IGN)
141 except (ImportError, AttributeError):
142 pass
Antoine Pitroua28fcfd2009-03-13 23:42:55 +0000143
Christian Heimes77c02eb2008-02-09 02:18:51 +0000144 # On Windows and Mac OSX this test comsumes large resources; It
145 # takes a long time to build the >2GB file and takes >2GB of disk
146 # space therefore the resource must be enabled to run this test.
147 # If not, nothing after this line stanza will be executed.
148 if sys.platform[:3] == 'win' or sys.platform == 'darwin':
149 requires('largefile',
150 'test requires %s bytes and a long time to run' % str(size))
Guido van Rossum47f40342001-09-10 13:34:12 +0000151 else:
Christian Heimes77c02eb2008-02-09 02:18:51 +0000152 # Only run if the current filesystem supports large files.
153 # (Skip this test on Windows, since we now always support
154 # large files.)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000155 f = open(TESTFN, 'wb', buffering=0)
Christian Heimes77c02eb2008-02-09 02:18:51 +0000156 try:
157 # 2**31 == 2147483648
158 f.seek(2147483649)
Serhiy Storchakac406a122013-07-17 13:42:24 +0300159 # Seeking is not enough of a test: you must write and flush, too!
Alexandre Vassalottia351f772008-03-03 02:59:49 +0000160 f.write(b'x')
Christian Heimes77c02eb2008-02-09 02:18:51 +0000161 f.flush()
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200162 except (OSError, OverflowError):
Serhiy Storchakac406a122013-07-17 13:42:24 +0300163 raise unittest.SkipTest("filesystem does not have "
164 "largefile support")
165 finally:
Christian Heimes77c02eb2008-02-09 02:18:51 +0000166 f.close()
167 unlink(TESTFN)
Serhiy Storchakac406a122013-07-17 13:42:24 +0300168
169
170class CLargeFileTest(LargeFileTest, unittest.TestCase):
171 open = staticmethod(io.open)
172
173class PyLargeFileTest(LargeFileTest, unittest.TestCase):
174 open = staticmethod(pyio.open)
175
176def tearDownModule():
177 unlink(TESTFN)
Guido van Rossum47f40342001-09-10 13:34:12 +0000178
Christian Heimes77c02eb2008-02-09 02:18:51 +0000179if __name__ == '__main__':
Serhiy Storchakac406a122013-07-17 13:42:24 +0300180 unittest.main()