blob: 5c2de37e11da20176042363a244eae308af66b12 [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 Kumarance8e33a2010-01-08 19:04:16 +000037 softspace = f.softspace
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000038 f.name # merely shouldn't blow up
39 f.mode # ditto
40 f.closed # ditto
41
Senthil Kumarance8e33a2010-01-08 19:04:16 +000042 # verify softspace is writable
43 f.softspace = softspace # merely shouldn't blow up
Antoine Pitrou47a5f482009-06-12 20:41:52 +000044
45 # verify the others aren't
46 for attr in 'name', 'mode', 'closed':
47 self.assertRaises((AttributeError, TypeError), setattr, f, attr, 'oops')
48
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000049 def testReadinto(self):
50 # verify readinto
Antoine Pitrou47a5f482009-06-12 20:41:52 +000051 self.f.write('12')
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000052 self.f.close()
Antoine Pitrou47a5f482009-06-12 20:41:52 +000053 a = array('c', 'x'*10)
54 self.f = open(TESTFN, 'rb')
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000055 n = self.f.readinto(a)
Antoine Pitrou47a5f482009-06-12 20:41:52 +000056 self.assertEquals('12', a.tostring()[:n])
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000057
58 def testWritelinesUserList(self):
59 # verify writelines with instance sequence
Antoine Pitrou47a5f482009-06-12 20:41:52 +000060 l = UserList(['1', '2'])
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000061 self.f.writelines(l)
62 self.f.close()
Antoine Pitrou47a5f482009-06-12 20:41:52 +000063 self.f = open(TESTFN, 'rb')
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000064 buf = self.f.read()
Antoine Pitrou47a5f482009-06-12 20:41:52 +000065 self.assertEquals(buf, '12')
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000066
67 def testWritelinesIntegers(self):
68 # verify writelines with integers
69 self.assertRaises(TypeError, self.f.writelines, [1, 2, 3])
70
71 def testWritelinesIntegersUserList(self):
72 # verify writelines with integers in UserList
73 l = UserList([1,2,3])
74 self.assertRaises(TypeError, self.f.writelines, l)
75
76 def testWritelinesNonString(self):
77 # verify writelines with non-string object
78 class NonString:
79 pass
80
81 self.assertRaises(TypeError, self.f.writelines,
82 [NonString(), NonString()])
83
Antoine Pitrou47a5f482009-06-12 20:41:52 +000084 def testRepr(self):
85 # verify repr works
Benjamin Peterson5c8da862009-06-30 22:57:08 +000086 self.assertTrue(repr(self.f).startswith("<open file '" + TESTFN))
Antoine Pitrou47a5f482009-06-12 20:41:52 +000087
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000088 def testErrors(self):
Antoine Pitroubb445a12010-02-05 17:05:54 +000089 self.f.close()
90 self.f = open(TESTFN, 'rb')
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000091 f = self.f
92 self.assertEquals(f.name, TESTFN)
Benjamin Peterson5c8da862009-06-30 22:57:08 +000093 self.assertTrue(not f.isatty())
94 self.assertTrue(not f.closed)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000095
Antoine Pitrou47a5f482009-06-12 20:41:52 +000096 self.assertRaises(TypeError, f.readinto, "")
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000097 f.close()
Benjamin Peterson5c8da862009-06-30 22:57:08 +000098 self.assertTrue(f.closed)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +000099
100 def testMethods(self):
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000101 methods = ['fileno', 'flush', 'isatty', 'next', 'read', 'readinto',
102 'readline', 'readlines', 'seek', 'tell', 'truncate',
Senthil Kumarance8e33a2010-01-08 19:04:16 +0000103 'write', 'xreadlines', '__iter__']
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000104 if sys.platform.startswith('atheos'):
105 methods.remove('truncate')
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000106
107 # __exit__ should close the file
108 self.f.__exit__(None, None, None)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000109 self.assertTrue(self.f.closed)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000110
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000111 for methodname in methods:
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000112 method = getattr(self.f, methodname)
113 # should raise on closed file
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000114 self.assertRaises(ValueError, method)
115 self.assertRaises(ValueError, self.f.writelines, [])
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000116
117 # file is closed, __exit__ shouldn't do anything
118 self.assertEquals(self.f.__exit__(None, None, None), None)
119 # it must also return None if an exception was given
120 try:
Senthil Kumarance8e33a2010-01-08 19:04:16 +0000121 1/0
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000122 except:
123 self.assertEquals(self.f.__exit__(*sys.exc_info()), None)
124
125 def testReadWhenWriting(self):
126 self.assertRaises(IOError, self.f.read)
127
Antoine Pitroubb445a12010-02-05 17:05:54 +0000128 def testIssue5677(self):
129 # Remark: Do not perform more than one test per open file,
130 # since that does NOT catch the readline error on Windows.
131 data = 'xxx'
132 for mode in ['w', 'wb', 'a', 'ab']:
133 for attr in ['read', 'readline', 'readlines']:
134 self.f = open(TESTFN, mode)
135 self.f.write(data)
136 self.assertRaises(IOError, getattr(self.f, attr))
137 self.f.close()
138
139 self.f = open(TESTFN, mode)
140 self.f.write(data)
141 self.assertRaises(IOError, lambda: [line for line in self.f])
142 self.f.close()
143
144 self.f = open(TESTFN, mode)
145 self.f.write(data)
146 self.assertRaises(IOError, self.f.readinto, bytearray(len(data)))
147 self.f.close()
148
149 for mode in ['r', 'rb', 'U', 'Ub', 'Ur', 'rU', 'rbU', 'rUb']:
150 self.f = open(TESTFN, mode)
151 self.assertRaises(IOError, self.f.write, data)
152 self.f.close()
153
154 self.f = open(TESTFN, mode)
155 self.assertRaises(IOError, self.f.writelines, [data, data])
156 self.f.close()
157
158 self.f = open(TESTFN, mode)
159 self.assertRaises(IOError, self.f.truncate)
160 self.f.close()
161
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000162class OtherFileTests(unittest.TestCase):
163
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000164 def testOpenDir(self):
165 this_dir = os.path.dirname(__file__)
166 for mode in (None, "w"):
167 try:
168 if mode:
169 f = open(this_dir, mode)
170 else:
171 f = open(this_dir)
172 except IOError as e:
173 self.assertEqual(e.filename, this_dir)
174 else:
175 self.fail("opening a directory didn't raise an IOError")
176
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000177 def testModeStrings(self):
178 # check invalid mode strings
179 for mode in ("", "aU", "wU+"):
180 try:
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000181 f = open(TESTFN, mode)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000182 except ValueError:
183 pass
184 else:
185 f.close()
186 self.fail('%r is an invalid file mode' % mode)
187
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000188 # Some invalid modes fail on Windows, but pass on Unix
189 # Issue3965: avoid a crash on Windows when filename is unicode
190 for name in (TESTFN, unicode(TESTFN), unicode(TESTFN + '\t')):
191 try:
192 f = open(name, "rr")
193 except (IOError, ValueError):
194 pass
195 else:
196 f.close()
197
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000198 def testStdin(self):
199 # This causes the interpreter to exit on OSF1 v5.1.
200 if sys.platform != 'osf1V5':
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000201 self.assertRaises(IOError, sys.stdin.seek, -1)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000202 else:
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000203 print >>sys.__stdout__, (
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000204 ' Skipping sys.stdin.seek(-1), it may crash the interpreter.'
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000205 ' Test manually.')
206 self.assertRaises(IOError, sys.stdin.truncate)
207
208 def testUnicodeOpen(self):
209 # verify repr works for unicode too
210 f = open(unicode(TESTFN), "w")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000211 self.assertTrue(repr(f).startswith("<open file u'" + TESTFN))
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000212 f.close()
213 os.unlink(TESTFN)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000214
215 def testBadModeArgument(self):
216 # verify that we get a sensible error message for bad mode argument
217 bad_mode = "qwerty"
218 try:
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000219 f = open(TESTFN, bad_mode)
220 except ValueError, msg:
Senthil Kumarance8e33a2010-01-08 19:04:16 +0000221 if msg[0] != 0:
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000222 s = str(msg)
223 if s.find(TESTFN) != -1 or s.find(bad_mode) == -1:
224 self.fail("bad error message for invalid mode: %s" % s)
Senthil Kumarance8e33a2010-01-08 19:04:16 +0000225 # if msg[0] == 0, we're probably on Windows where there may be
226 # no obvious way to discover why open() failed.
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000227 else:
228 f.close()
229 self.fail("no error for invalid mode: %s" % bad_mode)
230
231 def testSetBufferSize(self):
232 # make sure that explicitly setting the buffer size doesn't cause
233 # misbehaviour especially with repeated close() calls
234 for s in (-1, 0, 1, 512):
235 try:
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000236 f = open(TESTFN, 'w', s)
237 f.write(str(s))
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000238 f.close()
239 f.close()
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000240 f = open(TESTFN, 'r', s)
241 d = int(f.read())
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000242 f.close()
243 f.close()
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000244 except IOError, msg:
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000245 self.fail('error setting buffer size %d: %s' % (s, str(msg)))
246 self.assertEquals(d, s)
247
248 def testTruncateOnWindows(self):
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000249 os.unlink(TESTFN)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000250
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000251 def bug801631():
252 # SF bug <http://www.python.org/sf/801631>
253 # "file.truncate fault on windows"
254 f = open(TESTFN, 'wb')
255 f.write('12345678901') # 11 bytes
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000256 f.close()
257
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000258 f = open(TESTFN,'rb+')
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000259 data = f.read(5)
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000260 if data != '12345':
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000261 self.fail("Read on file opened for update failed %r" % data)
262 if f.tell() != 5:
263 self.fail("File pos after read wrong %d" % f.tell())
264
265 f.truncate()
266 if f.tell() != 5:
267 self.fail("File pos after ftruncate wrong %d" % f.tell())
268
269 f.close()
270 size = os.path.getsize(TESTFN)
271 if size != 5:
272 self.fail("File size after ftruncate wrong %d" % size)
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000273
274 try:
275 bug801631()
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000276 finally:
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000277 os.unlink(TESTFN)
278
279 def testIteration(self):
280 # Test the complex interaction when mixing file-iteration and the
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000281 # various read* methods. Ostensibly, the mixture could just be tested
282 # to work when it should work according to the Python language,
283 # instead of fail when it should fail according to the current CPython
284 # implementation. People don't always program Python the way they
285 # should, though, and the implemenation might change in subtle ways,
286 # so we explicitly test for errors, too; the test will just have to
287 # be updated when the implementation changes.
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000288 dataoffset = 16384
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000289 filler = "ham\n"
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000290 assert not dataoffset % len(filler), \
291 "dataoffset must be multiple of len(filler)"
292 nchunks = dataoffset // len(filler)
293 testlines = [
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000294 "spam, spam and eggs\n",
295 "eggs, spam, ham and spam\n",
296 "saussages, spam, spam and eggs\n",
297 "spam, ham, spam and eggs\n",
298 "spam, spam, spam, spam, spam, ham, spam\n",
299 "wonderful spaaaaaam.\n"
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000300 ]
301 methods = [("readline", ()), ("read", ()), ("readlines", ()),
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000302 ("readinto", (array("c", " "*100),))]
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000303
304 try:
305 # Prepare the testfile
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000306 bag = open(TESTFN, "w")
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000307 bag.write(filler * nchunks)
308 bag.writelines(testlines)
309 bag.close()
310 # Test for appropriate errors mixing read* and iteration
311 for methodname, args in methods:
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000312 f = open(TESTFN)
313 if f.next() != filler:
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000314 self.fail, "Broken testfile"
315 meth = getattr(f, methodname)
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000316 try:
317 meth(*args)
318 except ValueError:
319 pass
320 else:
321 self.fail("%s%r after next() didn't raise ValueError" %
322 (methodname, args))
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000323 f.close()
324
325 # Test to see if harmless (by accident) mixing of read* and
326 # iteration still works. This depends on the size of the internal
327 # iteration buffer (currently 8192,) but we can test it in a
328 # flexible manner. Each line in the bag o' ham is 4 bytes
329 # ("h", "a", "m", "\n"), so 4096 lines of that should get us
330 # exactly on the buffer boundary for any power-of-2 buffersize
331 # between 4 and 16384 (inclusive).
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000332 f = open(TESTFN)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000333 for i in range(nchunks):
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000334 f.next()
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000335 testline = testlines.pop(0)
336 try:
337 line = f.readline()
338 except ValueError:
339 self.fail("readline() after next() with supposedly empty "
340 "iteration-buffer failed anyway")
341 if line != testline:
342 self.fail("readline() after next() with empty buffer "
343 "failed. Got %r, expected %r" % (line, testline))
344 testline = testlines.pop(0)
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000345 buf = array("c", "\x00" * len(testline))
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000346 try:
347 f.readinto(buf)
348 except ValueError:
349 self.fail("readinto() after next() with supposedly empty "
350 "iteration-buffer failed anyway")
351 line = buf.tostring()
352 if line != testline:
353 self.fail("readinto() after next() with empty buffer "
354 "failed. Got %r, expected %r" % (line, testline))
355
356 testline = testlines.pop(0)
357 try:
358 line = f.read(len(testline))
359 except ValueError:
360 self.fail("read() after next() with supposedly empty "
361 "iteration-buffer failed anyway")
362 if line != testline:
363 self.fail("read() after next() with empty buffer "
364 "failed. Got %r, expected %r" % (line, testline))
365 try:
366 lines = f.readlines()
367 except ValueError:
368 self.fail("readlines() after next() with supposedly empty "
369 "iteration-buffer failed anyway")
370 if lines != testlines:
371 self.fail("readlines() after next() with empty buffer "
372 "failed. Got %r, expected %r" % (line, testline))
373 # Reading after iteration hit EOF shouldn't hurt either
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000374 f = open(TESTFN)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000375 try:
376 for line in f:
377 pass
378 try:
379 f.readline()
380 f.readinto(buf)
381 f.read()
382 f.readlines()
383 except ValueError:
384 self.fail("read* failed after next() consumed file")
385 finally:
386 f.close()
387 finally:
388 os.unlink(TESTFN)
389
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000390class FileSubclassTests(unittest.TestCase):
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000391
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000392 def testExit(self):
393 # test that exiting with context calls subclass' close
394 class C(file):
395 def __init__(self, *args):
396 self.subclass_closed = False
397 file.__init__(self, *args)
398 def close(self):
399 self.subclass_closed = True
400 file.close(self)
401
402 with C(TESTFN, 'w') as f:
403 pass
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000404 self.assertTrue(f.subclass_closed)
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000405
406
407class FileThreadingTests(unittest.TestCase):
408 # These tests check the ability to call various methods of file objects
409 # (including close()) concurrently without crashing the Python interpreter.
410 # See #815646, #595601
411
412 def setUp(self):
Antoine Pitrou0df2c732009-10-27 19:36:44 +0000413 self._threads = test_support.threading_setup()
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000414 self.f = None
415 self.filename = TESTFN
416 with open(self.filename, "w") as f:
417 f.write("\n".join("0123456789"))
418 self._count_lock = threading.Lock()
419 self.close_count = 0
420 self.close_success_count = 0
421
422 def tearDown(self):
423 if self.f:
424 try:
425 self.f.close()
426 except (EnvironmentError, ValueError):
427 pass
428 try:
429 os.remove(self.filename)
430 except EnvironmentError:
431 pass
Antoine Pitrou0df2c732009-10-27 19:36:44 +0000432 test_support.threading_cleanup(*self._threads)
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000433
434 def _create_file(self):
435 self.f = open(self.filename, "w+")
436
437 def _close_file(self):
438 with self._count_lock:
439 self.close_count += 1
440 self.f.close()
441 with self._count_lock:
442 self.close_success_count += 1
443
444 def _close_and_reopen_file(self):
445 self._close_file()
446 # if close raises an exception thats fine, self.f remains valid so
447 # we don't need to reopen.
448 self._create_file()
449
450 def _run_workers(self, func, nb_workers, duration=0.2):
451 with self._count_lock:
452 self.close_count = 0
453 self.close_success_count = 0
454 self.do_continue = True
455 threads = []
456 try:
457 for i in range(nb_workers):
458 t = threading.Thread(target=func)
459 t.start()
460 threads.append(t)
461 for _ in xrange(100):
462 time.sleep(duration/100)
463 with self._count_lock:
464 if self.close_count-self.close_success_count > nb_workers+1:
465 if test_support.verbose:
466 print 'Q',
467 break
468 time.sleep(duration)
469 finally:
470 self.do_continue = False
471 for t in threads:
472 t.join()
473
474 def _test_close_open_io(self, io_func, nb_workers=5):
475 def worker():
476 self._create_file()
477 funcs = itertools.cycle((
478 lambda: io_func(),
479 lambda: self._close_and_reopen_file(),
480 ))
481 for f in funcs:
482 if not self.do_continue:
483 break
484 try:
485 f()
486 except (IOError, ValueError):
487 pass
488 self._run_workers(worker, nb_workers)
489 if test_support.verbose:
490 # Useful verbose statistics when tuning this test to take
491 # less time to run but still ensuring that its still useful.
492 #
493 # the percent of close calls that raised an error
494 percent = 100. - 100.*self.close_success_count/self.close_count
495 print self.close_count, ('%.4f ' % percent),
496
497 def test_close_open(self):
498 def io_func():
499 pass
500 self._test_close_open_io(io_func)
501
502 def test_close_open_flush(self):
503 def io_func():
504 self.f.flush()
505 self._test_close_open_io(io_func)
506
507 def test_close_open_iter(self):
508 def io_func():
509 list(iter(self.f))
510 self._test_close_open_io(io_func)
511
512 def test_close_open_isatty(self):
513 def io_func():
514 self.f.isatty()
515 self._test_close_open_io(io_func)
516
517 def test_close_open_print(self):
518 def io_func():
519 print >> self.f, ''
520 self._test_close_open_io(io_func)
521
522 def test_close_open_read(self):
523 def io_func():
524 self.f.read(0)
525 self._test_close_open_io(io_func)
526
527 def test_close_open_readinto(self):
528 def io_func():
529 a = array('c', 'xxxxx')
530 self.f.readinto(a)
531 self._test_close_open_io(io_func)
532
533 def test_close_open_readline(self):
534 def io_func():
535 self.f.readline()
536 self._test_close_open_io(io_func)
537
538 def test_close_open_readlines(self):
539 def io_func():
540 self.f.readlines()
541 self._test_close_open_io(io_func)
542
543 def test_close_open_seek(self):
544 def io_func():
545 self.f.seek(0, 0)
546 self._test_close_open_io(io_func)
547
548 def test_close_open_tell(self):
549 def io_func():
550 self.f.tell()
551 self._test_close_open_io(io_func)
552
553 def test_close_open_truncate(self):
554 def io_func():
555 self.f.truncate()
556 self._test_close_open_io(io_func)
557
558 def test_close_open_write(self):
559 def io_func():
560 self.f.write('')
561 self._test_close_open_io(io_func)
562
563 def test_close_open_writelines(self):
564 def io_func():
565 self.f.writelines('')
566 self._test_close_open_io(io_func)
567
568
569class StdoutTests(unittest.TestCase):
570
571 def test_move_stdout_on_write(self):
572 # Issue 3242: sys.stdout can be replaced (and freed) during a
573 # print statement; prevent a segfault in this case
574 save_stdout = sys.stdout
575
576 class File:
577 def write(self, data):
578 if '\n' in data:
579 sys.stdout = save_stdout
580
581 try:
582 sys.stdout = File()
583 print "some text"
584 finally:
585 sys.stdout = save_stdout
586
587 def test_del_stdout_before_print(self):
588 # Issue 4597: 'print' with no argument wasn't reporting when
589 # sys.stdout was deleted.
590 save_stdout = sys.stdout
591 del sys.stdout
592 try:
593 print
594 except RuntimeError as e:
595 self.assertEquals(str(e), "lost sys.stdout")
596 else:
597 self.fail("Expected RuntimeError")
598 finally:
599 sys.stdout = save_stdout
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000600
601
602def test_main():
603 # Historically, these tests have been sloppy about removing TESTFN.
604 # So get rid of it no matter what.
605 try:
Antoine Pitrou47a5f482009-06-12 20:41:52 +0000606 run_unittest(AutoFileTests, OtherFileTests, FileSubclassTests,
607 FileThreadingTests, StdoutTests)
Antoine Pitrouc5d2b412009-06-12 20:36:25 +0000608 finally:
609 if os.path.exists(TESTFN):
610 os.unlink(TESTFN)
611
612if __name__ == '__main__':
613 test_main()