ยปCore Development>Code coverage>Lib/test/test_fileio.py

Python code coverage for Lib/test/test_fileio.py

#countcontent
1n/a# Adapted from test_file.py by Daniel Stutzbach
2n/a
3n/aimport sys
4n/aimport os
5n/aimport io
6n/aimport errno
7n/aimport unittest
8n/afrom array import array
9n/afrom weakref import proxy
10n/afrom functools import wraps
11n/a
12n/afrom test.support import (TESTFN, TESTFN_UNICODE, check_warnings, run_unittest,
13n/a make_bad_fd, cpython_only)
14n/afrom collections import UserList
15n/a
16n/aimport _io # C implementation of io
17n/aimport _pyio # Python implementation of io
18n/a
19n/a
20n/aclass AutoFileTests:
21n/a # file tests for which a test file is automatically set up
22n/a
23n/a def setUp(self):
24n/a self.f = self.FileIO(TESTFN, 'w')
25n/a
26n/a def tearDown(self):
27n/a if self.f:
28n/a self.f.close()
29n/a os.remove(TESTFN)
30n/a
31n/a def testWeakRefs(self):
32n/a # verify weak references
33n/a p = proxy(self.f)
34n/a p.write(bytes(range(10)))
35n/a self.assertEqual(self.f.tell(), p.tell())
36n/a self.f.close()
37n/a self.f = None
38n/a self.assertRaises(ReferenceError, getattr, p, 'tell')
39n/a
40n/a def testSeekTell(self):
41n/a self.f.write(bytes(range(20)))
42n/a self.assertEqual(self.f.tell(), 20)
43n/a self.f.seek(0)
44n/a self.assertEqual(self.f.tell(), 0)
45n/a self.f.seek(10)
46n/a self.assertEqual(self.f.tell(), 10)
47n/a self.f.seek(5, 1)
48n/a self.assertEqual(self.f.tell(), 15)
49n/a self.f.seek(-5, 1)
50n/a self.assertEqual(self.f.tell(), 10)
51n/a self.f.seek(-5, 2)
52n/a self.assertEqual(self.f.tell(), 15)
53n/a
54n/a def testAttributes(self):
55n/a # verify expected attributes exist
56n/a f = self.f
57n/a
58n/a self.assertEqual(f.mode, "wb")
59n/a self.assertEqual(f.closed, False)
60n/a
61n/a # verify the attributes are readonly
62n/a for attr in 'mode', 'closed':
63n/a self.assertRaises((AttributeError, TypeError),
64n/a setattr, f, attr, 'oops')
65n/a
66n/a def testBlksize(self):
67n/a # test private _blksize attribute
68n/a blksize = io.DEFAULT_BUFFER_SIZE
69n/a # try to get preferred blksize from stat.st_blksize, if available
70n/a if hasattr(os, 'fstat'):
71n/a fst = os.fstat(self.f.fileno())
72n/a blksize = getattr(fst, 'st_blksize', blksize)
73n/a self.assertEqual(self.f._blksize, blksize)
74n/a
75n/a # verify readinto
76n/a def testReadintoByteArray(self):
77n/a self.f.write(bytes([1, 2, 0, 255]))
78n/a self.f.close()
79n/a
80n/a ba = bytearray(b'abcdefgh')
81n/a with self.FileIO(TESTFN, 'r') as f:
82n/a n = f.readinto(ba)
83n/a self.assertEqual(ba, b'\x01\x02\x00\xffefgh')
84n/a self.assertEqual(n, 4)
85n/a
86n/a def _testReadintoMemoryview(self):
87n/a self.f.write(bytes([1, 2, 0, 255]))
88n/a self.f.close()
89n/a
90n/a m = memoryview(bytearray(b'abcdefgh'))
91n/a with self.FileIO(TESTFN, 'r') as f:
92n/a n = f.readinto(m)
93n/a self.assertEqual(m, b'\x01\x02\x00\xffefgh')
94n/a self.assertEqual(n, 4)
95n/a
96n/a m = memoryview(bytearray(b'abcdefgh')).cast('H', shape=[2, 2])
97n/a with self.FileIO(TESTFN, 'r') as f:
98n/a n = f.readinto(m)
99n/a self.assertEqual(bytes(m), b'\x01\x02\x00\xffefgh')
100n/a self.assertEqual(n, 4)
101n/a
102n/a def _testReadintoArray(self):
103n/a self.f.write(bytes([1, 2, 0, 255]))
104n/a self.f.close()
105n/a
106n/a a = array('B', b'abcdefgh')
107n/a with self.FileIO(TESTFN, 'r') as f:
108n/a n = f.readinto(a)
109n/a self.assertEqual(a, array('B', [1, 2, 0, 255, 101, 102, 103, 104]))
110n/a self.assertEqual(n, 4)
111n/a
112n/a a = array('b', b'abcdefgh')
113n/a with self.FileIO(TESTFN, 'r') as f:
114n/a n = f.readinto(a)
115n/a self.assertEqual(a, array('b', [1, 2, 0, -1, 101, 102, 103, 104]))
116n/a self.assertEqual(n, 4)
117n/a
118n/a a = array('I', b'abcdefgh')
119n/a with self.FileIO(TESTFN, 'r') as f:
120n/a n = f.readinto(a)
121n/a self.assertEqual(a, array('I', b'\x01\x02\x00\xffefgh'))
122n/a self.assertEqual(n, 4)
123n/a
124n/a def testWritelinesList(self):
125n/a l = [b'123', b'456']
126n/a self.f.writelines(l)
127n/a self.f.close()
128n/a self.f = self.FileIO(TESTFN, 'rb')
129n/a buf = self.f.read()
130n/a self.assertEqual(buf, b'123456')
131n/a
132n/a def testWritelinesUserList(self):
133n/a l = UserList([b'123', b'456'])
134n/a self.f.writelines(l)
135n/a self.f.close()
136n/a self.f = self.FileIO(TESTFN, 'rb')
137n/a buf = self.f.read()
138n/a self.assertEqual(buf, b'123456')
139n/a
140n/a def testWritelinesError(self):
141n/a self.assertRaises(TypeError, self.f.writelines, [1, 2, 3])
142n/a self.assertRaises(TypeError, self.f.writelines, None)
143n/a self.assertRaises(TypeError, self.f.writelines, "abc")
144n/a
145n/a def test_none_args(self):
146n/a self.f.write(b"hi\nbye\nabc")
147n/a self.f.close()
148n/a self.f = self.FileIO(TESTFN, 'r')
149n/a self.assertEqual(self.f.read(None), b"hi\nbye\nabc")
150n/a self.f.seek(0)
151n/a self.assertEqual(self.f.readline(None), b"hi\n")
152n/a self.assertEqual(self.f.readlines(None), [b"bye\n", b"abc"])
153n/a
154n/a def test_reject(self):
155n/a self.assertRaises(TypeError, self.f.write, "Hello!")
156n/a
157n/a def testRepr(self):
158n/a self.assertEqual(repr(self.f),
159n/a "<%s.FileIO name=%r mode=%r closefd=True>" %
160n/a (self.modulename, self.f.name, self.f.mode))
161n/a del self.f.name
162n/a self.assertEqual(repr(self.f),
163n/a "<%s.FileIO fd=%r mode=%r closefd=True>" %
164n/a (self.modulename, self.f.fileno(), self.f.mode))
165n/a self.f.close()
166n/a self.assertEqual(repr(self.f),
167n/a "<%s.FileIO [closed]>" % (self.modulename,))
168n/a
169n/a def testReprNoCloseFD(self):
170n/a fd = os.open(TESTFN, os.O_RDONLY)
171n/a try:
172n/a with self.FileIO(fd, 'r', closefd=False) as f:
173n/a self.assertEqual(repr(f),
174n/a "<%s.FileIO name=%r mode=%r closefd=False>" %
175n/a (self.modulename, f.name, f.mode))
176n/a finally:
177n/a os.close(fd)
178n/a
179n/a def testErrors(self):
180n/a f = self.f
181n/a self.assertFalse(f.isatty())
182n/a self.assertFalse(f.closed)
183n/a #self.assertEqual(f.name, TESTFN)
184n/a self.assertRaises(ValueError, f.read, 10) # Open for reading
185n/a f.close()
186n/a self.assertTrue(f.closed)
187n/a f = self.FileIO(TESTFN, 'r')
188n/a self.assertRaises(TypeError, f.readinto, "")
189n/a self.assertFalse(f.closed)
190n/a f.close()
191n/a self.assertTrue(f.closed)
192n/a
193n/a def testMethods(self):
194n/a methods = ['fileno', 'isatty', 'seekable', 'readable', 'writable',
195n/a 'read', 'readall', 'readline', 'readlines',
196n/a 'tell', 'truncate', 'flush']
197n/a
198n/a self.f.close()
199n/a self.assertTrue(self.f.closed)
200n/a
201n/a for methodname in methods:
202n/a method = getattr(self.f, methodname)
203n/a # should raise on closed file
204n/a self.assertRaises(ValueError, method)
205n/a
206n/a self.assertRaises(TypeError, self.f.readinto)
207n/a self.assertRaises(ValueError, self.f.readinto, bytearray(1))
208n/a self.assertRaises(TypeError, self.f.seek)
209n/a self.assertRaises(ValueError, self.f.seek, 0)
210n/a self.assertRaises(TypeError, self.f.write)
211n/a self.assertRaises(ValueError, self.f.write, b'')
212n/a self.assertRaises(TypeError, self.f.writelines)
213n/a self.assertRaises(ValueError, self.f.writelines, b'')
214n/a
215n/a def testOpendir(self):
216n/a # Issue 3703: opening a directory should fill the errno
217n/a # Windows always returns "[Errno 13]: Permission denied
218n/a # Unix uses fstat and returns "[Errno 21]: Is a directory"
219n/a try:
220n/a self.FileIO('.', 'r')
221n/a except OSError as e:
222n/a self.assertNotEqual(e.errno, 0)
223n/a self.assertEqual(e.filename, ".")
224n/a else:
225n/a self.fail("Should have raised OSError")
226n/a
227n/a @unittest.skipIf(os.name == 'nt', "test only works on a POSIX-like system")
228n/a def testOpenDirFD(self):
229n/a fd = os.open('.', os.O_RDONLY)
230n/a with self.assertRaises(OSError) as cm:
231n/a self.FileIO(fd, 'r')
232n/a os.close(fd)
233n/a self.assertEqual(cm.exception.errno, errno.EISDIR)
234n/a
235n/a #A set of functions testing that we get expected behaviour if someone has
236n/a #manually closed the internal file descriptor. First, a decorator:
237n/a def ClosedFD(func):
238n/a @wraps(func)
239n/a def wrapper(self):
240n/a #forcibly close the fd before invoking the problem function
241n/a f = self.f
242n/a os.close(f.fileno())
243n/a try:
244n/a func(self, f)
245n/a finally:
246n/a try:
247n/a self.f.close()
248n/a except OSError:
249n/a pass
250n/a return wrapper
251n/a
252n/a def ClosedFDRaises(func):
253n/a @wraps(func)
254n/a def wrapper(self):
255n/a #forcibly close the fd before invoking the problem function
256n/a f = self.f
257n/a os.close(f.fileno())
258n/a try:
259n/a func(self, f)
260n/a except OSError as e:
261n/a self.assertEqual(e.errno, errno.EBADF)
262n/a else:
263n/a self.fail("Should have raised OSError")
264n/a finally:
265n/a try:
266n/a self.f.close()
267n/a except OSError:
268n/a pass
269n/a return wrapper
270n/a
271n/a @ClosedFDRaises
272n/a def testErrnoOnClose(self, f):
273n/a f.close()
274n/a
275n/a @ClosedFDRaises
276n/a def testErrnoOnClosedWrite(self, f):
277n/a f.write(b'a')
278n/a
279n/a @ClosedFDRaises
280n/a def testErrnoOnClosedSeek(self, f):
281n/a f.seek(0)
282n/a
283n/a @ClosedFDRaises
284n/a def testErrnoOnClosedTell(self, f):
285n/a f.tell()
286n/a
287n/a @ClosedFDRaises
288n/a def testErrnoOnClosedTruncate(self, f):
289n/a f.truncate(0)
290n/a
291n/a @ClosedFD
292n/a def testErrnoOnClosedSeekable(self, f):
293n/a f.seekable()
294n/a
295n/a @ClosedFD
296n/a def testErrnoOnClosedReadable(self, f):
297n/a f.readable()
298n/a
299n/a @ClosedFD
300n/a def testErrnoOnClosedWritable(self, f):
301n/a f.writable()
302n/a
303n/a @ClosedFD
304n/a def testErrnoOnClosedFileno(self, f):
305n/a f.fileno()
306n/a
307n/a @ClosedFD
308n/a def testErrnoOnClosedIsatty(self, f):
309n/a self.assertEqual(f.isatty(), False)
310n/a
311n/a def ReopenForRead(self):
312n/a try:
313n/a self.f.close()
314n/a except OSError:
315n/a pass
316n/a self.f = self.FileIO(TESTFN, 'r')
317n/a os.close(self.f.fileno())
318n/a return self.f
319n/a
320n/a @ClosedFDRaises
321n/a def testErrnoOnClosedRead(self, f):
322n/a f = self.ReopenForRead()
323n/a f.read(1)
324n/a
325n/a @ClosedFDRaises
326n/a def testErrnoOnClosedReadall(self, f):
327n/a f = self.ReopenForRead()
328n/a f.readall()
329n/a
330n/a @ClosedFDRaises
331n/a def testErrnoOnClosedReadinto(self, f):
332n/a f = self.ReopenForRead()
333n/a a = array('b', b'x'*10)
334n/a f.readinto(a)
335n/a
336n/aclass CAutoFileTests(AutoFileTests, unittest.TestCase):
337n/a FileIO = _io.FileIO
338n/a modulename = '_io'
339n/a
340n/aclass PyAutoFileTests(AutoFileTests, unittest.TestCase):
341n/a FileIO = _pyio.FileIO
342n/a modulename = '_pyio'
343n/a
344n/a
345n/aclass OtherFileTests:
346n/a
347n/a def testAbles(self):
348n/a try:
349n/a f = self.FileIO(TESTFN, "w")
350n/a self.assertEqual(f.readable(), False)
351n/a self.assertEqual(f.writable(), True)
352n/a self.assertEqual(f.seekable(), True)
353n/a f.close()
354n/a
355n/a f = self.FileIO(TESTFN, "r")
356n/a self.assertEqual(f.readable(), True)
357n/a self.assertEqual(f.writable(), False)
358n/a self.assertEqual(f.seekable(), True)
359n/a f.close()
360n/a
361n/a f = self.FileIO(TESTFN, "a+")
362n/a self.assertEqual(f.readable(), True)
363n/a self.assertEqual(f.writable(), True)
364n/a self.assertEqual(f.seekable(), True)
365n/a self.assertEqual(f.isatty(), False)
366n/a f.close()
367n/a
368n/a if sys.platform != "win32":
369n/a try:
370n/a f = self.FileIO("/dev/tty", "a")
371n/a except OSError:
372n/a # When run in a cron job there just aren't any
373n/a # ttys, so skip the test. This also handles other
374n/a # OS'es that don't support /dev/tty.
375n/a pass
376n/a else:
377n/a self.assertEqual(f.readable(), False)
378n/a self.assertEqual(f.writable(), True)
379n/a if sys.platform != "darwin" and \
380n/a 'bsd' not in sys.platform and \
381n/a not sys.platform.startswith(('sunos', 'aix')):
382n/a # Somehow /dev/tty appears seekable on some BSDs
383n/a self.assertEqual(f.seekable(), False)
384n/a self.assertEqual(f.isatty(), True)
385n/a f.close()
386n/a finally:
387n/a os.unlink(TESTFN)
388n/a
389n/a def testInvalidModeStrings(self):
390n/a # check invalid mode strings
391n/a for mode in ("", "aU", "wU+", "rw", "rt"):
392n/a try:
393n/a f = self.FileIO(TESTFN, mode)
394n/a except ValueError:
395n/a pass
396n/a else:
397n/a f.close()
398n/a self.fail('%r is an invalid file mode' % mode)
399n/a
400n/a def testModeStrings(self):
401n/a # test that the mode attribute is correct for various mode strings
402n/a # given as init args
403n/a try:
404n/a for modes in [('w', 'wb'), ('wb', 'wb'), ('wb+', 'rb+'),
405n/a ('w+b', 'rb+'), ('a', 'ab'), ('ab', 'ab'),
406n/a ('ab+', 'ab+'), ('a+b', 'ab+'), ('r', 'rb'),
407n/a ('rb', 'rb'), ('rb+', 'rb+'), ('r+b', 'rb+')]:
408n/a # read modes are last so that TESTFN will exist first
409n/a with self.FileIO(TESTFN, modes[0]) as f:
410n/a self.assertEqual(f.mode, modes[1])
411n/a finally:
412n/a if os.path.exists(TESTFN):
413n/a os.unlink(TESTFN)
414n/a
415n/a def testUnicodeOpen(self):
416n/a # verify repr works for unicode too
417n/a f = self.FileIO(str(TESTFN), "w")
418n/a f.close()
419n/a os.unlink(TESTFN)
420n/a
421n/a def testBytesOpen(self):
422n/a # Opening a bytes filename
423n/a try:
424n/a fn = TESTFN.encode("ascii")
425n/a except UnicodeEncodeError:
426n/a self.skipTest('could not encode %r to ascii' % TESTFN)
427n/a f = self.FileIO(fn, "w")
428n/a try:
429n/a f.write(b"abc")
430n/a f.close()
431n/a with open(TESTFN, "rb") as f:
432n/a self.assertEqual(f.read(), b"abc")
433n/a finally:
434n/a os.unlink(TESTFN)
435n/a
436n/a @unittest.skipIf(sys.getfilesystemencoding() != 'utf-8',
437n/a "test only works for utf-8 filesystems")
438n/a def testUtf8BytesOpen(self):
439n/a # Opening a UTF-8 bytes filename
440n/a try:
441n/a fn = TESTFN_UNICODE.encode("utf-8")
442n/a except UnicodeEncodeError:
443n/a self.skipTest('could not encode %r to utf-8' % TESTFN_UNICODE)
444n/a f = self.FileIO(fn, "w")
445n/a try:
446n/a f.write(b"abc")
447n/a f.close()
448n/a with open(TESTFN_UNICODE, "rb") as f:
449n/a self.assertEqual(f.read(), b"abc")
450n/a finally:
451n/a os.unlink(TESTFN_UNICODE)
452n/a
453n/a def testConstructorHandlesNULChars(self):
454n/a fn_with_NUL = 'foo\0bar'
455n/a self.assertRaises(ValueError, self.FileIO, fn_with_NUL, 'w')
456n/a self.assertRaises(ValueError, self.FileIO, bytes(fn_with_NUL, 'ascii'), 'w')
457n/a
458n/a def testInvalidFd(self):
459n/a self.assertRaises(ValueError, self.FileIO, -10)
460n/a self.assertRaises(OSError, self.FileIO, make_bad_fd())
461n/a if sys.platform == 'win32':
462n/a import msvcrt
463n/a self.assertRaises(OSError, msvcrt.get_osfhandle, make_bad_fd())
464n/a
465n/a def testBadModeArgument(self):
466n/a # verify that we get a sensible error message for bad mode argument
467n/a bad_mode = "qwerty"
468n/a try:
469n/a f = self.FileIO(TESTFN, bad_mode)
470n/a except ValueError as msg:
471n/a if msg.args[0] != 0:
472n/a s = str(msg)
473n/a if TESTFN in s or bad_mode not in s:
474n/a self.fail("bad error message for invalid mode: %s" % s)
475n/a # if msg.args[0] == 0, we're probably on Windows where there may be
476n/a # no obvious way to discover why open() failed.
477n/a else:
478n/a f.close()
479n/a self.fail("no error for invalid mode: %s" % bad_mode)
480n/a
481n/a def testTruncate(self):
482n/a f = self.FileIO(TESTFN, 'w')
483n/a f.write(bytes(bytearray(range(10))))
484n/a self.assertEqual(f.tell(), 10)
485n/a f.truncate(5)
486n/a self.assertEqual(f.tell(), 10)
487n/a self.assertEqual(f.seek(0, io.SEEK_END), 5)
488n/a f.truncate(15)
489n/a self.assertEqual(f.tell(), 5)
490n/a self.assertEqual(f.seek(0, io.SEEK_END), 15)
491n/a f.close()
492n/a
493n/a def testTruncateOnWindows(self):
494n/a def bug801631():
495n/a # SF bug <http://www.python.org/sf/801631>
496n/a # "file.truncate fault on windows"
497n/a f = self.FileIO(TESTFN, 'w')
498n/a f.write(bytes(range(11)))
499n/a f.close()
500n/a
501n/a f = self.FileIO(TESTFN,'r+')
502n/a data = f.read(5)
503n/a if data != bytes(range(5)):
504n/a self.fail("Read on file opened for update failed %r" % data)
505n/a if f.tell() != 5:
506n/a self.fail("File pos after read wrong %d" % f.tell())
507n/a
508n/a f.truncate()
509n/a if f.tell() != 5:
510n/a self.fail("File pos after ftruncate wrong %d" % f.tell())
511n/a
512n/a f.close()
513n/a size = os.path.getsize(TESTFN)
514n/a if size != 5:
515n/a self.fail("File size after ftruncate wrong %d" % size)
516n/a
517n/a try:
518n/a bug801631()
519n/a finally:
520n/a os.unlink(TESTFN)
521n/a
522n/a def testAppend(self):
523n/a try:
524n/a f = open(TESTFN, 'wb')
525n/a f.write(b'spam')
526n/a f.close()
527n/a f = open(TESTFN, 'ab')
528n/a f.write(b'eggs')
529n/a f.close()
530n/a f = open(TESTFN, 'rb')
531n/a d = f.read()
532n/a f.close()
533n/a self.assertEqual(d, b'spameggs')
534n/a finally:
535n/a try:
536n/a os.unlink(TESTFN)
537n/a except:
538n/a pass
539n/a
540n/a def testInvalidInit(self):
541n/a self.assertRaises(TypeError, self.FileIO, "1", 0, 0)
542n/a
543n/a def testWarnings(self):
544n/a with check_warnings(quiet=True) as w:
545n/a self.assertEqual(w.warnings, [])
546n/a self.assertRaises(TypeError, self.FileIO, [])
547n/a self.assertEqual(w.warnings, [])
548n/a self.assertRaises(ValueError, self.FileIO, "/some/invalid/name", "rt")
549n/a self.assertEqual(w.warnings, [])
550n/a
551n/a def testUnclosedFDOnException(self):
552n/a class MyException(Exception): pass
553n/a class MyFileIO(self.FileIO):
554n/a def __setattr__(self, name, value):
555n/a if name == "name":
556n/a raise MyException("blocked setting name")
557n/a return super(MyFileIO, self).__setattr__(name, value)
558n/a fd = os.open(__file__, os.O_RDONLY)
559n/a self.assertRaises(MyException, MyFileIO, fd)
560n/a os.close(fd) # should not raise OSError(EBADF)
561n/a
562n/aclass COtherFileTests(OtherFileTests, unittest.TestCase):
563n/a FileIO = _io.FileIO
564n/a modulename = '_io'
565n/a
566n/a @cpython_only
567n/a def testInvalidFd_overflow(self):
568n/a # Issue 15989
569n/a import _testcapi
570n/a self.assertRaises(TypeError, self.FileIO, _testcapi.INT_MAX + 1)
571n/a self.assertRaises(TypeError, self.FileIO, _testcapi.INT_MIN - 1)
572n/a
573n/aclass PyOtherFileTests(OtherFileTests, unittest.TestCase):
574n/a FileIO = _pyio.FileIO
575n/a modulename = '_pyio'
576n/a
577n/a
578n/adef test_main():
579n/a # Historically, these tests have been sloppy about removing TESTFN.
580n/a # So get rid of it no matter what.
581n/a try:
582n/a run_unittest(CAutoFileTests, PyAutoFileTests,
583n/a COtherFileTests, PyOtherFileTests)
584n/a finally:
585n/a if os.path.exists(TESTFN):
586n/a os.unlink(TESTFN)
587n/a
588n/aif __name__ == '__main__':
589n/a test_main()