| 
									
										
										
										
											2000-07-24 06:55:00 +00:00
										 |  |  | """Supporting definitions for the Python regression test.""" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-21 18:26:33 +00:00
										 |  |  | import sys | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-07-24 06:55:00 +00:00
										 |  |  | class Error(Exception): | 
					
						
							| 
									
										
										
										
											2000-10-23 17:22:08 +00:00
										 |  |  |     """Base class for regression test exceptions.""" | 
					
						
							| 
									
										
										
										
											2000-07-24 06:55:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | class TestFailed(Error): | 
					
						
							| 
									
										
										
										
											2000-10-23 17:22:08 +00:00
										 |  |  |     """Test failed.""" | 
					
						
							| 
									
										
										
										
											2000-07-24 06:55:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | class TestSkipped(Error): | 
					
						
							| 
									
										
										
										
											2000-10-23 17:22:08 +00:00
										 |  |  |     """Test skipped.
 | 
					
						
							| 
									
										
										
										
											2000-07-24 06:55:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-10-23 17:22:08 +00:00
										 |  |  |     This can be raised to indicate that a test was deliberatly | 
					
						
							|  |  |  |     skipped, but not because a feature wasn't available.  For | 
					
						
							|  |  |  |     example, if some resource can't be used, such as the network | 
					
						
							|  |  |  |     appears to be unavailable, this should be raised instead of | 
					
						
							|  |  |  |     TestFailed. | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											1992-01-27 17:00:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-20 22:29:23 +00:00
										 |  |  | verbose = 1              # Flag set to 0 by regrtest.py | 
					
						
							| 
									
										
										
										
											2001-09-06 16:09:41 +00:00
										 |  |  | use_resources = None       # Flag set to [] by regrtest.py | 
					
						
							| 
									
										
										
										
											1996-12-20 02:58:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-25 20:05:11 +00:00
										 |  |  | # _original_stdout is meant to hold stdout at the time regrtest began. | 
					
						
							|  |  |  | # This may be "the real" stdout, or IDLE's emulation of stdout, or whatever. | 
					
						
							|  |  |  | # The point is to have some flavor of stdout the user can actually see. | 
					
						
							|  |  |  | _original_stdout = None | 
					
						
							|  |  |  | def record_original_stdout(stdout): | 
					
						
							|  |  |  |     global _original_stdout | 
					
						
							|  |  |  |     _original_stdout = stdout | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def get_original_stdout(): | 
					
						
							|  |  |  |     return _original_stdout or sys.stdout | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1992-01-27 17:00:37 +00:00
										 |  |  | def unload(name): | 
					
						
							| 
									
										
										
										
											2000-10-23 17:22:08 +00:00
										 |  |  |     try: | 
					
						
							|  |  |  |         del sys.modules[name] | 
					
						
							|  |  |  |     except KeyError: | 
					
						
							|  |  |  |         pass | 
					
						
							| 
									
										
										
										
											1992-01-27 17:00:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def forget(modname): | 
					
						
							| 
									
										
										
										
											2000-10-23 17:22:08 +00:00
										 |  |  |     unload(modname) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:26:33 +00:00
										 |  |  |     import os | 
					
						
							| 
									
										
										
										
											2000-10-23 17:22:08 +00:00
										 |  |  |     for dirname in sys.path: | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             os.unlink(os.path.join(dirname, modname + '.pyc')) | 
					
						
							|  |  |  |         except os.error: | 
					
						
							|  |  |  |             pass | 
					
						
							| 
									
										
										
										
											1992-01-27 17:00:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-20 22:29:23 +00:00
										 |  |  | def requires(resource, msg=None): | 
					
						
							| 
									
										
										
										
											2001-09-06 16:09:41 +00:00
										 |  |  |     if use_resources is not None and resource not in use_resources: | 
					
						
							| 
									
										
										
										
											2001-08-20 22:29:23 +00:00
										 |  |  |         if msg is None: | 
					
						
							|  |  |  |             msg = "Use of the `%s' resource not enabled" % resource | 
					
						
							|  |  |  |         raise TestSkipped(msg) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1993-01-26 13:04:43 +00:00
										 |  |  | FUZZ = 1e-6 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def fcmp(x, y): # fuzzy comparison function | 
					
						
							| 
									
										
										
										
											2000-10-23 17:22:08 +00:00
										 |  |  |     if type(x) == type(0.0) or type(y) == type(0.0): | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             x, y = coerce(x, y) | 
					
						
							|  |  |  |             fuzz = (abs(x) + abs(y)) * FUZZ | 
					
						
							|  |  |  |             if abs(x-y) <= fuzz: | 
					
						
							|  |  |  |                 return 0 | 
					
						
							|  |  |  |         except: | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  |     elif type(x) == type(y) and type(x) in (type(()), type([])): | 
					
						
							|  |  |  |         for i in range(min(len(x), len(y))): | 
					
						
							|  |  |  |             outcome = fcmp(x[i], y[i]) | 
					
						
							| 
									
										
										
										
											2000-12-12 23:11:42 +00:00
										 |  |  |             if outcome != 0: | 
					
						
							| 
									
										
										
										
											2000-10-23 17:22:08 +00:00
										 |  |  |                 return outcome | 
					
						
							|  |  |  |         return cmp(len(x), len(y)) | 
					
						
							|  |  |  |     return cmp(x, y) | 
					
						
							| 
									
										
										
										
											1993-01-26 13:04:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-17 18:39:25 +00:00
										 |  |  | try: | 
					
						
							|  |  |  |     unicode | 
					
						
							|  |  |  |     have_unicode = 1 | 
					
						
							|  |  |  | except NameError: | 
					
						
							|  |  |  |     have_unicode = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-13 09:31:07 +00:00
										 |  |  | import os | 
					
						
							| 
									
										
										
										
											2001-03-23 18:04:02 +00:00
										 |  |  | # Filename used for testing | 
					
						
							|  |  |  | if os.name == 'java': | 
					
						
							|  |  |  |     # Jython disallows @ in module names | 
					
						
							|  |  |  |     TESTFN = '$test' | 
					
						
							|  |  |  | elif os.name != 'riscos': | 
					
						
							|  |  |  |     TESTFN = '@test' | 
					
						
							| 
									
										
										
										
											2001-05-13 08:04:26 +00:00
										 |  |  |     # Unicode name only used if TEST_FN_ENCODING exists for the platform. | 
					
						
							| 
									
										
										
										
											2001-08-17 18:39:25 +00:00
										 |  |  |     if have_unicode: | 
					
						
							|  |  |  |         TESTFN_UNICODE=unicode("@test-\xe0\xf2", "latin-1") # 2 latin characters. | 
					
						
							|  |  |  |         if os.name=="nt": | 
					
						
							|  |  |  |             TESTFN_ENCODING="mbcs" | 
					
						
							| 
									
										
										
										
											2001-03-13 09:31:07 +00:00
										 |  |  | else: | 
					
						
							| 
									
										
										
										
											2001-03-23 18:04:02 +00:00
										 |  |  |     TESTFN = 'test' | 
					
						
							| 
									
										
										
										
											2001-03-13 09:31:07 +00:00
										 |  |  | del os | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1992-01-27 17:00:37 +00:00
										 |  |  | from os import unlink | 
					
						
							| 
									
										
										
										
											1998-04-23 20:13:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def findfile(file, here=__file__): | 
					
						
							| 
									
										
										
										
											2000-10-23 17:22:08 +00:00
										 |  |  |     import os | 
					
						
							|  |  |  |     if os.path.isabs(file): | 
					
						
							|  |  |  |         return file | 
					
						
							|  |  |  |     path = sys.path | 
					
						
							|  |  |  |     path = [os.path.dirname(here)] + path | 
					
						
							|  |  |  |     for dn in path: | 
					
						
							|  |  |  |         fn = os.path.join(dn, file) | 
					
						
							|  |  |  |         if os.path.exists(fn): return fn | 
					
						
							|  |  |  |     return file | 
					
						
							| 
									
										
										
										
											2001-01-17 19:11:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def verify(condition, reason='test failed'): | 
					
						
							| 
									
										
										
										
											2001-01-19 19:01:56 +00:00
										 |  |  |     """Verify that condition is true. If not, raise TestFailed.
 | 
					
						
							| 
									
										
										
										
											2001-01-18 02:22:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-01-20 19:12:54 +00:00
										 |  |  |        The optional argument reason can be given to provide | 
					
						
							| 
									
										
										
										
											2001-01-19 05:59:21 +00:00
										 |  |  |        a better error text. | 
					
						
							| 
									
										
										
										
											2001-01-18 02:22:22 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2001-01-19 05:59:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-01-18 02:22:22 +00:00
										 |  |  |     if not condition: | 
					
						
							| 
									
										
										
										
											2001-01-19 19:01:56 +00:00
										 |  |  |         raise TestFailed(reason) | 
					
						
							| 
									
										
										
										
											2001-02-19 15:35:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-30 23:20:46 +00:00
										 |  |  | def vereq(a, b): | 
					
						
							| 
									
										
										
										
											2001-12-29 17:34:57 +00:00
										 |  |  |     """Raise TestFailed if a == b is false.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This is better than verify(a == b) because, in case of failure, the | 
					
						
							|  |  |  |     error message incorporates repr(a) and repr(b) so you can see the | 
					
						
							|  |  |  |     inputs. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Note that "not (a == b)" isn't necessarily the same as "a != b"; the | 
					
						
							|  |  |  |     former is tested. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-30 23:20:46 +00:00
										 |  |  |     if not (a == b): | 
					
						
							|  |  |  |         raise TestFailed, "%r == %r" % (a, b) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Get rid of the superstitious "~" in dict hashing's "i = (~hash) & mask".
The comment following used to say:
	/* We use ~hash instead of hash, as degenerate hash functions, such
	   as for ints <sigh>, can have lots of leading zeros. It's not
	   really a performance risk, but better safe than sorry.
	   12-Dec-00 tim:  so ~hash produces lots of leading ones instead --
	   what's the gain? */
That is, there was never a good reason for doing it.  And to the contrary,
as explained on Python-Dev last December, it tended to make the *sum*
(i + incr) & mask (which is the first table index examined in case of
collison) the same "too often" across distinct hashes.
Changing to the simpler "i = hash & mask" reduced the number of string-dict
collisions (== # number of times we go around the lookup for-loop) from about
6 million to 5 million during a full run of the test suite (these are
approximate because the test suite does some random stuff from run to run).
The number of collisions in non-string dicts also decreased, but not as
dramatically.
Note that this may, for a given dict, change the order (wrt previous
releases) of entries exposed by .keys(), .values() and .items().  A number
of std tests suffered bogus failures as a result.  For dicts keyed by
small ints, or (less so) by characters, the order is much more likely to be
in increasing order of key now; e.g.,
>>> d = {}
>>> for i in range(10):
...    d[i] = i
...
>>> d
{0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9}
>>>
Unfortunately. people may latch on to that in small examples and draw a
bogus conclusion.
test_support.py
    Moved test_extcall's sortdict() into test_support, made it stronger,
    and imported sortdict into other std tests that needed it.
test_unicode.py
    Excluced cp875 from the "roundtrip over range(128)" test, because
    cp875 doesn't have a well-defined inverse for unicode("?", "cp875").
    See Python-Dev for excruciating details.
Cookie.py
    Chaged various output functions to sort dicts before building
    strings from them.
test_extcall
    Fiddled the expected-result file.  This remains sensitive to native
    dict ordering, because, e.g., if there are multiple errors in a
    keyword-arg dict (and test_extcall sets up many cases like that), the
    specific error Python complains about first depends on native dict
    ordering.
											
										 
											2001-05-13 00:19:31 +00:00
										 |  |  | def sortdict(dict): | 
					
						
							|  |  |  |     "Like repr(dict), but in sorted order." | 
					
						
							|  |  |  |     items = dict.items() | 
					
						
							|  |  |  |     items.sort() | 
					
						
							|  |  |  |     reprpairs = ["%r: %r" % pair for pair in items] | 
					
						
							|  |  |  |     withcommas = ", ".join(reprpairs) | 
					
						
							|  |  |  |     return "{%s}" % withcommas | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-02-19 15:35:26 +00:00
										 |  |  | def check_syntax(statement): | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         compile(statement, '<string>', 'exec') | 
					
						
							|  |  |  |     except SyntaxError: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         print 'Missing SyntaxError: "%s"' % statement | 
					
						
							| 
									
										
										
										
											2001-03-21 18:26:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #======================================================================= | 
					
						
							|  |  |  | # Preliminary PyUNIT integration. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import unittest | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  | class BasicTestRunner: | 
					
						
							| 
									
										
										
										
											2001-03-21 18:26:33 +00:00
										 |  |  |     def run(self, test): | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |         result = unittest.TestResult() | 
					
						
							| 
									
										
										
										
											2001-03-21 18:26:33 +00:00
										 |  |  |         test(result) | 
					
						
							|  |  |  |         return result | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-04 19:46:07 +00:00
										 |  |  | def run_suite(suite, testclass=None): | 
					
						
							| 
									
										
										
										
											2001-09-20 06:31:22 +00:00
										 |  |  |     """Run tests from a unittest.TestSuite-derived class.""" | 
					
						
							| 
									
										
										
										
											2001-03-21 18:26:33 +00:00
										 |  |  |     if verbose: | 
					
						
							| 
									
										
										
										
											2001-03-23 04:21:17 +00:00
										 |  |  |         runner = unittest.TextTestRunner(sys.stdout, verbosity=2) | 
					
						
							| 
									
										
										
										
											2001-03-21 18:26:33 +00:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |         runner = BasicTestRunner() | 
					
						
							| 
									
										
										
										
											2001-03-21 18:26:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-22 08:45:36 +00:00
										 |  |  |     result = runner.run(suite) | 
					
						
							|  |  |  |     if not result.wasSuccessful(): | 
					
						
							| 
									
										
										
										
											2001-07-16 18:51:32 +00:00
										 |  |  |         if len(result.errors) == 1 and not result.failures: | 
					
						
							|  |  |  |             err = result.errors[0][1] | 
					
						
							|  |  |  |         elif len(result.failures) == 1 and not result.errors: | 
					
						
							|  |  |  |             err = result.failures[0][1] | 
					
						
							|  |  |  |         else: | 
					
						
							| 
									
										
										
										
											2001-10-04 19:46:07 +00:00
										 |  |  |             if testclass is None: | 
					
						
							|  |  |  |                 msg = "errors occurred; run in verbose mode for details" | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 msg = "errors occurred in %s.%s" \ | 
					
						
							|  |  |  |                       % (testclass.__module__, testclass.__name__) | 
					
						
							|  |  |  |             raise TestFailed(msg) | 
					
						
							| 
									
										
										
										
											2001-09-08 03:37:56 +00:00
										 |  |  |         raise TestFailed(err) | 
					
						
							| 
									
										
										
										
											2001-09-09 06:12:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-20 06:30:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def run_unittest(testclass): | 
					
						
							|  |  |  |     """Run tests from a unittest.TestCase-derived class.""" | 
					
						
							| 
									
										
										
										
											2001-10-04 19:46:07 +00:00
										 |  |  |     run_suite(unittest.makeSuite(testclass), testclass) | 
					
						
							| 
									
										
										
										
											2001-09-20 06:30:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-09 06:12:01 +00:00
										 |  |  | #======================================================================= | 
					
						
							|  |  |  | # doctest driver. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def run_doctest(module, verbosity=None): | 
					
						
							| 
									
										
										
										
											2001-10-03 04:08:26 +00:00
										 |  |  |     """Run doctest on the given module.  Return (#failures, #tests).
 | 
					
						
							| 
									
										
										
										
											2001-09-09 06:12:01 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     If optional argument verbosity is not specified (or is None), pass | 
					
						
							| 
									
										
										
										
											2001-09-10 01:39:21 +00:00
										 |  |  |     test_support's belief about verbosity on to doctest.  Else doctest's | 
					
						
							|  |  |  |     usual behavior is used (it searches sys.argv for -v). | 
					
						
							| 
									
										
										
										
											2001-09-09 06:12:01 +00:00
										 |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     import doctest | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if verbosity is None: | 
					
						
							|  |  |  |         verbosity = verbose | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         verbosity = None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-25 19:13:20 +00:00
										 |  |  |     # Direct doctest output (normally just errors) to real stdout; doctest | 
					
						
							|  |  |  |     # output shouldn't be compared by regrtest. | 
					
						
							|  |  |  |     save_stdout = sys.stdout | 
					
						
							| 
									
										
										
										
											2001-09-25 20:05:11 +00:00
										 |  |  |     sys.stdout = get_original_stdout() | 
					
						
							| 
									
										
										
										
											2001-09-25 19:13:20 +00:00
										 |  |  |     try: | 
					
						
							|  |  |  |         f, t = doctest.testmod(module, verbose=verbosity) | 
					
						
							|  |  |  |         if f: | 
					
						
							|  |  |  |             raise TestFailed("%d of %d doctests failed" % (f, t)) | 
					
						
							| 
									
										
										
										
											2001-10-03 04:08:26 +00:00
										 |  |  |         return f, t | 
					
						
							| 
									
										
										
										
											2001-09-25 19:13:20 +00:00
										 |  |  |     finally: | 
					
						
							|  |  |  |         sys.stdout = save_stdout |