blob: 9c36cf6bd0aedc8ef29f9653be54fcafe9b91f76 [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
52def forget(modname):
Brett Cannonf1cfb622003-05-04 21:15:27 +000053 '''"Forget" a module was ever imported by removing it from sys.modules and
54 deleting any .pyc and .pyo files.'''
Fred Drake004d5e62000-10-23 17:22:08 +000055 unload(modname)
Fred Drakecd1b1dd2001-03-21 18:26:33 +000056 import os
Fred Drake004d5e62000-10-23 17:22:08 +000057 for dirname in sys.path:
58 try:
59 os.unlink(os.path.join(dirname, modname + '.pyc'))
60 except os.error:
61 pass
Brett Cannonf1cfb622003-05-04 21:15:27 +000062 # 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 + '.pyo'))
67 except os.error:
68 pass
Guido van Rossum3bead091992-01-27 17:00:37 +000069
Tim Petersb4ee4eb2002-12-04 03:26:57 +000070def is_resource_enabled(resource):
Brett Cannonf1cfb622003-05-04 21:15:27 +000071 """Test whether a resource is enabled. Known resources are set by
72 regrtest.py."""
Tim Petersb4ee4eb2002-12-04 03:26:57 +000073 return use_resources is not None and resource in use_resources
74
Barry Warsawc0fb6052001-08-20 22:29:23 +000075def requires(resource, msg=None):
Brett Cannonf1cfb622003-05-04 21:15:27 +000076 """Raise ResourceDenied if the specified resource is not available.
77
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."""
Skip Montanarod839ecd2003-04-24 19:06:57 +000080 # 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
Tim Petersb4ee4eb2002-12-04 03:26:57 +000084 if not is_resource_enabled(resource):
Barry Warsawc0fb6052001-08-20 22:29:23 +000085 if msg is None:
86 msg = "Use of the `%s' resource not enabled" % resource
Fred Drake9a0db072003-02-03 15:19:30 +000087 raise ResourceDenied(msg)
Barry Warsawc0fb6052001-08-20 22:29:23 +000088
Guido van Rossum35fb82a1993-01-26 13:04:43 +000089FUZZ = 1e-6
90
91def fcmp(x, y): # fuzzy comparison function
Fred Drake004d5e62000-10-23 17:22:08 +000092 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])
Fred Drake132dce22000-12-12 23:11:42 +0000103 if outcome != 0:
Fred Drake004d5e62000-10-23 17:22:08 +0000104 return outcome
105 return cmp(len(x), len(y))
106 return cmp(x, y)
Guido van Rossum35fb82a1993-01-26 13:04:43 +0000107
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000108try:
109 unicode
110 have_unicode = 1
111except NameError:
112 have_unicode = 0
113
Finn Bock57bc5fa2002-11-01 18:02:03 +0000114is_jython = sys.platform.startswith('java')
115
Guido van Rossuma8f7e592001-03-13 09:31:07 +0000116import os
Barry Warsaw559f6682001-03-23 18:04:02 +0000117# Filename used for testing
118if os.name == 'java':
119 # Jython disallows @ in module names
120 TESTFN = '$test'
121elif os.name != 'riscos':
122 TESTFN = '@test'
Mark Hammondef8b6542001-05-13 08:04:26 +0000123 # Unicode name only used if TEST_FN_ENCODING exists for the platform.
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000124 if have_unicode:
Martin v. Löwis2411a2d2002-11-09 19:57:26 +0000125 if isinstance('', unicode):
126 # python -U
127 # XXX perhaps unicode() should accept Unicode strings?
128 TESTFN_UNICODE="@test-\xe0\xf2"
129 else:
130 TESTFN_UNICODE=unicode("@test-\xe0\xf2", "latin-1") # 2 latin characters.
Martin v. Löwis73d538b2003-03-05 15:13:47 +0000131 TESTFN_ENCODING=sys.getfilesystemencoding()
Guido van Rossuma8f7e592001-03-13 09:31:07 +0000132else:
Barry Warsaw559f6682001-03-23 18:04:02 +0000133 TESTFN = 'test'
Neal Norwitz26a1eef2002-11-03 00:35:53 +0000134
135# Make sure we can write to TESTFN, try in /tmp if we can't
136fp = None
137try:
138 fp = open(TESTFN, 'w+')
139except IOError:
140 TMP_TESTFN = os.path.join('/tmp', TESTFN)
141 try:
142 fp = open(TMP_TESTFN, 'w+')
143 TESTFN = TMP_TESTFN
144 del TMP_TESTFN
145 except IOError:
Tim Peters3de75262002-11-09 05:26:15 +0000146 print ('WARNING: tests will fail, unable to write to: %s or %s' %
Neal Norwitz26a1eef2002-11-03 00:35:53 +0000147 (TESTFN, TMP_TESTFN))
148if fp is not None:
149 fp.close()
150 try:
151 os.unlink(TESTFN)
152 except:
153 pass
154del os, fp
Guido van Rossuma8f7e592001-03-13 09:31:07 +0000155
Guido van Rossum3bead091992-01-27 17:00:37 +0000156from os import unlink
Guido van Rossume26132c1998-04-23 20:13:30 +0000157
158def findfile(file, here=__file__):
Brett Cannonf1cfb622003-05-04 21:15:27 +0000159 """Try to find a file on sys.path and the working directory. If it is not
160 found the argument passed to the function is returned (this does not
161 necessarily signal failure; could still be the legitimate path)."""
Fred Drake004d5e62000-10-23 17:22:08 +0000162 import os
163 if os.path.isabs(file):
164 return file
Fred Drake004d5e62000-10-23 17:22:08 +0000165 path = sys.path
166 path = [os.path.dirname(here)] + path
167 for dn in path:
168 fn = os.path.join(dn, file)
169 if os.path.exists(fn): return fn
170 return file
Marc-André Lemburg36619082001-01-17 19:11:13 +0000171
172def verify(condition, reason='test failed'):
Guido van Rossuma1374e42001-01-19 19:01:56 +0000173 """Verify that condition is true. If not, raise TestFailed.
Marc-André Lemburg36619082001-01-17 19:11:13 +0000174
Skip Montanaroc955f892001-01-20 19:12:54 +0000175 The optional argument reason can be given to provide
Tim Peters983874d2001-01-19 05:59:21 +0000176 a better error text.
Tim Petersd2bf3b72001-01-18 02:22:22 +0000177 """
Tim Peters983874d2001-01-19 05:59:21 +0000178
Tim Petersd2bf3b72001-01-18 02:22:22 +0000179 if not condition:
Guido van Rossuma1374e42001-01-19 19:01:56 +0000180 raise TestFailed(reason)
Jeremy Hylton47793992001-02-19 15:35:26 +0000181
Tim Petersc2fe6182001-10-30 23:20:46 +0000182def vereq(a, b):
Tim Peters77902972001-12-29 17:34:57 +0000183 """Raise TestFailed if a == b is false.
184
185 This is better than verify(a == b) because, in case of failure, the
186 error message incorporates repr(a) and repr(b) so you can see the
187 inputs.
188
189 Note that "not (a == b)" isn't necessarily the same as "a != b"; the
190 former is tested.
191 """
192
Tim Petersc2fe6182001-10-30 23:20:46 +0000193 if not (a == b):
194 raise TestFailed, "%r == %r" % (a, b)
195
Tim Peters2f228e72001-05-13 00:19:31 +0000196def sortdict(dict):
197 "Like repr(dict), but in sorted order."
198 items = dict.items()
199 items.sort()
200 reprpairs = ["%r: %r" % pair for pair in items]
201 withcommas = ", ".join(reprpairs)
202 return "{%s}" % withcommas
203
Jeremy Hylton47793992001-02-19 15:35:26 +0000204def check_syntax(statement):
205 try:
206 compile(statement, '<string>', 'exec')
207 except SyntaxError:
208 pass
209 else:
210 print 'Missing SyntaxError: "%s"' % statement
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000211
212
213
214#=======================================================================
215# Preliminary PyUNIT integration.
216
217import unittest
218
219
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000220class BasicTestRunner:
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000221 def run(self, test):
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000222 result = unittest.TestResult()
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000223 test(result)
224 return result
225
226
Fred Drake26641032001-10-04 19:46:07 +0000227def run_suite(suite, testclass=None):
Barry Warsawc88425e2001-09-20 06:31:22 +0000228 """Run tests from a unittest.TestSuite-derived class."""
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000229 if verbose:
Fred Drake84a59342001-03-23 04:21:17 +0000230 runner = unittest.TextTestRunner(sys.stdout, verbosity=2)
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000231 else:
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000232 runner = BasicTestRunner()
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000233
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000234 result = runner.run(suite)
235 if not result.wasSuccessful():
Fred Drake14f6c182001-07-16 18:51:32 +0000236 if len(result.errors) == 1 and not result.failures:
237 err = result.errors[0][1]
238 elif len(result.failures) == 1 and not result.errors:
239 err = result.failures[0][1]
240 else:
Fred Drake26641032001-10-04 19:46:07 +0000241 if testclass is None:
242 msg = "errors occurred; run in verbose mode for details"
243 else:
244 msg = "errors occurred in %s.%s" \
245 % (testclass.__module__, testclass.__name__)
246 raise TestFailed(msg)
Tim Peters2d84f2c2001-09-08 03:37:56 +0000247 raise TestFailed(err)
Tim Petersa0a62222001-09-09 06:12:01 +0000248
Barry Warsawc10d6902001-09-20 06:30:41 +0000249
Walter Dörwald21d3a322003-05-01 17:45:56 +0000250def run_unittest(*classes):
251 """Run tests from unittest.TestCase-derived classes."""
Raymond Hettinger9dcbbea2003-04-27 07:54:23 +0000252 suite = unittest.TestSuite()
Walter Dörwald21d3a322003-05-01 17:45:56 +0000253 for cls in classes:
Raymond Hettinger9dcbbea2003-04-27 07:54:23 +0000254 suite.addTest(unittest.makeSuite(cls))
Walter Dörwald21d3a322003-05-01 17:45:56 +0000255 if len(classes)==1:
256 testclass = classes[0]
257 else:
258 testclass = None
259 run_suite(suite, testclass)
Raymond Hettinger9dcbbea2003-04-27 07:54:23 +0000260
Barry Warsawc10d6902001-09-20 06:30:41 +0000261
Tim Petersa0a62222001-09-09 06:12:01 +0000262#=======================================================================
263# doctest driver.
264
265def run_doctest(module, verbosity=None):
Tim Peters17111f32001-10-03 04:08:26 +0000266 """Run doctest on the given module. Return (#failures, #tests).
Tim Petersa0a62222001-09-09 06:12:01 +0000267
268 If optional argument verbosity is not specified (or is None), pass
Tim Petersbea3fb82001-09-10 01:39:21 +0000269 test_support's belief about verbosity on to doctest. Else doctest's
270 usual behavior is used (it searches sys.argv for -v).
Tim Petersa0a62222001-09-09 06:12:01 +0000271 """
272
273 import doctest
274
275 if verbosity is None:
276 verbosity = verbose
277 else:
278 verbosity = None
279
Tim Peters342ca752001-09-25 19:13:20 +0000280 # Direct doctest output (normally just errors) to real stdout; doctest
281 # output shouldn't be compared by regrtest.
282 save_stdout = sys.stdout
Tim Peters8dee8092001-09-25 20:05:11 +0000283 sys.stdout = get_original_stdout()
Tim Peters342ca752001-09-25 19:13:20 +0000284 try:
285 f, t = doctest.testmod(module, verbose=verbosity)
286 if f:
287 raise TestFailed("%d of %d doctests failed" % (f, t))
Tim Peters17111f32001-10-03 04:08:26 +0000288 return f, t
Tim Peters342ca752001-09-25 19:13:20 +0000289 finally:
290 sys.stdout = save_stdout