blob: 8ac385134a4bf54f5af9b8fac9d3bf6f47c0f5e5 [file] [log] [blame]
Fred Drake1790dd42000-07-24 06:55:00 +00001"""Supporting definitions for the Python regression test."""
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):
Fred Drake004d5e62000-10-23 17:22:08 +000053 unload(modname)
Fred Drakecd1b1dd2001-03-21 18:26:33 +000054 import os
Fred Drake004d5e62000-10-23 17:22:08 +000055 for dirname in sys.path:
56 try:
57 os.unlink(os.path.join(dirname, modname + '.pyc'))
58 except os.error:
59 pass
Guido van Rossum3bead091992-01-27 17:00:37 +000060
Tim Petersb4ee4eb2002-12-04 03:26:57 +000061def is_resource_enabled(resource):
62 return use_resources is not None and resource in use_resources
63
Barry Warsawc0fb6052001-08-20 22:29:23 +000064def requires(resource, msg=None):
Tim Petersb4ee4eb2002-12-04 03:26:57 +000065 if not is_resource_enabled(resource):
Barry Warsawc0fb6052001-08-20 22:29:23 +000066 if msg is None:
67 msg = "Use of the `%s' resource not enabled" % resource
Fred Drake9a0db072003-02-03 15:19:30 +000068 raise ResourceDenied(msg)
Barry Warsawc0fb6052001-08-20 22:29:23 +000069
Guido van Rossum35fb82a1993-01-26 13:04:43 +000070FUZZ = 1e-6
71
72def fcmp(x, y): # fuzzy comparison function
Fred Drake004d5e62000-10-23 17:22:08 +000073 if type(x) == type(0.0) or type(y) == type(0.0):
74 try:
75 x, y = coerce(x, y)
76 fuzz = (abs(x) + abs(y)) * FUZZ
77 if abs(x-y) <= fuzz:
78 return 0
79 except:
80 pass
81 elif type(x) == type(y) and type(x) in (type(()), type([])):
82 for i in range(min(len(x), len(y))):
83 outcome = fcmp(x[i], y[i])
Fred Drake132dce22000-12-12 23:11:42 +000084 if outcome != 0:
Fred Drake004d5e62000-10-23 17:22:08 +000085 return outcome
86 return cmp(len(x), len(y))
87 return cmp(x, y)
Guido van Rossum35fb82a1993-01-26 13:04:43 +000088
Martin v. Löwis339d0f72001-08-17 18:39:25 +000089try:
90 unicode
91 have_unicode = 1
92except NameError:
93 have_unicode = 0
94
Finn Bock57bc5fa2002-11-01 18:02:03 +000095is_jython = sys.platform.startswith('java')
96
Guido van Rossuma8f7e592001-03-13 09:31:07 +000097import os
Barry Warsaw559f6682001-03-23 18:04:02 +000098# Filename used for testing
99if os.name == 'java':
100 # Jython disallows @ in module names
101 TESTFN = '$test'
102elif os.name != 'riscos':
103 TESTFN = '@test'
Mark Hammondef8b6542001-05-13 08:04:26 +0000104 # Unicode name only used if TEST_FN_ENCODING exists for the platform.
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000105 if have_unicode:
Martin v. Löwis2411a2d2002-11-09 19:57:26 +0000106 if isinstance('', unicode):
107 # python -U
108 # XXX perhaps unicode() should accept Unicode strings?
109 TESTFN_UNICODE="@test-\xe0\xf2"
110 else:
111 TESTFN_UNICODE=unicode("@test-\xe0\xf2", "latin-1") # 2 latin characters.
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000112 if os.name=="nt":
113 TESTFN_ENCODING="mbcs"
Guido van Rossuma8f7e592001-03-13 09:31:07 +0000114else:
Barry Warsaw559f6682001-03-23 18:04:02 +0000115 TESTFN = 'test'
Neal Norwitz26a1eef2002-11-03 00:35:53 +0000116
117# Make sure we can write to TESTFN, try in /tmp if we can't
118fp = None
119try:
120 fp = open(TESTFN, 'w+')
121except IOError:
122 TMP_TESTFN = os.path.join('/tmp', TESTFN)
123 try:
124 fp = open(TMP_TESTFN, 'w+')
125 TESTFN = TMP_TESTFN
126 del TMP_TESTFN
127 except IOError:
Tim Peters3de75262002-11-09 05:26:15 +0000128 print ('WARNING: tests will fail, unable to write to: %s or %s' %
Neal Norwitz26a1eef2002-11-03 00:35:53 +0000129 (TESTFN, TMP_TESTFN))
130if fp is not None:
131 fp.close()
132 try:
133 os.unlink(TESTFN)
134 except:
135 pass
136del os, fp
Guido van Rossuma8f7e592001-03-13 09:31:07 +0000137
Guido van Rossum3bead091992-01-27 17:00:37 +0000138from os import unlink
Guido van Rossume26132c1998-04-23 20:13:30 +0000139
140def findfile(file, here=__file__):
Fred Drake004d5e62000-10-23 17:22:08 +0000141 import os
142 if os.path.isabs(file):
143 return file
Fred Drake004d5e62000-10-23 17:22:08 +0000144 path = sys.path
145 path = [os.path.dirname(here)] + path
146 for dn in path:
147 fn = os.path.join(dn, file)
148 if os.path.exists(fn): return fn
149 return file
Marc-André Lemburg36619082001-01-17 19:11:13 +0000150
151def verify(condition, reason='test failed'):
Guido van Rossuma1374e42001-01-19 19:01:56 +0000152 """Verify that condition is true. If not, raise TestFailed.
Marc-André Lemburg36619082001-01-17 19:11:13 +0000153
Skip Montanaroc955f892001-01-20 19:12:54 +0000154 The optional argument reason can be given to provide
Tim Peters983874d2001-01-19 05:59:21 +0000155 a better error text.
Tim Petersd2bf3b72001-01-18 02:22:22 +0000156 """
Tim Peters983874d2001-01-19 05:59:21 +0000157
Tim Petersd2bf3b72001-01-18 02:22:22 +0000158 if not condition:
Guido van Rossuma1374e42001-01-19 19:01:56 +0000159 raise TestFailed(reason)
Jeremy Hylton47793992001-02-19 15:35:26 +0000160
Tim Petersc2fe6182001-10-30 23:20:46 +0000161def vereq(a, b):
Tim Peters77902972001-12-29 17:34:57 +0000162 """Raise TestFailed if a == b is false.
163
164 This is better than verify(a == b) because, in case of failure, the
165 error message incorporates repr(a) and repr(b) so you can see the
166 inputs.
167
168 Note that "not (a == b)" isn't necessarily the same as "a != b"; the
169 former is tested.
170 """
171
Tim Petersc2fe6182001-10-30 23:20:46 +0000172 if not (a == b):
173 raise TestFailed, "%r == %r" % (a, b)
174
Tim Peters2f228e72001-05-13 00:19:31 +0000175def sortdict(dict):
176 "Like repr(dict), but in sorted order."
177 items = dict.items()
178 items.sort()
179 reprpairs = ["%r: %r" % pair for pair in items]
180 withcommas = ", ".join(reprpairs)
181 return "{%s}" % withcommas
182
Jeremy Hylton47793992001-02-19 15:35:26 +0000183def check_syntax(statement):
184 try:
185 compile(statement, '<string>', 'exec')
186 except SyntaxError:
187 pass
188 else:
189 print 'Missing SyntaxError: "%s"' % statement
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000190
191
192
193#=======================================================================
194# Preliminary PyUNIT integration.
195
196import unittest
197
198
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000199class BasicTestRunner:
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000200 def run(self, test):
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000201 result = unittest.TestResult()
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000202 test(result)
203 return result
204
205
Fred Drake26641032001-10-04 19:46:07 +0000206def run_suite(suite, testclass=None):
Barry Warsawc88425e2001-09-20 06:31:22 +0000207 """Run tests from a unittest.TestSuite-derived class."""
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000208 if verbose:
Fred Drake84a59342001-03-23 04:21:17 +0000209 runner = unittest.TextTestRunner(sys.stdout, verbosity=2)
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000210 else:
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000211 runner = BasicTestRunner()
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000212
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000213 result = runner.run(suite)
214 if not result.wasSuccessful():
Fred Drake14f6c182001-07-16 18:51:32 +0000215 if len(result.errors) == 1 and not result.failures:
216 err = result.errors[0][1]
217 elif len(result.failures) == 1 and not result.errors:
218 err = result.failures[0][1]
219 else:
Fred Drake26641032001-10-04 19:46:07 +0000220 if testclass is None:
221 msg = "errors occurred; run in verbose mode for details"
222 else:
223 msg = "errors occurred in %s.%s" \
224 % (testclass.__module__, testclass.__name__)
225 raise TestFailed(msg)
Tim Peters2d84f2c2001-09-08 03:37:56 +0000226 raise TestFailed(err)
Tim Petersa0a62222001-09-09 06:12:01 +0000227
Barry Warsawc10d6902001-09-20 06:30:41 +0000228
229def run_unittest(testclass):
230 """Run tests from a unittest.TestCase-derived class."""
Fred Drake26641032001-10-04 19:46:07 +0000231 run_suite(unittest.makeSuite(testclass), testclass)
Barry Warsawc10d6902001-09-20 06:30:41 +0000232
233
Tim Petersa0a62222001-09-09 06:12:01 +0000234#=======================================================================
235# doctest driver.
236
237def run_doctest(module, verbosity=None):
Tim Peters17111f32001-10-03 04:08:26 +0000238 """Run doctest on the given module. Return (#failures, #tests).
Tim Petersa0a62222001-09-09 06:12:01 +0000239
240 If optional argument verbosity is not specified (or is None), pass
Tim Petersbea3fb82001-09-10 01:39:21 +0000241 test_support's belief about verbosity on to doctest. Else doctest's
242 usual behavior is used (it searches sys.argv for -v).
Tim Petersa0a62222001-09-09 06:12:01 +0000243 """
244
245 import doctest
246
247 if verbosity is None:
248 verbosity = verbose
249 else:
250 verbosity = None
251
Tim Peters342ca752001-09-25 19:13:20 +0000252 # Direct doctest output (normally just errors) to real stdout; doctest
253 # output shouldn't be compared by regrtest.
254 save_stdout = sys.stdout
Tim Peters8dee8092001-09-25 20:05:11 +0000255 sys.stdout = get_original_stdout()
Tim Peters342ca752001-09-25 19:13:20 +0000256 try:
257 f, t = doctest.testmod(module, verbose=verbosity)
258 if f:
259 raise TestFailed("%d of %d doctests failed" % (f, t))
Tim Peters17111f32001-10-03 04:08:26 +0000260 return f, t
Tim Peters342ca752001-09-25 19:13:20 +0000261 finally:
262 sys.stdout = save_stdout