blob: 906ed8aba8705276ae1c7209b825b848628d75bd [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):
Skip Montanarod839ecd2003-04-24 19:06:57 +000065 # see if the caller's module is __main__ - if so, treat as if
66 # the resource was set
67 if sys._getframe().f_back.f_globals.get("__name__") == "__main__":
68 return
Tim Petersb4ee4eb2002-12-04 03:26:57 +000069 if not is_resource_enabled(resource):
Barry Warsawc0fb6052001-08-20 22:29:23 +000070 if msg is None:
71 msg = "Use of the `%s' resource not enabled" % resource
Fred Drake9a0db072003-02-03 15:19:30 +000072 raise ResourceDenied(msg)
Barry Warsawc0fb6052001-08-20 22:29:23 +000073
Guido van Rossum35fb82a1993-01-26 13:04:43 +000074FUZZ = 1e-6
75
76def fcmp(x, y): # fuzzy comparison function
Fred Drake004d5e62000-10-23 17:22:08 +000077 if type(x) == type(0.0) or type(y) == type(0.0):
78 try:
79 x, y = coerce(x, y)
80 fuzz = (abs(x) + abs(y)) * FUZZ
81 if abs(x-y) <= fuzz:
82 return 0
83 except:
84 pass
85 elif type(x) == type(y) and type(x) in (type(()), type([])):
86 for i in range(min(len(x), len(y))):
87 outcome = fcmp(x[i], y[i])
Fred Drake132dce22000-12-12 23:11:42 +000088 if outcome != 0:
Fred Drake004d5e62000-10-23 17:22:08 +000089 return outcome
90 return cmp(len(x), len(y))
91 return cmp(x, y)
Guido van Rossum35fb82a1993-01-26 13:04:43 +000092
Martin v. Löwis339d0f72001-08-17 18:39:25 +000093try:
94 unicode
95 have_unicode = 1
96except NameError:
97 have_unicode = 0
98
Finn Bock57bc5fa2002-11-01 18:02:03 +000099is_jython = sys.platform.startswith('java')
100
Guido van Rossuma8f7e592001-03-13 09:31:07 +0000101import os
Barry Warsaw559f6682001-03-23 18:04:02 +0000102# Filename used for testing
103if os.name == 'java':
104 # Jython disallows @ in module names
105 TESTFN = '$test'
106elif os.name != 'riscos':
107 TESTFN = '@test'
Mark Hammondef8b6542001-05-13 08:04:26 +0000108 # Unicode name only used if TEST_FN_ENCODING exists for the platform.
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000109 if have_unicode:
Martin v. Löwis2411a2d2002-11-09 19:57:26 +0000110 if isinstance('', unicode):
111 # python -U
112 # XXX perhaps unicode() should accept Unicode strings?
113 TESTFN_UNICODE="@test-\xe0\xf2"
114 else:
115 TESTFN_UNICODE=unicode("@test-\xe0\xf2", "latin-1") # 2 latin characters.
Martin v. Löwis73d538b2003-03-05 15:13:47 +0000116 TESTFN_ENCODING=sys.getfilesystemencoding()
Guido van Rossuma8f7e592001-03-13 09:31:07 +0000117else:
Barry Warsaw559f6682001-03-23 18:04:02 +0000118 TESTFN = 'test'
Neal Norwitz26a1eef2002-11-03 00:35:53 +0000119
120# Make sure we can write to TESTFN, try in /tmp if we can't
121fp = None
122try:
123 fp = open(TESTFN, 'w+')
124except IOError:
125 TMP_TESTFN = os.path.join('/tmp', TESTFN)
126 try:
127 fp = open(TMP_TESTFN, 'w+')
128 TESTFN = TMP_TESTFN
129 del TMP_TESTFN
130 except IOError:
Tim Peters3de75262002-11-09 05:26:15 +0000131 print ('WARNING: tests will fail, unable to write to: %s or %s' %
Neal Norwitz26a1eef2002-11-03 00:35:53 +0000132 (TESTFN, TMP_TESTFN))
133if fp is not None:
134 fp.close()
135 try:
136 os.unlink(TESTFN)
137 except:
138 pass
139del os, fp
Guido van Rossuma8f7e592001-03-13 09:31:07 +0000140
Guido van Rossum3bead091992-01-27 17:00:37 +0000141from os import unlink
Guido van Rossume26132c1998-04-23 20:13:30 +0000142
143def findfile(file, here=__file__):
Fred Drake004d5e62000-10-23 17:22:08 +0000144 import os
145 if os.path.isabs(file):
146 return file
Fred Drake004d5e62000-10-23 17:22:08 +0000147 path = sys.path
148 path = [os.path.dirname(here)] + path
149 for dn in path:
150 fn = os.path.join(dn, file)
151 if os.path.exists(fn): return fn
152 return file
Marc-André Lemburg36619082001-01-17 19:11:13 +0000153
154def verify(condition, reason='test failed'):
Guido van Rossuma1374e42001-01-19 19:01:56 +0000155 """Verify that condition is true. If not, raise TestFailed.
Marc-André Lemburg36619082001-01-17 19:11:13 +0000156
Skip Montanaroc955f892001-01-20 19:12:54 +0000157 The optional argument reason can be given to provide
Tim Peters983874d2001-01-19 05:59:21 +0000158 a better error text.
Tim Petersd2bf3b72001-01-18 02:22:22 +0000159 """
Tim Peters983874d2001-01-19 05:59:21 +0000160
Tim Petersd2bf3b72001-01-18 02:22:22 +0000161 if not condition:
Guido van Rossuma1374e42001-01-19 19:01:56 +0000162 raise TestFailed(reason)
Jeremy Hylton47793992001-02-19 15:35:26 +0000163
Tim Petersc2fe6182001-10-30 23:20:46 +0000164def vereq(a, b):
Tim Peters77902972001-12-29 17:34:57 +0000165 """Raise TestFailed if a == b is false.
166
167 This is better than verify(a == b) because, in case of failure, the
168 error message incorporates repr(a) and repr(b) so you can see the
169 inputs.
170
171 Note that "not (a == b)" isn't necessarily the same as "a != b"; the
172 former is tested.
173 """
174
Tim Petersc2fe6182001-10-30 23:20:46 +0000175 if not (a == b):
176 raise TestFailed, "%r == %r" % (a, b)
177
Tim Peters2f228e72001-05-13 00:19:31 +0000178def sortdict(dict):
179 "Like repr(dict), but in sorted order."
180 items = dict.items()
181 items.sort()
182 reprpairs = ["%r: %r" % pair for pair in items]
183 withcommas = ", ".join(reprpairs)
184 return "{%s}" % withcommas
185
Jeremy Hylton47793992001-02-19 15:35:26 +0000186def check_syntax(statement):
187 try:
188 compile(statement, '<string>', 'exec')
189 except SyntaxError:
190 pass
191 else:
192 print 'Missing SyntaxError: "%s"' % statement
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000193
194
195
196#=======================================================================
197# Preliminary PyUNIT integration.
198
199import unittest
200
201
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000202class BasicTestRunner:
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000203 def run(self, test):
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000204 result = unittest.TestResult()
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000205 test(result)
206 return result
207
208
Fred Drake26641032001-10-04 19:46:07 +0000209def run_suite(suite, testclass=None):
Barry Warsawc88425e2001-09-20 06:31:22 +0000210 """Run tests from a unittest.TestSuite-derived class."""
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000211 if verbose:
Fred Drake84a59342001-03-23 04:21:17 +0000212 runner = unittest.TextTestRunner(sys.stdout, verbosity=2)
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000213 else:
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000214 runner = BasicTestRunner()
Fred Drakecd1b1dd2001-03-21 18:26:33 +0000215
Steve Purcell5ddd1a82001-03-22 08:45:36 +0000216 result = runner.run(suite)
217 if not result.wasSuccessful():
Fred Drake14f6c182001-07-16 18:51:32 +0000218 if len(result.errors) == 1 and not result.failures:
219 err = result.errors[0][1]
220 elif len(result.failures) == 1 and not result.errors:
221 err = result.failures[0][1]
222 else:
Fred Drake26641032001-10-04 19:46:07 +0000223 if testclass is None:
224 msg = "errors occurred; run in verbose mode for details"
225 else:
226 msg = "errors occurred in %s.%s" \
227 % (testclass.__module__, testclass.__name__)
228 raise TestFailed(msg)
Tim Peters2d84f2c2001-09-08 03:37:56 +0000229 raise TestFailed(err)
Tim Petersa0a62222001-09-09 06:12:01 +0000230
Barry Warsawc10d6902001-09-20 06:30:41 +0000231
Walter Dörwald21d3a322003-05-01 17:45:56 +0000232def run_unittest(*classes):
233 """Run tests from unittest.TestCase-derived classes."""
Raymond Hettinger9dcbbea2003-04-27 07:54:23 +0000234 suite = unittest.TestSuite()
Walter Dörwald21d3a322003-05-01 17:45:56 +0000235 for cls in classes:
Raymond Hettinger9dcbbea2003-04-27 07:54:23 +0000236 suite.addTest(unittest.makeSuite(cls))
Walter Dörwald21d3a322003-05-01 17:45:56 +0000237 if len(classes)==1:
238 testclass = classes[0]
239 else:
240 testclass = None
241 run_suite(suite, testclass)
Raymond Hettinger9dcbbea2003-04-27 07:54:23 +0000242
Barry Warsawc10d6902001-09-20 06:30:41 +0000243
Tim Petersa0a62222001-09-09 06:12:01 +0000244#=======================================================================
245# doctest driver.
246
247def run_doctest(module, verbosity=None):
Tim Peters17111f32001-10-03 04:08:26 +0000248 """Run doctest on the given module. Return (#failures, #tests).
Tim Petersa0a62222001-09-09 06:12:01 +0000249
250 If optional argument verbosity is not specified (or is None), pass
Tim Petersbea3fb82001-09-10 01:39:21 +0000251 test_support's belief about verbosity on to doctest. Else doctest's
252 usual behavior is used (it searches sys.argv for -v).
Tim Petersa0a62222001-09-09 06:12:01 +0000253 """
254
255 import doctest
256
257 if verbosity is None:
258 verbosity = verbose
259 else:
260 verbosity = None
261
Tim Peters342ca752001-09-25 19:13:20 +0000262 # Direct doctest output (normally just errors) to real stdout; doctest
263 # output shouldn't be compared by regrtest.
264 save_stdout = sys.stdout
Tim Peters8dee8092001-09-25 20:05:11 +0000265 sys.stdout = get_original_stdout()
Tim Peters342ca752001-09-25 19:13:20 +0000266 try:
267 f, t = doctest.testmod(module, verbose=verbosity)
268 if f:
269 raise TestFailed("%d of %d doctests failed" % (f, t))
Tim Peters17111f32001-10-03 04:08:26 +0000270 return f, t
Tim Peters342ca752001-09-25 19:13:20 +0000271 finally:
272 sys.stdout = save_stdout