1ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# Adapted from test_file.py by Daniel Stutzbach
2ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
3ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom __future__ import unicode_literals
4ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
5ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport sys
6ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport os
7ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport errno
8ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport unittest
9ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom array import array
10ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom weakref import proxy
11ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom functools import wraps
12ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom UserList import UserList
13ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport _testcapi
14ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
15ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom test.test_support import TESTFN, check_warnings, run_unittest, make_bad_fd
16ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom test.test_support import py3k_bytes as bytes
17ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom test.script_helper import run_python
18ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
19ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom _io import FileIO as _FileIO
20ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
21ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass AutoFileTests(unittest.TestCase):
22ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    # file tests for which a test file is automatically set up
23ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
24ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def setUp(self):
25ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.f = _FileIO(TESTFN, 'w')
26ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
27ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def tearDown(self):
28ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if self.f:
29ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.f.close()
30ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        os.remove(TESTFN)
31ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
32ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testWeakRefs(self):
33ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # verify weak references
34ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        p = proxy(self.f)
35ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        p.write(bytes(range(10)))
36ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(self.f.tell(), p.tell())
37ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.f.close()
38ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.f = None
39ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertRaises(ReferenceError, getattr, p, 'tell')
40ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
41ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testSeekTell(self):
42ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.f.write(bytes(range(20)))
43ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(self.f.tell(), 20)
44ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.f.seek(0)
45ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(self.f.tell(), 0)
46ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.f.seek(10)
47ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(self.f.tell(), 10)
48ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.f.seek(5, 1)
49ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(self.f.tell(), 15)
50ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.f.seek(-5, 1)
51ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(self.f.tell(), 10)
52ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.f.seek(-5, 2)
53ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(self.f.tell(), 15)
54ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
55ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testAttributes(self):
56ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # verify expected attributes exist
57ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f = self.f
58ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
59ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(f.mode, "wb")
60ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(f.closed, False)
61ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
62ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # verify the attributes are readonly
63ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for attr in 'mode', 'closed':
64ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertRaises((AttributeError, TypeError),
65ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                              setattr, f, attr, 'oops')
66ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
67ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testReadinto(self):
68ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # verify readinto
69ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.f.write(b"\x01\x02")
70ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.f.close()
71ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        a = array(b'b', b'x'*10)
72ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.f = _FileIO(TESTFN, 'r')
73ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        n = self.f.readinto(a)
74ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(array(b'b', [1, 2]), a[:n])
75ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
76ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testWritelinesList(self):
77ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        l = [b'123', b'456']
78ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.f.writelines(l)
79ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.f.close()
80ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.f = _FileIO(TESTFN, 'rb')
81ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        buf = self.f.read()
82ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(buf, b'123456')
83ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
84ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testWritelinesUserList(self):
85ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        l = UserList([b'123', b'456'])
86ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.f.writelines(l)
87ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.f.close()
88ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.f = _FileIO(TESTFN, 'rb')
89ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        buf = self.f.read()
90ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(buf, b'123456')
91ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
92ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testWritelinesError(self):
93ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertRaises(TypeError, self.f.writelines, [1, 2, 3])
94ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertRaises(TypeError, self.f.writelines, None)
95ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
96ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_none_args(self):
97ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.f.write(b"hi\nbye\nabc")
98ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.f.close()
99ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.f = _FileIO(TESTFN, 'r')
100ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(self.f.read(None), b"hi\nbye\nabc")
101ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.f.seek(0)
102ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(self.f.readline(None), b"hi\n")
103ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(self.f.readlines(None), [b"bye\n", b"abc"])
104ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
105ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testRepr(self):
106ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(repr(self.f), "<_io.FileIO name=%r mode='%s'>"
107ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                                       % (self.f.name, self.f.mode))
108ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        del self.f.name
109ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(repr(self.f), "<_io.FileIO fd=%r mode='%s'>"
110ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                                       % (self.f.fileno(), self.f.mode))
111ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.f.close()
112ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(repr(self.f), "<_io.FileIO [closed]>")
113ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
114ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testErrors(self):
115ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f = self.f
116ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertTrue(not f.isatty())
117ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertTrue(not f.closed)
118ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        #self.assertEqual(f.name, TESTFN)
119ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertRaises(ValueError, f.read, 10) # Open for reading
120ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f.close()
121ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertTrue(f.closed)
122ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f = _FileIO(TESTFN, 'r')
123ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertRaises(TypeError, f.readinto, "")
124ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertTrue(not f.closed)
125ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f.close()
126ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertTrue(f.closed)
127ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
128ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testMethods(self):
129ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        methods = ['fileno', 'isatty', 'read', 'readinto',
130ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                   'seek', 'tell', 'truncate', 'write', 'seekable',
131ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                   'readable', 'writable']
132ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if sys.platform.startswith('atheos'):
133ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            methods.remove('truncate')
134ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
135ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.f.close()
136ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertTrue(self.f.closed)
137ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
138ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for methodname in methods:
139ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            method = getattr(self.f, methodname)
140ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            # should raise on closed file
141ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertRaises(ValueError, method)
142ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
143ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testOpendir(self):
144ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Issue 3703: opening a directory should fill the errno
145ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Windows always returns "[Errno 13]: Permission denied
146ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Unix calls dircheck() and returns "[Errno 21]: Is a directory"
147ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        try:
148ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            _FileIO('.', 'r')
149ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        except IOError as e:
150ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertNotEqual(e.errno, 0)
151ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertEqual(e.filename, ".")
152ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        else:
153ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.fail("Should have raised IOError")
154ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
155ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    @unittest.skipIf(os.name == 'nt', "test only works on a POSIX-like system")
156ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testOpenDirFD(self):
157ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        fd = os.open('.', os.O_RDONLY)
158ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        with self.assertRaises(IOError) as cm:
159ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            _FileIO(fd, 'r')
160ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        os.close(fd)
161ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(cm.exception.errno, errno.EISDIR)
162ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
163ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    #A set of functions testing that we get expected behaviour if someone has
164ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    #manually closed the internal file descriptor.  First, a decorator:
165ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def ClosedFD(func):
166ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        @wraps(func)
167ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        def wrapper(self):
168ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            #forcibly close the fd before invoking the problem function
169ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            f = self.f
170ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            os.close(f.fileno())
171ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            try:
172ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                func(self, f)
173ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            finally:
174ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                try:
175ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    self.f.close()
176ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                except IOError:
177ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    pass
178ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return wrapper
179ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
180ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def ClosedFDRaises(func):
181ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        @wraps(func)
182ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        def wrapper(self):
183ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            #forcibly close the fd before invoking the problem function
184ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            f = self.f
185ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            os.close(f.fileno())
186ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            try:
187ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                func(self, f)
188ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            except IOError as e:
189ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                self.assertEqual(e.errno, errno.EBADF)
190ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            else:
191ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                self.fail("Should have raised IOError")
192ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            finally:
193ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                try:
194ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    self.f.close()
195ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                except IOError:
196ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    pass
197ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return wrapper
198ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
199ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    @ClosedFDRaises
200ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testErrnoOnClose(self, f):
201ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f.close()
202ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
203ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    @ClosedFDRaises
204ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testErrnoOnClosedWrite(self, f):
205ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f.write('a')
206ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
207ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    @ClosedFDRaises
208ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testErrnoOnClosedSeek(self, f):
209ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f.seek(0)
210ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
211ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    @ClosedFDRaises
212ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testErrnoOnClosedTell(self, f):
213ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f.tell()
214ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
215ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    @ClosedFDRaises
216ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testErrnoOnClosedTruncate(self, f):
217ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f.truncate(0)
218ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
219ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    @ClosedFD
220ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testErrnoOnClosedSeekable(self, f):
221ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f.seekable()
222ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
223ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    @ClosedFD
224ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testErrnoOnClosedReadable(self, f):
225ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f.readable()
226ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
227ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    @ClosedFD
228ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testErrnoOnClosedWritable(self, f):
229ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f.writable()
230ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
231ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    @ClosedFD
232ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testErrnoOnClosedFileno(self, f):
233ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f.fileno()
234ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
235ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    @ClosedFD
236ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testErrnoOnClosedIsatty(self, f):
237ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(f.isatty(), False)
238ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
239ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def ReopenForRead(self):
240ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        try:
241ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.f.close()
242ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        except IOError:
243ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            pass
244ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.f = _FileIO(TESTFN, 'r')
245ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        os.close(self.f.fileno())
246ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return self.f
247ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
248ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    @ClosedFDRaises
249ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testErrnoOnClosedRead(self, f):
250ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f = self.ReopenForRead()
251ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f.read(1)
252ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
253ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    @ClosedFDRaises
254ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testErrnoOnClosedReadall(self, f):
255ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f = self.ReopenForRead()
256ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f.readall()
257ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
258ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    @ClosedFDRaises
259ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testErrnoOnClosedReadinto(self, f):
260ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f = self.ReopenForRead()
261ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        a = array(b'b', b'x'*10)
262ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f.readinto(a)
263ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
264ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass OtherFileTests(unittest.TestCase):
265ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
266ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testAbles(self):
267ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        try:
268ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            f = _FileIO(TESTFN, "w")
269ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertEqual(f.readable(), False)
270ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertEqual(f.writable(), True)
271ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertEqual(f.seekable(), True)
272ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            f.close()
273ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
274ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            f = _FileIO(TESTFN, "r")
275ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertEqual(f.readable(), True)
276ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertEqual(f.writable(), False)
277ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertEqual(f.seekable(), True)
278ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            f.close()
279ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
280ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            f = _FileIO(TESTFN, "a+")
281ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertEqual(f.readable(), True)
282ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertEqual(f.writable(), True)
283ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertEqual(f.seekable(), True)
284ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertEqual(f.isatty(), False)
285ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            f.close()
286ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
287ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if sys.platform != "win32":
288ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                try:
289ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    f = _FileIO("/dev/tty", "a")
290ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                except EnvironmentError:
291ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    # When run in a cron job there just aren't any
292ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    # ttys, so skip the test.  This also handles other
293ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    # OS'es that don't support /dev/tty.
294ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    pass
295ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                else:
296ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    self.assertEqual(f.readable(), False)
297ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    self.assertEqual(f.writable(), True)
298ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    if sys.platform != "darwin" and \
299ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                       'bsd' not in sys.platform and \
300ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                       not sys.platform.startswith('sunos'):
301ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                        # Somehow /dev/tty appears seekable on some BSDs
302ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                        self.assertEqual(f.seekable(), False)
303ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    self.assertEqual(f.isatty(), True)
304ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    f.close()
305ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        finally:
306ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            os.unlink(TESTFN)
307ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
308ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testModeStrings(self):
309ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # check invalid mode strings
310ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for mode in ("", "aU", "wU+", "rw", "rt"):
311ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            try:
312ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                f = _FileIO(TESTFN, mode)
313ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            except ValueError:
314ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                pass
315ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            else:
316ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                f.close()
317ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                self.fail('%r is an invalid file mode' % mode)
318ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
319ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testUnicodeOpen(self):
320ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # verify repr works for unicode too
321ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f = _FileIO(str(TESTFN), "w")
322ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f.close()
323ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        os.unlink(TESTFN)
324ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
325ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testBytesOpen(self):
326ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Opening a bytes filename
327ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        try:
328ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            fn = TESTFN.encode("ascii")
329ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        except UnicodeEncodeError:
330ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            # Skip test
331ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            return
332ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f = _FileIO(fn, "w")
333ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        try:
334ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            f.write(b"abc")
335ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            f.close()
336ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            with open(TESTFN, "rb") as f:
337ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                self.assertEqual(f.read(), b"abc")
338ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        finally:
339ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            os.unlink(TESTFN)
340ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
341ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testInvalidFd(self):
342ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertRaises(ValueError, _FileIO, -10)
343ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertRaises(OSError, _FileIO, make_bad_fd())
344ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if sys.platform == 'win32':
345ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            import msvcrt
346ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertRaises(IOError, msvcrt.get_osfhandle, make_bad_fd())
347ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Issue 15989
348ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertRaises(TypeError, _FileIO, _testcapi.INT_MAX + 1)
349ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertRaises(TypeError, _FileIO, _testcapi.INT_MIN - 1)
350ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
351ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testBadModeArgument(self):
352ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # verify that we get a sensible error message for bad mode argument
353ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        bad_mode = "qwerty"
354ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        try:
355ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            f = _FileIO(TESTFN, bad_mode)
356ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        except ValueError as msg:
357ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if msg.args[0] != 0:
358ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                s = str(msg)
359ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                if TESTFN in s or bad_mode not in s:
360ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    self.fail("bad error message for invalid mode: %s" % s)
361ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            # if msg.args[0] == 0, we're probably on Windows where there may be
362ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            # no obvious way to discover why open() failed.
363ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        else:
364ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            f.close()
365ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.fail("no error for invalid mode: %s" % bad_mode)
366ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
367ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testTruncate(self):
368ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f = _FileIO(TESTFN, 'w')
369ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f.write(bytes(bytearray(range(10))))
370ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(f.tell(), 10)
371ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f.truncate(5)
372ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(f.tell(), 10)
373ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(f.seek(0, os.SEEK_END), 5)
374ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f.truncate(15)
375ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(f.tell(), 5)
376ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(f.seek(0, os.SEEK_END), 15)
377ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f.close()
378ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
379ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testTruncateOnWindows(self):
380ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        def bug801631():
381ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            # SF bug <http://www.python.org/sf/801631>
382ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            # "file.truncate fault on windows"
383ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            f = _FileIO(TESTFN, 'w')
384ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            f.write(bytes(range(11)))
385ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            f.close()
386ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
387ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            f = _FileIO(TESTFN,'r+')
388ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            data = f.read(5)
389ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if data != bytes(range(5)):
390ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                self.fail("Read on file opened for update failed %r" % data)
391ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if f.tell() != 5:
392ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                self.fail("File pos after read wrong %d" % f.tell())
393ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
394ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            f.truncate()
395ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if f.tell() != 5:
396ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                self.fail("File pos after ftruncate wrong %d" % f.tell())
397ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
398ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            f.close()
399ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            size = os.path.getsize(TESTFN)
400ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if size != 5:
401ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                self.fail("File size after ftruncate wrong %d" % size)
402ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
403ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        try:
404ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            bug801631()
405ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        finally:
406ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            os.unlink(TESTFN)
407ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
408ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testAppend(self):
409ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        try:
410ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            f = open(TESTFN, 'wb')
411ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            f.write(b'spam')
412ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            f.close()
413ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            f = open(TESTFN, 'ab')
414ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            f.write(b'eggs')
415ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            f.close()
416ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            f = open(TESTFN, 'rb')
417ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            d = f.read()
418ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            f.close()
419ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertEqual(d, b'spameggs')
420ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        finally:
421ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            try:
422ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                os.unlink(TESTFN)
423ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            except:
424ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                pass
425ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
426ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testInvalidInit(self):
427ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertRaises(TypeError, _FileIO, "1", 0, 0)
428ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
429ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testWarnings(self):
430ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        with check_warnings(quiet=True) as w:
431ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertEqual(w.warnings, [])
432ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertRaises(TypeError, _FileIO, [])
433ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertEqual(w.warnings, [])
434ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertRaises(ValueError, _FileIO, "/some/invalid/name", "rt")
435ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertEqual(w.warnings, [])
436ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
437ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_surrogates(self):
438ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Issue #8438: try to open a filename containing surrogates.
439ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # It should either fail because the file doesn't exist or the filename
440ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # can't be represented using the filesystem encoding, but not because
441ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # of a LookupError for the error handler "surrogateescape".
442ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        filename = u'\udc80.txt'
443ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        try:
444ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            with _FileIO(filename):
445ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                pass
446ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        except (UnicodeEncodeError, IOError):
447ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            pass
448ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Spawn a separate Python process with a different "file system
449ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # default encoding", to exercise this further.
450ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        env = dict(os.environ)
451ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        env[b'LC_CTYPE'] = b'C'
452ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        _, out = run_python('-c', 'import _io; _io.FileIO(%r)' % filename, env=env)
453ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if ('UnicodeEncodeError' not in out and not
454ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                ( ('IOError: [Errno 2] No such file or directory' in out) or
455ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                  ('IOError: [Errno 22] Invalid argument' in out) ) ):
456ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.fail('Bad output: %r' % out)
457ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
458ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def testUnclosedFDOnException(self):
459ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        class MyException(Exception): pass
460ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        class MyFileIO(_FileIO):
461ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            def __setattr__(self, name, value):
462ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                if name == "name":
463ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    raise MyException("blocked setting name")
464ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                return super(MyFileIO, self).__setattr__(name, value)
465ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        fd = os.open(__file__, os.O_RDONLY)
466ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertRaises(MyException, MyFileIO, fd)
467ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        os.close(fd)  # should not raise OSError(EBADF)
468ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
469ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef test_main():
470ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    # Historically, these tests have been sloppy about removing TESTFN.
471ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    # So get rid of it no matter what.
472ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    try:
473ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        run_unittest(AutoFileTests, OtherFileTests)
474ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    finally:
475ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if os.path.exists(TESTFN):
476ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            os.unlink(TESTFN)
477ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
478ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehif __name__ == '__main__':
479ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    test_main()
480