test_zipfile.py revision ea5962f86e8550978446724dadcacd60e03feef2
1# We can test part of the module without zlib.
2try:
3    import zlib
4except ImportError:
5    zlib = None
6
7import zipfile, os, unittest, sys, shutil, struct
8
9from StringIO import StringIO
10from tempfile import TemporaryFile
11from random import randint, random
12
13from test.test_support import TESTFN, run_unittest
14
15TESTFN2 = TESTFN + "2"
16FIXEDTEST_SIZE = 10
17
18class TestsWithSourceFile(unittest.TestCase):
19    def setUp(self):
20        self.line_gen = ("Zipfile test line %d. random float: %f" % (i, random())
21                          for i in xrange(FIXEDTEST_SIZE))
22        self.data = '\n'.join(self.line_gen) + '\n'
23
24        # Make a source file with some lines
25        fp = open(TESTFN, "wb")
26        fp.write(self.data)
27        fp.close()
28
29    def makeTestArchive(self, f, compression):
30        # Create the ZIP archive
31        zipfp = zipfile.ZipFile(f, "w", compression)
32        zipfp.write(TESTFN, "another"+os.extsep+"name")
33        zipfp.write(TESTFN, TESTFN)
34        zipfp.writestr("strfile", self.data)
35        zipfp.close()
36
37    def zipTest(self, f, compression):
38        self.makeTestArchive(f, compression)
39
40        # Read the ZIP archive
41        zipfp = zipfile.ZipFile(f, "r", compression)
42        self.assertEqual(zipfp.read(TESTFN), self.data)
43        self.assertEqual(zipfp.read("another"+os.extsep+"name"), self.data)
44        self.assertEqual(zipfp.read("strfile"), self.data)
45
46        # Print the ZIP directory
47        fp = StringIO()
48        stdout = sys.stdout
49        try:
50            sys.stdout = fp
51
52            zipfp.printdir()
53        finally:
54            sys.stdout = stdout
55
56        directory = fp.getvalue()
57        lines = directory.splitlines()
58        self.assertEquals(len(lines), 4) # Number of files + header
59
60        self.assert_('File Name' in lines[0])
61        self.assert_('Modified' in lines[0])
62        self.assert_('Size' in lines[0])
63
64        fn, date, time, size = lines[1].split()
65        self.assertEquals(fn, 'another.name')
66        # XXX: timestamp is not tested
67        self.assertEquals(size, str(len(self.data)))
68
69        # Check the namelist
70        names = zipfp.namelist()
71        self.assertEquals(len(names), 3)
72        self.assert_(TESTFN in names)
73        self.assert_("another"+os.extsep+"name" in names)
74        self.assert_("strfile" in names)
75
76        # Check infolist
77        infos = zipfp.infolist()
78        names = [ i.filename for i in infos ]
79        self.assertEquals(len(names), 3)
80        self.assert_(TESTFN in names)
81        self.assert_("another"+os.extsep+"name" in names)
82        self.assert_("strfile" in names)
83        for i in infos:
84            self.assertEquals(i.file_size, len(self.data))
85
86        # check getinfo
87        for nm in (TESTFN, "another"+os.extsep+"name", "strfile"):
88            info = zipfp.getinfo(nm)
89            self.assertEquals(info.filename, nm)
90            self.assertEquals(info.file_size, len(self.data))
91
92        # Check that testzip doesn't raise an exception
93        zipfp.testzip()
94        zipfp.close()
95
96    def testStored(self):
97        for f in (TESTFN2, TemporaryFile(), StringIO()):
98            self.zipTest(f, zipfile.ZIP_STORED)
99
100    def zipOpenTest(self, f, compression):
101        self.makeTestArchive(f, compression)
102
103        # Read the ZIP archive
104        zipfp = zipfile.ZipFile(f, "r", compression)
105        zipdata1 = []
106        zipopen1 = zipfp.open(TESTFN)
107        while 1:
108            read_data = zipopen1.read(256)
109            if not read_data:
110                break
111            zipdata1.append(read_data)
112
113        zipdata2 = []
114        zipopen2 = zipfp.open("another"+os.extsep+"name")
115        while 1:
116            read_data = zipopen2.read(256)
117            if not read_data:
118                break
119            zipdata2.append(read_data)
120
121        self.assertEqual(''.join(zipdata1), self.data)
122        self.assertEqual(''.join(zipdata2), self.data)
123        zipfp.close()
124
125    def testOpenStored(self):
126        for f in (TESTFN2, TemporaryFile(), StringIO()):
127            self.zipOpenTest(f, zipfile.ZIP_STORED)
128
129    def zipRandomOpenTest(self, f, compression):
130        self.makeTestArchive(f, compression)
131
132        # Read the ZIP archive
133        zipfp = zipfile.ZipFile(f, "r", compression)
134        zipdata1 = []
135        zipopen1 = zipfp.open(TESTFN)
136        while 1:
137            read_data = zipopen1.read(randint(1, 1024))
138            if not read_data:
139                break
140            zipdata1.append(read_data)
141
142        self.assertEqual(''.join(zipdata1), self.data)
143        zipfp.close()
144
145    def testRandomOpenStored(self):
146        for f in (TESTFN2, TemporaryFile(), StringIO()):
147            self.zipRandomOpenTest(f, zipfile.ZIP_STORED)
148
149    def zipReadlineTest(self, f, compression):
150        self.makeTestArchive(f, compression)
151
152        # Read the ZIP archive
153        zipfp = zipfile.ZipFile(f, "r")
154        zipopen = zipfp.open(TESTFN)
155        for line in self.line_gen:
156            linedata = zipopen.readline()
157            self.assertEqual(linedata, line + '\n')
158
159        zipfp.close()
160
161    def zipReadlinesTest(self, f, compression):
162        self.makeTestArchive(f, compression)
163
164        # Read the ZIP archive
165        zipfp = zipfile.ZipFile(f, "r")
166        ziplines = zipfp.open(TESTFN).readlines()
167        for line, zipline in zip(self.line_gen, ziplines):
168            self.assertEqual(zipline, line + '\n')
169
170        zipfp.close()
171
172    def zipIterlinesTest(self, f, compression):
173        self.makeTestArchive(f, compression)
174
175        # Read the ZIP archive
176        zipfp = zipfile.ZipFile(f, "r")
177        for line, zipline in zip(self.line_gen, zipfp.open(TESTFN)):
178            self.assertEqual(zipline, line + '\n')
179
180        zipfp.close()
181
182    def testReadlineStored(self):
183        for f in (TESTFN2, TemporaryFile(), StringIO()):
184            self.zipReadlineTest(f, zipfile.ZIP_STORED)
185
186    def testReadlinesStored(self):
187        for f in (TESTFN2, TemporaryFile(), StringIO()):
188            self.zipReadlinesTest(f, zipfile.ZIP_STORED)
189
190    def testIterlinesStored(self):
191        for f in (TESTFN2, TemporaryFile(), StringIO()):
192            self.zipIterlinesTest(f, zipfile.ZIP_STORED)
193
194    if zlib:
195        def testDeflated(self):
196            for f in (TESTFN2, TemporaryFile(), StringIO()):
197                self.zipTest(f, zipfile.ZIP_DEFLATED)
198
199        def testOpenDeflated(self):
200            for f in (TESTFN2, TemporaryFile(), StringIO()):
201                self.zipOpenTest(f, zipfile.ZIP_DEFLATED)
202
203        def testRandomOpenDeflated(self):
204            for f in (TESTFN2, TemporaryFile(), StringIO()):
205                self.zipRandomOpenTest(f, zipfile.ZIP_DEFLATED)
206
207        def testReadlineDeflated(self):
208            for f in (TESTFN2, TemporaryFile(), StringIO()):
209                self.zipReadlineTest(f, zipfile.ZIP_DEFLATED)
210
211        def testReadlinesDeflated(self):
212            for f in (TESTFN2, TemporaryFile(), StringIO()):
213                self.zipReadlinesTest(f, zipfile.ZIP_DEFLATED)
214
215        def testIterlinesDeflated(self):
216            for f in (TESTFN2, TemporaryFile(), StringIO()):
217                self.zipIterlinesTest(f, zipfile.ZIP_DEFLATED)
218
219        def testLowCompression(self):
220            # Checks for cases where compressed data is larger than original
221            # Create the ZIP archive
222            zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_DEFLATED)
223            zipfp.writestr("strfile", '12')
224            zipfp.close()
225
226            # Get an open object for strfile
227            zipfp = zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_DEFLATED)
228            openobj = zipfp.open("strfile")
229            self.assertEqual(openobj.read(1), '1')
230            self.assertEqual(openobj.read(1), '2')
231
232    def testAbsoluteArcnames(self):
233        zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED)
234        zipfp.write(TESTFN, "/absolute")
235        zipfp.close()
236
237        zipfp = zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_STORED)
238        self.assertEqual(zipfp.namelist(), ["absolute"])
239        zipfp.close()
240
241    def tearDown(self):
242        os.remove(TESTFN)
243        os.remove(TESTFN2)
244
245class TestZip64InSmallFiles(unittest.TestCase):
246    # These tests test the ZIP64 functionality without using large files,
247    # see test_zipfile64 for proper tests.
248
249    def setUp(self):
250        self._limit = zipfile.ZIP64_LIMIT
251        zipfile.ZIP64_LIMIT = 5
252
253        line_gen = ("Test of zipfile line %d." % i for i in range(0, FIXEDTEST_SIZE))
254        self.data = '\n'.join(line_gen)
255
256        # Make a source file with some lines
257        fp = open(TESTFN, "wb")
258        fp.write(self.data)
259        fp.close()
260
261    def largeFileExceptionTest(self, f, compression):
262        zipfp = zipfile.ZipFile(f, "w", compression)
263        self.assertRaises(zipfile.LargeZipFile,
264                zipfp.write, TESTFN, "another"+os.extsep+"name")
265        zipfp.close()
266
267    def largeFileExceptionTest2(self, f, compression):
268        zipfp = zipfile.ZipFile(f, "w", compression)
269        self.assertRaises(zipfile.LargeZipFile,
270                zipfp.writestr, "another"+os.extsep+"name", self.data)
271        zipfp.close()
272
273    def testLargeFileException(self):
274        for f in (TESTFN2, TemporaryFile(), StringIO()):
275            self.largeFileExceptionTest(f, zipfile.ZIP_STORED)
276            self.largeFileExceptionTest2(f, zipfile.ZIP_STORED)
277
278    def zipTest(self, f, compression):
279        # Create the ZIP archive
280        zipfp = zipfile.ZipFile(f, "w", compression, allowZip64=True)
281        zipfp.write(TESTFN, "another"+os.extsep+"name")
282        zipfp.write(TESTFN, TESTFN)
283        zipfp.writestr("strfile", self.data)
284        zipfp.close()
285
286        # Read the ZIP archive
287        zipfp = zipfile.ZipFile(f, "r", compression)
288        self.assertEqual(zipfp.read(TESTFN), self.data)
289        self.assertEqual(zipfp.read("another"+os.extsep+"name"), self.data)
290        self.assertEqual(zipfp.read("strfile"), self.data)
291
292        # Print the ZIP directory
293        fp = StringIO()
294        stdout = sys.stdout
295        try:
296            sys.stdout = fp
297
298            zipfp.printdir()
299        finally:
300            sys.stdout = stdout
301
302        directory = fp.getvalue()
303        lines = directory.splitlines()
304        self.assertEquals(len(lines), 4) # Number of files + header
305
306        self.assert_('File Name' in lines[0])
307        self.assert_('Modified' in lines[0])
308        self.assert_('Size' in lines[0])
309
310        fn, date, time, size = lines[1].split()
311        self.assertEquals(fn, 'another.name')
312        # XXX: timestamp is not tested
313        self.assertEquals(size, str(len(self.data)))
314
315        # Check the namelist
316        names = zipfp.namelist()
317        self.assertEquals(len(names), 3)
318        self.assert_(TESTFN in names)
319        self.assert_("another"+os.extsep+"name" in names)
320        self.assert_("strfile" in names)
321
322        # Check infolist
323        infos = zipfp.infolist()
324        names = [ i.filename for i in infos ]
325        self.assertEquals(len(names), 3)
326        self.assert_(TESTFN in names)
327        self.assert_("another"+os.extsep+"name" in names)
328        self.assert_("strfile" in names)
329        for i in infos:
330            self.assertEquals(i.file_size, len(self.data))
331
332        # check getinfo
333        for nm in (TESTFN, "another"+os.extsep+"name", "strfile"):
334            info = zipfp.getinfo(nm)
335            self.assertEquals(info.filename, nm)
336            self.assertEquals(info.file_size, len(self.data))
337
338        # Check that testzip doesn't raise an exception
339        zipfp.testzip()
340
341
342        zipfp.close()
343
344    def testStored(self):
345        for f in (TESTFN2, TemporaryFile(), StringIO()):
346            self.zipTest(f, zipfile.ZIP_STORED)
347
348
349    if zlib:
350        def testDeflated(self):
351            for f in (TESTFN2, TemporaryFile(), StringIO()):
352                self.zipTest(f, zipfile.ZIP_DEFLATED)
353
354    def testAbsoluteArcnames(self):
355        zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED, allowZip64=True)
356        zipfp.write(TESTFN, "/absolute")
357        zipfp.close()
358
359        zipfp = zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_STORED)
360        self.assertEqual(zipfp.namelist(), ["absolute"])
361        zipfp.close()
362
363
364    def tearDown(self):
365        zipfile.ZIP64_LIMIT = self._limit
366        os.remove(TESTFN)
367        os.remove(TESTFN2)
368
369class PyZipFileTests(unittest.TestCase):
370    def testWritePyfile(self):
371        zipfp  = zipfile.PyZipFile(TemporaryFile(), "w")
372        fn = __file__
373        if fn.endswith('.pyc') or fn.endswith('.pyo'):
374            fn = fn[:-1]
375
376        zipfp.writepy(fn)
377
378        bn = os.path.basename(fn)
379        self.assert_(bn not in zipfp.namelist())
380        self.assert_(bn + 'o' in zipfp.namelist() or bn + 'c' in zipfp.namelist())
381        zipfp.close()
382
383
384        zipfp  = zipfile.PyZipFile(TemporaryFile(), "w")
385        fn = __file__
386        if fn.endswith('.pyc') or fn.endswith('.pyo'):
387            fn = fn[:-1]
388
389        zipfp.writepy(fn, "testpackage")
390
391        bn = "%s/%s"%("testpackage", os.path.basename(fn))
392        self.assert_(bn not in zipfp.namelist())
393        self.assert_(bn + 'o' in zipfp.namelist() or bn + 'c' in zipfp.namelist())
394        zipfp.close()
395
396    def testWritePythonPackage(self):
397        import email
398        packagedir = os.path.dirname(email.__file__)
399
400        zipfp  = zipfile.PyZipFile(TemporaryFile(), "w")
401        zipfp.writepy(packagedir)
402
403        # Check for a couple of modules at different levels of the hieararchy
404        names = zipfp.namelist()
405        self.assert_('email/__init__.pyo' in names or 'email/__init__.pyc' in names)
406        self.assert_('email/mime/text.pyo' in names or 'email/mime/text.pyc' in names)
407
408    def testWritePythonDirectory(self):
409        os.mkdir(TESTFN2)
410        try:
411            fp = open(os.path.join(TESTFN2, "mod1.py"), "w")
412            fp.write("print 42\n")
413            fp.close()
414
415            fp = open(os.path.join(TESTFN2, "mod2.py"), "w")
416            fp.write("print 42 * 42\n")
417            fp.close()
418
419            fp = open(os.path.join(TESTFN2, "mod2.txt"), "w")
420            fp.write("bla bla bla\n")
421            fp.close()
422
423            zipfp  = zipfile.PyZipFile(TemporaryFile(), "w")
424            zipfp.writepy(TESTFN2)
425
426            names = zipfp.namelist()
427            self.assert_('mod1.pyc' in names or 'mod1.pyo' in names)
428            self.assert_('mod2.pyc' in names or 'mod2.pyo' in names)
429            self.assert_('mod2.txt' not in names)
430
431        finally:
432            shutil.rmtree(TESTFN2)
433
434
435
436class OtherTests(unittest.TestCase):
437    def testCreateNonExistentFileForAppend(self):
438        if os.path.exists(TESTFN):
439            os.unlink(TESTFN)
440
441        filename = 'testfile.txt'
442        content = 'hello, world. this is some content.'
443
444        try:
445            zf = zipfile.ZipFile(TESTFN, 'a')
446            zf.writestr(filename, content)
447            zf.close()
448        except IOError, (errno, errmsg):
449            self.fail('Could not append data to a non-existent zip file.')
450
451        self.assert_(os.path.exists(TESTFN))
452
453        zf = zipfile.ZipFile(TESTFN, 'r')
454        self.assertEqual(zf.read(filename), content)
455        zf.close()
456
457        os.unlink(TESTFN)
458
459    def testCloseErroneousFile(self):
460        # This test checks that the ZipFile constructor closes the file object
461        # it opens if there's an error in the file.  If it doesn't, the traceback
462        # holds a reference to the ZipFile object and, indirectly, the file object.
463        # On Windows, this causes the os.unlink() call to fail because the
464        # underlying file is still open.  This is SF bug #412214.
465        #
466        fp = open(TESTFN, "w")
467        fp.write("this is not a legal zip file\n")
468        fp.close()
469        try:
470            zf = zipfile.ZipFile(TESTFN)
471        except zipfile.BadZipfile:
472            os.unlink(TESTFN)
473
474    def testIsZipErroneousFile(self):
475        # This test checks that the is_zipfile function correctly identifies
476        # a file that is not a zip file
477        fp = open(TESTFN, "w")
478        fp.write("this is not a legal zip file\n")
479        fp.close()
480        chk = zipfile.is_zipfile(TESTFN)
481        os.unlink(TESTFN)
482        self.assert_(chk is False)
483
484    def testIsZipValidFile(self):
485        # This test checks that the is_zipfile function correctly identifies
486        # a file that is a zip file
487        zipf = zipfile.ZipFile(TESTFN, mode="w")
488        zipf.writestr("foo.txt", "O, for a Muse of Fire!")
489        zipf.close()
490        chk = zipfile.is_zipfile(TESTFN)
491        os.unlink(TESTFN)
492        self.assert_(chk is True)
493
494    def testNonExistentFileRaisesIOError(self):
495        # make sure we don't raise an AttributeError when a partially-constructed
496        # ZipFile instance is finalized; this tests for regression on SF tracker
497        # bug #403871.
498
499        # The bug we're testing for caused an AttributeError to be raised
500        # when a ZipFile instance was created for a file that did not
501        # exist; the .fp member was not initialized but was needed by the
502        # __del__() method.  Since the AttributeError is in the __del__(),
503        # it is ignored, but the user should be sufficiently annoyed by
504        # the message on the output that regression will be noticed
505        # quickly.
506        self.assertRaises(IOError, zipfile.ZipFile, TESTFN)
507
508    def testClosedZipRaisesRuntimeError(self):
509        # Verify that testzip() doesn't swallow inappropriate exceptions.
510        data = StringIO()
511        zipf = zipfile.ZipFile(data, mode="w")
512        zipf.writestr("foo.txt", "O, for a Muse of Fire!")
513        zipf.close()
514
515        # This is correct; calling .read on a closed ZipFile should throw
516        # a RuntimeError, and so should calling .testzip.  An earlier
517        # version of .testzip would swallow this exception (and any other)
518        # and report that the first file in the archive was corrupt.
519        self.assertRaises(RuntimeError, zipf.testzip)
520
521class DecryptionTests(unittest.TestCase):
522    # This test checks that ZIP decryption works. Since the library does not
523    # support encryption at the moment, we use a pre-generated encrypted
524    # ZIP file
525
526    data = (
527    'PK\x03\x04\x14\x00\x01\x00\x00\x00n\x92i.#y\xef?&\x00\x00\x00\x1a\x00'
528    '\x00\x00\x08\x00\x00\x00test.txt\xfa\x10\xa0gly|\xfa-\xc5\xc0=\xf9y'
529    '\x18\xe0\xa8r\xb3Z}Lg\xbc\xae\xf9|\x9b\x19\xe4\x8b\xba\xbb)\x8c\xb0\xdbl'
530    'PK\x01\x02\x14\x00\x14\x00\x01\x00\x00\x00n\x92i.#y\xef?&\x00\x00\x00'
531    '\x1a\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x01\x00 \x00\xb6\x81'
532    '\x00\x00\x00\x00test.txtPK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x006\x00'
533    '\x00\x00L\x00\x00\x00\x00\x00' )
534
535    plain = 'zipfile.py encryption test'
536
537    def setUp(self):
538        fp = open(TESTFN, "wb")
539        fp.write(self.data)
540        fp.close()
541        self.zip = zipfile.ZipFile(TESTFN, "r")
542
543    def tearDown(self):
544        self.zip.close()
545        os.unlink(TESTFN)
546
547    def testNoPassword(self):
548        # Reading the encrypted file without password
549        # must generate a RunTime exception
550        self.assertRaises(RuntimeError, self.zip.read, "test.txt")
551
552    def testBadPassword(self):
553        self.zip.setpassword("perl")
554        self.assertRaises(RuntimeError, self.zip.read, "test.txt")
555
556    def testGoodPassword(self):
557        self.zip.setpassword("python")
558        self.assertEquals(self.zip.read("test.txt"), self.plain)
559
560
561class TestsWithRandomBinaryFiles(unittest.TestCase):
562    def setUp(self):
563        datacount = randint(16, 64)*1024 + randint(1, 1024)
564        self.data = ''.join((struct.pack('<f', random()*randint(-1000, 1000)) for i in xrange(datacount)))
565
566        # Make a source file with some lines
567        fp = open(TESTFN, "wb")
568        fp.write(self.data)
569        fp.close()
570
571    def makeTestArchive(self, f, compression):
572        # Create the ZIP archive
573        zipfp = zipfile.ZipFile(f, "w", compression)
574        zipfp.write(TESTFN, "another"+os.extsep+"name")
575        zipfp.write(TESTFN, TESTFN)
576        zipfp.close()
577
578    def zipTest(self, f, compression):
579        self.makeTestArchive(f, compression)
580
581        # Read the ZIP archive
582        zipfp = zipfile.ZipFile(f, "r", compression)
583        testdata = zipfp.read(TESTFN)
584        self.assertEqual(len(testdata), len(self.data))
585        self.assertEqual(testdata, self.data)
586        self.assertEqual(zipfp.read("another"+os.extsep+"name"), self.data)
587        zipfp.close()
588
589    def testStored(self):
590        for f in (TESTFN2, TemporaryFile(), StringIO()):
591            self.zipTest(f, zipfile.ZIP_STORED)
592
593    def zipOpenTest(self, f, compression):
594        self.makeTestArchive(f, compression)
595
596        # Read the ZIP archive
597        zipfp = zipfile.ZipFile(f, "r", compression)
598        zipdata1 = []
599        zipopen1 = zipfp.open(TESTFN)
600        while 1:
601            read_data = zipopen1.read(256)
602            if not read_data:
603                break
604            zipdata1.append(read_data)
605
606        zipdata2 = []
607        zipopen2 = zipfp.open("another"+os.extsep+"name")
608        while 1:
609            read_data = zipopen2.read(256)
610            if not read_data:
611                break
612            zipdata2.append(read_data)
613
614        testdata1 = ''.join(zipdata1)
615        self.assertEqual(len(testdata1), len(self.data))
616        self.assertEqual(testdata1, self.data)
617
618        testdata2 = ''.join(zipdata2)
619        self.assertEqual(len(testdata1), len(self.data))
620        self.assertEqual(testdata1, self.data)
621        zipfp.close()
622
623    def testOpenStored(self):
624        for f in (TESTFN2, TemporaryFile(), StringIO()):
625            self.zipOpenTest(f, zipfile.ZIP_STORED)
626
627    def zipRandomOpenTest(self, f, compression):
628        self.makeTestArchive(f, compression)
629
630        # Read the ZIP archive
631        zipfp = zipfile.ZipFile(f, "r", compression)
632        zipdata1 = []
633        zipopen1 = zipfp.open(TESTFN)
634        while 1:
635            read_data = zipopen1.read(randint(1, 1024))
636            if not read_data:
637                break
638            zipdata1.append(read_data)
639
640        testdata = ''.join(zipdata1)
641        self.assertEqual(len(testdata), len(self.data))
642        self.assertEqual(testdata, self.data)
643        zipfp.close()
644
645    def testRandomOpenStored(self):
646        for f in (TESTFN2, TemporaryFile(), StringIO()):
647            self.zipRandomOpenTest(f, zipfile.ZIP_STORED)
648
649class TestsWithMultipleOpens(unittest.TestCase):
650    def setUp(self):
651        # Create the ZIP archive
652        zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_DEFLATED)
653        zipfp.writestr('ones', '1'*FIXEDTEST_SIZE)
654        zipfp.writestr('twos', '2'*FIXEDTEST_SIZE)
655        zipfp.close()
656
657    def testSameFile(self):
658        # Verify that (when the ZipFile is in control of creating file objects)
659        # multiple open() calls can be made without interfering with each other.
660        zipf = zipfile.ZipFile(TESTFN2, mode="r")
661        zopen1 = zipf.open('ones')
662        zopen2 = zipf.open('ones')
663        data1 = zopen1.read(500)
664        data2 = zopen2.read(500)
665        data1 += zopen1.read(500)
666        data2 += zopen2.read(500)
667        self.assertEqual(data1, data2)
668        zipf.close()
669
670    def testDifferentFile(self):
671        # Verify that (when the ZipFile is in control of creating file objects)
672        # multiple open() calls can be made without interfering with each other.
673        zipf = zipfile.ZipFile(TESTFN2, mode="r")
674        zopen1 = zipf.open('ones')
675        zopen2 = zipf.open('twos')
676        data1 = zopen1.read(500)
677        data2 = zopen2.read(500)
678        data1 += zopen1.read(500)
679        data2 += zopen2.read(500)
680        self.assertEqual(data1, '1'*FIXEDTEST_SIZE)
681        self.assertEqual(data2, '2'*FIXEDTEST_SIZE)
682        zipf.close()
683
684    def testInterleaved(self):
685        # Verify that (when the ZipFile is in control of creating file objects)
686        # multiple open() calls can be made without interfering with each other.
687        zipf = zipfile.ZipFile(TESTFN2, mode="r")
688        zopen1 = zipf.open('ones')
689        data1 = zopen1.read(500)
690        zopen2 = zipf.open('twos')
691        data2 = zopen2.read(500)
692        data1 += zopen1.read(500)
693        data2 += zopen2.read(500)
694        self.assertEqual(data1, '1'*FIXEDTEST_SIZE)
695        self.assertEqual(data2, '2'*FIXEDTEST_SIZE)
696        zipf.close()
697
698    def tearDown(self):
699        os.remove(TESTFN2)
700
701
702class UniversalNewlineTests(unittest.TestCase):
703    def setUp(self):
704        self.line_gen = ["Test of zipfile line %d." % i for i in xrange(FIXEDTEST_SIZE)]
705        self.seps = ('\r', '\r\n', '\n')
706        self.arcdata, self.arcfiles = {}, {}
707        for n, s in enumerate(self.seps):
708            self.arcdata[s] = s.join(self.line_gen) + s
709            self.arcfiles[s] = '%s-%d' % (TESTFN, n)
710            file(self.arcfiles[s], "wb").write(self.arcdata[s])
711
712    def makeTestArchive(self, f, compression):
713        # Create the ZIP archive
714        zipfp = zipfile.ZipFile(f, "w", compression)
715        for fn in self.arcfiles.values():
716            zipfp.write(fn, fn)
717        zipfp.close()
718
719    def readTest(self, f, compression):
720        self.makeTestArchive(f, compression)
721
722        # Read the ZIP archive
723        zipfp = zipfile.ZipFile(f, "r")
724        for sep, fn in self.arcfiles.items():
725            zipdata = zipfp.open(fn, "rU").read()
726            self.assertEqual(self.arcdata[sep], zipdata)
727
728        zipfp.close()
729
730    def readlineTest(self, f, compression):
731        self.makeTestArchive(f, compression)
732
733        # Read the ZIP archive
734        zipfp = zipfile.ZipFile(f, "r")
735        for sep, fn in self.arcfiles.items():
736            zipopen = zipfp.open(fn, "rU")
737            for line in self.line_gen:
738                linedata = zipopen.readline()
739                self.assertEqual(linedata, line + '\n')
740
741        zipfp.close()
742
743    def readlinesTest(self, f, compression):
744        self.makeTestArchive(f, compression)
745
746        # Read the ZIP archive
747        zipfp = zipfile.ZipFile(f, "r")
748        for sep, fn in self.arcfiles.items():
749            ziplines = zipfp.open(fn, "rU").readlines()
750            for line, zipline in zip(self.line_gen, ziplines):
751                self.assertEqual(zipline, line + '\n')
752
753        zipfp.close()
754
755    def iterlinesTest(self, f, compression):
756        self.makeTestArchive(f, compression)
757
758        # Read the ZIP archive
759        zipfp = zipfile.ZipFile(f, "r")
760        for sep, fn in self.arcfiles.items():
761            for line, zipline in zip(self.line_gen, zipfp.open(fn, "rU")):
762                self.assertEqual(zipline, line + '\n')
763
764        zipfp.close()
765
766    def testReadStored(self):
767        for f in (TESTFN2, TemporaryFile(), StringIO()):
768            self.readTest(f, zipfile.ZIP_STORED)
769
770    def testReadlineStored(self):
771        for f in (TESTFN2, TemporaryFile(), StringIO()):
772            self.readlineTest(f, zipfile.ZIP_STORED)
773
774    def testReadlinesStored(self):
775        for f in (TESTFN2, TemporaryFile(), StringIO()):
776            self.readlinesTest(f, zipfile.ZIP_STORED)
777
778    def testIterlinesStored(self):
779        for f in (TESTFN2, TemporaryFile(), StringIO()):
780            self.iterlinesTest(f, zipfile.ZIP_STORED)
781
782    if zlib:
783        def testReadDeflated(self):
784            for f in (TESTFN2, TemporaryFile(), StringIO()):
785                self.readTest(f, zipfile.ZIP_DEFLATED)
786
787        def testReadlineDeflated(self):
788            for f in (TESTFN2, TemporaryFile(), StringIO()):
789                self.readlineTest(f, zipfile.ZIP_DEFLATED)
790
791        def testReadlinesDeflated(self):
792            for f in (TESTFN2, TemporaryFile(), StringIO()):
793                self.readlinesTest(f, zipfile.ZIP_DEFLATED)
794
795        def testIterlinesDeflated(self):
796            for f in (TESTFN2, TemporaryFile(), StringIO()):
797                self.iterlinesTest(f, zipfile.ZIP_DEFLATED)
798
799    def tearDown(self):
800        for sep, fn in self.arcfiles.items():
801            os.remove(fn)
802
803
804def test_main():
805    run_unittest(TestsWithSourceFile, TestZip64InSmallFiles, OtherTests,
806                 PyZipFileTests, DecryptionTests, TestsWithMultipleOpens,
807                 UniversalNewlineTests, TestsWithRandomBinaryFiles)
808
809    #run_unittest(TestZip64InSmallFiles)
810
811if __name__ == "__main__":
812    test_main()
813