blob: ef05fcfc1f356f50b9b3f31fd12a8994da411bbc [file] [log] [blame]
Guido van Rossum152494a1996-12-20 03:12:20 +00001#! /usr/bin/env python
2
3"""Regression test.
4
5This will find all modules whose name is "test_*" in the test
6directory, and run them. Various command line options provide
7additional facilities.
8
9Command line options:
10
Barry Warsawa873b032000-08-03 15:50:37 +000011-v: verbose -- run tests in verbose mode with output to stdout
12-q: quiet -- don't print anything except if a test fails
13-g: generate -- write the output file for a test instead of comparing it
14-x: exclude -- arguments are tests to *exclude*
15-s: single -- run only a single test (see below)
16-r: random -- randomize test execution order
17-l: leakdebug -- if cycle garbage collection is enabled, run with DEBUG_LEAK
Trent Mickf29f47b2000-08-11 19:02:59 +000018--have-resources -- run tests that require large resources (time/space)
Guido van Rossum152494a1996-12-20 03:12:20 +000019
20If non-option arguments are present, they are names for tests to run,
21unless -x is given, in which case they are names for tests not to run.
22If no test names are given, all tests are run.
Guido van Rossumf58ed251997-03-07 21:04:33 +000023
Guido van Rossuma4122201997-08-18 20:08:24 +000024-v is incompatible with -g and does not compare test output files.
Barry Warsawe11e3de1999-01-28 19:51:51 +000025
26-s means to run only a single test and exit. This is useful when Purifying
27the Python interpreter. The file /tmp/pynexttest is read to find the next
28test to run. If this file is missing, the first test_*.py file in testdir or
29on the command line is used. (actually tempfile.gettempdir() is used instead
30of /tmp).
31
Guido van Rossum152494a1996-12-20 03:12:20 +000032"""
33
34import sys
35import string
36import os
37import getopt
Guido van Rossum9e48b271997-07-16 01:56:13 +000038import traceback
Skip Montanaroab1c7912000-06-30 16:39:27 +000039import random
Guido van Rossum152494a1996-12-20 03:12:20 +000040
41import test_support
42
Skip Montanaroab1c7912000-06-30 16:39:27 +000043def main(tests=None, testdir=None, verbose=0, quiet=0, generate=0,
Trent Mickf29f47b2000-08-11 19:02:59 +000044 exclude=0, single=0, randomize=0, leakdebug=0,
45 use_large_resources=0):
Guido van Rossum6fd83b71998-08-01 17:04:08 +000046 """Execute a test suite.
47
Thomas Wouters7e474022000-07-16 12:04:32 +000048 This also parses command-line options and modifies its behavior
Guido van Rossum6fd83b71998-08-01 17:04:08 +000049 accordingly.
50
51 tests -- a list of strings containing test names (optional)
52 testdir -- the directory in which to look for tests (optional)
53
54 Users other than the Python test suite will certainly want to
55 specify testdir; if it's omitted, the directory containing the
56 Python test suite is searched for.
57
58 If the tests argument is omitted, the tests listed on the
59 command-line will be used. If that's empty, too, then all *.py
60 files beginning with test_ will be used.
Skip Montanaroab1c7912000-06-30 16:39:27 +000061
Barry Warsawa873b032000-08-03 15:50:37 +000062 The other seven default arguments (verbose, quiet, generate, exclude,
63 single, randomize, and leakdebug) allow programmers calling main()
64 directly to set the values that would normally be set by flags on the
65 command line.
66
Guido van Rossum6fd83b71998-08-01 17:04:08 +000067 """
68
Guido van Rossum152494a1996-12-20 03:12:20 +000069 try:
Trent Mickf29f47b2000-08-11 19:02:59 +000070 opts, args = getopt.getopt(sys.argv[1:], 'vgqxsrl', ['have-resources'])
Guido van Rossum152494a1996-12-20 03:12:20 +000071 except getopt.error, msg:
Guido van Rossum41360a41998-03-26 19:42:58 +000072 print msg
73 print __doc__
74 return 2
Guido van Rossum152494a1996-12-20 03:12:20 +000075 for o, a in opts:
Guido van Rossum41360a41998-03-26 19:42:58 +000076 if o == '-v': verbose = verbose+1
77 if o == '-q': quiet = 1; verbose = 0
78 if o == '-g': generate = 1
79 if o == '-x': exclude = 1
Barry Warsawe11e3de1999-01-28 19:51:51 +000080 if o == '-s': single = 1
Skip Montanaroab1c7912000-06-30 16:39:27 +000081 if o == '-r': randomize = 1
Barry Warsawa873b032000-08-03 15:50:37 +000082 if o == '-l': leakdebug = 1
Trent Mickf29f47b2000-08-11 19:02:59 +000083 if o == '--have-resources': use_large_resources = 1
Guido van Rossuma4122201997-08-18 20:08:24 +000084 if generate and verbose:
Guido van Rossum41360a41998-03-26 19:42:58 +000085 print "-g and -v don't go together!"
86 return 2
Guido van Rossum152494a1996-12-20 03:12:20 +000087 good = []
88 bad = []
89 skipped = []
Barry Warsawe11e3de1999-01-28 19:51:51 +000090
Barry Warsawa873b032000-08-03 15:50:37 +000091 if leakdebug:
92 try:
93 import gc
94 except ImportError:
95 print 'cycle garbage collection not available'
96 else:
97 gc.set_debug(gc.DEBUG_LEAK)
98
Barry Warsawe11e3de1999-01-28 19:51:51 +000099 if single:
100 from tempfile import gettempdir
101 filename = os.path.join(gettempdir(), 'pynexttest')
102 try:
103 fp = open(filename, 'r')
104 next = string.strip(fp.read())
105 tests = [next]
106 fp.close()
107 except IOError:
108 pass
Guido van Rossuma4122201997-08-18 20:08:24 +0000109 for i in range(len(args)):
Guido van Rossum41360a41998-03-26 19:42:58 +0000110 # Strip trailing ".py" from arguments
111 if args[i][-3:] == '.py':
112 args[i] = args[i][:-3]
Guido van Rossum6c74fea1998-08-25 12:29:08 +0000113 stdtests = STDTESTS[:]
114 nottests = NOTTESTS[:]
Guido van Rossum152494a1996-12-20 03:12:20 +0000115 if exclude:
Guido van Rossum6c74fea1998-08-25 12:29:08 +0000116 for arg in args:
117 if arg in stdtests:
118 stdtests.remove(arg)
119 nottests[:0] = args
Guido van Rossum41360a41998-03-26 19:42:58 +0000120 args = []
Guido van Rossum747e1ca1998-08-24 13:48:36 +0000121 tests = tests or args or findtests(testdir, stdtests, nottests)
Barry Warsawe11e3de1999-01-28 19:51:51 +0000122 if single:
123 tests = tests[:1]
Skip Montanaroab1c7912000-06-30 16:39:27 +0000124 if randomize:
125 random.shuffle(tests)
Guido van Rossum41360a41998-03-26 19:42:58 +0000126 test_support.verbose = verbose # Tell tests to be moderately quiet
Trent Mickf29f47b2000-08-11 19:02:59 +0000127 test_support.use_large_resources = use_large_resources
Guido van Rossum5796d262000-04-21 21:35:06 +0000128 save_modules = sys.modules.keys()
Guido van Rossum152494a1996-12-20 03:12:20 +0000129 for test in tests:
Guido van Rossum41360a41998-03-26 19:42:58 +0000130 if not quiet:
131 print test
Trent Mickf29f47b2000-08-11 19:02:59 +0000132 ok = runtest(test, generate, verbose, quiet, testdir)
Guido van Rossum41360a41998-03-26 19:42:58 +0000133 if ok > 0:
134 good.append(test)
135 elif ok == 0:
136 bad.append(test)
137 else:
Guido van Rossum41360a41998-03-26 19:42:58 +0000138 skipped.append(test)
Guido van Rossum5796d262000-04-21 21:35:06 +0000139 # Unload the newly imported modules (best effort finalization)
140 for module in sys.modules.keys():
Guido van Rossum51931142000-05-05 14:27:39 +0000141 if module not in save_modules and module.startswith("test."):
Guido van Rossum5796d262000-04-21 21:35:06 +0000142 test_support.unload(module)
Guido van Rossum152494a1996-12-20 03:12:20 +0000143 if good and not quiet:
Guido van Rossum41360a41998-03-26 19:42:58 +0000144 if not bad and not skipped and len(good) > 1:
145 print "All",
146 print count(len(good), "test"), "OK."
Guido van Rossum152494a1996-12-20 03:12:20 +0000147 if bad:
Guido van Rossum41360a41998-03-26 19:42:58 +0000148 print count(len(bad), "test"), "failed:",
149 print string.join(bad)
Guido van Rossum152494a1996-12-20 03:12:20 +0000150 if skipped and not quiet:
Guido van Rossum41360a41998-03-26 19:42:58 +0000151 print count(len(skipped), "test"), "skipped:",
152 print string.join(skipped)
Barry Warsawe11e3de1999-01-28 19:51:51 +0000153
154 if single:
155 alltests = findtests(testdir, stdtests, nottests)
156 for i in range(len(alltests)):
157 if tests[0] == alltests[i]:
158 if i == len(alltests) - 1:
159 os.unlink(filename)
160 else:
161 fp = open(filename, 'w')
162 fp.write(alltests[i+1] + '\n')
163 fp.close()
164 break
165 else:
166 os.unlink(filename)
167
Guido van Rossume8387011997-08-14 19:40:34 +0000168 return len(bad) > 0
Guido van Rossum152494a1996-12-20 03:12:20 +0000169
Guido van Rossum6fd83b71998-08-01 17:04:08 +0000170STDTESTS = [
Guido van Rossum152494a1996-12-20 03:12:20 +0000171 'test_grammar',
172 'test_opcodes',
173 'test_operations',
174 'test_builtin',
175 'test_exceptions',
176 'test_types',
177 ]
178
Guido van Rossum6fd83b71998-08-01 17:04:08 +0000179NOTTESTS = [
Guido van Rossum152494a1996-12-20 03:12:20 +0000180 'test_support',
181 'test_b1',
182 'test_b2',
183 ]
184
Guido van Rossum6fd83b71998-08-01 17:04:08 +0000185def findtests(testdir=None, stdtests=STDTESTS, nottests=NOTTESTS):
Guido van Rossum152494a1996-12-20 03:12:20 +0000186 """Return a list of all applicable test modules."""
Guido van Rossum6fd83b71998-08-01 17:04:08 +0000187 if not testdir: testdir = findtestdir()
Guido van Rossum152494a1996-12-20 03:12:20 +0000188 names = os.listdir(testdir)
189 tests = []
190 for name in names:
Guido van Rossum41360a41998-03-26 19:42:58 +0000191 if name[:5] == "test_" and name[-3:] == ".py":
192 modname = name[:-3]
193 if modname not in stdtests and modname not in nottests:
194 tests.append(modname)
Guido van Rossum152494a1996-12-20 03:12:20 +0000195 tests.sort()
196 return stdtests + tests
197
Trent Mickf29f47b2000-08-11 19:02:59 +0000198def runtest(test, generate, verbose, quiet, testdir = None):
Guido van Rossum6fd83b71998-08-01 17:04:08 +0000199 """Run a single test.
200 test -- the name of the test
201 generate -- if true, generate output, instead of running the test
202 and comparing it to a previously created output file
203 verbose -- if true, print more messages
Trent Mickf29f47b2000-08-11 19:02:59 +0000204 quiet -- if true, don't print 'skipped' messages (probably redundant)
Guido van Rossum6fd83b71998-08-01 17:04:08 +0000205 testdir -- test directory
206 """
Guido van Rossum152494a1996-12-20 03:12:20 +0000207 test_support.unload(test)
Guido van Rossum6fd83b71998-08-01 17:04:08 +0000208 if not testdir: testdir = findtestdir()
Guido van Rossum152494a1996-12-20 03:12:20 +0000209 outputdir = os.path.join(testdir, "output")
210 outputfile = os.path.join(outputdir, test)
211 try:
Guido van Rossum41360a41998-03-26 19:42:58 +0000212 if generate:
213 cfp = open(outputfile, "w")
214 elif verbose:
215 cfp = sys.stdout
216 else:
217 cfp = Compare(outputfile)
Guido van Rossum152494a1996-12-20 03:12:20 +0000218 except IOError:
Guido van Rossum41360a41998-03-26 19:42:58 +0000219 cfp = None
220 print "Warning: can't open", outputfile
Guido van Rossum152494a1996-12-20 03:12:20 +0000221 try:
Guido van Rossum41360a41998-03-26 19:42:58 +0000222 save_stdout = sys.stdout
223 try:
224 if cfp:
225 sys.stdout = cfp
226 print test # Output file starts with test name
227 __import__(test, globals(), locals(), [])
Jeremy Hyltonfff9e202000-07-11 15:15:31 +0000228 if cfp and not (generate or verbose):
229 cfp.close()
Guido van Rossum41360a41998-03-26 19:42:58 +0000230 finally:
231 sys.stdout = save_stdout
Thomas Wouters3af826e2000-08-04 13:17:51 +0000232 except (ImportError, test_support.TestSkipped), msg:
Trent Mickf29f47b2000-08-11 19:02:59 +0000233 if not quiet:
234 print "test", test,
235 print "skipped -- ", msg
Guido van Rossum41360a41998-03-26 19:42:58 +0000236 return -1
Fred Drakefe5c22a2000-08-18 16:04:05 +0000237 except KeyboardInterrupt:
238 raise
Guido van Rossum152494a1996-12-20 03:12:20 +0000239 except test_support.TestFailed, msg:
Guido van Rossum41360a41998-03-26 19:42:58 +0000240 print "test", test, "failed --", msg
241 return 0
Guido van Rossum9e48b271997-07-16 01:56:13 +0000242 except:
Guido van Rossum41360a41998-03-26 19:42:58 +0000243 type, value = sys.exc_info()[:2]
Fred Drake27c4b392000-08-23 20:34:40 +0000244 print "test", test, "crashed --", str(type) + ":", value
Guido van Rossum41360a41998-03-26 19:42:58 +0000245 if verbose:
246 traceback.print_exc(file=sys.stdout)
247 return 0
Guido van Rossum152494a1996-12-20 03:12:20 +0000248 else:
Guido van Rossum41360a41998-03-26 19:42:58 +0000249 return 1
Guido van Rossum152494a1996-12-20 03:12:20 +0000250
251def findtestdir():
252 if __name__ == '__main__':
Guido van Rossum41360a41998-03-26 19:42:58 +0000253 file = sys.argv[0]
Guido van Rossum152494a1996-12-20 03:12:20 +0000254 else:
Guido van Rossum41360a41998-03-26 19:42:58 +0000255 file = __file__
Guido van Rossum152494a1996-12-20 03:12:20 +0000256 testdir = os.path.dirname(file) or os.curdir
257 return testdir
258
259def count(n, word):
260 if n == 1:
Guido van Rossum41360a41998-03-26 19:42:58 +0000261 return "%d %s" % (n, word)
Guido van Rossum152494a1996-12-20 03:12:20 +0000262 else:
Guido van Rossum41360a41998-03-26 19:42:58 +0000263 return "%d %ss" % (n, word)
Guido van Rossum152494a1996-12-20 03:12:20 +0000264
265class Compare:
266
267 def __init__(self, filename):
Guido van Rossum41360a41998-03-26 19:42:58 +0000268 self.fp = open(filename, 'r')
Guido van Rossum152494a1996-12-20 03:12:20 +0000269
270 def write(self, data):
Guido van Rossum41360a41998-03-26 19:42:58 +0000271 expected = self.fp.read(len(data))
272 if data <> expected:
273 raise test_support.TestFailed, \
274 'Writing: '+`data`+', expected: '+`expected`
Guido van Rossum152494a1996-12-20 03:12:20 +0000275
Guido van Rossume87ed5f1998-04-23 13:33:21 +0000276 def writelines(self, listoflines):
277 map(self.write, listoflines)
278
Guido van Rossum75fce301997-07-17 14:51:37 +0000279 def flush(self):
Guido van Rossum41360a41998-03-26 19:42:58 +0000280 pass
Guido van Rossum75fce301997-07-17 14:51:37 +0000281
Guido van Rossum152494a1996-12-20 03:12:20 +0000282 def close(self):
Guido van Rossum41360a41998-03-26 19:42:58 +0000283 leftover = self.fp.read()
284 if leftover:
285 raise test_support.TestFailed, 'Unread: '+`leftover`
286 self.fp.close()
Guido van Rossum152494a1996-12-20 03:12:20 +0000287
288 def isatty(self):
Guido van Rossum41360a41998-03-26 19:42:58 +0000289 return 0
Guido van Rossum152494a1996-12-20 03:12:20 +0000290
291if __name__ == '__main__':
Guido van Rossume8387011997-08-14 19:40:34 +0000292 sys.exit(main())