Exceptions raised during renaming in rotating file handlers are now passed to handleE...
[python.git] / Lib / test / test_support.py
blobbec1a0f401f51b401b766f0a93528e0f1b9c97fc
1 """Supporting definitions for the Python regression tests."""
3 if __name__ != 'test.test_support':
4 raise ImportError, 'test_support must be imported from the test package'
6 import sys
8 class Error(Exception):
9 """Base class for regression test exceptions."""
11 class TestFailed(Error):
12 """Test failed."""
14 class TestSkipped(Error):
15 """Test skipped.
17 This can be raised to indicate that a test was deliberatly
18 skipped, but not because a feature wasn't available. For
19 example, if some resource can't be used, such as the network
20 appears to be unavailable, this should be raised instead of
21 TestFailed.
22 """
24 class ResourceDenied(TestSkipped):
25 """Test skipped because it requested a disallowed resource.
27 This is raised when a test calls requires() for a resource that
28 has not be enabled. It is used to distinguish between expected
29 and unexpected skips.
30 """
32 verbose = 1 # Flag set to 0 by regrtest.py
33 use_resources = None # Flag set to [] by regrtest.py
35 # _original_stdout is meant to hold stdout at the time regrtest began.
36 # This may be "the real" stdout, or IDLE's emulation of stdout, or whatever.
37 # The point is to have some flavor of stdout the user can actually see.
38 _original_stdout = None
39 def record_original_stdout(stdout):
40 global _original_stdout
41 _original_stdout = stdout
43 def get_original_stdout():
44 return _original_stdout or sys.stdout
46 def unload(name):
47 try:
48 del sys.modules[name]
49 except KeyError:
50 pass
52 def forget(modname):
53 '''"Forget" a module was ever imported by removing it from sys.modules and
54 deleting any .pyc and .pyo files.'''
55 unload(modname)
56 import os
57 for dirname in sys.path:
58 try:
59 os.unlink(os.path.join(dirname, modname + os.extsep + 'pyc'))
60 except os.error:
61 pass
62 # Deleting the .pyo file cannot be within the 'try' for the .pyc since
63 # the chance exists that there is no .pyc (and thus the 'try' statement
64 # is exited) but there is a .pyo file.
65 try:
66 os.unlink(os.path.join(dirname, modname + os.extsep + 'pyo'))
67 except os.error:
68 pass
70 def is_resource_enabled(resource):
71 """Test whether a resource is enabled. Known resources are set by
72 regrtest.py."""
73 return use_resources is not None and resource in use_resources
75 def requires(resource, msg=None):
76 """Raise ResourceDenied if the specified resource is not available.
78 If the caller's module is __main__ then automatically return True. The
79 possibility of False being returned occurs when regrtest.py is executing."""
80 # see if the caller's module is __main__ - if so, treat as if
81 # the resource was set
82 if sys._getframe().f_back.f_globals.get("__name__") == "__main__":
83 return
84 if not is_resource_enabled(resource):
85 if msg is None:
86 msg = "Use of the `%s' resource not enabled" % resource
87 raise ResourceDenied(msg)
89 FUZZ = 1e-6
91 def fcmp(x, y): # fuzzy comparison function
92 if type(x) == type(0.0) or type(y) == type(0.0):
93 try:
94 x, y = coerce(x, y)
95 fuzz = (abs(x) + abs(y)) * FUZZ
96 if abs(x-y) <= fuzz:
97 return 0
98 except:
99 pass
100 elif type(x) == type(y) and type(x) in (type(()), type([])):
101 for i in range(min(len(x), len(y))):
102 outcome = fcmp(x[i], y[i])
103 if outcome != 0:
104 return outcome
105 return cmp(len(x), len(y))
106 return cmp(x, y)
108 try:
109 unicode
110 have_unicode = 1
111 except NameError:
112 have_unicode = 0
114 is_jython = sys.platform.startswith('java')
116 import os
117 # Filename used for testing
118 if os.name == 'java':
119 # Jython disallows @ in module names
120 TESTFN = '$test'
121 elif os.name == 'riscos':
122 TESTFN = 'testfile'
123 else:
124 TESTFN = '@test'
125 # Unicode name only used if TEST_FN_ENCODING exists for the platform.
126 if have_unicode:
127 # Assuming sys.getfilesystemencoding()!=sys.getdefaultencoding()
128 # TESTFN_UNICODE is a filename that can be encoded using the
129 # file system encoding, but *not* with the default (ascii) encoding
130 if isinstance('', unicode):
131 # python -U
132 # XXX perhaps unicode() should accept Unicode strings?
133 TESTFN_UNICODE = "@test-\xe0\xf2"
134 else:
135 # 2 latin characters.
136 TESTFN_UNICODE = unicode("@test-\xe0\xf2", "latin-1")
137 TESTFN_ENCODING = sys.getfilesystemencoding()
138 # TESTFN_UNICODE_UNENCODEABLE is a filename that should *not* be
139 # able to be encoded by *either* the default or filesystem encoding.
140 # This test really only makes sense on Windows NT platforms
141 # which have special Unicode support in posixmodule.
142 if (not hasattr(sys, "getwindowsversion") or
143 sys.getwindowsversion()[3] < 2): # 0=win32s or 1=9x/ME
144 TESTFN_UNICODE_UNENCODEABLE = None
145 else:
146 # Japanese characters (I think - from bug 846133)
147 TESTFN_UNICODE_UNENCODEABLE = eval('u"@test-\u5171\u6709\u3055\u308c\u308b"')
148 try:
149 # XXX - Note - should be using TESTFN_ENCODING here - but for
150 # Windows, "mbcs" currently always operates as if in
151 # errors=ignore' mode - hence we get '?' characters rather than
152 # the exception. 'Latin1' operates as we expect - ie, fails.
153 # See [ 850997 ] mbcs encoding ignores errors
154 TESTFN_UNICODE_UNENCODEABLE.encode("Latin1")
155 except UnicodeEncodeError:
156 pass
157 else:
158 print \
159 'WARNING: The filename %r CAN be encoded by the filesystem. ' \
160 'Unicode filename tests may not be effective' \
161 % TESTFN_UNICODE_UNENCODEABLE
163 # Make sure we can write to TESTFN, try in /tmp if we can't
164 fp = None
165 try:
166 fp = open(TESTFN, 'w+')
167 except IOError:
168 TMP_TESTFN = os.path.join('/tmp', TESTFN)
169 try:
170 fp = open(TMP_TESTFN, 'w+')
171 TESTFN = TMP_TESTFN
172 del TMP_TESTFN
173 except IOError:
174 print ('WARNING: tests will fail, unable to write to: %s or %s' %
175 (TESTFN, TMP_TESTFN))
176 if fp is not None:
177 fp.close()
178 try:
179 os.unlink(TESTFN)
180 except:
181 pass
182 del os, fp
184 from os import unlink
186 def findfile(file, here=__file__):
187 """Try to find a file on sys.path and the working directory. If it is not
188 found the argument passed to the function is returned (this does not
189 necessarily signal failure; could still be the legitimate path)."""
190 import os
191 if os.path.isabs(file):
192 return file
193 path = sys.path
194 path = [os.path.dirname(here)] + path
195 for dn in path:
196 fn = os.path.join(dn, file)
197 if os.path.exists(fn): return fn
198 return file
200 def verify(condition, reason='test failed'):
201 """Verify that condition is true. If not, raise TestFailed.
203 The optional argument reason can be given to provide
204 a better error text.
207 if not condition:
208 raise TestFailed(reason)
210 def vereq(a, b):
211 """Raise TestFailed if a == b is false.
213 This is better than verify(a == b) because, in case of failure, the
214 error message incorporates repr(a) and repr(b) so you can see the
215 inputs.
217 Note that "not (a == b)" isn't necessarily the same as "a != b"; the
218 former is tested.
221 if not (a == b):
222 raise TestFailed, "%r == %r" % (a, b)
224 def sortdict(dict):
225 "Like repr(dict), but in sorted order."
226 items = dict.items()
227 items.sort()
228 reprpairs = ["%r: %r" % pair for pair in items]
229 withcommas = ", ".join(reprpairs)
230 return "{%s}" % withcommas
232 def check_syntax(statement):
233 try:
234 compile(statement, '<string>', 'exec')
235 except SyntaxError:
236 pass
237 else:
238 print 'Missing SyntaxError: "%s"' % statement
240 def open_urlresource(url):
241 import urllib, urlparse
242 import os.path
244 filename = urlparse.urlparse(url)[2].split('/')[-1] # '/': it's URL!
246 for path in [os.path.curdir, os.path.pardir]:
247 fn = os.path.join(path, filename)
248 if os.path.exists(fn):
249 return open(fn)
251 requires('urlfetch')
252 print >> get_original_stdout(), '\tfetching %s ...' % url
253 fn, _ = urllib.urlretrieve(url, filename)
254 return open(fn)
256 #=======================================================================
257 # Preliminary PyUNIT integration.
259 import unittest
262 class BasicTestRunner:
263 def run(self, test):
264 result = unittest.TestResult()
265 test(result)
266 return result
269 def run_suite(suite, testclass=None):
270 """Run tests from a unittest.TestSuite-derived class."""
271 if verbose:
272 runner = unittest.TextTestRunner(sys.stdout, verbosity=2)
273 else:
274 runner = BasicTestRunner()
276 result = runner.run(suite)
277 if not result.wasSuccessful():
278 if len(result.errors) == 1 and not result.failures:
279 err = result.errors[0][1]
280 elif len(result.failures) == 1 and not result.errors:
281 err = result.failures[0][1]
282 else:
283 if testclass is None:
284 msg = "errors occurred; run in verbose mode for details"
285 else:
286 msg = "errors occurred in %s.%s" \
287 % (testclass.__module__, testclass.__name__)
288 raise TestFailed(msg)
289 raise TestFailed(err)
292 def run_unittest(*classes):
293 """Run tests from unittest.TestCase-derived classes."""
294 suite = unittest.TestSuite()
295 for cls in classes:
296 if isinstance(cls, (unittest.TestSuite, unittest.TestCase)):
297 suite.addTest(cls)
298 else:
299 suite.addTest(unittest.makeSuite(cls))
300 if len(classes)==1:
301 testclass = classes[0]
302 else:
303 testclass = None
304 run_suite(suite, testclass)
307 #=======================================================================
308 # doctest driver.
310 def run_doctest(module, verbosity=None):
311 """Run doctest on the given module. Return (#failures, #tests).
313 If optional argument verbosity is not specified (or is None), pass
314 test_support's belief about verbosity on to doctest. Else doctest's
315 usual behavior is used (it searches sys.argv for -v).
318 import doctest
320 if verbosity is None:
321 verbosity = verbose
322 else:
323 verbosity = None
325 # Direct doctest output (normally just errors) to real stdout; doctest
326 # output shouldn't be compared by regrtest.
327 save_stdout = sys.stdout
328 sys.stdout = get_original_stdout()
329 try:
330 f, t = doctest.testmod(module, verbose=verbosity)
331 if f:
332 raise TestFailed("%d of %d doctests failed" % (f, t))
333 finally:
334 sys.stdout = save_stdout
335 if verbose:
336 print 'doctest (%s) ... %d tests with zero failures' % (module.__name__, t)
337 return f, t