~ubuntu-branches/ubuntu/trusty/python3.4/trusty-proposed

« back to all changes in this revision

Viewing changes to Lib/test/test_file.py

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2013-11-25 09:44:27 UTC
  • Revision ID: package-import@ubuntu.com-20131125094427-lzxj8ap5w01lmo7f
Tags: upstream-3.4~b1
ImportĀ upstreamĀ versionĀ 3.4~b1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import sys
 
2
import os
 
3
import unittest
 
4
from array import array
 
5
from weakref import proxy
 
6
 
 
7
import io
 
8
import _pyio as pyio
 
9
 
 
10
from test.support import TESTFN, run_unittest
 
11
from collections import UserList
 
12
 
 
13
class AutoFileTests:
 
14
    # file tests for which a test file is automatically set up
 
15
 
 
16
    def setUp(self):
 
17
        self.f = self.open(TESTFN, 'wb')
 
18
 
 
19
    def tearDown(self):
 
20
        if self.f:
 
21
            self.f.close()
 
22
        os.remove(TESTFN)
 
23
 
 
24
    def testWeakRefs(self):
 
25
        # verify weak references
 
26
        p = proxy(self.f)
 
27
        p.write(b'teststring')
 
28
        self.assertEqual(self.f.tell(), p.tell())
 
29
        self.f.close()
 
30
        self.f = None
 
31
        self.assertRaises(ReferenceError, getattr, p, 'tell')
 
32
 
 
33
    def testAttributes(self):
 
34
        # verify expected attributes exist
 
35
        f = self.f
 
36
        f.name     # merely shouldn't blow up
 
37
        f.mode     # ditto
 
38
        f.closed   # ditto
 
39
 
 
40
    def testReadinto(self):
 
41
        # verify readinto
 
42
        self.f.write(b'12')
 
43
        self.f.close()
 
44
        a = array('b', b'x'*10)
 
45
        self.f = self.open(TESTFN, 'rb')
 
46
        n = self.f.readinto(a)
 
47
        self.assertEqual(b'12', a.tobytes()[:n])
 
48
 
 
49
    def testReadinto_text(self):
 
50
        # verify readinto refuses text files
 
51
        a = array('b', b'x'*10)
 
52
        self.f.close()
 
53
        self.f = self.open(TESTFN, 'r')
 
54
        if hasattr(self.f, "readinto"):
 
55
            self.assertRaises(TypeError, self.f.readinto, a)
 
56
 
 
57
    def testWritelinesUserList(self):
 
58
        # verify writelines with instance sequence
 
59
        l = UserList([b'1', b'2'])
 
60
        self.f.writelines(l)
 
61
        self.f.close()
 
62
        self.f = self.open(TESTFN, 'rb')
 
63
        buf = self.f.read()
 
64
        self.assertEqual(buf, b'12')
 
65
 
 
66
    def testWritelinesIntegers(self):
 
67
        # verify writelines with integers
 
68
        self.assertRaises(TypeError, self.f.writelines, [1, 2, 3])
 
69
 
 
70
    def testWritelinesIntegersUserList(self):
 
71
        # verify writelines with integers in UserList
 
72
        l = UserList([1,2,3])
 
73
        self.assertRaises(TypeError, self.f.writelines, l)
 
74
 
 
75
    def testWritelinesNonString(self):
 
76
        # verify writelines with non-string object
 
77
        class NonString:
 
78
            pass
 
79
 
 
80
        self.assertRaises(TypeError, self.f.writelines,
 
81
                          [NonString(), NonString()])
 
82
 
 
83
    def testErrors(self):
 
84
        f = self.f
 
85
        self.assertEqual(f.name, TESTFN)
 
86
        self.assertTrue(not f.isatty())
 
87
        self.assertTrue(not f.closed)
 
88
 
 
89
        if hasattr(f, "readinto"):
 
90
            self.assertRaises((OSError, TypeError), f.readinto, "")
 
91
        f.close()
 
92
        self.assertTrue(f.closed)
 
93
 
 
94
    def testMethods(self):
 
95
        methods = [('fileno', ()),
 
96
                   ('flush', ()),
 
97
                   ('isatty', ()),
 
98
                   ('__next__', ()),
 
99
                   ('read', ()),
 
100
                   ('write', (b"",)),
 
101
                   ('readline', ()),
 
102
                   ('readlines', ()),
 
103
                   ('seek', (0,)),
 
104
                   ('tell', ()),
 
105
                   ('write', (b"",)),
 
106
                   ('writelines', ([],)),
 
107
                   ('__iter__', ()),
 
108
                   ]
 
109
        methods.append(('truncate', ()))
 
110
 
 
111
        # __exit__ should close the file
 
112
        self.f.__exit__(None, None, None)
 
113
        self.assertTrue(self.f.closed)
 
114
 
 
115
        for methodname, args in methods:
 
116
            method = getattr(self.f, methodname)
 
117
            # should raise on closed file
 
118
            self.assertRaises(ValueError, method, *args)
 
119
 
 
120
        # file is closed, __exit__ shouldn't do anything
 
121
        self.assertEqual(self.f.__exit__(None, None, None), None)
 
122
        # it must also return None if an exception was given
 
123
        try:
 
124
            1/0
 
125
        except:
 
126
            self.assertEqual(self.f.__exit__(*sys.exc_info()), None)
 
127
 
 
128
    def testReadWhenWriting(self):
 
129
        self.assertRaises(OSError, self.f.read)
 
130
 
 
131
class CAutoFileTests(AutoFileTests, unittest.TestCase):
 
132
    open = io.open
 
133
 
 
134
class PyAutoFileTests(AutoFileTests, unittest.TestCase):
 
135
    open = staticmethod(pyio.open)
 
136
 
 
137
 
 
138
class OtherFileTests:
 
139
 
 
140
    def testModeStrings(self):
 
141
        # check invalid mode strings
 
142
        for mode in ("", "aU", "wU+"):
 
143
            try:
 
144
                f = self.open(TESTFN, mode)
 
145
            except ValueError:
 
146
                pass
 
147
            else:
 
148
                f.close()
 
149
                self.fail('%r is an invalid file mode' % mode)
 
150
 
 
151
    def testBadModeArgument(self):
 
152
        # verify that we get a sensible error message for bad mode argument
 
153
        bad_mode = "qwerty"
 
154
        try:
 
155
            f = self.open(TESTFN, bad_mode)
 
156
        except ValueError as msg:
 
157
            if msg.args[0] != 0:
 
158
                s = str(msg)
 
159
                if TESTFN in s or bad_mode not in s:
 
160
                    self.fail("bad error message for invalid mode: %s" % s)
 
161
            # if msg.args[0] == 0, we're probably on Windows where there may be
 
162
            # no obvious way to discover why open() failed.
 
163
        else:
 
164
            f.close()
 
165
            self.fail("no error for invalid mode: %s" % bad_mode)
 
166
 
 
167
    def testSetBufferSize(self):
 
168
        # make sure that explicitly setting the buffer size doesn't cause
 
169
        # misbehaviour especially with repeated close() calls
 
170
        for s in (-1, 0, 1, 512):
 
171
            try:
 
172
                f = self.open(TESTFN, 'wb', s)
 
173
                f.write(str(s).encode("ascii"))
 
174
                f.close()
 
175
                f.close()
 
176
                f = self.open(TESTFN, 'rb', s)
 
177
                d = int(f.read().decode("ascii"))
 
178
                f.close()
 
179
                f.close()
 
180
            except OSError as msg:
 
181
                self.fail('error setting buffer size %d: %s' % (s, str(msg)))
 
182
            self.assertEqual(d, s)
 
183
 
 
184
    def testTruncateOnWindows(self):
 
185
        # SF bug <http://www.python.org/sf/801631>
 
186
        # "file.truncate fault on windows"
 
187
 
 
188
        os.unlink(TESTFN)
 
189
        f = self.open(TESTFN, 'wb')
 
190
 
 
191
        try:
 
192
            f.write(b'12345678901')   # 11 bytes
 
193
            f.close()
 
194
 
 
195
            f = self.open(TESTFN,'rb+')
 
196
            data = f.read(5)
 
197
            if data != b'12345':
 
198
                self.fail("Read on file opened for update failed %r" % data)
 
199
            if f.tell() != 5:
 
200
                self.fail("File pos after read wrong %d" % f.tell())
 
201
 
 
202
            f.truncate()
 
203
            if f.tell() != 5:
 
204
                self.fail("File pos after ftruncate wrong %d" % f.tell())
 
205
 
 
206
            f.close()
 
207
            size = os.path.getsize(TESTFN)
 
208
            if size != 5:
 
209
                self.fail("File size after ftruncate wrong %d" % size)
 
210
        finally:
 
211
            f.close()
 
212
            os.unlink(TESTFN)
 
213
 
 
214
    def testIteration(self):
 
215
        # Test the complex interaction when mixing file-iteration and the
 
216
        # various read* methods.
 
217
        dataoffset = 16384
 
218
        filler = b"ham\n"
 
219
        assert not dataoffset % len(filler), \
 
220
            "dataoffset must be multiple of len(filler)"
 
221
        nchunks = dataoffset // len(filler)
 
222
        testlines = [
 
223
            b"spam, spam and eggs\n",
 
224
            b"eggs, spam, ham and spam\n",
 
225
            b"saussages, spam, spam and eggs\n",
 
226
            b"spam, ham, spam and eggs\n",
 
227
            b"spam, spam, spam, spam, spam, ham, spam\n",
 
228
            b"wonderful spaaaaaam.\n"
 
229
        ]
 
230
        methods = [("readline", ()), ("read", ()), ("readlines", ()),
 
231
                   ("readinto", (array("b", b" "*100),))]
 
232
 
 
233
        try:
 
234
            # Prepare the testfile
 
235
            bag = self.open(TESTFN, "wb")
 
236
            bag.write(filler * nchunks)
 
237
            bag.writelines(testlines)
 
238
            bag.close()
 
239
            # Test for appropriate errors mixing read* and iteration
 
240
            for methodname, args in methods:
 
241
                f = self.open(TESTFN, 'rb')
 
242
                if next(f) != filler:
 
243
                    self.fail, "Broken testfile"
 
244
                meth = getattr(f, methodname)
 
245
                meth(*args)  # This simply shouldn't fail
 
246
                f.close()
 
247
 
 
248
            # Test to see if harmless (by accident) mixing of read* and
 
249
            # iteration still works. This depends on the size of the internal
 
250
            # iteration buffer (currently 8192,) but we can test it in a
 
251
            # flexible manner.  Each line in the bag o' ham is 4 bytes
 
252
            # ("h", "a", "m", "\n"), so 4096 lines of that should get us
 
253
            # exactly on the buffer boundary for any power-of-2 buffersize
 
254
            # between 4 and 16384 (inclusive).
 
255
            f = self.open(TESTFN, 'rb')
 
256
            for i in range(nchunks):
 
257
                next(f)
 
258
            testline = testlines.pop(0)
 
259
            try:
 
260
                line = f.readline()
 
261
            except ValueError:
 
262
                self.fail("readline() after next() with supposedly empty "
 
263
                          "iteration-buffer failed anyway")
 
264
            if line != testline:
 
265
                self.fail("readline() after next() with empty buffer "
 
266
                          "failed. Got %r, expected %r" % (line, testline))
 
267
            testline = testlines.pop(0)
 
268
            buf = array("b", b"\x00" * len(testline))
 
269
            try:
 
270
                f.readinto(buf)
 
271
            except ValueError:
 
272
                self.fail("readinto() after next() with supposedly empty "
 
273
                          "iteration-buffer failed anyway")
 
274
            line = buf.tobytes()
 
275
            if line != testline:
 
276
                self.fail("readinto() after next() with empty buffer "
 
277
                          "failed. Got %r, expected %r" % (line, testline))
 
278
 
 
279
            testline = testlines.pop(0)
 
280
            try:
 
281
                line = f.read(len(testline))
 
282
            except ValueError:
 
283
                self.fail("read() after next() with supposedly empty "
 
284
                          "iteration-buffer failed anyway")
 
285
            if line != testline:
 
286
                self.fail("read() after next() with empty buffer "
 
287
                          "failed. Got %r, expected %r" % (line, testline))
 
288
            try:
 
289
                lines = f.readlines()
 
290
            except ValueError:
 
291
                self.fail("readlines() after next() with supposedly empty "
 
292
                          "iteration-buffer failed anyway")
 
293
            if lines != testlines:
 
294
                self.fail("readlines() after next() with empty buffer "
 
295
                          "failed. Got %r, expected %r" % (line, testline))
 
296
            f.close()
 
297
 
 
298
            # Reading after iteration hit EOF shouldn't hurt either
 
299
            f = self.open(TESTFN, 'rb')
 
300
            try:
 
301
                for line in f:
 
302
                    pass
 
303
                try:
 
304
                    f.readline()
 
305
                    f.readinto(buf)
 
306
                    f.read()
 
307
                    f.readlines()
 
308
                except ValueError:
 
309
                    self.fail("read* failed after next() consumed file")
 
310
            finally:
 
311
                f.close()
 
312
        finally:
 
313
            os.unlink(TESTFN)
 
314
 
 
315
class COtherFileTests(OtherFileTests, unittest.TestCase):
 
316
    open = io.open
 
317
 
 
318
class PyOtherFileTests(OtherFileTests, unittest.TestCase):
 
319
    open = staticmethod(pyio.open)
 
320
 
 
321
 
 
322
def tearDownModule():
 
323
    # Historically, these tests have been sloppy about removing TESTFN.
 
324
    # So get rid of it no matter what.
 
325
    if os.path.exists(TESTFN):
 
326
        os.unlink(TESTFN)
 
327
 
 
328
if __name__ == '__main__':
 
329
    unittest.main()