#1153769: document PEP 237 changes to string formatting.
[python.git] / Lib / test / test_zipfile.py
blobc83622a71904113a0eef5a7180396daada7b0e69
1 # We can test part of the module without zlib.
2 try:
3 import zlib
4 except ImportError:
5 zlib = None
7 import zipfile, os, unittest, sys, shutil, struct
9 from StringIO import StringIO
10 from tempfile import TemporaryFile
11 from random import randint, random
13 import test.test_support as support
14 from test.test_support import TESTFN, run_unittest
16 TESTFN2 = TESTFN + "2"
17 FIXEDTEST_SIZE = 1000
19 SMALL_TEST_DATA = [('_ziptest1', '1q2w3e4r5t'),
20 ('ziptest2dir/_ziptest2', 'qawsedrftg'),
21 ('/ziptest2dir/ziptest3dir/_ziptest3', 'azsxdcfvgb'),
22 ('ziptest2dir/ziptest3dir/ziptest4dir/_ziptest3', '6y7u8i9o0p')]
24 class TestsWithSourceFile(unittest.TestCase):
25 def setUp(self):
26 self.line_gen = ["Zipfile test line %d. random float: %f" % (i, random())
27 for i in xrange(FIXEDTEST_SIZE)]
28 self.data = '\n'.join(self.line_gen) + '\n'
30 # Make a source file with some lines
31 fp = open(TESTFN, "wb")
32 fp.write(self.data)
33 fp.close()
35 def makeTestArchive(self, f, compression):
36 # Create the ZIP archive
37 zipfp = zipfile.ZipFile(f, "w", compression)
38 zipfp.write(TESTFN, "another"+os.extsep+"name")
39 zipfp.write(TESTFN, TESTFN)
40 zipfp.writestr("strfile", self.data)
41 zipfp.close()
43 def zipTest(self, f, compression):
44 self.makeTestArchive(f, compression)
46 # Read the ZIP archive
47 zipfp = zipfile.ZipFile(f, "r", compression)
48 self.assertEqual(zipfp.read(TESTFN), self.data)
49 self.assertEqual(zipfp.read("another"+os.extsep+"name"), self.data)
50 self.assertEqual(zipfp.read("strfile"), self.data)
52 # Print the ZIP directory
53 fp = StringIO()
54 stdout = sys.stdout
55 try:
56 sys.stdout = fp
58 zipfp.printdir()
59 finally:
60 sys.stdout = stdout
62 directory = fp.getvalue()
63 lines = directory.splitlines()
64 self.assertEquals(len(lines), 4) # Number of files + header
66 self.assert_('File Name' in lines[0])
67 self.assert_('Modified' in lines[0])
68 self.assert_('Size' in lines[0])
70 fn, date, time, size = lines[1].split()
71 self.assertEquals(fn, 'another.name')
72 # XXX: timestamp is not tested
73 self.assertEquals(size, str(len(self.data)))
75 # Check the namelist
76 names = zipfp.namelist()
77 self.assertEquals(len(names), 3)
78 self.assert_(TESTFN in names)
79 self.assert_("another"+os.extsep+"name" in names)
80 self.assert_("strfile" in names)
82 # Check infolist
83 infos = zipfp.infolist()
84 names = [ i.filename for i in infos ]
85 self.assertEquals(len(names), 3)
86 self.assert_(TESTFN in names)
87 self.assert_("another"+os.extsep+"name" in names)
88 self.assert_("strfile" in names)
89 for i in infos:
90 self.assertEquals(i.file_size, len(self.data))
92 # check getinfo
93 for nm in (TESTFN, "another"+os.extsep+"name", "strfile"):
94 info = zipfp.getinfo(nm)
95 self.assertEquals(info.filename, nm)
96 self.assertEquals(info.file_size, len(self.data))
98 # Check that testzip doesn't raise an exception
99 zipfp.testzip()
100 zipfp.close()
102 def testStored(self):
103 for f in (TESTFN2, TemporaryFile(), StringIO()):
104 self.zipTest(f, zipfile.ZIP_STORED)
106 def zipOpenTest(self, f, compression):
107 self.makeTestArchive(f, compression)
109 # Read the ZIP archive
110 zipfp = zipfile.ZipFile(f, "r", compression)
111 zipdata1 = []
112 zipopen1 = zipfp.open(TESTFN)
113 while 1:
114 read_data = zipopen1.read(256)
115 if not read_data:
116 break
117 zipdata1.append(read_data)
119 zipdata2 = []
120 zipopen2 = zipfp.open("another"+os.extsep+"name")
121 while 1:
122 read_data = zipopen2.read(256)
123 if not read_data:
124 break
125 zipdata2.append(read_data)
127 self.assertEqual(''.join(zipdata1), self.data)
128 self.assertEqual(''.join(zipdata2), self.data)
129 zipfp.close()
131 def testOpenStored(self):
132 for f in (TESTFN2, TemporaryFile(), StringIO()):
133 self.zipOpenTest(f, zipfile.ZIP_STORED)
135 def zipRandomOpenTest(self, f, compression):
136 self.makeTestArchive(f, compression)
138 # Read the ZIP archive
139 zipfp = zipfile.ZipFile(f, "r", compression)
140 zipdata1 = []
141 zipopen1 = zipfp.open(TESTFN)
142 while 1:
143 read_data = zipopen1.read(randint(1, 1024))
144 if not read_data:
145 break
146 zipdata1.append(read_data)
148 self.assertEqual(''.join(zipdata1), self.data)
149 zipfp.close()
151 def testRandomOpenStored(self):
152 for f in (TESTFN2, TemporaryFile(), StringIO()):
153 self.zipRandomOpenTest(f, zipfile.ZIP_STORED)
155 def zipReadlineTest(self, f, compression):
156 self.makeTestArchive(f, compression)
158 # Read the ZIP archive
159 zipfp = zipfile.ZipFile(f, "r")
160 zipopen = zipfp.open(TESTFN)
161 for line in self.line_gen:
162 linedata = zipopen.readline()
163 self.assertEqual(linedata, line + '\n')
165 zipfp.close()
167 def zipReadlinesTest(self, f, compression):
168 self.makeTestArchive(f, compression)
170 # Read the ZIP archive
171 zipfp = zipfile.ZipFile(f, "r")
172 ziplines = zipfp.open(TESTFN).readlines()
173 for line, zipline in zip(self.line_gen, ziplines):
174 self.assertEqual(zipline, line + '\n')
176 zipfp.close()
178 def zipIterlinesTest(self, f, compression):
179 self.makeTestArchive(f, compression)
181 # Read the ZIP archive
182 zipfp = zipfile.ZipFile(f, "r")
183 for line, zipline in zip(self.line_gen, zipfp.open(TESTFN)):
184 self.assertEqual(zipline, line + '\n')
186 zipfp.close()
188 def testReadlineStored(self):
189 for f in (TESTFN2, TemporaryFile(), StringIO()):
190 self.zipReadlineTest(f, zipfile.ZIP_STORED)
192 def testReadlinesStored(self):
193 for f in (TESTFN2, TemporaryFile(), StringIO()):
194 self.zipReadlinesTest(f, zipfile.ZIP_STORED)
196 def testIterlinesStored(self):
197 for f in (TESTFN2, TemporaryFile(), StringIO()):
198 self.zipIterlinesTest(f, zipfile.ZIP_STORED)
200 if zlib:
201 def testDeflated(self):
202 for f in (TESTFN2, TemporaryFile(), StringIO()):
203 self.zipTest(f, zipfile.ZIP_DEFLATED)
205 def testOpenDeflated(self):
206 for f in (TESTFN2, TemporaryFile(), StringIO()):
207 self.zipOpenTest(f, zipfile.ZIP_DEFLATED)
209 def testRandomOpenDeflated(self):
210 for f in (TESTFN2, TemporaryFile(), StringIO()):
211 self.zipRandomOpenTest(f, zipfile.ZIP_DEFLATED)
213 def testReadlineDeflated(self):
214 for f in (TESTFN2, TemporaryFile(), StringIO()):
215 self.zipReadlineTest(f, zipfile.ZIP_DEFLATED)
217 def testReadlinesDeflated(self):
218 for f in (TESTFN2, TemporaryFile(), StringIO()):
219 self.zipReadlinesTest(f, zipfile.ZIP_DEFLATED)
221 def testIterlinesDeflated(self):
222 for f in (TESTFN2, TemporaryFile(), StringIO()):
223 self.zipIterlinesTest(f, zipfile.ZIP_DEFLATED)
225 def testLowCompression(self):
226 # Checks for cases where compressed data is larger than original
227 # Create the ZIP archive
228 zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_DEFLATED)
229 zipfp.writestr("strfile", '12')
230 zipfp.close()
232 # Get an open object for strfile
233 zipfp = zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_DEFLATED)
234 openobj = zipfp.open("strfile")
235 self.assertEqual(openobj.read(1), '1')
236 self.assertEqual(openobj.read(1), '2')
238 def testAbsoluteArcnames(self):
239 zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED)
240 zipfp.write(TESTFN, "/absolute")
241 zipfp.close()
243 zipfp = zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_STORED)
244 self.assertEqual(zipfp.namelist(), ["absolute"])
245 zipfp.close()
247 def testAppendToZipFile(self):
248 # Test appending to an existing zipfile
249 zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED)
250 zipfp.write(TESTFN, TESTFN)
251 zipfp.close()
252 zipfp = zipfile.ZipFile(TESTFN2, "a", zipfile.ZIP_STORED)
253 zipfp.writestr("strfile", self.data)
254 self.assertEqual(zipfp.namelist(), [TESTFN, "strfile"])
255 zipfp.close()
257 def testAppendToNonZipFile(self):
258 # Test appending to an existing file that is not a zipfile
259 # NOTE: this test fails if len(d) < 22 because of the first
260 # line "fpin.seek(-22, 2)" in _EndRecData
261 d = 'I am not a ZipFile!'*10
262 f = file(TESTFN2, 'wb')
263 f.write(d)
264 f.close()
265 zipfp = zipfile.ZipFile(TESTFN2, "a", zipfile.ZIP_STORED)
266 zipfp.write(TESTFN, TESTFN)
267 zipfp.close()
269 f = file(TESTFN2, 'rb')
270 f.seek(len(d))
271 zipfp = zipfile.ZipFile(f, "r")
272 self.assertEqual(zipfp.namelist(), [TESTFN])
273 zipfp.close()
274 f.close()
276 def test_WriteDefaultName(self):
277 # Check that calling ZipFile.write without arcname specified produces the expected result
278 zipfp = zipfile.ZipFile(TESTFN2, "w")
279 zipfp.write(TESTFN)
280 self.assertEqual(zipfp.read(TESTFN), file(TESTFN).read())
281 zipfp.close()
283 def test_PerFileCompression(self):
284 # Check that files within a Zip archive can have different compression options
285 zipfp = zipfile.ZipFile(TESTFN2, "w")
286 zipfp.write(TESTFN, 'storeme', zipfile.ZIP_STORED)
287 zipfp.write(TESTFN, 'deflateme', zipfile.ZIP_DEFLATED)
288 sinfo = zipfp.getinfo('storeme')
289 dinfo = zipfp.getinfo('deflateme')
290 self.assertEqual(sinfo.compress_type, zipfile.ZIP_STORED)
291 self.assertEqual(dinfo.compress_type, zipfile.ZIP_DEFLATED)
292 zipfp.close()
294 def test_WriteToReadonly(self):
295 # Check that trying to call write() on a readonly ZipFile object
296 # raises a RuntimeError
297 zipf = zipfile.ZipFile(TESTFN2, mode="w")
298 zipf.writestr("somefile.txt", "bogus")
299 zipf.close()
300 zipf = zipfile.ZipFile(TESTFN2, mode="r")
301 self.assertRaises(RuntimeError, zipf.write, TESTFN)
302 zipf.close()
304 def testExtract(self):
305 zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED)
306 for fpath, fdata in SMALL_TEST_DATA:
307 zipfp.writestr(fpath, fdata)
308 zipfp.close()
310 zipfp = zipfile.ZipFile(TESTFN2, "r")
311 for fpath, fdata in SMALL_TEST_DATA:
312 writtenfile = zipfp.extract(fpath)
314 # make sure it was written to the right place
315 if os.path.isabs(fpath):
316 correctfile = os.path.join(os.getcwd(), fpath[1:])
317 else:
318 correctfile = os.path.join(os.getcwd(), fpath)
319 correctfile = os.path.normpath(correctfile)
321 self.assertEqual(writtenfile, correctfile)
323 # make sure correct data is in correct file
324 self.assertEqual(fdata, file(writtenfile, "rb").read())
326 os.remove(writtenfile)
328 zipfp.close()
330 # remove the test file subdirectories
331 shutil.rmtree(os.path.join(os.getcwd(), 'ziptest2dir'))
333 def testExtractAll(self):
334 zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED)
335 for fpath, fdata in SMALL_TEST_DATA:
336 zipfp.writestr(fpath, fdata)
337 zipfp.close()
339 zipfp = zipfile.ZipFile(TESTFN2, "r")
340 zipfp.extractall()
341 for fpath, fdata in SMALL_TEST_DATA:
342 if os.path.isabs(fpath):
343 outfile = os.path.join(os.getcwd(), fpath[1:])
344 else:
345 outfile = os.path.join(os.getcwd(), fpath)
347 self.assertEqual(fdata, file(outfile, "rb").read())
349 os.remove(outfile)
351 zipfp.close()
353 # remove the test file subdirectories
354 shutil.rmtree(os.path.join(os.getcwd(), 'ziptest2dir'))
356 def tearDown(self):
357 os.remove(TESTFN)
358 os.remove(TESTFN2)
360 class TestZip64InSmallFiles(unittest.TestCase):
361 # These tests test the ZIP64 functionality without using large files,
362 # see test_zipfile64 for proper tests.
364 def setUp(self):
365 self._limit = zipfile.ZIP64_LIMIT
366 zipfile.ZIP64_LIMIT = 5
368 line_gen = ("Test of zipfile line %d." % i for i in range(0, FIXEDTEST_SIZE))
369 self.data = '\n'.join(line_gen)
371 # Make a source file with some lines
372 fp = open(TESTFN, "wb")
373 fp.write(self.data)
374 fp.close()
376 def largeFileExceptionTest(self, f, compression):
377 zipfp = zipfile.ZipFile(f, "w", compression)
378 self.assertRaises(zipfile.LargeZipFile,
379 zipfp.write, TESTFN, "another"+os.extsep+"name")
380 zipfp.close()
382 def largeFileExceptionTest2(self, f, compression):
383 zipfp = zipfile.ZipFile(f, "w", compression)
384 self.assertRaises(zipfile.LargeZipFile,
385 zipfp.writestr, "another"+os.extsep+"name", self.data)
386 zipfp.close()
388 def testLargeFileException(self):
389 for f in (TESTFN2, TemporaryFile(), StringIO()):
390 self.largeFileExceptionTest(f, zipfile.ZIP_STORED)
391 self.largeFileExceptionTest2(f, zipfile.ZIP_STORED)
393 def zipTest(self, f, compression):
394 # Create the ZIP archive
395 zipfp = zipfile.ZipFile(f, "w", compression, allowZip64=True)
396 zipfp.write(TESTFN, "another"+os.extsep+"name")
397 zipfp.write(TESTFN, TESTFN)
398 zipfp.writestr("strfile", self.data)
399 zipfp.close()
401 # Read the ZIP archive
402 zipfp = zipfile.ZipFile(f, "r", compression)
403 self.assertEqual(zipfp.read(TESTFN), self.data)
404 self.assertEqual(zipfp.read("another"+os.extsep+"name"), self.data)
405 self.assertEqual(zipfp.read("strfile"), self.data)
407 # Print the ZIP directory
408 fp = StringIO()
409 stdout = sys.stdout
410 try:
411 sys.stdout = fp
413 zipfp.printdir()
414 finally:
415 sys.stdout = stdout
417 directory = fp.getvalue()
418 lines = directory.splitlines()
419 self.assertEquals(len(lines), 4) # Number of files + header
421 self.assert_('File Name' in lines[0])
422 self.assert_('Modified' in lines[0])
423 self.assert_('Size' in lines[0])
425 fn, date, time, size = lines[1].split()
426 self.assertEquals(fn, 'another.name')
427 # XXX: timestamp is not tested
428 self.assertEquals(size, str(len(self.data)))
430 # Check the namelist
431 names = zipfp.namelist()
432 self.assertEquals(len(names), 3)
433 self.assert_(TESTFN in names)
434 self.assert_("another"+os.extsep+"name" in names)
435 self.assert_("strfile" in names)
437 # Check infolist
438 infos = zipfp.infolist()
439 names = [ i.filename for i in infos ]
440 self.assertEquals(len(names), 3)
441 self.assert_(TESTFN in names)
442 self.assert_("another"+os.extsep+"name" in names)
443 self.assert_("strfile" in names)
444 for i in infos:
445 self.assertEquals(i.file_size, len(self.data))
447 # check getinfo
448 for nm in (TESTFN, "another"+os.extsep+"name", "strfile"):
449 info = zipfp.getinfo(nm)
450 self.assertEquals(info.filename, nm)
451 self.assertEquals(info.file_size, len(self.data))
453 # Check that testzip doesn't raise an exception
454 zipfp.testzip()
457 zipfp.close()
459 def testStored(self):
460 for f in (TESTFN2, TemporaryFile(), StringIO()):
461 self.zipTest(f, zipfile.ZIP_STORED)
464 if zlib:
465 def testDeflated(self):
466 for f in (TESTFN2, TemporaryFile(), StringIO()):
467 self.zipTest(f, zipfile.ZIP_DEFLATED)
469 def testAbsoluteArcnames(self):
470 zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED, allowZip64=True)
471 zipfp.write(TESTFN, "/absolute")
472 zipfp.close()
474 zipfp = zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_STORED)
475 self.assertEqual(zipfp.namelist(), ["absolute"])
476 zipfp.close()
478 def tearDown(self):
479 zipfile.ZIP64_LIMIT = self._limit
480 os.remove(TESTFN)
481 os.remove(TESTFN2)
483 class PyZipFileTests(unittest.TestCase):
484 def testWritePyfile(self):
485 zipfp = zipfile.PyZipFile(TemporaryFile(), "w")
486 fn = __file__
487 if fn.endswith('.pyc') or fn.endswith('.pyo'):
488 fn = fn[:-1]
490 zipfp.writepy(fn)
492 bn = os.path.basename(fn)
493 self.assert_(bn not in zipfp.namelist())
494 self.assert_(bn + 'o' in zipfp.namelist() or bn + 'c' in zipfp.namelist())
495 zipfp.close()
498 zipfp = zipfile.PyZipFile(TemporaryFile(), "w")
499 fn = __file__
500 if fn.endswith('.pyc') or fn.endswith('.pyo'):
501 fn = fn[:-1]
503 zipfp.writepy(fn, "testpackage")
505 bn = "%s/%s"%("testpackage", os.path.basename(fn))
506 self.assert_(bn not in zipfp.namelist())
507 self.assert_(bn + 'o' in zipfp.namelist() or bn + 'c' in zipfp.namelist())
508 zipfp.close()
510 def testWritePythonPackage(self):
511 import email
512 packagedir = os.path.dirname(email.__file__)
514 zipfp = zipfile.PyZipFile(TemporaryFile(), "w")
515 zipfp.writepy(packagedir)
517 # Check for a couple of modules at different levels of the hieararchy
518 names = zipfp.namelist()
519 self.assert_('email/__init__.pyo' in names or 'email/__init__.pyc' in names)
520 self.assert_('email/mime/text.pyo' in names or 'email/mime/text.pyc' in names)
522 def testWritePythonDirectory(self):
523 os.mkdir(TESTFN2)
524 try:
525 fp = open(os.path.join(TESTFN2, "mod1.py"), "w")
526 fp.write("print 42\n")
527 fp.close()
529 fp = open(os.path.join(TESTFN2, "mod2.py"), "w")
530 fp.write("print 42 * 42\n")
531 fp.close()
533 fp = open(os.path.join(TESTFN2, "mod2.txt"), "w")
534 fp.write("bla bla bla\n")
535 fp.close()
537 zipfp = zipfile.PyZipFile(TemporaryFile(), "w")
538 zipfp.writepy(TESTFN2)
540 names = zipfp.namelist()
541 self.assert_('mod1.pyc' in names or 'mod1.pyo' in names)
542 self.assert_('mod2.pyc' in names or 'mod2.pyo' in names)
543 self.assert_('mod2.txt' not in names)
545 finally:
546 shutil.rmtree(TESTFN2)
548 def testWriteNonPyfile(self):
549 zipfp = zipfile.PyZipFile(TemporaryFile(), "w")
550 file(TESTFN, 'w').write('most definitely not a python file')
551 self.assertRaises(RuntimeError, zipfp.writepy, TESTFN)
552 os.remove(TESTFN)
555 class OtherTests(unittest.TestCase):
556 def testUnicodeFilenames(self):
557 zf = zipfile.ZipFile(TESTFN, "w")
558 zf.writestr(u"foo.txt", "Test for unicode filename")
559 zf.writestr(u"\xf6.txt", "Test for unicode filename")
560 self.assertTrue(isinstance(zf.infolist()[0].filename, unicode))
561 zf.close()
562 zf = zipfile.ZipFile(TESTFN, "r")
563 self.assertEqual(zf.filelist[0].filename, "foo.txt")
564 self.assertEqual(zf.filelist[1].filename, u"\xf6.txt")
565 zf.close()
567 def testCreateNonExistentFileForAppend(self):
568 if os.path.exists(TESTFN):
569 os.unlink(TESTFN)
571 filename = 'testfile.txt'
572 content = 'hello, world. this is some content.'
574 try:
575 zf = zipfile.ZipFile(TESTFN, 'a')
576 zf.writestr(filename, content)
577 zf.close()
578 except IOError, (errno, errmsg):
579 self.fail('Could not append data to a non-existent zip file.')
581 self.assert_(os.path.exists(TESTFN))
583 zf = zipfile.ZipFile(TESTFN, 'r')
584 self.assertEqual(zf.read(filename), content)
585 zf.close()
587 def testCloseErroneousFile(self):
588 # This test checks that the ZipFile constructor closes the file object
589 # it opens if there's an error in the file. If it doesn't, the traceback
590 # holds a reference to the ZipFile object and, indirectly, the file object.
591 # On Windows, this causes the os.unlink() call to fail because the
592 # underlying file is still open. This is SF bug #412214.
594 fp = open(TESTFN, "w")
595 fp.write("this is not a legal zip file\n")
596 fp.close()
597 try:
598 zf = zipfile.ZipFile(TESTFN)
599 except zipfile.BadZipfile:
600 pass
602 def testIsZipErroneousFile(self):
603 # This test checks that the is_zipfile function correctly identifies
604 # a file that is not a zip file
605 fp = open(TESTFN, "w")
606 fp.write("this is not a legal zip file\n")
607 fp.close()
608 chk = zipfile.is_zipfile(TESTFN)
609 self.assert_(chk is False)
611 def testIsZipValidFile(self):
612 # This test checks that the is_zipfile function correctly identifies
613 # a file that is a zip file
614 zipf = zipfile.ZipFile(TESTFN, mode="w")
615 zipf.writestr("foo.txt", "O, for a Muse of Fire!")
616 zipf.close()
617 chk = zipfile.is_zipfile(TESTFN)
618 self.assert_(chk is True)
620 def testNonExistentFileRaisesIOError(self):
621 # make sure we don't raise an AttributeError when a partially-constructed
622 # ZipFile instance is finalized; this tests for regression on SF tracker
623 # bug #403871.
625 # The bug we're testing for caused an AttributeError to be raised
626 # when a ZipFile instance was created for a file that did not
627 # exist; the .fp member was not initialized but was needed by the
628 # __del__() method. Since the AttributeError is in the __del__(),
629 # it is ignored, but the user should be sufficiently annoyed by
630 # the message on the output that regression will be noticed
631 # quickly.
632 self.assertRaises(IOError, zipfile.ZipFile, TESTFN)
634 def testClosedZipRaisesRuntimeError(self):
635 # Verify that testzip() doesn't swallow inappropriate exceptions.
636 data = StringIO()
637 zipf = zipfile.ZipFile(data, mode="w")
638 zipf.writestr("foo.txt", "O, for a Muse of Fire!")
639 zipf.close()
641 # This is correct; calling .read on a closed ZipFile should throw
642 # a RuntimeError, and so should calling .testzip. An earlier
643 # version of .testzip would swallow this exception (and any other)
644 # and report that the first file in the archive was corrupt.
645 self.assertRaises(RuntimeError, zipf.read, "foo.txt")
646 self.assertRaises(RuntimeError, zipf.open, "foo.txt")
647 self.assertRaises(RuntimeError, zipf.testzip)
648 self.assertRaises(RuntimeError, zipf.writestr, "bogus.txt", "bogus")
649 file(TESTFN, 'w').write('zipfile test data')
650 self.assertRaises(RuntimeError, zipf.write, TESTFN)
652 def test_BadConstructorMode(self):
653 # Check that bad modes passed to ZipFile constructor are caught
654 self.assertRaises(RuntimeError, zipfile.ZipFile, TESTFN, "q")
656 def test_BadOpenMode(self):
657 # Check that bad modes passed to ZipFile.open are caught
658 zipf = zipfile.ZipFile(TESTFN, mode="w")
659 zipf.writestr("foo.txt", "O, for a Muse of Fire!")
660 zipf.close()
661 zipf = zipfile.ZipFile(TESTFN, mode="r")
662 # read the data to make sure the file is there
663 zipf.read("foo.txt")
664 self.assertRaises(RuntimeError, zipf.open, "foo.txt", "q")
665 zipf.close()
667 def test_Read0(self):
668 # Check that calling read(0) on a ZipExtFile object returns an empty
669 # string and doesn't advance file pointer
670 zipf = zipfile.ZipFile(TESTFN, mode="w")
671 zipf.writestr("foo.txt", "O, for a Muse of Fire!")
672 # read the data to make sure the file is there
673 f = zipf.open("foo.txt")
674 for i in xrange(FIXEDTEST_SIZE):
675 self.assertEqual(f.read(0), '')
677 self.assertEqual(f.read(), "O, for a Muse of Fire!")
678 zipf.close()
680 def test_OpenNonexistentItem(self):
681 # Check that attempting to call open() for an item that doesn't
682 # exist in the archive raises a RuntimeError
683 zipf = zipfile.ZipFile(TESTFN, mode="w")
684 self.assertRaises(KeyError, zipf.open, "foo.txt", "r")
686 def test_BadCompressionMode(self):
687 # Check that bad compression methods passed to ZipFile.open are caught
688 self.assertRaises(RuntimeError, zipfile.ZipFile, TESTFN, "w", -1)
690 def test_NullByteInFilename(self):
691 # Check that a filename containing a null byte is properly terminated
692 zipf = zipfile.ZipFile(TESTFN, mode="w")
693 zipf.writestr("foo.txt\x00qqq", "O, for a Muse of Fire!")
694 self.assertEqual(zipf.namelist(), ['foo.txt'])
696 def tearDown(self):
697 support.unlink(TESTFN)
698 support.unlink(TESTFN2)
700 class DecryptionTests(unittest.TestCase):
701 # This test checks that ZIP decryption works. Since the library does not
702 # support encryption at the moment, we use a pre-generated encrypted
703 # ZIP file
705 data = (
706 'PK\x03\x04\x14\x00\x01\x00\x00\x00n\x92i.#y\xef?&\x00\x00\x00\x1a\x00'
707 '\x00\x00\x08\x00\x00\x00test.txt\xfa\x10\xa0gly|\xfa-\xc5\xc0=\xf9y'
708 '\x18\xe0\xa8r\xb3Z}Lg\xbc\xae\xf9|\x9b\x19\xe4\x8b\xba\xbb)\x8c\xb0\xdbl'
709 'PK\x01\x02\x14\x00\x14\x00\x01\x00\x00\x00n\x92i.#y\xef?&\x00\x00\x00'
710 '\x1a\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x01\x00 \x00\xb6\x81'
711 '\x00\x00\x00\x00test.txtPK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x006\x00'
712 '\x00\x00L\x00\x00\x00\x00\x00' )
713 data2 = (
714 'PK\x03\x04\x14\x00\t\x00\x08\x00\xcf}38xu\xaa\xb2\x14\x00\x00\x00\x00\x02'
715 '\x00\x00\x04\x00\x15\x00zeroUT\t\x00\x03\xd6\x8b\x92G\xda\x8b\x92GUx\x04'
716 '\x00\xe8\x03\xe8\x03\xc7<M\xb5a\xceX\xa3Y&\x8b{oE\xd7\x9d\x8c\x98\x02\xc0'
717 'PK\x07\x08xu\xaa\xb2\x14\x00\x00\x00\x00\x02\x00\x00PK\x01\x02\x17\x03'
718 '\x14\x00\t\x00\x08\x00\xcf}38xu\xaa\xb2\x14\x00\x00\x00\x00\x02\x00\x00'
719 '\x04\x00\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x00ze'
720 'roUT\x05\x00\x03\xd6\x8b\x92GUx\x00\x00PK\x05\x06\x00\x00\x00\x00\x01'
721 '\x00\x01\x00?\x00\x00\x00[\x00\x00\x00\x00\x00' )
723 plain = 'zipfile.py encryption test'
724 plain2 = '\x00'*512
726 def setUp(self):
727 fp = open(TESTFN, "wb")
728 fp.write(self.data)
729 fp.close()
730 self.zip = zipfile.ZipFile(TESTFN, "r")
731 fp = open(TESTFN2, "wb")
732 fp.write(self.data2)
733 fp.close()
734 self.zip2 = zipfile.ZipFile(TESTFN2, "r")
736 def tearDown(self):
737 self.zip.close()
738 os.unlink(TESTFN)
739 self.zip2.close()
740 os.unlink(TESTFN2)
742 def testNoPassword(self):
743 # Reading the encrypted file without password
744 # must generate a RunTime exception
745 self.assertRaises(RuntimeError, self.zip.read, "test.txt")
746 self.assertRaises(RuntimeError, self.zip2.read, "zero")
748 def testBadPassword(self):
749 self.zip.setpassword("perl")
750 self.assertRaises(RuntimeError, self.zip.read, "test.txt")
751 self.zip2.setpassword("perl")
752 self.assertRaises(RuntimeError, self.zip2.read, "zero")
754 def testGoodPassword(self):
755 self.zip.setpassword("python")
756 self.assertEquals(self.zip.read("test.txt"), self.plain)
757 self.zip2.setpassword("12345")
758 self.assertEquals(self.zip2.read("zero"), self.plain2)
761 class TestsWithRandomBinaryFiles(unittest.TestCase):
762 def setUp(self):
763 datacount = randint(16, 64)*1024 + randint(1, 1024)
764 self.data = ''.join((struct.pack('<f', random()*randint(-1000, 1000)) for i in xrange(datacount)))
766 # Make a source file with some lines
767 fp = open(TESTFN, "wb")
768 fp.write(self.data)
769 fp.close()
771 def tearDown(self):
772 support.unlink(TESTFN)
773 support.unlink(TESTFN2)
775 def makeTestArchive(self, f, compression):
776 # Create the ZIP archive
777 zipfp = zipfile.ZipFile(f, "w", compression)
778 zipfp.write(TESTFN, "another"+os.extsep+"name")
779 zipfp.write(TESTFN, TESTFN)
780 zipfp.close()
782 def zipTest(self, f, compression):
783 self.makeTestArchive(f, compression)
785 # Read the ZIP archive
786 zipfp = zipfile.ZipFile(f, "r", compression)
787 testdata = zipfp.read(TESTFN)
788 self.assertEqual(len(testdata), len(self.data))
789 self.assertEqual(testdata, self.data)
790 self.assertEqual(zipfp.read("another"+os.extsep+"name"), self.data)
791 zipfp.close()
793 def testStored(self):
794 for f in (TESTFN2, TemporaryFile(), StringIO()):
795 self.zipTest(f, zipfile.ZIP_STORED)
797 def zipOpenTest(self, f, compression):
798 self.makeTestArchive(f, compression)
800 # Read the ZIP archive
801 zipfp = zipfile.ZipFile(f, "r", compression)
802 zipdata1 = []
803 zipopen1 = zipfp.open(TESTFN)
804 while 1:
805 read_data = zipopen1.read(256)
806 if not read_data:
807 break
808 zipdata1.append(read_data)
810 zipdata2 = []
811 zipopen2 = zipfp.open("another"+os.extsep+"name")
812 while 1:
813 read_data = zipopen2.read(256)
814 if not read_data:
815 break
816 zipdata2.append(read_data)
818 testdata1 = ''.join(zipdata1)
819 self.assertEqual(len(testdata1), len(self.data))
820 self.assertEqual(testdata1, self.data)
822 testdata2 = ''.join(zipdata2)
823 self.assertEqual(len(testdata1), len(self.data))
824 self.assertEqual(testdata1, self.data)
825 zipfp.close()
827 def testOpenStored(self):
828 for f in (TESTFN2, TemporaryFile(), StringIO()):
829 self.zipOpenTest(f, zipfile.ZIP_STORED)
831 def zipRandomOpenTest(self, f, compression):
832 self.makeTestArchive(f, compression)
834 # Read the ZIP archive
835 zipfp = zipfile.ZipFile(f, "r", compression)
836 zipdata1 = []
837 zipopen1 = zipfp.open(TESTFN)
838 while 1:
839 read_data = zipopen1.read(randint(1, 1024))
840 if not read_data:
841 break
842 zipdata1.append(read_data)
844 testdata = ''.join(zipdata1)
845 self.assertEqual(len(testdata), len(self.data))
846 self.assertEqual(testdata, self.data)
847 zipfp.close()
849 def testRandomOpenStored(self):
850 for f in (TESTFN2, TemporaryFile(), StringIO()):
851 self.zipRandomOpenTest(f, zipfile.ZIP_STORED)
853 class TestsWithMultipleOpens(unittest.TestCase):
854 def setUp(self):
855 # Create the ZIP archive
856 zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_DEFLATED)
857 zipfp.writestr('ones', '1'*FIXEDTEST_SIZE)
858 zipfp.writestr('twos', '2'*FIXEDTEST_SIZE)
859 zipfp.close()
861 def testSameFile(self):
862 # Verify that (when the ZipFile is in control of creating file objects)
863 # multiple open() calls can be made without interfering with each other.
864 zipf = zipfile.ZipFile(TESTFN2, mode="r")
865 zopen1 = zipf.open('ones')
866 zopen2 = zipf.open('ones')
867 data1 = zopen1.read(500)
868 data2 = zopen2.read(500)
869 data1 += zopen1.read(500)
870 data2 += zopen2.read(500)
871 self.assertEqual(data1, data2)
872 zipf.close()
874 def testDifferentFile(self):
875 # Verify that (when the ZipFile is in control of creating file objects)
876 # multiple open() calls can be made without interfering with each other.
877 zipf = zipfile.ZipFile(TESTFN2, mode="r")
878 zopen1 = zipf.open('ones')
879 zopen2 = zipf.open('twos')
880 data1 = zopen1.read(500)
881 data2 = zopen2.read(500)
882 data1 += zopen1.read(500)
883 data2 += zopen2.read(500)
884 self.assertEqual(data1, '1'*FIXEDTEST_SIZE)
885 self.assertEqual(data2, '2'*FIXEDTEST_SIZE)
886 zipf.close()
888 def testInterleaved(self):
889 # Verify that (when the ZipFile is in control of creating file objects)
890 # multiple open() calls can be made without interfering with each other.
891 zipf = zipfile.ZipFile(TESTFN2, mode="r")
892 zopen1 = zipf.open('ones')
893 data1 = zopen1.read(500)
894 zopen2 = zipf.open('twos')
895 data2 = zopen2.read(500)
896 data1 += zopen1.read(500)
897 data2 += zopen2.read(500)
898 self.assertEqual(data1, '1'*FIXEDTEST_SIZE)
899 self.assertEqual(data2, '2'*FIXEDTEST_SIZE)
900 zipf.close()
902 def tearDown(self):
903 os.remove(TESTFN2)
906 class UniversalNewlineTests(unittest.TestCase):
907 def setUp(self):
908 self.line_gen = ["Test of zipfile line %d." % i for i in xrange(FIXEDTEST_SIZE)]
909 self.seps = ('\r', '\r\n', '\n')
910 self.arcdata, self.arcfiles = {}, {}
911 for n, s in enumerate(self.seps):
912 self.arcdata[s] = s.join(self.line_gen) + s
913 self.arcfiles[s] = '%s-%d' % (TESTFN, n)
914 open(self.arcfiles[s], "wb").write(self.arcdata[s])
916 def makeTestArchive(self, f, compression):
917 # Create the ZIP archive
918 zipfp = zipfile.ZipFile(f, "w", compression)
919 for fn in self.arcfiles.values():
920 zipfp.write(fn, fn)
921 zipfp.close()
923 def readTest(self, f, compression):
924 self.makeTestArchive(f, compression)
926 # Read the ZIP archive
927 zipfp = zipfile.ZipFile(f, "r")
928 for sep, fn in self.arcfiles.items():
929 zipdata = zipfp.open(fn, "rU").read()
930 self.assertEqual(self.arcdata[sep], zipdata)
932 zipfp.close()
934 def readlineTest(self, f, compression):
935 self.makeTestArchive(f, compression)
937 # Read the ZIP archive
938 zipfp = zipfile.ZipFile(f, "r")
939 for sep, fn in self.arcfiles.items():
940 zipopen = zipfp.open(fn, "rU")
941 for line in self.line_gen:
942 linedata = zipopen.readline()
943 self.assertEqual(linedata, line + '\n')
945 zipfp.close()
947 def readlinesTest(self, f, compression):
948 self.makeTestArchive(f, compression)
950 # Read the ZIP archive
951 zipfp = zipfile.ZipFile(f, "r")
952 for sep, fn in self.arcfiles.items():
953 ziplines = zipfp.open(fn, "rU").readlines()
954 for line, zipline in zip(self.line_gen, ziplines):
955 self.assertEqual(zipline, line + '\n')
957 zipfp.close()
959 def iterlinesTest(self, f, compression):
960 self.makeTestArchive(f, compression)
962 # Read the ZIP archive
963 zipfp = zipfile.ZipFile(f, "r")
964 for sep, fn in self.arcfiles.items():
965 for line, zipline in zip(self.line_gen, zipfp.open(fn, "rU")):
966 self.assertEqual(zipline, line + '\n')
968 zipfp.close()
970 def testReadStored(self):
971 for f in (TESTFN2, TemporaryFile(), StringIO()):
972 self.readTest(f, zipfile.ZIP_STORED)
974 def testReadlineStored(self):
975 for f in (TESTFN2, TemporaryFile(), StringIO()):
976 self.readlineTest(f, zipfile.ZIP_STORED)
978 def testReadlinesStored(self):
979 for f in (TESTFN2, TemporaryFile(), StringIO()):
980 self.readlinesTest(f, zipfile.ZIP_STORED)
982 def testIterlinesStored(self):
983 for f in (TESTFN2, TemporaryFile(), StringIO()):
984 self.iterlinesTest(f, zipfile.ZIP_STORED)
986 if zlib:
987 def testReadDeflated(self):
988 for f in (TESTFN2, TemporaryFile(), StringIO()):
989 self.readTest(f, zipfile.ZIP_DEFLATED)
991 def testReadlineDeflated(self):
992 for f in (TESTFN2, TemporaryFile(), StringIO()):
993 self.readlineTest(f, zipfile.ZIP_DEFLATED)
995 def testReadlinesDeflated(self):
996 for f in (TESTFN2, TemporaryFile(), StringIO()):
997 self.readlinesTest(f, zipfile.ZIP_DEFLATED)
999 def testIterlinesDeflated(self):
1000 for f in (TESTFN2, TemporaryFile(), StringIO()):
1001 self.iterlinesTest(f, zipfile.ZIP_DEFLATED)
1003 def tearDown(self):
1004 for sep, fn in self.arcfiles.items():
1005 os.remove(fn)
1006 support.unlink(TESTFN)
1007 support.unlink(TESTFN2)
1010 def test_main():
1011 run_unittest(TestsWithSourceFile, TestZip64InSmallFiles, OtherTests,
1012 PyZipFileTests, DecryptionTests, TestsWithMultipleOpens,
1013 UniversalNewlineTests, TestsWithRandomBinaryFiles)
1015 if __name__ == "__main__":
1016 test_main()