blob: bebc43ddd61abb8ac11db8e39fd67480e1585050 [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
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000011from test.test_support import TESTFN, findfile, run_unittest
12from 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
Senthil Kumaran3ddc4352010-01-08 18:41:40 +000037 # Silence Py3k warning
38 with test_support.check_warnings():
39 softspace = f.softspace
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000040 f.name # merely shouldn't blow up
41 f.mode # ditto
42 f.closed # ditto
43
Senthil Kumaran3ddc4352010-01-08 18:41:40 +000044 # Silence Py3k warning
45 with test_support.check_warnings():
46 # verify softspace is writable
47 f.softspace = softspace # merely shouldn't blow up
Antoine Pitrou47a5f482009-06-12 20:41:52 +000048
49 # verify the others aren't
50 for attr in 'name', 'mode', 'closed':
51 self.assertRaises((AttributeError, TypeError), setattr, f, attr, 'oops')
52
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000053 def testReadinto(self):
54 # verify readinto
Antoine Pitrou47a5f482009-06-12 20:41:52 +000055 self.f.write('12')
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000056 self.f.close()
Antoine Pitrou47a5f482009-06-12 20:41:52 +000057 a = array('c', 'x'*10)
58 self.f = open(TESTFN, 'rb')
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000059 n = self.f.readinto(a)
Antoine Pitrou47a5f482009-06-12 20:41:52 +000060 self.assertEquals('12', a.tostring()[:n])
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000061
62 def testWritelinesUserList(self):
63 # verify writelines with instance sequence
Antoine Pitrou47a5f482009-06-12 20:41:52 +000064 l = UserList(['1', '2'])
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000065 self.f.writelines(l)
66 self.f.close()
Antoine Pitrou47a5f482009-06-12 20:41:52 +000067 self.f = open(TESTFN, 'rb')
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000068 buf = self.f.read()
Antoine Pitrou47a5f482009-06-12 20:41:52 +000069 self.assertEquals(buf, '12')
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000070
71 def testWritelinesIntegers(self):
72 # verify writelines with integers
73 self.assertRaises(TypeError, self.f.writelines, [1, 2, 3])
74
75 def testWritelinesIntegersUserList(self):
76 # verify writelines with integers in UserList
77 l = UserList([1,2,3])
78 self.assertRaises(TypeError, self.f.writelines, l)
79
80 def testWritelinesNonString(self):
81 # verify writelines with non-string object
82 class NonString:
83 pass
84
85 self.assertRaises(TypeError, self.f.writelines,
86 [NonString(), NonString()])
87
Antoine Pitrou47a5f482009-06-12 20:41:52 +000088 def testRepr(self):
89 # verify repr works
Benjamin Peterson5c8da862009-06-30 22:57:08 +000090 self.assertTrue(repr(self.f).startswith("<open file '" + TESTFN))
Antoine Pitrou47a5f482009-06-12 20:41:52 +000091
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000092 def testErrors(self):
93 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',
Senthil Kumaran3ddc4352010-01-08 18:41:40 +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)
Senthil Kumaran3ddc4352010-01-08 18:41:40 +0000118 # Silence Py3k warning
119 with test_support.check_warnings():
120 for methodname in deprecated_methods:
121 method = getattr(self.f, methodname)
122 self.assertRaises(ValueError, method)
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000123 self.assertRaises(ValueError, self.f.writelines, [])
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000124
125 # file is closed, __exit__ shouldn't do anything
126 self.assertEquals(self.f.__exit__(None, None, None), None)
127 # it must also return None if an exception was given
128 try:
Senthil Kumaran3ddc4352010-01-08 18:41:40 +0000129 1 // 0
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000130 except:
131 self.assertEquals(self.f.__exit__(*sys.exc_info()), None)
132
133 def testReadWhenWriting(self):
134 self.assertRaises(IOError, self.f.read)
135
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000136class OtherFileTests(unittest.TestCase):
137
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000138 def testOpenDir(self):
139 this_dir = os.path.dirname(__file__)
140 for mode in (None, "w"):
141 try:
142 if mode:
143 f = open(this_dir, mode)
144 else:
145 f = open(this_dir)
146 except IOError as e:
147 self.assertEqual(e.filename, this_dir)
148 else:
149 self.fail("opening a directory didn't raise an IOError")
150
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000151 def testModeStrings(self):
152 # check invalid mode strings
153 for mode in ("", "aU", "wU+"):
154 try:
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000155 f = open(TESTFN, mode)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000156 except ValueError:
157 pass
158 else:
159 f.close()
160 self.fail('%r is an invalid file mode' % mode)
161
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000162 # Some invalid modes fail on Windows, but pass on Unix
163 # Issue3965: avoid a crash on Windows when filename is unicode
164 for name in (TESTFN, unicode(TESTFN), unicode(TESTFN + '\t')):
165 try:
166 f = open(name, "rr")
167 except (IOError, ValueError):
168 pass
169 else:
170 f.close()
171
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000172 def testStdin(self):
173 # This causes the interpreter to exit on OSF1 v5.1.
174 if sys.platform != 'osf1V5':
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000175 self.assertRaises(IOError, sys.stdin.seek, -1)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000176 else:
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000177 print >>sys.__stdout__, (
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000178 ' Skipping sys.stdin.seek(-1), it may crash the interpreter.'
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000179 ' Test manually.')
180 self.assertRaises(IOError, sys.stdin.truncate)
181
182 def testUnicodeOpen(self):
183 # verify repr works for unicode too
184 f = open(unicode(TESTFN), "w")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000185 self.assertTrue(repr(f).startswith("<open file u'" + TESTFN))
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000186 f.close()
187 os.unlink(TESTFN)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000188
189 def testBadModeArgument(self):
190 # verify that we get a sensible error message for bad mode argument
191 bad_mode = "qwerty"
192 try:
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000193 f = open(TESTFN, bad_mode)
194 except ValueError, msg:
Senthil Kumaran3ddc4352010-01-08 18:41:40 +0000195 if msg.args[0] != 0:
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000196 s = str(msg)
197 if s.find(TESTFN) != -1 or s.find(bad_mode) == -1:
198 self.fail("bad error message for invalid mode: %s" % s)
Senthil Kumaran3ddc4352010-01-08 18:41:40 +0000199 # if msg.args[0] == 0, we're probably on Windows where there may
200 # be no obvious way to discover why open() failed.
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000201 else:
202 f.close()
203 self.fail("no error for invalid mode: %s" % bad_mode)
204
205 def testSetBufferSize(self):
206 # make sure that explicitly setting the buffer size doesn't cause
207 # misbehaviour especially with repeated close() calls
208 for s in (-1, 0, 1, 512):
209 try:
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000210 f = open(TESTFN, 'w', s)
211 f.write(str(s))
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000212 f.close()
213 f.close()
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000214 f = open(TESTFN, 'r', s)
215 d = int(f.read())
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000216 f.close()
217 f.close()
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000218 except IOError, msg:
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000219 self.fail('error setting buffer size %d: %s' % (s, str(msg)))
220 self.assertEquals(d, s)
221
222 def testTruncateOnWindows(self):
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000223 os.unlink(TESTFN)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000224
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000225 def bug801631():
226 # SF bug <http://www.python.org/sf/801631>
227 # "file.truncate fault on windows"
228 f = open(TESTFN, 'wb')
229 f.write('12345678901') # 11 bytes
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000230 f.close()
231
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000232 f = open(TESTFN,'rb+')
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000233 data = f.read(5)
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000234 if data != '12345':
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000235 self.fail("Read on file opened for update failed %r" % data)
236 if f.tell() != 5:
237 self.fail("File pos after read wrong %d" % f.tell())
238
239 f.truncate()
240 if f.tell() != 5:
241 self.fail("File pos after ftruncate wrong %d" % f.tell())
242
243 f.close()
244 size = os.path.getsize(TESTFN)
245 if size != 5:
246 self.fail("File size after ftruncate wrong %d" % size)
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000247
248 try:
249 bug801631()
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000250 finally:
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000251 os.unlink(TESTFN)
252
253 def testIteration(self):
254 # Test the complex interaction when mixing file-iteration and the
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000255 # various read* methods. Ostensibly, the mixture could just be tested
256 # to work when it should work according to the Python language,
257 # instead of fail when it should fail according to the current CPython
258 # implementation. People don't always program Python the way they
259 # should, though, and the implemenation might change in subtle ways,
260 # so we explicitly test for errors, too; the test will just have to
261 # be updated when the implementation changes.
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000262 dataoffset = 16384
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000263 filler = "ham\n"
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000264 assert not dataoffset % len(filler), \
265 "dataoffset must be multiple of len(filler)"
266 nchunks = dataoffset // len(filler)
267 testlines = [
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000268 "spam, spam and eggs\n",
269 "eggs, spam, ham and spam\n",
270 "saussages, spam, spam and eggs\n",
271 "spam, ham, spam and eggs\n",
272 "spam, spam, spam, spam, spam, ham, spam\n",
273 "wonderful spaaaaaam.\n"
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000274 ]
275 methods = [("readline", ()), ("read", ()), ("readlines", ()),
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000276 ("readinto", (array("c", " "*100),))]
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000277
278 try:
279 # Prepare the testfile
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000280 bag = open(TESTFN, "w")
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000281 bag.write(filler * nchunks)
282 bag.writelines(testlines)
283 bag.close()
284 # Test for appropriate errors mixing read* and iteration
285 for methodname, args in methods:
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000286 f = open(TESTFN)
287 if f.next() != filler:
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000288 self.fail, "Broken testfile"
289 meth = getattr(f, methodname)
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000290 try:
291 meth(*args)
292 except ValueError:
293 pass
294 else:
295 self.fail("%s%r after next() didn't raise ValueError" %
296 (methodname, args))
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000297 f.close()
298
299 # Test to see if harmless (by accident) mixing of read* and
300 # iteration still works. This depends on the size of the internal
301 # iteration buffer (currently 8192,) but we can test it in a
302 # flexible manner. Each line in the bag o' ham is 4 bytes
303 # ("h", "a", "m", "\n"), so 4096 lines of that should get us
304 # exactly on the buffer boundary for any power-of-2 buffersize
305 # between 4 and 16384 (inclusive).
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000306 f = open(TESTFN)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000307 for i in range(nchunks):
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000308 f.next()
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000309 testline = testlines.pop(0)
310 try:
311 line = f.readline()
312 except ValueError:
313 self.fail("readline() after next() with supposedly empty "
314 "iteration-buffer failed anyway")
315 if line != testline:
316 self.fail("readline() after next() with empty buffer "
317 "failed. Got %r, expected %r" % (line, testline))
318 testline = testlines.pop(0)
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000319 buf = array("c", "\x00" * len(testline))
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000320 try:
321 f.readinto(buf)
322 except ValueError:
323 self.fail("readinto() after next() with supposedly empty "
324 "iteration-buffer failed anyway")
325 line = buf.tostring()
326 if line != testline:
327 self.fail("readinto() after next() with empty buffer "
328 "failed. Got %r, expected %r" % (line, testline))
329
330 testline = testlines.pop(0)
331 try:
332 line = f.read(len(testline))
333 except ValueError:
334 self.fail("read() after next() with supposedly empty "
335 "iteration-buffer failed anyway")
336 if line != testline:
337 self.fail("read() after next() with empty buffer "
338 "failed. Got %r, expected %r" % (line, testline))
339 try:
340 lines = f.readlines()
341 except ValueError:
342 self.fail("readlines() after next() with supposedly empty "
343 "iteration-buffer failed anyway")
344 if lines != testlines:
345 self.fail("readlines() after next() with empty buffer "
346 "failed. Got %r, expected %r" % (line, testline))
347 # Reading after iteration hit EOF shouldn't hurt either
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000348 f = open(TESTFN)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000349 try:
350 for line in f:
351 pass
352 try:
353 f.readline()
354 f.readinto(buf)
355 f.read()
356 f.readlines()
357 except ValueError:
358 self.fail("read* failed after next() consumed file")
359 finally:
360 f.close()
361 finally:
362 os.unlink(TESTFN)
363
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000364class FileSubclassTests(unittest.TestCase):
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000365
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000366 def testExit(self):
367 # test that exiting with context calls subclass' close
368 class C(file):
369 def __init__(self, *args):
370 self.subclass_closed = False
371 file.__init__(self, *args)
372 def close(self):
373 self.subclass_closed = True
374 file.close(self)
375
376 with C(TESTFN, 'w') as f:
377 pass
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000378 self.assertTrue(f.subclass_closed)
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000379
380
381class FileThreadingTests(unittest.TestCase):
382 # These tests check the ability to call various methods of file objects
383 # (including close()) concurrently without crashing the Python interpreter.
384 # See #815646, #595601
385
386 def setUp(self):
Antoine Pitrou0df2c732009-10-27 19:36:44 +0000387 self._threads = test_support.threading_setup()
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000388 self.f = None
389 self.filename = TESTFN
390 with open(self.filename, "w") as f:
391 f.write("\n".join("0123456789"))
392 self._count_lock = threading.Lock()
393 self.close_count = 0
394 self.close_success_count = 0
395
396 def tearDown(self):
397 if self.f:
398 try:
399 self.f.close()
400 except (EnvironmentError, ValueError):
401 pass
402 try:
403 os.remove(self.filename)
404 except EnvironmentError:
405 pass
Antoine Pitrou0df2c732009-10-27 19:36:44 +0000406 test_support.threading_cleanup(*self._threads)
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000407
408 def _create_file(self):
409 self.f = open(self.filename, "w+")
410
411 def _close_file(self):
412 with self._count_lock:
413 self.close_count += 1
414 self.f.close()
415 with self._count_lock:
416 self.close_success_count += 1
417
418 def _close_and_reopen_file(self):
419 self._close_file()
420 # if close raises an exception thats fine, self.f remains valid so
421 # we don't need to reopen.
422 self._create_file()
423
424 def _run_workers(self, func, nb_workers, duration=0.2):
425 with self._count_lock:
426 self.close_count = 0
427 self.close_success_count = 0
428 self.do_continue = True
429 threads = []
430 try:
431 for i in range(nb_workers):
432 t = threading.Thread(target=func)
433 t.start()
434 threads.append(t)
435 for _ in xrange(100):
436 time.sleep(duration/100)
437 with self._count_lock:
438 if self.close_count-self.close_success_count > nb_workers+1:
439 if test_support.verbose:
440 print 'Q',
441 break
442 time.sleep(duration)
443 finally:
444 self.do_continue = False
445 for t in threads:
446 t.join()
447
448 def _test_close_open_io(self, io_func, nb_workers=5):
449 def worker():
450 self._create_file()
451 funcs = itertools.cycle((
452 lambda: io_func(),
453 lambda: self._close_and_reopen_file(),
454 ))
455 for f in funcs:
456 if not self.do_continue:
457 break
458 try:
459 f()
460 except (IOError, ValueError):
461 pass
462 self._run_workers(worker, nb_workers)
463 if test_support.verbose:
464 # Useful verbose statistics when tuning this test to take
465 # less time to run but still ensuring that its still useful.
466 #
467 # the percent of close calls that raised an error
468 percent = 100. - 100.*self.close_success_count/self.close_count
469 print self.close_count, ('%.4f ' % percent),
470
471 def test_close_open(self):
472 def io_func():
473 pass
474 self._test_close_open_io(io_func)
475
476 def test_close_open_flush(self):
477 def io_func():
478 self.f.flush()
479 self._test_close_open_io(io_func)
480
481 def test_close_open_iter(self):
482 def io_func():
483 list(iter(self.f))
484 self._test_close_open_io(io_func)
485
486 def test_close_open_isatty(self):
487 def io_func():
488 self.f.isatty()
489 self._test_close_open_io(io_func)
490
491 def test_close_open_print(self):
492 def io_func():
493 print >> self.f, ''
494 self._test_close_open_io(io_func)
495
496 def test_close_open_read(self):
497 def io_func():
498 self.f.read(0)
499 self._test_close_open_io(io_func)
500
501 def test_close_open_readinto(self):
502 def io_func():
503 a = array('c', 'xxxxx')
504 self.f.readinto(a)
505 self._test_close_open_io(io_func)
506
507 def test_close_open_readline(self):
508 def io_func():
509 self.f.readline()
510 self._test_close_open_io(io_func)
511
512 def test_close_open_readlines(self):
513 def io_func():
514 self.f.readlines()
515 self._test_close_open_io(io_func)
516
517 def test_close_open_seek(self):
518 def io_func():
519 self.f.seek(0, 0)
520 self._test_close_open_io(io_func)
521
522 def test_close_open_tell(self):
523 def io_func():
524 self.f.tell()
525 self._test_close_open_io(io_func)
526
527 def test_close_open_truncate(self):
528 def io_func():
529 self.f.truncate()
530 self._test_close_open_io(io_func)
531
532 def test_close_open_write(self):
533 def io_func():
534 self.f.write('')
535 self._test_close_open_io(io_func)
536
537 def test_close_open_writelines(self):
538 def io_func():
539 self.f.writelines('')
540 self._test_close_open_io(io_func)
541
542
543class StdoutTests(unittest.TestCase):
544
545 def test_move_stdout_on_write(self):
546 # Issue 3242: sys.stdout can be replaced (and freed) during a
547 # print statement; prevent a segfault in this case
548 save_stdout = sys.stdout
549
550 class File:
551 def write(self, data):
552 if '\n' in data:
553 sys.stdout = save_stdout
554
555 try:
556 sys.stdout = File()
557 print "some text"
558 finally:
559 sys.stdout = save_stdout
560
561 def test_del_stdout_before_print(self):
562 # Issue 4597: 'print' with no argument wasn't reporting when
563 # sys.stdout was deleted.
564 save_stdout = sys.stdout
565 del sys.stdout
566 try:
567 print
568 except RuntimeError as e:
569 self.assertEquals(str(e), "lost sys.stdout")
570 else:
571 self.fail("Expected RuntimeError")
572 finally:
573 sys.stdout = save_stdout
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000574
575
576def test_main():
577 # Historically, these tests have been sloppy about removing TESTFN.
578 # So get rid of it no matter what.
579 try:
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000580 run_unittest(AutoFileTests, OtherFileTests, FileSubclassTests,
581 FileThreadingTests, StdoutTests)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000582 finally:
583 if os.path.exists(TESTFN):
584 os.unlink(TESTFN)
585
586if __name__ == '__main__':
587 test_main()