source: python/trunk/Lib/test/test_zipfile.py

Last change on this file was 391, checked in by dmik, 11 years ago

python: Merge vendor 2.7.6 to trunk.

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