~malept/ubuntu/lucid/python2.6/dev-dependency-fix

« back to all changes in this revision

Viewing changes to Lib/test/test_zipimport.py

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-02-13 12:51:00 UTC
  • Revision ID: james.westby@ubuntu.com-20090213125100-uufgcb9yeqzujpqw
Tags: upstream-2.6.1
ImportĀ upstreamĀ versionĀ 2.6.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import sys
 
2
import os
 
3
import marshal
 
4
import imp
 
5
import struct
 
6
import time
 
7
import unittest
 
8
 
 
9
import zlib # implied prerequisite
 
10
from zipfile import ZipFile, ZipInfo, ZIP_STORED, ZIP_DEFLATED
 
11
from test import test_support
 
12
from test.test_importhooks import ImportHooksBaseTestCase, test_src, test_co
 
13
 
 
14
import zipimport
 
15
import linecache
 
16
import doctest
 
17
import inspect
 
18
import StringIO
 
19
from traceback import extract_tb, extract_stack, print_tb
 
20
raise_src = 'def do_raise(): raise TypeError\n'
 
21
 
 
22
# so we only run testAFakeZlib once if this test is run repeatedly
 
23
# which happens when we look for ref leaks
 
24
test_imported = False
 
25
 
 
26
 
 
27
def make_pyc(co, mtime):
 
28
    data = marshal.dumps(co)
 
29
    if type(mtime) is type(0.0):
 
30
        # Mac mtimes need a bit of special casing
 
31
        if mtime < 0x7fffffff:
 
32
            mtime = int(mtime)
 
33
        else:
 
34
            mtime = int(-0x100000000L + long(mtime))
 
35
    pyc = imp.get_magic() + struct.pack("<i", int(mtime)) + data
 
36
    return pyc
 
37
 
 
38
def module_path_to_dotted_name(path):
 
39
    return path.replace(os.sep, '.')
 
40
 
 
41
NOW = time.time()
 
42
test_pyc = make_pyc(test_co, NOW)
 
43
 
 
44
 
 
45
if __debug__:
 
46
    pyc_ext = ".pyc"
 
47
else:
 
48
    pyc_ext = ".pyo"
 
49
 
 
50
 
 
51
TESTMOD = "ziptestmodule"
 
52
TESTPACK = "ziptestpackage"
 
53
TESTPACK2 = "ziptestpackage2"
 
54
TEMP_ZIP = os.path.abspath("junk95142" + os.extsep + "zip")
 
55
 
 
56
class UncompressedZipImportTestCase(ImportHooksBaseTestCase):
 
57
 
 
58
    compression = ZIP_STORED
 
59
 
 
60
    def setUp(self):
 
61
        # We're reusing the zip archive path, so we must clear the
 
62
        # cached directory info and linecache
 
63
        linecache.clearcache()
 
64
        zipimport._zip_directory_cache.clear()
 
65
        ImportHooksBaseTestCase.setUp(self)
 
66
 
 
67
    def doTest(self, expected_ext, files, *modules, **kw):
 
68
        z = ZipFile(TEMP_ZIP, "w")
 
69
        try:
 
70
            for name, (mtime, data) in files.items():
 
71
                zinfo = ZipInfo(name, time.localtime(mtime))
 
72
                zinfo.compress_type = self.compression
 
73
                z.writestr(zinfo, data)
 
74
            z.close()
 
75
 
 
76
            stuff = kw.get("stuff", None)
 
77
            if stuff is not None:
 
78
                # Prepend 'stuff' to the start of the zipfile
 
79
                f = open(TEMP_ZIP, "rb")
 
80
                data = f.read()
 
81
                f.close()
 
82
 
 
83
                f = open(TEMP_ZIP, "wb")
 
84
                f.write(stuff)
 
85
                f.write(data)
 
86
                f.close()
 
87
 
 
88
            sys.path.insert(0, TEMP_ZIP)
 
89
 
 
90
            mod = __import__(".".join(modules), globals(), locals(),
 
91
                             ["__dummy__"])
 
92
 
 
93
            call = kw.get('call')
 
94
            if call is not None:
 
95
                call(mod)
 
96
 
 
97
            if expected_ext:
 
98
                file = mod.get_file()
 
99
                self.assertEquals(file, os.path.join(TEMP_ZIP,
 
100
                                  *modules) + expected_ext)
 
101
        finally:
 
102
            z.close()
 
103
            os.remove(TEMP_ZIP)
 
104
 
 
105
    def testAFakeZlib(self):
 
106
        #
 
107
        # This could cause a stack overflow before: importing zlib.py
 
108
        # from a compressed archive would cause zlib to be imported
 
109
        # which would find zlib.py in the archive, which would... etc.
 
110
        #
 
111
        # This test *must* be executed first: it must be the first one
 
112
        # to trigger zipimport to import zlib (zipimport caches the
 
113
        # zlib.decompress function object, after which the problem being
 
114
        # tested here wouldn't be a problem anymore...
 
115
        # (Hence the 'A' in the test method name: to make it the first
 
116
        # item in a list sorted by name, like unittest.makeSuite() does.)
 
117
        #
 
118
        # This test fails on platforms on which the zlib module is
 
119
        # statically linked, but the problem it tests for can't
 
120
        # occur in that case (builtin modules are always found first),
 
121
        # so we'll simply skip it then. Bug #765456.
 
122
        #
 
123
        if "zlib" in sys.builtin_module_names:
 
124
            return
 
125
        if "zlib" in sys.modules:
 
126
            del sys.modules["zlib"]
 
127
        files = {"zlib.py": (NOW, test_src)}
 
128
        try:
 
129
            self.doTest(".py", files, "zlib")
 
130
        except ImportError:
 
131
            if self.compression != ZIP_DEFLATED:
 
132
                self.fail("expected test to not raise ImportError")
 
133
        else:
 
134
            if self.compression != ZIP_STORED:
 
135
                self.fail("expected test to raise ImportError")
 
136
 
 
137
    def testPy(self):
 
138
        files = {TESTMOD + ".py": (NOW, test_src)}
 
139
        self.doTest(".py", files, TESTMOD)
 
140
 
 
141
    def testPyc(self):
 
142
        files = {TESTMOD + pyc_ext: (NOW, test_pyc)}
 
143
        self.doTest(pyc_ext, files, TESTMOD)
 
144
 
 
145
    def testBoth(self):
 
146
        files = {TESTMOD + ".py": (NOW, test_src),
 
147
                 TESTMOD + pyc_ext: (NOW, test_pyc)}
 
148
        self.doTest(pyc_ext, files, TESTMOD)
 
149
 
 
150
    def testEmptyPy(self):
 
151
        files = {TESTMOD + ".py": (NOW, "")}
 
152
        self.doTest(None, files, TESTMOD)
 
153
 
 
154
    def testBadMagic(self):
 
155
        # make pyc magic word invalid, forcing loading from .py
 
156
        m0 = ord(test_pyc[0])
 
157
        m0 ^= 0x04  # flip an arbitrary bit
 
158
        badmagic_pyc = chr(m0) + test_pyc[1:]
 
159
        files = {TESTMOD + ".py": (NOW, test_src),
 
160
                 TESTMOD + pyc_ext: (NOW, badmagic_pyc)}
 
161
        self.doTest(".py", files, TESTMOD)
 
162
 
 
163
    def testBadMagic2(self):
 
164
        # make pyc magic word invalid, causing an ImportError
 
165
        m0 = ord(test_pyc[0])
 
166
        m0 ^= 0x04  # flip an arbitrary bit
 
167
        badmagic_pyc = chr(m0) + test_pyc[1:]
 
168
        files = {TESTMOD + pyc_ext: (NOW, badmagic_pyc)}
 
169
        try:
 
170
            self.doTest(".py", files, TESTMOD)
 
171
        except ImportError:
 
172
            pass
 
173
        else:
 
174
            self.fail("expected ImportError; import from bad pyc")
 
175
 
 
176
    def testBadMTime(self):
 
177
        t3 = ord(test_pyc[7])
 
178
        t3 ^= 0x02  # flip the second bit -- not the first as that one
 
179
                    # isn't stored in the .py's mtime in the zip archive.
 
180
        badtime_pyc = test_pyc[:7] + chr(t3) + test_pyc[8:]
 
181
        files = {TESTMOD + ".py": (NOW, test_src),
 
182
                 TESTMOD + pyc_ext: (NOW, badtime_pyc)}
 
183
        self.doTest(".py", files, TESTMOD)
 
184
 
 
185
    def testPackage(self):
 
186
        packdir = TESTPACK + os.sep
 
187
        files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc),
 
188
                 packdir + TESTMOD + pyc_ext: (NOW, test_pyc)}
 
189
        self.doTest(pyc_ext, files, TESTPACK, TESTMOD)
 
190
 
 
191
    def testDeepPackage(self):
 
192
        packdir = TESTPACK + os.sep
 
193
        packdir2 = packdir + TESTPACK2 + os.sep
 
194
        files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc),
 
195
                 packdir2 + "__init__" + pyc_ext: (NOW, test_pyc),
 
196
                 packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)}
 
197
        self.doTest(pyc_ext, files, TESTPACK, TESTPACK2, TESTMOD)
 
198
 
 
199
    def testZipImporterMethods(self):
 
200
        packdir = TESTPACK + os.sep
 
201
        packdir2 = packdir + TESTPACK2 + os.sep
 
202
        files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc),
 
203
                 packdir2 + "__init__" + pyc_ext: (NOW, test_pyc),
 
204
                 packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)}
 
205
 
 
206
        z = ZipFile(TEMP_ZIP, "w")
 
207
        try:
 
208
            for name, (mtime, data) in files.items():
 
209
                zinfo = ZipInfo(name, time.localtime(mtime))
 
210
                zinfo.compress_type = self.compression
 
211
                z.writestr(zinfo, data)
 
212
            z.close()
 
213
 
 
214
            zi = zipimport.zipimporter(TEMP_ZIP)
 
215
            self.assertEquals(zi.archive, TEMP_ZIP)
 
216
            self.assertEquals(zi.is_package(TESTPACK), True)
 
217
            zi.load_module(TESTPACK)
 
218
 
 
219
            self.assertEquals(zi.is_package(packdir + '__init__'), False)
 
220
            self.assertEquals(zi.is_package(packdir + TESTPACK2), True)
 
221
            self.assertEquals(zi.is_package(packdir2 + TESTMOD), False)
 
222
 
 
223
            mod_name = packdir2 + TESTMOD
 
224
            mod = __import__(module_path_to_dotted_name(mod_name))
 
225
            self.assertEquals(zi.get_source(TESTPACK), None)
 
226
            self.assertEquals(zi.get_source(mod_name), None)
 
227
 
 
228
            # test prefix and archivepath members
 
229
            zi2 = zipimport.zipimporter(TEMP_ZIP + os.sep + TESTPACK)
 
230
            self.assertEquals(zi2.archive, TEMP_ZIP)
 
231
            self.assertEquals(zi2.prefix, TESTPACK + os.sep)
 
232
        finally:
 
233
            z.close()
 
234
            os.remove(TEMP_ZIP)
 
235
 
 
236
    def testZipImporterMethodsInSubDirectory(self):
 
237
        packdir = TESTPACK + os.sep
 
238
        packdir2 = packdir + TESTPACK2 + os.sep
 
239
        files = {packdir2 + "__init__" + pyc_ext: (NOW, test_pyc),
 
240
                 packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)}
 
241
 
 
242
        z = ZipFile(TEMP_ZIP, "w")
 
243
        try:
 
244
            for name, (mtime, data) in files.items():
 
245
                zinfo = ZipInfo(name, time.localtime(mtime))
 
246
                zinfo.compress_type = self.compression
 
247
                z.writestr(zinfo, data)
 
248
            z.close()
 
249
 
 
250
            zi = zipimport.zipimporter(TEMP_ZIP + os.sep + packdir)
 
251
            self.assertEquals(zi.archive, TEMP_ZIP)
 
252
            self.assertEquals(zi.prefix, packdir)
 
253
            self.assertEquals(zi.is_package(TESTPACK2), True)
 
254
            zi.load_module(TESTPACK2)
 
255
 
 
256
            self.assertEquals(zi.is_package(TESTPACK2 + os.sep + '__init__'), False)
 
257
            self.assertEquals(zi.is_package(TESTPACK2 + os.sep + TESTMOD), False)
 
258
 
 
259
            mod_name = TESTPACK2 + os.sep + TESTMOD
 
260
            mod = __import__(module_path_to_dotted_name(mod_name))
 
261
            self.assertEquals(zi.get_source(TESTPACK2), None)
 
262
            self.assertEquals(zi.get_source(mod_name), None)
 
263
        finally:
 
264
            z.close()
 
265
            os.remove(TEMP_ZIP)
 
266
 
 
267
    def testGetData(self):
 
268
        z = ZipFile(TEMP_ZIP, "w")
 
269
        z.compression = self.compression
 
270
        try:
 
271
            name = "testdata.dat"
 
272
            data = "".join([chr(x) for x in range(256)]) * 500
 
273
            z.writestr(name, data)
 
274
            z.close()
 
275
            zi = zipimport.zipimporter(TEMP_ZIP)
 
276
            self.assertEquals(data, zi.get_data(name))
 
277
            self.assert_('zipimporter object' in repr(zi))
 
278
        finally:
 
279
            z.close()
 
280
            os.remove(TEMP_ZIP)
 
281
 
 
282
    def testImporterAttr(self):
 
283
        src = """if 1:  # indent hack
 
284
        def get_file():
 
285
            return __file__
 
286
        if __loader__.get_data("some.data") != "some data":
 
287
            raise AssertionError, "bad data"\n"""
 
288
        pyc = make_pyc(compile(src, "<???>", "exec"), NOW)
 
289
        files = {TESTMOD + pyc_ext: (NOW, pyc),
 
290
                 "some.data": (NOW, "some data")}
 
291
        self.doTest(pyc_ext, files, TESTMOD)
 
292
 
 
293
    def testImport_WithStuff(self):
 
294
        # try importing from a zipfile which contains additional
 
295
        # stuff at the beginning of the file
 
296
        files = {TESTMOD + ".py": (NOW, test_src)}
 
297
        self.doTest(".py", files, TESTMOD,
 
298
                    stuff="Some Stuff"*31)
 
299
 
 
300
    def assertModuleSource(self, module):
 
301
        self.assertEqual(inspect.getsource(module), test_src)
 
302
 
 
303
    def testGetSource(self):
 
304
        files = {TESTMOD + ".py": (NOW, test_src)}
 
305
        self.doTest(".py", files, TESTMOD, call=self.assertModuleSource)
 
306
 
 
307
    def testGetCompiledSource(self):
 
308
        pyc = make_pyc(compile(test_src, "<???>", "exec"), NOW)
 
309
        files = {TESTMOD + ".py": (NOW, test_src),
 
310
                 TESTMOD + pyc_ext: (NOW, pyc)}
 
311
        self.doTest(pyc_ext, files, TESTMOD, call=self.assertModuleSource)
 
312
 
 
313
    def runDoctest(self, callback):
 
314
        files = {TESTMOD + ".py": (NOW, test_src),
 
315
                 "xyz.txt": (NOW, ">>> log.append(True)\n")}
 
316
        self.doTest(".py", files, TESTMOD, call=callback)
 
317
 
 
318
    def doDoctestFile(self, module):
 
319
        log = []
 
320
        old_master, doctest.master = doctest.master, None
 
321
        try:
 
322
            doctest.testfile(
 
323
                'xyz.txt', package=module, module_relative=True,
 
324
                globs=locals()
 
325
            )
 
326
        finally:
 
327
            doctest.master = old_master
 
328
        self.assertEqual(log,[True])
 
329
 
 
330
    def testDoctestFile(self):
 
331
        self.runDoctest(self.doDoctestFile)
 
332
 
 
333
    def doDoctestSuite(self, module):
 
334
        log = []
 
335
        doctest.DocFileTest(
 
336
            'xyz.txt', package=module, module_relative=True,
 
337
            globs=locals()
 
338
        ).run()
 
339
        self.assertEqual(log,[True])
 
340
 
 
341
    def testDoctestSuite(self):
 
342
        self.runDoctest(self.doDoctestSuite)
 
343
 
 
344
 
 
345
    def doTraceback(self, module):
 
346
        try:
 
347
            module.do_raise()
 
348
        except:
 
349
            tb = sys.exc_info()[2].tb_next
 
350
 
 
351
            f,lno,n,line = extract_tb(tb, 1)[0]
 
352
            self.assertEqual(line, raise_src.strip())
 
353
 
 
354
            f,lno,n,line = extract_stack(tb.tb_frame, 1)[0]
 
355
            self.assertEqual(line, raise_src.strip())
 
356
 
 
357
            s = StringIO.StringIO()
 
358
            print_tb(tb, 1, s)
 
359
            self.failUnless(s.getvalue().endswith(raise_src))
 
360
        else:
 
361
            raise AssertionError("This ought to be impossible")
 
362
 
 
363
    def testTraceback(self):
 
364
        files = {TESTMOD + ".py": (NOW, raise_src)}
 
365
        self.doTest(None, files, TESTMOD, call=self.doTraceback)
 
366
 
 
367
 
 
368
class CompressedZipImportTestCase(UncompressedZipImportTestCase):
 
369
    compression = ZIP_DEFLATED
 
370
 
 
371
 
 
372
class BadFileZipImportTestCase(unittest.TestCase):
 
373
    def assertZipFailure(self, filename):
 
374
        self.assertRaises(zipimport.ZipImportError,
 
375
                          zipimport.zipimporter, filename)
 
376
 
 
377
    def testNoFile(self):
 
378
        self.assertZipFailure('AdfjdkFJKDFJjdklfjs')
 
379
 
 
380
    def testEmptyFilename(self):
 
381
        self.assertZipFailure('')
 
382
 
 
383
    def testBadArgs(self):
 
384
        self.assertRaises(TypeError, zipimport.zipimporter, None)
 
385
        self.assertRaises(TypeError, zipimport.zipimporter, TESTMOD, kwd=None)
 
386
 
 
387
    def testFilenameTooLong(self):
 
388
        self.assertZipFailure('A' * 33000)
 
389
 
 
390
    def testEmptyFile(self):
 
391
        test_support.unlink(TESTMOD)
 
392
        open(TESTMOD, 'w+').close()
 
393
        self.assertZipFailure(TESTMOD)
 
394
 
 
395
    def testFileUnreadable(self):
 
396
        test_support.unlink(TESTMOD)
 
397
        fd = os.open(TESTMOD, os.O_CREAT, 000)
 
398
        try:
 
399
            os.close(fd)
 
400
            self.assertZipFailure(TESTMOD)
 
401
        finally:
 
402
            # If we leave "the read-only bit" set on Windows, nothing can
 
403
            # delete TESTMOD, and later tests suffer bogus failures.
 
404
            os.chmod(TESTMOD, 0666)
 
405
            test_support.unlink(TESTMOD)
 
406
 
 
407
    def testNotZipFile(self):
 
408
        test_support.unlink(TESTMOD)
 
409
        fp = open(TESTMOD, 'w+')
 
410
        fp.write('a' * 22)
 
411
        fp.close()
 
412
        self.assertZipFailure(TESTMOD)
 
413
 
 
414
    # XXX: disabled until this works on Big-endian machines
 
415
    def _testBogusZipFile(self):
 
416
        test_support.unlink(TESTMOD)
 
417
        fp = open(TESTMOD, 'w+')
 
418
        fp.write(struct.pack('=I', 0x06054B50))
 
419
        fp.write('a' * 18)
 
420
        fp.close()
 
421
        z = zipimport.zipimporter(TESTMOD)
 
422
 
 
423
        try:
 
424
            self.assertRaises(TypeError, z.find_module, None)
 
425
            self.assertRaises(TypeError, z.load_module, None)
 
426
            self.assertRaises(TypeError, z.is_package, None)
 
427
            self.assertRaises(TypeError, z.get_code, None)
 
428
            self.assertRaises(TypeError, z.get_data, None)
 
429
            self.assertRaises(TypeError, z.get_source, None)
 
430
 
 
431
            error = zipimport.ZipImportError
 
432
            self.assertEqual(z.find_module('abc'), None)
 
433
 
 
434
            self.assertRaises(error, z.load_module, 'abc')
 
435
            self.assertRaises(error, z.get_code, 'abc')
 
436
            self.assertRaises(IOError, z.get_data, 'abc')
 
437
            self.assertRaises(error, z.get_source, 'abc')
 
438
            self.assertRaises(error, z.is_package, 'abc')
 
439
        finally:
 
440
            zipimport._zip_directory_cache.clear()
 
441
 
 
442
 
 
443
def cleanup():
 
444
    # this is necessary if test is run repeated (like when finding leaks)
 
445
    global test_imported
 
446
    if test_imported:
 
447
        zipimport._zip_directory_cache.clear()
 
448
        if hasattr(UncompressedZipImportTestCase, 'testAFakeZlib'):
 
449
            delattr(UncompressedZipImportTestCase, 'testAFakeZlib')
 
450
        if hasattr(CompressedZipImportTestCase, 'testAFakeZlib'):
 
451
            delattr(CompressedZipImportTestCase, 'testAFakeZlib')
 
452
    test_imported = True
 
453
 
 
454
def test_main():
 
455
    cleanup()
 
456
    try:
 
457
        test_support.run_unittest(
 
458
              UncompressedZipImportTestCase,
 
459
              CompressedZipImportTestCase,
 
460
              BadFileZipImportTestCase,
 
461
            )
 
462
    finally:
 
463
        test_support.unlink(TESTMOD)
 
464
 
 
465
if __name__ == "__main__":
 
466
    test_main()