+++ /dev/null
-# NOTE: this file tests the new `io` library backported from Python 3.x.\r
-# Similar tests for the builtin file object can be found in test_file2k.py.\r
-\r
-from __future__ import print_function\r
-\r
-import sys\r
-import os\r
-import unittest\r
-from array import array\r
-from weakref import proxy\r
-\r
-import io\r
-import _pyio as pyio\r
-\r
-from test.test_support import TESTFN, run_unittest\r
-from UserList import UserList\r
-\r
-class AutoFileTests(unittest.TestCase):\r
- # file tests for which a test file is automatically set up\r
-\r
- def setUp(self):\r
- self.f = self.open(TESTFN, 'wb')\r
-\r
- def tearDown(self):\r
- if self.f:\r
- self.f.close()\r
- os.remove(TESTFN)\r
-\r
- def testWeakRefs(self):\r
- # verify weak references\r
- p = proxy(self.f)\r
- p.write(b'teststring')\r
- self.assertEqual(self.f.tell(), p.tell())\r
- self.f.close()\r
- self.f = None\r
- self.assertRaises(ReferenceError, getattr, p, 'tell')\r
-\r
- def testAttributes(self):\r
- # verify expected attributes exist\r
- f = self.f\r
- f.name # merely shouldn't blow up\r
- f.mode # ditto\r
- f.closed # ditto\r
-\r
- def testReadinto(self):\r
- # verify readinto\r
- self.f.write(b'12')\r
- self.f.close()\r
- a = array('b', b'x'*10)\r
- self.f = self.open(TESTFN, 'rb')\r
- n = self.f.readinto(a)\r
- self.assertEqual(b'12', a.tostring()[:n])\r
-\r
- def testReadinto_text(self):\r
- # verify readinto refuses text files\r
- a = array('b', b'x'*10)\r
- self.f.close()\r
- self.f = self.open(TESTFN, 'r')\r
- if hasattr(self.f, "readinto"):\r
- self.assertRaises(TypeError, self.f.readinto, a)\r
-\r
- def testWritelinesUserList(self):\r
- # verify writelines with instance sequence\r
- l = UserList([b'1', b'2'])\r
- self.f.writelines(l)\r
- self.f.close()\r
- self.f = self.open(TESTFN, 'rb')\r
- buf = self.f.read()\r
- self.assertEqual(buf, b'12')\r
-\r
- def testWritelinesIntegers(self):\r
- # verify writelines with integers\r
- self.assertRaises(TypeError, self.f.writelines, [1, 2, 3])\r
-\r
- def testWritelinesIntegersUserList(self):\r
- # verify writelines with integers in UserList\r
- l = UserList([1,2,3])\r
- self.assertRaises(TypeError, self.f.writelines, l)\r
-\r
- def testWritelinesNonString(self):\r
- # verify writelines with non-string object\r
- class NonString:\r
- pass\r
-\r
- self.assertRaises(TypeError, self.f.writelines,\r
- [NonString(), NonString()])\r
-\r
- def testErrors(self):\r
- f = self.f\r
- self.assertEqual(f.name, TESTFN)\r
- self.assertTrue(not f.isatty())\r
- self.assertTrue(not f.closed)\r
-\r
- if hasattr(f, "readinto"):\r
- self.assertRaises((IOError, TypeError), f.readinto, "")\r
- f.close()\r
- self.assertTrue(f.closed)\r
-\r
- def testMethods(self):\r
- methods = [('fileno', ()),\r
- ('flush', ()),\r
- ('isatty', ()),\r
- ('next', ()),\r
- ('read', ()),\r
- ('write', (b"",)),\r
- ('readline', ()),\r
- ('readlines', ()),\r
- ('seek', (0,)),\r
- ('tell', ()),\r
- ('write', (b"",)),\r
- ('writelines', ([],)),\r
- ('__iter__', ()),\r
- ]\r
- if not sys.platform.startswith('atheos'):\r
- methods.append(('truncate', ()))\r
-\r
- # __exit__ should close the file\r
- self.f.__exit__(None, None, None)\r
- self.assertTrue(self.f.closed)\r
-\r
- for methodname, args in methods:\r
- method = getattr(self.f, methodname)\r
- # should raise on closed file\r
- self.assertRaises(ValueError, method, *args)\r
-\r
- # file is closed, __exit__ shouldn't do anything\r
- self.assertEqual(self.f.__exit__(None, None, None), None)\r
- # it must also return None if an exception was given\r
- try:\r
- 1 // 0\r
- except:\r
- self.assertEqual(self.f.__exit__(*sys.exc_info()), None)\r
-\r
- def testReadWhenWriting(self):\r
- self.assertRaises(IOError, self.f.read)\r
-\r
-class CAutoFileTests(AutoFileTests):\r
- open = io.open\r
-\r
-class PyAutoFileTests(AutoFileTests):\r
- open = staticmethod(pyio.open)\r
-\r
-\r
-class OtherFileTests(unittest.TestCase):\r
-\r
- def testModeStrings(self):\r
- # check invalid mode strings\r
- for mode in ("", "aU", "wU+"):\r
- try:\r
- f = self.open(TESTFN, mode)\r
- except ValueError:\r
- pass\r
- else:\r
- f.close()\r
- self.fail('%r is an invalid file mode' % mode)\r
-\r
- def testStdin(self):\r
- # This causes the interpreter to exit on OSF1 v5.1.\r
- if sys.platform != 'osf1V5':\r
- self.assertRaises((IOError, ValueError), sys.stdin.seek, -1)\r
- else:\r
- print((\r
- ' Skipping sys.stdin.seek(-1), it may crash the interpreter.'\r
- ' Test manually.'), file=sys.__stdout__)\r
- self.assertRaises((IOError, ValueError), sys.stdin.truncate)\r
-\r
- def testBadModeArgument(self):\r
- # verify that we get a sensible error message for bad mode argument\r
- bad_mode = "qwerty"\r
- try:\r
- f = self.open(TESTFN, bad_mode)\r
- except ValueError as msg:\r
- if msg.args[0] != 0:\r
- s = str(msg)\r
- if TESTFN in s or bad_mode not in s:\r
- self.fail("bad error message for invalid mode: %s" % s)\r
- # if msg.args[0] == 0, we're probably on Windows where there may be\r
- # no obvious way to discover why open() failed.\r
- else:\r
- f.close()\r
- self.fail("no error for invalid mode: %s" % bad_mode)\r
-\r
- def testSetBufferSize(self):\r
- # make sure that explicitly setting the buffer size doesn't cause\r
- # misbehaviour especially with repeated close() calls\r
- for s in (-1, 0, 1, 512):\r
- try:\r
- f = self.open(TESTFN, 'wb', s)\r
- f.write(str(s).encode("ascii"))\r
- f.close()\r
- f.close()\r
- f = self.open(TESTFN, 'rb', s)\r
- d = int(f.read().decode("ascii"))\r
- f.close()\r
- f.close()\r
- except IOError as msg:\r
- self.fail('error setting buffer size %d: %s' % (s, str(msg)))\r
- self.assertEqual(d, s)\r
-\r
- def testTruncateOnWindows(self):\r
- # SF bug <http://www.python.org/sf/801631>\r
- # "file.truncate fault on windows"\r
-\r
- os.unlink(TESTFN)\r
- f = self.open(TESTFN, 'wb')\r
-\r
- try:\r
- f.write(b'12345678901') # 11 bytes\r
- f.close()\r
-\r
- f = self.open(TESTFN,'rb+')\r
- data = f.read(5)\r
- if data != b'12345':\r
- self.fail("Read on file opened for update failed %r" % data)\r
- if f.tell() != 5:\r
- self.fail("File pos after read wrong %d" % f.tell())\r
-\r
- f.truncate()\r
- if f.tell() != 5:\r
- self.fail("File pos after ftruncate wrong %d" % f.tell())\r
-\r
- f.close()\r
- size = os.path.getsize(TESTFN)\r
- if size != 5:\r
- self.fail("File size after ftruncate wrong %d" % size)\r
- finally:\r
- f.close()\r
- os.unlink(TESTFN)\r
-\r
- def testIteration(self):\r
- # Test the complex interaction when mixing file-iteration and the\r
- # various read* methods.\r
- dataoffset = 16384\r
- filler = b"ham\n"\r
- assert not dataoffset % len(filler), \\r
- "dataoffset must be multiple of len(filler)"\r
- nchunks = dataoffset // len(filler)\r
- testlines = [\r
- b"spam, spam and eggs\n",\r
- b"eggs, spam, ham and spam\n",\r
- b"saussages, spam, spam and eggs\n",\r
- b"spam, ham, spam and eggs\n",\r
- b"spam, spam, spam, spam, spam, ham, spam\n",\r
- b"wonderful spaaaaaam.\n"\r
- ]\r
- methods = [("readline", ()), ("read", ()), ("readlines", ()),\r
- ("readinto", (array("b", b" "*100),))]\r
-\r
- try:\r
- # Prepare the testfile\r
- bag = self.open(TESTFN, "wb")\r
- bag.write(filler * nchunks)\r
- bag.writelines(testlines)\r
- bag.close()\r
- # Test for appropriate errors mixing read* and iteration\r
- for methodname, args in methods:\r
- f = self.open(TESTFN, 'rb')\r
- if next(f) != filler:\r
- self.fail, "Broken testfile"\r
- meth = getattr(f, methodname)\r
- meth(*args) # This simply shouldn't fail\r
- f.close()\r
-\r
- # Test to see if harmless (by accident) mixing of read* and\r
- # iteration still works. This depends on the size of the internal\r
- # iteration buffer (currently 8192,) but we can test it in a\r
- # flexible manner. Each line in the bag o' ham is 4 bytes\r
- # ("h", "a", "m", "\n"), so 4096 lines of that should get us\r
- # exactly on the buffer boundary for any power-of-2 buffersize\r
- # between 4 and 16384 (inclusive).\r
- f = self.open(TESTFN, 'rb')\r
- for i in range(nchunks):\r
- next(f)\r
- testline = testlines.pop(0)\r
- try:\r
- line = f.readline()\r
- except ValueError:\r
- self.fail("readline() after next() with supposedly empty "\r
- "iteration-buffer failed anyway")\r
- if line != testline:\r
- self.fail("readline() after next() with empty buffer "\r
- "failed. Got %r, expected %r" % (line, testline))\r
- testline = testlines.pop(0)\r
- buf = array("b", b"\x00" * len(testline))\r
- try:\r
- f.readinto(buf)\r
- except ValueError:\r
- self.fail("readinto() after next() with supposedly empty "\r
- "iteration-buffer failed anyway")\r
- line = buf.tostring()\r
- if line != testline:\r
- self.fail("readinto() after next() with empty buffer "\r
- "failed. Got %r, expected %r" % (line, testline))\r
-\r
- testline = testlines.pop(0)\r
- try:\r
- line = f.read(len(testline))\r
- except ValueError:\r
- self.fail("read() after next() with supposedly empty "\r
- "iteration-buffer failed anyway")\r
- if line != testline:\r
- self.fail("read() after next() with empty buffer "\r
- "failed. Got %r, expected %r" % (line, testline))\r
- try:\r
- lines = f.readlines()\r
- except ValueError:\r
- self.fail("readlines() after next() with supposedly empty "\r
- "iteration-buffer failed anyway")\r
- if lines != testlines:\r
- self.fail("readlines() after next() with empty buffer "\r
- "failed. Got %r, expected %r" % (line, testline))\r
- # Reading after iteration hit EOF shouldn't hurt either\r
- f = self.open(TESTFN, 'rb')\r
- try:\r
- for line in f:\r
- pass\r
- try:\r
- f.readline()\r
- f.readinto(buf)\r
- f.read()\r
- f.readlines()\r
- except ValueError:\r
- self.fail("read* failed after next() consumed file")\r
- finally:\r
- f.close()\r
- finally:\r
- os.unlink(TESTFN)\r
-\r
-class COtherFileTests(OtherFileTests):\r
- open = io.open\r
-\r
-class PyOtherFileTests(OtherFileTests):\r
- open = staticmethod(pyio.open)\r
-\r
-\r
-def test_main():\r
- # Historically, these tests have been sloppy about removing TESTFN.\r
- # So get rid of it no matter what.\r
- try:\r
- run_unittest(CAutoFileTests, PyAutoFileTests,\r
- COtherFileTests, PyOtherFileTests)\r
- finally:\r
- if os.path.exists(TESTFN):\r
- os.unlink(TESTFN)\r
-\r
-if __name__ == '__main__':\r
- test_main()\r