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