diff options
Diffstat (limited to 'Lib/test/test_zipimport.py')
| -rw-r--r-- | Lib/test/test_zipimport.py | 121 |
1 files changed, 103 insertions, 18 deletions
diff --git a/Lib/test/test_zipimport.py b/Lib/test/test_zipimport.py index e31e217..b435b32 100644 --- a/Lib/test/test_zipimport.py +++ b/Lib/test/test_zipimport.py @@ -395,59 +395,144 @@ class ZipFileModifiedAfterImportTestCase(ImportHooksBaseTestCase): def setUp(self): zipimport._zip_directory_cache.clear() zipimport._zip_stat_cache.clear() + # save sys.modules so we can unimport everything done by our tests. + self._sys_modules_orig = dict(sys.modules) ImportHooksBaseTestCase.setUp(self) def tearDown(self): ImportHooksBaseTestCase.tearDown(self) + # The closest we can come to un-importing our zipped up test modules. + sys.modules.clear() + sys.modules.update(self._sys_modules_orig) if os.path.exists(TEMP_ZIP): os.remove(TEMP_ZIP) - def testZipFileChangesAfterFirstImport(self): - """Alter the zip file after caching its index and try an import.""" + def setUpZipFileModuleAndTestImports(self): + # Create a .zip file to test with + self.zipfile_path = TEMP_ZIP packdir = TESTPACK + os.sep files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc), packdir + TESTMOD + ".py": (NOW, "test_value = 38\n"), "ziptest_a.py": (NOW, "test_value = 23\n"), "ziptest_b.py": (NOW, "test_value = 42\n"), "ziptest_c.py": (NOW, "test_value = 1337\n")} - zipfile_path = TEMP_ZIP - _write_zip_package(zipfile_path, files) - self.assertTrue(os.path.exists(zipfile_path)) - sys.path.insert(0, zipfile_path) + _write_zip_package(self.zipfile_path, files) + self.assertTrue(os.path.exists(self.zipfile_path)) + sys.path.insert(0, self.zipfile_path) + + self.testpack_testmod = TESTPACK + "." + TESTMOD + + with io.open(self.zipfile_path, "rb") as orig_zip_file: + self.orig_zip_file_contents = orig_zip_file.read() # Import something out of the zipfile and confirm it is correct. - testmod = __import__(TESTPACK + "." + TESTMOD, + testmod = __import__(self.testpack_testmod, globals(), locals(), ["__dummy__"]) self.assertEqual(testmod.test_value, 38) + del sys.modules[TESTPACK] + del sys.modules[self.testpack_testmod] + # Import something else out of the zipfile and confirm it is correct. ziptest_b = __import__("ziptest_b", globals(), locals(), ["test_value"]) self.assertEqual(ziptest_b.test_value, 42) + del sys.modules["ziptest_b"] - # Truncate and fill the zip file with non-zip garbage. - with io.open(zipfile_path, "rb") as orig_zip_file: - orig_zip_file_contents = orig_zip_file.read() - with io.open(zipfile_path, "wb") as byebye_valid_zip_file: + def truncateAndFillZipWithNonZipGarbage(self): + with io.open(self.zipfile_path, "wb") as byebye_valid_zip_file: byebye_valid_zip_file.write(b"Tear down this wall!\n"*1987) + + def restoreZipFileWithDifferentHeaderOffsets(self): + """Make it a valid zipfile with some garbage at the start.""" + # This alters all of the caches offsets within the file. + with io.open(self.zipfile_path, "wb") as new_zip_file: + new_zip_file.write(b"X"*1991) # The year Python was created. + new_zip_file.write(self.orig_zip_file_contents) + + def testZipFileChangesAfterFirstImport(self): + """Alter the zip file after caching its index and try an import.""" + self.setUpZipFileModuleAndTestImports() + # The above call cached the .zip table of contents during its tests. + self.truncateAndFillZipWithNonZipGarbage() # Now that the zipfile has been replaced, import something else from it # which should fail as the file contents are now garbage. with self.assertRaises(ImportError): ziptest_a = __import__("ziptest_a", globals(), locals(), ["test_value"]) + # The code path used by the __import__ call is different than + # that used by import statements. Try these as well. Some of + # these may create new zipimporter instances. We need to + # function properly using the global zipimport caches + # regardless of how many zipimporter instances for the same + # .zip file exist. + with self.assertRaises(ImportError): + import ziptest_a + with self.assertRaises(ImportError): + from ziptest_a import test_value + with self.assertRaises(ImportError): + exec("from {} import {}".format(TESTPACK, TESTMOD)) - # Now lets make it a valid zipfile that has some garbage at the start. - # This alters all of the offsets within the file - with io.open(zipfile_path, "wb") as new_zip_file: - new_zip_file.write(b"X"*1991) # The year Python was created. - new_zip_file.write(orig_zip_file_contents) + # Alters all of the offsets within the file + self.restoreZipFileWithDifferentHeaderOffsets() # Now that the zip file has been "restored" to a valid but different - # zipfile the zipimporter should *successfully* re-read the new zip - # file's end of file central index and be able to import from it again. + # zipfile all zipimporter instances should *successfully* re-read the + # new file's end of file central index and be able to import again. + + # Importing a submodule triggers a different import code path. + exec("import " + self.testpack_testmod) + self.assertEqual(getattr(locals()[TESTPACK], TESTMOD).test_value, 38) + exec("from {} import {}".format(TESTPACK, TESTMOD)) + self.assertEqual(locals()[TESTMOD].test_value, 38) + ziptest_a = __import__("ziptest_a", globals(), locals(), ["test_value"]) self.assertEqual(ziptest_a.test_value, 23) ziptest_c = __import__("ziptest_c", globals(), locals(), ["test_value"]) self.assertEqual(ziptest_c.test_value, 1337) + def testZipFileSubpackageImport(self): + """Import via multiple sys.path entries into parts of the zip.""" + self.setUpZipFileModuleAndTestImports() + # Put a subdirectory within the zip file into the import path. + sys.path.insert(0, self.zipfile_path + os.sep + TESTPACK) + + testmod = __import__(TESTMOD, globals(), locals(), ["test_value"]) + self.assertEqual(testmod.test_value, 38) + del sys.modules[TESTMOD] + exec("from {} import test_value".format(TESTMOD)) + self.assertEqual(test_value, 38) + del sys.modules[TESTMOD] + + # Confirm that imports from the top level of the zip file + # (already in sys.path from the setup call above) still work. + ziptest_a = __import__("ziptest_a", globals(), locals(), ["test_value"]) + self.assertEqual(ziptest_a.test_value, 23) + del sys.modules["ziptest_a"] + import ziptest_c + self.assertEqual(ziptest_c.test_value, 1337) + del sys.modules["ziptest_c"] + + self.truncateAndFillZipWithNonZipGarbage() + # Imports should now fail. + with self.assertRaises(ImportError): + testmod = __import__(TESTMOD, globals(), locals(), ["test_value"]) + with self.assertRaises(ImportError): + exec("from {} import test_value".format(TESTMOD)) + with self.assertRaises(ImportError): + import ziptest_a + + self.restoreZipFileWithDifferentHeaderOffsets() + # Imports should work again, the central directory TOC will be re-read. + testmod = __import__(TESTMOD, globals(), locals(), ["test_value"]) + self.assertEqual(testmod.test_value, 38) + del sys.modules[TESTMOD] + exec("from {} import test_value".format(TESTMOD)) + self.assertEqual(test_value, 38) + + ziptest_a = __import__("ziptest_a", globals(), locals(), ["test_value"]) + self.assertEqual(ziptest_a.test_value, 23) + import ziptest_c + self.assertEqual(ziptest_c.test_value, 1337) + class BadFileZipImportTestCase(unittest.TestCase): def assertZipFailure(self, filename): |
