blob: cc71366a8b4860ea9fc7883278fd52eb0a2e19e6 [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
Guido van Rossumfe3f6962001-09-06 16:09:41 +000033use_resources = None # Flag set to [] by regrtest.py
Guido van Rossum531661c1996-12-20 02:58:22 +000034
Tim Peters8dee8092001-09-25 20:05:11 +000035# _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
39def record_original_stdout(stdout):
40 global _original_stdout
41 _original_stdout = stdout
42
43def get_original_stdout():
44 return _original_stdout or sys.stdout
45
Guido van Rossum3bead091992-01-27 17:00:37 +000046def unload(name):
Fred Drake004d5e62000-10-23 17:22:08 +000047 try:
48 del sys.modules[name]
49 except KeyError:
50 pass
Guido van Rossum3bead091992-01-27 17:00:37 +000051
Neal Norwitz0e17f8c2006-01-23 07:51:27 +000052def unlink(filename):
53 import os
54 try:
55 os.unlink(filename)
56 except OSError:
57 pass
58
Guido van Rossum3bead091992-01-27 17:00:37 +000059def forget(modname):
Brett Cannonf1cfb622003-05-04 21:15:27 +000060 '''"Forget" a module was ever imported by removing it from sys.modules and
61 deleting any .pyc and .pyo files.'''
Fred Drake004d5e62000-10-23 17:22:08 +000062 unload(modname)
Fred Drakecd1b1dd2001-03-21 18:26:33 +000063 import os
Fred Drake004d5e62000-10-23 17:22:08 +000064 for dirname in sys.path:
Neal Norwitz0e17f8c2006-01-23 07:51:27 +000065 unlink(os.path.join(dirname, modname + os.extsep + 'pyc'))
Brett Cannonf1cfb622003-05-04 21:15:27 +000066 # Deleting the .pyo file cannot be within the 'try' for the .pyc since
67 # the chance exists that there is no .pyc (and thus the 'try' statement
68 # is exited) but there is a .pyo file.
Neal Norwitz0e17f8c2006-01-23 07:51:27 +000069 unlink(os.path.join(dirname, modname + os.extsep + 'pyo'))
Guido van Rossum3bead091992-01-27 17:00:37 +000070
Tim Petersb4ee4eb2002-12-04 03:26:57 +000071def is_resource_enabled(resource):
Brett Cannonf1cfb622003-05-04 21:15:27 +000072 """Test whether a resource is enabled. Known resources are set by
73 regrtest.py."""
Tim Petersb4ee4eb2002-12-04 03:26:57 +000074 return use_resources is not None and resource in use_resources
75
Barry Warsawc0fb6052001-08-20 22:29:23 +000076def requires(resource, msg=None):
Brett Cannonf1cfb622003-05-04 21:15:27 +000077 """Raise ResourceDenied if the specified resource is not available.
78
79 If the caller's module is __main__ then automatically return True. The
80 possibility of False being returned occurs when regrtest.py is executing."""
Skip Montanarod839ecd2003-04-24 19:06:57 +000081 # see if the caller's module is __main__ - if so, treat as if
82 # the resource was set
83 if sys._getframe().f_back.f_globals.get("__name__") == "__main__":
84 return
Tim Petersb4ee4eb2002-12-04 03:26:57 +000085 if not is_resource_enabled(resource):
Barry Warsawc0fb6052001-08-20 22:29:23 +000086 if msg is None:
87 msg = "Use of the `%s' resource not enabled" % resource
Fred Drake9a0db072003-02-03 15:19:30 +000088 raise ResourceDenied(msg)
Barry Warsawc0fb6052001-08-20 22:29:23 +000089
Guido van Rossum35fb82a1993-01-26 13:04:43 +000090FUZZ = 1e-6
91
92def fcmp(x, y): # fuzzy comparison function
Fred Drake004d5e62000-10-23 17:22:08 +000093 if type(x) == type(0.0) or type(y) == type(0.0):
94 try:
95 x, y = coerce(x, y)
96 fuzz = (abs(x) + abs(y)) * FUZZ
97 if abs(x-y) <= fuzz:
98 return 0
99 except:
100 pass
101 elif type(x) == type(y) and type(x) in (type(()), type([])):
102 for i in range(min(len(x), len(y))):
103 outcome = fcmp(x[i], y[i])
Fred Drake132dce22000-12-12 23:11:42 +0000104 if outcome != 0:
Fred Drake004d5e62000-10-23 17:22:08 +0000105 return outcome
106 return cmp(len(x), len(y))
107 return cmp(x, y)
Guido van Rossum35fb82a1993-01-26 13:04:43 +0000108
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000109try:
110 unicode
111 have_unicode = 1
112except NameError:
113 have_unicode = 0
114
Finn Bock57bc5fa2002-11-01 18:02:03 +0000115is_jython = sys.platform.startswith('java')
116
Guido van Rossuma8f7e592001-03-13 09:31:07 +0000117import os
Barry Warsaw559f6682001-03-23 18:04:02 +0000118# Filename used for testing
119if os.name == 'java':
120 # Jython disallows @ in module names
121 TESTFN = '$test'
Martin v. Löwisa94568a2003-05-10 07:36:56 +0000122elif os.name == 'riscos':
123 TESTFN = 'testfile'
124else:
Barry Warsaw559f6682001-03-23 18:04:02 +0000125 TESTFN = '@test'
Mark Hammondef8b6542001-05-13 08:04:26 +0000126 # Unicode name only used if TEST_FN_ENCODING exists for the platform.
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000127 if have_unicode:
Mark Hammondb337dd92003-12-03 01:27:23 +0000128 # Assuming sys.getfilesystemencoding()!=sys.getdefaultencoding()
129 # TESTFN_UNICODE is a filename that can be encoded using the
130 # file system encoding, but *not* with the default (ascii) encoding
Martin v. Löwis2411a2d2002-11-09 19:57:26 +0000131 if isinstance('', unicode):
132 # python -U
133 # XXX perhaps unicode() should accept Unicode strings?
Tim Petersc6c5ece2003-12-04 05:39:43 +0000134 TESTFN_UNICODE = "@test-\xe0\xf2"
Martin v. Löwis2411a2d2002-11-09 19:57:26 +0000135 else:
Tim Petersc6c5ece2003-12-04 05:39:43 +0000136 # 2 latin characters.
137 TESTFN_UNICODE = unicode("@test-\xe0\xf2", "latin-1")
138 TESTFN_ENCODING = sys.getfilesystemencoding()
139 # TESTFN_UNICODE_UNENCODEABLE is a filename that should *not* be
Mark Hammondb337dd92003-12-03 01:27:23 +0000140 # able to be encoded by *either* the default or filesystem encoding.
Tim Petersc6c5ece2003-12-04 05:39:43 +0000141 # This test really only makes sense on Windows NT platforms
Mark Hammond2e8624c2003-12-03 22:16:47 +0000142 # which have special Unicode support in posixmodule.
Tim Petersc6c5ece2003-12-04 05:39:43 +0000143 if (not hasattr(sys, "getwindowsversion") or
144 sys.getwindowsversion()[3] < 2): # 0=win32s or 1=9x/ME
Tim Peters58eb11c2004-01-18 20:29:55 +0000145 TESTFN_UNICODE_UNENCODEABLE = None
Mark Hammondb337dd92003-12-03 01:27:23 +0000146 else:
Mark Hammond2e8624c2003-12-03 22:16:47 +0000147 # Japanese characters (I think - from bug 846133)
Martin v. Löwise2713be2005-03-08 15:03:08 +0000148 TESTFN_UNICODE_UNENCODEABLE = eval('u"@test-\u5171\u6709\u3055\u308c\u308b"')
Mark Hammond2e8624c2003-12-03 22:16:47 +0000149 try:
150 # XXX - Note - should be using TESTFN_ENCODING here - but for
Tim Petersc6c5ece2003-12-04 05:39:43 +0000151 # Windows, "mbcs" currently always operates as if in
Mark Hammond2e8624c2003-12-03 22:16:47 +0000152 # errors=ignore' mode - hence we get '?' characters rather than
153 # the exception. 'Latin1' operates as we expect - ie, fails.
154 # See [ 850997 ] mbcs encoding ignores errors
155 TESTFN_UNICODE_UNENCODEABLE.encode("Latin1")
156 except UnicodeEncodeError:
157 pass
158 else:
159 print \
160 'WARNING: The filename %r CAN be encoded by the filesystem. ' \
161 'Unicode filename tests may not be effective' \
162 % TESTFN_UNICODE_UNENCODEABLE
Neal Norwitz26a1eef2002-11-03 00:35:53 +0000163
164# Make sure we can write to TESTFN, try in /tmp if we can't
165fp = None
166try:
167 fp = open(TESTFN, 'w+')
168except IOError:
169 TMP_TESTFN = os.path.join('/tmp', TESTFN)
170 try:
171 fp = open(TMP_TESTFN, 'w+')
172 TESTFN = TMP_TESTFN
173 del TMP_TESTFN
174 except IOError:
Tim Peters3de75262002-11-09 05:26:15 +0000175 print ('WARNING: tests will fail, unable to write to: %s or %s' %
Neal Norwitz26a1eef2002-11-03 00:35:53 +0000176 (TESTFN, TMP_TESTFN))
177if fp is not None:
178 fp.close()
Neal Norwitz0e17f8c2006-01-23 07:51:27 +0000179 unlink(TESTFN)
Neal Norwitz26a1eef2002-11-03 00:35:53 +0000180del os, fp
Guido van Rossuma8f7e592001-03-13 09:31:07 +0000181
Guido van Rossume26132c1998-04-23 20:13:30 +0000182def findfile(file, here=__file__):
Brett Cannonf1cfb622003-05-04 21:15:27 +0000183 """Try to find a file on sys.path and the working directory. If it is not
184 found the argument passed to the function is returned (this does not
185 necessarily signal failure; could still be the legitimate path)."""
Fred Drake004d5e62000-10-23 17:22:08 +0000186 import os
187 if os.path.isabs(file):
188 return file
Fred Drake004d5e62000-10-23 17:22:08 +0000189 path = sys.path
190 path = [os.path.dirname(here)] + path
191 for dn in path:
192 fn = os.path.join(dn, file)
193 if os.path.exists(fn): return fn
194 return file
Marc-André Lemburg36619082001-01-17 19:11:13 +0000195
196def verify(condition, reason='test failed'):
Guido van Rossuma1374e42001-01-19 19:01:56 +0000197 """Verify that condition is true. If not, raise TestFailed.
Marc-André Lemburg36619082001-01-17 19:11:13 +0000198
Skip Montanaroc955f892001-01-20 19:12:54 +0000199 The optional argument reason can be given to provide
Tim Peters983874d2001-01-19 05:59:21 +0000200 a better error text.
Tim Petersd2bf3b72001-01-18 02:22:22 +0000201 """
Tim Peters983874d2001-01-19 05:59:21 +0000202
Tim Petersd2bf3b72001-01-18 02:22:22 +0000203 if not condition:
Guido van Rossuma1374e42001-01-19 19:01:56 +0000204 raise TestFailed(reason)
Jeremy Hylton47793992001-02-19 15:35:26 +0000205
Tim Petersc2fe6182001-10-30 23:20:46 +0000206def vereq(a, b):
Tim Peters77902972001-12-29 17:34:57 +0000207 """Raise TestFailed if a == b is false.
208
209 This is better than verify(a == b) because, in case of failure, the
210 error message incorporates repr(a) and repr(b) so you can see the
211 inputs.
212
213 Note that "not (a == b)" isn't necessarily the same as "a != b"; the
214 former is tested.
215 """
216
Tim Petersc2fe6182001-10-30 23:20:46 +0000217 if not (a == b):
218 raise TestFailed, "%r == %r" % (a, b)
219
Tim Peters2f228e72001-05-13 00:19:31 +0000220def sortdict(dict):
221 "Like repr(dict), but in sorted order."
222 items = dict.items()
223 items.sort()
224 reprpairs = ["%r: %r" % pair for pair in items]
225 withcommas = ", ".join(reprpairs)
226 return "{%s}" % withcommas
227
Jeremy Hylton47793992001-02-19 15:35:26 +0000228def check_syntax(statement):
229 try:
230 compile(statement, '<string>', 'exec')
231 except SyntaxError:
232 pass
233 else:
234 print 'Missing SyntaxError: "%s"' % statement
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000235
Hye-Shik Changaaa2f1d2005-12-10 17:44:27 +0000236def open_urlresource(url):
237 import urllib, urlparse
238 import os.path
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000239
Hye-Shik Changaaa2f1d2005-12-10 17:44:27 +0000240 filename = urlparse.urlparse(url)[2].split('/')[-1] # '/': it's URL!
241
242 for path in [os.path.curdir, os.path.pardir]:
243 fn = os.path.join(path, filename)
244 if os.path.exists(fn):
245 return open(fn)
246
247 requires('urlfetch')
248 print >> get_original_stdout(), '\tfetching %s ...' % url
249 fn, _ = urllib.urlretrieve(url, filename)
250 return open(fn)
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000251
252#=======================================================================
253# Preliminary PyUNIT integration.
254
255import unittest
256
257
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000258class BasicTestRunner:
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000259 def run(self, test):
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000260 result = unittest.TestResult()
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000261 test(result)
262 return result
263
264
Fred Drake26641032001-10-04 19:46:07 +0000265def run_suite(suite, testclass=None):
Barry Warsawc88425e2001-09-20 06:31:22 +0000266 """Run tests from a unittest.TestSuite-derived class."""
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000267 if verbose:
Fred Drake84a59342001-03-23 04:21:17 +0000268 runner = unittest.TextTestRunner(sys.stdout, verbosity=2)
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000269 else:
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000270 runner = BasicTestRunner()
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000271
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000272 result = runner.run(suite)
273 if not result.wasSuccessful():
Fred Drake14f6c182001-07-16 18:51:32 +0000274 if len(result.errors) == 1 and not result.failures:
275 err = result.errors[0][1]
276 elif len(result.failures) == 1 and not result.errors:
277 err = result.failures[0][1]
278 else:
Fred Drake26641032001-10-04 19:46:07 +0000279 if testclass is None:
280 msg = "errors occurred; run in verbose mode for details"
281 else:
282 msg = "errors occurred in %s.%s" \
283 % (testclass.__module__, testclass.__name__)
284 raise TestFailed(msg)
Tim Peters2d84f2c2001-09-08 03:37:56 +0000285 raise TestFailed(err)
Tim Petersa0a62222001-09-09 06:12:01 +0000286
Barry Warsawc10d6902001-09-20 06:30:41 +0000287
Walter Dörwald21d3a322003-05-01 17:45:56 +0000288def run_unittest(*classes):
289 """Run tests from unittest.TestCase-derived classes."""
Raymond Hettinger9dcbbea2003-04-27 07:54:23 +0000290 suite = unittest.TestSuite()
Walter Dörwald21d3a322003-05-01 17:45:56 +0000291 for cls in classes:
Raymond Hettingerf3590622003-07-16 04:29:42 +0000292 if isinstance(cls, (unittest.TestSuite, unittest.TestCase)):
Raymond Hettinger21d99872003-07-16 02:59:32 +0000293 suite.addTest(cls)
294 else:
295 suite.addTest(unittest.makeSuite(cls))
Walter Dörwald21d3a322003-05-01 17:45:56 +0000296 if len(classes)==1:
297 testclass = classes[0]
298 else:
299 testclass = None
300 run_suite(suite, testclass)
Raymond Hettinger9dcbbea2003-04-27 07:54:23 +0000301
Barry Warsawc10d6902001-09-20 06:30:41 +0000302
Tim Petersa0a62222001-09-09 06:12:01 +0000303#=======================================================================
304# doctest driver.
305
306def run_doctest(module, verbosity=None):
Tim Peters17111f32001-10-03 04:08:26 +0000307 """Run doctest on the given module. Return (#failures, #tests).
Tim Petersa0a62222001-09-09 06:12:01 +0000308
309 If optional argument verbosity is not specified (or is None), pass
Tim Petersbea3fb82001-09-10 01:39:21 +0000310 test_support's belief about verbosity on to doctest. Else doctest's
311 usual behavior is used (it searches sys.argv for -v).
Tim Petersa0a62222001-09-09 06:12:01 +0000312 """
313
314 import doctest
315
316 if verbosity is None:
317 verbosity = verbose
318 else:
319 verbosity = None
320
Tim Peters342ca752001-09-25 19:13:20 +0000321 # Direct doctest output (normally just errors) to real stdout; doctest
322 # output shouldn't be compared by regrtest.
323 save_stdout = sys.stdout
Tim Peters8dee8092001-09-25 20:05:11 +0000324 sys.stdout = get_original_stdout()
Tim Peters342ca752001-09-25 19:13:20 +0000325 try:
326 f, t = doctest.testmod(module, verbose=verbosity)
327 if f:
328 raise TestFailed("%d of %d doctests failed" % (f, t))
329 finally:
330 sys.stdout = save_stdout
Raymond Hettinger35b34bd2003-05-17 00:58:33 +0000331 if verbose:
Raymond Hettinger1ba24b42003-05-17 01:59:57 +0000332 print 'doctest (%s) ... %d tests with zero failures' % (module.__name__, t)
Raymond Hettinger35b34bd2003-05-17 00:58:33 +0000333 return f, t