blob: 5f6d8ef056854706432fec9fba0fba672896b059 [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__"])
59 file = mod.get_file()
60 self.assertEquals(file, os.path.join(TEMP_ZIP,
61 os.sep.join(modules) + expected_ext))
62 finally:
63 z.close()
64 os.remove(TEMP_ZIP)
65
66 def testAFakeZlib(self):
67 #
68 # This could cause a stack overflow before: importing zlib.py
69 # from a compressed archive would cause zlib to be imported
70 # which would find zlib.py in the archive, which would... etc.
71 #
72 # This test *must* be executed first: it must be the first one
73 # to trigger zipimport to import zlib (zipimport caches the
74 # zlib.decompress function object, after which the problem being
75 # tested here wouldn't be a problem anymore...
76 # (Hence the 'A' in the test method name: to make it the first
77 # item in a list sorted by name, like unittest.makeSuite() does.)
78 #
79 if "zlib" in sys.modules:
80 del sys.modules["zlib"]
81 files = {"zlib.py": (NOW, test_src)}
82 try:
83 self.doTest(".py", files, "zlib")
84 except ImportError:
85 if self.compression != ZIP_DEFLATED:
86 self.fail("expected test to not raise ImportError")
87 else:
88 if self.compression != ZIP_STORED:
89 self.fail("expected test to raise ImportError")
90
91 def testPy(self):
92 files = {TESTMOD + ".py": (NOW, test_src)}
93 self.doTest(".py", files, TESTMOD)
94
95 def testPyc(self):
96 files = {TESTMOD + pyc_ext: (NOW, test_pyc)}
97 self.doTest(pyc_ext, files, TESTMOD)
98
99 def testBoth(self):
100 files = {TESTMOD + ".py": (NOW, test_src),
101 TESTMOD + pyc_ext: (NOW, test_pyc)}
102 self.doTest(pyc_ext, files, TESTMOD)
103
104 def testBadMagic(self):
105 # make pyc magic word invalid, forcing loading from .py
106 m0 = ord(test_pyc[0])
107 m0 ^= 0x04 # flip an arbitrary bit
108 badmagic_pyc = chr(m0) + test_pyc[1:]
109 files = {TESTMOD + ".py": (NOW, test_src),
110 TESTMOD + pyc_ext: (NOW, badmagic_pyc)}
111 self.doTest(".py", files, TESTMOD)
112
113 def testBadMagic2(self):
114 # make pyc magic word invalid, causing an ImportError
115 m0 = ord(test_pyc[0])
116 m0 ^= 0x04 # flip an arbitrary bit
117 badmagic_pyc = chr(m0) + test_pyc[1:]
118 files = {TESTMOD + pyc_ext: (NOW, badmagic_pyc)}
119 try:
120 self.doTest(".py", files, TESTMOD)
121 except ImportError:
122 pass
123 else:
124 self.fail("expected ImportError; import from bad pyc")
125
126 def testBadMTime(self):
127 t3 = ord(test_pyc[7])
128 t3 ^= 0x02 # flip the second bit -- not the first as that one
129 # isn't stored in the .py's mtime in the zip archive.
130 badtime_pyc = test_pyc[:7] + chr(t3) + test_pyc[8:]
131 files = {TESTMOD + ".py": (NOW, test_src),
132 TESTMOD + pyc_ext: (NOW, badtime_pyc)}
133 self.doTest(".py", files, TESTMOD)
134
135 def testPackage(self):
136 packdir = TESTPACK + os.sep
137 files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc),
138 packdir + TESTMOD + pyc_ext: (NOW, test_pyc)}
139 self.doTest(pyc_ext, files, TESTPACK, TESTMOD)
140
141 def testDeepPackage(self):
142 packdir = TESTPACK + os.sep
Just van Rossumd35c6db2003-01-02 12:55:48 +0000143 packdir2 = packdir + TESTPACK2 + os.sep
Just van Rossum52e14d62002-12-30 22:08:05 +0000144 files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc),
145 packdir2 + "__init__" + pyc_ext: (NOW, test_pyc),
146 packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)}
Just van Rossumd35c6db2003-01-02 12:55:48 +0000147 self.doTest(pyc_ext, files, TESTPACK, TESTPACK2, TESTMOD)
Just van Rossum52e14d62002-12-30 22:08:05 +0000148
149 def testGetData(self):
150 z = ZipFile(TEMP_ZIP, "w")
151 z.compression = self.compression
152 try:
153 name = "testdata.dat"
154 data = "".join([chr(x) for x in range(256)]) * 500
155 z.writestr(name, data)
156 z.close()
157 zi = zipimport.zipimporter(TEMP_ZIP)
158 self.assertEquals(data, zi.get_data(name))
159 finally:
160 z.close()
161 os.remove(TEMP_ZIP)
162
163 def testImporterAttr(self):
164 src = """if 1: # indent hack
165 def get_file():
166 return __file__
Just van Rossumd35c6db2003-01-02 12:55:48 +0000167 if __loader__.get_data("some.data") != "some data":
Just van Rossum52e14d62002-12-30 22:08:05 +0000168 raise AssertionError, "bad data"\n"""
169 pyc = make_pyc(compile(src, "<???>", "exec"), NOW)
170 files = {TESTMOD + pyc_ext: (NOW, pyc),
171 "some.data": (NOW, "some data")}
172 self.doTest(pyc_ext, files, TESTMOD)
173
174
175class CompressedZipImportTestCase(UncompressedZipImportTestCase):
176 compression = ZIP_DEFLATED
177
178
179if __name__ == "__main__":
180 test_support.run_unittest(UncompressedZipImportTestCase)
181 test_support.run_unittest(CompressedZipImportTestCase)