ddd713f974c01395b181cad4e58f575a9681756c
[profile/ivi/python.git] / Lib / test / test_zipfile.py
1 # We can test part of the module without zlib.
2 try:
3     import zlib
4 except ImportError:
5     zlib = None
6
7 import os
8 import io
9 import sys
10 import time
11 import shutil
12 import struct
13 import zipfile
14 import unittest
15
16 from StringIO import StringIO
17 from tempfile import TemporaryFile
18 from random import randint, random
19 from unittest import skipUnless
20
21 from test.test_support import TESTFN, run_unittest, findfile, unlink
22
23 TESTFN2 = TESTFN + "2"
24 TESTFNDIR = TESTFN + "d"
25 FIXEDTEST_SIZE = 1000
26
27 SMALL_TEST_DATA = [('_ziptest1', '1q2w3e4r5t'),
28                    ('ziptest2dir/_ziptest2', 'qawsedrftg'),
29                    ('/ziptest2dir/ziptest3dir/_ziptest3', 'azsxdcfvgb'),
30                    ('ziptest2dir/ziptest3dir/ziptest4dir/_ziptest3', '6y7u8i9o0p')]
31
32
33 class TestsWithSourceFile(unittest.TestCase):
34     def setUp(self):
35         self.line_gen = ["Zipfile test line %d. random float: %f" % (i, random())
36                          for i in xrange(FIXEDTEST_SIZE)]
37         self.data = '\n'.join(self.line_gen) + '\n'
38
39         # Make a source file with some lines
40         with open(TESTFN, "wb") as fp:
41             fp.write(self.data)
42
43     def make_test_archive(self, f, compression):
44         # Create the ZIP archive
45         with zipfile.ZipFile(f, "w", compression) as zipfp:
46             zipfp.write(TESTFN, "another.name")
47             zipfp.write(TESTFN, TESTFN)
48             zipfp.writestr("strfile", self.data)
49
50     def zip_test(self, f, compression):
51         self.make_test_archive(f, compression)
52
53         # Read the ZIP archive
54         with zipfile.ZipFile(f, "r", compression) as zipfp:
55             self.assertEqual(zipfp.read(TESTFN), self.data)
56             self.assertEqual(zipfp.read("another.name"), self.data)
57             self.assertEqual(zipfp.read("strfile"), self.data)
58
59             # Print the ZIP directory
60             fp = StringIO()
61             stdout = sys.stdout
62             try:
63                 sys.stdout = fp
64                 zipfp.printdir()
65             finally:
66                 sys.stdout = stdout
67
68             directory = fp.getvalue()
69             lines = directory.splitlines()
70             self.assertEqual(len(lines), 4) # Number of files + header
71
72             self.assertIn('File Name', lines[0])
73             self.assertIn('Modified', lines[0])
74             self.assertIn('Size', lines[0])
75
76             fn, date, time_, size = lines[1].split()
77             self.assertEqual(fn, 'another.name')
78             self.assertTrue(time.strptime(date, '%Y-%m-%d'))
79             self.assertTrue(time.strptime(time_, '%H:%M:%S'))
80             self.assertEqual(size, str(len(self.data)))
81
82             # Check the namelist
83             names = zipfp.namelist()
84             self.assertEqual(len(names), 3)
85             self.assertIn(TESTFN, names)
86             self.assertIn("another.name", names)
87             self.assertIn("strfile", names)
88
89             # Check infolist
90             infos = zipfp.infolist()
91             names = [i.filename for i in infos]
92             self.assertEqual(len(names), 3)
93             self.assertIn(TESTFN, names)
94             self.assertIn("another.name", names)
95             self.assertIn("strfile", names)
96             for i in infos:
97                 self.assertEqual(i.file_size, len(self.data))
98
99             # check getinfo
100             for nm in (TESTFN, "another.name", "strfile"):
101                 info = zipfp.getinfo(nm)
102                 self.assertEqual(info.filename, nm)
103                 self.assertEqual(info.file_size, len(self.data))
104
105             # Check that testzip doesn't raise an exception
106             zipfp.testzip()
107
108     def test_stored(self):
109         for f in (TESTFN2, TemporaryFile(), StringIO()):
110             self.zip_test(f, zipfile.ZIP_STORED)
111
112     def zip_open_test(self, f, compression):
113         self.make_test_archive(f, compression)
114
115         # Read the ZIP archive
116         with zipfile.ZipFile(f, "r", compression) as zipfp:
117             zipdata1 = []
118             zipopen1 = zipfp.open(TESTFN)
119             while True:
120                 read_data = zipopen1.read(256)
121                 if not read_data:
122                     break
123                 zipdata1.append(read_data)
124
125             zipdata2 = []
126             zipopen2 = zipfp.open("another.name")
127             while True:
128                 read_data = zipopen2.read(256)
129                 if not read_data:
130                     break
131                 zipdata2.append(read_data)
132
133             self.assertEqual(''.join(zipdata1), self.data)
134             self.assertEqual(''.join(zipdata2), self.data)
135
136     def test_open_stored(self):
137         for f in (TESTFN2, TemporaryFile(), StringIO()):
138             self.zip_open_test(f, zipfile.ZIP_STORED)
139
140     def test_open_via_zip_info(self):
141         # Create the ZIP archive
142         with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) as zipfp:
143             zipfp.writestr("name", "foo")
144             zipfp.writestr("name", "bar")
145
146         with zipfile.ZipFile(TESTFN2, "r") as zipfp:
147             infos = zipfp.infolist()
148             data = ""
149             for info in infos:
150                 data += zipfp.open(info).read()
151             self.assertTrue(data == "foobar" or data == "barfoo")
152             data = ""
153             for info in infos:
154                 data += zipfp.read(info)
155             self.assertTrue(data == "foobar" or data == "barfoo")
156
157     def zip_random_open_test(self, f, compression):
158         self.make_test_archive(f, compression)
159
160         # Read the ZIP archive
161         with zipfile.ZipFile(f, "r", compression) as zipfp:
162             zipdata1 = []
163             zipopen1 = zipfp.open(TESTFN)
164             while True:
165                 read_data = zipopen1.read(randint(1, 1024))
166                 if not read_data:
167                     break
168                 zipdata1.append(read_data)
169
170             self.assertEqual(''.join(zipdata1), self.data)
171
172     def test_random_open_stored(self):
173         for f in (TESTFN2, TemporaryFile(), StringIO()):
174             self.zip_random_open_test(f, zipfile.ZIP_STORED)
175
176     def test_univeral_readaheads(self):
177         f = StringIO()
178
179         data = 'a\r\n' * 16 * 1024
180         zipfp = zipfile.ZipFile(f, 'w', zipfile.ZIP_STORED)
181         zipfp.writestr(TESTFN, data)
182         zipfp.close()
183
184         data2 = ''
185         zipfp = zipfile.ZipFile(f, 'r')
186         zipopen = zipfp.open(TESTFN, 'rU')
187         for line in zipopen:
188             data2 += line
189         zipfp.close()
190
191         self.assertEqual(data, data2.replace('\n', '\r\n'))
192
193     def zip_readline_read_test(self, f, compression):
194         self.make_test_archive(f, compression)
195
196         # Read the ZIP archive
197         zipfp = zipfile.ZipFile(f, "r")
198         zipopen = zipfp.open(TESTFN)
199
200         data = ''
201         while True:
202             read = zipopen.readline()
203             if not read:
204                 break
205             data += read
206
207             read = zipopen.read(100)
208             if not read:
209                 break
210             data += read
211
212         self.assertEqual(data, self.data)
213         zipfp.close()
214
215     def zip_readline_test(self, f, compression):
216         self.make_test_archive(f, compression)
217
218         # Read the ZIP archive
219         with zipfile.ZipFile(f, "r") as zipfp:
220             zipopen = zipfp.open(TESTFN)
221             for line in self.line_gen:
222                 linedata = zipopen.readline()
223                 self.assertEqual(linedata, line + '\n')
224
225     def zip_readlines_test(self, f, compression):
226         self.make_test_archive(f, compression)
227
228         # Read the ZIP archive
229         with zipfile.ZipFile(f, "r") as zipfp:
230             ziplines = zipfp.open(TESTFN).readlines()
231             for line, zipline in zip(self.line_gen, ziplines):
232                 self.assertEqual(zipline, line + '\n')
233
234     def zip_iterlines_test(self, f, compression):
235         self.make_test_archive(f, compression)
236
237         # Read the ZIP archive
238         with zipfile.ZipFile(f, "r") as zipfp:
239             for line, zipline in zip(self.line_gen, zipfp.open(TESTFN)):
240                 self.assertEqual(zipline, line + '\n')
241
242     def test_readline_read_stored(self):
243         # Issue #7610: calls to readline() interleaved with calls to read().
244         for f in (TESTFN2, TemporaryFile(), StringIO()):
245             self.zip_readline_read_test(f, zipfile.ZIP_STORED)
246
247     def test_readline_stored(self):
248         for f in (TESTFN2, TemporaryFile(), StringIO()):
249             self.zip_readline_test(f, zipfile.ZIP_STORED)
250
251     def test_readlines_stored(self):
252         for f in (TESTFN2, TemporaryFile(), StringIO()):
253             self.zip_readlines_test(f, zipfile.ZIP_STORED)
254
255     def test_iterlines_stored(self):
256         for f in (TESTFN2, TemporaryFile(), StringIO()):
257             self.zip_iterlines_test(f, zipfile.ZIP_STORED)
258
259     @skipUnless(zlib, "requires zlib")
260     def test_deflated(self):
261         for f in (TESTFN2, TemporaryFile(), StringIO()):
262             self.zip_test(f, zipfile.ZIP_DEFLATED)
263
264     @skipUnless(zlib, "requires zlib")
265     def test_open_deflated(self):
266         for f in (TESTFN2, TemporaryFile(), StringIO()):
267             self.zip_open_test(f, zipfile.ZIP_DEFLATED)
268
269     @skipUnless(zlib, "requires zlib")
270     def test_random_open_deflated(self):
271         for f in (TESTFN2, TemporaryFile(), StringIO()):
272             self.zip_random_open_test(f, zipfile.ZIP_DEFLATED)
273
274     @skipUnless(zlib, "requires zlib")
275     def test_readline_read_deflated(self):
276         # Issue #7610: calls to readline() interleaved with calls to read().
277         for f in (TESTFN2, TemporaryFile(), StringIO()):
278             self.zip_readline_read_test(f, zipfile.ZIP_DEFLATED)
279
280     @skipUnless(zlib, "requires zlib")
281     def test_readline_deflated(self):
282         for f in (TESTFN2, TemporaryFile(), StringIO()):
283             self.zip_readline_test(f, zipfile.ZIP_DEFLATED)
284
285     @skipUnless(zlib, "requires zlib")
286     def test_readlines_deflated(self):
287         for f in (TESTFN2, TemporaryFile(), StringIO()):
288             self.zip_readlines_test(f, zipfile.ZIP_DEFLATED)
289
290     @skipUnless(zlib, "requires zlib")
291     def test_iterlines_deflated(self):
292         for f in (TESTFN2, TemporaryFile(), StringIO()):
293             self.zip_iterlines_test(f, zipfile.ZIP_DEFLATED)
294
295     @skipUnless(zlib, "requires zlib")
296     def test_low_compression(self):
297         """Check for cases where compressed data is larger than original."""
298         # Create the ZIP archive
299         with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_DEFLATED) as zipfp:
300             zipfp.writestr("strfile", '12')
301
302         # Get an open object for strfile
303         with zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_DEFLATED) as zipfp:
304             openobj = zipfp.open("strfile")
305             self.assertEqual(openobj.read(1), '1')
306             self.assertEqual(openobj.read(1), '2')
307
308     def test_absolute_arcnames(self):
309         with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) as zipfp:
310             zipfp.write(TESTFN, "/absolute")
311
312         with zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_STORED) as zipfp:
313             self.assertEqual(zipfp.namelist(), ["absolute"])
314
315     def test_append_to_zip_file(self):
316         """Test appending to an existing zipfile."""
317         with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) as zipfp:
318             zipfp.write(TESTFN, TESTFN)
319
320         with zipfile.ZipFile(TESTFN2, "a", zipfile.ZIP_STORED) as zipfp:
321             zipfp.writestr("strfile", self.data)
322             self.assertEqual(zipfp.namelist(), [TESTFN, "strfile"])
323
324     def test_append_to_non_zip_file(self):
325         """Test appending to an existing file that is not a zipfile."""
326         # NOTE: this test fails if len(d) < 22 because of the first
327         # line "fpin.seek(-22, 2)" in _EndRecData
328         data = 'I am not a ZipFile!'*10
329         with open(TESTFN2, 'wb') as f:
330             f.write(data)
331
332         with zipfile.ZipFile(TESTFN2, "a", zipfile.ZIP_STORED) as zipfp:
333             zipfp.write(TESTFN, TESTFN)
334
335         with open(TESTFN2, 'rb') as f:
336             f.seek(len(data))
337             with zipfile.ZipFile(f, "r") as zipfp:
338                 self.assertEqual(zipfp.namelist(), [TESTFN])
339
340     def test_write_default_name(self):
341         """Check that calling ZipFile.write without arcname specified
342         produces the expected result."""
343         with zipfile.ZipFile(TESTFN2, "w") as zipfp:
344             zipfp.write(TESTFN)
345             self.assertEqual(zipfp.read(TESTFN), open(TESTFN).read())
346
347     @skipUnless(zlib, "requires zlib")
348     def test_per_file_compression(self):
349         """Check that files within a Zip archive can have different
350         compression options."""
351         with zipfile.ZipFile(TESTFN2, "w") as zipfp:
352             zipfp.write(TESTFN, 'storeme', zipfile.ZIP_STORED)
353             zipfp.write(TESTFN, 'deflateme', zipfile.ZIP_DEFLATED)
354             sinfo = zipfp.getinfo('storeme')
355             dinfo = zipfp.getinfo('deflateme')
356             self.assertEqual(sinfo.compress_type, zipfile.ZIP_STORED)
357             self.assertEqual(dinfo.compress_type, zipfile.ZIP_DEFLATED)
358
359     def test_write_to_readonly(self):
360         """Check that trying to call write() on a readonly ZipFile object
361         raises a RuntimeError."""
362         with zipfile.ZipFile(TESTFN2, mode="w") as zipfp:
363             zipfp.writestr("somefile.txt", "bogus")
364
365         with zipfile.ZipFile(TESTFN2, mode="r") as zipfp:
366             self.assertRaises(RuntimeError, zipfp.write, TESTFN)
367
368     def test_extract(self):
369         with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) as zipfp:
370             for fpath, fdata in SMALL_TEST_DATA:
371                 zipfp.writestr(fpath, fdata)
372
373         with zipfile.ZipFile(TESTFN2, "r") as zipfp:
374             for fpath, fdata in SMALL_TEST_DATA:
375                 writtenfile = zipfp.extract(fpath)
376
377                 # make sure it was written to the right place
378                 if os.path.isabs(fpath):
379                     correctfile = os.path.join(os.getcwd(), fpath[1:])
380                 else:
381                     correctfile = os.path.join(os.getcwd(), fpath)
382                 correctfile = os.path.normpath(correctfile)
383
384                 self.assertEqual(writtenfile, correctfile)
385
386                 # make sure correct data is in correct file
387                 self.assertEqual(fdata, open(writtenfile, "rb").read())
388                 os.remove(writtenfile)
389
390         # remove the test file subdirectories
391         shutil.rmtree(os.path.join(os.getcwd(), 'ziptest2dir'))
392
393     def test_extract_all(self):
394         with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) as zipfp:
395             for fpath, fdata in SMALL_TEST_DATA:
396                 zipfp.writestr(fpath, fdata)
397
398         with zipfile.ZipFile(TESTFN2, "r") as zipfp:
399             zipfp.extractall()
400             for fpath, fdata in SMALL_TEST_DATA:
401                 if os.path.isabs(fpath):
402                     outfile = os.path.join(os.getcwd(), fpath[1:])
403                 else:
404                     outfile = os.path.join(os.getcwd(), fpath)
405
406                 self.assertEqual(fdata, open(outfile, "rb").read())
407                 os.remove(outfile)
408
409         # remove the test file subdirectories
410         shutil.rmtree(os.path.join(os.getcwd(), 'ziptest2dir'))
411
412     def test_writestr_compression(self):
413         zipfp = zipfile.ZipFile(TESTFN2, "w")
414         zipfp.writestr("a.txt", "hello world", compress_type=zipfile.ZIP_STORED)
415         if zlib:
416             zipfp.writestr("b.txt", "hello world", compress_type=zipfile.ZIP_DEFLATED)
417
418         info = zipfp.getinfo('a.txt')
419         self.assertEqual(info.compress_type, zipfile.ZIP_STORED)
420
421         if zlib:
422             info = zipfp.getinfo('b.txt')
423             self.assertEqual(info.compress_type, zipfile.ZIP_DEFLATED)
424
425
426     def zip_test_writestr_permissions(self, f, compression):
427         # Make sure that writestr creates files with mode 0600,
428         # when it is passed a name rather than a ZipInfo instance.
429
430         self.make_test_archive(f, compression)
431         with zipfile.ZipFile(f, "r") as zipfp:
432             zinfo = zipfp.getinfo('strfile')
433             self.assertEqual(zinfo.external_attr, 0600 << 16)
434
435     def test_writestr_permissions(self):
436         for f in (TESTFN2, TemporaryFile(), StringIO()):
437             self.zip_test_writestr_permissions(f, zipfile.ZIP_STORED)
438
439     def test_close(self):
440         """Check that the zipfile is closed after the 'with' block."""
441         with zipfile.ZipFile(TESTFN2, "w") as zipfp:
442             for fpath, fdata in SMALL_TEST_DATA:
443                 zipfp.writestr(fpath, fdata)
444                 self.assertTrue(zipfp.fp is not None, 'zipfp is not open')
445         self.assertTrue(zipfp.fp is None, 'zipfp is not closed')
446
447         with zipfile.ZipFile(TESTFN2, "r") as zipfp:
448             self.assertTrue(zipfp.fp is not None, 'zipfp is not open')
449         self.assertTrue(zipfp.fp is None, 'zipfp is not closed')
450
451     def test_close_on_exception(self):
452         """Check that the zipfile is closed if an exception is raised in the
453         'with' block."""
454         with zipfile.ZipFile(TESTFN2, "w") as zipfp:
455             for fpath, fdata in SMALL_TEST_DATA:
456                 zipfp.writestr(fpath, fdata)
457
458         try:
459             with zipfile.ZipFile(TESTFN2, "r") as zipfp2:
460                 raise zipfile.BadZipfile()
461         except zipfile.BadZipfile:
462             self.assertTrue(zipfp2.fp is None, 'zipfp is not closed')
463
464     def tearDown(self):
465         unlink(TESTFN)
466         unlink(TESTFN2)
467
468
469 class TestZip64InSmallFiles(unittest.TestCase):
470     # These tests test the ZIP64 functionality without using large files,
471     # see test_zipfile64 for proper tests.
472
473     def setUp(self):
474         self._limit = zipfile.ZIP64_LIMIT
475         zipfile.ZIP64_LIMIT = 5
476
477         line_gen = ("Test of zipfile line %d." % i
478                     for i in range(0, FIXEDTEST_SIZE))
479         self.data = '\n'.join(line_gen)
480
481         # Make a source file with some lines
482         with open(TESTFN, "wb") as fp:
483             fp.write(self.data)
484
485     def large_file_exception_test(self, f, compression):
486         with zipfile.ZipFile(f, "w", compression) as zipfp:
487             self.assertRaises(zipfile.LargeZipFile,
488                               zipfp.write, TESTFN, "another.name")
489
490     def large_file_exception_test2(self, f, compression):
491         with zipfile.ZipFile(f, "w", compression) as zipfp:
492             self.assertRaises(zipfile.LargeZipFile,
493                               zipfp.writestr, "another.name", self.data)
494
495     def test_large_file_exception(self):
496         for f in (TESTFN2, TemporaryFile(), StringIO()):
497             self.large_file_exception_test(f, zipfile.ZIP_STORED)
498             self.large_file_exception_test2(f, zipfile.ZIP_STORED)
499
500     def zip_test(self, f, compression):
501         # Create the ZIP archive
502         with zipfile.ZipFile(f, "w", compression, allowZip64=True) as zipfp:
503             zipfp.write(TESTFN, "another.name")
504             zipfp.write(TESTFN, TESTFN)
505             zipfp.writestr("strfile", self.data)
506
507         # Read the ZIP archive
508         with zipfile.ZipFile(f, "r", compression) as zipfp:
509             self.assertEqual(zipfp.read(TESTFN), self.data)
510             self.assertEqual(zipfp.read("another.name"), self.data)
511             self.assertEqual(zipfp.read("strfile"), self.data)
512
513             # Print the ZIP directory
514             fp = StringIO()
515             stdout = sys.stdout
516             try:
517                 sys.stdout = fp
518                 zipfp.printdir()
519             finally:
520                 sys.stdout = stdout
521
522             directory = fp.getvalue()
523             lines = directory.splitlines()
524             self.assertEqual(len(lines), 4) # Number of files + header
525
526             self.assertIn('File Name', lines[0])
527             self.assertIn('Modified', lines[0])
528             self.assertIn('Size', lines[0])
529
530             fn, date, time_, size = lines[1].split()
531             self.assertEqual(fn, 'another.name')
532             self.assertTrue(time.strptime(date, '%Y-%m-%d'))
533             self.assertTrue(time.strptime(time_, '%H:%M:%S'))
534             self.assertEqual(size, str(len(self.data)))
535
536             # Check the namelist
537             names = zipfp.namelist()
538             self.assertEqual(len(names), 3)
539             self.assertIn(TESTFN, names)
540             self.assertIn("another.name", names)
541             self.assertIn("strfile", names)
542
543             # Check infolist
544             infos = zipfp.infolist()
545             names = [i.filename for i in infos]
546             self.assertEqual(len(names), 3)
547             self.assertIn(TESTFN, names)
548             self.assertIn("another.name", names)
549             self.assertIn("strfile", names)
550             for i in infos:
551                 self.assertEqual(i.file_size, len(self.data))
552
553             # check getinfo
554             for nm in (TESTFN, "another.name", "strfile"):
555                 info = zipfp.getinfo(nm)
556                 self.assertEqual(info.filename, nm)
557                 self.assertEqual(info.file_size, len(self.data))
558
559             # Check that testzip doesn't raise an exception
560             zipfp.testzip()
561
562     def test_stored(self):
563         for f in (TESTFN2, TemporaryFile(), StringIO()):
564             self.zip_test(f, zipfile.ZIP_STORED)
565
566     @skipUnless(zlib, "requires zlib")
567     def test_deflated(self):
568         for f in (TESTFN2, TemporaryFile(), StringIO()):
569             self.zip_test(f, zipfile.ZIP_DEFLATED)
570
571     def test_absolute_arcnames(self):
572         with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED,
573                              allowZip64=True) as zipfp:
574             zipfp.write(TESTFN, "/absolute")
575
576         with zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_STORED) as zipfp:
577             self.assertEqual(zipfp.namelist(), ["absolute"])
578
579     def tearDown(self):
580         zipfile.ZIP64_LIMIT = self._limit
581         unlink(TESTFN)
582         unlink(TESTFN2)
583
584
585 class PyZipFileTests(unittest.TestCase):
586     def test_write_pyfile(self):
587         with zipfile.PyZipFile(TemporaryFile(), "w") as zipfp:
588             fn = __file__
589             if fn.endswith('.pyc') or fn.endswith('.pyo'):
590                 fn = fn[:-1]
591
592             zipfp.writepy(fn)
593
594             bn = os.path.basename(fn)
595             self.assertNotIn(bn, zipfp.namelist())
596             self.assertTrue(bn + 'o' in zipfp.namelist() or
597                             bn + 'c' in zipfp.namelist())
598
599         with zipfile.PyZipFile(TemporaryFile(), "w") as zipfp:
600             fn = __file__
601             if fn.endswith(('.pyc', '.pyo')):
602                 fn = fn[:-1]
603
604             zipfp.writepy(fn, "testpackage")
605
606             bn = "%s/%s" % ("testpackage", os.path.basename(fn))
607             self.assertNotIn(bn, zipfp.namelist())
608             self.assertTrue(bn + 'o' in zipfp.namelist() or
609                             bn + 'c' in zipfp.namelist())
610
611     def test_write_python_package(self):
612         import email
613         packagedir = os.path.dirname(email.__file__)
614
615         with zipfile.PyZipFile(TemporaryFile(), "w") as zipfp:
616             zipfp.writepy(packagedir)
617
618             # Check for a couple of modules at different levels of the
619             # hierarchy
620             names = zipfp.namelist()
621             self.assertTrue('email/__init__.pyo' in names or
622                             'email/__init__.pyc' in names)
623             self.assertTrue('email/mime/text.pyo' in names or
624                             'email/mime/text.pyc' in names)
625
626     def test_write_python_directory(self):
627         os.mkdir(TESTFN2)
628         try:
629             with open(os.path.join(TESTFN2, "mod1.py"), "w") as fp:
630                 fp.write("print(42)\n")
631
632             with open(os.path.join(TESTFN2, "mod2.py"), "w") as fp:
633                 fp.write("print(42 * 42)\n")
634
635             with open(os.path.join(TESTFN2, "mod2.txt"), "w") as fp:
636                 fp.write("bla bla bla\n")
637
638             zipfp  = zipfile.PyZipFile(TemporaryFile(), "w")
639             zipfp.writepy(TESTFN2)
640
641             names = zipfp.namelist()
642             self.assertTrue('mod1.pyc' in names or 'mod1.pyo' in names)
643             self.assertTrue('mod2.pyc' in names or 'mod2.pyo' in names)
644             self.assertNotIn('mod2.txt', names)
645
646         finally:
647             shutil.rmtree(TESTFN2)
648
649     def test_write_non_pyfile(self):
650         with zipfile.PyZipFile(TemporaryFile(), "w") as zipfp:
651             open(TESTFN, 'w').write('most definitely not a python file')
652             self.assertRaises(RuntimeError, zipfp.writepy, TESTFN)
653             os.remove(TESTFN)
654
655
656 class OtherTests(unittest.TestCase):
657     zips_with_bad_crc = {
658         zipfile.ZIP_STORED: (
659             b'PK\003\004\024\0\0\0\0\0 \213\212;:r'
660             b'\253\377\f\0\0\0\f\0\0\0\005\0\0\000af'
661             b'ilehello,AworldP'
662             b'K\001\002\024\003\024\0\0\0\0\0 \213\212;:'
663             b'r\253\377\f\0\0\0\f\0\0\0\005\0\0\0\0'
664             b'\0\0\0\0\0\0\0\200\001\0\0\0\000afi'
665             b'lePK\005\006\0\0\0\0\001\0\001\0003\000'
666             b'\0\0/\0\0\0\0\0'),
667         zipfile.ZIP_DEFLATED: (
668             b'PK\x03\x04\x14\x00\x00\x00\x08\x00n}\x0c=FA'
669             b'KE\x10\x00\x00\x00n\x00\x00\x00\x05\x00\x00\x00af'
670             b'ile\xcbH\xcd\xc9\xc9W(\xcf/\xcaI\xc9\xa0'
671             b'=\x13\x00PK\x01\x02\x14\x03\x14\x00\x00\x00\x08\x00n'
672             b'}\x0c=FAKE\x10\x00\x00\x00n\x00\x00\x00\x05'
673             b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\x00'
674             b'\x00afilePK\x05\x06\x00\x00\x00\x00\x01\x00'
675             b'\x01\x003\x00\x00\x003\x00\x00\x00\x00\x00'),
676     }
677
678     def test_unicode_filenames(self):
679         with zipfile.ZipFile(TESTFN, "w") as zf:
680             zf.writestr(u"foo.txt", "Test for unicode filename")
681             zf.writestr(u"\xf6.txt", "Test for unicode filename")
682             self.assertIsInstance(zf.infolist()[0].filename, unicode)
683
684         with zipfile.ZipFile(TESTFN, "r") as zf:
685             self.assertEqual(zf.filelist[0].filename, "foo.txt")
686             self.assertEqual(zf.filelist[1].filename, u"\xf6.txt")
687
688     def test_create_non_existent_file_for_append(self):
689         if os.path.exists(TESTFN):
690             os.unlink(TESTFN)
691
692         filename = 'testfile.txt'
693         content = 'hello, world. this is some content.'
694
695         try:
696             with zipfile.ZipFile(TESTFN, 'a') as zf:
697                 zf.writestr(filename, content)
698         except IOError:
699             self.fail('Could not append data to a non-existent zip file.')
700
701         self.assertTrue(os.path.exists(TESTFN))
702
703         with zipfile.ZipFile(TESTFN, 'r') as zf:
704             self.assertEqual(zf.read(filename), content)
705
706     def test_close_erroneous_file(self):
707         # This test checks that the ZipFile constructor closes the file object
708         # it opens if there's an error in the file.  If it doesn't, the
709         # traceback holds a reference to the ZipFile object and, indirectly,
710         # the file object.
711         # On Windows, this causes the os.unlink() call to fail because the
712         # underlying file is still open.  This is SF bug #412214.
713         #
714         with open(TESTFN, "w") as fp:
715             fp.write("this is not a legal zip file\n")
716         try:
717             zf = zipfile.ZipFile(TESTFN)
718         except zipfile.BadZipfile:
719             pass
720
721     def test_is_zip_erroneous_file(self):
722         """Check that is_zipfile() correctly identifies non-zip files."""
723         # - passing a filename
724         with open(TESTFN, "w") as fp:
725             fp.write("this is not a legal zip file\n")
726         chk = zipfile.is_zipfile(TESTFN)
727         self.assertFalse(chk)
728         # - passing a file object
729         with open(TESTFN, "rb") as fp:
730             chk = zipfile.is_zipfile(fp)
731             self.assertTrue(not chk)
732         # - passing a file-like object
733         fp = StringIO()
734         fp.write("this is not a legal zip file\n")
735         chk = zipfile.is_zipfile(fp)
736         self.assertTrue(not chk)
737         fp.seek(0, 0)
738         chk = zipfile.is_zipfile(fp)
739         self.assertTrue(not chk)
740
741     def test_is_zip_valid_file(self):
742         """Check that is_zipfile() correctly identifies zip files."""
743         # - passing a filename
744         with zipfile.ZipFile(TESTFN, mode="w") as zipf:
745             zipf.writestr("foo.txt", "O, for a Muse of Fire!")
746         chk = zipfile.is_zipfile(TESTFN)
747         self.assertTrue(chk)
748         # - passing a file object
749         with open(TESTFN, "rb") as fp:
750             chk = zipfile.is_zipfile(fp)
751             self.assertTrue(chk)
752             fp.seek(0, 0)
753             zip_contents = fp.read()
754         # - passing a file-like object
755         fp = StringIO()
756         fp.write(zip_contents)
757         chk = zipfile.is_zipfile(fp)
758         self.assertTrue(chk)
759         fp.seek(0, 0)
760         chk = zipfile.is_zipfile(fp)
761         self.assertTrue(chk)
762
763     def test_non_existent_file_raises_IOError(self):
764         # make sure we don't raise an AttributeError when a partially-constructed
765         # ZipFile instance is finalized; this tests for regression on SF tracker
766         # bug #403871.
767
768         # The bug we're testing for caused an AttributeError to be raised
769         # when a ZipFile instance was created for a file that did not
770         # exist; the .fp member was not initialized but was needed by the
771         # __del__() method.  Since the AttributeError is in the __del__(),
772         # it is ignored, but the user should be sufficiently annoyed by
773         # the message on the output that regression will be noticed
774         # quickly.
775         self.assertRaises(IOError, zipfile.ZipFile, TESTFN)
776
777     def test_empty_file_raises_BadZipFile(self):
778         f = open(TESTFN, 'w')
779         f.close()
780         self.assertRaises(zipfile.BadZipfile, zipfile.ZipFile, TESTFN)
781
782         with open(TESTFN, 'w') as fp:
783             fp.write("short file")
784         self.assertRaises(zipfile.BadZipfile, zipfile.ZipFile, TESTFN)
785
786     def test_closed_zip_raises_RuntimeError(self):
787         """Verify that testzip() doesn't swallow inappropriate exceptions."""
788         data = StringIO()
789         with zipfile.ZipFile(data, mode="w") as zipf:
790             zipf.writestr("foo.txt", "O, for a Muse of Fire!")
791
792         # This is correct; calling .read on a closed ZipFile should throw
793         # a RuntimeError, and so should calling .testzip.  An earlier
794         # version of .testzip would swallow this exception (and any other)
795         # and report that the first file in the archive was corrupt.
796         self.assertRaises(RuntimeError, zipf.read, "foo.txt")
797         self.assertRaises(RuntimeError, zipf.open, "foo.txt")
798         self.assertRaises(RuntimeError, zipf.testzip)
799         self.assertRaises(RuntimeError, zipf.writestr, "bogus.txt", "bogus")
800         open(TESTFN, 'w').write('zipfile test data')
801         self.assertRaises(RuntimeError, zipf.write, TESTFN)
802
803     def test_bad_constructor_mode(self):
804         """Check that bad modes passed to ZipFile constructor are caught."""
805         self.assertRaises(RuntimeError, zipfile.ZipFile, TESTFN, "q")
806
807     def test_bad_open_mode(self):
808         """Check that bad modes passed to ZipFile.open are caught."""
809         with zipfile.ZipFile(TESTFN, mode="w") as zipf:
810             zipf.writestr("foo.txt", "O, for a Muse of Fire!")
811
812         with zipfile.ZipFile(TESTFN, mode="r") as zipf:
813         # read the data to make sure the file is there
814             zipf.read("foo.txt")
815             self.assertRaises(RuntimeError, zipf.open, "foo.txt", "q")
816
817     def test_read0(self):
818         """Check that calling read(0) on a ZipExtFile object returns an empty
819         string and doesn't advance file pointer."""
820         with zipfile.ZipFile(TESTFN, mode="w") as zipf:
821             zipf.writestr("foo.txt", "O, for a Muse of Fire!")
822             # read the data to make sure the file is there
823             f = zipf.open("foo.txt")
824             for i in xrange(FIXEDTEST_SIZE):
825                 self.assertEqual(f.read(0), '')
826
827             self.assertEqual(f.read(), "O, for a Muse of Fire!")
828
829     def test_open_non_existent_item(self):
830         """Check that attempting to call open() for an item that doesn't
831         exist in the archive raises a RuntimeError."""
832         with zipfile.ZipFile(TESTFN, mode="w") as zipf:
833             self.assertRaises(KeyError, zipf.open, "foo.txt", "r")
834
835     def test_bad_compression_mode(self):
836         """Check that bad compression methods passed to ZipFile.open are
837         caught."""
838         self.assertRaises(RuntimeError, zipfile.ZipFile, TESTFN, "w", -1)
839
840     def test_null_byte_in_filename(self):
841         """Check that a filename containing a null byte is properly
842         terminated."""
843         with zipfile.ZipFile(TESTFN, mode="w") as zipf:
844             zipf.writestr("foo.txt\x00qqq", "O, for a Muse of Fire!")
845             self.assertEqual(zipf.namelist(), ['foo.txt'])
846
847     def test_struct_sizes(self):
848         """Check that ZIP internal structure sizes are calculated correctly."""
849         self.assertEqual(zipfile.sizeEndCentDir, 22)
850         self.assertEqual(zipfile.sizeCentralDir, 46)
851         self.assertEqual(zipfile.sizeEndCentDir64, 56)
852         self.assertEqual(zipfile.sizeEndCentDir64Locator, 20)
853
854     def test_comments(self):
855         """Check that comments on the archive are handled properly."""
856
857         # check default comment is empty
858         with zipfile.ZipFile(TESTFN, mode="w") as zipf:
859             self.assertEqual(zipf.comment, '')
860             zipf.writestr("foo.txt", "O, for a Muse of Fire!")
861
862         with zipfile.ZipFile(TESTFN, mode="r") as zipf:
863             self.assertEqual(zipf.comment, '')
864
865         # check a simple short comment
866         comment = 'Bravely taking to his feet, he beat a very brave retreat.'
867         with zipfile.ZipFile(TESTFN, mode="w") as zipf:
868             zipf.comment = comment
869             zipf.writestr("foo.txt", "O, for a Muse of Fire!")
870         with zipfile.ZipFile(TESTFN, mode="r") as zipf:
871             self.assertEqual(zipf.comment, comment)
872
873         # check a comment of max length
874         comment2 = ''.join(['%d' % (i**3 % 10) for i in xrange((1 << 16)-1)])
875         with zipfile.ZipFile(TESTFN, mode="w") as zipf:
876             zipf.comment = comment2
877             zipf.writestr("foo.txt", "O, for a Muse of Fire!")
878
879         with zipfile.ZipFile(TESTFN, mode="r") as zipf:
880             self.assertEqual(zipf.comment, comment2)
881
882         # check a comment that is too long is truncated
883         with zipfile.ZipFile(TESTFN, mode="w") as zipf:
884             zipf.comment = comment2 + 'oops'
885             zipf.writestr("foo.txt", "O, for a Muse of Fire!")
886         with zipfile.ZipFile(TESTFN, mode="r") as zipf:
887             self.assertEqual(zipf.comment, comment2)
888
889     def check_testzip_with_bad_crc(self, compression):
890         """Tests that files with bad CRCs return their name from testzip."""
891         zipdata = self.zips_with_bad_crc[compression]
892
893         with zipfile.ZipFile(io.BytesIO(zipdata), mode="r") as zipf:
894             # testzip returns the name of the first corrupt file, or None
895             self.assertEqual('afile', zipf.testzip())
896
897     def test_testzip_with_bad_crc_stored(self):
898         self.check_testzip_with_bad_crc(zipfile.ZIP_STORED)
899
900     @skipUnless(zlib, "requires zlib")
901     def test_testzip_with_bad_crc_deflated(self):
902         self.check_testzip_with_bad_crc(zipfile.ZIP_DEFLATED)
903
904     def check_read_with_bad_crc(self, compression):
905         """Tests that files with bad CRCs raise a BadZipfile exception when read."""
906         zipdata = self.zips_with_bad_crc[compression]
907
908         # Using ZipFile.read()
909         with zipfile.ZipFile(io.BytesIO(zipdata), mode="r") as zipf:
910             self.assertRaises(zipfile.BadZipfile, zipf.read, 'afile')
911
912         # Using ZipExtFile.read()
913         with zipfile.ZipFile(io.BytesIO(zipdata), mode="r") as zipf:
914             with zipf.open('afile', 'r') as corrupt_file:
915                 self.assertRaises(zipfile.BadZipfile, corrupt_file.read)
916
917         # Same with small reads (in order to exercise the buffering logic)
918         with zipfile.ZipFile(io.BytesIO(zipdata), mode="r") as zipf:
919             with zipf.open('afile', 'r') as corrupt_file:
920                 corrupt_file.MIN_READ_SIZE = 2
921                 with self.assertRaises(zipfile.BadZipfile):
922                     while corrupt_file.read(2):
923                         pass
924
925     def test_read_with_bad_crc_stored(self):
926         self.check_read_with_bad_crc(zipfile.ZIP_STORED)
927
928     @skipUnless(zlib, "requires zlib")
929     def test_read_with_bad_crc_deflated(self):
930         self.check_read_with_bad_crc(zipfile.ZIP_DEFLATED)
931
932     def check_read_return_size(self, compression):
933         # Issue #9837: ZipExtFile.read() shouldn't return more bytes
934         # than requested.
935         for test_size in (1, 4095, 4096, 4097, 16384):
936             file_size = test_size + 1
937             junk = b''.join(struct.pack('B', randint(0, 255))
938                             for x in range(file_size))
939             with zipfile.ZipFile(io.BytesIO(), "w", compression) as zipf:
940                 zipf.writestr('foo', junk)
941                 with zipf.open('foo', 'r') as fp:
942                     buf = fp.read(test_size)
943                     self.assertEqual(len(buf), test_size)
944
945     def test_read_return_size_stored(self):
946         self.check_read_return_size(zipfile.ZIP_STORED)
947
948     @skipUnless(zlib, "requires zlib")
949     def test_read_return_size_deflated(self):
950         self.check_read_return_size(zipfile.ZIP_DEFLATED)
951
952     def test_empty_zipfile(self):
953         # Check that creating a file in 'w' or 'a' mode and closing without
954         # adding any files to the archives creates a valid empty ZIP file
955         zipf = zipfile.ZipFile(TESTFN, mode="w")
956         zipf.close()
957         try:
958             zipf = zipfile.ZipFile(TESTFN, mode="r")
959         except zipfile.BadZipFile:
960             self.fail("Unable to create empty ZIP file in 'w' mode")
961
962         zipf = zipfile.ZipFile(TESTFN, mode="a")
963         zipf.close()
964         try:
965             zipf = zipfile.ZipFile(TESTFN, mode="r")
966         except:
967             self.fail("Unable to create empty ZIP file in 'a' mode")
968
969     def test_open_empty_file(self):
970         # Issue 1710703: Check that opening a file with less than 22 bytes
971         # raises a BadZipfile exception (rather than the previously unhelpful
972         # IOError)
973         f = open(TESTFN, 'w')
974         f.close()
975         self.assertRaises(zipfile.BadZipfile, zipfile.ZipFile, TESTFN, 'r')
976
977     def tearDown(self):
978         unlink(TESTFN)
979         unlink(TESTFN2)
980
981
982 class DecryptionTests(unittest.TestCase):
983     """Check that ZIP decryption works. Since the library does not
984     support encryption at the moment, we use a pre-generated encrypted
985     ZIP file."""
986
987     data = (
988     'PK\x03\x04\x14\x00\x01\x00\x00\x00n\x92i.#y\xef?&\x00\x00\x00\x1a\x00'
989     '\x00\x00\x08\x00\x00\x00test.txt\xfa\x10\xa0gly|\xfa-\xc5\xc0=\xf9y'
990     '\x18\xe0\xa8r\xb3Z}Lg\xbc\xae\xf9|\x9b\x19\xe4\x8b\xba\xbb)\x8c\xb0\xdbl'
991     'PK\x01\x02\x14\x00\x14\x00\x01\x00\x00\x00n\x92i.#y\xef?&\x00\x00\x00'
992     '\x1a\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x01\x00 \x00\xb6\x81'
993     '\x00\x00\x00\x00test.txtPK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x006\x00'
994     '\x00\x00L\x00\x00\x00\x00\x00' )
995     data2 = (
996     'PK\x03\x04\x14\x00\t\x00\x08\x00\xcf}38xu\xaa\xb2\x14\x00\x00\x00\x00\x02'
997     '\x00\x00\x04\x00\x15\x00zeroUT\t\x00\x03\xd6\x8b\x92G\xda\x8b\x92GUx\x04'
998     '\x00\xe8\x03\xe8\x03\xc7<M\xb5a\xceX\xa3Y&\x8b{oE\xd7\x9d\x8c\x98\x02\xc0'
999     'PK\x07\x08xu\xaa\xb2\x14\x00\x00\x00\x00\x02\x00\x00PK\x01\x02\x17\x03'
1000     '\x14\x00\t\x00\x08\x00\xcf}38xu\xaa\xb2\x14\x00\x00\x00\x00\x02\x00\x00'
1001     '\x04\x00\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x00ze'
1002     'roUT\x05\x00\x03\xd6\x8b\x92GUx\x00\x00PK\x05\x06\x00\x00\x00\x00\x01'
1003     '\x00\x01\x00?\x00\x00\x00[\x00\x00\x00\x00\x00' )
1004
1005     plain = 'zipfile.py encryption test'
1006     plain2 = '\x00'*512
1007
1008     def setUp(self):
1009         with open(TESTFN, "wb") as fp:
1010             fp.write(self.data)
1011         self.zip = zipfile.ZipFile(TESTFN, "r")
1012         with open(TESTFN2, "wb") as fp:
1013             fp.write(self.data2)
1014         self.zip2 = zipfile.ZipFile(TESTFN2, "r")
1015
1016     def tearDown(self):
1017         self.zip.close()
1018         os.unlink(TESTFN)
1019         self.zip2.close()
1020         os.unlink(TESTFN2)
1021
1022     def test_no_password(self):
1023         # Reading the encrypted file without password
1024         # must generate a RunTime exception
1025         self.assertRaises(RuntimeError, self.zip.read, "test.txt")
1026         self.assertRaises(RuntimeError, self.zip2.read, "zero")
1027
1028     def test_bad_password(self):
1029         self.zip.setpassword("perl")
1030         self.assertRaises(RuntimeError, self.zip.read, "test.txt")
1031         self.zip2.setpassword("perl")
1032         self.assertRaises(RuntimeError, self.zip2.read, "zero")
1033
1034     @skipUnless(zlib, "requires zlib")
1035     def test_good_password(self):
1036         self.zip.setpassword("python")
1037         self.assertEqual(self.zip.read("test.txt"), self.plain)
1038         self.zip2.setpassword("12345")
1039         self.assertEqual(self.zip2.read("zero"), self.plain2)
1040
1041
1042 class TestsWithRandomBinaryFiles(unittest.TestCase):
1043     def setUp(self):
1044         datacount = randint(16, 64)*1024 + randint(1, 1024)
1045         self.data = ''.join(struct.pack('<f', random()*randint(-1000, 1000))
1046                             for i in xrange(datacount))
1047
1048         # Make a source file with some lines
1049         with open(TESTFN, "wb") as fp:
1050             fp.write(self.data)
1051
1052     def tearDown(self):
1053         unlink(TESTFN)
1054         unlink(TESTFN2)
1055
1056     def make_test_archive(self, f, compression):
1057         # Create the ZIP archive
1058         with zipfile.ZipFile(f, "w", compression) as zipfp:
1059             zipfp.write(TESTFN, "another.name")
1060             zipfp.write(TESTFN, TESTFN)
1061
1062     def zip_test(self, f, compression):
1063         self.make_test_archive(f, compression)
1064
1065         # Read the ZIP archive
1066         with zipfile.ZipFile(f, "r", compression) as zipfp:
1067             testdata = zipfp.read(TESTFN)
1068             self.assertEqual(len(testdata), len(self.data))
1069             self.assertEqual(testdata, self.data)
1070             self.assertEqual(zipfp.read("another.name"), self.data)
1071
1072     def test_stored(self):
1073         for f in (TESTFN2, TemporaryFile(), StringIO()):
1074             self.zip_test(f, zipfile.ZIP_STORED)
1075
1076     @skipUnless(zlib, "requires zlib")
1077     def test_deflated(self):
1078         for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
1079             self.zip_test(f, zipfile.ZIP_DEFLATED)
1080
1081     def zip_open_test(self, f, compression):
1082         self.make_test_archive(f, compression)
1083
1084         # Read the ZIP archive
1085         with zipfile.ZipFile(f, "r", compression) as zipfp:
1086             zipdata1 = []
1087             zipopen1 = zipfp.open(TESTFN)
1088             while True:
1089                 read_data = zipopen1.read(256)
1090                 if not read_data:
1091                     break
1092                 zipdata1.append(read_data)
1093
1094             zipdata2 = []
1095             zipopen2 = zipfp.open("another.name")
1096             while True:
1097                 read_data = zipopen2.read(256)
1098                 if not read_data:
1099                     break
1100                 zipdata2.append(read_data)
1101
1102             testdata1 = ''.join(zipdata1)
1103             self.assertEqual(len(testdata1), len(self.data))
1104             self.assertEqual(testdata1, self.data)
1105
1106             testdata2 = ''.join(zipdata2)
1107             self.assertEqual(len(testdata2), len(self.data))
1108             self.assertEqual(testdata2, self.data)
1109
1110     def test_open_stored(self):
1111         for f in (TESTFN2, TemporaryFile(), StringIO()):
1112             self.zip_open_test(f, zipfile.ZIP_STORED)
1113
1114     @skipUnless(zlib, "requires zlib")
1115     def test_open_deflated(self):
1116         for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
1117             self.zip_open_test(f, zipfile.ZIP_DEFLATED)
1118
1119     def zip_random_open_test(self, f, compression):
1120         self.make_test_archive(f, compression)
1121
1122         # Read the ZIP archive
1123         with zipfile.ZipFile(f, "r", compression) as zipfp:
1124             zipdata1 = []
1125             zipopen1 = zipfp.open(TESTFN)
1126             while True:
1127                 read_data = zipopen1.read(randint(1, 1024))
1128                 if not read_data:
1129                     break
1130                 zipdata1.append(read_data)
1131
1132             testdata = ''.join(zipdata1)
1133             self.assertEqual(len(testdata), len(self.data))
1134             self.assertEqual(testdata, self.data)
1135
1136     def test_random_open_stored(self):
1137         for f in (TESTFN2, TemporaryFile(), StringIO()):
1138             self.zip_random_open_test(f, zipfile.ZIP_STORED)
1139
1140     @skipUnless(zlib, "requires zlib")
1141     def test_random_open_deflated(self):
1142         for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
1143             self.zip_random_open_test(f, zipfile.ZIP_DEFLATED)
1144
1145
1146 @skipUnless(zlib, "requires zlib")
1147 class TestsWithMultipleOpens(unittest.TestCase):
1148     def setUp(self):
1149         # Create the ZIP archive
1150         with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_DEFLATED) as zipfp:
1151             zipfp.writestr('ones', '1'*FIXEDTEST_SIZE)
1152             zipfp.writestr('twos', '2'*FIXEDTEST_SIZE)
1153
1154     def test_same_file(self):
1155         # Verify that (when the ZipFile is in control of creating file objects)
1156         # multiple open() calls can be made without interfering with each other.
1157         with zipfile.ZipFile(TESTFN2, mode="r") as zipf:
1158             zopen1 = zipf.open('ones')
1159             zopen2 = zipf.open('ones')
1160             data1 = zopen1.read(500)
1161             data2 = zopen2.read(500)
1162             data1 += zopen1.read(500)
1163             data2 += zopen2.read(500)
1164             self.assertEqual(data1, data2)
1165
1166     def test_different_file(self):
1167         # Verify that (when the ZipFile is in control of creating file objects)
1168         # multiple open() calls can be made without interfering with each other.
1169         with zipfile.ZipFile(TESTFN2, mode="r") as zipf:
1170             zopen1 = zipf.open('ones')
1171             zopen2 = zipf.open('twos')
1172             data1 = zopen1.read(500)
1173             data2 = zopen2.read(500)
1174             data1 += zopen1.read(500)
1175             data2 += zopen2.read(500)
1176             self.assertEqual(data1, '1'*FIXEDTEST_SIZE)
1177             self.assertEqual(data2, '2'*FIXEDTEST_SIZE)
1178
1179     def test_interleaved(self):
1180         # Verify that (when the ZipFile is in control of creating file objects)
1181         # multiple open() calls can be made without interfering with each other.
1182         with zipfile.ZipFile(TESTFN2, mode="r") as zipf:
1183             zopen1 = zipf.open('ones')
1184             data1 = zopen1.read(500)
1185             zopen2 = zipf.open('twos')
1186             data2 = zopen2.read(500)
1187             data1 += zopen1.read(500)
1188             data2 += zopen2.read(500)
1189             self.assertEqual(data1, '1'*FIXEDTEST_SIZE)
1190             self.assertEqual(data2, '2'*FIXEDTEST_SIZE)
1191
1192     def tearDown(self):
1193         unlink(TESTFN2)
1194
1195
1196 class TestWithDirectory(unittest.TestCase):
1197     def setUp(self):
1198         os.mkdir(TESTFN2)
1199
1200     def test_extract_dir(self):
1201         with zipfile.ZipFile(findfile("zipdir.zip")) as zipf:
1202             zipf.extractall(TESTFN2)
1203         self.assertTrue(os.path.isdir(os.path.join(TESTFN2, "a")))
1204         self.assertTrue(os.path.isdir(os.path.join(TESTFN2, "a", "b")))
1205         self.assertTrue(os.path.exists(os.path.join(TESTFN2, "a", "b", "c")))
1206
1207     def test_bug_6050(self):
1208         # Extraction should succeed if directories already exist
1209         os.mkdir(os.path.join(TESTFN2, "a"))
1210         self.test_extract_dir()
1211
1212     def test_store_dir(self):
1213         os.mkdir(os.path.join(TESTFN2, "x"))
1214         zipf = zipfile.ZipFile(TESTFN, "w")
1215         zipf.write(os.path.join(TESTFN2, "x"), "x")
1216         self.assertTrue(zipf.filelist[0].filename.endswith("x/"))
1217
1218     def tearDown(self):
1219         shutil.rmtree(TESTFN2)
1220         if os.path.exists(TESTFN):
1221             unlink(TESTFN)
1222
1223
1224 class UniversalNewlineTests(unittest.TestCase):
1225     def setUp(self):
1226         self.line_gen = ["Test of zipfile line %d." % i
1227                          for i in xrange(FIXEDTEST_SIZE)]
1228         self.seps = ('\r', '\r\n', '\n')
1229         self.arcdata, self.arcfiles = {}, {}
1230         for n, s in enumerate(self.seps):
1231             self.arcdata[s] = s.join(self.line_gen) + s
1232             self.arcfiles[s] = '%s-%d' % (TESTFN, n)
1233             open(self.arcfiles[s], "wb").write(self.arcdata[s])
1234
1235     def make_test_archive(self, f, compression):
1236         # Create the ZIP archive
1237         with zipfile.ZipFile(f, "w", compression) as zipfp:
1238             for fn in self.arcfiles.values():
1239                 zipfp.write(fn, fn)
1240
1241     def read_test(self, f, compression):
1242         self.make_test_archive(f, compression)
1243
1244         # Read the ZIP archive
1245         with zipfile.ZipFile(f, "r") as zipfp:
1246             for sep, fn in self.arcfiles.items():
1247                 zipdata = zipfp.open(fn, "rU").read()
1248                 self.assertEqual(self.arcdata[sep], zipdata)
1249
1250     def readline_read_test(self, f, compression):
1251         self.make_test_archive(f, compression)
1252
1253         # Read the ZIP archive
1254         zipfp = zipfile.ZipFile(f, "r")
1255         for sep, fn in self.arcfiles.items():
1256             zipopen = zipfp.open(fn, "rU")
1257             data = ''
1258             while True:
1259                 read = zipopen.readline()
1260                 if not read:
1261                     break
1262                 data += read
1263
1264                 read = zipopen.read(5)
1265                 if not read:
1266                     break
1267                 data += read
1268
1269             self.assertEqual(data, self.arcdata['\n'])
1270
1271         zipfp.close()
1272
1273     def readline_test(self, f, compression):
1274         self.make_test_archive(f, compression)
1275
1276         # Read the ZIP archive
1277         with zipfile.ZipFile(f, "r") as zipfp:
1278             for sep, fn in self.arcfiles.items():
1279                 zipopen = zipfp.open(fn, "rU")
1280                 for line in self.line_gen:
1281                     linedata = zipopen.readline()
1282                     self.assertEqual(linedata, line + '\n')
1283
1284     def readlines_test(self, f, compression):
1285         self.make_test_archive(f, compression)
1286
1287         # Read the ZIP archive
1288         with zipfile.ZipFile(f, "r") as zipfp:
1289             for sep, fn in self.arcfiles.items():
1290                 ziplines = zipfp.open(fn, "rU").readlines()
1291                 for line, zipline in zip(self.line_gen, ziplines):
1292                     self.assertEqual(zipline, line + '\n')
1293
1294     def iterlines_test(self, f, compression):
1295         self.make_test_archive(f, compression)
1296
1297         # Read the ZIP archive
1298         with zipfile.ZipFile(f, "r") as zipfp:
1299             for sep, fn in self.arcfiles.items():
1300                 for line, zipline in zip(self.line_gen, zipfp.open(fn, "rU")):
1301                     self.assertEqual(zipline, line + '\n')
1302
1303     def test_read_stored(self):
1304         for f in (TESTFN2, TemporaryFile(), StringIO()):
1305             self.read_test(f, zipfile.ZIP_STORED)
1306
1307     def test_readline_read_stored(self):
1308         # Issue #7610: calls to readline() interleaved with calls to read().
1309         for f in (TESTFN2, TemporaryFile(), StringIO()):
1310             self.readline_read_test(f, zipfile.ZIP_STORED)
1311
1312     def test_readline_stored(self):
1313         for f in (TESTFN2, TemporaryFile(), StringIO()):
1314             self.readline_test(f, zipfile.ZIP_STORED)
1315
1316     def test_readlines_stored(self):
1317         for f in (TESTFN2, TemporaryFile(), StringIO()):
1318             self.readlines_test(f, zipfile.ZIP_STORED)
1319
1320     def test_iterlines_stored(self):
1321         for f in (TESTFN2, TemporaryFile(), StringIO()):
1322             self.iterlines_test(f, zipfile.ZIP_STORED)
1323
1324     @skipUnless(zlib, "requires zlib")
1325     def test_read_deflated(self):
1326         for f in (TESTFN2, TemporaryFile(), StringIO()):
1327             self.read_test(f, zipfile.ZIP_DEFLATED)
1328
1329     @skipUnless(zlib, "requires zlib")
1330     def test_readline_read_deflated(self):
1331         # Issue #7610: calls to readline() interleaved with calls to read().
1332         for f in (TESTFN2, TemporaryFile(), StringIO()):
1333             self.readline_read_test(f, zipfile.ZIP_DEFLATED)
1334
1335     @skipUnless(zlib, "requires zlib")
1336     def test_readline_deflated(self):
1337         for f in (TESTFN2, TemporaryFile(), StringIO()):
1338             self.readline_test(f, zipfile.ZIP_DEFLATED)
1339
1340     @skipUnless(zlib, "requires zlib")
1341     def test_readlines_deflated(self):
1342         for f in (TESTFN2, TemporaryFile(), StringIO()):
1343             self.readlines_test(f, zipfile.ZIP_DEFLATED)
1344
1345     @skipUnless(zlib, "requires zlib")
1346     def test_iterlines_deflated(self):
1347         for f in (TESTFN2, TemporaryFile(), StringIO()):
1348             self.iterlines_test(f, zipfile.ZIP_DEFLATED)
1349
1350     def tearDown(self):
1351         for sep, fn in self.arcfiles.items():
1352             os.remove(fn)
1353         unlink(TESTFN)
1354         unlink(TESTFN2)
1355
1356
1357 def test_main():
1358     run_unittest(TestsWithSourceFile, TestZip64InSmallFiles, OtherTests,
1359                  PyZipFileTests, DecryptionTests, TestsWithMultipleOpens,
1360                  TestWithDirectory, UniversalNewlineTests,
1361                  TestsWithRandomBinaryFiles)
1362
1363 if __name__ == "__main__":
1364     test_main()