blob: eda686323faf6ecac13938e9e8cd62fe768dd70c [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
Guido van Rossumd6ca5462007-05-22 01:29:33 +00006import zipfile, os, unittest, sys, shutil, struct, io
Tim Petersa45cacf2004-08-20 03:47:14 +00007
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +00008from tempfile import TemporaryFile
Guido van Rossumd8faa362007-04-27 19:54:29 +00009from random import randint, random
Tim Petersa19a1682001-03-29 04:36:09 +000010
Guido van Rossumd8faa362007-04-27 19:54:29 +000011import test.test_support as support
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +000012from test.test_support import TESTFN, run_unittest
Guido van Rossum368f04a2000-04-10 13:23:04 +000013
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +000014TESTFN2 = TESTFN + "2"
Guido van Rossumb5a755e2007-07-18 18:15:48 +000015FIXEDTEST_SIZE = 1000
Guido van Rossum368f04a2000-04-10 13:23:04 +000016
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +000017class TestsWithSourceFile(unittest.TestCase):
18 def setUp(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +000019 self.line_gen = (bytes("Zipfile test line %d. random float: %f" %
20 (i, random()))
21 for i in range(FIXEDTEST_SIZE))
22 self.data = b'\n'.join(self.line_gen) + b'\n'
Fred Drake6e7e4852001-02-28 05:34:16 +000023
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +000024 # Make a source file with some lines
25 fp = open(TESTFN, "wb")
26 fp.write(self.data)
27 fp.close()
Tim Peters7d3bad62001-04-04 18:56:49 +000028
Guido van Rossumd8faa362007-04-27 19:54:29 +000029 def makeTestArchive(self, f, compression):
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +000030 # Create the ZIP archive
31 zipfp = zipfile.ZipFile(f, "w", compression)
32 zipfp.write(TESTFN, "another"+os.extsep+"name")
33 zipfp.write(TESTFN, TESTFN)
Thomas Wouters0e3f5912006-08-11 14:57:12 +000034 zipfp.writestr("strfile", self.data)
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +000035 zipfp.close()
Tim Peters7d3bad62001-04-04 18:56:49 +000036
Guido van Rossumd8faa362007-04-27 19:54:29 +000037 def zipTest(self, f, compression):
38 self.makeTestArchive(f, compression)
39
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +000040 # Read the ZIP archive
41 zipfp = zipfile.ZipFile(f, "r", compression)
42 self.assertEqual(zipfp.read(TESTFN), self.data)
43 self.assertEqual(zipfp.read("another"+os.extsep+"name"), self.data)
Thomas Wouters0e3f5912006-08-11 14:57:12 +000044 self.assertEqual(zipfp.read("strfile"), self.data)
45
46 # Print the ZIP directory
Guido van Rossumd6ca5462007-05-22 01:29:33 +000047 fp = io.StringIO()
48 zipfp.printdir(file=fp)
Thomas Wouters0e3f5912006-08-11 14:57:12 +000049
50 directory = fp.getvalue()
51 lines = directory.splitlines()
52 self.assertEquals(len(lines), 4) # Number of files + header
53
54 self.assert_('File Name' in lines[0])
55 self.assert_('Modified' in lines[0])
56 self.assert_('Size' in lines[0])
57
58 fn, date, time, size = lines[1].split()
59 self.assertEquals(fn, 'another.name')
60 # XXX: timestamp is not tested
61 self.assertEquals(size, str(len(self.data)))
62
63 # Check the namelist
64 names = zipfp.namelist()
65 self.assertEquals(len(names), 3)
66 self.assert_(TESTFN in names)
67 self.assert_("another"+os.extsep+"name" in names)
68 self.assert_("strfile" in names)
69
70 # Check infolist
71 infos = zipfp.infolist()
72 names = [ i.filename for i in infos ]
73 self.assertEquals(len(names), 3)
74 self.assert_(TESTFN in names)
75 self.assert_("another"+os.extsep+"name" in names)
76 self.assert_("strfile" in names)
77 for i in infos:
78 self.assertEquals(i.file_size, len(self.data))
79
80 # check getinfo
81 for nm in (TESTFN, "another"+os.extsep+"name", "strfile"):
82 info = zipfp.getinfo(nm)
83 self.assertEquals(info.filename, nm)
84 self.assertEquals(info.file_size, len(self.data))
85
86 # Check that testzip doesn't raise an exception
87 zipfp.testzip()
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +000088 zipfp.close()
Tim Peters7d3bad62001-04-04 18:56:49 +000089
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +000090 def testStored(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +000091 for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +000092 self.zipTest(f, zipfile.ZIP_STORED)
Raymond Hettingerc0fac962003-06-27 22:25:03 +000093
Guido van Rossumd8faa362007-04-27 19:54:29 +000094 def zipOpenTest(self, f, compression):
95 self.makeTestArchive(f, compression)
96
97 # Read the ZIP archive
98 zipfp = zipfile.ZipFile(f, "r", compression)
99 zipdata1 = []
100 zipopen1 = zipfp.open(TESTFN)
101 while 1:
102 read_data = zipopen1.read(256)
103 if not read_data:
104 break
105 zipdata1.append(read_data)
106
107 zipdata2 = []
108 zipopen2 = zipfp.open("another"+os.extsep+"name")
109 while 1:
110 read_data = zipopen2.read(256)
111 if not read_data:
112 break
113 zipdata2.append(read_data)
114
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000115 self.assertEqual(b''.join(zipdata1), self.data)
116 self.assertEqual(b''.join(zipdata2), self.data)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000117 zipfp.close()
118
119 def testOpenStored(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000120 for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000121 self.zipOpenTest(f, zipfile.ZIP_STORED)
122
123 def zipRandomOpenTest(self, f, compression):
124 self.makeTestArchive(f, compression)
125
126 # Read the ZIP archive
127 zipfp = zipfile.ZipFile(f, "r", compression)
128 zipdata1 = []
129 zipopen1 = zipfp.open(TESTFN)
130 while 1:
131 read_data = zipopen1.read(randint(1, 1024))
132 if not read_data:
133 break
134 zipdata1.append(read_data)
135
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000136 self.assertEqual(b''.join(zipdata1), self.data)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000137 zipfp.close()
138
139 def testRandomOpenStored(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000140 for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000141 self.zipRandomOpenTest(f, zipfile.ZIP_STORED)
142
143 def zipReadlineTest(self, f, compression):
144 self.makeTestArchive(f, compression)
145
146 # Read the ZIP archive
147 zipfp = zipfile.ZipFile(f, "r")
148 zipopen = zipfp.open(TESTFN)
149 for line in self.line_gen:
150 linedata = zipopen.readline()
151 self.assertEqual(linedata, line + '\n')
152
153 zipfp.close()
154
155 def zipReadlinesTest(self, f, compression):
156 self.makeTestArchive(f, compression)
157
158 # Read the ZIP archive
159 zipfp = zipfile.ZipFile(f, "r")
160 ziplines = zipfp.open(TESTFN).readlines()
161 for line, zipline in zip(self.line_gen, ziplines):
162 self.assertEqual(zipline, line + '\n')
163
164 zipfp.close()
165
166 def zipIterlinesTest(self, f, compression):
167 self.makeTestArchive(f, compression)
168
169 # Read the ZIP archive
170 zipfp = zipfile.ZipFile(f, "r")
171 for line, zipline in zip(self.line_gen, zipfp.open(TESTFN)):
172 self.assertEqual(zipline, line + '\n')
173
174 zipfp.close()
175
176 def testReadlineStored(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000177 for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000178 self.zipReadlineTest(f, zipfile.ZIP_STORED)
179
180 def testReadlinesStored(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000181 for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000182 self.zipReadlinesTest(f, zipfile.ZIP_STORED)
183
184 def testIterlinesStored(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000185 for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000186 self.zipIterlinesTest(f, zipfile.ZIP_STORED)
187
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +0000188 if zlib:
189 def testDeflated(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000190 for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +0000191 self.zipTest(f, zipfile.ZIP_DEFLATED)
Raymond Hettingerc0fac962003-06-27 22:25:03 +0000192
Guido van Rossumd8faa362007-04-27 19:54:29 +0000193 def testOpenDeflated(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000194 for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000195 self.zipOpenTest(f, zipfile.ZIP_DEFLATED)
196
197 def testRandomOpenDeflated(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000198 for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000199 self.zipRandomOpenTest(f, zipfile.ZIP_DEFLATED)
200
201 def testReadlineDeflated(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000202 for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000203 self.zipReadlineTest(f, zipfile.ZIP_DEFLATED)
204
205 def testReadlinesDeflated(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000206 for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000207 self.zipReadlinesTest(f, zipfile.ZIP_DEFLATED)
208
209 def testIterlinesDeflated(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000210 for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000211 self.zipIterlinesTest(f, zipfile.ZIP_DEFLATED)
212
213 def testLowCompression(self):
214 # Checks for cases where compressed data is larger than original
215 # Create the ZIP archive
216 zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_DEFLATED)
217 zipfp.writestr("strfile", '12')
218 zipfp.close()
219
220 # Get an open object for strfile
221 zipfp = zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_DEFLATED)
222 openobj = zipfp.open("strfile")
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000223 self.assertEqual(openobj.read(1), b'1')
224 self.assertEqual(openobj.read(1), b'2')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000225
Georg Brandl8f7c54e2006-02-20 08:40:38 +0000226 def testAbsoluteArcnames(self):
227 zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED)
228 zipfp.write(TESTFN, "/absolute")
229 zipfp.close()
230
231 zipfp = zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_STORED)
232 self.assertEqual(zipfp.namelist(), ["absolute"])
233 zipfp.close()
Tim Peters32cbc962006-02-20 21:42:18 +0000234
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000235 def testAppendToZipFile(self):
236 # Test appending to an existing zipfile
237 zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED)
238 zipfp.write(TESTFN, TESTFN)
239 zipfp.close()
240 zipfp = zipfile.ZipFile(TESTFN2, "a", zipfile.ZIP_STORED)
241 zipfp.writestr("strfile", self.data)
242 self.assertEqual(zipfp.namelist(), [TESTFN, "strfile"])
243 zipfp.close()
244
245 def testAppendToNonZipFile(self):
246 # Test appending to an existing file that is not a zipfile
247 # NOTE: this test fails if len(d) < 22 because of the first
248 # line "fpin.seek(-22, 2)" in _EndRecData
249 d = 'I am not a ZipFile!'*10
250 f = file(TESTFN2, 'wb')
251 f.write(d)
252 f.close()
253 zipfp = zipfile.ZipFile(TESTFN2, "a", zipfile.ZIP_STORED)
254 zipfp.write(TESTFN, TESTFN)
255 zipfp.close()
256
257 f = file(TESTFN2, 'rb')
258 f.seek(len(d))
259 zipfp = zipfile.ZipFile(f, "r")
260 self.assertEqual(zipfp.namelist(), [TESTFN])
261 zipfp.close()
262 f.close()
263
264 def test_WriteDefaultName(self):
265 # Check that calling ZipFile.write without arcname specified produces the expected result
266 zipfp = zipfile.ZipFile(TESTFN2, "w")
267 zipfp.write(TESTFN)
268 self.assertEqual(zipfp.read(TESTFN), file(TESTFN).read())
269 zipfp.close()
270
271 def test_PerFileCompression(self):
272 # Check that files within a Zip archive can have different compression options
273 zipfp = zipfile.ZipFile(TESTFN2, "w")
274 zipfp.write(TESTFN, 'storeme', zipfile.ZIP_STORED)
275 zipfp.write(TESTFN, 'deflateme', zipfile.ZIP_DEFLATED)
276 sinfo = zipfp.getinfo('storeme')
277 dinfo = zipfp.getinfo('deflateme')
278 self.assertEqual(sinfo.compress_type, zipfile.ZIP_STORED)
279 self.assertEqual(dinfo.compress_type, zipfile.ZIP_DEFLATED)
280 zipfp.close()
281
282 def test_WriteToReadonly(self):
283 # Check that trying to call write() on a readonly ZipFile object
284 # raises a RuntimeError
285 zipf = zipfile.ZipFile(TESTFN2, mode="w")
286 zipf.writestr("somefile.txt", "bogus")
287 zipf.close()
288 zipf = zipfile.ZipFile(TESTFN2, mode="r")
289 self.assertRaises(RuntimeError, zipf.write, TESTFN)
290 zipf.close()
291
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +0000292 def tearDown(self):
293 os.remove(TESTFN)
294 os.remove(TESTFN2)
295
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000296class TestZip64InSmallFiles(unittest.TestCase):
297 # These tests test the ZIP64 functionality without using large files,
298 # see test_zipfile64 for proper tests.
299
300 def setUp(self):
301 self._limit = zipfile.ZIP64_LIMIT
302 zipfile.ZIP64_LIMIT = 5
303
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000304 line_gen = (bytes("Test of zipfile line %d." % i)
305 for i in range(0, FIXEDTEST_SIZE))
306 self.data = b'\n'.join(line_gen)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000307
308 # Make a source file with some lines
309 fp = open(TESTFN, "wb")
310 fp.write(self.data)
311 fp.close()
312
313 def largeFileExceptionTest(self, f, compression):
314 zipfp = zipfile.ZipFile(f, "w", compression)
315 self.assertRaises(zipfile.LargeZipFile,
316 zipfp.write, TESTFN, "another"+os.extsep+"name")
317 zipfp.close()
318
319 def largeFileExceptionTest2(self, f, compression):
320 zipfp = zipfile.ZipFile(f, "w", compression)
321 self.assertRaises(zipfile.LargeZipFile,
322 zipfp.writestr, "another"+os.extsep+"name", self.data)
323 zipfp.close()
324
325 def testLargeFileException(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000326 for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000327 self.largeFileExceptionTest(f, zipfile.ZIP_STORED)
328 self.largeFileExceptionTest2(f, zipfile.ZIP_STORED)
329
330 def zipTest(self, f, compression):
331 # Create the ZIP archive
332 zipfp = zipfile.ZipFile(f, "w", compression, allowZip64=True)
333 zipfp.write(TESTFN, "another"+os.extsep+"name")
334 zipfp.write(TESTFN, TESTFN)
335 zipfp.writestr("strfile", self.data)
336 zipfp.close()
337
338 # Read the ZIP archive
339 zipfp = zipfile.ZipFile(f, "r", compression)
340 self.assertEqual(zipfp.read(TESTFN), self.data)
341 self.assertEqual(zipfp.read("another"+os.extsep+"name"), self.data)
342 self.assertEqual(zipfp.read("strfile"), self.data)
343
344 # Print the ZIP directory
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000345 fp = io.StringIO()
346 zipfp.printdir(fp)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000347
348 directory = fp.getvalue()
349 lines = directory.splitlines()
350 self.assertEquals(len(lines), 4) # Number of files + header
351
352 self.assert_('File Name' in lines[0])
353 self.assert_('Modified' in lines[0])
354 self.assert_('Size' in lines[0])
355
356 fn, date, time, size = lines[1].split()
357 self.assertEquals(fn, 'another.name')
358 # XXX: timestamp is not tested
359 self.assertEquals(size, str(len(self.data)))
360
361 # Check the namelist
362 names = zipfp.namelist()
363 self.assertEquals(len(names), 3)
364 self.assert_(TESTFN in names)
365 self.assert_("another"+os.extsep+"name" in names)
366 self.assert_("strfile" in names)
367
368 # Check infolist
369 infos = zipfp.infolist()
370 names = [ i.filename for i in infos ]
371 self.assertEquals(len(names), 3)
372 self.assert_(TESTFN in names)
373 self.assert_("another"+os.extsep+"name" in names)
374 self.assert_("strfile" in names)
375 for i in infos:
376 self.assertEquals(i.file_size, len(self.data))
377
378 # check getinfo
379 for nm in (TESTFN, "another"+os.extsep+"name", "strfile"):
380 info = zipfp.getinfo(nm)
381 self.assertEquals(info.filename, nm)
382 self.assertEquals(info.file_size, len(self.data))
383
384 # Check that testzip doesn't raise an exception
385 zipfp.testzip()
386
387
388 zipfp.close()
389
390 def testStored(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000391 for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000392 self.zipTest(f, zipfile.ZIP_STORED)
393
394
395 if zlib:
396 def testDeflated(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000397 for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000398 self.zipTest(f, zipfile.ZIP_DEFLATED)
399
400 def testAbsoluteArcnames(self):
401 zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED, allowZip64=True)
402 zipfp.write(TESTFN, "/absolute")
403 zipfp.close()
404
405 zipfp = zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_STORED)
406 self.assertEqual(zipfp.namelist(), ["absolute"])
407 zipfp.close()
408
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000409 def tearDown(self):
410 zipfile.ZIP64_LIMIT = self._limit
411 os.remove(TESTFN)
412 os.remove(TESTFN2)
413
414class PyZipFileTests(unittest.TestCase):
415 def testWritePyfile(self):
416 zipfp = zipfile.PyZipFile(TemporaryFile(), "w")
417 fn = __file__
418 if fn.endswith('.pyc') or fn.endswith('.pyo'):
419 fn = fn[:-1]
420
421 zipfp.writepy(fn)
422
423 bn = os.path.basename(fn)
424 self.assert_(bn not in zipfp.namelist())
425 self.assert_(bn + 'o' in zipfp.namelist() or bn + 'c' in zipfp.namelist())
426 zipfp.close()
427
428
429 zipfp = zipfile.PyZipFile(TemporaryFile(), "w")
430 fn = __file__
431 if fn.endswith('.pyc') or fn.endswith('.pyo'):
432 fn = fn[:-1]
433
434 zipfp.writepy(fn, "testpackage")
435
436 bn = "%s/%s"%("testpackage", os.path.basename(fn))
437 self.assert_(bn not in zipfp.namelist())
438 self.assert_(bn + 'o' in zipfp.namelist() or bn + 'c' in zipfp.namelist())
439 zipfp.close()
440
441 def testWritePythonPackage(self):
442 import email
443 packagedir = os.path.dirname(email.__file__)
444
445 zipfp = zipfile.PyZipFile(TemporaryFile(), "w")
446 zipfp.writepy(packagedir)
447
448 # Check for a couple of modules at different levels of the hieararchy
449 names = zipfp.namelist()
450 self.assert_('email/__init__.pyo' in names or 'email/__init__.pyc' in names)
451 self.assert_('email/mime/text.pyo' in names or 'email/mime/text.pyc' in names)
452
453 def testWritePythonDirectory(self):
454 os.mkdir(TESTFN2)
455 try:
456 fp = open(os.path.join(TESTFN2, "mod1.py"), "w")
Guido van Rossum43fc78d2007-02-09 22:18:41 +0000457 fp.write("print(42)\n")
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000458 fp.close()
459
460 fp = open(os.path.join(TESTFN2, "mod2.py"), "w")
Guido van Rossum43fc78d2007-02-09 22:18:41 +0000461 fp.write("print(42 * 42)\n")
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000462 fp.close()
463
464 fp = open(os.path.join(TESTFN2, "mod2.txt"), "w")
465 fp.write("bla bla bla\n")
466 fp.close()
467
468 zipfp = zipfile.PyZipFile(TemporaryFile(), "w")
469 zipfp.writepy(TESTFN2)
470
471 names = zipfp.namelist()
472 self.assert_('mod1.pyc' in names or 'mod1.pyo' in names)
473 self.assert_('mod2.pyc' in names or 'mod2.pyo' in names)
474 self.assert_('mod2.txt' not in names)
475
476 finally:
477 shutil.rmtree(TESTFN2)
478
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000479 def testWriteNonPyfile(self):
480 zipfp = zipfile.PyZipFile(TemporaryFile(), "w")
481 file(TESTFN, 'w').write('most definitely not a python file')
482 self.assertRaises(RuntimeError, zipfp.writepy, TESTFN)
483 os.remove(TESTFN)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000484
485
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +0000486class OtherTests(unittest.TestCase):
Thomas Wouterscf297e42007-02-23 15:07:44 +0000487 def testCreateNonExistentFileForAppend(self):
488 if os.path.exists(TESTFN):
489 os.unlink(TESTFN)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000490
Thomas Wouterscf297e42007-02-23 15:07:44 +0000491 filename = 'testfile.txt'
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000492 content = b'hello, world. this is some content.'
Guido van Rossumd8faa362007-04-27 19:54:29 +0000493
Thomas Wouterscf297e42007-02-23 15:07:44 +0000494 try:
495 zf = zipfile.ZipFile(TESTFN, 'a')
496 zf.writestr(filename, content)
497 zf.close()
498 except IOError:
499 self.fail('Could not append data to a non-existent zip file.')
500
501 self.assert_(os.path.exists(TESTFN))
502
503 zf = zipfile.ZipFile(TESTFN, 'r')
504 self.assertEqual(zf.read(filename), content)
505 zf.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000506
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +0000507 def testCloseErroneousFile(self):
508 # This test checks that the ZipFile constructor closes the file object
509 # it opens if there's an error in the file. If it doesn't, the traceback
510 # holds a reference to the ZipFile object and, indirectly, the file object.
511 # On Windows, this causes the os.unlink() call to fail because the
512 # underlying file is still open. This is SF bug #412214.
513 #
514 fp = open(TESTFN, "w")
515 fp.write("this is not a legal zip file\n")
516 fp.close()
517 try:
518 zf = zipfile.ZipFile(TESTFN)
519 except zipfile.BadZipfile:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000520 pass
521
522 def testIsZipErroneousFile(self):
523 # This test checks that the is_zipfile function correctly identifies
524 # a file that is not a zip file
525 fp = open(TESTFN, "w")
526 fp.write("this is not a legal zip file\n")
527 fp.close()
528 chk = zipfile.is_zipfile(TESTFN)
529 self.assert_(chk is False)
530
531 def testIsZipValidFile(self):
532 # This test checks that the is_zipfile function correctly identifies
533 # a file that is a zip file
534 zipf = zipfile.ZipFile(TESTFN, mode="w")
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000535 zipf.writestr("foo.txt", b"O, for a Muse of Fire!")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000536 zipf.close()
537 chk = zipfile.is_zipfile(TESTFN)
538 self.assert_(chk is True)
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +0000539
540 def testNonExistentFileRaisesIOError(self):
541 # make sure we don't raise an AttributeError when a partially-constructed
542 # ZipFile instance is finalized; this tests for regression on SF tracker
543 # bug #403871.
544
545 # The bug we're testing for caused an AttributeError to be raised
546 # when a ZipFile instance was created for a file that did not
547 # exist; the .fp member was not initialized but was needed by the
548 # __del__() method. Since the AttributeError is in the __del__(),
549 # it is ignored, but the user should be sufficiently annoyed by
550 # the message on the output that regression will be noticed
551 # quickly.
552 self.assertRaises(IOError, zipfile.ZipFile, TESTFN)
553
554 def testClosedZipRaisesRuntimeError(self):
555 # Verify that testzip() doesn't swallow inappropriate exceptions.
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000556 data = io.BytesIO()
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +0000557 zipf = zipfile.ZipFile(data, mode="w")
558 zipf.writestr("foo.txt", "O, for a Muse of Fire!")
559 zipf.close()
560
561 # This is correct; calling .read on a closed ZipFile should throw
562 # a RuntimeError, and so should calling .testzip. An earlier
563 # version of .testzip would swallow this exception (and any other)
564 # and report that the first file in the archive was corrupt.
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000565 self.assertRaises(RuntimeError, zipf.read, "foo.txt")
566 self.assertRaises(RuntimeError, zipf.open, "foo.txt")
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +0000567 self.assertRaises(RuntimeError, zipf.testzip)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000568 self.assertRaises(RuntimeError, zipf.writestr, "bogus.txt", "bogus")
569 file(TESTFN, 'w').write('zipfile test data')
570 self.assertRaises(RuntimeError, zipf.write, TESTFN)
571
572 def test_BadConstructorMode(self):
573 # Check that bad modes passed to ZipFile constructor are caught
574 self.assertRaises(RuntimeError, zipfile.ZipFile, TESTFN, "q")
575
576 def test_BadOpenMode(self):
577 # Check that bad modes passed to ZipFile.open are caught
578 zipf = zipfile.ZipFile(TESTFN, mode="w")
579 zipf.writestr("foo.txt", "O, for a Muse of Fire!")
580 zipf.close()
581 zipf = zipfile.ZipFile(TESTFN, mode="r")
582 # read the data to make sure the file is there
583 zipf.read("foo.txt")
584 self.assertRaises(RuntimeError, zipf.open, "foo.txt", "q")
585 zipf.close()
586
587 def test_Read0(self):
588 # Check that calling read(0) on a ZipExtFile object returns an empty
589 # string and doesn't advance file pointer
590 zipf = zipfile.ZipFile(TESTFN, mode="w")
591 zipf.writestr("foo.txt", "O, for a Muse of Fire!")
592 # read the data to make sure the file is there
593 f = zipf.open("foo.txt")
594 for i in range(FIXEDTEST_SIZE):
595 self.assertEqual(f.read(0), '')
596
597 self.assertEqual(f.read(), "O, for a Muse of Fire!")
598 zipf.close()
599
600 def test_OpenNonexistentItem(self):
601 # Check that attempting to call open() for an item that doesn't
602 # exist in the archive raises a RuntimeError
603 zipf = zipfile.ZipFile(TESTFN, mode="w")
604 self.assertRaises(KeyError, zipf.open, "foo.txt", "r")
605
606 def test_BadCompressionMode(self):
607 # Check that bad compression methods passed to ZipFile.open are caught
608 self.assertRaises(RuntimeError, zipfile.ZipFile, TESTFN, "w", -1)
609
610 def test_NullByteInFilename(self):
611 # Check that a filename containing a null byte is properly terminated
612 zipf = zipfile.ZipFile(TESTFN, mode="w")
613 zipf.writestr("foo.txt\x00qqq", "O, for a Muse of Fire!")
614 self.assertEqual(zipf.namelist(), ['foo.txt'])
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +0000615
Guido van Rossumd8faa362007-04-27 19:54:29 +0000616 def tearDown(self):
617 support.unlink(TESTFN)
618 support.unlink(TESTFN2)
Thomas Wouterscf297e42007-02-23 15:07:44 +0000619
620class DecryptionTests(unittest.TestCase):
621 # This test checks that ZIP decryption works. Since the library does not
622 # support encryption at the moment, we use a pre-generated encrypted
623 # ZIP file
624
625 data = (
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000626 b'PK\x03\x04\x14\x00\x01\x00\x00\x00n\x92i.#y\xef?&\x00\x00\x00\x1a\x00'
627 b'\x00\x00\x08\x00\x00\x00test.txt\xfa\x10\xa0gly|\xfa-\xc5\xc0=\xf9y'
628 b'\x18\xe0\xa8r\xb3Z}Lg\xbc\xae\xf9|\x9b\x19\xe4\x8b\xba\xbb)\x8c\xb0\xdbl'
629 b'PK\x01\x02\x14\x00\x14\x00\x01\x00\x00\x00n\x92i.#y\xef?&\x00\x00\x00'
630 b'\x1a\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x01\x00 \x00\xb6\x81'
631 b'\x00\x00\x00\x00test.txtPK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x006\x00'
632 b'\x00\x00L\x00\x00\x00\x00\x00' )
Thomas Wouterscf297e42007-02-23 15:07:44 +0000633
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000634 plain = b'zipfile.py encryption test'
Thomas Wouterscf297e42007-02-23 15:07:44 +0000635
636 def setUp(self):
637 fp = open(TESTFN, "wb")
638 fp.write(self.data)
639 fp.close()
640 self.zip = zipfile.ZipFile(TESTFN, "r")
641
642 def tearDown(self):
643 self.zip.close()
644 os.unlink(TESTFN)
645
646 def testNoPassword(self):
647 # Reading the encrypted file without password
648 # must generate a RunTime exception
649 self.assertRaises(RuntimeError, self.zip.read, "test.txt")
650
651 def testBadPassword(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000652 self.zip.setpassword(b"perl")
Thomas Wouterscf297e42007-02-23 15:07:44 +0000653 self.assertRaises(RuntimeError, self.zip.read, "test.txt")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000654
Thomas Wouterscf297e42007-02-23 15:07:44 +0000655 def testGoodPassword(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000656 self.zip.setpassword(b"python")
Thomas Wouterscf297e42007-02-23 15:07:44 +0000657 self.assertEquals(self.zip.read("test.txt"), self.plain)
658
Guido van Rossumd8faa362007-04-27 19:54:29 +0000659
660class TestsWithRandomBinaryFiles(unittest.TestCase):
661 def setUp(self):
662 datacount = randint(16, 64)*1024 + randint(1, 1024)
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000663 self.data = b''.join(struct.pack('<f', random()*randint(-1000, 1000))
664 for i in range(datacount))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000665
666 # Make a source file with some lines
667 fp = open(TESTFN, "wb")
668 fp.write(self.data)
669 fp.close()
670
671 def tearDown(self):
672 support.unlink(TESTFN)
673 support.unlink(TESTFN2)
674
675 def makeTestArchive(self, f, compression):
676 # Create the ZIP archive
677 zipfp = zipfile.ZipFile(f, "w", compression)
678 zipfp.write(TESTFN, "another"+os.extsep+"name")
679 zipfp.write(TESTFN, TESTFN)
680 zipfp.close()
681
682 def zipTest(self, f, compression):
683 self.makeTestArchive(f, compression)
684
685 # Read the ZIP archive
686 zipfp = zipfile.ZipFile(f, "r", compression)
687 testdata = zipfp.read(TESTFN)
688 self.assertEqual(len(testdata), len(self.data))
689 self.assertEqual(testdata, self.data)
690 self.assertEqual(zipfp.read("another"+os.extsep+"name"), self.data)
691 zipfp.close()
692
693 def testStored(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000694 for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000695 self.zipTest(f, zipfile.ZIP_STORED)
696
697 def zipOpenTest(self, f, compression):
698 self.makeTestArchive(f, compression)
699
700 # Read the ZIP archive
701 zipfp = zipfile.ZipFile(f, "r", compression)
702 zipdata1 = []
703 zipopen1 = zipfp.open(TESTFN)
704 while 1:
705 read_data = zipopen1.read(256)
706 if not read_data:
707 break
708 zipdata1.append(read_data)
709
710 zipdata2 = []
711 zipopen2 = zipfp.open("another"+os.extsep+"name")
712 while 1:
713 read_data = zipopen2.read(256)
714 if not read_data:
715 break
716 zipdata2.append(read_data)
717
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000718 testdata1 = b''.join(zipdata1)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000719 self.assertEqual(len(testdata1), len(self.data))
720 self.assertEqual(testdata1, self.data)
721
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000722 testdata2 = b''.join(zipdata2)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000723 self.assertEqual(len(testdata1), len(self.data))
724 self.assertEqual(testdata1, self.data)
725 zipfp.close()
726
727 def testOpenStored(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000728 for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000729 self.zipOpenTest(f, zipfile.ZIP_STORED)
730
731 def zipRandomOpenTest(self, f, compression):
732 self.makeTestArchive(f, compression)
733
734 # Read the ZIP archive
735 zipfp = zipfile.ZipFile(f, "r", compression)
736 zipdata1 = []
737 zipopen1 = zipfp.open(TESTFN)
738 while 1:
739 read_data = zipopen1.read(randint(1, 1024))
740 if not read_data:
741 break
742 zipdata1.append(read_data)
743
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000744 testdata = b''.join(zipdata1)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000745 self.assertEqual(len(testdata), len(self.data))
746 self.assertEqual(testdata, self.data)
747 zipfp.close()
748
749 def testRandomOpenStored(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000750 for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000751 self.zipRandomOpenTest(f, zipfile.ZIP_STORED)
752
753class TestsWithMultipleOpens(unittest.TestCase):
754 def setUp(self):
755 # Create the ZIP archive
756 zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_DEFLATED)
757 zipfp.writestr('ones', '1'*FIXEDTEST_SIZE)
758 zipfp.writestr('twos', '2'*FIXEDTEST_SIZE)
759 zipfp.close()
760
761 def testSameFile(self):
762 # Verify that (when the ZipFile is in control of creating file objects)
763 # multiple open() calls can be made without interfering with each other.
764 zipf = zipfile.ZipFile(TESTFN2, mode="r")
765 zopen1 = zipf.open('ones')
766 zopen2 = zipf.open('ones')
767 data1 = zopen1.read(500)
768 data2 = zopen2.read(500)
769 data1 += zopen1.read(500)
770 data2 += zopen2.read(500)
771 self.assertEqual(data1, data2)
772 zipf.close()
773
774 def testDifferentFile(self):
775 # Verify that (when the ZipFile is in control of creating file objects)
776 # multiple open() calls can be made without interfering with each other.
777 zipf = zipfile.ZipFile(TESTFN2, mode="r")
778 zopen1 = zipf.open('ones')
779 zopen2 = zipf.open('twos')
780 data1 = zopen1.read(500)
781 data2 = zopen2.read(500)
782 data1 += zopen1.read(500)
783 data2 += zopen2.read(500)
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000784 self.assertEqual(data1, b'1'*FIXEDTEST_SIZE)
785 self.assertEqual(data2, b'2'*FIXEDTEST_SIZE)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000786 zipf.close()
787
788 def testInterleaved(self):
789 # Verify that (when the ZipFile is in control of creating file objects)
790 # multiple open() calls can be made without interfering with each other.
791 zipf = zipfile.ZipFile(TESTFN2, mode="r")
792 zopen1 = zipf.open('ones')
793 data1 = zopen1.read(500)
794 zopen2 = zipf.open('twos')
795 data2 = zopen2.read(500)
796 data1 += zopen1.read(500)
797 data2 += zopen2.read(500)
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000798 self.assertEqual(data1, b'1'*FIXEDTEST_SIZE)
799 self.assertEqual(data2, b'2'*FIXEDTEST_SIZE)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000800 zipf.close()
801
802 def tearDown(self):
803 os.remove(TESTFN2)
804
805
806class UniversalNewlineTests(unittest.TestCase):
807 def setUp(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000808 self.line_gen = [bytes("Test of zipfile line %d." % i)
809 for i in range(FIXEDTEST_SIZE)]
Guido van Rossumd8faa362007-04-27 19:54:29 +0000810 self.seps = ('\r', '\r\n', '\n')
811 self.arcdata, self.arcfiles = {}, {}
812 for n, s in enumerate(self.seps):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000813 b = s.encode("ascii")
814 self.arcdata[s] = b.join(self.line_gen) + b
Guido van Rossumd8faa362007-04-27 19:54:29 +0000815 self.arcfiles[s] = '%s-%d' % (TESTFN, n)
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000816 f = open(self.arcfiles[s], "wb")
817 try:
818 f.write(self.arcdata[s])
819 finally:
820 f.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000821
822 def makeTestArchive(self, f, compression):
823 # Create the ZIP archive
824 zipfp = zipfile.ZipFile(f, "w", compression)
825 for fn in self.arcfiles.values():
826 zipfp.write(fn, fn)
827 zipfp.close()
828
829 def readTest(self, f, compression):
830 self.makeTestArchive(f, compression)
831
832 # Read the ZIP archive
833 zipfp = zipfile.ZipFile(f, "r")
834 for sep, fn in self.arcfiles.items():
835 zipdata = zipfp.open(fn, "rU").read()
836 self.assertEqual(self.arcdata[sep], zipdata)
837
838 zipfp.close()
839
840 def readlineTest(self, f, compression):
841 self.makeTestArchive(f, compression)
842
843 # Read the ZIP archive
844 zipfp = zipfile.ZipFile(f, "r")
845 for sep, fn in self.arcfiles.items():
846 zipopen = zipfp.open(fn, "rU")
847 for line in self.line_gen:
848 linedata = zipopen.readline()
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000849 self.assertEqual(linedata, line + b'\n')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000850
851 zipfp.close()
852
853 def readlinesTest(self, f, compression):
854 self.makeTestArchive(f, compression)
855
856 # Read the ZIP archive
857 zipfp = zipfile.ZipFile(f, "r")
858 for sep, fn in self.arcfiles.items():
859 ziplines = zipfp.open(fn, "rU").readlines()
860 for line, zipline in zip(self.line_gen, ziplines):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000861 self.assertEqual(zipline, line + b'\n')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000862
863 zipfp.close()
864
865 def iterlinesTest(self, f, compression):
866 self.makeTestArchive(f, compression)
867
868 # Read the ZIP archive
869 zipfp = zipfile.ZipFile(f, "r")
870 for sep, fn in self.arcfiles.items():
871 for line, zipline in zip(self.line_gen, zipfp.open(fn, "rU")):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000872 self.assertEqual(zipline, line + b'\n')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000873
874 zipfp.close()
875
876 def testReadStored(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000877 for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000878 self.readTest(f, zipfile.ZIP_STORED)
879
880 def testReadlineStored(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000881 for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000882 self.readlineTest(f, zipfile.ZIP_STORED)
883
884 def testReadlinesStored(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000885 for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000886 self.readlinesTest(f, zipfile.ZIP_STORED)
887
888 def testIterlinesStored(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000889 for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000890 self.iterlinesTest(f, zipfile.ZIP_STORED)
891
892 if zlib:
893 def testReadDeflated(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000894 for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000895 self.readTest(f, zipfile.ZIP_DEFLATED)
896
897 def testReadlineDeflated(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000898 for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000899 self.readlineTest(f, zipfile.ZIP_DEFLATED)
900
901 def testReadlinesDeflated(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000902 for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000903 self.readlinesTest(f, zipfile.ZIP_DEFLATED)
904
905 def testIterlinesDeflated(self):
Guido van Rossumd6ca5462007-05-22 01:29:33 +0000906 for f in (TESTFN2, TemporaryFile(), io.BytesIO()):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000907 self.iterlinesTest(f, zipfile.ZIP_DEFLATED)
908
909 def tearDown(self):
910 for sep, fn in self.arcfiles.items():
911 os.remove(fn)
912 support.unlink(TESTFN)
913 support.unlink(TESTFN2)
914
915
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +0000916def test_main():
Guido van Rossumd8faa362007-04-27 19:54:29 +0000917 run_unittest(TestsWithSourceFile, TestZip64InSmallFiles, OtherTests,
918 PyZipFileTests, DecryptionTests, TestsWithMultipleOpens,
919 UniversalNewlineTests, TestsWithRandomBinaryFiles)
Johannes Gijsbers3caf9c12004-08-19 15:11:50 +0000920
921if __name__ == "__main__":
922 test_main()