blob: a7681a9a848bfa3e28a20194014b58285ebe7f01 [file] [log] [blame]
Antoine Pitrouc5d2b412009-06-12 20:36:25 +00001import sys
2import os
3import unittest
Antoine Pitrou47a5f482009-06-12 20:41:52 +00004import itertools
5import time
6import threading
Antoine Pitrouc5d2b412009-06-12 20:36:25 +00007from array import array
8from weakref import proxy
9
Antoine Pitrou47a5f482009-06-12 20:41:52 +000010from test import test_support
Georg Brandla4f46e12010-02-07 17:03:15 +000011from test.test_support import TESTFN, run_unittest
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000012from UserList import UserList
13
14class AutoFileTests(unittest.TestCase):
15 # file tests for which a test file is automatically set up
16
17 def setUp(self):
Antoine Pitrou47a5f482009-06-12 20:41:52 +000018 self.f = open(TESTFN, 'wb')
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000019
20 def tearDown(self):
21 if self.f:
22 self.f.close()
23 os.remove(TESTFN)
24
25 def testWeakRefs(self):
26 # verify weak references
27 p = proxy(self.f)
Antoine Pitrou47a5f482009-06-12 20:41:52 +000028 p.write('teststring')
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000029 self.assertEquals(self.f.tell(), p.tell())
30 self.f.close()
31 self.f = None
32 self.assertRaises(ReferenceError, getattr, p, 'tell')
33
34 def testAttributes(self):
35 # verify expected attributes exist
36 f = self.f
Ezio Melottid80b4bf2010-03-17 13:52:48 +000037 with test_support.check_py3k_warnings():
38 softspace = f.softspace
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000039 f.name # merely shouldn't blow up
40 f.mode # ditto
41 f.closed # ditto
42
Ezio Melottid80b4bf2010-03-17 13:52:48 +000043 with test_support.check_py3k_warnings():
44 # verify softspace is writable
45 f.softspace = softspace # merely shouldn't blow up
Antoine Pitrou47a5f482009-06-12 20:41:52 +000046
47 # verify the others aren't
48 for attr in 'name', 'mode', 'closed':
49 self.assertRaises((AttributeError, TypeError), setattr, f, attr, 'oops')
50
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000051 def testReadinto(self):
52 # verify readinto
Antoine Pitrou47a5f482009-06-12 20:41:52 +000053 self.f.write('12')
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000054 self.f.close()
Antoine Pitrou47a5f482009-06-12 20:41:52 +000055 a = array('c', 'x'*10)
56 self.f = open(TESTFN, 'rb')
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000057 n = self.f.readinto(a)
Antoine Pitrou47a5f482009-06-12 20:41:52 +000058 self.assertEquals('12', a.tostring()[:n])
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000059
60 def testWritelinesUserList(self):
61 # verify writelines with instance sequence
Antoine Pitrou47a5f482009-06-12 20:41:52 +000062 l = UserList(['1', '2'])
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000063 self.f.writelines(l)
64 self.f.close()
Antoine Pitrou47a5f482009-06-12 20:41:52 +000065 self.f = open(TESTFN, 'rb')
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000066 buf = self.f.read()
Antoine Pitrou47a5f482009-06-12 20:41:52 +000067 self.assertEquals(buf, '12')
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000068
69 def testWritelinesIntegers(self):
70 # verify writelines with integers
71 self.assertRaises(TypeError, self.f.writelines, [1, 2, 3])
72
73 def testWritelinesIntegersUserList(self):
74 # verify writelines with integers in UserList
75 l = UserList([1,2,3])
76 self.assertRaises(TypeError, self.f.writelines, l)
77
78 def testWritelinesNonString(self):
79 # verify writelines with non-string object
80 class NonString:
81 pass
82
83 self.assertRaises(TypeError, self.f.writelines,
84 [NonString(), NonString()])
85
Antoine Pitrou47a5f482009-06-12 20:41:52 +000086 def testRepr(self):
87 # verify repr works
Benjamin Peterson5c8da862009-06-30 22:57:08 +000088 self.assertTrue(repr(self.f).startswith("<open file '" + TESTFN))
Antoine Pitrou47a5f482009-06-12 20:41:52 +000089
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000090 def testErrors(self):
Antoine Pitroubb445a12010-02-05 17:05:54 +000091 self.f.close()
92 self.f = open(TESTFN, 'rb')
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000093 f = self.f
94 self.assertEquals(f.name, TESTFN)
Benjamin Peterson5c8da862009-06-30 22:57:08 +000095 self.assertTrue(not f.isatty())
96 self.assertTrue(not f.closed)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000097
Antoine Pitrou47a5f482009-06-12 20:41:52 +000098 self.assertRaises(TypeError, f.readinto, "")
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000099 f.close()
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000100 self.assertTrue(f.closed)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000101
102 def testMethods(self):
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000103 methods = ['fileno', 'flush', 'isatty', 'next', 'read', 'readinto',
104 'readline', 'readlines', 'seek', 'tell', 'truncate',
Ezio Melottid80b4bf2010-03-17 13:52:48 +0000105 'write', '__iter__']
106 deprecated_methods = ['xreadlines']
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000107 if sys.platform.startswith('atheos'):
108 methods.remove('truncate')
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000109
110 # __exit__ should close the file
111 self.f.__exit__(None, None, None)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000112 self.assertTrue(self.f.closed)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000113
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000114 for methodname in methods:
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000115 method = getattr(self.f, methodname)
116 # should raise on closed file
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000117 self.assertRaises(ValueError, method)
Ezio Melottid80b4bf2010-03-17 13:52:48 +0000118 with test_support.check_py3k_warnings():
119 for methodname in deprecated_methods:
120 method = getattr(self.f, methodname)
121 self.assertRaises(ValueError, method)
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000122 self.assertRaises(ValueError, self.f.writelines, [])
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000123
124 # file is closed, __exit__ shouldn't do anything
125 self.assertEquals(self.f.__exit__(None, None, None), None)
126 # it must also return None if an exception was given
127 try:
Ezio Melottid80b4bf2010-03-17 13:52:48 +0000128 1 // 0
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000129 except:
130 self.assertEquals(self.f.__exit__(*sys.exc_info()), None)
131
132 def testReadWhenWriting(self):
133 self.assertRaises(IOError, self.f.read)
134
Antoine Pitroubb445a12010-02-05 17:05:54 +0000135 def testIssue5677(self):
136 # Remark: Do not perform more than one test per open file,
137 # since that does NOT catch the readline error on Windows.
138 data = 'xxx'
139 for mode in ['w', 'wb', 'a', 'ab']:
140 for attr in ['read', 'readline', 'readlines']:
141 self.f = open(TESTFN, mode)
142 self.f.write(data)
143 self.assertRaises(IOError, getattr(self.f, attr))
144 self.f.close()
145
146 self.f = open(TESTFN, mode)
147 self.f.write(data)
148 self.assertRaises(IOError, lambda: [line for line in self.f])
149 self.f.close()
150
151 self.f = open(TESTFN, mode)
152 self.f.write(data)
153 self.assertRaises(IOError, self.f.readinto, bytearray(len(data)))
154 self.f.close()
155
156 for mode in ['r', 'rb', 'U', 'Ub', 'Ur', 'rU', 'rbU', 'rUb']:
157 self.f = open(TESTFN, mode)
158 self.assertRaises(IOError, self.f.write, data)
159 self.f.close()
160
161 self.f = open(TESTFN, mode)
162 self.assertRaises(IOError, self.f.writelines, [data, data])
163 self.f.close()
164
165 self.f = open(TESTFN, mode)
166 self.assertRaises(IOError, self.f.truncate)
167 self.f.close()
168
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000169class OtherFileTests(unittest.TestCase):
170
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000171 def testOpenDir(self):
172 this_dir = os.path.dirname(__file__)
173 for mode in (None, "w"):
174 try:
175 if mode:
176 f = open(this_dir, mode)
177 else:
178 f = open(this_dir)
179 except IOError as e:
180 self.assertEqual(e.filename, this_dir)
181 else:
182 self.fail("opening a directory didn't raise an IOError")
183
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000184 def testModeStrings(self):
185 # check invalid mode strings
186 for mode in ("", "aU", "wU+"):
187 try:
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000188 f = open(TESTFN, mode)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000189 except ValueError:
190 pass
191 else:
192 f.close()
193 self.fail('%r is an invalid file mode' % mode)
194
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000195 # Some invalid modes fail on Windows, but pass on Unix
196 # Issue3965: avoid a crash on Windows when filename is unicode
197 for name in (TESTFN, unicode(TESTFN), unicode(TESTFN + '\t')):
198 try:
199 f = open(name, "rr")
200 except (IOError, ValueError):
201 pass
202 else:
203 f.close()
204
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000205 def testStdin(self):
206 # This causes the interpreter to exit on OSF1 v5.1.
207 if sys.platform != 'osf1V5':
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000208 self.assertRaises(IOError, sys.stdin.seek, -1)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000209 else:
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000210 print >>sys.__stdout__, (
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000211 ' Skipping sys.stdin.seek(-1), it may crash the interpreter.'
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000212 ' Test manually.')
213 self.assertRaises(IOError, sys.stdin.truncate)
214
215 def testUnicodeOpen(self):
216 # verify repr works for unicode too
217 f = open(unicode(TESTFN), "w")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000218 self.assertTrue(repr(f).startswith("<open file u'" + TESTFN))
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000219 f.close()
220 os.unlink(TESTFN)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000221
222 def testBadModeArgument(self):
223 # verify that we get a sensible error message for bad mode argument
224 bad_mode = "qwerty"
225 try:
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000226 f = open(TESTFN, bad_mode)
227 except ValueError, msg:
Ezio Melottid80b4bf2010-03-17 13:52:48 +0000228 if msg.args[0] != 0:
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000229 s = str(msg)
Ezio Melotti187f93d2010-03-17 14:22:34 +0000230 if TESTFN in s or bad_mode not in s:
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000231 self.fail("bad error message for invalid mode: %s" % s)
Ezio Melottid80b4bf2010-03-17 13:52:48 +0000232 # if msg.args[0] == 0, we're probably on Windows where there may
233 # be no obvious way to discover why open() failed.
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000234 else:
235 f.close()
236 self.fail("no error for invalid mode: %s" % bad_mode)
237
238 def testSetBufferSize(self):
239 # make sure that explicitly setting the buffer size doesn't cause
240 # misbehaviour especially with repeated close() calls
241 for s in (-1, 0, 1, 512):
242 try:
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000243 f = open(TESTFN, 'w', s)
244 f.write(str(s))
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000245 f.close()
246 f.close()
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000247 f = open(TESTFN, 'r', s)
248 d = int(f.read())
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000249 f.close()
250 f.close()
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000251 except IOError, msg:
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000252 self.fail('error setting buffer size %d: %s' % (s, str(msg)))
253 self.assertEquals(d, s)
254
255 def testTruncateOnWindows(self):
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000256 os.unlink(TESTFN)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000257
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000258 def bug801631():
259 # SF bug <http://www.python.org/sf/801631>
260 # "file.truncate fault on windows"
261 f = open(TESTFN, 'wb')
262 f.write('12345678901') # 11 bytes
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000263 f.close()
264
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000265 f = open(TESTFN,'rb+')
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000266 data = f.read(5)
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000267 if data != '12345':
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000268 self.fail("Read on file opened for update failed %r" % data)
269 if f.tell() != 5:
270 self.fail("File pos after read wrong %d" % f.tell())
271
272 f.truncate()
273 if f.tell() != 5:
274 self.fail("File pos after ftruncate wrong %d" % f.tell())
275
276 f.close()
277 size = os.path.getsize(TESTFN)
278 if size != 5:
279 self.fail("File size after ftruncate wrong %d" % size)
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000280
281 try:
282 bug801631()
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000283 finally:
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000284 os.unlink(TESTFN)
285
286 def testIteration(self):
287 # Test the complex interaction when mixing file-iteration and the
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000288 # various read* methods. Ostensibly, the mixture could just be tested
289 # to work when it should work according to the Python language,
290 # instead of fail when it should fail according to the current CPython
291 # implementation. People don't always program Python the way they
292 # should, though, and the implemenation might change in subtle ways,
293 # so we explicitly test for errors, too; the test will just have to
294 # be updated when the implementation changes.
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000295 dataoffset = 16384
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000296 filler = "ham\n"
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000297 assert not dataoffset % len(filler), \
298 "dataoffset must be multiple of len(filler)"
299 nchunks = dataoffset // len(filler)
300 testlines = [
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000301 "spam, spam and eggs\n",
302 "eggs, spam, ham and spam\n",
303 "saussages, spam, spam and eggs\n",
304 "spam, ham, spam and eggs\n",
305 "spam, spam, spam, spam, spam, ham, spam\n",
306 "wonderful spaaaaaam.\n"
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000307 ]
308 methods = [("readline", ()), ("read", ()), ("readlines", ()),
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000309 ("readinto", (array("c", " "*100),))]
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000310
311 try:
312 # Prepare the testfile
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000313 bag = open(TESTFN, "w")
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000314 bag.write(filler * nchunks)
315 bag.writelines(testlines)
316 bag.close()
317 # Test for appropriate errors mixing read* and iteration
318 for methodname, args in methods:
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000319 f = open(TESTFN)
320 if f.next() != filler:
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000321 self.fail, "Broken testfile"
322 meth = getattr(f, methodname)
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000323 try:
324 meth(*args)
325 except ValueError:
326 pass
327 else:
328 self.fail("%s%r after next() didn't raise ValueError" %
329 (methodname, args))
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000330 f.close()
331
332 # Test to see if harmless (by accident) mixing of read* and
333 # iteration still works. This depends on the size of the internal
334 # iteration buffer (currently 8192,) but we can test it in a
335 # flexible manner. Each line in the bag o' ham is 4 bytes
336 # ("h", "a", "m", "\n"), so 4096 lines of that should get us
337 # exactly on the buffer boundary for any power-of-2 buffersize
338 # between 4 and 16384 (inclusive).
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000339 f = open(TESTFN)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000340 for i in range(nchunks):
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000341 f.next()
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000342 testline = testlines.pop(0)
343 try:
344 line = f.readline()
345 except ValueError:
346 self.fail("readline() after next() with supposedly empty "
347 "iteration-buffer failed anyway")
348 if line != testline:
349 self.fail("readline() after next() with empty buffer "
350 "failed. Got %r, expected %r" % (line, testline))
351 testline = testlines.pop(0)
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000352 buf = array("c", "\x00" * len(testline))
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000353 try:
354 f.readinto(buf)
355 except ValueError:
356 self.fail("readinto() after next() with supposedly empty "
357 "iteration-buffer failed anyway")
358 line = buf.tostring()
359 if line != testline:
360 self.fail("readinto() after next() with empty buffer "
361 "failed. Got %r, expected %r" % (line, testline))
362
363 testline = testlines.pop(0)
364 try:
365 line = f.read(len(testline))
366 except ValueError:
367 self.fail("read() after next() with supposedly empty "
368 "iteration-buffer failed anyway")
369 if line != testline:
370 self.fail("read() after next() with empty buffer "
371 "failed. Got %r, expected %r" % (line, testline))
372 try:
373 lines = f.readlines()
374 except ValueError:
375 self.fail("readlines() after next() with supposedly empty "
376 "iteration-buffer failed anyway")
377 if lines != testlines:
378 self.fail("readlines() after next() with empty buffer "
379 "failed. Got %r, expected %r" % (line, testline))
380 # Reading after iteration hit EOF shouldn't hurt either
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000381 f = open(TESTFN)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000382 try:
383 for line in f:
384 pass
385 try:
386 f.readline()
387 f.readinto(buf)
388 f.read()
389 f.readlines()
390 except ValueError:
391 self.fail("read* failed after next() consumed file")
392 finally:
393 f.close()
394 finally:
395 os.unlink(TESTFN)
396
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000397class FileSubclassTests(unittest.TestCase):
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000398
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000399 def testExit(self):
400 # test that exiting with context calls subclass' close
401 class C(file):
402 def __init__(self, *args):
403 self.subclass_closed = False
404 file.__init__(self, *args)
405 def close(self):
406 self.subclass_closed = True
407 file.close(self)
408
409 with C(TESTFN, 'w') as f:
410 pass
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000411 self.assertTrue(f.subclass_closed)
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000412
413
414class FileThreadingTests(unittest.TestCase):
415 # These tests check the ability to call various methods of file objects
416 # (including close()) concurrently without crashing the Python interpreter.
417 # See #815646, #595601
418
419 def setUp(self):
Antoine Pitrou0df2c732009-10-27 19:36:44 +0000420 self._threads = test_support.threading_setup()
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000421 self.f = None
422 self.filename = TESTFN
423 with open(self.filename, "w") as f:
424 f.write("\n".join("0123456789"))
425 self._count_lock = threading.Lock()
426 self.close_count = 0
427 self.close_success_count = 0
428
429 def tearDown(self):
430 if self.f:
431 try:
432 self.f.close()
433 except (EnvironmentError, ValueError):
434 pass
435 try:
436 os.remove(self.filename)
437 except EnvironmentError:
438 pass
Antoine Pitrou0df2c732009-10-27 19:36:44 +0000439 test_support.threading_cleanup(*self._threads)
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000440
441 def _create_file(self):
442 self.f = open(self.filename, "w+")
443
444 def _close_file(self):
445 with self._count_lock:
446 self.close_count += 1
447 self.f.close()
448 with self._count_lock:
449 self.close_success_count += 1
450
451 def _close_and_reopen_file(self):
452 self._close_file()
453 # if close raises an exception thats fine, self.f remains valid so
454 # we don't need to reopen.
455 self._create_file()
456
457 def _run_workers(self, func, nb_workers, duration=0.2):
458 with self._count_lock:
459 self.close_count = 0
460 self.close_success_count = 0
461 self.do_continue = True
462 threads = []
463 try:
464 for i in range(nb_workers):
465 t = threading.Thread(target=func)
466 t.start()
467 threads.append(t)
468 for _ in xrange(100):
469 time.sleep(duration/100)
470 with self._count_lock:
471 if self.close_count-self.close_success_count > nb_workers+1:
472 if test_support.verbose:
473 print 'Q',
474 break
475 time.sleep(duration)
476 finally:
477 self.do_continue = False
478 for t in threads:
479 t.join()
480
481 def _test_close_open_io(self, io_func, nb_workers=5):
482 def worker():
483 self._create_file()
484 funcs = itertools.cycle((
485 lambda: io_func(),
486 lambda: self._close_and_reopen_file(),
487 ))
488 for f in funcs:
489 if not self.do_continue:
490 break
491 try:
492 f()
493 except (IOError, ValueError):
494 pass
495 self._run_workers(worker, nb_workers)
496 if test_support.verbose:
497 # Useful verbose statistics when tuning this test to take
498 # less time to run but still ensuring that its still useful.
499 #
500 # the percent of close calls that raised an error
501 percent = 100. - 100.*self.close_success_count/self.close_count
502 print self.close_count, ('%.4f ' % percent),
503
504 def test_close_open(self):
505 def io_func():
506 pass
507 self._test_close_open_io(io_func)
508
509 def test_close_open_flush(self):
510 def io_func():
511 self.f.flush()
512 self._test_close_open_io(io_func)
513
514 def test_close_open_iter(self):
515 def io_func():
516 list(iter(self.f))
517 self._test_close_open_io(io_func)
518
519 def test_close_open_isatty(self):
520 def io_func():
521 self.f.isatty()
522 self._test_close_open_io(io_func)
523
524 def test_close_open_print(self):
525 def io_func():
526 print >> self.f, ''
527 self._test_close_open_io(io_func)
528
529 def test_close_open_read(self):
530 def io_func():
531 self.f.read(0)
532 self._test_close_open_io(io_func)
533
534 def test_close_open_readinto(self):
535 def io_func():
536 a = array('c', 'xxxxx')
537 self.f.readinto(a)
538 self._test_close_open_io(io_func)
539
540 def test_close_open_readline(self):
541 def io_func():
542 self.f.readline()
543 self._test_close_open_io(io_func)
544
545 def test_close_open_readlines(self):
546 def io_func():
547 self.f.readlines()
548 self._test_close_open_io(io_func)
549
550 def test_close_open_seek(self):
551 def io_func():
552 self.f.seek(0, 0)
553 self._test_close_open_io(io_func)
554
555 def test_close_open_tell(self):
556 def io_func():
557 self.f.tell()
558 self._test_close_open_io(io_func)
559
560 def test_close_open_truncate(self):
561 def io_func():
562 self.f.truncate()
563 self._test_close_open_io(io_func)
564
565 def test_close_open_write(self):
566 def io_func():
567 self.f.write('')
568 self._test_close_open_io(io_func)
569
570 def test_close_open_writelines(self):
571 def io_func():
572 self.f.writelines('')
573 self._test_close_open_io(io_func)
574
575
576class StdoutTests(unittest.TestCase):
577
578 def test_move_stdout_on_write(self):
579 # Issue 3242: sys.stdout can be replaced (and freed) during a
580 # print statement; prevent a segfault in this case
581 save_stdout = sys.stdout
582
583 class File:
584 def write(self, data):
585 if '\n' in data:
586 sys.stdout = save_stdout
587
588 try:
589 sys.stdout = File()
590 print "some text"
591 finally:
592 sys.stdout = save_stdout
593
594 def test_del_stdout_before_print(self):
595 # Issue 4597: 'print' with no argument wasn't reporting when
596 # sys.stdout was deleted.
597 save_stdout = sys.stdout
598 del sys.stdout
599 try:
600 print
601 except RuntimeError as e:
602 self.assertEquals(str(e), "lost sys.stdout")
603 else:
604 self.fail("Expected RuntimeError")
605 finally:
606 sys.stdout = save_stdout
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000607
608
609def test_main():
610 # Historically, these tests have been sloppy about removing TESTFN.
611 # So get rid of it no matter what.
612 try:
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000613 run_unittest(AutoFileTests, OtherFileTests, FileSubclassTests,
614 FileThreadingTests, StdoutTests)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000615 finally:
616 if os.path.exists(TESTFN):
617 os.unlink(TESTFN)
618
619if __name__ == '__main__':
620 test_main()