blob: 3c790eb4deaa501926c765a6471f9951e3821615 [file] [log] [blame]
Just van Rossum52e14d62002-12-30 22:08:05 +00001import sys
2import os
3import marshal
4import imp
5import struct
6import time
7
8import zlib # implied prerequisite
9from zipfile import ZipFile, ZipInfo, ZIP_STORED, ZIP_DEFLATED
10from test import test_support
11from test.test_importhooks import ImportHooksBaseTestCase, test_src, test_co
12
13import zipimport
14
15
16def make_pyc(co, mtime):
17 data = marshal.dumps(co)
18 pyc = imp.get_magic() + struct.pack("<i", mtime) + data
19 return pyc
20
21NOW = time.time()
22test_pyc = make_pyc(test_co, NOW)
23
24
25if __debug__:
26 pyc_ext = ".pyc"
27else:
28 pyc_ext = ".pyo"
29
30
31TESTMOD = "ziptestmodule"
32TESTPACK = "ziptestpackage"
Just van Rossumd35c6db2003-01-02 12:55:48 +000033TESTPACK2 = "ziptestpackage2"
34TEMP_ZIP = os.path.abspath("junk95142.zip")
Just van Rossum52e14d62002-12-30 22:08:05 +000035
36
37class UncompressedZipImportTestCase(ImportHooksBaseTestCase):
38
39 compression = ZIP_STORED
40
41 def setUp(self):
42 # We're reusing the zip archive path, so we must clear the
43 # cached directory info.
44 zipimport._zip_directory_cache.clear()
45 ImportHooksBaseTestCase.setUp(self)
46
47 def doTest(self, expected_ext, files, *modules):
48 z = ZipFile(TEMP_ZIP, "w")
49 try:
50 for name, (mtime, data) in files.items():
51 zinfo = ZipInfo(name, time.localtime(mtime))
52 zinfo.compress_type = self.compression
53 z.writestr(zinfo, data)
54 z.close()
55 sys.path.insert(0, TEMP_ZIP)
56
57 mod = __import__(".".join(modules), globals(), locals(),
58 ["__dummy__"])
Just van Rossum9a3129c2003-01-03 11:18:56 +000059 if expected_ext:
60 file = mod.get_file()
61 self.assertEquals(file, os.path.join(TEMP_ZIP,
62 os.sep.join(modules) + expected_ext))
Just van Rossum52e14d62002-12-30 22:08:05 +000063 finally:
64 z.close()
65 os.remove(TEMP_ZIP)
66
67 def testAFakeZlib(self):
68 #
69 # This could cause a stack overflow before: importing zlib.py
70 # from a compressed archive would cause zlib to be imported
71 # which would find zlib.py in the archive, which would... etc.
72 #
73 # This test *must* be executed first: it must be the first one
74 # to trigger zipimport to import zlib (zipimport caches the
75 # zlib.decompress function object, after which the problem being
76 # tested here wouldn't be a problem anymore...
77 # (Hence the 'A' in the test method name: to make it the first
78 # item in a list sorted by name, like unittest.makeSuite() does.)
79 #
80 if "zlib" in sys.modules:
81 del sys.modules["zlib"]
82 files = {"zlib.py": (NOW, test_src)}
83 try:
84 self.doTest(".py", files, "zlib")
85 except ImportError:
86 if self.compression != ZIP_DEFLATED:
87 self.fail("expected test to not raise ImportError")
88 else:
89 if self.compression != ZIP_STORED:
90 self.fail("expected test to raise ImportError")
91
92 def testPy(self):
93 files = {TESTMOD + ".py": (NOW, test_src)}
94 self.doTest(".py", files, TESTMOD)
95
96 def testPyc(self):
97 files = {TESTMOD + pyc_ext: (NOW, test_pyc)}
98 self.doTest(pyc_ext, files, TESTMOD)
99
100 def testBoth(self):
101 files = {TESTMOD + ".py": (NOW, test_src),
102 TESTMOD + pyc_ext: (NOW, test_pyc)}
103 self.doTest(pyc_ext, files, TESTMOD)
104
Just van Rossum9a3129c2003-01-03 11:18:56 +0000105 def testEmptyPy(self):
106 files = {TESTMOD + ".py": (NOW, "")}
107 self.doTest(None, files, TESTMOD)
108
Just van Rossum52e14d62002-12-30 22:08:05 +0000109 def testBadMagic(self):
110 # make pyc magic word invalid, forcing loading from .py
111 m0 = ord(test_pyc[0])
112 m0 ^= 0x04 # flip an arbitrary bit
113 badmagic_pyc = chr(m0) + test_pyc[1:]
114 files = {TESTMOD + ".py": (NOW, test_src),
115 TESTMOD + pyc_ext: (NOW, badmagic_pyc)}
116 self.doTest(".py", files, TESTMOD)
117
118 def testBadMagic2(self):
119 # make pyc magic word invalid, causing an ImportError
120 m0 = ord(test_pyc[0])
121 m0 ^= 0x04 # flip an arbitrary bit
122 badmagic_pyc = chr(m0) + test_pyc[1:]
123 files = {TESTMOD + pyc_ext: (NOW, badmagic_pyc)}
124 try:
125 self.doTest(".py", files, TESTMOD)
126 except ImportError:
127 pass
128 else:
129 self.fail("expected ImportError; import from bad pyc")
130
131 def testBadMTime(self):
132 t3 = ord(test_pyc[7])
133 t3 ^= 0x02 # flip the second bit -- not the first as that one
134 # isn't stored in the .py's mtime in the zip archive.
135 badtime_pyc = test_pyc[:7] + chr(t3) + test_pyc[8:]
136 files = {TESTMOD + ".py": (NOW, test_src),
137 TESTMOD + pyc_ext: (NOW, badtime_pyc)}
138 self.doTest(".py", files, TESTMOD)
139
140 def testPackage(self):
141 packdir = TESTPACK + os.sep
142 files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc),
143 packdir + TESTMOD + pyc_ext: (NOW, test_pyc)}
144 self.doTest(pyc_ext, files, TESTPACK, TESTMOD)
145
146 def testDeepPackage(self):
147 packdir = TESTPACK + os.sep
Just van Rossumd35c6db2003-01-02 12:55:48 +0000148 packdir2 = packdir + TESTPACK2 + os.sep
Just van Rossum52e14d62002-12-30 22:08:05 +0000149 files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc),
150 packdir2 + "__init__" + pyc_ext: (NOW, test_pyc),
151 packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)}
Just van Rossumd35c6db2003-01-02 12:55:48 +0000152 self.doTest(pyc_ext, files, TESTPACK, TESTPACK2, TESTMOD)
Just van Rossum52e14d62002-12-30 22:08:05 +0000153
154 def testGetData(self):
155 z = ZipFile(TEMP_ZIP, "w")
156 z.compression = self.compression
157 try:
158 name = "testdata.dat"
159 data = "".join([chr(x) for x in range(256)]) * 500
160 z.writestr(name, data)
161 z.close()
162 zi = zipimport.zipimporter(TEMP_ZIP)
163 self.assertEquals(data, zi.get_data(name))
164 finally:
165 z.close()
166 os.remove(TEMP_ZIP)
167
168 def testImporterAttr(self):
169 src = """if 1: # indent hack
170 def get_file():
171 return __file__
Just van Rossumd35c6db2003-01-02 12:55:48 +0000172 if __loader__.get_data("some.data") != "some data":
Just van Rossum52e14d62002-12-30 22:08:05 +0000173 raise AssertionError, "bad data"\n"""
174 pyc = make_pyc(compile(src, "<???>", "exec"), NOW)
175 files = {TESTMOD + pyc_ext: (NOW, pyc),
176 "some.data": (NOW, "some data")}
177 self.doTest(pyc_ext, files, TESTMOD)
178
179
180class CompressedZipImportTestCase(UncompressedZipImportTestCase):
181 compression = ZIP_DEFLATED
182
183
184if __name__ == "__main__":
185 test_support.run_unittest(UncompressedZipImportTestCase)
186 test_support.run_unittest(CompressedZipImportTestCase)