blob: b78800a76e048de1788506d41c2a230c7cbcb2f5 [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
Neil Schemenauerd569f232000-09-22 15:29:28 +000017-l: findleaks -- if GC is available detect and print cyclic garbage
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,
Neil Schemenauerd569f232000-09-22 15:29:28 +000044 exclude=0, single=0, randomize=0, findleaks=0,
Trent Mickf29f47b2000-08-11 19:02:59 +000045 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,
Neil Schemenauerd569f232000-09-22 15:29:28 +000063 single, randomize, and findleaks) allow programmers calling main()
Barry Warsawa873b032000-08-03 15:50:37 +000064 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
Neil Schemenauerd569f232000-09-22 15:29:28 +000082 if o == '-l': findleaks = 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
Neil Schemenauerd569f232000-09-22 15:29:28 +000091 if findleaks:
Barry Warsawa873b032000-08-03 15:50:37 +000092 try:
93 import gc
94 except ImportError:
95 print 'cycle garbage collection not available'
Neil Schemenauerd569f232000-09-22 15:29:28 +000096 findleaks = 0
Barry Warsawa873b032000-08-03 15:50:37 +000097 else:
Neil Schemenauerd569f232000-09-22 15:29:28 +000098 gc.set_debug(gc.DEBUG_SAVEALL)
99 found_garbage = []
Barry Warsawa873b032000-08-03 15:50:37 +0000100
Barry Warsawe11e3de1999-01-28 19:51:51 +0000101 if single:
102 from tempfile import gettempdir
103 filename = os.path.join(gettempdir(), 'pynexttest')
104 try:
105 fp = open(filename, 'r')
106 next = string.strip(fp.read())
107 tests = [next]
108 fp.close()
109 except IOError:
110 pass
Guido van Rossuma4122201997-08-18 20:08:24 +0000111 for i in range(len(args)):
Guido van Rossum41360a41998-03-26 19:42:58 +0000112 # Strip trailing ".py" from arguments
113 if args[i][-3:] == '.py':
114 args[i] = args[i][:-3]
Guido van Rossum6c74fea1998-08-25 12:29:08 +0000115 stdtests = STDTESTS[:]
116 nottests = NOTTESTS[:]
Guido van Rossum152494a1996-12-20 03:12:20 +0000117 if exclude:
Guido van Rossum6c74fea1998-08-25 12:29:08 +0000118 for arg in args:
119 if arg in stdtests:
120 stdtests.remove(arg)
121 nottests[:0] = args
Guido van Rossum41360a41998-03-26 19:42:58 +0000122 args = []
Guido van Rossum747e1ca1998-08-24 13:48:36 +0000123 tests = tests or args or findtests(testdir, stdtests, nottests)
Barry Warsawe11e3de1999-01-28 19:51:51 +0000124 if single:
125 tests = tests[:1]
Skip Montanaroab1c7912000-06-30 16:39:27 +0000126 if randomize:
127 random.shuffle(tests)
Guido van Rossum41360a41998-03-26 19:42:58 +0000128 test_support.verbose = verbose # Tell tests to be moderately quiet
Trent Mickf29f47b2000-08-11 19:02:59 +0000129 test_support.use_large_resources = use_large_resources
Guido van Rossum5796d262000-04-21 21:35:06 +0000130 save_modules = sys.modules.keys()
Guido van Rossum152494a1996-12-20 03:12:20 +0000131 for test in tests:
Guido van Rossum41360a41998-03-26 19:42:58 +0000132 if not quiet:
133 print test
Trent Mickf29f47b2000-08-11 19:02:59 +0000134 ok = runtest(test, generate, verbose, quiet, testdir)
Guido van Rossum41360a41998-03-26 19:42:58 +0000135 if ok > 0:
136 good.append(test)
137 elif ok == 0:
138 bad.append(test)
139 else:
Guido van Rossum41360a41998-03-26 19:42:58 +0000140 skipped.append(test)
Neil Schemenauerd569f232000-09-22 15:29:28 +0000141 if findleaks:
142 gc.collect()
143 if gc.garbage:
144 print "garbage:", repr(gc.garbage)
145 found_garbage.extend(gc.garbage)
146 del gc.garbage[:]
Guido van Rossum5796d262000-04-21 21:35:06 +0000147 # Unload the newly imported modules (best effort finalization)
148 for module in sys.modules.keys():
Guido van Rossum51931142000-05-05 14:27:39 +0000149 if module not in save_modules and module.startswith("test."):
Guido van Rossum5796d262000-04-21 21:35:06 +0000150 test_support.unload(module)
Guido van Rossum152494a1996-12-20 03:12:20 +0000151 if good and not quiet:
Guido van Rossum41360a41998-03-26 19:42:58 +0000152 if not bad and not skipped and len(good) > 1:
153 print "All",
154 print count(len(good), "test"), "OK."
Guido van Rossum152494a1996-12-20 03:12:20 +0000155 if bad:
Guido van Rossum41360a41998-03-26 19:42:58 +0000156 print count(len(bad), "test"), "failed:",
157 print string.join(bad)
Guido van Rossum152494a1996-12-20 03:12:20 +0000158 if skipped and not quiet:
Guido van Rossum41360a41998-03-26 19:42:58 +0000159 print count(len(skipped), "test"), "skipped:",
160 print string.join(skipped)
Barry Warsawe11e3de1999-01-28 19:51:51 +0000161
162 if single:
163 alltests = findtests(testdir, stdtests, nottests)
164 for i in range(len(alltests)):
165 if tests[0] == alltests[i]:
166 if i == len(alltests) - 1:
167 os.unlink(filename)
168 else:
169 fp = open(filename, 'w')
170 fp.write(alltests[i+1] + '\n')
171 fp.close()
172 break
173 else:
174 os.unlink(filename)
175
Guido van Rossume8387011997-08-14 19:40:34 +0000176 return len(bad) > 0
Guido van Rossum152494a1996-12-20 03:12:20 +0000177
Guido van Rossum6fd83b71998-08-01 17:04:08 +0000178STDTESTS = [
Guido van Rossum152494a1996-12-20 03:12:20 +0000179 'test_grammar',
180 'test_opcodes',
181 'test_operations',
182 'test_builtin',
183 'test_exceptions',
184 'test_types',
185 ]
186
Guido van Rossum6fd83b71998-08-01 17:04:08 +0000187NOTTESTS = [
Guido van Rossum152494a1996-12-20 03:12:20 +0000188 'test_support',
189 'test_b1',
190 'test_b2',
191 ]
192
Guido van Rossum6fd83b71998-08-01 17:04:08 +0000193def findtests(testdir=None, stdtests=STDTESTS, nottests=NOTTESTS):
Guido van Rossum152494a1996-12-20 03:12:20 +0000194 """Return a list of all applicable test modules."""
Guido van Rossum6fd83b71998-08-01 17:04:08 +0000195 if not testdir: testdir = findtestdir()
Guido van Rossum152494a1996-12-20 03:12:20 +0000196 names = os.listdir(testdir)
197 tests = []
198 for name in names:
Guido van Rossum41360a41998-03-26 19:42:58 +0000199 if name[:5] == "test_" and name[-3:] == ".py":
200 modname = name[:-3]
201 if modname not in stdtests and modname not in nottests:
202 tests.append(modname)
Guido van Rossum152494a1996-12-20 03:12:20 +0000203 tests.sort()
204 return stdtests + tests
205
Trent Mickf29f47b2000-08-11 19:02:59 +0000206def runtest(test, generate, verbose, quiet, testdir = None):
Guido van Rossum6fd83b71998-08-01 17:04:08 +0000207 """Run a single test.
208 test -- the name of the test
209 generate -- if true, generate output, instead of running the test
210 and comparing it to a previously created output file
211 verbose -- if true, print more messages
Trent Mickf29f47b2000-08-11 19:02:59 +0000212 quiet -- if true, don't print 'skipped' messages (probably redundant)
Guido van Rossum6fd83b71998-08-01 17:04:08 +0000213 testdir -- test directory
214 """
Guido van Rossum152494a1996-12-20 03:12:20 +0000215 test_support.unload(test)
Guido van Rossum6fd83b71998-08-01 17:04:08 +0000216 if not testdir: testdir = findtestdir()
Guido van Rossum152494a1996-12-20 03:12:20 +0000217 outputdir = os.path.join(testdir, "output")
218 outputfile = os.path.join(outputdir, test)
219 try:
Guido van Rossum41360a41998-03-26 19:42:58 +0000220 if generate:
221 cfp = open(outputfile, "w")
222 elif verbose:
223 cfp = sys.stdout
224 else:
225 cfp = Compare(outputfile)
Guido van Rossum152494a1996-12-20 03:12:20 +0000226 except IOError:
Guido van Rossum41360a41998-03-26 19:42:58 +0000227 cfp = None
228 print "Warning: can't open", outputfile
Guido van Rossum152494a1996-12-20 03:12:20 +0000229 try:
Guido van Rossum41360a41998-03-26 19:42:58 +0000230 save_stdout = sys.stdout
231 try:
232 if cfp:
233 sys.stdout = cfp
234 print test # Output file starts with test name
235 __import__(test, globals(), locals(), [])
Jeremy Hyltonfff9e202000-07-11 15:15:31 +0000236 if cfp and not (generate or verbose):
237 cfp.close()
Guido van Rossum41360a41998-03-26 19:42:58 +0000238 finally:
239 sys.stdout = save_stdout
Thomas Wouters3af826e2000-08-04 13:17:51 +0000240 except (ImportError, test_support.TestSkipped), msg:
Trent Mickf29f47b2000-08-11 19:02:59 +0000241 if not quiet:
242 print "test", test,
243 print "skipped -- ", msg
Guido van Rossum41360a41998-03-26 19:42:58 +0000244 return -1
Fred Drakefe5c22a2000-08-18 16:04:05 +0000245 except KeyboardInterrupt:
246 raise
Guido van Rossum152494a1996-12-20 03:12:20 +0000247 except test_support.TestFailed, msg:
Guido van Rossum41360a41998-03-26 19:42:58 +0000248 print "test", test, "failed --", msg
249 return 0
Guido van Rossum9e48b271997-07-16 01:56:13 +0000250 except:
Guido van Rossum41360a41998-03-26 19:42:58 +0000251 type, value = sys.exc_info()[:2]
Fred Drake27c4b392000-08-23 20:34:40 +0000252 print "test", test, "crashed --", str(type) + ":", value
Guido van Rossum41360a41998-03-26 19:42:58 +0000253 if verbose:
254 traceback.print_exc(file=sys.stdout)
255 return 0
Guido van Rossum152494a1996-12-20 03:12:20 +0000256 else:
Guido van Rossum41360a41998-03-26 19:42:58 +0000257 return 1
Guido van Rossum152494a1996-12-20 03:12:20 +0000258
259def findtestdir():
260 if __name__ == '__main__':
Guido van Rossum41360a41998-03-26 19:42:58 +0000261 file = sys.argv[0]
Guido van Rossum152494a1996-12-20 03:12:20 +0000262 else:
Guido van Rossum41360a41998-03-26 19:42:58 +0000263 file = __file__
Guido van Rossum152494a1996-12-20 03:12:20 +0000264 testdir = os.path.dirname(file) or os.curdir
265 return testdir
266
267def count(n, word):
268 if n == 1:
Guido van Rossum41360a41998-03-26 19:42:58 +0000269 return "%d %s" % (n, word)
Guido van Rossum152494a1996-12-20 03:12:20 +0000270 else:
Guido van Rossum41360a41998-03-26 19:42:58 +0000271 return "%d %ss" % (n, word)
Guido van Rossum152494a1996-12-20 03:12:20 +0000272
273class Compare:
274
275 def __init__(self, filename):
Guido van Rossum41360a41998-03-26 19:42:58 +0000276 self.fp = open(filename, 'r')
Guido van Rossum152494a1996-12-20 03:12:20 +0000277
278 def write(self, data):
Guido van Rossum41360a41998-03-26 19:42:58 +0000279 expected = self.fp.read(len(data))
280 if data <> expected:
281 raise test_support.TestFailed, \
282 'Writing: '+`data`+', expected: '+`expected`
Guido van Rossum152494a1996-12-20 03:12:20 +0000283
Guido van Rossume87ed5f1998-04-23 13:33:21 +0000284 def writelines(self, listoflines):
285 map(self.write, listoflines)
286
Guido van Rossum75fce301997-07-17 14:51:37 +0000287 def flush(self):
Guido van Rossum41360a41998-03-26 19:42:58 +0000288 pass
Guido van Rossum75fce301997-07-17 14:51:37 +0000289
Guido van Rossum152494a1996-12-20 03:12:20 +0000290 def close(self):
Guido van Rossum41360a41998-03-26 19:42:58 +0000291 leftover = self.fp.read()
292 if leftover:
293 raise test_support.TestFailed, 'Unread: '+`leftover`
294 self.fp.close()
Guido van Rossum152494a1996-12-20 03:12:20 +0000295
296 def isatty(self):
Guido van Rossum41360a41998-03-26 19:42:58 +0000297 return 0
Guido van Rossum152494a1996-12-20 03:12:20 +0000298
299if __name__ == '__main__':
Guido van Rossume8387011997-08-14 19:40:34 +0000300 sys.exit(main())