##// END OF EJS Templates
tests: configure fsmonitor.mode=paranoid always if fsmonitor is used...
FUJIWARA Katsunori -
r40244:b7ba1cfb default
parent child Browse files
Show More
@@ -1,133 +1,139
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2
2
3 # fsmonitor-run-tests.py - Run Mercurial tests with fsmonitor enabled
3 # fsmonitor-run-tests.py - Run Mercurial tests with fsmonitor enabled
4 #
4 #
5 # Copyright 2017 Facebook, Inc.
5 # Copyright 2017 Facebook, Inc.
6 #
6 #
7 # This software may be used and distributed according to the terms of the
7 # This software may be used and distributed according to the terms of the
8 # GNU General Public License version 2 or any later version.
8 # GNU General Public License version 2 or any later version.
9 #
9 #
10 # This is a wrapper around run-tests.py that spins up an isolated instance of
10 # This is a wrapper around run-tests.py that spins up an isolated instance of
11 # Watchman and runs the Mercurial tests against it. This ensures that the global
11 # Watchman and runs the Mercurial tests against it. This ensures that the global
12 # version of Watchman isn't affected by anything this test does.
12 # version of Watchman isn't affected by anything this test does.
13
13
14 from __future__ import absolute_import
14 from __future__ import absolute_import
15 from __future__ import print_function
15 from __future__ import print_function
16
16
17 import argparse
17 import argparse
18 import contextlib
18 import contextlib
19 import json
19 import json
20 import os
20 import os
21 import shutil
21 import shutil
22 import subprocess
22 import subprocess
23 import sys
23 import sys
24 import tempfile
24 import tempfile
25 import uuid
25 import uuid
26
26
27 osenvironb = getattr(os, 'environb', os.environ)
27 osenvironb = getattr(os, 'environb', os.environ)
28
28
29 if sys.version_info > (3, 5, 0):
29 if sys.version_info > (3, 5, 0):
30 PYTHON3 = True
30 PYTHON3 = True
31 xrange = range # we use xrange in one place, and we'd rather not use range
31 xrange = range # we use xrange in one place, and we'd rather not use range
32 def _bytespath(p):
32 def _bytespath(p):
33 return p.encode('utf-8')
33 return p.encode('utf-8')
34
34
35 elif sys.version_info >= (3, 0, 0):
35 elif sys.version_info >= (3, 0, 0):
36 print('%s is only supported on Python 3.5+ and 2.7, not %s' %
36 print('%s is only supported on Python 3.5+ and 2.7, not %s' %
37 (sys.argv[0], '.'.join(str(v) for v in sys.version_info[:3])))
37 (sys.argv[0], '.'.join(str(v) for v in sys.version_info[:3])))
38 sys.exit(70) # EX_SOFTWARE from `man 3 sysexit`
38 sys.exit(70) # EX_SOFTWARE from `man 3 sysexit`
39 else:
39 else:
40 PYTHON3 = False
40 PYTHON3 = False
41
41
42 # In python 2.x, path operations are generally done using
42 # In python 2.x, path operations are generally done using
43 # bytestrings by default, so we don't have to do any extra
43 # bytestrings by default, so we don't have to do any extra
44 # fiddling there. We define the wrapper functions anyway just to
44 # fiddling there. We define the wrapper functions anyway just to
45 # help keep code consistent between platforms.
45 # help keep code consistent between platforms.
46 def _bytespath(p):
46 def _bytespath(p):
47 return p
47 return p
48
48
49 def getparser():
49 def getparser():
50 """Obtain the argument parser used by the CLI."""
50 """Obtain the argument parser used by the CLI."""
51 parser = argparse.ArgumentParser(
51 parser = argparse.ArgumentParser(
52 description='Run tests with fsmonitor enabled.',
52 description='Run tests with fsmonitor enabled.',
53 epilog='Unrecognized options are passed to run-tests.py.')
53 epilog='Unrecognized options are passed to run-tests.py.')
54 # - keep these sorted
54 # - keep these sorted
55 # - none of these options should conflict with any in run-tests.py
55 # - none of these options should conflict with any in run-tests.py
56 parser.add_argument('--keep-fsmonitor-tmpdir', action='store_true',
56 parser.add_argument('--keep-fsmonitor-tmpdir', action='store_true',
57 help='keep temporary directory with fsmonitor state')
57 help='keep temporary directory with fsmonitor state')
58 parser.add_argument('--watchman',
58 parser.add_argument('--watchman',
59 help='location of watchman binary (default: watchman in PATH)',
59 help='location of watchman binary (default: watchman in PATH)',
60 default='watchman')
60 default='watchman')
61
61
62 return parser
62 return parser
63
63
64 @contextlib.contextmanager
64 @contextlib.contextmanager
65 def watchman(args):
65 def watchman(args):
66 basedir = tempfile.mkdtemp(prefix='hg-fsmonitor')
66 basedir = tempfile.mkdtemp(prefix='hg-fsmonitor')
67 try:
67 try:
68 # Much of this configuration is borrowed from Watchman's test harness.
68 # Much of this configuration is borrowed from Watchman's test harness.
69 cfgfile = os.path.join(basedir, 'config.json')
69 cfgfile = os.path.join(basedir, 'config.json')
70 # TODO: allow setting a config
70 # TODO: allow setting a config
71 with open(cfgfile, 'w') as f:
71 with open(cfgfile, 'w') as f:
72 f.write(json.dumps({}))
72 f.write(json.dumps({}))
73
73
74 logfile = os.path.join(basedir, 'log')
74 logfile = os.path.join(basedir, 'log')
75 clilogfile = os.path.join(basedir, 'cli-log')
75 clilogfile = os.path.join(basedir, 'cli-log')
76 if os.name == 'nt':
76 if os.name == 'nt':
77 sockfile = '\\\\.\\pipe\\watchman-test-%s' % uuid.uuid4().hex
77 sockfile = '\\\\.\\pipe\\watchman-test-%s' % uuid.uuid4().hex
78 else:
78 else:
79 sockfile = os.path.join(basedir, 'sock')
79 sockfile = os.path.join(basedir, 'sock')
80 pidfile = os.path.join(basedir, 'pid')
80 pidfile = os.path.join(basedir, 'pid')
81 statefile = os.path.join(basedir, 'state')
81 statefile = os.path.join(basedir, 'state')
82
82
83 argv = [
83 argv = [
84 args.watchman,
84 args.watchman,
85 '--sockname', sockfile,
85 '--sockname', sockfile,
86 '--logfile', logfile,
86 '--logfile', logfile,
87 '--pidfile', pidfile,
87 '--pidfile', pidfile,
88 '--statefile', statefile,
88 '--statefile', statefile,
89 '--foreground',
89 '--foreground',
90 '--log-level=2', # debug logging for watchman
90 '--log-level=2', # debug logging for watchman
91 ]
91 ]
92
92
93 envb = osenvironb.copy()
93 envb = osenvironb.copy()
94 envb[b'WATCHMAN_CONFIG_FILE'] = _bytespath(cfgfile)
94 envb[b'WATCHMAN_CONFIG_FILE'] = _bytespath(cfgfile)
95 with open(clilogfile, 'wb') as f:
95 with open(clilogfile, 'wb') as f:
96 proc = subprocess.Popen(
96 proc = subprocess.Popen(
97 argv, env=envb, stdin=None, stdout=f, stderr=f)
97 argv, env=envb, stdin=None, stdout=f, stderr=f)
98 try:
98 try:
99 yield sockfile
99 yield sockfile
100 finally:
100 finally:
101 proc.terminate()
101 proc.terminate()
102 proc.kill()
102 proc.kill()
103 finally:
103 finally:
104 if args.keep_fsmonitor_tmpdir:
104 if args.keep_fsmonitor_tmpdir:
105 print('fsmonitor dir available at %s' % basedir)
105 print('fsmonitor dir available at %s' % basedir)
106 else:
106 else:
107 shutil.rmtree(basedir, ignore_errors=True)
107 shutil.rmtree(basedir, ignore_errors=True)
108
108
109 def run():
109 def run():
110 parser = getparser()
110 parser = getparser()
111 args, runtestsargv = parser.parse_known_args()
111 args, runtestsargv = parser.parse_known_args()
112
112
113 with watchman(args) as sockfile:
113 with watchman(args) as sockfile:
114 osenvironb[b'WATCHMAN_SOCK'] = _bytespath(sockfile)
114 osenvironb[b'WATCHMAN_SOCK'] = _bytespath(sockfile)
115 # Indicate to hghave that we're running with fsmonitor enabled.
115 # Indicate to hghave that we're running with fsmonitor enabled.
116 osenvironb[b'HGFSMONITOR_TESTS'] = b'1'
116 osenvironb[b'HGFSMONITOR_TESTS'] = b'1'
117
117
118 runtestdir = os.path.dirname(__file__)
118 runtestdir = os.path.dirname(__file__)
119 runtests = os.path.join(runtestdir, 'run-tests.py')
119 runtests = os.path.join(runtestdir, 'run-tests.py')
120 blacklist = os.path.join(runtestdir, 'blacklists', 'fsmonitor')
120 blacklist = os.path.join(runtestdir, 'blacklists', 'fsmonitor')
121
121
122 runtestsargv.insert(0, runtests)
122 runtestsargv.insert(0, runtests)
123 runtestsargv.extend([
123 runtestsargv.extend([
124 '--extra-config',
124 '--extra-config',
125 'extensions.fsmonitor=',
125 'extensions.fsmonitor=',
126 # specify fsmonitor.mode=paranoid always in order to force
127 # fsmonitor extension execute "paranoid" code path
128 #
129 # TODO: make fsmonitor-run-tests.py accept specific options
130 '--extra-config',
131 'fsmonitor.mode=paranoid',
126 '--blacklist',
132 '--blacklist',
127 blacklist,
133 blacklist,
128 ])
134 ])
129
135
130 return subprocess.call(runtestsargv)
136 return subprocess.call(runtestsargv)
131
137
132 if __name__ == '__main__':
138 if __name__ == '__main__':
133 sys.exit(run())
139 sys.exit(run())
General Comments 0
You need to be logged in to leave comments. Login now