blob: 04c7b4559910f4f388f30d8b2d51cdc5e232190d [file] [log] [blame]
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +00001# Adapted from test_file.py by Daniel Stutzbach
2#from __future__ import unicode_literals
3
4import sys
5import os
6import unittest
7from array import array
8from weakref import proxy
9
Benjamin Peterson5539c782009-01-19 17:37:42 +000010from test.test_support import (TESTFN, findfile, check_warnings, run_unittest,
11 make_bad_fd)
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +000012from UserList import UserList
13
14import _fileio
15
16class AutoFileTests(unittest.TestCase):
17 # file tests for which a test file is automatically set up
18
19 def setUp(self):
20 self.f = _fileio._FileIO(TESTFN, 'w')
21
22 def tearDown(self):
23 if self.f:
24 self.f.close()
25 os.remove(TESTFN)
26
27 def testWeakRefs(self):
28 # verify weak references
29 p = proxy(self.f)
30 p.write(bytes(range(10)))
31 self.assertEquals(self.f.tell(), p.tell())
32 self.f.close()
33 self.f = None
34 self.assertRaises(ReferenceError, getattr, p, 'tell')
35
36 def testSeekTell(self):
37 self.f.write(bytes(bytearray(range(20))))
38 self.assertEquals(self.f.tell(), 20)
39 self.f.seek(0)
40 self.assertEquals(self.f.tell(), 0)
41 self.f.seek(10)
42 self.assertEquals(self.f.tell(), 10)
43 self.f.seek(5, 1)
44 self.assertEquals(self.f.tell(), 15)
45 self.f.seek(-5, 1)
46 self.assertEquals(self.f.tell(), 10)
47 self.f.seek(-5, 2)
48 self.assertEquals(self.f.tell(), 15)
49
50 def testAttributes(self):
51 # verify expected attributes exist
52 f = self.f
53
Benjamin Petersonbfc51562008-11-22 01:59:15 +000054 self.assertEquals(f.mode, "wb")
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +000055 self.assertEquals(f.closed, False)
56
57 # verify the attributes are readonly
58 for attr in 'mode', 'closed':
59 self.assertRaises((AttributeError, TypeError),
60 setattr, f, attr, 'oops')
61
62 def testReadinto(self):
63 # verify readinto
64 self.f.write(bytes(bytearray([1, 2])))
65 self.f.close()
66 a = array('b', b'x'*10)
67 self.f = _fileio._FileIO(TESTFN, 'r')
68 n = self.f.readinto(a)
69 self.assertEquals(array('b', [1, 2]), a[:n])
70
71 def testRepr(self):
72 self.assertEquals(repr(self.f),
73 "_fileio._FileIO(%d, %s)" % (self.f.fileno(),
74 repr(self.f.mode)))
75
76 def testErrors(self):
77 f = self.f
78 self.assert_(not f.isatty())
79 self.assert_(not f.closed)
80 #self.assertEquals(f.name, TESTFN)
81 self.assertRaises(ValueError, f.read, 10) # Open for reading
82 f.close()
83 self.assert_(f.closed)
84 f = _fileio._FileIO(TESTFN, 'r')
85 self.assertRaises(TypeError, f.readinto, "")
86 self.assert_(not f.closed)
87 f.close()
88 self.assert_(f.closed)
89
90 def testMethods(self):
91 methods = ['fileno', 'isatty', 'read', 'readinto',
92 'seek', 'tell', 'truncate', 'write', 'seekable',
93 'readable', 'writable']
94 if sys.platform.startswith('atheos'):
95 methods.remove('truncate')
96
97 self.f.close()
98 self.assert_(self.f.closed)
99
100 for methodname in methods:
101 method = getattr(self.f, methodname)
102 # should raise on closed file
103 self.assertRaises(ValueError, method)
104
Benjamin Petersonf22c26e2008-09-01 14:13:43 +0000105 def testOpendir(self):
106 # Issue 3703: opening a directory should fill the errno
107 # Windows always returns "[Errno 13]: Permission denied
108 # Unix calls dircheck() and returns "[Errno 21]: Is a directory"
109 try:
110 _fileio._FileIO('.', 'r')
111 except IOError as e:
112 self.assertNotEqual(e.errno, 0)
Benjamin Peterson7af65562008-12-29 17:56:58 +0000113 self.assertEqual(e.filename, ".")
Benjamin Petersonf22c26e2008-09-01 14:13:43 +0000114 else:
115 self.fail("Should have raised IOError")
116
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000117
118class OtherFileTests(unittest.TestCase):
119
120 def testAbles(self):
121 try:
122 f = _fileio._FileIO(TESTFN, "w")
123 self.assertEquals(f.readable(), False)
124 self.assertEquals(f.writable(), True)
125 self.assertEquals(f.seekable(), True)
126 f.close()
127
128 f = _fileio._FileIO(TESTFN, "r")
129 self.assertEquals(f.readable(), True)
130 self.assertEquals(f.writable(), False)
131 self.assertEquals(f.seekable(), True)
132 f.close()
133
134 f = _fileio._FileIO(TESTFN, "a+")
135 self.assertEquals(f.readable(), True)
136 self.assertEquals(f.writable(), True)
137 self.assertEquals(f.seekable(), True)
138 self.assertEquals(f.isatty(), False)
139 f.close()
140
141 if sys.platform != "win32":
142 try:
143 f = _fileio._FileIO("/dev/tty", "a")
144 except EnvironmentError:
145 # When run in a cron job there just aren't any
146 # ttys, so skip the test. This also handles other
147 # OS'es that don't support /dev/tty.
148 pass
149 else:
150 f = _fileio._FileIO("/dev/tty", "a")
151 self.assertEquals(f.readable(), False)
152 self.assertEquals(f.writable(), True)
153 if sys.platform != "darwin" and \
154 not sys.platform.startswith('freebsd') and \
155 not sys.platform.startswith('sunos'):
156 # Somehow /dev/tty appears seekable on some BSDs
157 self.assertEquals(f.seekable(), False)
158 self.assertEquals(f.isatty(), True)
159 f.close()
160 finally:
161 os.unlink(TESTFN)
162
163 def testModeStrings(self):
164 # check invalid mode strings
Benjamin Petersonbfc51562008-11-22 01:59:15 +0000165 for mode in ("", "aU", "wU+", "rw", "rt"):
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000166 try:
167 f = _fileio._FileIO(TESTFN, mode)
168 except ValueError:
169 pass
170 else:
171 f.close()
172 self.fail('%r is an invalid file mode' % mode)
173
174 def testUnicodeOpen(self):
175 # verify repr works for unicode too
176 f = _fileio._FileIO(str(TESTFN), "w")
177 f.close()
178 os.unlink(TESTFN)
179
Benjamin Peterson5848d1f2009-01-19 00:08:08 +0000180 def testInvalidFd(self):
181 self.assertRaises(ValueError, _fileio._FileIO, -10)
Benjamin Peterson5539c782009-01-19 17:37:42 +0000182 self.assertRaises(OSError, _fileio._FileIO, make_bad_fd())
Benjamin Peterson5848d1f2009-01-19 00:08:08 +0000183
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000184 def testBadModeArgument(self):
185 # verify that we get a sensible error message for bad mode argument
186 bad_mode = "qwerty"
187 try:
188 f = _fileio._FileIO(TESTFN, bad_mode)
189 except ValueError as msg:
190 if msg.args[0] != 0:
191 s = str(msg)
192 if s.find(TESTFN) != -1 or s.find(bad_mode) == -1:
193 self.fail("bad error message for invalid mode: %s" % s)
194 # if msg.args[0] == 0, we're probably on Windows where there may be
195 # no obvious way to discover why open() failed.
196 else:
197 f.close()
198 self.fail("no error for invalid mode: %s" % bad_mode)
199
200 def testTruncateOnWindows(self):
201 def bug801631():
202 # SF bug <http://www.python.org/sf/801631>
203 # "file.truncate fault on windows"
204 f = _fileio._FileIO(TESTFN, 'w')
205 f.write(bytes(bytearray(range(11))))
206 f.close()
207
208 f = _fileio._FileIO(TESTFN,'r+')
209 data = f.read(5)
210 if data != bytes(bytearray(range(5))):
211 self.fail("Read on file opened for update failed %r" % data)
212 if f.tell() != 5:
213 self.fail("File pos after read wrong %d" % f.tell())
214
215 f.truncate()
216 if f.tell() != 5:
217 self.fail("File pos after ftruncate wrong %d" % f.tell())
218
219 f.close()
220 size = os.path.getsize(TESTFN)
221 if size != 5:
222 self.fail("File size after ftruncate wrong %d" % size)
223
224 try:
225 bug801631()
226 finally:
227 os.unlink(TESTFN)
228
229 def testAppend(self):
230 try:
231 f = open(TESTFN, 'wb')
232 f.write(b'spam')
233 f.close()
234 f = open(TESTFN, 'ab')
235 f.write(b'eggs')
236 f.close()
237 f = open(TESTFN, 'rb')
238 d = f.read()
239 f.close()
240 self.assertEqual(d, b'spameggs')
241 finally:
242 try:
243 os.unlink(TESTFN)
244 except:
245 pass
246
Neal Norwitz901e4712008-08-24 22:03:05 +0000247 def testInvalidInit(self):
248 self.assertRaises(TypeError, _fileio._FileIO, "1", 0, 0)
249
Benjamin Peterson81e92e52008-11-03 22:34:57 +0000250 def testWarnings(self):
251 with check_warnings() as w:
252 self.assertEqual(w.warnings, [])
253 self.assertRaises(TypeError, _fileio._FileIO, [])
254 self.assertEqual(w.warnings, [])
255 self.assertRaises(ValueError, _fileio._FileIO, "/some/invalid/name", "rt")
256 self.assertEqual(w.warnings, [])
257
Neal Norwitz901e4712008-08-24 22:03:05 +0000258
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000259def test_main():
260 # Historically, these tests have been sloppy about removing TESTFN.
261 # So get rid of it no matter what.
262 try:
263 run_unittest(AutoFileTests, OtherFileTests)
264 finally:
265 if os.path.exists(TESTFN):
266 os.unlink(TESTFN)
267
268if __name__ == '__main__':
269 test_main()