##// END OF EJS Templates
tests: set a default encoding for running tests (ASCII)
Matt Mackall -
r3776:037824e6 default
parent child Browse files
Show More
@@ -1,419 +1,421 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 #
2 #
3 # run-tests.py - Run a set of tests on Mercurial
3 # run-tests.py - Run a set of tests on Mercurial
4 #
4 #
5 # Copyright 2006 Matt Mackall <mpm@selenic.com>
5 # Copyright 2006 Matt Mackall <mpm@selenic.com>
6 #
6 #
7 # This software may be used and distributed according to the terms
7 # This software may be used and distributed according to the terms
8 # of the GNU General Public License, incorporated herein by reference.
8 # of the GNU General Public License, incorporated herein by reference.
9
9
10 import difflib
10 import difflib
11 import errno
11 import errno
12 import optparse
12 import optparse
13 import os
13 import os
14 import popen2
14 import popen2
15 import re
15 import re
16 import shutil
16 import shutil
17 import signal
17 import signal
18 import sys
18 import sys
19 import tempfile
19 import tempfile
20 import time
20 import time
21
21
22 required_tools = ["python", "diff", "grep", "unzip", "gunzip", "bunzip2", "sed", "merge"]
22 required_tools = ["python", "diff", "grep", "unzip", "gunzip", "bunzip2", "sed", "merge"]
23
23
24 parser = optparse.OptionParser("%prog [options] [tests]")
24 parser = optparse.OptionParser("%prog [options] [tests]")
25 parser.add_option("-v", "--verbose", action="store_true",
25 parser.add_option("-v", "--verbose", action="store_true",
26 help="output verbose messages")
26 help="output verbose messages")
27 parser.add_option("-t", "--timeout", type="int",
27 parser.add_option("-t", "--timeout", type="int",
28 help="kill errant tests after TIMEOUT seconds")
28 help="kill errant tests after TIMEOUT seconds")
29 parser.add_option("-c", "--cover", action="store_true",
29 parser.add_option("-c", "--cover", action="store_true",
30 help="print a test coverage report")
30 help="print a test coverage report")
31 parser.add_option("-s", "--cover_stdlib", action="store_true",
31 parser.add_option("-s", "--cover_stdlib", action="store_true",
32 help="print a test coverage report inc. standard libraries")
32 help="print a test coverage report inc. standard libraries")
33 parser.add_option("-C", "--annotate", action="store_true",
33 parser.add_option("-C", "--annotate", action="store_true",
34 help="output files annotated with coverage")
34 help="output files annotated with coverage")
35 parser.add_option("-r", "--retest", action="store_true",
35 parser.add_option("-r", "--retest", action="store_true",
36 help="retest failed tests")
36 help="retest failed tests")
37 parser.add_option("-f", "--first", action="store_true",
37 parser.add_option("-f", "--first", action="store_true",
38 help="exit on the first test failure")
38 help="exit on the first test failure")
39 parser.add_option("-R", "--restart", action="store_true",
39 parser.add_option("-R", "--restart", action="store_true",
40 help="restart at last error")
40 help="restart at last error")
41 parser.add_option("-i", "--interactive", action="store_true",
41 parser.add_option("-i", "--interactive", action="store_true",
42 help="prompt to accept changed output")
42 help="prompt to accept changed output")
43
43
44 parser.set_defaults(timeout=180)
44 parser.set_defaults(timeout=180)
45 (options, args) = parser.parse_args()
45 (options, args) = parser.parse_args()
46 verbose = options.verbose
46 verbose = options.verbose
47 coverage = options.cover or options.cover_stdlib or options.annotate
47 coverage = options.cover or options.cover_stdlib or options.annotate
48
48
49 def vlog(*msg):
49 def vlog(*msg):
50 if verbose:
50 if verbose:
51 for m in msg:
51 for m in msg:
52 print m,
52 print m,
53 print
53 print
54
54
55 def splitnewlines(text):
55 def splitnewlines(text):
56 '''like str.splitlines, but only split on newlines.
56 '''like str.splitlines, but only split on newlines.
57 keep line endings.'''
57 keep line endings.'''
58 i = 0
58 i = 0
59 lines = []
59 lines = []
60 while True:
60 while True:
61 n = text.find('\n', i)
61 n = text.find('\n', i)
62 if n == -1:
62 if n == -1:
63 last = text[i:]
63 last = text[i:]
64 if last:
64 if last:
65 lines.append(last)
65 lines.append(last)
66 return lines
66 return lines
67 lines.append(text[i:n+1])
67 lines.append(text[i:n+1])
68 i = n + 1
68 i = n + 1
69
69
70 def show_diff(expected, output):
70 def show_diff(expected, output):
71 for line in difflib.unified_diff(expected, output,
71 for line in difflib.unified_diff(expected, output,
72 "Expected output", "Test output"):
72 "Expected output", "Test output"):
73 sys.stdout.write(line)
73 sys.stdout.write(line)
74
74
75 def find_program(program):
75 def find_program(program):
76 """Search PATH for a executable program"""
76 """Search PATH for a executable program"""
77 for p in os.environ.get('PATH', os.defpath).split(os.pathsep):
77 for p in os.environ.get('PATH', os.defpath).split(os.pathsep):
78 name = os.path.join(p, program)
78 name = os.path.join(p, program)
79 if os.access(name, os.X_OK):
79 if os.access(name, os.X_OK):
80 return name
80 return name
81 return None
81 return None
82
82
83 def check_required_tools():
83 def check_required_tools():
84 # Before we go any further, check for pre-requisite tools
84 # Before we go any further, check for pre-requisite tools
85 # stuff from coreutils (cat, rm, etc) are not tested
85 # stuff from coreutils (cat, rm, etc) are not tested
86 for p in required_tools:
86 for p in required_tools:
87 if os.name == 'nt':
87 if os.name == 'nt':
88 p += '.exe'
88 p += '.exe'
89 found = find_program(p)
89 found = find_program(p)
90 if found:
90 if found:
91 vlog("# Found prerequisite", p, "at", found)
91 vlog("# Found prerequisite", p, "at", found)
92 else:
92 else:
93 print "WARNING: Did not find prerequisite tool: "+p
93 print "WARNING: Did not find prerequisite tool: "+p
94
94
95 def cleanup_exit():
95 def cleanup_exit():
96 if verbose:
96 if verbose:
97 print "# Cleaning up HGTMP", HGTMP
97 print "# Cleaning up HGTMP", HGTMP
98 shutil.rmtree(HGTMP, True)
98 shutil.rmtree(HGTMP, True)
99
99
100 def use_correct_python():
100 def use_correct_python():
101 # some tests run python interpreter. they must use same
101 # some tests run python interpreter. they must use same
102 # interpreter we use or bad things will happen.
102 # interpreter we use or bad things will happen.
103 exedir, exename = os.path.split(sys.executable)
103 exedir, exename = os.path.split(sys.executable)
104 if exename == 'python':
104 if exename == 'python':
105 path = find_program('python')
105 path = find_program('python')
106 if os.path.dirname(path) == exedir:
106 if os.path.dirname(path) == exedir:
107 return
107 return
108 vlog('# Making python executable in test path use correct Python')
108 vlog('# Making python executable in test path use correct Python')
109 my_python = os.path.join(BINDIR, 'python')
109 my_python = os.path.join(BINDIR, 'python')
110 try:
110 try:
111 os.symlink(sys.executable, my_python)
111 os.symlink(sys.executable, my_python)
112 except AttributeError:
112 except AttributeError:
113 # windows fallback
113 # windows fallback
114 shutil.copyfile(sys.executable, my_python)
114 shutil.copyfile(sys.executable, my_python)
115 shutil.copymode(sys.executable, my_python)
115 shutil.copymode(sys.executable, my_python)
116
116
117 def install_hg():
117 def install_hg():
118 vlog("# Performing temporary installation of HG")
118 vlog("# Performing temporary installation of HG")
119 installerrs = os.path.join("tests", "install.err")
119 installerrs = os.path.join("tests", "install.err")
120
120
121 os.chdir("..") # Get back to hg root
121 os.chdir("..") # Get back to hg root
122 cmd = ('%s setup.py clean --all'
122 cmd = ('%s setup.py clean --all'
123 ' install --force --home="%s" --install-lib="%s" >%s 2>&1'
123 ' install --force --home="%s" --install-lib="%s" >%s 2>&1'
124 % (sys.executable, INST, PYTHONDIR, installerrs))
124 % (sys.executable, INST, PYTHONDIR, installerrs))
125 vlog("# Running", cmd)
125 vlog("# Running", cmd)
126 if os.system(cmd) == 0:
126 if os.system(cmd) == 0:
127 if not verbose:
127 if not verbose:
128 os.remove(installerrs)
128 os.remove(installerrs)
129 else:
129 else:
130 f = open(installerrs)
130 f = open(installerrs)
131 for line in f:
131 for line in f:
132 print line,
132 print line,
133 f.close()
133 f.close()
134 sys.exit(1)
134 sys.exit(1)
135 os.chdir(TESTDIR)
135 os.chdir(TESTDIR)
136
136
137 os.environ["PATH"] = "%s%s%s" % (BINDIR, os.pathsep, os.environ["PATH"])
137 os.environ["PATH"] = "%s%s%s" % (BINDIR, os.pathsep, os.environ["PATH"])
138 os.environ["PYTHONPATH"] = PYTHONDIR
138 os.environ["PYTHONPATH"] = PYTHONDIR
139
139
140 use_correct_python()
140 use_correct_python()
141
141
142 if coverage:
142 if coverage:
143 vlog("# Installing coverage wrapper")
143 vlog("# Installing coverage wrapper")
144 os.environ['COVERAGE_FILE'] = COVERAGE_FILE
144 os.environ['COVERAGE_FILE'] = COVERAGE_FILE
145 if os.path.exists(COVERAGE_FILE):
145 if os.path.exists(COVERAGE_FILE):
146 os.unlink(COVERAGE_FILE)
146 os.unlink(COVERAGE_FILE)
147 # Create a wrapper script to invoke hg via coverage.py
147 # Create a wrapper script to invoke hg via coverage.py
148 os.rename(os.path.join(BINDIR, "hg"), os.path.join(BINDIR, "_hg.py"))
148 os.rename(os.path.join(BINDIR, "hg"), os.path.join(BINDIR, "_hg.py"))
149 f = open(os.path.join(BINDIR, 'hg'), 'w')
149 f = open(os.path.join(BINDIR, 'hg'), 'w')
150 f.write('#!' + sys.executable + '\n')
150 f.write('#!' + sys.executable + '\n')
151 f.write('import sys, os; os.execv(sys.executable, [sys.executable, '+ \
151 f.write('import sys, os; os.execv(sys.executable, [sys.executable, '+ \
152 '"%s", "-x", "%s"] + sys.argv[1:])\n' % (
152 '"%s", "-x", "%s"] + sys.argv[1:])\n' % (
153 os.path.join(TESTDIR, 'coverage.py'),
153 os.path.join(TESTDIR, 'coverage.py'),
154 os.path.join(BINDIR, '_hg.py')))
154 os.path.join(BINDIR, '_hg.py')))
155 f.close()
155 f.close()
156 os.chmod(os.path.join(BINDIR, 'hg'), 0700)
156 os.chmod(os.path.join(BINDIR, 'hg'), 0700)
157
157
158 def output_coverage():
158 def output_coverage():
159 vlog("# Producing coverage report")
159 vlog("# Producing coverage report")
160 omit = [BINDIR, TESTDIR, PYTHONDIR]
160 omit = [BINDIR, TESTDIR, PYTHONDIR]
161 if not options.cover_stdlib:
161 if not options.cover_stdlib:
162 # Exclude as system paths (ignoring empty strings seen on win)
162 # Exclude as system paths (ignoring empty strings seen on win)
163 omit += [x for x in sys.path if x != '']
163 omit += [x for x in sys.path if x != '']
164 omit = ','.join(omit)
164 omit = ','.join(omit)
165 os.chdir(PYTHONDIR)
165 os.chdir(PYTHONDIR)
166 cmd = '"%s" "%s" -r "--omit=%s"' % (
166 cmd = '"%s" "%s" -r "--omit=%s"' % (
167 sys.executable, os.path.join(TESTDIR, 'coverage.py'), omit)
167 sys.executable, os.path.join(TESTDIR, 'coverage.py'), omit)
168 vlog("# Running: "+cmd)
168 vlog("# Running: "+cmd)
169 os.system(cmd)
169 os.system(cmd)
170 if options.annotate:
170 if options.annotate:
171 adir = os.path.join(TESTDIR, 'annotated')
171 adir = os.path.join(TESTDIR, 'annotated')
172 if not os.path.isdir(adir):
172 if not os.path.isdir(adir):
173 os.mkdir(adir)
173 os.mkdir(adir)
174 cmd = '"%s" "%s" -a "--directory=%s" "--omit=%s"' % (
174 cmd = '"%s" "%s" -a "--directory=%s" "--omit=%s"' % (
175 sys.executable, os.path.join(TESTDIR, 'coverage.py'),
175 sys.executable, os.path.join(TESTDIR, 'coverage.py'),
176 adir, omit)
176 adir, omit)
177 vlog("# Running: "+cmd)
177 vlog("# Running: "+cmd)
178 os.system(cmd)
178 os.system(cmd)
179
179
180 class Timeout(Exception):
180 class Timeout(Exception):
181 pass
181 pass
182
182
183 def alarmed(signum, frame):
183 def alarmed(signum, frame):
184 raise Timeout
184 raise Timeout
185
185
186 def run(cmd):
186 def run(cmd):
187 """Run command in a sub-process, capturing the output (stdout and stderr).
187 """Run command in a sub-process, capturing the output (stdout and stderr).
188 Return the exist code, and output."""
188 Return the exist code, and output."""
189 # TODO: Use subprocess.Popen if we're running on Python 2.4
189 # TODO: Use subprocess.Popen if we're running on Python 2.4
190 if os.name == 'nt':
190 if os.name == 'nt':
191 tochild, fromchild = os.popen4(cmd)
191 tochild, fromchild = os.popen4(cmd)
192 tochild.close()
192 tochild.close()
193 output = fromchild.read()
193 output = fromchild.read()
194 ret = fromchild.close()
194 ret = fromchild.close()
195 if ret == None:
195 if ret == None:
196 ret = 0
196 ret = 0
197 else:
197 else:
198 proc = popen2.Popen4(cmd)
198 proc = popen2.Popen4(cmd)
199 try:
199 try:
200 output = ''
200 output = ''
201 proc.tochild.close()
201 proc.tochild.close()
202 output = proc.fromchild.read()
202 output = proc.fromchild.read()
203 ret = proc.wait()
203 ret = proc.wait()
204 except Timeout:
204 except Timeout:
205 vlog('# Process %d timed out - killing it' % proc.pid)
205 vlog('# Process %d timed out - killing it' % proc.pid)
206 os.kill(proc.pid, signal.SIGTERM)
206 os.kill(proc.pid, signal.SIGTERM)
207 ret = proc.wait()
207 ret = proc.wait()
208 if ret == 0:
208 if ret == 0:
209 ret = signal.SIGTERM << 8
209 ret = signal.SIGTERM << 8
210 return ret, splitnewlines(output)
210 return ret, splitnewlines(output)
211
211
212 def run_one(test):
212 def run_one(test):
213 '''tristate output:
213 '''tristate output:
214 None -> skipped
214 None -> skipped
215 True -> passed
215 True -> passed
216 False -> failed'''
216 False -> failed'''
217
217
218 vlog("# Test", test)
218 vlog("# Test", test)
219 if not verbose:
219 if not verbose:
220 sys.stdout.write('.')
220 sys.stdout.write('.')
221 sys.stdout.flush()
221 sys.stdout.flush()
222
222
223 # create a fresh hgrc
223 # create a fresh hgrc
224 hgrc = file(HGRCPATH, 'w+')
224 hgrc = file(HGRCPATH, 'w+')
225 hgrc.close()
225 hgrc.close()
226
226
227 err = os.path.join(TESTDIR, test+".err")
227 err = os.path.join(TESTDIR, test+".err")
228 ref = os.path.join(TESTDIR, test+".out")
228 ref = os.path.join(TESTDIR, test+".out")
229
229
230 if os.path.exists(err):
230 if os.path.exists(err):
231 os.remove(err) # Remove any previous output files
231 os.remove(err) # Remove any previous output files
232
232
233 # Make a tmp subdirectory to work in
233 # Make a tmp subdirectory to work in
234 tmpd = os.path.join(HGTMP, test)
234 tmpd = os.path.join(HGTMP, test)
235 os.mkdir(tmpd)
235 os.mkdir(tmpd)
236 os.chdir(tmpd)
236 os.chdir(tmpd)
237
237
238 lctest = test.lower()
238 lctest = test.lower()
239
239
240 if lctest.endswith('.py'):
240 if lctest.endswith('.py'):
241 cmd = '%s "%s"' % (sys.executable, os.path.join(TESTDIR, test))
241 cmd = '%s "%s"' % (sys.executable, os.path.join(TESTDIR, test))
242 elif lctest.endswith('.bat'):
242 elif lctest.endswith('.bat'):
243 # do not run batch scripts on non-windows
243 # do not run batch scripts on non-windows
244 if os.name != 'nt':
244 if os.name != 'nt':
245 print '\nSkipping %s: batch script' % test
245 print '\nSkipping %s: batch script' % test
246 return None
246 return None
247 # To reliably get the error code from batch files on WinXP,
247 # To reliably get the error code from batch files on WinXP,
248 # the "cmd /c call" prefix is needed. Grrr
248 # the "cmd /c call" prefix is needed. Grrr
249 cmd = 'cmd /c call "%s"' % (os.path.join(TESTDIR, test))
249 cmd = 'cmd /c call "%s"' % (os.path.join(TESTDIR, test))
250 else:
250 else:
251 # do not run shell scripts on windows
251 # do not run shell scripts on windows
252 if os.name == 'nt':
252 if os.name == 'nt':
253 print '\nSkipping %s: shell script' % test
253 print '\nSkipping %s: shell script' % test
254 return None
254 return None
255 # do not try to run non-executable programs
255 # do not try to run non-executable programs
256 if not os.access(os.path.join(TESTDIR, test), os.X_OK):
256 if not os.access(os.path.join(TESTDIR, test), os.X_OK):
257 print '\nSkipping %s: not executable' % test
257 print '\nSkipping %s: not executable' % test
258 return None
258 return None
259 cmd = '"%s"' % (os.path.join(TESTDIR, test))
259 cmd = '"%s"' % (os.path.join(TESTDIR, test))
260
260
261 if options.timeout > 0:
261 if options.timeout > 0:
262 signal.alarm(options.timeout)
262 signal.alarm(options.timeout)
263
263
264 vlog("# Running", cmd)
264 vlog("# Running", cmd)
265 ret, out = run(cmd)
265 ret, out = run(cmd)
266 vlog("# Ret was:", ret)
266 vlog("# Ret was:", ret)
267
267
268 if options.timeout > 0:
268 if options.timeout > 0:
269 signal.alarm(0)
269 signal.alarm(0)
270
270
271 diffret = 0
271 diffret = 0
272 # If reference output file exists, check test output against it
272 # If reference output file exists, check test output against it
273 if os.path.exists(ref):
273 if os.path.exists(ref):
274 f = open(ref, "r")
274 f = open(ref, "r")
275 ref_out = splitnewlines(f.read())
275 ref_out = splitnewlines(f.read())
276 f.close()
276 f.close()
277 else:
277 else:
278 ref_out = []
278 ref_out = []
279 if out != ref_out:
279 if out != ref_out:
280 diffret = 1
280 diffret = 1
281 print "\nERROR: %s output changed" % (test)
281 print "\nERROR: %s output changed" % (test)
282 show_diff(ref_out, out)
282 show_diff(ref_out, out)
283 if ret:
283 if ret:
284 print "\nERROR: %s failed with error code %d" % (test, ret)
284 print "\nERROR: %s failed with error code %d" % (test, ret)
285 elif diffret:
285 elif diffret:
286 ret = diffret
286 ret = diffret
287
287
288 if ret != 0: # Save errors to a file for diagnosis
288 if ret != 0: # Save errors to a file for diagnosis
289 f = open(err, "wb")
289 f = open(err, "wb")
290 for line in out:
290 for line in out:
291 f.write(line)
291 f.write(line)
292 f.close()
292 f.close()
293
293
294 # Kill off any leftover daemon processes
294 # Kill off any leftover daemon processes
295 try:
295 try:
296 fp = file(DAEMON_PIDS)
296 fp = file(DAEMON_PIDS)
297 for line in fp:
297 for line in fp:
298 try:
298 try:
299 pid = int(line)
299 pid = int(line)
300 except ValueError:
300 except ValueError:
301 continue
301 continue
302 try:
302 try:
303 os.kill(pid, 0)
303 os.kill(pid, 0)
304 vlog('# Killing daemon process %d' % pid)
304 vlog('# Killing daemon process %d' % pid)
305 os.kill(pid, signal.SIGTERM)
305 os.kill(pid, signal.SIGTERM)
306 time.sleep(0.25)
306 time.sleep(0.25)
307 os.kill(pid, 0)
307 os.kill(pid, 0)
308 vlog('# Daemon process %d is stuck - really killing it' % pid)
308 vlog('# Daemon process %d is stuck - really killing it' % pid)
309 os.kill(pid, signal.SIGKILL)
309 os.kill(pid, signal.SIGKILL)
310 except OSError, err:
310 except OSError, err:
311 if err.errno != errno.ESRCH:
311 if err.errno != errno.ESRCH:
312 raise
312 raise
313 fp.close()
313 fp.close()
314 os.unlink(DAEMON_PIDS)
314 os.unlink(DAEMON_PIDS)
315 except IOError:
315 except IOError:
316 pass
316 pass
317
317
318 os.chdir(TESTDIR)
318 os.chdir(TESTDIR)
319 shutil.rmtree(tmpd, True)
319 shutil.rmtree(tmpd, True)
320 return ret == 0
320 return ret == 0
321
321
322
322
323 os.umask(022)
323 os.umask(022)
324
324
325 check_required_tools()
325 check_required_tools()
326
326
327 # Reset some environment variables to well-known values so that
327 # Reset some environment variables to well-known values so that
328 # the tests produce repeatable output.
328 # the tests produce repeatable output.
329 os.environ['LANG'] = os.environ['LC_ALL'] = 'C'
329 os.environ['LANG'] = os.environ['LC_ALL'] = 'C'
330 os.environ['TZ'] = 'GMT'
330 os.environ['TZ'] = 'GMT'
331
331
332 os.environ["HGEDITOR"] = sys.executable + ' -c "import sys; sys.exit(0)"'
332 os.environ["HGEDITOR"] = sys.executable + ' -c "import sys; sys.exit(0)"'
333 os.environ["HGMERGE"] = sys.executable + ' -c "import sys; sys.exit(0)"'
333 os.environ["HGMERGE"] = sys.executable + ' -c "import sys; sys.exit(0)"'
334 os.environ["HGUSER"] = "test"
334 os.environ["HGUSER"] = "test"
335 os.environ["HGENCODING"] = "ascii"
336 os.environ["HGENCODINGMODE"] = "strict"
335
337
336 TESTDIR = os.environ["TESTDIR"] = os.getcwd()
338 TESTDIR = os.environ["TESTDIR"] = os.getcwd()
337 HGTMP = os.environ["HGTMP"] = tempfile.mkdtemp("", "hgtests.")
339 HGTMP = os.environ["HGTMP"] = tempfile.mkdtemp("", "hgtests.")
338 DAEMON_PIDS = os.environ["DAEMON_PIDS"] = os.path.join(HGTMP, 'daemon.pids')
340 DAEMON_PIDS = os.environ["DAEMON_PIDS"] = os.path.join(HGTMP, 'daemon.pids')
339 HGRCPATH = os.environ["HGRCPATH"] = os.path.join(HGTMP, '.hgrc')
341 HGRCPATH = os.environ["HGRCPATH"] = os.path.join(HGTMP, '.hgrc')
340
342
341 vlog("# Using TESTDIR", TESTDIR)
343 vlog("# Using TESTDIR", TESTDIR)
342 vlog("# Using HGTMP", HGTMP)
344 vlog("# Using HGTMP", HGTMP)
343
345
344 INST = os.path.join(HGTMP, "install")
346 INST = os.path.join(HGTMP, "install")
345 BINDIR = os.path.join(INST, "bin")
347 BINDIR = os.path.join(INST, "bin")
346 PYTHONDIR = os.path.join(INST, "lib", "python")
348 PYTHONDIR = os.path.join(INST, "lib", "python")
347 COVERAGE_FILE = os.path.join(TESTDIR, ".coverage")
349 COVERAGE_FILE = os.path.join(TESTDIR, ".coverage")
348
350
349 try:
351 try:
350 try:
352 try:
351 install_hg()
353 install_hg()
352
354
353 if options.timeout > 0:
355 if options.timeout > 0:
354 try:
356 try:
355 signal.signal(signal.SIGALRM, alarmed)
357 signal.signal(signal.SIGALRM, alarmed)
356 vlog('# Running tests with %d-second timeout' %
358 vlog('# Running tests with %d-second timeout' %
357 options.timeout)
359 options.timeout)
358 except AttributeError:
360 except AttributeError:
359 print 'WARNING: cannot run tests with timeouts'
361 print 'WARNING: cannot run tests with timeouts'
360 options.timeout = 0
362 options.timeout = 0
361
363
362 tested = 0
364 tested = 0
363 failed = 0
365 failed = 0
364 skipped = 0
366 skipped = 0
365
367
366 if len(args) == 0:
368 if len(args) == 0:
367 args = os.listdir(".")
369 args = os.listdir(".")
368 args.sort()
370 args.sort()
369
371
370
372
371 tests = []
373 tests = []
372 for test in args:
374 for test in args:
373 if (test.startswith("test-") and '~' not in test and
375 if (test.startswith("test-") and '~' not in test and
374 ('.' not in test or test.endswith('.py') or
376 ('.' not in test or test.endswith('.py') or
375 test.endswith('.bat'))):
377 test.endswith('.bat'))):
376 tests.append(test)
378 tests.append(test)
377
379
378 if options.restart:
380 if options.restart:
379 orig = list(tests)
381 orig = list(tests)
380 while tests:
382 while tests:
381 if os.path.exists(tests[0] + ".err"):
383 if os.path.exists(tests[0] + ".err"):
382 break
384 break
383 tests.pop(0)
385 tests.pop(0)
384 if not tests:
386 if not tests:
385 print "running all tests"
387 print "running all tests"
386 tests = orig
388 tests = orig
387
389
388 for test in tests:
390 for test in tests:
389 if options.retest and not os.path.exists(test + ".err"):
391 if options.retest and not os.path.exists(test + ".err"):
390 skipped += 1
392 skipped += 1
391 continue
393 continue
392 ret = run_one(test)
394 ret = run_one(test)
393 if ret is None:
395 if ret is None:
394 skipped += 1
396 skipped += 1
395 elif not ret:
397 elif not ret:
396 if options.interactive:
398 if options.interactive:
397 print "Accept this change? [n] ",
399 print "Accept this change? [n] ",
398 answer = sys.stdin.readline().strip()
400 answer = sys.stdin.readline().strip()
399 if answer.lower() in "y yes".split():
401 if answer.lower() in "y yes".split():
400 os.rename(test + ".err", test + ".out")
402 os.rename(test + ".err", test + ".out")
401 tested += 1
403 tested += 1
402 continue
404 continue
403 failed += 1
405 failed += 1
404 if options.first:
406 if options.first:
405 break
407 break
406 tested += 1
408 tested += 1
407
409
408 print "\n# Ran %d tests, %d skipped, %d failed." % (tested, skipped,
410 print "\n# Ran %d tests, %d skipped, %d failed." % (tested, skipped,
409 failed)
411 failed)
410 if coverage:
412 if coverage:
411 output_coverage()
413 output_coverage()
412 except KeyboardInterrupt:
414 except KeyboardInterrupt:
413 failed = True
415 failed = True
414 print "\ninterrupted!"
416 print "\ninterrupted!"
415 finally:
417 finally:
416 cleanup_exit()
418 cleanup_exit()
417
419
418 if failed:
420 if failed:
419 sys.exit(1)
421 sys.exit(1)
General Comments 0
You need to be logged in to leave comments. Login now