test_zipfile.py revision 8c4364127193100d0c3e267f5a49aadd096732a6
1# We can test part of the module without zlib. 2try: 3 import zlib 4except ImportError: 5 zlib = None 6 7import zipfile, os, unittest, sys, shutil, struct 8 9from StringIO import StringIO 10from tempfile import TemporaryFile 11from random import randint, random 12 13import test.test_support as support 14from test.test_support import TESTFN, run_unittest 15 16TESTFN2 = TESTFN + "2" 17FIXEDTEST_SIZE = 1000 18 19SMALL_TEST_DATA = [('_ziptest1', '1q2w3e4r5t'), 20 ('ziptest2dir/_ziptest2', 'qawsedrftg'), 21 ('/ziptest2dir/ziptest3dir/_ziptest3', 'azsxdcfvgb'), 22 ('ziptest2dir/ziptest3dir/ziptest4dir/_ziptest3', '6y7u8i9o0p')] 23 24class 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' 29 30 # Make a source file with some lines 31 fp = open(TESTFN, "wb") 32 fp.write(self.data) 33 fp.close() 34 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() 42 43 def zipTest(self, f, compression): 44 self.makeTestArchive(f, compression) 45 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) 51 52 # Print the ZIP directory 53 fp = StringIO() 54 stdout = sys.stdout 55 try: 56 sys.stdout = fp 57 58 zipfp.printdir() 59 finally: 60 sys.stdout = stdout 61 62 directory = fp.getvalue() 63 lines = directory.splitlines() 64 self.assertEquals(len(lines), 4) # Number of files + header 65 66 self.assert_('File Name' in lines[0]) 67 self.assert_('Modified' in lines[0]) 68 self.assert_('Size' in lines[0]) 69 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))) 74 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) 81 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)) 91 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)) 97 98 # Check that testzip doesn't raise an exception 99 zipfp.testzip() 100 zipfp.close() 101 102 def testStored(self): 103 for f in (TESTFN2, TemporaryFile(), StringIO()): 104 self.zipTest(f, zipfile.ZIP_STORED) 105 106 def zipOpenTest(self, f, compression): 107 self.makeTestArchive(f, compression) 108 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) 118 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) 126 127 self.assertEqual(''.join(zipdata1), self.data) 128 self.assertEqual(''.join(zipdata2), self.data) 129 zipfp.close() 130 131 def testOpenStored(self): 132 for f in (TESTFN2, TemporaryFile(), StringIO()): 133 self.zipOpenTest(f, zipfile.ZIP_STORED) 134 135 def testOpenViaZipInfo(self): 136 # Create the ZIP archive 137 zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) 138 zipfp.writestr("name", "foo") 139 zipfp.writestr("name", "bar") 140 zipfp.close() 141 142 zipfp = zipfile.ZipFile(TESTFN2, "r") 143 infos = zipfp.infolist() 144 data = "" 145 for info in infos: 146 data += zipfp.open(info).read() 147 self.assert_(data == "foobar" or data == "barfoo") 148 data = "" 149 for info in infos: 150 data += zipfp.read(info) 151 self.assert_(data == "foobar" or data == "barfoo") 152 zipfp.close() 153 154 def zipRandomOpenTest(self, f, compression): 155 self.makeTestArchive(f, compression) 156 157 # Read the ZIP archive 158 zipfp = zipfile.ZipFile(f, "r", compression) 159 zipdata1 = [] 160 zipopen1 = zipfp.open(TESTFN) 161 while 1: 162 read_data = zipopen1.read(randint(1, 1024)) 163 if not read_data: 164 break 165 zipdata1.append(read_data) 166 167 self.assertEqual(''.join(zipdata1), self.data) 168 zipfp.close() 169 170 def testRandomOpenStored(self): 171 for f in (TESTFN2, TemporaryFile(), StringIO()): 172 self.zipRandomOpenTest(f, zipfile.ZIP_STORED) 173 174 def zipReadlineTest(self, f, compression): 175 self.makeTestArchive(f, compression) 176 177 # Read the ZIP archive 178 zipfp = zipfile.ZipFile(f, "r") 179 zipopen = zipfp.open(TESTFN) 180 for line in self.line_gen: 181 linedata = zipopen.readline() 182 self.assertEqual(linedata, line + '\n') 183 184 zipfp.close() 185 186 def zipReadlinesTest(self, f, compression): 187 self.makeTestArchive(f, compression) 188 189 # Read the ZIP archive 190 zipfp = zipfile.ZipFile(f, "r") 191 ziplines = zipfp.open(TESTFN).readlines() 192 for line, zipline in zip(self.line_gen, ziplines): 193 self.assertEqual(zipline, line + '\n') 194 195 zipfp.close() 196 197 def zipIterlinesTest(self, f, compression): 198 self.makeTestArchive(f, compression) 199 200 # Read the ZIP archive 201 zipfp = zipfile.ZipFile(f, "r") 202 for line, zipline in zip(self.line_gen, zipfp.open(TESTFN)): 203 self.assertEqual(zipline, line + '\n') 204 205 zipfp.close() 206 207 def testReadlineStored(self): 208 for f in (TESTFN2, TemporaryFile(), StringIO()): 209 self.zipReadlineTest(f, zipfile.ZIP_STORED) 210 211 def testReadlinesStored(self): 212 for f in (TESTFN2, TemporaryFile(), StringIO()): 213 self.zipReadlinesTest(f, zipfile.ZIP_STORED) 214 215 def testIterlinesStored(self): 216 for f in (TESTFN2, TemporaryFile(), StringIO()): 217 self.zipIterlinesTest(f, zipfile.ZIP_STORED) 218 219 if zlib: 220 def testDeflated(self): 221 for f in (TESTFN2, TemporaryFile(), StringIO()): 222 self.zipTest(f, zipfile.ZIP_DEFLATED) 223 224 def testOpenDeflated(self): 225 for f in (TESTFN2, TemporaryFile(), StringIO()): 226 self.zipOpenTest(f, zipfile.ZIP_DEFLATED) 227 228 def testRandomOpenDeflated(self): 229 for f in (TESTFN2, TemporaryFile(), StringIO()): 230 self.zipRandomOpenTest(f, zipfile.ZIP_DEFLATED) 231 232 def testReadlineDeflated(self): 233 for f in (TESTFN2, TemporaryFile(), StringIO()): 234 self.zipReadlineTest(f, zipfile.ZIP_DEFLATED) 235 236 def testReadlinesDeflated(self): 237 for f in (TESTFN2, TemporaryFile(), StringIO()): 238 self.zipReadlinesTest(f, zipfile.ZIP_DEFLATED) 239 240 def testIterlinesDeflated(self): 241 for f in (TESTFN2, TemporaryFile(), StringIO()): 242 self.zipIterlinesTest(f, zipfile.ZIP_DEFLATED) 243 244 def testLowCompression(self): 245 # Checks for cases where compressed data is larger than original 246 # Create the ZIP archive 247 zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_DEFLATED) 248 zipfp.writestr("strfile", '12') 249 zipfp.close() 250 251 # Get an open object for strfile 252 zipfp = zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_DEFLATED) 253 openobj = zipfp.open("strfile") 254 self.assertEqual(openobj.read(1), '1') 255 self.assertEqual(openobj.read(1), '2') 256 257 def testAbsoluteArcnames(self): 258 zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) 259 zipfp.write(TESTFN, "/absolute") 260 zipfp.close() 261 262 zipfp = zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_STORED) 263 self.assertEqual(zipfp.namelist(), ["absolute"]) 264 zipfp.close() 265 266 def testAppendToZipFile(self): 267 # Test appending to an existing zipfile 268 zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) 269 zipfp.write(TESTFN, TESTFN) 270 zipfp.close() 271 zipfp = zipfile.ZipFile(TESTFN2, "a", zipfile.ZIP_STORED) 272 zipfp.writestr("strfile", self.data) 273 self.assertEqual(zipfp.namelist(), [TESTFN, "strfile"]) 274 zipfp.close() 275 276 def testAppendToNonZipFile(self): 277 # Test appending to an existing file that is not a zipfile 278 # NOTE: this test fails if len(d) < 22 because of the first 279 # line "fpin.seek(-22, 2)" in _EndRecData 280 d = 'I am not a ZipFile!'*10 281 f = file(TESTFN2, 'wb') 282 f.write(d) 283 f.close() 284 zipfp = zipfile.ZipFile(TESTFN2, "a", zipfile.ZIP_STORED) 285 zipfp.write(TESTFN, TESTFN) 286 zipfp.close() 287 288 f = file(TESTFN2, 'rb') 289 f.seek(len(d)) 290 zipfp = zipfile.ZipFile(f, "r") 291 self.assertEqual(zipfp.namelist(), [TESTFN]) 292 zipfp.close() 293 f.close() 294 295 def test_WriteDefaultName(self): 296 # Check that calling ZipFile.write without arcname specified produces the expected result 297 zipfp = zipfile.ZipFile(TESTFN2, "w") 298 zipfp.write(TESTFN) 299 self.assertEqual(zipfp.read(TESTFN), file(TESTFN).read()) 300 zipfp.close() 301 302 def test_PerFileCompression(self): 303 # Check that files within a Zip archive can have different compression options 304 zipfp = zipfile.ZipFile(TESTFN2, "w") 305 zipfp.write(TESTFN, 'storeme', zipfile.ZIP_STORED) 306 zipfp.write(TESTFN, 'deflateme', zipfile.ZIP_DEFLATED) 307 sinfo = zipfp.getinfo('storeme') 308 dinfo = zipfp.getinfo('deflateme') 309 self.assertEqual(sinfo.compress_type, zipfile.ZIP_STORED) 310 self.assertEqual(dinfo.compress_type, zipfile.ZIP_DEFLATED) 311 zipfp.close() 312 313 def test_WriteToReadonly(self): 314 # Check that trying to call write() on a readonly ZipFile object 315 # raises a RuntimeError 316 zipf = zipfile.ZipFile(TESTFN2, mode="w") 317 zipf.writestr("somefile.txt", "bogus") 318 zipf.close() 319 zipf = zipfile.ZipFile(TESTFN2, mode="r") 320 self.assertRaises(RuntimeError, zipf.write, TESTFN) 321 zipf.close() 322 323 def testExtract(self): 324 zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) 325 for fpath, fdata in SMALL_TEST_DATA: 326 zipfp.writestr(fpath, fdata) 327 zipfp.close() 328 329 zipfp = zipfile.ZipFile(TESTFN2, "r") 330 for fpath, fdata in SMALL_TEST_DATA: 331 writtenfile = zipfp.extract(fpath) 332 333 # make sure it was written to the right place 334 if os.path.isabs(fpath): 335 correctfile = os.path.join(os.getcwd(), fpath[1:]) 336 else: 337 correctfile = os.path.join(os.getcwd(), fpath) 338 correctfile = os.path.normpath(correctfile) 339 340 self.assertEqual(writtenfile, correctfile) 341 342 # make sure correct data is in correct file 343 self.assertEqual(fdata, file(writtenfile, "rb").read()) 344 345 os.remove(writtenfile) 346 347 zipfp.close() 348 349 # remove the test file subdirectories 350 shutil.rmtree(os.path.join(os.getcwd(), 'ziptest2dir')) 351 352 def testExtractAll(self): 353 zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) 354 for fpath, fdata in SMALL_TEST_DATA: 355 zipfp.writestr(fpath, fdata) 356 zipfp.close() 357 358 zipfp = zipfile.ZipFile(TESTFN2, "r") 359 zipfp.extractall() 360 for fpath, fdata in SMALL_TEST_DATA: 361 if os.path.isabs(fpath): 362 outfile = os.path.join(os.getcwd(), fpath[1:]) 363 else: 364 outfile = os.path.join(os.getcwd(), fpath) 365 366 self.assertEqual(fdata, file(outfile, "rb").read()) 367 368 os.remove(outfile) 369 370 zipfp.close() 371 372 # remove the test file subdirectories 373 shutil.rmtree(os.path.join(os.getcwd(), 'ziptest2dir')) 374 375 def tearDown(self): 376 os.remove(TESTFN) 377 os.remove(TESTFN2) 378 379class TestZip64InSmallFiles(unittest.TestCase): 380 # These tests test the ZIP64 functionality without using large files, 381 # see test_zipfile64 for proper tests. 382 383 def setUp(self): 384 self._limit = zipfile.ZIP64_LIMIT 385 zipfile.ZIP64_LIMIT = 5 386 387 line_gen = ("Test of zipfile line %d." % i for i in range(0, FIXEDTEST_SIZE)) 388 self.data = '\n'.join(line_gen) 389 390 # Make a source file with some lines 391 fp = open(TESTFN, "wb") 392 fp.write(self.data) 393 fp.close() 394 395 def largeFileExceptionTest(self, f, compression): 396 zipfp = zipfile.ZipFile(f, "w", compression) 397 self.assertRaises(zipfile.LargeZipFile, 398 zipfp.write, TESTFN, "another"+os.extsep+"name") 399 zipfp.close() 400 401 def largeFileExceptionTest2(self, f, compression): 402 zipfp = zipfile.ZipFile(f, "w", compression) 403 self.assertRaises(zipfile.LargeZipFile, 404 zipfp.writestr, "another"+os.extsep+"name", self.data) 405 zipfp.close() 406 407 def testLargeFileException(self): 408 for f in (TESTFN2, TemporaryFile(), StringIO()): 409 self.largeFileExceptionTest(f, zipfile.ZIP_STORED) 410 self.largeFileExceptionTest2(f, zipfile.ZIP_STORED) 411 412 def zipTest(self, f, compression): 413 # Create the ZIP archive 414 zipfp = zipfile.ZipFile(f, "w", compression, allowZip64=True) 415 zipfp.write(TESTFN, "another"+os.extsep+"name") 416 zipfp.write(TESTFN, TESTFN) 417 zipfp.writestr("strfile", self.data) 418 zipfp.close() 419 420 # Read the ZIP archive 421 zipfp = zipfile.ZipFile(f, "r", compression) 422 self.assertEqual(zipfp.read(TESTFN), self.data) 423 self.assertEqual(zipfp.read("another"+os.extsep+"name"), self.data) 424 self.assertEqual(zipfp.read("strfile"), self.data) 425 426 # Print the ZIP directory 427 fp = StringIO() 428 stdout = sys.stdout 429 try: 430 sys.stdout = fp 431 432 zipfp.printdir() 433 finally: 434 sys.stdout = stdout 435 436 directory = fp.getvalue() 437 lines = directory.splitlines() 438 self.assertEquals(len(lines), 4) # Number of files + header 439 440 self.assert_('File Name' in lines[0]) 441 self.assert_('Modified' in lines[0]) 442 self.assert_('Size' in lines[0]) 443 444 fn, date, time, size = lines[1].split() 445 self.assertEquals(fn, 'another.name') 446 # XXX: timestamp is not tested 447 self.assertEquals(size, str(len(self.data))) 448 449 # Check the namelist 450 names = zipfp.namelist() 451 self.assertEquals(len(names), 3) 452 self.assert_(TESTFN in names) 453 self.assert_("another"+os.extsep+"name" in names) 454 self.assert_("strfile" in names) 455 456 # Check infolist 457 infos = zipfp.infolist() 458 names = [ i.filename for i in infos ] 459 self.assertEquals(len(names), 3) 460 self.assert_(TESTFN in names) 461 self.assert_("another"+os.extsep+"name" in names) 462 self.assert_("strfile" in names) 463 for i in infos: 464 self.assertEquals(i.file_size, len(self.data)) 465 466 # check getinfo 467 for nm in (TESTFN, "another"+os.extsep+"name", "strfile"): 468 info = zipfp.getinfo(nm) 469 self.assertEquals(info.filename, nm) 470 self.assertEquals(info.file_size, len(self.data)) 471 472 # Check that testzip doesn't raise an exception 473 zipfp.testzip() 474 475 476 zipfp.close() 477 478 def testStored(self): 479 for f in (TESTFN2, TemporaryFile(), StringIO()): 480 self.zipTest(f, zipfile.ZIP_STORED) 481 482 483 if zlib: 484 def testDeflated(self): 485 for f in (TESTFN2, TemporaryFile(), StringIO()): 486 self.zipTest(f, zipfile.ZIP_DEFLATED) 487 488 def testAbsoluteArcnames(self): 489 zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED, allowZip64=True) 490 zipfp.write(TESTFN, "/absolute") 491 zipfp.close() 492 493 zipfp = zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_STORED) 494 self.assertEqual(zipfp.namelist(), ["absolute"]) 495 zipfp.close() 496 497 def tearDown(self): 498 zipfile.ZIP64_LIMIT = self._limit 499 os.remove(TESTFN) 500 os.remove(TESTFN2) 501 502class PyZipFileTests(unittest.TestCase): 503 def testWritePyfile(self): 504 zipfp = zipfile.PyZipFile(TemporaryFile(), "w") 505 fn = __file__ 506 if fn.endswith('.pyc') or fn.endswith('.pyo'): 507 fn = fn[:-1] 508 509 zipfp.writepy(fn) 510 511 bn = os.path.basename(fn) 512 self.assert_(bn not in zipfp.namelist()) 513 self.assert_(bn + 'o' in zipfp.namelist() or bn + 'c' in zipfp.namelist()) 514 zipfp.close() 515 516 517 zipfp = zipfile.PyZipFile(TemporaryFile(), "w") 518 fn = __file__ 519 if fn.endswith('.pyc') or fn.endswith('.pyo'): 520 fn = fn[:-1] 521 522 zipfp.writepy(fn, "testpackage") 523 524 bn = "%s/%s"%("testpackage", os.path.basename(fn)) 525 self.assert_(bn not in zipfp.namelist()) 526 self.assert_(bn + 'o' in zipfp.namelist() or bn + 'c' in zipfp.namelist()) 527 zipfp.close() 528 529 def testWritePythonPackage(self): 530 import email 531 packagedir = os.path.dirname(email.__file__) 532 533 zipfp = zipfile.PyZipFile(TemporaryFile(), "w") 534 zipfp.writepy(packagedir) 535 536 # Check for a couple of modules at different levels of the hieararchy 537 names = zipfp.namelist() 538 self.assert_('email/__init__.pyo' in names or 'email/__init__.pyc' in names) 539 self.assert_('email/mime/text.pyo' in names or 'email/mime/text.pyc' in names) 540 541 def testWritePythonDirectory(self): 542 os.mkdir(TESTFN2) 543 try: 544 fp = open(os.path.join(TESTFN2, "mod1.py"), "w") 545 fp.write("print 42\n") 546 fp.close() 547 548 fp = open(os.path.join(TESTFN2, "mod2.py"), "w") 549 fp.write("print 42 * 42\n") 550 fp.close() 551 552 fp = open(os.path.join(TESTFN2, "mod2.txt"), "w") 553 fp.write("bla bla bla\n") 554 fp.close() 555 556 zipfp = zipfile.PyZipFile(TemporaryFile(), "w") 557 zipfp.writepy(TESTFN2) 558 559 names = zipfp.namelist() 560 self.assert_('mod1.pyc' in names or 'mod1.pyo' in names) 561 self.assert_('mod2.pyc' in names or 'mod2.pyo' in names) 562 self.assert_('mod2.txt' not in names) 563 564 finally: 565 shutil.rmtree(TESTFN2) 566 567 def testWriteNonPyfile(self): 568 zipfp = zipfile.PyZipFile(TemporaryFile(), "w") 569 file(TESTFN, 'w').write('most definitely not a python file') 570 self.assertRaises(RuntimeError, zipfp.writepy, TESTFN) 571 os.remove(TESTFN) 572 573 574class OtherTests(unittest.TestCase): 575 def testUnicodeFilenames(self): 576 zf = zipfile.ZipFile(TESTFN, "w") 577 zf.writestr(u"foo.txt", "Test for unicode filename") 578 zf.writestr(u"\xf6.txt", "Test for unicode filename") 579 self.assertTrue(isinstance(zf.infolist()[0].filename, unicode)) 580 zf.close() 581 zf = zipfile.ZipFile(TESTFN, "r") 582 self.assertEqual(zf.filelist[0].filename, "foo.txt") 583 self.assertEqual(zf.filelist[1].filename, u"\xf6.txt") 584 zf.close() 585 586 def testCreateNonExistentFileForAppend(self): 587 if os.path.exists(TESTFN): 588 os.unlink(TESTFN) 589 590 filename = 'testfile.txt' 591 content = 'hello, world. this is some content.' 592 593 try: 594 zf = zipfile.ZipFile(TESTFN, 'a') 595 zf.writestr(filename, content) 596 zf.close() 597 except IOError, (errno, errmsg): 598 self.fail('Could not append data to a non-existent zip file.') 599 600 self.assert_(os.path.exists(TESTFN)) 601 602 zf = zipfile.ZipFile(TESTFN, 'r') 603 self.assertEqual(zf.read(filename), content) 604 zf.close() 605 606 def testCloseErroneousFile(self): 607 # This test checks that the ZipFile constructor closes the file object 608 # it opens if there's an error in the file. If it doesn't, the traceback 609 # holds a reference to the ZipFile object and, indirectly, the file object. 610 # On Windows, this causes the os.unlink() call to fail because the 611 # underlying file is still open. This is SF bug #412214. 612 # 613 fp = open(TESTFN, "w") 614 fp.write("this is not a legal zip file\n") 615 fp.close() 616 try: 617 zf = zipfile.ZipFile(TESTFN) 618 except zipfile.BadZipfile: 619 pass 620 621 def testIsZipErroneousFile(self): 622 # This test checks that the is_zipfile function correctly identifies 623 # a file that is not a zip file 624 fp = open(TESTFN, "w") 625 fp.write("this is not a legal zip file\n") 626 fp.close() 627 chk = zipfile.is_zipfile(TESTFN) 628 self.assert_(chk is False) 629 630 def testIsZipValidFile(self): 631 # This test checks that the is_zipfile function correctly identifies 632 # a file that is a zip file 633 zipf = zipfile.ZipFile(TESTFN, mode="w") 634 zipf.writestr("foo.txt", "O, for a Muse of Fire!") 635 zipf.close() 636 chk = zipfile.is_zipfile(TESTFN) 637 self.assert_(chk is True) 638 639 def testNonExistentFileRaisesIOError(self): 640 # make sure we don't raise an AttributeError when a partially-constructed 641 # ZipFile instance is finalized; this tests for regression on SF tracker 642 # bug #403871. 643 644 # The bug we're testing for caused an AttributeError to be raised 645 # when a ZipFile instance was created for a file that did not 646 # exist; the .fp member was not initialized but was needed by the 647 # __del__() method. Since the AttributeError is in the __del__(), 648 # it is ignored, but the user should be sufficiently annoyed by 649 # the message on the output that regression will be noticed 650 # quickly. 651 self.assertRaises(IOError, zipfile.ZipFile, TESTFN) 652 653 def testClosedZipRaisesRuntimeError(self): 654 # Verify that testzip() doesn't swallow inappropriate exceptions. 655 data = StringIO() 656 zipf = zipfile.ZipFile(data, mode="w") 657 zipf.writestr("foo.txt", "O, for a Muse of Fire!") 658 zipf.close() 659 660 # This is correct; calling .read on a closed ZipFile should throw 661 # a RuntimeError, and so should calling .testzip. An earlier 662 # version of .testzip would swallow this exception (and any other) 663 # and report that the first file in the archive was corrupt. 664 self.assertRaises(RuntimeError, zipf.read, "foo.txt") 665 self.assertRaises(RuntimeError, zipf.open, "foo.txt") 666 self.assertRaises(RuntimeError, zipf.testzip) 667 self.assertRaises(RuntimeError, zipf.writestr, "bogus.txt", "bogus") 668 file(TESTFN, 'w').write('zipfile test data') 669 self.assertRaises(RuntimeError, zipf.write, TESTFN) 670 671 def test_BadConstructorMode(self): 672 # Check that bad modes passed to ZipFile constructor are caught 673 self.assertRaises(RuntimeError, zipfile.ZipFile, TESTFN, "q") 674 675 def test_BadOpenMode(self): 676 # Check that bad modes passed to ZipFile.open are caught 677 zipf = zipfile.ZipFile(TESTFN, mode="w") 678 zipf.writestr("foo.txt", "O, for a Muse of Fire!") 679 zipf.close() 680 zipf = zipfile.ZipFile(TESTFN, mode="r") 681 # read the data to make sure the file is there 682 zipf.read("foo.txt") 683 self.assertRaises(RuntimeError, zipf.open, "foo.txt", "q") 684 zipf.close() 685 686 def test_Read0(self): 687 # Check that calling read(0) on a ZipExtFile object returns an empty 688 # string and doesn't advance file pointer 689 zipf = zipfile.ZipFile(TESTFN, mode="w") 690 zipf.writestr("foo.txt", "O, for a Muse of Fire!") 691 # read the data to make sure the file is there 692 f = zipf.open("foo.txt") 693 for i in xrange(FIXEDTEST_SIZE): 694 self.assertEqual(f.read(0), '') 695 696 self.assertEqual(f.read(), "O, for a Muse of Fire!") 697 zipf.close() 698 699 def test_OpenNonexistentItem(self): 700 # Check that attempting to call open() for an item that doesn't 701 # exist in the archive raises a RuntimeError 702 zipf = zipfile.ZipFile(TESTFN, mode="w") 703 self.assertRaises(KeyError, zipf.open, "foo.txt", "r") 704 705 def test_BadCompressionMode(self): 706 # Check that bad compression methods passed to ZipFile.open are caught 707 self.assertRaises(RuntimeError, zipfile.ZipFile, TESTFN, "w", -1) 708 709 def test_NullByteInFilename(self): 710 # Check that a filename containing a null byte is properly terminated 711 zipf = zipfile.ZipFile(TESTFN, mode="w") 712 zipf.writestr("foo.txt\x00qqq", "O, for a Muse of Fire!") 713 self.assertEqual(zipf.namelist(), ['foo.txt']) 714 715 def test_StructSizes(self): 716 # check that ZIP internal structure sizes are calculated correctly 717 self.assertEqual(zipfile.sizeEndCentDir, 22) 718 self.assertEqual(zipfile.sizeCentralDir, 46) 719 self.assertEqual(zipfile.sizeEndCentDir64, 56) 720 self.assertEqual(zipfile.sizeEndCentDir64Locator, 20) 721 722 def testComments(self): 723 # This test checks that comments on the archive are handled properly 724 725 # check default comment is empty 726 zipf = zipfile.ZipFile(TESTFN, mode="w") 727 self.assertEqual(zipf.comment, '') 728 zipf.writestr("foo.txt", "O, for a Muse of Fire!") 729 zipf.close() 730 zipfr = zipfile.ZipFile(TESTFN, mode="r") 731 self.assertEqual(zipfr.comment, '') 732 zipfr.close() 733 734 # check a simple short comment 735 comment = 'Bravely taking to his feet, he beat a very brave retreat.' 736 zipf = zipfile.ZipFile(TESTFN, mode="w") 737 zipf.comment = comment 738 zipf.writestr("foo.txt", "O, for a Muse of Fire!") 739 zipf.close() 740 zipfr = zipfile.ZipFile(TESTFN, mode="r") 741 self.assertEqual(zipfr.comment, comment) 742 zipfr.close() 743 744 # check a comment of max length 745 comment2 = ''.join(['%d' % (i**3 % 10) for i in xrange((1 << 16)-1)]) 746 zipf = zipfile.ZipFile(TESTFN, mode="w") 747 zipf.comment = comment2 748 zipf.writestr("foo.txt", "O, for a Muse of Fire!") 749 zipf.close() 750 zipfr = zipfile.ZipFile(TESTFN, mode="r") 751 self.assertEqual(zipfr.comment, comment2) 752 zipfr.close() 753 754 # check a comment that is too long is truncated 755 zipf = zipfile.ZipFile(TESTFN, mode="w") 756 zipf.comment = comment2 + 'oops' 757 zipf.writestr("foo.txt", "O, for a Muse of Fire!") 758 zipf.close() 759 zipfr = zipfile.ZipFile(TESTFN, mode="r") 760 self.assertEqual(zipfr.comment, comment2) 761 zipfr.close() 762 763 def tearDown(self): 764 support.unlink(TESTFN) 765 support.unlink(TESTFN2) 766 767class DecryptionTests(unittest.TestCase): 768 # This test checks that ZIP decryption works. Since the library does not 769 # support encryption at the moment, we use a pre-generated encrypted 770 # ZIP file 771 772 data = ( 773 'PK\x03\x04\x14\x00\x01\x00\x00\x00n\x92i.#y\xef?&\x00\x00\x00\x1a\x00' 774 '\x00\x00\x08\x00\x00\x00test.txt\xfa\x10\xa0gly|\xfa-\xc5\xc0=\xf9y' 775 '\x18\xe0\xa8r\xb3Z}Lg\xbc\xae\xf9|\x9b\x19\xe4\x8b\xba\xbb)\x8c\xb0\xdbl' 776 'PK\x01\x02\x14\x00\x14\x00\x01\x00\x00\x00n\x92i.#y\xef?&\x00\x00\x00' 777 '\x1a\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x01\x00 \x00\xb6\x81' 778 '\x00\x00\x00\x00test.txtPK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x006\x00' 779 '\x00\x00L\x00\x00\x00\x00\x00' ) 780 data2 = ( 781 'PK\x03\x04\x14\x00\t\x00\x08\x00\xcf}38xu\xaa\xb2\x14\x00\x00\x00\x00\x02' 782 '\x00\x00\x04\x00\x15\x00zeroUT\t\x00\x03\xd6\x8b\x92G\xda\x8b\x92GUx\x04' 783 '\x00\xe8\x03\xe8\x03\xc7<M\xb5a\xceX\xa3Y&\x8b{oE\xd7\x9d\x8c\x98\x02\xc0' 784 'PK\x07\x08xu\xaa\xb2\x14\x00\x00\x00\x00\x02\x00\x00PK\x01\x02\x17\x03' 785 '\x14\x00\t\x00\x08\x00\xcf}38xu\xaa\xb2\x14\x00\x00\x00\x00\x02\x00\x00' 786 '\x04\x00\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x00ze' 787 'roUT\x05\x00\x03\xd6\x8b\x92GUx\x00\x00PK\x05\x06\x00\x00\x00\x00\x01' 788 '\x00\x01\x00?\x00\x00\x00[\x00\x00\x00\x00\x00' ) 789 790 plain = 'zipfile.py encryption test' 791 plain2 = '\x00'*512 792 793 def setUp(self): 794 fp = open(TESTFN, "wb") 795 fp.write(self.data) 796 fp.close() 797 self.zip = zipfile.ZipFile(TESTFN, "r") 798 fp = open(TESTFN2, "wb") 799 fp.write(self.data2) 800 fp.close() 801 self.zip2 = zipfile.ZipFile(TESTFN2, "r") 802 803 def tearDown(self): 804 self.zip.close() 805 os.unlink(TESTFN) 806 self.zip2.close() 807 os.unlink(TESTFN2) 808 809 def testNoPassword(self): 810 # Reading the encrypted file without password 811 # must generate a RunTime exception 812 self.assertRaises(RuntimeError, self.zip.read, "test.txt") 813 self.assertRaises(RuntimeError, self.zip2.read, "zero") 814 815 def testBadPassword(self): 816 self.zip.setpassword("perl") 817 self.assertRaises(RuntimeError, self.zip.read, "test.txt") 818 self.zip2.setpassword("perl") 819 self.assertRaises(RuntimeError, self.zip2.read, "zero") 820 821 def testGoodPassword(self): 822 self.zip.setpassword("python") 823 self.assertEquals(self.zip.read("test.txt"), self.plain) 824 self.zip2.setpassword("12345") 825 self.assertEquals(self.zip2.read("zero"), self.plain2) 826 827 828class TestsWithRandomBinaryFiles(unittest.TestCase): 829 def setUp(self): 830 datacount = randint(16, 64)*1024 + randint(1, 1024) 831 self.data = ''.join((struct.pack('<f', random()*randint(-1000, 1000)) for i in xrange(datacount))) 832 833 # Make a source file with some lines 834 fp = open(TESTFN, "wb") 835 fp.write(self.data) 836 fp.close() 837 838 def tearDown(self): 839 support.unlink(TESTFN) 840 support.unlink(TESTFN2) 841 842 def makeTestArchive(self, f, compression): 843 # Create the ZIP archive 844 zipfp = zipfile.ZipFile(f, "w", compression) 845 zipfp.write(TESTFN, "another"+os.extsep+"name") 846 zipfp.write(TESTFN, TESTFN) 847 zipfp.close() 848 849 def zipTest(self, f, compression): 850 self.makeTestArchive(f, compression) 851 852 # Read the ZIP archive 853 zipfp = zipfile.ZipFile(f, "r", compression) 854 testdata = zipfp.read(TESTFN) 855 self.assertEqual(len(testdata), len(self.data)) 856 self.assertEqual(testdata, self.data) 857 self.assertEqual(zipfp.read("another"+os.extsep+"name"), self.data) 858 zipfp.close() 859 860 def testStored(self): 861 for f in (TESTFN2, TemporaryFile(), StringIO()): 862 self.zipTest(f, zipfile.ZIP_STORED) 863 864 def zipOpenTest(self, f, compression): 865 self.makeTestArchive(f, compression) 866 867 # Read the ZIP archive 868 zipfp = zipfile.ZipFile(f, "r", compression) 869 zipdata1 = [] 870 zipopen1 = zipfp.open(TESTFN) 871 while 1: 872 read_data = zipopen1.read(256) 873 if not read_data: 874 break 875 zipdata1.append(read_data) 876 877 zipdata2 = [] 878 zipopen2 = zipfp.open("another"+os.extsep+"name") 879 while 1: 880 read_data = zipopen2.read(256) 881 if not read_data: 882 break 883 zipdata2.append(read_data) 884 885 testdata1 = ''.join(zipdata1) 886 self.assertEqual(len(testdata1), len(self.data)) 887 self.assertEqual(testdata1, self.data) 888 889 testdata2 = ''.join(zipdata2) 890 self.assertEqual(len(testdata1), len(self.data)) 891 self.assertEqual(testdata1, self.data) 892 zipfp.close() 893 894 def testOpenStored(self): 895 for f in (TESTFN2, TemporaryFile(), StringIO()): 896 self.zipOpenTest(f, zipfile.ZIP_STORED) 897 898 def zipRandomOpenTest(self, f, compression): 899 self.makeTestArchive(f, compression) 900 901 # Read the ZIP archive 902 zipfp = zipfile.ZipFile(f, "r", compression) 903 zipdata1 = [] 904 zipopen1 = zipfp.open(TESTFN) 905 while 1: 906 read_data = zipopen1.read(randint(1, 1024)) 907 if not read_data: 908 break 909 zipdata1.append(read_data) 910 911 testdata = ''.join(zipdata1) 912 self.assertEqual(len(testdata), len(self.data)) 913 self.assertEqual(testdata, self.data) 914 zipfp.close() 915 916 def testRandomOpenStored(self): 917 for f in (TESTFN2, TemporaryFile(), StringIO()): 918 self.zipRandomOpenTest(f, zipfile.ZIP_STORED) 919 920class TestsWithMultipleOpens(unittest.TestCase): 921 def setUp(self): 922 # Create the ZIP archive 923 zipfp = zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_DEFLATED) 924 zipfp.writestr('ones', '1'*FIXEDTEST_SIZE) 925 zipfp.writestr('twos', '2'*FIXEDTEST_SIZE) 926 zipfp.close() 927 928 def testSameFile(self): 929 # Verify that (when the ZipFile is in control of creating file objects) 930 # multiple open() calls can be made without interfering with each other. 931 zipf = zipfile.ZipFile(TESTFN2, mode="r") 932 zopen1 = zipf.open('ones') 933 zopen2 = zipf.open('ones') 934 data1 = zopen1.read(500) 935 data2 = zopen2.read(500) 936 data1 += zopen1.read(500) 937 data2 += zopen2.read(500) 938 self.assertEqual(data1, data2) 939 zipf.close() 940 941 def testDifferentFile(self): 942 # Verify that (when the ZipFile is in control of creating file objects) 943 # multiple open() calls can be made without interfering with each other. 944 zipf = zipfile.ZipFile(TESTFN2, mode="r") 945 zopen1 = zipf.open('ones') 946 zopen2 = zipf.open('twos') 947 data1 = zopen1.read(500) 948 data2 = zopen2.read(500) 949 data1 += zopen1.read(500) 950 data2 += zopen2.read(500) 951 self.assertEqual(data1, '1'*FIXEDTEST_SIZE) 952 self.assertEqual(data2, '2'*FIXEDTEST_SIZE) 953 zipf.close() 954 955 def testInterleaved(self): 956 # Verify that (when the ZipFile is in control of creating file objects) 957 # multiple open() calls can be made without interfering with each other. 958 zipf = zipfile.ZipFile(TESTFN2, mode="r") 959 zopen1 = zipf.open('ones') 960 data1 = zopen1.read(500) 961 zopen2 = zipf.open('twos') 962 data2 = zopen2.read(500) 963 data1 += zopen1.read(500) 964 data2 += zopen2.read(500) 965 self.assertEqual(data1, '1'*FIXEDTEST_SIZE) 966 self.assertEqual(data2, '2'*FIXEDTEST_SIZE) 967 zipf.close() 968 969 def tearDown(self): 970 os.remove(TESTFN2) 971 972 973class UniversalNewlineTests(unittest.TestCase): 974 def setUp(self): 975 self.line_gen = ["Test of zipfile line %d." % i for i in xrange(FIXEDTEST_SIZE)] 976 self.seps = ('\r', '\r\n', '\n') 977 self.arcdata, self.arcfiles = {}, {} 978 for n, s in enumerate(self.seps): 979 self.arcdata[s] = s.join(self.line_gen) + s 980 self.arcfiles[s] = '%s-%d' % (TESTFN, n) 981 open(self.arcfiles[s], "wb").write(self.arcdata[s]) 982 983 def makeTestArchive(self, f, compression): 984 # Create the ZIP archive 985 zipfp = zipfile.ZipFile(f, "w", compression) 986 for fn in self.arcfiles.values(): 987 zipfp.write(fn, fn) 988 zipfp.close() 989 990 def readTest(self, f, compression): 991 self.makeTestArchive(f, compression) 992 993 # Read the ZIP archive 994 zipfp = zipfile.ZipFile(f, "r") 995 for sep, fn in self.arcfiles.items(): 996 zipdata = zipfp.open(fn, "rU").read() 997 self.assertEqual(self.arcdata[sep], zipdata) 998 999 zipfp.close() 1000 1001 def readlineTest(self, f, compression): 1002 self.makeTestArchive(f, compression) 1003 1004 # Read the ZIP archive 1005 zipfp = zipfile.ZipFile(f, "r") 1006 for sep, fn in self.arcfiles.items(): 1007 zipopen = zipfp.open(fn, "rU") 1008 for line in self.line_gen: 1009 linedata = zipopen.readline() 1010 self.assertEqual(linedata, line + '\n') 1011 1012 zipfp.close() 1013 1014 def readlinesTest(self, f, compression): 1015 self.makeTestArchive(f, compression) 1016 1017 # Read the ZIP archive 1018 zipfp = zipfile.ZipFile(f, "r") 1019 for sep, fn in self.arcfiles.items(): 1020 ziplines = zipfp.open(fn, "rU").readlines() 1021 for line, zipline in zip(self.line_gen, ziplines): 1022 self.assertEqual(zipline, line + '\n') 1023 1024 zipfp.close() 1025 1026 def iterlinesTest(self, f, compression): 1027 self.makeTestArchive(f, compression) 1028 1029 # Read the ZIP archive 1030 zipfp = zipfile.ZipFile(f, "r") 1031 for sep, fn in self.arcfiles.items(): 1032 for line, zipline in zip(self.line_gen, zipfp.open(fn, "rU")): 1033 self.assertEqual(zipline, line + '\n') 1034 1035 zipfp.close() 1036 1037 def testReadStored(self): 1038 for f in (TESTFN2, TemporaryFile(), StringIO()): 1039 self.readTest(f, zipfile.ZIP_STORED) 1040 1041 def testReadlineStored(self): 1042 for f in (TESTFN2, TemporaryFile(), StringIO()): 1043 self.readlineTest(f, zipfile.ZIP_STORED) 1044 1045 def testReadlinesStored(self): 1046 for f in (TESTFN2, TemporaryFile(), StringIO()): 1047 self.readlinesTest(f, zipfile.ZIP_STORED) 1048 1049 def testIterlinesStored(self): 1050 for f in (TESTFN2, TemporaryFile(), StringIO()): 1051 self.iterlinesTest(f, zipfile.ZIP_STORED) 1052 1053 if zlib: 1054 def testReadDeflated(self): 1055 for f in (TESTFN2, TemporaryFile(), StringIO()): 1056 self.readTest(f, zipfile.ZIP_DEFLATED) 1057 1058 def testReadlineDeflated(self): 1059 for f in (TESTFN2, TemporaryFile(), StringIO()): 1060 self.readlineTest(f, zipfile.ZIP_DEFLATED) 1061 1062 def testReadlinesDeflated(self): 1063 for f in (TESTFN2, TemporaryFile(), StringIO()): 1064 self.readlinesTest(f, zipfile.ZIP_DEFLATED) 1065 1066 def testIterlinesDeflated(self): 1067 for f in (TESTFN2, TemporaryFile(), StringIO()): 1068 self.iterlinesTest(f, zipfile.ZIP_DEFLATED) 1069 1070 def tearDown(self): 1071 for sep, fn in self.arcfiles.items(): 1072 os.remove(fn) 1073 support.unlink(TESTFN) 1074 support.unlink(TESTFN2) 1075 1076 1077def test_main(): 1078 run_unittest(TestsWithSourceFile, TestZip64InSmallFiles, OtherTests, 1079 PyZipFileTests, DecryptionTests, TestsWithMultipleOpens, 1080 UniversalNewlineTests, TestsWithRandomBinaryFiles) 1081 1082if __name__ == "__main__": 1083 test_main() 1084