blob: 3d2f9bd43f1722590f16fad56217dddb5d2d6160 [file] [log] [blame]
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +00001# We can test part of the module without zlib.
Guido van Rossum368f04a2000-04-10 13:23:04 +00002try:
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +00003 import zlib
4except ImportError:
5 zlib = None
Tim Petersa45cacf2004-08-20 03:47:14 +00006
Martin v. Löwis3eb76482007-03-06 10:41:24 +00007import zipfile, os, unittest, sys, shutil, struct
Tim Petersa19a1682001-03-29 04:36:09 +00008
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +00009from StringIO import StringIO
10from tempfile import TemporaryFile
Martin v. Löwis3eb76482007-03-06 10:41:24 +000011from random import randint, random
Tim Petersa19a1682001-03-29 04:36:09 +000012
Collin Winter04a51ec2007-03-29 02:28:16 +000013import test.test_support as support
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +000014from test.test_support import TESTFN, run_unittest
Guido van Rossum368f04a2000-04-10 13:23:04 +000015
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +000016TESTFN2 = TESTFN + "2"
Georg Brandl4b3ab6f2007-07-12 09:59:22 +000017FIXEDTEST_SIZE = 1000
Guido van Rossum368f04a2000-04-10 13:23:04 +000018
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +000019class TestsWithSourceFile(unittest.TestCase):
20 def setUp(self):
Georg Brandl4b3ab6f2007-07-12 09:59:22 +000021 self.line_gen = ["Zipfile test line %d. random float: %f" % (i, random())
22 for i in xrange(FIXEDTEST_SIZE)]
Martin v. Löwis3eb76482007-03-06 10:41:24 +000023 self.data = '\n'.join(self.line_gen) + '\n'
Fred Drake6e7e4852001-02-28 05:34:16 +000024
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +000025 # Make a source file with some lines
26 fp = open(TESTFN, "wb")
27 fp.write(self.data)
28 fp.close()
Tim Peters7d3bad62001-04-04 18:56:49 +000029
Martin v. Löwis3eb76482007-03-06 10:41:24 +000030 def makeTestArchive(self, f, compression):
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +000031 # Create the ZIP archive
32 zipfp = zipfile.ZipFile(f, "w", compression)
33 zipfp.write(TESTFN, "another"+os.extsep+"name")
34 zipfp.write(TESTFN, TESTFN)
Ronald Oussoren143cefb2006-06-15 08:14:18 +000035 zipfp.writestr("strfile", self.data)
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +000036 zipfp.close()
Tim Peters7d3bad62001-04-04 18:56:49 +000037
Martin v. Löwis3eb76482007-03-06 10:41:24 +000038 def zipTest(self, f, compression):
39 self.makeTestArchive(f, compression)
40
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +000041 # Read the ZIP archive
42 zipfp = zipfile.ZipFile(f, "r", compression)
43 self.assertEqual(zipfp.read(TESTFN), self.data)
44 self.assertEqual(zipfp.read("another"+os.extsep+"name"), self.data)
Ronald Oussoren143cefb2006-06-15 08:14:18 +000045 self.assertEqual(zipfp.read("strfile"), self.data)
46
47 # Print the ZIP directory
48 fp = StringIO()
49 stdout = sys.stdout
50 try:
51 sys.stdout = fp
52
53 zipfp.printdir()
54 finally:
55 sys.stdout = stdout
Tim Petersa608bb22006-06-15 18:06:29 +000056
Ronald Oussoren143cefb2006-06-15 08:14:18 +000057 directory = fp.getvalue()
58 lines = directory.splitlines()
59 self.assertEquals(len(lines), 4) # Number of files + header
60
61 self.assert_('File Name' in lines[0])
62 self.assert_('Modified' in lines[0])
63 self.assert_('Size' in lines[0])
64
65 fn, date, time, size = lines[1].split()
66 self.assertEquals(fn, 'another.name')
67 # XXX: timestamp is not tested
68 self.assertEquals(size, str(len(self.data)))
69
70 # Check the namelist
71 names = zipfp.namelist()
72 self.assertEquals(len(names), 3)
73 self.assert_(TESTFN in names)
74 self.assert_("another"+os.extsep+"name" in names)
75 self.assert_("strfile" in names)
76
77 # Check infolist
78 infos = zipfp.infolist()
79 names = [ i.filename for i in infos ]
80 self.assertEquals(len(names), 3)
81 self.assert_(TESTFN in names)
82 self.assert_("another"+os.extsep+"name" in names)
83 self.assert_("strfile" in names)
84 for i in infos:
85 self.assertEquals(i.file_size, len(self.data))
86
87 # check getinfo
88 for nm in (TESTFN, "another"+os.extsep+"name", "strfile"):
89 info = zipfp.getinfo(nm)
90 self.assertEquals(info.filename, nm)
91 self.assertEquals(info.file_size, len(self.data))
92
93 # Check that testzip doesn't raise an exception
94 zipfp.testzip()
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +000095 zipfp.close()
Tim Peters7d3bad62001-04-04 18:56:49 +000096
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +000097 def testStored(self):
98 for f in (TESTFN2, TemporaryFile(), StringIO()):
99 self.zipTest(f, zipfile.ZIP_STORED)
Raymond Hettingerc0fac962003-06-27 22:25:03 +0000100
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000101 def zipOpenTest(self, f, compression):
102 self.makeTestArchive(f, compression)
103
104 # Read the ZIP archive
105 zipfp = zipfile.ZipFile(f, "r", compression)
106 zipdata1 = []
107 zipopen1 = zipfp.open(TESTFN)
108 while 1:
109 read_data = zipopen1.read(256)
110 if not read_data:
111 break
112 zipdata1.append(read_data)
113
114 zipdata2 = []
115 zipopen2 = zipfp.open("another"+os.extsep+"name")
116 while 1:
117 read_data = zipopen2.read(256)
118 if not read_data:
119 break
120 zipdata2.append(read_data)
Tim Petersea5962f2007-03-12 18:07:52 +0000121
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000122 self.assertEqual(''.join(zipdata1), self.data)
123 self.assertEqual(''.join(zipdata2), self.data)
124 zipfp.close()
Tim Petersea5962f2007-03-12 18:07:52 +0000125
126 def testOpenStored(self):
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000127 for f in (TESTFN2, TemporaryFile(), StringIO()):
128 self.zipOpenTest(f, zipfile.ZIP_STORED)
129
130 def zipRandomOpenTest(self, f, compression):
131 self.makeTestArchive(f, compression)
132
133 # Read the ZIP archive
134 zipfp = zipfile.ZipFile(f, "r", compression)
135 zipdata1 = []
136 zipopen1 = zipfp.open(TESTFN)
137 while 1:
138 read_data = zipopen1.read(randint(1, 1024))
139 if not read_data:
140 break
141 zipdata1.append(read_data)
142
143 self.assertEqual(''.join(zipdata1), self.data)
144 zipfp.close()
Tim Petersea5962f2007-03-12 18:07:52 +0000145
146 def testRandomOpenStored(self):
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000147 for f in (TESTFN2, TemporaryFile(), StringIO()):
148 self.zipRandomOpenTest(f, zipfile.ZIP_STORED)
Tim Petersea5962f2007-03-12 18:07:52 +0000149
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000150 def zipReadlineTest(self, f, compression):
151 self.makeTestArchive(f, compression)
152
153 # Read the ZIP archive
154 zipfp = zipfile.ZipFile(f, "r")
155 zipopen = zipfp.open(TESTFN)
156 for line in self.line_gen:
157 linedata = zipopen.readline()
158 self.assertEqual(linedata, line + '\n')
159
160 zipfp.close()
161
162 def zipReadlinesTest(self, f, compression):
163 self.makeTestArchive(f, compression)
164
165 # Read the ZIP archive
166 zipfp = zipfile.ZipFile(f, "r")
167 ziplines = zipfp.open(TESTFN).readlines()
168 for line, zipline in zip(self.line_gen, ziplines):
169 self.assertEqual(zipline, line + '\n')
170
171 zipfp.close()
172
173 def zipIterlinesTest(self, f, compression):
174 self.makeTestArchive(f, compression)
175
176 # Read the ZIP archive
177 zipfp = zipfile.ZipFile(f, "r")
178 for line, zipline in zip(self.line_gen, zipfp.open(TESTFN)):
179 self.assertEqual(zipline, line + '\n')
180
181 zipfp.close()
Tim Petersea5962f2007-03-12 18:07:52 +0000182
183 def testReadlineStored(self):
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000184 for f in (TESTFN2, TemporaryFile(), StringIO()):
185 self.zipReadlineTest(f, zipfile.ZIP_STORED)
186
Tim Petersea5962f2007-03-12 18:07:52 +0000187 def testReadlinesStored(self):
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000188 for f in (TESTFN2, TemporaryFile(), StringIO()):
189 self.zipReadlinesTest(f, zipfile.ZIP_STORED)
190
Tim Petersea5962f2007-03-12 18:07:52 +0000191 def testIterlinesStored(self):
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000192 for f in (TESTFN2, TemporaryFile(), StringIO()):
193 self.zipIterlinesTest(f, zipfile.ZIP_STORED)
194
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +0000195 if zlib:
196 def testDeflated(self):
197 for f in (TESTFN2, TemporaryFile(), StringIO()):
198 self.zipTest(f, zipfile.ZIP_DEFLATED)
Raymond Hettingerc0fac962003-06-27 22:25:03 +0000199
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000200 def testOpenDeflated(self):
201 for f in (TESTFN2, TemporaryFile(), StringIO()):
202 self.zipOpenTest(f, zipfile.ZIP_DEFLATED)
203
204 def testRandomOpenDeflated(self):
205 for f in (TESTFN2, TemporaryFile(), StringIO()):
206 self.zipRandomOpenTest(f, zipfile.ZIP_DEFLATED)
207
Tim Petersea5962f2007-03-12 18:07:52 +0000208 def testReadlineDeflated(self):
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000209 for f in (TESTFN2, TemporaryFile(), StringIO()):
210 self.zipReadlineTest(f, zipfile.ZIP_DEFLATED)
211
Tim Petersea5962f2007-03-12 18:07:52 +0000212 def testReadlinesDeflated(self):
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000213 for f in (TESTFN2, TemporaryFile(), StringIO()):
214 self.zipReadlinesTest(f, zipfile.ZIP_DEFLATED)
215
Tim Petersea5962f2007-03-12 18:07:52 +0000216 def testIterlinesDeflated(self):
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000217 for f in (TESTFN2, TemporaryFile(), StringIO()):
218 self.zipIterlinesTest(f, zipfile.ZIP_DEFLATED)
Tim Petersea5962f2007-03-12 18:07:52 +0000219
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000220 def testLowCompression(self):
221 # Checks for cases where compressed data is larger than original
222 # Create the ZIP archive
223 zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_DEFLATED)
224 zipfp.writestr("strfile", '12')
225 zipfp.close()
226
227 # Get an open object for strfile
228 zipfp = zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_DEFLATED)
229 openobj = zipfp.open("strfile")
230 self.assertEqual(openobj.read(1), '1')
231 self.assertEqual(openobj.read(1), '2')
232
Georg Brandl8f7c54e2006-02-20 08:40:38 +0000233 def testAbsoluteArcnames(self):
234 zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED)
235 zipfp.write(TESTFN, "/absolute")
236 zipfp.close()
237
238 zipfp = zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_STORED)
239 self.assertEqual(zipfp.namelist(), ["absolute"])
240 zipfp.close()
Tim Peters32cbc962006-02-20 21:42:18 +0000241
Georg Brandl4b3ab6f2007-07-12 09:59:22 +0000242 def testAppendToZipFile(self):
243 # Test appending to an existing zipfile
244 zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED)
245 zipfp.write(TESTFN, TESTFN)
246 zipfp.close()
247 zipfp = zipfile.ZipFile(TESTFN2, "a", zipfile.ZIP_STORED)
248 zipfp.writestr("strfile", self.data)
249 self.assertEqual(zipfp.namelist(), [TESTFN, "strfile"])
250 zipfp.close()
251
252 def testAppendToNonZipFile(self):
253 # Test appending to an existing file that is not a zipfile
254 # NOTE: this test fails if len(d) < 22 because of the first
255 # line "fpin.seek(-22, 2)" in _EndRecData
256 d = 'I am not a ZipFile!'*10
257 f = file(TESTFN2, 'wb')
258 f.write(d)
259 f.close()
260 zipfp = zipfile.ZipFile(TESTFN2, "a", zipfile.ZIP_STORED)
261 zipfp.write(TESTFN, TESTFN)
262 zipfp.close()
263
264 f = file(TESTFN2, 'rb')
265 f.seek(len(d))
266 zipfp = zipfile.ZipFile(f, "r")
267 self.assertEqual(zipfp.namelist(), [TESTFN])
268 zipfp.close()
269 f.close()
270
271 def test_WriteDefaultName(self):
272 # Check that calling ZipFile.write without arcname specified produces the expected result
273 zipfp = zipfile.ZipFile(TESTFN2, "w")
274 zipfp.write(TESTFN)
275 self.assertEqual(zipfp.read(TESTFN), file(TESTFN).read())
276 zipfp.close()
277
278 def test_PerFileCompression(self):
279 # Check that files within a Zip archive can have different compression options
280 zipfp = zipfile.ZipFile(TESTFN2, "w")
281 zipfp.write(TESTFN, 'storeme', zipfile.ZIP_STORED)
282 zipfp.write(TESTFN, 'deflateme', zipfile.ZIP_DEFLATED)
283 sinfo = zipfp.getinfo('storeme')
284 dinfo = zipfp.getinfo('deflateme')
285 self.assertEqual(sinfo.compress_type, zipfile.ZIP_STORED)
286 self.assertEqual(dinfo.compress_type, zipfile.ZIP_DEFLATED)
287 zipfp.close()
288
289 def test_WriteToReadonly(self):
290 # Check that trying to call write() on a readonly ZipFile object
291 # raises a RuntimeError
292 zipf = zipfile.ZipFile(TESTFN2, mode="w")
293 zipf.writestr("somefile.txt", "bogus")
294 zipf.close()
295 zipf = zipfile.ZipFile(TESTFN2, mode="r")
296 self.assertRaises(RuntimeError, zipf.write, TESTFN)
297 zipf.close()
298
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +0000299 def tearDown(self):
300 os.remove(TESTFN)
301 os.remove(TESTFN2)
302
Ronald Oussoren143cefb2006-06-15 08:14:18 +0000303class TestZip64InSmallFiles(unittest.TestCase):
304 # These tests test the ZIP64 functionality without using large files,
305 # see test_zipfile64 for proper tests.
306
307 def setUp(self):
308 self._limit = zipfile.ZIP64_LIMIT
309 zipfile.ZIP64_LIMIT = 5
310
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000311 line_gen = ("Test of zipfile line %d." % i for i in range(0, FIXEDTEST_SIZE))
Ronald Oussoren143cefb2006-06-15 08:14:18 +0000312 self.data = '\n'.join(line_gen)
313
314 # Make a source file with some lines
315 fp = open(TESTFN, "wb")
316 fp.write(self.data)
317 fp.close()
318
319 def largeFileExceptionTest(self, f, compression):
320 zipfp = zipfile.ZipFile(f, "w", compression)
Tim Petersa608bb22006-06-15 18:06:29 +0000321 self.assertRaises(zipfile.LargeZipFile,
Ronald Oussoren143cefb2006-06-15 08:14:18 +0000322 zipfp.write, TESTFN, "another"+os.extsep+"name")
323 zipfp.close()
324
325 def largeFileExceptionTest2(self, f, compression):
326 zipfp = zipfile.ZipFile(f, "w", compression)
Tim Petersa608bb22006-06-15 18:06:29 +0000327 self.assertRaises(zipfile.LargeZipFile,
Ronald Oussoren143cefb2006-06-15 08:14:18 +0000328 zipfp.writestr, "another"+os.extsep+"name", self.data)
329 zipfp.close()
330
331 def testLargeFileException(self):
332 for f in (TESTFN2, TemporaryFile(), StringIO()):
333 self.largeFileExceptionTest(f, zipfile.ZIP_STORED)
334 self.largeFileExceptionTest2(f, zipfile.ZIP_STORED)
335
336 def zipTest(self, f, compression):
337 # Create the ZIP archive
338 zipfp = zipfile.ZipFile(f, "w", compression, allowZip64=True)
339 zipfp.write(TESTFN, "another"+os.extsep+"name")
340 zipfp.write(TESTFN, TESTFN)
341 zipfp.writestr("strfile", self.data)
342 zipfp.close()
343
344 # Read the ZIP archive
345 zipfp = zipfile.ZipFile(f, "r", compression)
346 self.assertEqual(zipfp.read(TESTFN), self.data)
347 self.assertEqual(zipfp.read("another"+os.extsep+"name"), self.data)
348 self.assertEqual(zipfp.read("strfile"), self.data)
349
350 # Print the ZIP directory
351 fp = StringIO()
352 stdout = sys.stdout
353 try:
354 sys.stdout = fp
355
356 zipfp.printdir()
357 finally:
358 sys.stdout = stdout
Tim Petersa608bb22006-06-15 18:06:29 +0000359
Ronald Oussoren143cefb2006-06-15 08:14:18 +0000360 directory = fp.getvalue()
361 lines = directory.splitlines()
362 self.assertEquals(len(lines), 4) # Number of files + header
363
364 self.assert_('File Name' in lines[0])
365 self.assert_('Modified' in lines[0])
366 self.assert_('Size' in lines[0])
367
368 fn, date, time, size = lines[1].split()
369 self.assertEquals(fn, 'another.name')
370 # XXX: timestamp is not tested
371 self.assertEquals(size, str(len(self.data)))
372
373 # Check the namelist
374 names = zipfp.namelist()
375 self.assertEquals(len(names), 3)
376 self.assert_(TESTFN in names)
377 self.assert_("another"+os.extsep+"name" in names)
378 self.assert_("strfile" in names)
379
380 # Check infolist
381 infos = zipfp.infolist()
382 names = [ i.filename for i in infos ]
383 self.assertEquals(len(names), 3)
384 self.assert_(TESTFN in names)
385 self.assert_("another"+os.extsep+"name" in names)
386 self.assert_("strfile" in names)
387 for i in infos:
388 self.assertEquals(i.file_size, len(self.data))
389
390 # check getinfo
391 for nm in (TESTFN, "another"+os.extsep+"name", "strfile"):
392 info = zipfp.getinfo(nm)
393 self.assertEquals(info.filename, nm)
394 self.assertEquals(info.file_size, len(self.data))
395
396 # Check that testzip doesn't raise an exception
397 zipfp.testzip()
398
399
400 zipfp.close()
401
402 def testStored(self):
403 for f in (TESTFN2, TemporaryFile(), StringIO()):
404 self.zipTest(f, zipfile.ZIP_STORED)
405
406
407 if zlib:
408 def testDeflated(self):
409 for f in (TESTFN2, TemporaryFile(), StringIO()):
410 self.zipTest(f, zipfile.ZIP_DEFLATED)
411
412 def testAbsoluteArcnames(self):
413 zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED, allowZip64=True)
414 zipfp.write(TESTFN, "/absolute")
415 zipfp.close()
416
417 zipfp = zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_STORED)
418 self.assertEqual(zipfp.namelist(), ["absolute"])
419 zipfp.close()
420
Ronald Oussoren143cefb2006-06-15 08:14:18 +0000421 def tearDown(self):
422 zipfile.ZIP64_LIMIT = self._limit
423 os.remove(TESTFN)
424 os.remove(TESTFN2)
425
426class PyZipFileTests(unittest.TestCase):
427 def testWritePyfile(self):
428 zipfp = zipfile.PyZipFile(TemporaryFile(), "w")
429 fn = __file__
430 if fn.endswith('.pyc') or fn.endswith('.pyo'):
431 fn = fn[:-1]
432
433 zipfp.writepy(fn)
434
435 bn = os.path.basename(fn)
436 self.assert_(bn not in zipfp.namelist())
437 self.assert_(bn + 'o' in zipfp.namelist() or bn + 'c' in zipfp.namelist())
438 zipfp.close()
439
440
441 zipfp = zipfile.PyZipFile(TemporaryFile(), "w")
442 fn = __file__
443 if fn.endswith('.pyc') or fn.endswith('.pyo'):
444 fn = fn[:-1]
445
446 zipfp.writepy(fn, "testpackage")
447
448 bn = "%s/%s"%("testpackage", os.path.basename(fn))
449 self.assert_(bn not in zipfp.namelist())
450 self.assert_(bn + 'o' in zipfp.namelist() or bn + 'c' in zipfp.namelist())
451 zipfp.close()
452
453 def testWritePythonPackage(self):
454 import email
455 packagedir = os.path.dirname(email.__file__)
456
457 zipfp = zipfile.PyZipFile(TemporaryFile(), "w")
458 zipfp.writepy(packagedir)
459
460 # Check for a couple of modules at different levels of the hieararchy
461 names = zipfp.namelist()
462 self.assert_('email/__init__.pyo' in names or 'email/__init__.pyc' in names)
463 self.assert_('email/mime/text.pyo' in names or 'email/mime/text.pyc' in names)
464
465 def testWritePythonDirectory(self):
466 os.mkdir(TESTFN2)
467 try:
468 fp = open(os.path.join(TESTFN2, "mod1.py"), "w")
469 fp.write("print 42\n")
470 fp.close()
471
472 fp = open(os.path.join(TESTFN2, "mod2.py"), "w")
473 fp.write("print 42 * 42\n")
474 fp.close()
475
476 fp = open(os.path.join(TESTFN2, "mod2.txt"), "w")
477 fp.write("bla bla bla\n")
478 fp.close()
479
480 zipfp = zipfile.PyZipFile(TemporaryFile(), "w")
481 zipfp.writepy(TESTFN2)
482
483 names = zipfp.namelist()
484 self.assert_('mod1.pyc' in names or 'mod1.pyo' in names)
485 self.assert_('mod2.pyc' in names or 'mod2.pyo' in names)
486 self.assert_('mod2.txt' not in names)
487
488 finally:
489 shutil.rmtree(TESTFN2)
490
Georg Brandl4b3ab6f2007-07-12 09:59:22 +0000491 def testWriteNonPyfile(self):
492 zipfp = zipfile.PyZipFile(TemporaryFile(), "w")
493 file(TESTFN, 'w').write('most definitely not a python file')
494 self.assertRaises(RuntimeError, zipfp.writepy, TESTFN)
495 os.remove(TESTFN)
Ronald Oussoren143cefb2006-06-15 08:14:18 +0000496
497
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +0000498class OtherTests(unittest.TestCase):
Martin v. Löwis84f6de92007-02-13 10:10:39 +0000499 def testCreateNonExistentFileForAppend(self):
500 if os.path.exists(TESTFN):
501 os.unlink(TESTFN)
Tim Petersea5962f2007-03-12 18:07:52 +0000502
Martin v. Löwis84f6de92007-02-13 10:10:39 +0000503 filename = 'testfile.txt'
504 content = 'hello, world. this is some content.'
Tim Petersea5962f2007-03-12 18:07:52 +0000505
Martin v. Löwis84f6de92007-02-13 10:10:39 +0000506 try:
507 zf = zipfile.ZipFile(TESTFN, 'a')
508 zf.writestr(filename, content)
509 zf.close()
510 except IOError, (errno, errmsg):
511 self.fail('Could not append data to a non-existent zip file.')
512
513 self.assert_(os.path.exists(TESTFN))
514
515 zf = zipfile.ZipFile(TESTFN, 'r')
516 self.assertEqual(zf.read(filename), content)
517 zf.close()
Tim Petersea5962f2007-03-12 18:07:52 +0000518
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +0000519 def testCloseErroneousFile(self):
520 # This test checks that the ZipFile constructor closes the file object
521 # it opens if there's an error in the file. If it doesn't, the traceback
522 # holds a reference to the ZipFile object and, indirectly, the file object.
523 # On Windows, this causes the os.unlink() call to fail because the
524 # underlying file is still open. This is SF bug #412214.
525 #
526 fp = open(TESTFN, "w")
527 fp.write("this is not a legal zip file\n")
528 fp.close()
529 try:
530 zf = zipfile.ZipFile(TESTFN)
531 except zipfile.BadZipfile:
Collin Winter04a51ec2007-03-29 02:28:16 +0000532 pass
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +0000533
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000534 def testIsZipErroneousFile(self):
Tim Petersea5962f2007-03-12 18:07:52 +0000535 # This test checks that the is_zipfile function correctly identifies
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000536 # a file that is not a zip file
537 fp = open(TESTFN, "w")
538 fp.write("this is not a legal zip file\n")
539 fp.close()
Tim Petersea5962f2007-03-12 18:07:52 +0000540 chk = zipfile.is_zipfile(TESTFN)
Tim Petersea5962f2007-03-12 18:07:52 +0000541 self.assert_(chk is False)
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000542
543 def testIsZipValidFile(self):
Tim Petersea5962f2007-03-12 18:07:52 +0000544 # This test checks that the is_zipfile function correctly identifies
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000545 # a file that is a zip file
546 zipf = zipfile.ZipFile(TESTFN, mode="w")
547 zipf.writestr("foo.txt", "O, for a Muse of Fire!")
548 zipf.close()
Tim Petersea5962f2007-03-12 18:07:52 +0000549 chk = zipfile.is_zipfile(TESTFN)
Tim Petersea5962f2007-03-12 18:07:52 +0000550 self.assert_(chk is True)
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000551
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +0000552 def testNonExistentFileRaisesIOError(self):
553 # make sure we don't raise an AttributeError when a partially-constructed
554 # ZipFile instance is finalized; this tests for regression on SF tracker
555 # bug #403871.
556
557 # The bug we're testing for caused an AttributeError to be raised
558 # when a ZipFile instance was created for a file that did not
559 # exist; the .fp member was not initialized but was needed by the
560 # __del__() method. Since the AttributeError is in the __del__(),
561 # it is ignored, but the user should be sufficiently annoyed by
562 # the message on the output that regression will be noticed
563 # quickly.
564 self.assertRaises(IOError, zipfile.ZipFile, TESTFN)
565
566 def testClosedZipRaisesRuntimeError(self):
567 # Verify that testzip() doesn't swallow inappropriate exceptions.
568 data = StringIO()
569 zipf = zipfile.ZipFile(data, mode="w")
570 zipf.writestr("foo.txt", "O, for a Muse of Fire!")
571 zipf.close()
572
573 # This is correct; calling .read on a closed ZipFile should throw
574 # a RuntimeError, and so should calling .testzip. An earlier
575 # version of .testzip would swallow this exception (and any other)
576 # and report that the first file in the archive was corrupt.
Georg Brandl4b3ab6f2007-07-12 09:59:22 +0000577 self.assertRaises(RuntimeError, zipf.read, "foo.txt")
578 self.assertRaises(RuntimeError, zipf.open, "foo.txt")
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +0000579 self.assertRaises(RuntimeError, zipf.testzip)
Georg Brandl4b3ab6f2007-07-12 09:59:22 +0000580 self.assertRaises(RuntimeError, zipf.writestr, "bogus.txt", "bogus")
581 file(TESTFN, 'w').write('zipfile test data')
582 self.assertRaises(RuntimeError, zipf.write, TESTFN)
583
584 def test_BadConstructorMode(self):
585 # Check that bad modes passed to ZipFile constructor are caught
586 self.assertRaises(RuntimeError, zipfile.ZipFile, TESTFN, "q")
587
588 def test_BadOpenMode(self):
589 # Check that bad modes passed to ZipFile.open are caught
590 zipf = zipfile.ZipFile(TESTFN, mode="w")
591 zipf.writestr("foo.txt", "O, for a Muse of Fire!")
592 zipf.close()
593 zipf = zipfile.ZipFile(TESTFN, mode="r")
594 # read the data to make sure the file is there
595 zipf.read("foo.txt")
596 self.assertRaises(RuntimeError, zipf.open, "foo.txt", "q")
597 zipf.close()
598
599 def test_Read0(self):
600 # Check that calling read(0) on a ZipExtFile object returns an empty
601 # string and doesn't advance file pointer
602 zipf = zipfile.ZipFile(TESTFN, mode="w")
603 zipf.writestr("foo.txt", "O, for a Muse of Fire!")
604 # read the data to make sure the file is there
605 f = zipf.open("foo.txt")
606 for i in xrange(FIXEDTEST_SIZE):
607 self.assertEqual(f.read(0), '')
608
609 self.assertEqual(f.read(), "O, for a Muse of Fire!")
610 zipf.close()
611
612 def test_OpenNonexistentItem(self):
613 # Check that attempting to call open() for an item that doesn't
614 # exist in the archive raises a RuntimeError
615 zipf = zipfile.ZipFile(TESTFN, mode="w")
616 self.assertRaises(KeyError, zipf.open, "foo.txt", "r")
617
618 def test_BadCompressionMode(self):
619 # Check that bad compression methods passed to ZipFile.open are caught
620 self.assertRaises(RuntimeError, zipfile.ZipFile, TESTFN, "w", -1)
621
622 def test_NullByteInFilename(self):
623 # Check that a filename containing a null byte is properly terminated
624 zipf = zipfile.ZipFile(TESTFN, mode="w")
625 zipf.writestr("foo.txt\x00qqq", "O, for a Muse of Fire!")
626 self.assertEqual(zipf.namelist(), ['foo.txt'])
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000627
Collin Winter04a51ec2007-03-29 02:28:16 +0000628 def tearDown(self):
629 support.unlink(TESTFN)
630 support.unlink(TESTFN2)
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +0000631
Martin v. Löwisc6d626e2007-02-13 09:49:38 +0000632class DecryptionTests(unittest.TestCase):
633 # This test checks that ZIP decryption works. Since the library does not
634 # support encryption at the moment, we use a pre-generated encrypted
635 # ZIP file
636
637 data = (
638 'PK\x03\x04\x14\x00\x01\x00\x00\x00n\x92i.#y\xef?&\x00\x00\x00\x1a\x00'
639 '\x00\x00\x08\x00\x00\x00test.txt\xfa\x10\xa0gly|\xfa-\xc5\xc0=\xf9y'
640 '\x18\xe0\xa8r\xb3Z}Lg\xbc\xae\xf9|\x9b\x19\xe4\x8b\xba\xbb)\x8c\xb0\xdbl'
641 'PK\x01\x02\x14\x00\x14\x00\x01\x00\x00\x00n\x92i.#y\xef?&\x00\x00\x00'
642 '\x1a\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x01\x00 \x00\xb6\x81'
643 '\x00\x00\x00\x00test.txtPK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x006\x00'
644 '\x00\x00L\x00\x00\x00\x00\x00' )
645
646 plain = 'zipfile.py encryption test'
647
648 def setUp(self):
649 fp = open(TESTFN, "wb")
650 fp.write(self.data)
651 fp.close()
652 self.zip = zipfile.ZipFile(TESTFN, "r")
653
654 def tearDown(self):
655 self.zip.close()
656 os.unlink(TESTFN)
657
658 def testNoPassword(self):
659 # Reading the encrypted file without password
660 # must generate a RunTime exception
661 self.assertRaises(RuntimeError, self.zip.read, "test.txt")
662
663 def testBadPassword(self):
664 self.zip.setpassword("perl")
665 self.assertRaises(RuntimeError, self.zip.read, "test.txt")
Tim Petersea5962f2007-03-12 18:07:52 +0000666
Martin v. Löwisc6d626e2007-02-13 09:49:38 +0000667 def testGoodPassword(self):
668 self.zip.setpassword("python")
669 self.assertEquals(self.zip.read("test.txt"), self.plain)
670
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000671
672class TestsWithRandomBinaryFiles(unittest.TestCase):
673 def setUp(self):
674 datacount = randint(16, 64)*1024 + randint(1, 1024)
675 self.data = ''.join((struct.pack('<f', random()*randint(-1000, 1000)) for i in xrange(datacount)))
676
677 # Make a source file with some lines
678 fp = open(TESTFN, "wb")
679 fp.write(self.data)
680 fp.close()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000681
Collin Winter04a51ec2007-03-29 02:28:16 +0000682 def tearDown(self):
683 support.unlink(TESTFN)
684 support.unlink(TESTFN2)
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000685
686 def makeTestArchive(self, f, compression):
687 # Create the ZIP archive
688 zipfp = zipfile.ZipFile(f, "w", compression)
689 zipfp.write(TESTFN, "another"+os.extsep+"name")
690 zipfp.write(TESTFN, TESTFN)
691 zipfp.close()
692
693 def zipTest(self, f, compression):
694 self.makeTestArchive(f, compression)
695
696 # Read the ZIP archive
697 zipfp = zipfile.ZipFile(f, "r", compression)
698 testdata = zipfp.read(TESTFN)
699 self.assertEqual(len(testdata), len(self.data))
700 self.assertEqual(testdata, self.data)
701 self.assertEqual(zipfp.read("another"+os.extsep+"name"), self.data)
702 zipfp.close()
703
704 def testStored(self):
705 for f in (TESTFN2, TemporaryFile(), StringIO()):
706 self.zipTest(f, zipfile.ZIP_STORED)
Tim Petersea5962f2007-03-12 18:07:52 +0000707
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000708 def zipOpenTest(self, f, compression):
709 self.makeTestArchive(f, compression)
710
711 # Read the ZIP archive
712 zipfp = zipfile.ZipFile(f, "r", compression)
713 zipdata1 = []
714 zipopen1 = zipfp.open(TESTFN)
715 while 1:
716 read_data = zipopen1.read(256)
717 if not read_data:
718 break
719 zipdata1.append(read_data)
720
721 zipdata2 = []
722 zipopen2 = zipfp.open("another"+os.extsep+"name")
723 while 1:
724 read_data = zipopen2.read(256)
725 if not read_data:
726 break
727 zipdata2.append(read_data)
Tim Petersea5962f2007-03-12 18:07:52 +0000728
729 testdata1 = ''.join(zipdata1)
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000730 self.assertEqual(len(testdata1), len(self.data))
731 self.assertEqual(testdata1, self.data)
732
Tim Petersea5962f2007-03-12 18:07:52 +0000733 testdata2 = ''.join(zipdata2)
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000734 self.assertEqual(len(testdata1), len(self.data))
735 self.assertEqual(testdata1, self.data)
736 zipfp.close()
Tim Petersea5962f2007-03-12 18:07:52 +0000737
738 def testOpenStored(self):
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000739 for f in (TESTFN2, TemporaryFile(), StringIO()):
740 self.zipOpenTest(f, zipfile.ZIP_STORED)
741
742 def zipRandomOpenTest(self, f, compression):
743 self.makeTestArchive(f, compression)
744
745 # Read the ZIP archive
746 zipfp = zipfile.ZipFile(f, "r", compression)
747 zipdata1 = []
748 zipopen1 = zipfp.open(TESTFN)
749 while 1:
750 read_data = zipopen1.read(randint(1, 1024))
751 if not read_data:
752 break
753 zipdata1.append(read_data)
754
755 testdata = ''.join(zipdata1)
756 self.assertEqual(len(testdata), len(self.data))
757 self.assertEqual(testdata, self.data)
758 zipfp.close()
Tim Petersea5962f2007-03-12 18:07:52 +0000759
760 def testRandomOpenStored(self):
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000761 for f in (TESTFN2, TemporaryFile(), StringIO()):
762 self.zipRandomOpenTest(f, zipfile.ZIP_STORED)
763
764class TestsWithMultipleOpens(unittest.TestCase):
765 def setUp(self):
766 # Create the ZIP archive
767 zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_DEFLATED)
768 zipfp.writestr('ones', '1'*FIXEDTEST_SIZE)
769 zipfp.writestr('twos', '2'*FIXEDTEST_SIZE)
770 zipfp.close()
Tim Petersea5962f2007-03-12 18:07:52 +0000771
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000772 def testSameFile(self):
773 # Verify that (when the ZipFile is in control of creating file objects)
774 # multiple open() calls can be made without interfering with each other.
775 zipf = zipfile.ZipFile(TESTFN2, mode="r")
776 zopen1 = zipf.open('ones')
777 zopen2 = zipf.open('ones')
778 data1 = zopen1.read(500)
779 data2 = zopen2.read(500)
780 data1 += zopen1.read(500)
781 data2 += zopen2.read(500)
782 self.assertEqual(data1, data2)
783 zipf.close()
784
785 def testDifferentFile(self):
786 # Verify that (when the ZipFile is in control of creating file objects)
787 # multiple open() calls can be made without interfering with each other.
788 zipf = zipfile.ZipFile(TESTFN2, mode="r")
789 zopen1 = zipf.open('ones')
790 zopen2 = zipf.open('twos')
791 data1 = zopen1.read(500)
792 data2 = zopen2.read(500)
793 data1 += zopen1.read(500)
794 data2 += zopen2.read(500)
795 self.assertEqual(data1, '1'*FIXEDTEST_SIZE)
796 self.assertEqual(data2, '2'*FIXEDTEST_SIZE)
797 zipf.close()
798
799 def testInterleaved(self):
800 # Verify that (when the ZipFile is in control of creating file objects)
801 # multiple open() calls can be made without interfering with each other.
802 zipf = zipfile.ZipFile(TESTFN2, mode="r")
803 zopen1 = zipf.open('ones')
804 data1 = zopen1.read(500)
805 zopen2 = zipf.open('twos')
806 data2 = zopen2.read(500)
807 data1 += zopen1.read(500)
808 data2 += zopen2.read(500)
809 self.assertEqual(data1, '1'*FIXEDTEST_SIZE)
810 self.assertEqual(data2, '2'*FIXEDTEST_SIZE)
811 zipf.close()
Tim Petersea5962f2007-03-12 18:07:52 +0000812
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000813 def tearDown(self):
814 os.remove(TESTFN2)
Tim Petersea5962f2007-03-12 18:07:52 +0000815
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000816
817class UniversalNewlineTests(unittest.TestCase):
818 def setUp(self):
819 self.line_gen = ["Test of zipfile line %d." % i for i in xrange(FIXEDTEST_SIZE)]
820 self.seps = ('\r', '\r\n', '\n')
821 self.arcdata, self.arcfiles = {}, {}
822 for n, s in enumerate(self.seps):
823 self.arcdata[s] = s.join(self.line_gen) + s
824 self.arcfiles[s] = '%s-%d' % (TESTFN, n)
Brett Cannon6cef0762007-05-25 20:17:15 +0000825 open(self.arcfiles[s], "wb").write(self.arcdata[s])
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000826
827 def makeTestArchive(self, f, compression):
828 # Create the ZIP archive
829 zipfp = zipfile.ZipFile(f, "w", compression)
830 for fn in self.arcfiles.values():
831 zipfp.write(fn, fn)
832 zipfp.close()
833
834 def readTest(self, f, compression):
835 self.makeTestArchive(f, compression)
836
837 # Read the ZIP archive
838 zipfp = zipfile.ZipFile(f, "r")
839 for sep, fn in self.arcfiles.items():
840 zipdata = zipfp.open(fn, "rU").read()
841 self.assertEqual(self.arcdata[sep], zipdata)
842
843 zipfp.close()
Tim Petersea5962f2007-03-12 18:07:52 +0000844
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000845 def readlineTest(self, f, compression):
846 self.makeTestArchive(f, compression)
847
848 # Read the ZIP archive
849 zipfp = zipfile.ZipFile(f, "r")
850 for sep, fn in self.arcfiles.items():
851 zipopen = zipfp.open(fn, "rU")
852 for line in self.line_gen:
853 linedata = zipopen.readline()
854 self.assertEqual(linedata, line + '\n')
855
856 zipfp.close()
857
858 def readlinesTest(self, f, compression):
859 self.makeTestArchive(f, compression)
860
861 # Read the ZIP archive
862 zipfp = zipfile.ZipFile(f, "r")
863 for sep, fn in self.arcfiles.items():
864 ziplines = zipfp.open(fn, "rU").readlines()
865 for line, zipline in zip(self.line_gen, ziplines):
866 self.assertEqual(zipline, line + '\n')
867
868 zipfp.close()
869
870 def iterlinesTest(self, f, compression):
871 self.makeTestArchive(f, compression)
872
873 # Read the ZIP archive
874 zipfp = zipfile.ZipFile(f, "r")
875 for sep, fn in self.arcfiles.items():
876 for line, zipline in zip(self.line_gen, zipfp.open(fn, "rU")):
877 self.assertEqual(zipline, line + '\n')
878
879 zipfp.close()
880
Tim Petersea5962f2007-03-12 18:07:52 +0000881 def testReadStored(self):
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000882 for f in (TESTFN2, TemporaryFile(), StringIO()):
883 self.readTest(f, zipfile.ZIP_STORED)
Tim Petersea5962f2007-03-12 18:07:52 +0000884
885 def testReadlineStored(self):
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000886 for f in (TESTFN2, TemporaryFile(), StringIO()):
887 self.readlineTest(f, zipfile.ZIP_STORED)
888
Tim Petersea5962f2007-03-12 18:07:52 +0000889 def testReadlinesStored(self):
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000890 for f in (TESTFN2, TemporaryFile(), StringIO()):
891 self.readlinesTest(f, zipfile.ZIP_STORED)
892
Tim Petersea5962f2007-03-12 18:07:52 +0000893 def testIterlinesStored(self):
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000894 for f in (TESTFN2, TemporaryFile(), StringIO()):
895 self.iterlinesTest(f, zipfile.ZIP_STORED)
Tim Petersea5962f2007-03-12 18:07:52 +0000896
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000897 if zlib:
Tim Petersea5962f2007-03-12 18:07:52 +0000898 def testReadDeflated(self):
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000899 for f in (TESTFN2, TemporaryFile(), StringIO()):
900 self.readTest(f, zipfile.ZIP_DEFLATED)
901
Tim Petersea5962f2007-03-12 18:07:52 +0000902 def testReadlineDeflated(self):
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000903 for f in (TESTFN2, TemporaryFile(), StringIO()):
904 self.readlineTest(f, zipfile.ZIP_DEFLATED)
905
Tim Petersea5962f2007-03-12 18:07:52 +0000906 def testReadlinesDeflated(self):
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000907 for f in (TESTFN2, TemporaryFile(), StringIO()):
908 self.readlinesTest(f, zipfile.ZIP_DEFLATED)
909
Tim Petersea5962f2007-03-12 18:07:52 +0000910 def testIterlinesDeflated(self):
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000911 for f in (TESTFN2, TemporaryFile(), StringIO()):
912 self.iterlinesTest(f, zipfile.ZIP_DEFLATED)
913
914 def tearDown(self):
915 for sep, fn in self.arcfiles.items():
916 os.remove(fn)
Collin Winter04a51ec2007-03-29 02:28:16 +0000917 support.unlink(TESTFN)
918 support.unlink(TESTFN2)
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000919
920
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +0000921def test_main():
Tim Petersea5962f2007-03-12 18:07:52 +0000922 run_unittest(TestsWithSourceFile, TestZip64InSmallFiles, OtherTests,
923 PyZipFileTests, DecryptionTests, TestsWithMultipleOpens,
Martin v. Löwis3eb76482007-03-06 10:41:24 +0000924 UniversalNewlineTests, TestsWithRandomBinaryFiles)
925
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +0000926if __name__ == "__main__":
927 test_main()