blob: 2d08f4dde01ba3b272b542fc5dbc3520c0dcbda0 [file] [log] [blame]
Brett Cannonf1cfb622003-05-04 21:15:27 +00001"""Supporting definitions for the Python regression tests."""
Guido van Rossum3bead091992-01-27 17:00:37 +00002
Barry Warsaw408b6d32002-07-30 23:27:12 +00003if __name__ != 'test.test_support':
4 raise ImportError, 'test_support must be imported from the test package'
5
Fred Drakecd1b1dd2001-03-21 18:26:33 +00006import sys
7
Fred Drake1790dd42000-07-24 06:55:00 +00008class Error(Exception):
Fred Drake004d5e62000-10-23 17:22:08 +00009 """Base class for regression test exceptions."""
Fred Drake1790dd42000-07-24 06:55:00 +000010
11class TestFailed(Error):
Fred Drake004d5e62000-10-23 17:22:08 +000012 """Test failed."""
Fred Drake1790dd42000-07-24 06:55:00 +000013
14class TestSkipped(Error):
Fred Drake004d5e62000-10-23 17:22:08 +000015 """Test skipped.
Fred Drake1790dd42000-07-24 06:55:00 +000016
Fred Drake004d5e62000-10-23 17:22:08 +000017 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.
Fred Drake004d5e62000-10-23 17:22:08 +000022 """
Fred Drake1790dd42000-07-24 06:55:00 +000023
Fred Drake9a0db072003-02-03 15:19:30 +000024class ResourceDenied(TestSkipped):
25 """Test skipped because it requested a disallowed resource.
26
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 """
31
Barry Warsawc0fb6052001-08-20 22:29:23 +000032verbose = 1 # Flag set to 0 by regrtest.py
Thomas Wouters477c8d52006-05-27 19:21:47 +000033use_resources = None # Flag set to [] by regrtest.py
34max_memuse = 0 # Disable bigmem tests (they will still be run with
35 # small sizes, to make sure they work.)
Guido van Rossum531661c1996-12-20 02:58:22 +000036
Tim Peters8dee8092001-09-25 20:05:11 +000037# _original_stdout is meant to hold stdout at the time regrtest began.
38# This may be "the real" stdout, or IDLE's emulation of stdout, or whatever.
39# The point is to have some flavor of stdout the user can actually see.
40_original_stdout = None
41def record_original_stdout(stdout):
42 global _original_stdout
43 _original_stdout = stdout
44
45def get_original_stdout():
46 return _original_stdout or sys.stdout
47
Guido van Rossum3bead091992-01-27 17:00:37 +000048def unload(name):
Fred Drake004d5e62000-10-23 17:22:08 +000049 try:
50 del sys.modules[name]
51 except KeyError:
52 pass
Guido van Rossum3bead091992-01-27 17:00:37 +000053
Neal Norwitz0e17f8c2006-01-23 07:51:27 +000054def unlink(filename):
55 import os
56 try:
57 os.unlink(filename)
58 except OSError:
59 pass
60
Guido van Rossum3bead091992-01-27 17:00:37 +000061def forget(modname):
Brett Cannonf1cfb622003-05-04 21:15:27 +000062 '''"Forget" a module was ever imported by removing it from sys.modules and
63 deleting any .pyc and .pyo files.'''
Fred Drake004d5e62000-10-23 17:22:08 +000064 unload(modname)
Fred Drakecd1b1dd2001-03-21 18:26:33 +000065 import os
Fred Drake004d5e62000-10-23 17:22:08 +000066 for dirname in sys.path:
Neal Norwitz0e17f8c2006-01-23 07:51:27 +000067 unlink(os.path.join(dirname, modname + os.extsep + 'pyc'))
Brett Cannonf1cfb622003-05-04 21:15:27 +000068 # Deleting the .pyo file cannot be within the 'try' for the .pyc since
69 # the chance exists that there is no .pyc (and thus the 'try' statement
70 # is exited) but there is a .pyo file.
Neal Norwitz0e17f8c2006-01-23 07:51:27 +000071 unlink(os.path.join(dirname, modname + os.extsep + 'pyo'))
Guido van Rossum3bead091992-01-27 17:00:37 +000072
Tim Petersb4ee4eb2002-12-04 03:26:57 +000073def is_resource_enabled(resource):
Brett Cannonf1cfb622003-05-04 21:15:27 +000074 """Test whether a resource is enabled. Known resources are set by
75 regrtest.py."""
Tim Petersb4ee4eb2002-12-04 03:26:57 +000076 return use_resources is not None and resource in use_resources
77
Barry Warsawc0fb6052001-08-20 22:29:23 +000078def requires(resource, msg=None):
Brett Cannonf1cfb622003-05-04 21:15:27 +000079 """Raise ResourceDenied if the specified resource is not available.
80
81 If the caller's module is __main__ then automatically return True. The
82 possibility of False being returned occurs when regrtest.py is executing."""
Skip Montanarod839ecd2003-04-24 19:06:57 +000083 # see if the caller's module is __main__ - if so, treat as if
84 # the resource was set
85 if sys._getframe().f_back.f_globals.get("__name__") == "__main__":
86 return
Tim Petersb4ee4eb2002-12-04 03:26:57 +000087 if not is_resource_enabled(resource):
Barry Warsawc0fb6052001-08-20 22:29:23 +000088 if msg is None:
89 msg = "Use of the `%s' resource not enabled" % resource
Fred Drake9a0db072003-02-03 15:19:30 +000090 raise ResourceDenied(msg)
Barry Warsawc0fb6052001-08-20 22:29:23 +000091
Guido van Rossum35fb82a1993-01-26 13:04:43 +000092FUZZ = 1e-6
93
94def fcmp(x, y): # fuzzy comparison function
Fred Drake004d5e62000-10-23 17:22:08 +000095 if type(x) == type(0.0) or type(y) == type(0.0):
96 try:
97 x, y = coerce(x, y)
98 fuzz = (abs(x) + abs(y)) * FUZZ
99 if abs(x-y) <= fuzz:
100 return 0
101 except:
102 pass
103 elif type(x) == type(y) and type(x) in (type(()), type([])):
104 for i in range(min(len(x), len(y))):
105 outcome = fcmp(x[i], y[i])
Fred Drake132dce22000-12-12 23:11:42 +0000106 if outcome != 0:
Fred Drake004d5e62000-10-23 17:22:08 +0000107 return outcome
108 return cmp(len(x), len(y))
109 return cmp(x, y)
Guido van Rossum35fb82a1993-01-26 13:04:43 +0000110
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000111try:
112 unicode
113 have_unicode = 1
114except NameError:
115 have_unicode = 0
116
Finn Bock57bc5fa2002-11-01 18:02:03 +0000117is_jython = sys.platform.startswith('java')
118
Guido van Rossuma8f7e592001-03-13 09:31:07 +0000119import os
Barry Warsaw559f6682001-03-23 18:04:02 +0000120# Filename used for testing
121if os.name == 'java':
122 # Jython disallows @ in module names
123 TESTFN = '$test'
Martin v. Löwisa94568a2003-05-10 07:36:56 +0000124elif os.name == 'riscos':
125 TESTFN = 'testfile'
126else:
Barry Warsaw559f6682001-03-23 18:04:02 +0000127 TESTFN = '@test'
Mark Hammondef8b6542001-05-13 08:04:26 +0000128 # Unicode name only used if TEST_FN_ENCODING exists for the platform.
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000129 if have_unicode:
Mark Hammondb337dd92003-12-03 01:27:23 +0000130 # Assuming sys.getfilesystemencoding()!=sys.getdefaultencoding()
131 # TESTFN_UNICODE is a filename that can be encoded using the
132 # file system encoding, but *not* with the default (ascii) encoding
Martin v. Löwis2411a2d2002-11-09 19:57:26 +0000133 if isinstance('', unicode):
134 # python -U
135 # XXX perhaps unicode() should accept Unicode strings?
Tim Petersc6c5ece2003-12-04 05:39:43 +0000136 TESTFN_UNICODE = "@test-\xe0\xf2"
Martin v. Löwis2411a2d2002-11-09 19:57:26 +0000137 else:
Tim Petersc6c5ece2003-12-04 05:39:43 +0000138 # 2 latin characters.
139 TESTFN_UNICODE = unicode("@test-\xe0\xf2", "latin-1")
140 TESTFN_ENCODING = sys.getfilesystemencoding()
141 # TESTFN_UNICODE_UNENCODEABLE is a filename that should *not* be
Mark Hammondb337dd92003-12-03 01:27:23 +0000142 # able to be encoded by *either* the default or filesystem encoding.
Tim Petersc6c5ece2003-12-04 05:39:43 +0000143 # This test really only makes sense on Windows NT platforms
Mark Hammond2e8624c2003-12-03 22:16:47 +0000144 # which have special Unicode support in posixmodule.
Tim Petersc6c5ece2003-12-04 05:39:43 +0000145 if (not hasattr(sys, "getwindowsversion") or
146 sys.getwindowsversion()[3] < 2): # 0=win32s or 1=9x/ME
Tim Peters58eb11c2004-01-18 20:29:55 +0000147 TESTFN_UNICODE_UNENCODEABLE = None
Mark Hammondb337dd92003-12-03 01:27:23 +0000148 else:
Mark Hammond2e8624c2003-12-03 22:16:47 +0000149 # Japanese characters (I think - from bug 846133)
Martin v. Löwise2713be2005-03-08 15:03:08 +0000150 TESTFN_UNICODE_UNENCODEABLE = eval('u"@test-\u5171\u6709\u3055\u308c\u308b"')
Mark Hammond2e8624c2003-12-03 22:16:47 +0000151 try:
152 # XXX - Note - should be using TESTFN_ENCODING here - but for
Tim Petersc6c5ece2003-12-04 05:39:43 +0000153 # Windows, "mbcs" currently always operates as if in
Mark Hammond2e8624c2003-12-03 22:16:47 +0000154 # errors=ignore' mode - hence we get '?' characters rather than
155 # the exception. 'Latin1' operates as we expect - ie, fails.
156 # See [ 850997 ] mbcs encoding ignores errors
157 TESTFN_UNICODE_UNENCODEABLE.encode("Latin1")
158 except UnicodeEncodeError:
159 pass
160 else:
161 print \
162 'WARNING: The filename %r CAN be encoded by the filesystem. ' \
163 'Unicode filename tests may not be effective' \
164 % TESTFN_UNICODE_UNENCODEABLE
Neal Norwitz26a1eef2002-11-03 00:35:53 +0000165
166# Make sure we can write to TESTFN, try in /tmp if we can't
167fp = None
168try:
169 fp = open(TESTFN, 'w+')
170except IOError:
171 TMP_TESTFN = os.path.join('/tmp', TESTFN)
172 try:
173 fp = open(TMP_TESTFN, 'w+')
174 TESTFN = TMP_TESTFN
175 del TMP_TESTFN
176 except IOError:
Tim Peters3de75262002-11-09 05:26:15 +0000177 print ('WARNING: tests will fail, unable to write to: %s or %s' %
Neal Norwitz26a1eef2002-11-03 00:35:53 +0000178 (TESTFN, TMP_TESTFN))
179if fp is not None:
180 fp.close()
Neal Norwitz0e17f8c2006-01-23 07:51:27 +0000181 unlink(TESTFN)
Neal Norwitz26a1eef2002-11-03 00:35:53 +0000182del os, fp
Guido van Rossuma8f7e592001-03-13 09:31:07 +0000183
Guido van Rossume26132c1998-04-23 20:13:30 +0000184def findfile(file, here=__file__):
Brett Cannonf1cfb622003-05-04 21:15:27 +0000185 """Try to find a file on sys.path and the working directory. If it is not
186 found the argument passed to the function is returned (this does not
187 necessarily signal failure; could still be the legitimate path)."""
Fred Drake004d5e62000-10-23 17:22:08 +0000188 import os
189 if os.path.isabs(file):
190 return file
Fred Drake004d5e62000-10-23 17:22:08 +0000191 path = sys.path
192 path = [os.path.dirname(here)] + path
193 for dn in path:
194 fn = os.path.join(dn, file)
195 if os.path.exists(fn): return fn
196 return file
Marc-André Lemburg36619082001-01-17 19:11:13 +0000197
198def verify(condition, reason='test failed'):
Guido van Rossuma1374e42001-01-19 19:01:56 +0000199 """Verify that condition is true. If not, raise TestFailed.
Marc-André Lemburg36619082001-01-17 19:11:13 +0000200
Skip Montanaroc955f892001-01-20 19:12:54 +0000201 The optional argument reason can be given to provide
Tim Peters983874d2001-01-19 05:59:21 +0000202 a better error text.
Tim Petersd2bf3b72001-01-18 02:22:22 +0000203 """
Tim Peters983874d2001-01-19 05:59:21 +0000204
Tim Petersd2bf3b72001-01-18 02:22:22 +0000205 if not condition:
Guido van Rossuma1374e42001-01-19 19:01:56 +0000206 raise TestFailed(reason)
Jeremy Hylton47793992001-02-19 15:35:26 +0000207
Tim Petersc2fe6182001-10-30 23:20:46 +0000208def vereq(a, b):
Tim Peters77902972001-12-29 17:34:57 +0000209 """Raise TestFailed if a == b is false.
210
211 This is better than verify(a == b) because, in case of failure, the
212 error message incorporates repr(a) and repr(b) so you can see the
213 inputs.
214
215 Note that "not (a == b)" isn't necessarily the same as "a != b"; the
216 former is tested.
217 """
218
Tim Petersc2fe6182001-10-30 23:20:46 +0000219 if not (a == b):
220 raise TestFailed, "%r == %r" % (a, b)
221
Tim Peters2f228e72001-05-13 00:19:31 +0000222def sortdict(dict):
223 "Like repr(dict), but in sorted order."
224 items = dict.items()
225 items.sort()
226 reprpairs = ["%r: %r" % pair for pair in items]
227 withcommas = ", ".join(reprpairs)
228 return "{%s}" % withcommas
229
Jeremy Hylton47793992001-02-19 15:35:26 +0000230def check_syntax(statement):
231 try:
232 compile(statement, '<string>', 'exec')
233 except SyntaxError:
234 pass
235 else:
236 print 'Missing SyntaxError: "%s"' % statement
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000237
Hye-Shik Changaaa2f1d2005-12-10 17:44:27 +0000238def open_urlresource(url):
239 import urllib, urlparse
240 import os.path
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000241
Hye-Shik Changaaa2f1d2005-12-10 17:44:27 +0000242 filename = urlparse.urlparse(url)[2].split('/')[-1] # '/': it's URL!
243
244 for path in [os.path.curdir, os.path.pardir]:
245 fn = os.path.join(path, filename)
246 if os.path.exists(fn):
247 return open(fn)
248
249 requires('urlfetch')
250 print >> get_original_stdout(), '\tfetching %s ...' % url
251 fn, _ = urllib.urlretrieve(url, filename)
252 return open(fn)
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000253
254#=======================================================================
Thomas Wouters477c8d52006-05-27 19:21:47 +0000255# Decorator for running a function in a different locale, correctly resetting
256# it afterwards.
257
258def run_with_locale(catstr, *locales):
259 def decorator(func):
260 def inner(*args, **kwds):
261 try:
262 import locale
263 category = getattr(locale, catstr)
264 orig_locale = locale.setlocale(category)
265 except AttributeError:
266 # if the test author gives us an invalid category string
267 raise
268 except:
269 # cannot retrieve original locale, so do nothing
270 locale = orig_locale = None
271 else:
272 for loc in locales:
273 try:
274 locale.setlocale(category, loc)
275 break
276 except:
277 pass
278
279 # now run the function, resetting the locale on exceptions
280 try:
281 return func(*args, **kwds)
282 finally:
283 if locale and orig_locale:
284 locale.setlocale(category, orig_locale)
285 inner.func_name = func.func_name
286 inner.__doc__ = func.__doc__
287 return inner
288 return decorator
289
290#=======================================================================
291# Big-memory-test support. Separate from 'resources' because memory use should be configurable.
292
293# Some handy shorthands. Note that these are used for byte-limits as well
294# as size-limits, in the various bigmem tests
295_1M = 1024*1024
296_1G = 1024 * _1M
297_2G = 2 * _1G
298
299def set_memlimit(limit):
300 import re
301 global max_memuse
302 sizes = {
303 'k': 1024,
304 'm': _1M,
305 'g': _1G,
306 't': 1024*_1G,
307 }
308 m = re.match(r'(\d+(\.\d+)?) (K|M|G|T)b?$', limit,
309 re.IGNORECASE | re.VERBOSE)
310 if m is None:
311 raise ValueError('Invalid memory limit %r' % (limit,))
312 memlimit = int(float(m.group(1)) * sizes[m.group(3).lower()])
313 if memlimit < 2.5*_1G:
314 raise ValueError('Memory limit %r too low to be useful' % (limit,))
315 max_memuse = memlimit
316
317def bigmemtest(minsize, memuse, overhead=5*_1M):
318 """Decorator for bigmem tests.
319
320 'minsize' is the minimum useful size for the test (in arbitrary,
321 test-interpreted units.) 'memuse' is the number of 'bytes per size' for
322 the test, or a good estimate of it. 'overhead' specifies fixed overhead,
323 independant of the testsize, and defaults to 5Mb.
324
325 The decorator tries to guess a good value for 'size' and passes it to
326 the decorated test function. If minsize * memuse is more than the
327 allowed memory use (as defined by max_memuse), the test is skipped.
328 Otherwise, minsize is adjusted upward to use up to max_memuse.
329 """
330 def decorator(f):
331 def wrapper(self):
332 if not max_memuse:
333 # If max_memuse is 0 (the default),
334 # we still want to run the tests with size set to a few kb,
335 # to make sure they work. We still want to avoid using
336 # too much memory, though, but we do that noisily.
337 maxsize = 5147
338 self.failIf(maxsize * memuse + overhead > 20 * _1M)
339 else:
340 maxsize = int((max_memuse - overhead) / memuse)
341 if maxsize < minsize:
342 # Really ought to print 'test skipped' or something
343 if verbose:
344 sys.stderr.write("Skipping %s because of memory "
345 "constraint\n" % (f.__name__,))
346 return
347 # Try to keep some breathing room in memory use
348 maxsize = max(maxsize - 50 * _1M, minsize)
349 return f(self, maxsize)
350 wrapper.minsize = minsize
351 wrapper.memuse = memuse
352 wrapper.overhead = overhead
353 return wrapper
354 return decorator
355
356#=======================================================================
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000357# Preliminary PyUNIT integration.
358
359import unittest
360
361
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000362class BasicTestRunner:
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000363 def run(self, test):
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000364 result = unittest.TestResult()
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000365 test(result)
366 return result
367
368
Fred Drake26641032001-10-04 19:46:07 +0000369def run_suite(suite, testclass=None):
Barry Warsawc88425e2001-09-20 06:31:22 +0000370 """Run tests from a unittest.TestSuite-derived class."""
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000371 if verbose:
Fred Drake84a59342001-03-23 04:21:17 +0000372 runner = unittest.TextTestRunner(sys.stdout, verbosity=2)
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000373 else:
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000374 runner = BasicTestRunner()
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000375
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000376 result = runner.run(suite)
377 if not result.wasSuccessful():
Fred Drake14f6c182001-07-16 18:51:32 +0000378 if len(result.errors) == 1 and not result.failures:
379 err = result.errors[0][1]
380 elif len(result.failures) == 1 and not result.errors:
381 err = result.failures[0][1]
382 else:
Fred Drake26641032001-10-04 19:46:07 +0000383 if testclass is None:
384 msg = "errors occurred; run in verbose mode for details"
385 else:
386 msg = "errors occurred in %s.%s" \
387 % (testclass.__module__, testclass.__name__)
388 raise TestFailed(msg)
Tim Peters2d84f2c2001-09-08 03:37:56 +0000389 raise TestFailed(err)
Tim Petersa0a62222001-09-09 06:12:01 +0000390
Barry Warsawc10d6902001-09-20 06:30:41 +0000391
Walter Dörwald21d3a322003-05-01 17:45:56 +0000392def run_unittest(*classes):
393 """Run tests from unittest.TestCase-derived classes."""
Raymond Hettinger9dcbbea2003-04-27 07:54:23 +0000394 suite = unittest.TestSuite()
Walter Dörwald21d3a322003-05-01 17:45:56 +0000395 for cls in classes:
Raymond Hettingerf3590622003-07-16 04:29:42 +0000396 if isinstance(cls, (unittest.TestSuite, unittest.TestCase)):
Raymond Hettinger21d99872003-07-16 02:59:32 +0000397 suite.addTest(cls)
398 else:
399 suite.addTest(unittest.makeSuite(cls))
Walter Dörwald21d3a322003-05-01 17:45:56 +0000400 if len(classes)==1:
401 testclass = classes[0]
402 else:
403 testclass = None
404 run_suite(suite, testclass)
Raymond Hettinger9dcbbea2003-04-27 07:54:23 +0000405
Barry Warsawc10d6902001-09-20 06:30:41 +0000406
Tim Petersa0a62222001-09-09 06:12:01 +0000407#=======================================================================
408# doctest driver.
409
410def run_doctest(module, verbosity=None):
Tim Peters17111f32001-10-03 04:08:26 +0000411 """Run doctest on the given module. Return (#failures, #tests).
Tim Petersa0a62222001-09-09 06:12:01 +0000412
413 If optional argument verbosity is not specified (or is None), pass
Tim Petersbea3fb82001-09-10 01:39:21 +0000414 test_support's belief about verbosity on to doctest. Else doctest's
415 usual behavior is used (it searches sys.argv for -v).
Tim Petersa0a62222001-09-09 06:12:01 +0000416 """
417
418 import doctest
419
420 if verbosity is None:
421 verbosity = verbose
422 else:
423 verbosity = None
424
Tim Peters342ca752001-09-25 19:13:20 +0000425 # Direct doctest output (normally just errors) to real stdout; doctest
426 # output shouldn't be compared by regrtest.
427 save_stdout = sys.stdout
Tim Peters8dee8092001-09-25 20:05:11 +0000428 sys.stdout = get_original_stdout()
Tim Peters342ca752001-09-25 19:13:20 +0000429 try:
430 f, t = doctest.testmod(module, verbose=verbosity)
431 if f:
432 raise TestFailed("%d of %d doctests failed" % (f, t))
433 finally:
434 sys.stdout = save_stdout
Raymond Hettinger35b34bd2003-05-17 00:58:33 +0000435 if verbose:
Raymond Hettinger1ba24b42003-05-17 01:59:57 +0000436 print 'doctest (%s) ... %d tests with zero failures' % (module.__name__, t)
Raymond Hettinger35b34bd2003-05-17 00:58:33 +0000437 return f, t