10c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Adapted from test_file.py by Daniel Stutzbach
20c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
30c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom __future__ import unicode_literals
40c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
50c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport sys
60c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport os
70c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport errno
80c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport unittest
90c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom array import array
100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom weakref import proxy
110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom functools import wraps
120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom UserList import UserList
130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport _testcapi
140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom test.test_support import TESTFN, check_warnings, run_unittest, make_bad_fd
160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom test.test_support import py3k_bytes as bytes
170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom test.script_helper import run_python
180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom _io import FileIO as _FileIO
200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass AutoFileTests(unittest.TestCase):
220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # file tests for which a test file is automatically set up
230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def setUp(self):
250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f = _FileIO(TESTFN, 'w')
260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def tearDown(self):
280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.f:
290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.f.close()
300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        os.remove(TESTFN)
310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testWeakRefs(self):
330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # verify weak references
340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        p = proxy(self.f)
350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        p.write(bytes(range(10)))
360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(self.f.tell(), p.tell())
370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f.close()
380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f = None
390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ReferenceError, getattr, p, 'tell')
400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testSeekTell(self):
420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f.write(bytes(range(20)))
430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(self.f.tell(), 20)
440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f.seek(0)
450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(self.f.tell(), 0)
460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f.seek(10)
470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(self.f.tell(), 10)
480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f.seek(5, 1)
490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(self.f.tell(), 15)
500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f.seek(-5, 1)
510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(self.f.tell(), 10)
520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f.seek(-5, 2)
530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(self.f.tell(), 15)
540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testAttributes(self):
560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # verify expected attributes exist
570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f = self.f
580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(f.mode, "wb")
600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(f.closed, False)
610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # verify the attributes are readonly
630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for attr in 'mode', 'closed':
640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises((AttributeError, TypeError),
650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                              setattr, f, attr, 'oops')
660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testReadinto(self):
680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # verify readinto
690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f.write(b"\x01\x02")
700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f.close()
710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        a = array(b'b', b'x'*10)
720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f = _FileIO(TESTFN, 'r')
730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        n = self.f.readinto(a)
740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(array(b'b', [1, 2]), a[:n])
750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testWritelinesList(self):
770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        l = [b'123', b'456']
780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f.writelines(l)
790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f.close()
800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f = _FileIO(TESTFN, 'rb')
810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        buf = self.f.read()
820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(buf, b'123456')
830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testWritelinesUserList(self):
850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        l = UserList([b'123', b'456'])
860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f.writelines(l)
870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f.close()
880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f = _FileIO(TESTFN, 'rb')
890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        buf = self.f.read()
900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(buf, b'123456')
910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testWritelinesError(self):
930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, self.f.writelines, [1, 2, 3])
940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, self.f.writelines, None)
950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_none_args(self):
970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f.write(b"hi\nbye\nabc")
980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f.close()
990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f = _FileIO(TESTFN, 'r')
1000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(self.f.read(None), b"hi\nbye\nabc")
1010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f.seek(0)
1020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(self.f.readline(None), b"hi\n")
1030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(self.f.readlines(None), [b"bye\n", b"abc"])
1040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testRepr(self):
1060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(repr(self.f), "<_io.FileIO name=%r mode='%s'>"
1070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                       % (self.f.name, self.f.mode))
1080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        del self.f.name
1090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(repr(self.f), "<_io.FileIO fd=%r mode='%s'>"
1100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                       % (self.f.fileno(), self.f.mode))
1110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f.close()
1120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(repr(self.f), "<_io.FileIO [closed]>")
1130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testErrors(self):
1150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f = self.f
1160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(not f.isatty())
1170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(not f.closed)
1180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        #self.assertEqual(f.name, TESTFN)
1190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, f.read, 10) # Open for reading
1200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f.close()
1210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(f.closed)
1220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f = _FileIO(TESTFN, 'r')
1230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, f.readinto, "")
1240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(not f.closed)
1250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f.close()
1260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(f.closed)
1270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testMethods(self):
1290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        methods = ['fileno', 'isatty', 'read', 'readinto',
1300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                   'seek', 'tell', 'truncate', 'write', 'seekable',
1310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                   'readable', 'writable']
1320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if sys.platform.startswith('atheos'):
1330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            methods.remove('truncate')
1340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f.close()
1360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(self.f.closed)
1370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for methodname in methods:
1390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            method = getattr(self.f, methodname)
1400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # should raise on closed file
1410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(ValueError, method)
1420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testOpendir(self):
1440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Issue 3703: opening a directory should fill the errno
1450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Windows always returns "[Errno 13]: Permission denied
1460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Unix calls dircheck() and returns "[Errno 21]: Is a directory"
1470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        try:
1480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            _FileIO('.', 'r')
1490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        except IOError as e:
1500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertNotEqual(e.errno, 0)
1510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(e.filename, ".")
1520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
1530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.fail("Should have raised IOError")
1540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    @unittest.skipIf(os.name == 'nt', "test only works on a POSIX-like system")
1560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testOpenDirFD(self):
1570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        fd = os.open('.', os.O_RDONLY)
1580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        with self.assertRaises(IOError) as cm:
1590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            _FileIO(fd, 'r')
1600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        os.close(fd)
1610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(cm.exception.errno, errno.EISDIR)
1620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    #A set of functions testing that we get expected behaviour if someone has
1640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    #manually closed the internal file descriptor.  First, a decorator:
1650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def ClosedFD(func):
1660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        @wraps(func)
1670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        def wrapper(self):
1680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            #forcibly close the fd before invoking the problem function
1690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            f = self.f
1700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            os.close(f.fileno())
1710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            try:
1720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                func(self, f)
1730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            finally:
1740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                try:
1750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    self.f.close()
1760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                except IOError:
1770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    pass
1780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return wrapper
1790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def ClosedFDRaises(func):
1810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        @wraps(func)
1820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        def wrapper(self):
1830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            #forcibly close the fd before invoking the problem function
1840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            f = self.f
1850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            os.close(f.fileno())
1860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            try:
1870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                func(self, f)
1880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            except IOError as e:
1890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.assertEqual(e.errno, errno.EBADF)
1900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            else:
1910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.fail("Should have raised IOError")
1920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            finally:
1930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                try:
1940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    self.f.close()
1950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                except IOError:
1960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    pass
1970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return wrapper
1980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    @ClosedFDRaises
2000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testErrnoOnClose(self, f):
2010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f.close()
2020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    @ClosedFDRaises
2040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testErrnoOnClosedWrite(self, f):
2050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f.write('a')
2060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    @ClosedFDRaises
2080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testErrnoOnClosedSeek(self, f):
2090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f.seek(0)
2100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    @ClosedFDRaises
2120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testErrnoOnClosedTell(self, f):
2130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f.tell()
2140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    @ClosedFDRaises
2160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testErrnoOnClosedTruncate(self, f):
2170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f.truncate(0)
2180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    @ClosedFD
2200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testErrnoOnClosedSeekable(self, f):
2210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f.seekable()
2220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    @ClosedFD
2240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testErrnoOnClosedReadable(self, f):
2250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f.readable()
2260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    @ClosedFD
2280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testErrnoOnClosedWritable(self, f):
2290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f.writable()
2300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    @ClosedFD
2320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testErrnoOnClosedFileno(self, f):
2330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f.fileno()
2340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    @ClosedFD
2360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testErrnoOnClosedIsatty(self, f):
2370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(f.isatty(), False)
2380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def ReopenForRead(self):
2400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        try:
2410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.f.close()
2420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        except IOError:
2430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            pass
2440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.f = _FileIO(TESTFN, 'r')
2450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        os.close(self.f.fileno())
2460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.f
2470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    @ClosedFDRaises
2490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testErrnoOnClosedRead(self, f):
2500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f = self.ReopenForRead()
2510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f.read(1)
2520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    @ClosedFDRaises
2540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testErrnoOnClosedReadall(self, f):
2550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f = self.ReopenForRead()
2560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f.readall()
2570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    @ClosedFDRaises
2590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testErrnoOnClosedReadinto(self, f):
2600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f = self.ReopenForRead()
2610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        a = array(b'b', b'x'*10)
2620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f.readinto(a)
2630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass OtherFileTests(unittest.TestCase):
2650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testAbles(self):
2670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        try:
2680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            f = _FileIO(TESTFN, "w")
2690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(f.readable(), False)
2700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(f.writable(), True)
2710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(f.seekable(), True)
2720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            f.close()
2730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            f = _FileIO(TESTFN, "r")
2750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(f.readable(), True)
2760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(f.writable(), False)
2770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(f.seekable(), True)
2780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            f.close()
2790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            f = _FileIO(TESTFN, "a+")
2810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(f.readable(), True)
2820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(f.writable(), True)
2830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(f.seekable(), True)
2840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(f.isatty(), False)
2850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            f.close()
2860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if sys.platform != "win32":
2880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                try:
2890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    f = _FileIO("/dev/tty", "a")
2900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                except EnvironmentError:
2910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    # When run in a cron job there just aren't any
2920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    # ttys, so skip the test.  This also handles other
2930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    # OS'es that don't support /dev/tty.
2940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    pass
2950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                else:
2960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    self.assertEqual(f.readable(), False)
2970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    self.assertEqual(f.writable(), True)
2980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    if sys.platform != "darwin" and \
2990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                       'bsd' not in sys.platform and \
3000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                       not sys.platform.startswith('sunos'):
3010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        # Somehow /dev/tty appears seekable on some BSDs
3020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        self.assertEqual(f.seekable(), False)
3030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    self.assertEqual(f.isatty(), True)
3040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    f.close()
3050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        finally:
3060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            os.unlink(TESTFN)
3070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testModeStrings(self):
3090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # check invalid mode strings
3100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for mode in ("", "aU", "wU+", "rw", "rt"):
3110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            try:
3120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                f = _FileIO(TESTFN, mode)
3130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            except ValueError:
3140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                pass
3150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            else:
3160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                f.close()
3170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.fail('%r is an invalid file mode' % mode)
3180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testUnicodeOpen(self):
3200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # verify repr works for unicode too
3210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f = _FileIO(str(TESTFN), "w")
3220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f.close()
3230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        os.unlink(TESTFN)
3240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testBytesOpen(self):
3260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Opening a bytes filename
3270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        try:
3280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            fn = TESTFN.encode("ascii")
3290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        except UnicodeEncodeError:
3300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # Skip test
3310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return
3320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f = _FileIO(fn, "w")
3330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        try:
3340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            f.write(b"abc")
3350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            f.close()
3360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            with open(TESTFN, "rb") as f:
3370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.assertEqual(f.read(), b"abc")
3380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        finally:
3390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            os.unlink(TESTFN)
3400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testInvalidFd(self):
3420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, _FileIO, -10)
3430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(OSError, _FileIO, make_bad_fd())
3440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if sys.platform == 'win32':
3450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            import msvcrt
3460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(IOError, msvcrt.get_osfhandle, make_bad_fd())
3470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Issue 15989
3480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, _FileIO, _testcapi.INT_MAX + 1)
3490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, _FileIO, _testcapi.INT_MIN - 1)
3500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testBadModeArgument(self):
3520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # verify that we get a sensible error message for bad mode argument
3530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        bad_mode = "qwerty"
3540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        try:
3550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            f = _FileIO(TESTFN, bad_mode)
3560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        except ValueError as msg:
3570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if msg.args[0] != 0:
3580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                s = str(msg)
3590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                if TESTFN in s or bad_mode not in s:
3600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    self.fail("bad error message for invalid mode: %s" % s)
3610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # if msg.args[0] == 0, we're probably on Windows where there may be
3620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # no obvious way to discover why open() failed.
3630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
3640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            f.close()
3650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.fail("no error for invalid mode: %s" % bad_mode)
3660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testTruncate(self):
3680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f = _FileIO(TESTFN, 'w')
3690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f.write(bytes(bytearray(range(10))))
3700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(f.tell(), 10)
3710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f.truncate(5)
3720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(f.tell(), 10)
3730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(f.seek(0, os.SEEK_END), 5)
3740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f.truncate(15)
3750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(f.tell(), 5)
3760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(f.seek(0, os.SEEK_END), 15)
3770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f.close()
3780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testTruncateOnWindows(self):
3800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        def bug801631():
3810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # SF bug <http://www.python.org/sf/801631>
3820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # "file.truncate fault on windows"
3830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            f = _FileIO(TESTFN, 'w')
3840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            f.write(bytes(range(11)))
3850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            f.close()
3860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            f = _FileIO(TESTFN,'r+')
3880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            data = f.read(5)
3890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if data != bytes(range(5)):
3900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.fail("Read on file opened for update failed %r" % data)
3910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if f.tell() != 5:
3920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.fail("File pos after read wrong %d" % f.tell())
3930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            f.truncate()
3950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if f.tell() != 5:
3960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.fail("File pos after ftruncate wrong %d" % f.tell())
3970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            f.close()
3990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            size = os.path.getsize(TESTFN)
4000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if size != 5:
4010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.fail("File size after ftruncate wrong %d" % size)
4020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        try:
4040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            bug801631()
4050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        finally:
4060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            os.unlink(TESTFN)
4070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testAppend(self):
4090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        try:
4100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            f = open(TESTFN, 'wb')
4110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            f.write(b'spam')
4120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            f.close()
4130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            f = open(TESTFN, 'ab')
4140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            f.write(b'eggs')
4150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            f.close()
4160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            f = open(TESTFN, 'rb')
4170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d = f.read()
4180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            f.close()
4190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(d, b'spameggs')
4200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        finally:
4210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            try:
4220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                os.unlink(TESTFN)
4230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            except:
4240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                pass
4250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testInvalidInit(self):
4270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, _FileIO, "1", 0, 0)
4280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testWarnings(self):
4300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        with check_warnings(quiet=True) as w:
4310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(w.warnings, [])
4320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, _FileIO, [])
4330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(w.warnings, [])
4340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(ValueError, _FileIO, "/some/invalid/name", "rt")
4350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(w.warnings, [])
4360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_surrogates(self):
4380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Issue #8438: try to open a filename containing surrogates.
4390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # It should either fail because the file doesn't exist or the filename
4400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # can't be represented using the filesystem encoding, but not because
4410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # of a LookupError for the error handler "surrogateescape".
4420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        filename = u'\udc80.txt'
4430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        try:
4440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            with _FileIO(filename):
4450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                pass
4460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        except (UnicodeEncodeError, IOError):
4470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            pass
4480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Spawn a separate Python process with a different "file system
4490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # default encoding", to exercise this further.
4500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        env = dict(os.environ)
4510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        env[b'LC_CTYPE'] = b'C'
4520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        _, out = run_python('-c', 'import _io; _io.FileIO(%r)' % filename, env=env)
4530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if ('UnicodeEncodeError' not in out and not
4540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                ( ('IOError: [Errno 2] No such file or directory' in out) or
4550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                  ('IOError: [Errno 22] Invalid argument' in out) ) ):
4560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.fail('Bad output: %r' % out)
4570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def testUnclosedFDOnException(self):
4590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class MyException(Exception): pass
4600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class MyFileIO(_FileIO):
4610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def __setattr__(self, name, value):
4620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                if name == "name":
4630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    raise MyException("blocked setting name")
4640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return super(MyFileIO, self).__setattr__(name, value)
4650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        fd = os.open(__file__, os.O_RDONLY)
4660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(MyException, MyFileIO, fd)
4670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        os.close(fd)  # should not raise OSError(EBADF)
4680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef test_main():
4700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # Historically, these tests have been sloppy about removing TESTFN.
4710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # So get rid of it no matter what.
4720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    try:
4730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        run_unittest(AutoFileTests, OtherFileTests)
4740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    finally:
4750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if os.path.exists(TESTFN):
4760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            os.unlink(TESTFN)
4770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiif __name__ == '__main__':
4790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    test_main()
480