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