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