blob: 5b2176e009a429476339e5e101410994db638218 [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':
Guido van Rossumd8faa362007-04-27 19:54:29 +00004 raise ImportError('test_support must be imported from the test package')
Barry Warsaw408b6d32002-07-30 23:27:12 +00005
Guido van Rossumd8faa362007-04-27 19:54:29 +00006import contextlib
7import errno
8import socket
Fred Drakecd1b1dd2001-03-21 18:26:33 +00009import sys
Guido van Rossumd8faa362007-04-27 19:54:29 +000010import os
11import os.path
Thomas Wouters902d6eb2007-01-09 23:18:33 +000012import warnings
Guido van Rossumd8faa362007-04-27 19:54:29 +000013import types
14import unittest
Fred Drakecd1b1dd2001-03-21 18:26:33 +000015
Fred Drake1790dd42000-07-24 06:55:00 +000016class Error(Exception):
Fred Drake004d5e62000-10-23 17:22:08 +000017 """Base class for regression test exceptions."""
Fred Drake1790dd42000-07-24 06:55:00 +000018
19class TestFailed(Error):
Fred Drake004d5e62000-10-23 17:22:08 +000020 """Test failed."""
Fred Drake1790dd42000-07-24 06:55:00 +000021
22class TestSkipped(Error):
Fred Drake004d5e62000-10-23 17:22:08 +000023 """Test skipped.
Fred Drake1790dd42000-07-24 06:55:00 +000024
Fred Drake004d5e62000-10-23 17:22:08 +000025 This can be raised to indicate that a test was deliberatly
26 skipped, but not because a feature wasn't available. For
27 example, if some resource can't be used, such as the network
28 appears to be unavailable, this should be raised instead of
29 TestFailed.
Fred Drake004d5e62000-10-23 17:22:08 +000030 """
Fred Drake1790dd42000-07-24 06:55:00 +000031
Fred Drake9a0db072003-02-03 15:19:30 +000032class ResourceDenied(TestSkipped):
33 """Test skipped because it requested a disallowed resource.
34
35 This is raised when a test calls requires() for a resource that
36 has not be enabled. It is used to distinguish between expected
37 and unexpected skips.
38 """
39
Barry Warsawc0fb6052001-08-20 22:29:23 +000040verbose = 1 # Flag set to 0 by regrtest.py
Thomas Wouters477c8d52006-05-27 19:21:47 +000041use_resources = None # Flag set to [] by regrtest.py
42max_memuse = 0 # Disable bigmem tests (they will still be run with
43 # small sizes, to make sure they work.)
Guido van Rossum531661c1996-12-20 02:58:22 +000044
Tim Peters8dee8092001-09-25 20:05:11 +000045# _original_stdout is meant to hold stdout at the time regrtest began.
46# This may be "the real" stdout, or IDLE's emulation of stdout, or whatever.
47# The point is to have some flavor of stdout the user can actually see.
48_original_stdout = None
49def record_original_stdout(stdout):
50 global _original_stdout
51 _original_stdout = stdout
52
53def get_original_stdout():
54 return _original_stdout or sys.stdout
55
Guido van Rossum3bead091992-01-27 17:00:37 +000056def unload(name):
Fred Drake004d5e62000-10-23 17:22:08 +000057 try:
58 del sys.modules[name]
59 except KeyError:
60 pass
Guido van Rossum3bead091992-01-27 17:00:37 +000061
Neal Norwitz0e17f8c2006-01-23 07:51:27 +000062def unlink(filename):
Neal Norwitz0e17f8c2006-01-23 07:51:27 +000063 try:
64 os.unlink(filename)
65 except OSError:
66 pass
67
Guido van Rossum3bead091992-01-27 17:00:37 +000068def forget(modname):
Brett Cannonf1cfb622003-05-04 21:15:27 +000069 '''"Forget" a module was ever imported by removing it from sys.modules and
70 deleting any .pyc and .pyo files.'''
Fred Drake004d5e62000-10-23 17:22:08 +000071 unload(modname)
Fred Drake004d5e62000-10-23 17:22:08 +000072 for dirname in sys.path:
Skip Montanaro7a98be22007-08-16 14:35:24 +000073 unlink(os.path.join(dirname, modname + '.pyc'))
Brett Cannonf1cfb622003-05-04 21:15:27 +000074 # Deleting the .pyo file cannot be within the 'try' for the .pyc since
75 # the chance exists that there is no .pyc (and thus the 'try' statement
76 # is exited) but there is a .pyo file.
Skip Montanaro7a98be22007-08-16 14:35:24 +000077 unlink(os.path.join(dirname, modname + '.pyo'))
Guido van Rossum3bead091992-01-27 17:00:37 +000078
Tim Petersb4ee4eb2002-12-04 03:26:57 +000079def is_resource_enabled(resource):
Brett Cannonf1cfb622003-05-04 21:15:27 +000080 """Test whether a resource is enabled. Known resources are set by
81 regrtest.py."""
Tim Petersb4ee4eb2002-12-04 03:26:57 +000082 return use_resources is not None and resource in use_resources
83
Barry Warsawc0fb6052001-08-20 22:29:23 +000084def requires(resource, msg=None):
Brett Cannonf1cfb622003-05-04 21:15:27 +000085 """Raise ResourceDenied if the specified resource is not available.
86
87 If the caller's module is __main__ then automatically return True. The
88 possibility of False being returned occurs when regrtest.py is executing."""
Skip Montanarod839ecd2003-04-24 19:06:57 +000089 # see if the caller's module is __main__ - if so, treat as if
90 # the resource was set
91 if sys._getframe().f_back.f_globals.get("__name__") == "__main__":
92 return
Tim Petersb4ee4eb2002-12-04 03:26:57 +000093 if not is_resource_enabled(resource):
Barry Warsawc0fb6052001-08-20 22:29:23 +000094 if msg is None:
95 msg = "Use of the `%s' resource not enabled" % resource
Fred Drake9a0db072003-02-03 15:19:30 +000096 raise ResourceDenied(msg)
Barry Warsawc0fb6052001-08-20 22:29:23 +000097
Thomas Wouters0e3f5912006-08-11 14:57:12 +000098def bind_port(sock, host='', preferred_port=54321):
99 """Try to bind the sock to a port. If we are running multiple
100 tests and we don't try multiple ports, the test can fails. This
101 makes the test more robust."""
102
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000103 # some random ports that hopefully no one is listening on.
104 for port in [preferred_port, 9907, 10243, 32999]:
105 try:
106 sock.bind((host, port))
107 return port
Guido van Rossumb940e112007-01-10 16:19:56 +0000108 except socket.error as e:
Guido van Rossume2c8f2d2007-05-09 23:43:17 +0000109 (err, msg) = e.args
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000110 if err != errno.EADDRINUSE:
111 raise
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000112 print(' WARNING: failed to listen on port %d, trying another' % port, file=sys.__stderr__)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000113 raise TestFailed('unable to find port to listen on')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000114
Guido van Rossum35fb82a1993-01-26 13:04:43 +0000115FUZZ = 1e-6
116
117def fcmp(x, y): # fuzzy comparison function
Neal Norwitz79212992006-08-21 16:27:31 +0000118 if isinstance(x, float) or isinstance(y, float):
Fred Drake004d5e62000-10-23 17:22:08 +0000119 try:
Fred Drake004d5e62000-10-23 17:22:08 +0000120 fuzz = (abs(x) + abs(y)) * FUZZ
121 if abs(x-y) <= fuzz:
122 return 0
123 except:
124 pass
Neal Norwitz79212992006-08-21 16:27:31 +0000125 elif type(x) == type(y) and isinstance(x, (tuple, list)):
Fred Drake004d5e62000-10-23 17:22:08 +0000126 for i in range(min(len(x), len(y))):
127 outcome = fcmp(x[i], y[i])
Fred Drake132dce22000-12-12 23:11:42 +0000128 if outcome != 0:
Fred Drake004d5e62000-10-23 17:22:08 +0000129 return outcome
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000130 return (len(x) > len(y)) - (len(x) < len(y))
131 return (x > y) - (x < y)
Guido van Rossum35fb82a1993-01-26 13:04:43 +0000132
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000133try:
Guido van Rossumef87d6e2007-05-02 19:09:54 +0000134 str
Neal Norwitz79212992006-08-21 16:27:31 +0000135 have_unicode = True
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000136except NameError:
Neal Norwitz79212992006-08-21 16:27:31 +0000137 have_unicode = False
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000138
Finn Bock57bc5fa2002-11-01 18:02:03 +0000139is_jython = sys.platform.startswith('java')
140
Barry Warsaw559f6682001-03-23 18:04:02 +0000141# Filename used for testing
142if os.name == 'java':
143 # Jython disallows @ in module names
144 TESTFN = '$test'
Martin v. Löwisa94568a2003-05-10 07:36:56 +0000145else:
Barry Warsaw559f6682001-03-23 18:04:02 +0000146 TESTFN = '@test'
Walter Dörwald9b775532007-06-08 14:30:53 +0000147
148 # Assuming sys.getfilesystemencoding()!=sys.getdefaultencoding()
149 # TESTFN_UNICODE is a filename that can be encoded using the
150 # file system encoding, but *not* with the default (ascii) encoding
151 TESTFN_UNICODE = "@test-\xe0\xf2"
152 TESTFN_ENCODING = sys.getfilesystemencoding()
153 # TESTFN_UNICODE_UNENCODEABLE is a filename that should *not* be
154 # able to be encoded by *either* the default or filesystem encoding.
155 # This test really only makes sense on Windows NT platforms
156 # which have special Unicode support in posixmodule.
157 if (not hasattr(sys, "getwindowsversion") or
158 sys.getwindowsversion()[3] < 2): # 0=win32s or 1=9x/ME
159 TESTFN_UNICODE_UNENCODEABLE = None
160 else:
161 # Japanese characters (I think - from bug 846133)
162 TESTFN_UNICODE_UNENCODEABLE = "@test-\u5171\u6709\u3055\u308c\u308b"
163 try:
164 # XXX - Note - should be using TESTFN_ENCODING here - but for
165 # Windows, "mbcs" currently always operates as if in
166 # errors=ignore' mode - hence we get '?' characters rather than
167 # the exception. 'Latin1' operates as we expect - ie, fails.
168 # See [ 850997 ] mbcs encoding ignores errors
169 TESTFN_UNICODE_UNENCODEABLE.encode("Latin1")
170 except UnicodeEncodeError:
171 pass
Martin v. Löwis2411a2d2002-11-09 19:57:26 +0000172 else:
Walter Dörwald9b775532007-06-08 14:30:53 +0000173 print('WARNING: The filename %r CAN be encoded by the filesystem. ' \
174 'Unicode filename tests may not be effective' \
175 % TESTFN_UNICODE_UNENCODEABLE)
Neal Norwitz26a1eef2002-11-03 00:35:53 +0000176
177# Make sure we can write to TESTFN, try in /tmp if we can't
178fp = None
179try:
180 fp = open(TESTFN, 'w+')
181except IOError:
182 TMP_TESTFN = os.path.join('/tmp', TESTFN)
183 try:
184 fp = open(TMP_TESTFN, 'w+')
185 TESTFN = TMP_TESTFN
186 del TMP_TESTFN
187 except IOError:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000188 print(('WARNING: tests will fail, unable to write to: %s or %s' %
189 (TESTFN, TMP_TESTFN)))
Neal Norwitz26a1eef2002-11-03 00:35:53 +0000190if fp is not None:
191 fp.close()
Neal Norwitz0e17f8c2006-01-23 07:51:27 +0000192 unlink(TESTFN)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000193del fp
Guido van Rossuma8f7e592001-03-13 09:31:07 +0000194
Guido van Rossume26132c1998-04-23 20:13:30 +0000195def findfile(file, here=__file__):
Brett Cannonf1cfb622003-05-04 21:15:27 +0000196 """Try to find a file on sys.path and the working directory. If it is not
197 found the argument passed to the function is returned (this does not
198 necessarily signal failure; could still be the legitimate path)."""
Fred Drake004d5e62000-10-23 17:22:08 +0000199 if os.path.isabs(file):
200 return file
Fred Drake004d5e62000-10-23 17:22:08 +0000201 path = sys.path
202 path = [os.path.dirname(here)] + path
203 for dn in path:
204 fn = os.path.join(dn, file)
205 if os.path.exists(fn): return fn
206 return file
Marc-André Lemburg36619082001-01-17 19:11:13 +0000207
208def verify(condition, reason='test failed'):
Guido van Rossuma1374e42001-01-19 19:01:56 +0000209 """Verify that condition is true. If not, raise TestFailed.
Marc-André Lemburg36619082001-01-17 19:11:13 +0000210
Skip Montanaroc955f892001-01-20 19:12:54 +0000211 The optional argument reason can be given to provide
Tim Peters983874d2001-01-19 05:59:21 +0000212 a better error text.
Tim Petersd2bf3b72001-01-18 02:22:22 +0000213 """
Tim Peters983874d2001-01-19 05:59:21 +0000214
Tim Petersd2bf3b72001-01-18 02:22:22 +0000215 if not condition:
Guido van Rossuma1374e42001-01-19 19:01:56 +0000216 raise TestFailed(reason)
Jeremy Hylton47793992001-02-19 15:35:26 +0000217
Tim Petersc2fe6182001-10-30 23:20:46 +0000218def vereq(a, b):
Tim Peters77902972001-12-29 17:34:57 +0000219 """Raise TestFailed if a == b is false.
220
221 This is better than verify(a == b) because, in case of failure, the
222 error message incorporates repr(a) and repr(b) so you can see the
223 inputs.
224
225 Note that "not (a == b)" isn't necessarily the same as "a != b"; the
226 former is tested.
227 """
228
Tim Petersc2fe6182001-10-30 23:20:46 +0000229 if not (a == b):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000230 raise TestFailed("%r == %r" % (a, b))
Tim Petersc2fe6182001-10-30 23:20:46 +0000231
Tim Peters2f228e72001-05-13 00:19:31 +0000232def sortdict(dict):
233 "Like repr(dict), but in sorted order."
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000234 items = sorted(dict.items())
Tim Peters2f228e72001-05-13 00:19:31 +0000235 reprpairs = ["%r: %r" % pair for pair in items]
236 withcommas = ", ".join(reprpairs)
237 return "{%s}" % withcommas
238
Thomas Wouters89f507f2006-12-13 04:49:30 +0000239def check_syntax_error(testcase, statement):
Jeremy Hylton47793992001-02-19 15:35:26 +0000240 try:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000241 compile(statement, '<test string>', 'exec')
Jeremy Hylton47793992001-02-19 15:35:26 +0000242 except SyntaxError:
243 pass
244 else:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000245 testcase.fail('Missing SyntaxError: "%s"' % statement)
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000246
Martin v. Löwis234a34a2007-08-30 20:58:02 +0000247def open_urlresource(url, *args, **kw):
Hye-Shik Changaaa2f1d2005-12-10 17:44:27 +0000248 import urllib, urlparse
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000249
Guido van Rossum360e4b82007-05-14 22:51:27 +0000250 requires('urlfetch')
Hye-Shik Changaaa2f1d2005-12-10 17:44:27 +0000251 filename = urlparse.urlparse(url)[2].split('/')[-1] # '/': it's URL!
252
253 for path in [os.path.curdir, os.path.pardir]:
254 fn = os.path.join(path, filename)
255 if os.path.exists(fn):
Martin v. Löwis234a34a2007-08-30 20:58:02 +0000256 return open(fn, *args, **kw)
Hye-Shik Changaaa2f1d2005-12-10 17:44:27 +0000257
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000258 print('\tfetching %s ...' % url, file=get_original_stdout())
Hye-Shik Changaaa2f1d2005-12-10 17:44:27 +0000259 fn, _ = urllib.urlretrieve(url, filename)
Martin v. Löwis234a34a2007-08-30 20:58:02 +0000260 return open(fn, *args, **kw)
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000261
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000262
Guido van Rossumd8faa362007-04-27 19:54:29 +0000263class WarningMessage(object):
264 "Holds the result of the latest showwarning() call"
265 def __init__(self):
266 self.message = None
267 self.category = None
268 self.filename = None
269 self.lineno = None
270
271 def _showwarning(self, message, category, filename, lineno, file=None):
272 self.message = message
273 self.category = category
274 self.filename = filename
275 self.lineno = lineno
276
277@contextlib.contextmanager
278def catch_warning():
279 """
280 Guard the warnings filter from being permanently changed and record the
281 data of the last warning that has been issued.
282
283 Use like this:
284
Guido van Rossumaf554a02007-08-16 23:48:43 +0000285 with catch_warning() as w:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000286 warnings.warn("foo")
287 assert str(w.message) == "foo"
288 """
289 warning = WarningMessage()
290 original_filters = warnings.filters[:]
291 original_showwarning = warnings.showwarning
292 warnings.showwarning = warning._showwarning
293 try:
294 yield warning
295 finally:
296 warnings.showwarning = original_showwarning
297 warnings.filters = original_filters
298
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000299class EnvironmentVarGuard(object):
300
301 """Class to help protect the environment variable properly. Can be used as
302 a context manager."""
303
304 def __init__(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000305 self._environ = os.environ
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000306 self._unset = set()
307 self._reset = dict()
308
309 def set(self, envvar, value):
310 if envvar not in self._environ:
311 self._unset.add(envvar)
312 else:
313 self._reset[envvar] = self._environ[envvar]
314 self._environ[envvar] = value
315
316 def unset(self, envvar):
317 if envvar in self._environ:
318 self._reset[envvar] = self._environ[envvar]
319 del self._environ[envvar]
320
321 def __enter__(self):
322 return self
323
324 def __exit__(self, *ignore_exc):
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000325 for envvar, value in self._reset.items():
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000326 self._environ[envvar] = value
327 for unset in self._unset:
328 del self._environ[unset]
329
Guido van Rossumd8faa362007-04-27 19:54:29 +0000330class TransientResource(object):
331
332 """Raise ResourceDenied if an exception is raised while the context manager
333 is in effect that matches the specified exception and attributes."""
334
335 def __init__(self, exc, **kwargs):
336 self.exc = exc
337 self.attrs = kwargs
338
339 def __enter__(self):
340 return self
341
342 def __exit__(self, type_=None, value=None, traceback=None):
343 """If type_ is a subclass of self.exc and value has attributes matching
344 self.attrs, raise ResourceDenied. Otherwise let the exception
345 propagate (if any)."""
346 if type_ is not None and issubclass(self.exc, type_):
347 for attr, attr_value in self.attrs.items():
348 if not hasattr(value, attr):
349 break
350 if getattr(value, attr) != attr_value:
351 break
352 else:
353 raise ResourceDenied("an optional resource is not available")
354
355
356def transient_internet():
357 """Return a context manager that raises ResourceDenied when various issues
358 with the Internet connection manifest themselves as exceptions."""
359 time_out = TransientResource(IOError, errno=errno.ETIMEDOUT)
360 socket_peer_reset = TransientResource(socket.error, errno=errno.ECONNRESET)
361 ioerror_peer_reset = TransientResource(IOError, errno=errno.ECONNRESET)
362 return contextlib.nested(time_out, socket_peer_reset, ioerror_peer_reset)
363
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000364
Thomas Woutersed03b412007-08-28 21:37:11 +0000365@contextlib.contextmanager
366def captured_stdout():
367 """Run the with statement body using a StringIO object as sys.stdout.
368 Example use::
369
370 with captured_stdout() as s:
371 print "hello"
372 assert s.getvalue() == "hello"
373 """
374 import io
375 orig_stdout = sys.stdout
376 sys.stdout = io.StringIO()
377 yield sys.stdout
378 sys.stdout = orig_stdout
379
380
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000381#=======================================================================
Thomas Wouters477c8d52006-05-27 19:21:47 +0000382# Decorator for running a function in a different locale, correctly resetting
383# it afterwards.
384
385def run_with_locale(catstr, *locales):
386 def decorator(func):
387 def inner(*args, **kwds):
388 try:
389 import locale
390 category = getattr(locale, catstr)
391 orig_locale = locale.setlocale(category)
392 except AttributeError:
393 # if the test author gives us an invalid category string
394 raise
395 except:
396 # cannot retrieve original locale, so do nothing
397 locale = orig_locale = None
398 else:
399 for loc in locales:
400 try:
401 locale.setlocale(category, loc)
402 break
403 except:
404 pass
405
406 # now run the function, resetting the locale on exceptions
407 try:
408 return func(*args, **kwds)
409 finally:
410 if locale and orig_locale:
411 locale.setlocale(category, orig_locale)
Neal Norwitz221085d2007-02-25 20:55:47 +0000412 inner.__name__ = func.__name__
Thomas Wouters477c8d52006-05-27 19:21:47 +0000413 inner.__doc__ = func.__doc__
414 return inner
415 return decorator
416
417#=======================================================================
418# Big-memory-test support. Separate from 'resources' because memory use should be configurable.
419
420# Some handy shorthands. Note that these are used for byte-limits as well
421# as size-limits, in the various bigmem tests
422_1M = 1024*1024
423_1G = 1024 * _1M
424_2G = 2 * _1G
425
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000426MAX_Py_ssize_t = sys.maxsize
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000427
Thomas Wouters477c8d52006-05-27 19:21:47 +0000428def set_memlimit(limit):
429 import re
430 global max_memuse
431 sizes = {
432 'k': 1024,
433 'm': _1M,
434 'g': _1G,
435 't': 1024*_1G,
436 }
437 m = re.match(r'(\d+(\.\d+)?) (K|M|G|T)b?$', limit,
438 re.IGNORECASE | re.VERBOSE)
439 if m is None:
440 raise ValueError('Invalid memory limit %r' % (limit,))
441 memlimit = int(float(m.group(1)) * sizes[m.group(3).lower()])
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000442 if memlimit > MAX_Py_ssize_t:
443 memlimit = MAX_Py_ssize_t
444 if memlimit < _2G - 1:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000445 raise ValueError('Memory limit %r too low to be useful' % (limit,))
446 max_memuse = memlimit
447
448def bigmemtest(minsize, memuse, overhead=5*_1M):
449 """Decorator for bigmem tests.
450
451 'minsize' is the minimum useful size for the test (in arbitrary,
452 test-interpreted units.) 'memuse' is the number of 'bytes per size' for
453 the test, or a good estimate of it. 'overhead' specifies fixed overhead,
454 independant of the testsize, and defaults to 5Mb.
455
456 The decorator tries to guess a good value for 'size' and passes it to
457 the decorated test function. If minsize * memuse is more than the
458 allowed memory use (as defined by max_memuse), the test is skipped.
459 Otherwise, minsize is adjusted upward to use up to max_memuse.
460 """
461 def decorator(f):
462 def wrapper(self):
463 if not max_memuse:
464 # If max_memuse is 0 (the default),
465 # we still want to run the tests with size set to a few kb,
466 # to make sure they work. We still want to avoid using
467 # too much memory, though, but we do that noisily.
468 maxsize = 5147
469 self.failIf(maxsize * memuse + overhead > 20 * _1M)
470 else:
471 maxsize = int((max_memuse - overhead) / memuse)
472 if maxsize < minsize:
473 # Really ought to print 'test skipped' or something
474 if verbose:
475 sys.stderr.write("Skipping %s because of memory "
476 "constraint\n" % (f.__name__,))
477 return
478 # Try to keep some breathing room in memory use
479 maxsize = max(maxsize - 50 * _1M, minsize)
480 return f(self, maxsize)
481 wrapper.minsize = minsize
482 wrapper.memuse = memuse
483 wrapper.overhead = overhead
484 return wrapper
485 return decorator
486
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000487def bigaddrspacetest(f):
488 """Decorator for tests that fill the address space."""
489 def wrapper(self):
490 if max_memuse < MAX_Py_ssize_t:
491 if verbose:
492 sys.stderr.write("Skipping %s because of memory "
493 "constraint\n" % (f.__name__,))
494 else:
495 return f(self)
496 return wrapper
497
Thomas Wouters477c8d52006-05-27 19:21:47 +0000498#=======================================================================
Guido van Rossumd8faa362007-04-27 19:54:29 +0000499# unittest integration.
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000500
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000501class BasicTestRunner:
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000502 def run(self, test):
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000503 result = unittest.TestResult()
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000504 test(result)
505 return result
506
507
Guido van Rossumd8faa362007-04-27 19:54:29 +0000508def _run_suite(suite):
Barry Warsawc88425e2001-09-20 06:31:22 +0000509 """Run tests from a unittest.TestSuite-derived class."""
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000510 if verbose:
Fred Drake84a59342001-03-23 04:21:17 +0000511 runner = unittest.TextTestRunner(sys.stdout, verbosity=2)
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000512 else:
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000513 runner = BasicTestRunner()
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000514
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000515 result = runner.run(suite)
516 if not result.wasSuccessful():
Fred Drake14f6c182001-07-16 18:51:32 +0000517 if len(result.errors) == 1 and not result.failures:
518 err = result.errors[0][1]
519 elif len(result.failures) == 1 and not result.errors:
520 err = result.failures[0][1]
521 else:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000522 msg = "errors occurred; run in verbose mode for details"
Fred Drake26641032001-10-04 19:46:07 +0000523 raise TestFailed(msg)
Tim Peters2d84f2c2001-09-08 03:37:56 +0000524 raise TestFailed(err)
Tim Petersa0a62222001-09-09 06:12:01 +0000525
Barry Warsawc10d6902001-09-20 06:30:41 +0000526
Walter Dörwald21d3a322003-05-01 17:45:56 +0000527def run_unittest(*classes):
528 """Run tests from unittest.TestCase-derived classes."""
Guido van Rossumd8faa362007-04-27 19:54:29 +0000529 valid_types = (unittest.TestSuite, unittest.TestCase)
Raymond Hettinger9dcbbea2003-04-27 07:54:23 +0000530 suite = unittest.TestSuite()
Walter Dörwald21d3a322003-05-01 17:45:56 +0000531 for cls in classes:
Walter Dörwaldbf58bd62007-05-04 07:18:10 +0000532 if isinstance(cls, basestring):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000533 if cls in sys.modules:
534 suite.addTest(unittest.findTestCases(sys.modules[cls]))
535 else:
536 raise ValueError("str arguments must be keys in sys.modules")
537 elif isinstance(cls, valid_types):
Raymond Hettinger21d99872003-07-16 02:59:32 +0000538 suite.addTest(cls)
539 else:
540 suite.addTest(unittest.makeSuite(cls))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000541 _run_suite(suite)
Raymond Hettinger9dcbbea2003-04-27 07:54:23 +0000542
Barry Warsawc10d6902001-09-20 06:30:41 +0000543
Tim Petersa0a62222001-09-09 06:12:01 +0000544#=======================================================================
545# doctest driver.
546
547def run_doctest(module, verbosity=None):
Tim Peters17111f32001-10-03 04:08:26 +0000548 """Run doctest on the given module. Return (#failures, #tests).
Tim Petersa0a62222001-09-09 06:12:01 +0000549
550 If optional argument verbosity is not specified (or is None), pass
Tim Petersbea3fb82001-09-10 01:39:21 +0000551 test_support's belief about verbosity on to doctest. Else doctest's
552 usual behavior is used (it searches sys.argv for -v).
Tim Petersa0a62222001-09-09 06:12:01 +0000553 """
554
555 import doctest
556
557 if verbosity is None:
558 verbosity = verbose
559 else:
560 verbosity = None
561
Tim Peters342ca752001-09-25 19:13:20 +0000562 # Direct doctest output (normally just errors) to real stdout; doctest
563 # output shouldn't be compared by regrtest.
564 save_stdout = sys.stdout
Tim Peters8dee8092001-09-25 20:05:11 +0000565 sys.stdout = get_original_stdout()
Tim Peters342ca752001-09-25 19:13:20 +0000566 try:
567 f, t = doctest.testmod(module, verbose=verbosity)
568 if f:
569 raise TestFailed("%d of %d doctests failed" % (f, t))
570 finally:
571 sys.stdout = save_stdout
Raymond Hettinger35b34bd2003-05-17 00:58:33 +0000572 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000573 print('doctest (%s) ... %d tests with zero failures' % (module.__name__, t))
Raymond Hettinger35b34bd2003-05-17 00:58:33 +0000574 return f, t
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000575
576#=======================================================================
577# Threading support to prevent reporting refleaks when running regrtest.py -R
578
579def threading_setup():
580 import threading
581 return len(threading._active), len(threading._limbo)
582
583def threading_cleanup(num_active, num_limbo):
584 import threading
585 import time
586
587 _MAX_COUNT = 10
588 count = 0
589 while len(threading._active) != num_active and count < _MAX_COUNT:
590 count += 1
591 time.sleep(0.1)
592
593 count = 0
594 while len(threading._limbo) != num_limbo and count < _MAX_COUNT:
595 count += 1
596 time.sleep(0.1)
597
598def reap_children():
599 """Use this function at the end of test_main() whenever sub-processes
600 are started. This will help ensure that no extra children (zombies)
601 stick around to hog resources and create problems when looking
602 for refleaks.
603 """
604
605 # Reap all our dead child processes so we don't leave zombies around.
606 # These hog resources and might be causing some of the buildbots to die.
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000607 if hasattr(os, 'waitpid'):
608 any_process = -1
609 while True:
610 try:
611 # This will raise an exception on Windows. That's ok.
612 pid, status = os.waitpid(any_process, os.WNOHANG)
613 if pid == 0:
614 break
615 except:
616 break