blob: 9bde605f7595e023b71ca9bfa12348dca5aabd39 [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)
Jack Jansen472e7db2003-01-08 16:37:03 +000018 if type(mtime) is type(0.0):
19 # Mac mtimes need a bit of special casing
20 if mtime < 0x7fffffff:
21 mtime = int(mtime)
22 else:
23 mtime = int(-0x100000000L + long(mtime))
24 pyc = imp.get_magic() + struct.pack("<i", int(mtime)) + data
Just van Rossum52e14d62002-12-30 22:08:05 +000025 return pyc
26
27NOW = time.time()
28test_pyc = make_pyc(test_co, NOW)
29
30
31if __debug__:
32 pyc_ext = ".pyc"
33else:
34 pyc_ext = ".pyo"
35
36
37TESTMOD = "ziptestmodule"
38TESTPACK = "ziptestpackage"
Just van Rossumd35c6db2003-01-02 12:55:48 +000039TESTPACK2 = "ziptestpackage2"
40TEMP_ZIP = os.path.abspath("junk95142.zip")
Jack Jansen472e7db2003-01-08 16:37:03 +000041if sys.platform == 'mac':
42 CURDIRPREFIX=':'
43else:
44 CURDIRPREFIX=''
Just van Rossum52e14d62002-12-30 22:08:05 +000045
46class UncompressedZipImportTestCase(ImportHooksBaseTestCase):
47
48 compression = ZIP_STORED
49
50 def setUp(self):
51 # We're reusing the zip archive path, so we must clear the
52 # cached directory info.
53 zipimport._zip_directory_cache.clear()
54 ImportHooksBaseTestCase.setUp(self)
55
56 def doTest(self, expected_ext, files, *modules):
57 z = ZipFile(TEMP_ZIP, "w")
58 try:
59 for name, (mtime, data) in files.items():
60 zinfo = ZipInfo(name, time.localtime(mtime))
61 zinfo.compress_type = self.compression
62 z.writestr(zinfo, data)
63 z.close()
64 sys.path.insert(0, TEMP_ZIP)
65
66 mod = __import__(".".join(modules), globals(), locals(),
67 ["__dummy__"])
Just van Rossum9a3129c2003-01-03 11:18:56 +000068 if expected_ext:
69 file = mod.get_file()
70 self.assertEquals(file, os.path.join(TEMP_ZIP,
Jack Jansen472e7db2003-01-08 16:37:03 +000071 CURDIRPREFIX + os.sep.join(modules) + expected_ext))
Just van Rossum52e14d62002-12-30 22:08:05 +000072 finally:
73 z.close()
74 os.remove(TEMP_ZIP)
75
76 def testAFakeZlib(self):
77 #
78 # This could cause a stack overflow before: importing zlib.py
79 # from a compressed archive would cause zlib to be imported
80 # which would find zlib.py in the archive, which would... etc.
81 #
82 # This test *must* be executed first: it must be the first one
83 # to trigger zipimport to import zlib (zipimport caches the
84 # zlib.decompress function object, after which the problem being
85 # tested here wouldn't be a problem anymore...
86 # (Hence the 'A' in the test method name: to make it the first
87 # item in a list sorted by name, like unittest.makeSuite() does.)
88 #
89 if "zlib" in sys.modules:
90 del sys.modules["zlib"]
91 files = {"zlib.py": (NOW, test_src)}
92 try:
93 self.doTest(".py", files, "zlib")
94 except ImportError:
95 if self.compression != ZIP_DEFLATED:
96 self.fail("expected test to not raise ImportError")
97 else:
98 if self.compression != ZIP_STORED:
99 self.fail("expected test to raise ImportError")
100
101 def testPy(self):
102 files = {TESTMOD + ".py": (NOW, test_src)}
103 self.doTest(".py", files, TESTMOD)
104
105 def testPyc(self):
106 files = {TESTMOD + pyc_ext: (NOW, test_pyc)}
107 self.doTest(pyc_ext, files, TESTMOD)
108
109 def testBoth(self):
110 files = {TESTMOD + ".py": (NOW, test_src),
111 TESTMOD + pyc_ext: (NOW, test_pyc)}
112 self.doTest(pyc_ext, files, TESTMOD)
113
Just van Rossum9a3129c2003-01-03 11:18:56 +0000114 def testEmptyPy(self):
115 files = {TESTMOD + ".py": (NOW, "")}
116 self.doTest(None, files, TESTMOD)
117
Just van Rossum52e14d62002-12-30 22:08:05 +0000118 def testBadMagic(self):
119 # make pyc magic word invalid, forcing loading from .py
120 m0 = ord(test_pyc[0])
121 m0 ^= 0x04 # flip an arbitrary bit
122 badmagic_pyc = chr(m0) + test_pyc[1:]
123 files = {TESTMOD + ".py": (NOW, test_src),
124 TESTMOD + pyc_ext: (NOW, badmagic_pyc)}
125 self.doTest(".py", files, TESTMOD)
126
127 def testBadMagic2(self):
128 # make pyc magic word invalid, causing an ImportError
129 m0 = ord(test_pyc[0])
130 m0 ^= 0x04 # flip an arbitrary bit
131 badmagic_pyc = chr(m0) + test_pyc[1:]
132 files = {TESTMOD + pyc_ext: (NOW, badmagic_pyc)}
133 try:
134 self.doTest(".py", files, TESTMOD)
135 except ImportError:
136 pass
137 else:
138 self.fail("expected ImportError; import from bad pyc")
139
140 def testBadMTime(self):
141 t3 = ord(test_pyc[7])
142 t3 ^= 0x02 # flip the second bit -- not the first as that one
143 # isn't stored in the .py's mtime in the zip archive.
144 badtime_pyc = test_pyc[:7] + chr(t3) + test_pyc[8:]
145 files = {TESTMOD + ".py": (NOW, test_src),
146 TESTMOD + pyc_ext: (NOW, badtime_pyc)}
147 self.doTest(".py", files, TESTMOD)
148
149 def testPackage(self):
150 packdir = TESTPACK + os.sep
151 files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc),
152 packdir + TESTMOD + pyc_ext: (NOW, test_pyc)}
153 self.doTest(pyc_ext, files, TESTPACK, TESTMOD)
154
155 def testDeepPackage(self):
156 packdir = TESTPACK + os.sep
Just van Rossumd35c6db2003-01-02 12:55:48 +0000157 packdir2 = packdir + TESTPACK2 + os.sep
Just van Rossum52e14d62002-12-30 22:08:05 +0000158 files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc),
159 packdir2 + "__init__" + pyc_ext: (NOW, test_pyc),
160 packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)}
Just van Rossumd35c6db2003-01-02 12:55:48 +0000161 self.doTest(pyc_ext, files, TESTPACK, TESTPACK2, TESTMOD)
Just van Rossum52e14d62002-12-30 22:08:05 +0000162
163 def testGetData(self):
164 z = ZipFile(TEMP_ZIP, "w")
165 z.compression = self.compression
166 try:
167 name = "testdata.dat"
168 data = "".join([chr(x) for x in range(256)]) * 500
169 z.writestr(name, data)
170 z.close()
171 zi = zipimport.zipimporter(TEMP_ZIP)
172 self.assertEquals(data, zi.get_data(name))
173 finally:
174 z.close()
175 os.remove(TEMP_ZIP)
176
177 def testImporterAttr(self):
178 src = """if 1: # indent hack
179 def get_file():
180 return __file__
Just van Rossumd35c6db2003-01-02 12:55:48 +0000181 if __loader__.get_data("some.data") != "some data":
Just van Rossum52e14d62002-12-30 22:08:05 +0000182 raise AssertionError, "bad data"\n"""
183 pyc = make_pyc(compile(src, "<???>", "exec"), NOW)
184 files = {TESTMOD + pyc_ext: (NOW, pyc),
185 "some.data": (NOW, "some data")}
186 self.doTest(pyc_ext, files, TESTMOD)
187
188
189class CompressedZipImportTestCase(UncompressedZipImportTestCase):
190 compression = ZIP_DEFLATED
191
192
193if __name__ == "__main__":
194 test_support.run_unittest(UncompressedZipImportTestCase)
195 test_support.run_unittest(CompressedZipImportTestCase)