##// END OF EJS Templates
Use skipped: instead of hghave: for skipping tests, use this in test-merge-types
Thomas Arendsen Hein -
r5685:57d29a45 default
parent child Browse files
Show More
@@ -1,148 +1,148 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 """Test the running system for features availability. Exit with zero
2 """Test the running system for features availability. Exit with zero
3 if all features are there, non-zero otherwise. If a feature name is
3 if all features are there, non-zero otherwise. If a feature name is
4 prefixed with "no-", the absence of feature is tested.
4 prefixed with "no-", the absence of feature is tested.
5 """
5 """
6 import optparse
6 import optparse
7 import os
7 import os
8 import re
8 import re
9 import sys
9 import sys
10 import tempfile
10 import tempfile
11
11
12 tempprefix = 'hg-hghave-'
12 tempprefix = 'hg-hghave-'
13
13
14 def matchoutput(cmd, regexp, ignorestatus=False):
14 def matchoutput(cmd, regexp, ignorestatus=False):
15 """Return True if cmd executes successfully and its output
15 """Return True if cmd executes successfully and its output
16 is matched by the supplied regular expression.
16 is matched by the supplied regular expression.
17 """
17 """
18 r = re.compile(regexp)
18 r = re.compile(regexp)
19 fh = os.popen(cmd)
19 fh = os.popen(cmd)
20 s = fh.read()
20 s = fh.read()
21 ret = fh.close()
21 ret = fh.close()
22 return (ignorestatus or ret is None) and r.search(s)
22 return (ignorestatus or ret is None) and r.search(s)
23
23
24 def has_cvs():
24 def has_cvs():
25 return matchoutput('cvs --version 2>&1', r'Concurrent Versions System')
25 return matchoutput('cvs --version 2>&1', r'Concurrent Versions System')
26
26
27 def has_cvsps():
27 def has_cvsps():
28 return matchoutput('cvsps -h -q 2>&1', r'cvsps version', True)
28 return matchoutput('cvsps -h -q 2>&1', r'cvsps version', True)
29
29
30 def has_darcs():
30 def has_darcs():
31 return matchoutput('darcs', 'darcs version', True)
31 return matchoutput('darcs', 'darcs version', True)
32
32
33 def has_eol_in_paths():
33 def has_eol_in_paths():
34 try:
34 try:
35 fd, path = tempfile.mkstemp(prefix=tempprefix, suffix='\n\r')
35 fd, path = tempfile.mkstemp(prefix=tempprefix, suffix='\n\r')
36 os.close(fd)
36 os.close(fd)
37 os.remove(path)
37 os.remove(path)
38 return True
38 return True
39 except:
39 except:
40 return False
40 return False
41
41
42 def has_executablebit():
42 def has_executablebit():
43 fd, path = tempfile.mkstemp(prefix=tempprefix)
43 fd, path = tempfile.mkstemp(prefix=tempprefix)
44 os.close(fd)
44 os.close(fd)
45 try:
45 try:
46 s = os.lstat(path).st_mode
46 s = os.lstat(path).st_mode
47 os.chmod(path, s | 0100)
47 os.chmod(path, s | 0100)
48 return (os.lstat(path).st_mode & 0100 != 0)
48 return (os.lstat(path).st_mode & 0100 != 0)
49 finally:
49 finally:
50 os.remove(path)
50 os.remove(path)
51
51
52 def has_fifo():
52 def has_fifo():
53 return hasattr(os, "mkfifo")
53 return hasattr(os, "mkfifo")
54
54
55 def has_hotshot():
55 def has_hotshot():
56 try:
56 try:
57 # hotshot.stats tests hotshot and many problematic dependencies
57 # hotshot.stats tests hotshot and many problematic dependencies
58 # like profile.
58 # like profile.
59 import hotshot.stats
59 import hotshot.stats
60 return True
60 return True
61 except ImportError:
61 except ImportError:
62 return False
62 return False
63
63
64 def has_lsprof():
64 def has_lsprof():
65 try:
65 try:
66 import _lsprof
66 import _lsprof
67 return True
67 return True
68 except ImportError:
68 except ImportError:
69 return False
69 return False
70
70
71 def has_git():
71 def has_git():
72 return matchoutput('git --version 2>&1', r'^git version')
72 return matchoutput('git --version 2>&1', r'^git version')
73
73
74 def has_svn():
74 def has_svn():
75 return matchoutput('svn --version 2>&1', r'^svn, version') and \
75 return matchoutput('svn --version 2>&1', r'^svn, version') and \
76 matchoutput('svnadmin --version 2>&1', r'^svnadmin, version')
76 matchoutput('svnadmin --version 2>&1', r'^svnadmin, version')
77
77
78 def has_svn_bindings():
78 def has_svn_bindings():
79 try:
79 try:
80 import svn.core
80 import svn.core
81 return True
81 return True
82 except ImportError:
82 except ImportError:
83 return False
83 return False
84
84
85 def has_symlink():
85 def has_symlink():
86 return hasattr(os, "symlink")
86 return hasattr(os, "symlink")
87
87
88 checks = {
88 checks = {
89 "cvs": (has_cvs, "cvs client"),
89 "cvs": (has_cvs, "cvs client"),
90 "cvsps": (has_cvsps, "cvsps utility"),
90 "cvsps": (has_cvsps, "cvsps utility"),
91 "darcs": (has_darcs, "darcs client"),
91 "darcs": (has_darcs, "darcs client"),
92 "eol-in-paths": (has_eol_in_paths, "end-of-lines in paths"),
92 "eol-in-paths": (has_eol_in_paths, "end-of-lines in paths"),
93 "execbit": (has_executablebit, "executable bit"),
93 "execbit": (has_executablebit, "executable bit"),
94 "fifo": (has_fifo, "named pipes"),
94 "fifo": (has_fifo, "named pipes"),
95 "git": (has_git, "git command line client"),
95 "git": (has_git, "git command line client"),
96 "hotshot": (has_hotshot, "python hotshot module"),
96 "hotshot": (has_hotshot, "python hotshot module"),
97 "lsprof": (has_lsprof, "python lsprof module"),
97 "lsprof": (has_lsprof, "python lsprof module"),
98 "svn": (has_svn, "subversion client and admin tools"),
98 "svn": (has_svn, "subversion client and admin tools"),
99 "svn-bindings": (has_svn_bindings, "subversion python bindings"),
99 "svn-bindings": (has_svn_bindings, "subversion python bindings"),
100 "symlink": (has_symlink, "symbolic links"),
100 "symlink": (has_symlink, "symbolic links"),
101 }
101 }
102
102
103 def list_features():
103 def list_features():
104 for name, feature in checks.iteritems():
104 for name, feature in checks.iteritems():
105 desc = feature[1]
105 desc = feature[1]
106 print name + ':', desc
106 print name + ':', desc
107
107
108 parser = optparse.OptionParser("%prog [options] [features]")
108 parser = optparse.OptionParser("%prog [options] [features]")
109 parser.add_option("--list-features", action="store_true",
109 parser.add_option("--list-features", action="store_true",
110 help="list available features")
110 help="list available features")
111 parser.add_option("-q", "--quiet", action="store_true",
111 parser.add_option("-q", "--quiet", action="store_true",
112 help="check features silently")
112 help="check features silently")
113
113
114 if __name__ == '__main__':
114 if __name__ == '__main__':
115 options, args = parser.parse_args()
115 options, args = parser.parse_args()
116 if options.list_features:
116 if options.list_features:
117 list_features()
117 list_features()
118 sys.exit(0)
118 sys.exit(0)
119
119
120 quiet = options.quiet
120 quiet = options.quiet
121
121
122 failures = 0
122 failures = 0
123
123
124 def error(msg):
124 def error(msg):
125 global failures
125 global failures
126 if not quiet:
126 if not quiet:
127 sys.stderr.write(msg + '\n')
127 sys.stderr.write(msg + '\n')
128 failures += 1
128 failures += 1
129
129
130 for feature in args:
130 for feature in args:
131 negate = feature.startswith('no-')
131 negate = feature.startswith('no-')
132 if negate:
132 if negate:
133 feature = feature[3:]
133 feature = feature[3:]
134
134
135 if feature not in checks:
135 if feature not in checks:
136 error('hghave: unknown feature: ' + feature)
136 error('skipped: unknown feature: ' + feature)
137 continue
137 continue
138
138
139 check, desc = checks[feature]
139 check, desc = checks[feature]
140 if not negate and not check():
140 if not negate and not check():
141 error('hghave: missing feature: ' + desc)
141 error('skipped: missing feature: ' + desc)
142 elif negate and check():
142 elif negate and check():
143 error('hghave: system supports %s' % desc)
143 error('skipped: system supports %s' % desc)
144
144
145 if failures != 0:
145 if failures != 0:
146 sys.exit(1)
146 sys.exit(1)
147
147
148
148
@@ -1,581 +1,582 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
22 # reserved exit code to skip test (used by hghave)
23 SKIPPED_STATUS = 80
23 SKIPPED_STATUS = 80
24 SKIPPED_PREFIX = 'skipped: '
24
25
25 required_tools = ["python", "diff", "grep", "unzip", "gunzip", "bunzip2", "sed"]
26 required_tools = ["python", "diff", "grep", "unzip", "gunzip", "bunzip2", "sed"]
26
27
27 parser = optparse.OptionParser("%prog [options] [tests]")
28 parser = optparse.OptionParser("%prog [options] [tests]")
28 parser.add_option("-C", "--annotate", action="store_true",
29 parser.add_option("-C", "--annotate", action="store_true",
29 help="output files annotated with coverage")
30 help="output files annotated with coverage")
30 parser.add_option("--child", type="int",
31 parser.add_option("--child", type="int",
31 help="run as child process, summary to given fd")
32 help="run as child process, summary to given fd")
32 parser.add_option("-c", "--cover", action="store_true",
33 parser.add_option("-c", "--cover", action="store_true",
33 help="print a test coverage report")
34 help="print a test coverage report")
34 parser.add_option("-f", "--first", action="store_true",
35 parser.add_option("-f", "--first", action="store_true",
35 help="exit on the first test failure")
36 help="exit on the first test failure")
36 parser.add_option("-i", "--interactive", action="store_true",
37 parser.add_option("-i", "--interactive", action="store_true",
37 help="prompt to accept changed output")
38 help="prompt to accept changed output")
38 parser.add_option("-j", "--jobs", type="int",
39 parser.add_option("-j", "--jobs", type="int",
39 help="number of jobs to run in parallel")
40 help="number of jobs to run in parallel")
40 parser.add_option("-R", "--restart", action="store_true",
41 parser.add_option("-R", "--restart", action="store_true",
41 help="restart at last error")
42 help="restart at last error")
42 parser.add_option("-p", "--port", type="int",
43 parser.add_option("-p", "--port", type="int",
43 help="port on which servers should listen")
44 help="port on which servers should listen")
44 parser.add_option("-r", "--retest", action="store_true",
45 parser.add_option("-r", "--retest", action="store_true",
45 help="retest failed tests")
46 help="retest failed tests")
46 parser.add_option("-s", "--cover_stdlib", action="store_true",
47 parser.add_option("-s", "--cover_stdlib", action="store_true",
47 help="print a test coverage report inc. standard libraries")
48 help="print a test coverage report inc. standard libraries")
48 parser.add_option("-t", "--timeout", type="int",
49 parser.add_option("-t", "--timeout", type="int",
49 help="kill errant tests after TIMEOUT seconds")
50 help="kill errant tests after TIMEOUT seconds")
50 parser.add_option("--tmpdir", type="string",
51 parser.add_option("--tmpdir", type="string",
51 help="run tests in the given temporary directory")
52 help="run tests in the given temporary directory")
52 parser.add_option("-v", "--verbose", action="store_true",
53 parser.add_option("-v", "--verbose", action="store_true",
53 help="output verbose messages")
54 help="output verbose messages")
54 parser.add_option("--with-hg", type="string",
55 parser.add_option("--with-hg", type="string",
55 help="test existing install at given location")
56 help="test existing install at given location")
56
57
57 parser.set_defaults(jobs=1, port=20059, timeout=180)
58 parser.set_defaults(jobs=1, port=20059, timeout=180)
58 (options, args) = parser.parse_args()
59 (options, args) = parser.parse_args()
59 verbose = options.verbose
60 verbose = options.verbose
60 coverage = options.cover or options.cover_stdlib or options.annotate
61 coverage = options.cover or options.cover_stdlib or options.annotate
61 python = sys.executable
62 python = sys.executable
62
63
63 if options.jobs < 1:
64 if options.jobs < 1:
64 print >> sys.stderr, 'ERROR: -j/--jobs must be positive'
65 print >> sys.stderr, 'ERROR: -j/--jobs must be positive'
65 sys.exit(1)
66 sys.exit(1)
66 if options.interactive and options.jobs > 1:
67 if options.interactive and options.jobs > 1:
67 print >> sys.stderr, 'ERROR: cannot mix -interactive and --jobs > 1'
68 print >> sys.stderr, 'ERROR: cannot mix -interactive and --jobs > 1'
68 sys.exit(1)
69 sys.exit(1)
69
70
70 def vlog(*msg):
71 def vlog(*msg):
71 if verbose:
72 if verbose:
72 for m in msg:
73 for m in msg:
73 print m,
74 print m,
74 print
75 print
75
76
76 def splitnewlines(text):
77 def splitnewlines(text):
77 '''like str.splitlines, but only split on newlines.
78 '''like str.splitlines, but only split on newlines.
78 keep line endings.'''
79 keep line endings.'''
79 i = 0
80 i = 0
80 lines = []
81 lines = []
81 while True:
82 while True:
82 n = text.find('\n', i)
83 n = text.find('\n', i)
83 if n == -1:
84 if n == -1:
84 last = text[i:]
85 last = text[i:]
85 if last:
86 if last:
86 lines.append(last)
87 lines.append(last)
87 return lines
88 return lines
88 lines.append(text[i:n+1])
89 lines.append(text[i:n+1])
89 i = n + 1
90 i = n + 1
90
91
91 def extract_missing_features(lines):
92 def extract_missing_features(lines):
92 '''Extract missing/unknown features log lines as a list'''
93 '''Extract missing/unknown features log lines as a list'''
93 missing = []
94 missing = []
94 for line in lines:
95 for line in lines:
95 if not line.startswith('hghave: '):
96 if not line.startswith(SKIPPED_PREFIX):
96 continue
97 continue
97 line = line.splitlines()[0]
98 line = line.splitlines()[0]
98 missing.append(line[8:])
99 missing.append(line[len(SKIPPED_PREFIX):])
99
100
100 return missing
101 return missing
101
102
102 def show_diff(expected, output):
103 def show_diff(expected, output):
103 for line in difflib.unified_diff(expected, output,
104 for line in difflib.unified_diff(expected, output,
104 "Expected output", "Test output"):
105 "Expected output", "Test output"):
105 sys.stdout.write(line)
106 sys.stdout.write(line)
106
107
107 def find_program(program):
108 def find_program(program):
108 """Search PATH for a executable program"""
109 """Search PATH for a executable program"""
109 for p in os.environ.get('PATH', os.defpath).split(os.pathsep):
110 for p in os.environ.get('PATH', os.defpath).split(os.pathsep):
110 name = os.path.join(p, program)
111 name = os.path.join(p, program)
111 if os.access(name, os.X_OK):
112 if os.access(name, os.X_OK):
112 return name
113 return name
113 return None
114 return None
114
115
115 def check_required_tools():
116 def check_required_tools():
116 # Before we go any further, check for pre-requisite tools
117 # Before we go any further, check for pre-requisite tools
117 # stuff from coreutils (cat, rm, etc) are not tested
118 # stuff from coreutils (cat, rm, etc) are not tested
118 for p in required_tools:
119 for p in required_tools:
119 if os.name == 'nt':
120 if os.name == 'nt':
120 p += '.exe'
121 p += '.exe'
121 found = find_program(p)
122 found = find_program(p)
122 if found:
123 if found:
123 vlog("# Found prerequisite", p, "at", found)
124 vlog("# Found prerequisite", p, "at", found)
124 else:
125 else:
125 print "WARNING: Did not find prerequisite tool: "+p
126 print "WARNING: Did not find prerequisite tool: "+p
126
127
127 def cleanup_exit():
128 def cleanup_exit():
128 if verbose:
129 if verbose:
129 print "# Cleaning up HGTMP", HGTMP
130 print "# Cleaning up HGTMP", HGTMP
130 shutil.rmtree(HGTMP, True)
131 shutil.rmtree(HGTMP, True)
131
132
132 def use_correct_python():
133 def use_correct_python():
133 # some tests run python interpreter. they must use same
134 # some tests run python interpreter. they must use same
134 # interpreter we use or bad things will happen.
135 # interpreter we use or bad things will happen.
135 exedir, exename = os.path.split(sys.executable)
136 exedir, exename = os.path.split(sys.executable)
136 if exename == 'python':
137 if exename == 'python':
137 path = find_program('python')
138 path = find_program('python')
138 if os.path.dirname(path) == exedir:
139 if os.path.dirname(path) == exedir:
139 return
140 return
140 vlog('# Making python executable in test path use correct Python')
141 vlog('# Making python executable in test path use correct Python')
141 my_python = os.path.join(BINDIR, 'python')
142 my_python = os.path.join(BINDIR, 'python')
142 try:
143 try:
143 os.symlink(sys.executable, my_python)
144 os.symlink(sys.executable, my_python)
144 except AttributeError:
145 except AttributeError:
145 # windows fallback
146 # windows fallback
146 shutil.copyfile(sys.executable, my_python)
147 shutil.copyfile(sys.executable, my_python)
147 shutil.copymode(sys.executable, my_python)
148 shutil.copymode(sys.executable, my_python)
148
149
149 def install_hg():
150 def install_hg():
150 global python
151 global python
151 vlog("# Performing temporary installation of HG")
152 vlog("# Performing temporary installation of HG")
152 installerrs = os.path.join("tests", "install.err")
153 installerrs = os.path.join("tests", "install.err")
153
154
154 # Run installer in hg root
155 # Run installer in hg root
155 os.chdir(os.path.join(os.path.dirname(sys.argv[0]), '..'))
156 os.chdir(os.path.join(os.path.dirname(sys.argv[0]), '..'))
156 cmd = ('%s setup.py clean --all'
157 cmd = ('%s setup.py clean --all'
157 ' install --force --home="%s" --install-lib="%s"'
158 ' install --force --home="%s" --install-lib="%s"'
158 ' --install-scripts="%s" >%s 2>&1'
159 ' --install-scripts="%s" >%s 2>&1'
159 % (sys.executable, INST, PYTHONDIR, BINDIR, installerrs))
160 % (sys.executable, INST, PYTHONDIR, BINDIR, installerrs))
160 vlog("# Running", cmd)
161 vlog("# Running", cmd)
161 if os.system(cmd) == 0:
162 if os.system(cmd) == 0:
162 if not verbose:
163 if not verbose:
163 os.remove(installerrs)
164 os.remove(installerrs)
164 else:
165 else:
165 f = open(installerrs)
166 f = open(installerrs)
166 for line in f:
167 for line in f:
167 print line,
168 print line,
168 f.close()
169 f.close()
169 sys.exit(1)
170 sys.exit(1)
170 os.chdir(TESTDIR)
171 os.chdir(TESTDIR)
171
172
172 os.environ["PATH"] = "%s%s%s" % (BINDIR, os.pathsep, os.environ["PATH"])
173 os.environ["PATH"] = "%s%s%s" % (BINDIR, os.pathsep, os.environ["PATH"])
173
174
174 pydir = os.pathsep.join([PYTHONDIR, TESTDIR])
175 pydir = os.pathsep.join([PYTHONDIR, TESTDIR])
175 pythonpath = os.environ.get("PYTHONPATH")
176 pythonpath = os.environ.get("PYTHONPATH")
176 if pythonpath:
177 if pythonpath:
177 pythonpath = pydir + os.pathsep + pythonpath
178 pythonpath = pydir + os.pathsep + pythonpath
178 else:
179 else:
179 pythonpath = pydir
180 pythonpath = pydir
180 os.environ["PYTHONPATH"] = pythonpath
181 os.environ["PYTHONPATH"] = pythonpath
181
182
182 use_correct_python()
183 use_correct_python()
183
184
184 if coverage:
185 if coverage:
185 vlog("# Installing coverage wrapper")
186 vlog("# Installing coverage wrapper")
186 os.environ['COVERAGE_FILE'] = COVERAGE_FILE
187 os.environ['COVERAGE_FILE'] = COVERAGE_FILE
187 if os.path.exists(COVERAGE_FILE):
188 if os.path.exists(COVERAGE_FILE):
188 os.unlink(COVERAGE_FILE)
189 os.unlink(COVERAGE_FILE)
189 # Create a wrapper script to invoke hg via coverage.py
190 # Create a wrapper script to invoke hg via coverage.py
190 os.rename(os.path.join(BINDIR, "hg"), os.path.join(BINDIR, "_hg.py"))
191 os.rename(os.path.join(BINDIR, "hg"), os.path.join(BINDIR, "_hg.py"))
191 f = open(os.path.join(BINDIR, 'hg'), 'w')
192 f = open(os.path.join(BINDIR, 'hg'), 'w')
192 f.write('#!' + sys.executable + '\n')
193 f.write('#!' + sys.executable + '\n')
193 f.write('import sys, os; os.execv(sys.executable, [sys.executable, '
194 f.write('import sys, os; os.execv(sys.executable, [sys.executable, '
194 '"%s", "-x", "%s"] + sys.argv[1:])\n' %
195 '"%s", "-x", "%s"] + sys.argv[1:])\n' %
195 (os.path.join(TESTDIR, 'coverage.py'),
196 (os.path.join(TESTDIR, 'coverage.py'),
196 os.path.join(BINDIR, '_hg.py')))
197 os.path.join(BINDIR, '_hg.py')))
197 f.close()
198 f.close()
198 os.chmod(os.path.join(BINDIR, 'hg'), 0700)
199 os.chmod(os.path.join(BINDIR, 'hg'), 0700)
199 python = '"%s" "%s" -x' % (sys.executable,
200 python = '"%s" "%s" -x' % (sys.executable,
200 os.path.join(TESTDIR,'coverage.py'))
201 os.path.join(TESTDIR,'coverage.py'))
201
202
202 def output_coverage():
203 def output_coverage():
203 vlog("# Producing coverage report")
204 vlog("# Producing coverage report")
204 omit = [BINDIR, TESTDIR, PYTHONDIR]
205 omit = [BINDIR, TESTDIR, PYTHONDIR]
205 if not options.cover_stdlib:
206 if not options.cover_stdlib:
206 # Exclude as system paths (ignoring empty strings seen on win)
207 # Exclude as system paths (ignoring empty strings seen on win)
207 omit += [x for x in sys.path if x != '']
208 omit += [x for x in sys.path if x != '']
208 omit = ','.join(omit)
209 omit = ','.join(omit)
209 os.chdir(PYTHONDIR)
210 os.chdir(PYTHONDIR)
210 cmd = '"%s" "%s" -i -r "--omit=%s"' % (
211 cmd = '"%s" "%s" -i -r "--omit=%s"' % (
211 sys.executable, os.path.join(TESTDIR, 'coverage.py'), omit)
212 sys.executable, os.path.join(TESTDIR, 'coverage.py'), omit)
212 vlog("# Running: "+cmd)
213 vlog("# Running: "+cmd)
213 os.system(cmd)
214 os.system(cmd)
214 if options.annotate:
215 if options.annotate:
215 adir = os.path.join(TESTDIR, 'annotated')
216 adir = os.path.join(TESTDIR, 'annotated')
216 if not os.path.isdir(adir):
217 if not os.path.isdir(adir):
217 os.mkdir(adir)
218 os.mkdir(adir)
218 cmd = '"%s" "%s" -i -a "--directory=%s" "--omit=%s"' % (
219 cmd = '"%s" "%s" -i -a "--directory=%s" "--omit=%s"' % (
219 sys.executable, os.path.join(TESTDIR, 'coverage.py'),
220 sys.executable, os.path.join(TESTDIR, 'coverage.py'),
220 adir, omit)
221 adir, omit)
221 vlog("# Running: "+cmd)
222 vlog("# Running: "+cmd)
222 os.system(cmd)
223 os.system(cmd)
223
224
224 class Timeout(Exception):
225 class Timeout(Exception):
225 pass
226 pass
226
227
227 def alarmed(signum, frame):
228 def alarmed(signum, frame):
228 raise Timeout
229 raise Timeout
229
230
230 def run(cmd):
231 def run(cmd):
231 """Run command in a sub-process, capturing the output (stdout and stderr).
232 """Run command in a sub-process, capturing the output (stdout and stderr).
232 Return the exist code, and output."""
233 Return the exist code, and output."""
233 # TODO: Use subprocess.Popen if we're running on Python 2.4
234 # TODO: Use subprocess.Popen if we're running on Python 2.4
234 if os.name == 'nt':
235 if os.name == 'nt':
235 tochild, fromchild = os.popen4(cmd)
236 tochild, fromchild = os.popen4(cmd)
236 tochild.close()
237 tochild.close()
237 output = fromchild.read()
238 output = fromchild.read()
238 ret = fromchild.close()
239 ret = fromchild.close()
239 if ret == None:
240 if ret == None:
240 ret = 0
241 ret = 0
241 else:
242 else:
242 proc = popen2.Popen4(cmd)
243 proc = popen2.Popen4(cmd)
243 try:
244 try:
244 output = ''
245 output = ''
245 proc.tochild.close()
246 proc.tochild.close()
246 output = proc.fromchild.read()
247 output = proc.fromchild.read()
247 ret = proc.wait()
248 ret = proc.wait()
248 if os.WIFEXITED(ret):
249 if os.WIFEXITED(ret):
249 ret = os.WEXITSTATUS(ret)
250 ret = os.WEXITSTATUS(ret)
250 except Timeout:
251 except Timeout:
251 vlog('# Process %d timed out - killing it' % proc.pid)
252 vlog('# Process %d timed out - killing it' % proc.pid)
252 os.kill(proc.pid, signal.SIGTERM)
253 os.kill(proc.pid, signal.SIGTERM)
253 ret = proc.wait()
254 ret = proc.wait()
254 if ret == 0:
255 if ret == 0:
255 ret = signal.SIGTERM << 8
256 ret = signal.SIGTERM << 8
256 output += ("\n### Abort: timeout after %d seconds.\n"
257 output += ("\n### Abort: timeout after %d seconds.\n"
257 % options.timeout)
258 % options.timeout)
258 return ret, splitnewlines(output)
259 return ret, splitnewlines(output)
259
260
260 def run_one(test, skips):
261 def run_one(test, skips):
261 '''tristate output:
262 '''tristate output:
262 None -> skipped
263 None -> skipped
263 True -> passed
264 True -> passed
264 False -> failed'''
265 False -> failed'''
265
266
266 def skip(msg):
267 def skip(msg):
267 if not verbose:
268 if not verbose:
268 skips.append((test, msg))
269 skips.append((test, msg))
269 else:
270 else:
270 print "\nSkipping %s: %s" % (test, msg)
271 print "\nSkipping %s: %s" % (test, msg)
271 return None
272 return None
272
273
273 vlog("# Test", test)
274 vlog("# Test", test)
274
275
275 # create a fresh hgrc
276 # create a fresh hgrc
276 hgrc = file(HGRCPATH, 'w+')
277 hgrc = file(HGRCPATH, 'w+')
277 hgrc.write('[ui]\n')
278 hgrc.write('[ui]\n')
278 hgrc.write('slash = True\n')
279 hgrc.write('slash = True\n')
279 hgrc.write('[defaults]\n')
280 hgrc.write('[defaults]\n')
280 hgrc.write('backout = -d "0 0"\n')
281 hgrc.write('backout = -d "0 0"\n')
281 hgrc.write('commit = -d "0 0"\n')
282 hgrc.write('commit = -d "0 0"\n')
282 hgrc.write('debugrawcommit = -d "0 0"\n')
283 hgrc.write('debugrawcommit = -d "0 0"\n')
283 hgrc.write('tag = -d "0 0"\n')
284 hgrc.write('tag = -d "0 0"\n')
284 hgrc.close()
285 hgrc.close()
285
286
286 err = os.path.join(TESTDIR, test+".err")
287 err = os.path.join(TESTDIR, test+".err")
287 ref = os.path.join(TESTDIR, test+".out")
288 ref = os.path.join(TESTDIR, test+".out")
288 testpath = os.path.join(TESTDIR, test)
289 testpath = os.path.join(TESTDIR, test)
289
290
290 if os.path.exists(err):
291 if os.path.exists(err):
291 os.remove(err) # Remove any previous output files
292 os.remove(err) # Remove any previous output files
292
293
293 # Make a tmp subdirectory to work in
294 # Make a tmp subdirectory to work in
294 tmpd = os.path.join(HGTMP, test)
295 tmpd = os.path.join(HGTMP, test)
295 os.mkdir(tmpd)
296 os.mkdir(tmpd)
296 os.chdir(tmpd)
297 os.chdir(tmpd)
297
298
298 try:
299 try:
299 tf = open(testpath)
300 tf = open(testpath)
300 firstline = tf.readline().rstrip()
301 firstline = tf.readline().rstrip()
301 tf.close()
302 tf.close()
302 except:
303 except:
303 firstline = ''
304 firstline = ''
304 lctest = test.lower()
305 lctest = test.lower()
305
306
306 if lctest.endswith('.py') or firstline == '#!/usr/bin/env python':
307 if lctest.endswith('.py') or firstline == '#!/usr/bin/env python':
307 cmd = '%s "%s"' % (python, testpath)
308 cmd = '%s "%s"' % (python, testpath)
308 elif lctest.endswith('.bat'):
309 elif lctest.endswith('.bat'):
309 # do not run batch scripts on non-windows
310 # do not run batch scripts on non-windows
310 if os.name != 'nt':
311 if os.name != 'nt':
311 return skip("batch script")
312 return skip("batch script")
312 # To reliably get the error code from batch files on WinXP,
313 # To reliably get the error code from batch files on WinXP,
313 # the "cmd /c call" prefix is needed. Grrr
314 # the "cmd /c call" prefix is needed. Grrr
314 cmd = 'cmd /c call "%s"' % testpath
315 cmd = 'cmd /c call "%s"' % testpath
315 else:
316 else:
316 # do not run shell scripts on windows
317 # do not run shell scripts on windows
317 if os.name == 'nt':
318 if os.name == 'nt':
318 return skip("shell script")
319 return skip("shell script")
319 # do not try to run non-executable programs
320 # do not try to run non-executable programs
320 if not os.access(testpath, os.X_OK):
321 if not os.access(testpath, os.X_OK):
321 return skip("not executable")
322 return skip("not executable")
322 cmd = '"%s"' % testpath
323 cmd = '"%s"' % testpath
323
324
324 if options.timeout > 0:
325 if options.timeout > 0:
325 signal.alarm(options.timeout)
326 signal.alarm(options.timeout)
326
327
327 vlog("# Running", cmd)
328 vlog("# Running", cmd)
328 ret, out = run(cmd)
329 ret, out = run(cmd)
329 vlog("# Ret was:", ret)
330 vlog("# Ret was:", ret)
330
331
331 if options.timeout > 0:
332 if options.timeout > 0:
332 signal.alarm(0)
333 signal.alarm(0)
333
334
334 skipped = (ret == SKIPPED_STATUS)
335 skipped = (ret == SKIPPED_STATUS)
335 diffret = 0
336 diffret = 0
336 # If reference output file exists, check test output against it
337 # If reference output file exists, check test output against it
337 if os.path.exists(ref):
338 if os.path.exists(ref):
338 f = open(ref, "r")
339 f = open(ref, "r")
339 ref_out = splitnewlines(f.read())
340 ref_out = splitnewlines(f.read())
340 f.close()
341 f.close()
341 else:
342 else:
342 ref_out = []
343 ref_out = []
343 if not skipped and out != ref_out:
344 if not skipped and out != ref_out:
344 diffret = 1
345 diffret = 1
345 print "\nERROR: %s output changed" % (test)
346 print "\nERROR: %s output changed" % (test)
346 show_diff(ref_out, out)
347 show_diff(ref_out, out)
347 if skipped:
348 if skipped:
348 missing = extract_missing_features(out)
349 missing = extract_missing_features(out)
349 if not missing:
350 if not missing:
350 missing = ['irrelevant']
351 missing = ['irrelevant']
351 skip(missing[-1])
352 skip(missing[-1])
352 elif ret:
353 elif ret:
353 print "\nERROR: %s failed with error code %d" % (test, ret)
354 print "\nERROR: %s failed with error code %d" % (test, ret)
354 elif diffret:
355 elif diffret:
355 ret = diffret
356 ret = diffret
356
357
357 if not verbose:
358 if not verbose:
358 sys.stdout.write(skipped and 's' or '.')
359 sys.stdout.write(skipped and 's' or '.')
359 sys.stdout.flush()
360 sys.stdout.flush()
360
361
361 if ret != 0 and not skipped:
362 if ret != 0 and not skipped:
362 # Save errors to a file for diagnosis
363 # Save errors to a file for diagnosis
363 f = open(err, "wb")
364 f = open(err, "wb")
364 for line in out:
365 for line in out:
365 f.write(line)
366 f.write(line)
366 f.close()
367 f.close()
367
368
368 # Kill off any leftover daemon processes
369 # Kill off any leftover daemon processes
369 try:
370 try:
370 fp = file(DAEMON_PIDS)
371 fp = file(DAEMON_PIDS)
371 for line in fp:
372 for line in fp:
372 try:
373 try:
373 pid = int(line)
374 pid = int(line)
374 except ValueError:
375 except ValueError:
375 continue
376 continue
376 try:
377 try:
377 os.kill(pid, 0)
378 os.kill(pid, 0)
378 vlog('# Killing daemon process %d' % pid)
379 vlog('# Killing daemon process %d' % pid)
379 os.kill(pid, signal.SIGTERM)
380 os.kill(pid, signal.SIGTERM)
380 time.sleep(0.25)
381 time.sleep(0.25)
381 os.kill(pid, 0)
382 os.kill(pid, 0)
382 vlog('# Daemon process %d is stuck - really killing it' % pid)
383 vlog('# Daemon process %d is stuck - really killing it' % pid)
383 os.kill(pid, signal.SIGKILL)
384 os.kill(pid, signal.SIGKILL)
384 except OSError, err:
385 except OSError, err:
385 if err.errno != errno.ESRCH:
386 if err.errno != errno.ESRCH:
386 raise
387 raise
387 fp.close()
388 fp.close()
388 os.unlink(DAEMON_PIDS)
389 os.unlink(DAEMON_PIDS)
389 except IOError:
390 except IOError:
390 pass
391 pass
391
392
392 os.chdir(TESTDIR)
393 os.chdir(TESTDIR)
393 shutil.rmtree(tmpd, True)
394 shutil.rmtree(tmpd, True)
394 if skipped:
395 if skipped:
395 return None
396 return None
396 return ret == 0
397 return ret == 0
397
398
398 if not options.child:
399 if not options.child:
399 os.umask(022)
400 os.umask(022)
400
401
401 check_required_tools()
402 check_required_tools()
402
403
403 # Reset some environment variables to well-known values so that
404 # Reset some environment variables to well-known values so that
404 # the tests produce repeatable output.
405 # the tests produce repeatable output.
405 os.environ['LANG'] = os.environ['LC_ALL'] = 'C'
406 os.environ['LANG'] = os.environ['LC_ALL'] = 'C'
406 os.environ['TZ'] = 'GMT'
407 os.environ['TZ'] = 'GMT'
407
408
408 TESTDIR = os.environ["TESTDIR"] = os.getcwd()
409 TESTDIR = os.environ["TESTDIR"] = os.getcwd()
409 HGTMP = os.environ['HGTMP'] = tempfile.mkdtemp('', 'hgtests.', options.tmpdir)
410 HGTMP = os.environ['HGTMP'] = tempfile.mkdtemp('', 'hgtests.', options.tmpdir)
410 DAEMON_PIDS = None
411 DAEMON_PIDS = None
411 HGRCPATH = None
412 HGRCPATH = None
412
413
413 os.environ["HGEDITOR"] = sys.executable + ' -c "import sys; sys.exit(0)"'
414 os.environ["HGEDITOR"] = sys.executable + ' -c "import sys; sys.exit(0)"'
414 os.environ["HGMERGE"] = ('python "%s" -L my -L other'
415 os.environ["HGMERGE"] = ('python "%s" -L my -L other'
415 % os.path.join(TESTDIR, os.path.pardir,
416 % os.path.join(TESTDIR, os.path.pardir,
416 'contrib', 'simplemerge'))
417 'contrib', 'simplemerge'))
417 os.environ["HGUSER"] = "test"
418 os.environ["HGUSER"] = "test"
418 os.environ["HGENCODING"] = "ascii"
419 os.environ["HGENCODING"] = "ascii"
419 os.environ["HGENCODINGMODE"] = "strict"
420 os.environ["HGENCODINGMODE"] = "strict"
420 os.environ["HGPORT"] = str(options.port)
421 os.environ["HGPORT"] = str(options.port)
421 os.environ["HGPORT1"] = str(options.port + 1)
422 os.environ["HGPORT1"] = str(options.port + 1)
422 os.environ["HGPORT2"] = str(options.port + 2)
423 os.environ["HGPORT2"] = str(options.port + 2)
423
424
424 if options.with_hg:
425 if options.with_hg:
425 INST = options.with_hg
426 INST = options.with_hg
426 else:
427 else:
427 INST = os.path.join(HGTMP, "install")
428 INST = os.path.join(HGTMP, "install")
428 BINDIR = os.path.join(INST, "bin")
429 BINDIR = os.path.join(INST, "bin")
429 PYTHONDIR = os.path.join(INST, "lib", "python")
430 PYTHONDIR = os.path.join(INST, "lib", "python")
430 COVERAGE_FILE = os.path.join(TESTDIR, ".coverage")
431 COVERAGE_FILE = os.path.join(TESTDIR, ".coverage")
431
432
432 def run_children(tests):
433 def run_children(tests):
433 if not options.with_hg:
434 if not options.with_hg:
434 install_hg()
435 install_hg()
435
436
436 optcopy = dict(options.__dict__)
437 optcopy = dict(options.__dict__)
437 optcopy['jobs'] = 1
438 optcopy['jobs'] = 1
438 optcopy['with_hg'] = INST
439 optcopy['with_hg'] = INST
439 opts = []
440 opts = []
440 for opt, value in optcopy.iteritems():
441 for opt, value in optcopy.iteritems():
441 name = '--' + opt.replace('_', '-')
442 name = '--' + opt.replace('_', '-')
442 if value is True:
443 if value is True:
443 opts.append(name)
444 opts.append(name)
444 elif value is not None:
445 elif value is not None:
445 opts.append(name + '=' + str(value))
446 opts.append(name + '=' + str(value))
446
447
447 tests.reverse()
448 tests.reverse()
448 jobs = [[] for j in xrange(options.jobs)]
449 jobs = [[] for j in xrange(options.jobs)]
449 while tests:
450 while tests:
450 for j in xrange(options.jobs):
451 for j in xrange(options.jobs):
451 if not tests: break
452 if not tests: break
452 jobs[j].append(tests.pop())
453 jobs[j].append(tests.pop())
453 fps = {}
454 fps = {}
454 for j in xrange(len(jobs)):
455 for j in xrange(len(jobs)):
455 job = jobs[j]
456 job = jobs[j]
456 if not job:
457 if not job:
457 continue
458 continue
458 rfd, wfd = os.pipe()
459 rfd, wfd = os.pipe()
459 childopts = ['--child=%d' % wfd, '--port=%d' % (options.port + j * 3)]
460 childopts = ['--child=%d' % wfd, '--port=%d' % (options.port + j * 3)]
460 cmdline = [python, sys.argv[0]] + opts + childopts + job
461 cmdline = [python, sys.argv[0]] + opts + childopts + job
461 vlog(' '.join(cmdline))
462 vlog(' '.join(cmdline))
462 fps[os.spawnvp(os.P_NOWAIT, cmdline[0], cmdline)] = os.fdopen(rfd, 'r')
463 fps[os.spawnvp(os.P_NOWAIT, cmdline[0], cmdline)] = os.fdopen(rfd, 'r')
463 os.close(wfd)
464 os.close(wfd)
464 failures = 0
465 failures = 0
465 tested, skipped, failed = 0, 0, 0
466 tested, skipped, failed = 0, 0, 0
466 skips = []
467 skips = []
467 while fps:
468 while fps:
468 pid, status = os.wait()
469 pid, status = os.wait()
469 fp = fps.pop(pid)
470 fp = fps.pop(pid)
470 l = fp.read().splitlines()
471 l = fp.read().splitlines()
471 test, skip, fail = map(int, l[:3])
472 test, skip, fail = map(int, l[:3])
472 for s in l[3:]:
473 for s in l[3:]:
473 skips.append(s.split(" ", 1))
474 skips.append(s.split(" ", 1))
474 tested += test
475 tested += test
475 skipped += skip
476 skipped += skip
476 failed += fail
477 failed += fail
477 vlog('pid %d exited, status %d' % (pid, status))
478 vlog('pid %d exited, status %d' % (pid, status))
478 failures |= status
479 failures |= status
479 print
480 print
480 for s in skips:
481 for s in skips:
481 print "Skipped %s: %s" % (s[0], s[1])
482 print "Skipped %s: %s" % (s[0], s[1])
482 print "# Ran %d tests, %d skipped, %d failed." % (
483 print "# Ran %d tests, %d skipped, %d failed." % (
483 tested, skipped, failed)
484 tested, skipped, failed)
484 sys.exit(failures != 0)
485 sys.exit(failures != 0)
485
486
486 def run_tests(tests):
487 def run_tests(tests):
487 global DAEMON_PIDS, HGRCPATH
488 global DAEMON_PIDS, HGRCPATH
488 DAEMON_PIDS = os.environ["DAEMON_PIDS"] = os.path.join(HGTMP, 'daemon.pids')
489 DAEMON_PIDS = os.environ["DAEMON_PIDS"] = os.path.join(HGTMP, 'daemon.pids')
489 HGRCPATH = os.environ["HGRCPATH"] = os.path.join(HGTMP, '.hgrc')
490 HGRCPATH = os.environ["HGRCPATH"] = os.path.join(HGTMP, '.hgrc')
490
491
491 try:
492 try:
492 if not options.with_hg:
493 if not options.with_hg:
493 install_hg()
494 install_hg()
494
495
495 if options.timeout > 0:
496 if options.timeout > 0:
496 try:
497 try:
497 signal.signal(signal.SIGALRM, alarmed)
498 signal.signal(signal.SIGALRM, alarmed)
498 vlog('# Running tests with %d-second timeout' %
499 vlog('# Running tests with %d-second timeout' %
499 options.timeout)
500 options.timeout)
500 except AttributeError:
501 except AttributeError:
501 print 'WARNING: cannot run tests with timeouts'
502 print 'WARNING: cannot run tests with timeouts'
502 options.timeout = 0
503 options.timeout = 0
503
504
504 tested = 0
505 tested = 0
505 failed = 0
506 failed = 0
506 skipped = 0
507 skipped = 0
507
508
508 if options.restart:
509 if options.restart:
509 orig = list(tests)
510 orig = list(tests)
510 while tests:
511 while tests:
511 if os.path.exists(tests[0] + ".err"):
512 if os.path.exists(tests[0] + ".err"):
512 break
513 break
513 tests.pop(0)
514 tests.pop(0)
514 if not tests:
515 if not tests:
515 print "running all tests"
516 print "running all tests"
516 tests = orig
517 tests = orig
517
518
518 skips = []
519 skips = []
519 for test in tests:
520 for test in tests:
520 if options.retest and not os.path.exists(test + ".err"):
521 if options.retest and not os.path.exists(test + ".err"):
521 skipped += 1
522 skipped += 1
522 continue
523 continue
523 ret = run_one(test, skips)
524 ret = run_one(test, skips)
524 if ret is None:
525 if ret is None:
525 skipped += 1
526 skipped += 1
526 elif not ret:
527 elif not ret:
527 if options.interactive:
528 if options.interactive:
528 print "Accept this change? [n] ",
529 print "Accept this change? [n] ",
529 answer = sys.stdin.readline().strip()
530 answer = sys.stdin.readline().strip()
530 if answer.lower() in "y yes".split():
531 if answer.lower() in "y yes".split():
531 os.rename(test + ".err", test + ".out")
532 os.rename(test + ".err", test + ".out")
532 tested += 1
533 tested += 1
533 continue
534 continue
534 failed += 1
535 failed += 1
535 if options.first:
536 if options.first:
536 break
537 break
537 tested += 1
538 tested += 1
538
539
539 if options.child:
540 if options.child:
540 fp = os.fdopen(options.child, 'w')
541 fp = os.fdopen(options.child, 'w')
541 fp.write('%d\n%d\n%d\n' % (tested, skipped, failed))
542 fp.write('%d\n%d\n%d\n' % (tested, skipped, failed))
542 for s in skips:
543 for s in skips:
543 fp.write("%s %s\n" % s)
544 fp.write("%s %s\n" % s)
544 fp.close()
545 fp.close()
545 else:
546 else:
546 print
547 print
547 for s in skips:
548 for s in skips:
548 print "Skipped %s: %s" % s
549 print "Skipped %s: %s" % s
549 print "# Ran %d tests, %d skipped, %d failed." % (
550 print "# Ran %d tests, %d skipped, %d failed." % (
550 tested, skipped, failed)
551 tested, skipped, failed)
551
552
552 if coverage:
553 if coverage:
553 output_coverage()
554 output_coverage()
554 except KeyboardInterrupt:
555 except KeyboardInterrupt:
555 failed = True
556 failed = True
556 print "\ninterrupted!"
557 print "\ninterrupted!"
557
558
558 if failed:
559 if failed:
559 sys.exit(1)
560 sys.exit(1)
560
561
561 if len(args) == 0:
562 if len(args) == 0:
562 args = os.listdir(".")
563 args = os.listdir(".")
563 args.sort()
564 args.sort()
564
565
565 tests = []
566 tests = []
566 for test in args:
567 for test in args:
567 if (test.startswith("test-") and '~' not in test and
568 if (test.startswith("test-") and '~' not in test and
568 ('.' not in test or test.endswith('.py') or
569 ('.' not in test or test.endswith('.py') or
569 test.endswith('.bat'))):
570 test.endswith('.bat'))):
570 tests.append(test)
571 tests.append(test)
571
572
572 vlog("# Using TESTDIR", TESTDIR)
573 vlog("# Using TESTDIR", TESTDIR)
573 vlog("# Using HGTMP", HGTMP)
574 vlog("# Using HGTMP", HGTMP)
574
575
575 try:
576 try:
576 if len(tests) > 1 and options.jobs > 1:
577 if len(tests) > 1 and options.jobs > 1:
577 run_children(tests)
578 run_children(tests)
578 else:
579 else:
579 run_tests(tests)
580 run_tests(tests)
580 finally:
581 finally:
581 cleanup_exit()
582 cleanup_exit()
@@ -1,61 +1,61 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 "$TESTDIR/hghave" darcs || exit 80
3 "$TESTDIR/hghave" darcs || exit 80
4
4
5 echo "[extensions]" >> $HGRCPATH
5 echo "[extensions]" >> $HGRCPATH
6 echo "convert=" >> $HGRCPATH
6 echo "convert=" >> $HGRCPATH
7 echo 'hgext.graphlog =' >> $HGRCPATH
7 echo 'hgext.graphlog =' >> $HGRCPATH
8
8
9 DARCS_EMAIL='test@example.org'; export DARCS_EMAIL
9 DARCS_EMAIL='test@example.org'; export DARCS_EMAIL
10 HOME=do_not_use_HOME_darcs; export HOME
10 HOME=do_not_use_HOME_darcs; export HOME
11
11
12 # skip if we can't import elementtree
12 # skip if we can't import elementtree
13 mkdir dummy
13 mkdir dummy
14 mkdir dummy/_darcs
14 mkdir dummy/_darcs
15 if hg convert dummy 2>&1 | grep ElementTree > /dev/null; then
15 if hg convert dummy 2>&1 | grep ElementTree > /dev/null; then
16 echo 'hghave: missing feature: elementtree module'
16 echo 'skipped: missing feature: elementtree module'
17 exit 80
17 exit 80
18 fi
18 fi
19
19
20 echo % initialize darcs repo
20 echo % initialize darcs repo
21 mkdir darcs-repo
21 mkdir darcs-repo
22 cd darcs-repo
22 cd darcs-repo
23 darcs init
23 darcs init
24 echo a > a
24 echo a > a
25 darcs record -a -l -m p0
25 darcs record -a -l -m p0
26 cd ..
26 cd ..
27
27
28 echo % branch and update
28 echo % branch and update
29 darcs get darcs-repo darcs-clone >/dev/null
29 darcs get darcs-repo darcs-clone >/dev/null
30 cd darcs-clone
30 cd darcs-clone
31 echo c >> a
31 echo c >> a
32 echo c > c
32 echo c > c
33 darcs record -a -l -m p1.1
33 darcs record -a -l -m p1.1
34 cd ..
34 cd ..
35
35
36 echo % update source
36 echo % update source
37 cd darcs-repo
37 cd darcs-repo
38 echo b >> a
38 echo b >> a
39 echo b > b
39 echo b > b
40 darcs record -a -l -m p1.2
40 darcs record -a -l -m p1.2
41
41
42 echo % merge branch
42 echo % merge branch
43 darcs pull -a ../darcs-clone
43 darcs pull -a ../darcs-clone
44 echo e > a
44 echo e > a
45 darcs record -a -l -m p2
45 darcs record -a -l -m p2
46 cd ..
46 cd ..
47
47
48 glog()
48 glog()
49 {
49 {
50 hg glog --template '#rev# "#desc|firstline#" files: #files#\n' "$@"
50 hg glog --template '#rev# "#desc|firstline#" files: #files#\n' "$@"
51 }
51 }
52
52
53 hg convert darcs-repo darcs-repo-hg 2>&1 | grep -v hGetLine | grep -v '^$'
53 hg convert darcs-repo darcs-repo-hg 2>&1 | grep -v hGetLine | grep -v '^$'
54 # The converter does not currently handle patch conflicts very well.
54 # The converter does not currently handle patch conflicts very well.
55 # When they occur, it reverts *all* changes and moves forward,
55 # When they occur, it reverts *all* changes and moves forward,
56 # letting the conflict resolving patch fix collisions.
56 # letting the conflict resolving patch fix collisions.
57 # Unfortunately, non-conflicting changes, like the addition of the
57 # Unfortunately, non-conflicting changes, like the addition of the
58 # "c" file in p1.1 patch are reverted too.
58 # "c" file in p1.1 patch are reverted too.
59 # Just to say that manifest not listing "c" here is a bug.
59 # Just to say that manifest not listing "c" here is a bug.
60 glog -R darcs-repo-hg
60 glog -R darcs-repo-hg
61 hg -R darcs-repo-hg manifest --debug
61 hg -R darcs-repo-hg manifest --debug
@@ -1,36 +1,39 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 hg init
3 hg init
4 echo a > a
4 echo a > a
5 hg ci -Amadd
5 hg ci -Amadd
6
6
7 chmod +x a
7 chmod +x a
8 hg ci -mexecutable
8 hg ci -mexecutable
9
9
10 hg up 0
10 hg up 0
11 rm a
11 rm a
12 ln -s symlink a
12 ln -s symlink a
13 hg ci -msymlink
13 hg ci -msymlink
14
14
15 hg merge
15 hg merge
16
16
17 echo % symlink is left parent, executable is right
17 echo % symlink is left parent, executable is right
18
18
19 if [ -h a ]; then
19 if [ -h a ]; then
20 echo a is a symlink
20 echo a is a symlink
21 $TESTDIR/readlink.py a
21 $TESTDIR/readlink.py a
22 elif [ -x a ]; then
22 elif [ -x a ]; then
23 echo a is executable
23 echo a is executable
24 fi
24 fi
25
25
26 hg update -C 1
26 hg update -C 1
27 hg merge
27 hg merge
28
28
29 echo % symlink is right parent, executable is left
29 echo % symlink is right parent, executable is left
30
30
31 if [ -h a ]; then
31 if [ -h a ]; then
32 echo a is a symlink
32 echo a is a symlink
33 $TESTDIR/readlink.py a
33 $TESTDIR/readlink.py a
34 elif [ -x a ]; then
34 elif [ -x a ]; then
35 echo a is executable
35 echo a is executable
36 fi
36 fi
37
38 echo "skipped: test is for a known, unfixed bug"
39 exit 80
General Comments 0
You need to be logged in to leave comments. Login now