##// END OF EJS Templates
tests: use a decorator for hghave checks
Matt Mackall -
r22093:45611a30 default
parent child Browse files
Show More
@@ -1,333 +1,339 b''
1 1 import os, stat
2 2 import re
3 3 import sys
4 4 import tempfile
5 5
6 6 tempprefix = 'hg-hghave-'
7 7
8 checks = {
9 "true": (lambda: True, "yak shaving"),
10 "false": (lambda: False, "nail clipper"),
11 }
12
13 def check(name, desc):
14 def decorator(func):
15 checks[name] = (func, desc)
16 return func
17 return decorator
18
8 19 def matchoutput(cmd, regexp, ignorestatus=False):
9 20 """Return True if cmd executes successfully and its output
10 21 is matched by the supplied regular expression.
11 22 """
12 23 r = re.compile(regexp)
13 24 fh = os.popen(cmd)
14 25 s = fh.read()
15 26 try:
16 27 ret = fh.close()
17 28 except IOError:
18 29 # Happen in Windows test environment
19 30 ret = 1
20 31 return (ignorestatus or ret is None) and r.search(s)
21 32
33 @check("baz", "GNU Arch baz client")
22 34 def has_baz():
23 35 return matchoutput('baz --version 2>&1', r'baz Bazaar version')
24 36
37 @check("bzr", "Canonical's Bazaar client")
25 38 def has_bzr():
26 39 try:
27 40 import bzrlib
28 41 return bzrlib.__doc__ is not None
29 42 except ImportError:
30 43 return False
31 44
45 @check("bzr114", "Canonical's Bazaar client >= 1.14")
32 46 def has_bzr114():
33 47 try:
34 48 import bzrlib
35 49 return (bzrlib.__doc__ is not None
36 50 and bzrlib.version_info[:2] >= (1, 14))
37 51 except ImportError:
38 52 return False
39 53
54 @check("cvs", "cvs client/server")
40 55 def has_cvs():
41 56 re = r'Concurrent Versions System.*?server'
42 57 return matchoutput('cvs --version 2>&1', re) and not has_msys()
43 58
59 @check("cvs112", "cvs client/server >= 1.12")
44 60 def has_cvs112():
45 61 re = r'Concurrent Versions System \(CVS\) 1.12.*?server'
46 62 return matchoutput('cvs --version 2>&1', re) and not has_msys()
47 63
64 @check("darcs", "darcs client")
48 65 def has_darcs():
49 66 return matchoutput('darcs --version', r'2\.[2-9]', True)
50 67
68 @check("mtn", "monotone client (>= 1.0)")
51 69 def has_mtn():
52 70 return matchoutput('mtn --version', r'monotone', True) and not matchoutput(
53 71 'mtn --version', r'monotone 0\.', True)
54 72
73 @check("eol-in-paths", "end-of-lines in paths")
55 74 def has_eol_in_paths():
56 75 try:
57 76 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix, suffix='\n\r')
58 77 os.close(fd)
59 78 os.remove(path)
60 79 return True
61 80 except (IOError, OSError):
62 81 return False
63 82
83 @check("execbit", "executable bit")
64 84 def has_executablebit():
65 85 try:
66 86 EXECFLAGS = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
67 87 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
68 88 try:
69 89 os.close(fh)
70 90 m = os.stat(fn).st_mode & 0777
71 91 new_file_has_exec = m & EXECFLAGS
72 92 os.chmod(fn, m ^ EXECFLAGS)
73 93 exec_flags_cannot_flip = ((os.stat(fn).st_mode & 0777) == m)
74 94 finally:
75 95 os.unlink(fn)
76 96 except (IOError, OSError):
77 97 # we don't care, the user probably won't be able to commit anyway
78 98 return False
79 99 return not (new_file_has_exec or exec_flags_cannot_flip)
80 100
101 @check("icasefs", "case insensitive file system")
81 102 def has_icasefs():
82 103 # Stolen from mercurial.util
83 104 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
84 105 os.close(fd)
85 106 try:
86 107 s1 = os.stat(path)
87 108 d, b = os.path.split(path)
88 109 p2 = os.path.join(d, b.upper())
89 110 if path == p2:
90 111 p2 = os.path.join(d, b.lower())
91 112 try:
92 113 s2 = os.stat(p2)
93 114 return s2 == s1
94 115 except OSError:
95 116 return False
96 117 finally:
97 118 os.remove(path)
98 119
120 @check("fifo", "named pipes")
99 121 def has_fifo():
100 122 if getattr(os, "mkfifo", None) is None:
101 123 return False
102 124 name = tempfile.mktemp(dir='.', prefix=tempprefix)
103 125 try:
104 126 os.mkfifo(name)
105 127 os.unlink(name)
106 128 return True
107 129 except OSError:
108 130 return False
109 131
132 @check("killdaemons", 'killdaemons.py support')
110 133 def has_killdaemons():
111 134 return True
112 135
136 @check("cacheable", "cacheable filesystem")
113 137 def has_cacheable_fs():
114 138 from mercurial import util
115 139
116 140 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
117 141 os.close(fd)
118 142 try:
119 143 return util.cachestat(path).cacheable()
120 144 finally:
121 145 os.remove(path)
122 146
147 @check("lsprof", "python lsprof module")
123 148 def has_lsprof():
124 149 try:
125 150 import _lsprof
126 151 return True
127 152 except ImportError:
128 153 return False
129 154
155 @check("gettext", "GNU Gettext (msgfmt)")
130 156 def has_gettext():
131 157 return matchoutput('msgfmt --version', 'GNU gettext-tools')
132 158
159 @check("git", "git command line client")
133 160 def has_git():
134 161 return matchoutput('git --version 2>&1', r'^git version')
135 162
163 @check("docutils", "Docutils text processing library")
136 164 def has_docutils():
137 165 try:
138 166 from docutils.core import publish_cmdline
139 167 return True
140 168 except ImportError:
141 169 return False
142 170
143 171 def getsvnversion():
144 172 m = matchoutput('svn --version --quiet 2>&1', r'^(\d+)\.(\d+)')
145 173 if not m:
146 174 return (0, 0)
147 175 return (int(m.group(1)), int(m.group(2)))
148 176
177 @check("svn15", "subversion client and admin tools >= 1.5")
149 178 def has_svn15():
150 179 return getsvnversion() >= (1, 5)
151 180
181 @check("svn13", "subversion client and admin tools >= 1.3")
152 182 def has_svn13():
153 183 return getsvnversion() >= (1, 3)
154 184
185 @check("svn", "subversion client and admin tools")
155 186 def has_svn():
156 187 return matchoutput('svn --version 2>&1', r'^svn, version') and \
157 188 matchoutput('svnadmin --version 2>&1', r'^svnadmin, version')
158 189
190 @check("svn-bindings", "subversion python bindings")
159 191 def has_svn_bindings():
160 192 try:
161 193 import svn.core
162 194 version = svn.core.SVN_VER_MAJOR, svn.core.SVN_VER_MINOR
163 195 if version < (1, 4):
164 196 return False
165 197 return True
166 198 except ImportError:
167 199 return False
168 200
201 @check("p4", "Perforce server and client")
169 202 def has_p4():
170 203 return (matchoutput('p4 -V', r'Rev\. P4/') and
171 204 matchoutput('p4d -V', r'Rev\. P4D/'))
172 205
206 @check("symlink", "symbolic links")
173 207 def has_symlink():
174 208 if getattr(os, "symlink", None) is None:
175 209 return False
176 210 name = tempfile.mktemp(dir='.', prefix=tempprefix)
177 211 try:
178 212 os.symlink(".", name)
179 213 os.unlink(name)
180 214 return True
181 215 except (OSError, AttributeError):
182 216 return False
183 217
218 @check("hardlink", "hardlinks")
184 219 def has_hardlink():
185 220 from mercurial import util
186 221 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
187 222 os.close(fh)
188 223 name = tempfile.mktemp(dir='.', prefix=tempprefix)
189 224 try:
190 225 try:
191 226 util.oslink(fn, name)
192 227 os.unlink(name)
193 228 return True
194 229 except OSError:
195 230 return False
196 231 finally:
197 232 os.unlink(fn)
198 233
234 @check("tla", "GNU Arch tla client")
199 235 def has_tla():
200 236 return matchoutput('tla --version 2>&1', r'The GNU Arch Revision')
201 237
238 @check("gpg", "gpg client")
202 239 def has_gpg():
203 240 return matchoutput('gpg --version 2>&1', r'GnuPG')
204 241
242 @check("unix-permissions", "unix-style permissions")
205 243 def has_unix_permissions():
206 244 d = tempfile.mkdtemp(dir='.', prefix=tempprefix)
207 245 try:
208 246 fname = os.path.join(d, 'foo')
209 247 for umask in (077, 007, 022):
210 248 os.umask(umask)
211 249 f = open(fname, 'w')
212 250 f.close()
213 251 mode = os.stat(fname).st_mode
214 252 os.unlink(fname)
215 253 if mode & 0777 != ~umask & 0666:
216 254 return False
217 255 return True
218 256 finally:
219 257 os.rmdir(d)
220 258
259 @check("root", "root permissions")
221 260 def has_root():
222 261 return getattr(os, 'geteuid', None) and os.geteuid() == 0
223 262
263 @check("pyflakes", "Pyflakes python linter")
224 264 def has_pyflakes():
225 265 return matchoutput("sh -c \"echo 'import re' 2>&1 | pyflakes\"",
226 266 r"<stdin>:1: 're' imported but unused",
227 267 True)
228 268
269 @check("pygments", "Pygments source highlighting library")
229 270 def has_pygments():
230 271 try:
231 272 import pygments
232 273 return True
233 274 except ImportError:
234 275 return False
235 276
277 @check("python243", "python >= 2.4.3")
236 278 def has_python243():
237 279 return sys.version_info >= (2, 4, 3)
238 280
281 @check("outer-repo", "outer repo")
239 282 def has_outer_repo():
240 283 # failing for other reasons than 'no repo' imply that there is a repo
241 284 return not matchoutput('hg root 2>&1',
242 285 r'abort: no repository found', True)
243 286
287 @check("ssl", "python >= 2.6 ssl module and python OpenSSL")
244 288 def has_ssl():
245 289 try:
246 290 import ssl
247 291 import OpenSSL
248 292 OpenSSL.SSL.Context
249 293 return True
250 294 except ImportError:
251 295 return False
252 296
297 @check("windows", "Windows")
253 298 def has_windows():
254 299 return os.name == 'nt'
255 300
301 @check("system-sh", "system() uses sh")
256 302 def has_system_sh():
257 303 return os.name != 'nt'
258 304
305 @check("serve", "platform and python can manage 'hg serve -d'")
259 306 def has_serve():
260 307 return os.name != 'nt' # gross approximation
261 308
309 @check("test-repo", "running tests from repository")
262 310 def has_test_repo():
263 311 t = os.environ["TESTDIR"]
264 312 return os.path.isdir(os.path.join(t, "..", ".hg"))
265 313
314 @check("tic", "terminfo compiler and curses module")
266 315 def has_tic():
267 316 try:
268 317 import curses
269 318 curses.COLOR_BLUE
270 319 return matchoutput('test -x "`which tic`"', '')
271 320 except ImportError:
272 321 return False
273 322
323 @check("msys", "Windows with MSYS")
274 324 def has_msys():
275 325 return os.getenv('MSYSTEM')
276 326
327 @check("aix", "AIX")
277 328 def has_aix():
278 329 return sys.platform.startswith("aix")
279 330
331 @check("absimport", "absolute_import in __future__")
280 332 def has_absimport():
281 333 import __future__
282 334 from mercurial import util
283 335 return util.safehasattr(__future__, "absolute_import")
284 336
337 @check("py3k", "running with Python 3.x")
285 338 def has_py3k():
286 339 return 3 == sys.version_info[0]
287
288 checks = {
289 "true": (lambda: True, "yak shaving"),
290 "false": (lambda: False, "nail clipper"),
291 "baz": (has_baz, "GNU Arch baz client"),
292 "bzr": (has_bzr, "Canonical's Bazaar client"),
293 "bzr114": (has_bzr114, "Canonical's Bazaar client >= 1.14"),
294 "cacheable": (has_cacheable_fs, "cacheable filesystem"),
295 "cvs": (has_cvs, "cvs client/server"),
296 "cvs112": (has_cvs112, "cvs client/server >= 1.12"),
297 "darcs": (has_darcs, "darcs client"),
298 "docutils": (has_docutils, "Docutils text processing library"),
299 "eol-in-paths": (has_eol_in_paths, "end-of-lines in paths"),
300 "execbit": (has_executablebit, "executable bit"),
301 "fifo": (has_fifo, "named pipes"),
302 "gettext": (has_gettext, "GNU Gettext (msgfmt)"),
303 "git": (has_git, "git command line client"),
304 "gpg": (has_gpg, "gpg client"),
305 "hardlink": (has_hardlink, "hardlinks"),
306 "icasefs": (has_icasefs, "case insensitive file system"),
307 "killdaemons": (has_killdaemons, 'killdaemons.py support'),
308 "lsprof": (has_lsprof, "python lsprof module"),
309 "mtn": (has_mtn, "monotone client (>= 1.0)"),
310 "outer-repo": (has_outer_repo, "outer repo"),
311 "p4": (has_p4, "Perforce server and client"),
312 "pyflakes": (has_pyflakes, "Pyflakes python linter"),
313 "pygments": (has_pygments, "Pygments source highlighting library"),
314 "python243": (has_python243, "python >= 2.4.3"),
315 "root": (has_root, "root permissions"),
316 "serve": (has_serve, "platform and python can manage 'hg serve -d'"),
317 "ssl": (has_ssl, "python >= 2.6 ssl module and python OpenSSL"),
318 "svn": (has_svn, "subversion client and admin tools"),
319 "svn13": (has_svn13, "subversion client and admin tools >= 1.3"),
320 "svn15": (has_svn15, "subversion client and admin tools >= 1.5"),
321 "svn-bindings": (has_svn_bindings, "subversion python bindings"),
322 "symlink": (has_symlink, "symbolic links"),
323 "system-sh": (has_system_sh, "system() uses sh"),
324 "test-repo": (has_test_repo, "running tests from repository"),
325 "tic": (has_tic, "terminfo compiler and curses module"),
326 "tla": (has_tla, "GNU Arch tla client"),
327 "unix-permissions": (has_unix_permissions, "unix-style permissions"),
328 "windows": (has_windows, "Windows"),
329 "msys": (has_msys, "Windows with MSYS"),
330 "aix": (has_aix, "AIX"),
331 "absimport": (has_absimport, "absolute_import in __future__"),
332 "py3k": (has_py3k, "running with Python 3.x"),
333 }
General Comments 0
You need to be logged in to leave comments. Login now