Show More
@@ -0,0 +1,133 b'' | |||||
|
1 | #!/usr/bin/env python | |||
|
2 | ||||
|
3 | # fsmonitor-run-tests.py - Run Mercurial tests with fsmonitor enabled | |||
|
4 | # | |||
|
5 | # Copyright 2017 Facebook, Inc. | |||
|
6 | # | |||
|
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. | |||
|
9 | # | |||
|
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 | |||
|
12 | # version of Watchman isn't affected by anything this test does. | |||
|
13 | ||||
|
14 | from __future__ import absolute_import | |||
|
15 | from __future__ import print_function | |||
|
16 | ||||
|
17 | import argparse | |||
|
18 | import contextlib | |||
|
19 | import json | |||
|
20 | import os | |||
|
21 | import shutil | |||
|
22 | import subprocess | |||
|
23 | import sys | |||
|
24 | import tempfile | |||
|
25 | import uuid | |||
|
26 | ||||
|
27 | osenvironb = getattr(os, 'environb', os.environ) | |||
|
28 | ||||
|
29 | if sys.version_info > (3, 5, 0): | |||
|
30 | PYTHON3 = True | |||
|
31 | xrange = range # we use xrange in one place, and we'd rather not use range | |||
|
32 | def _bytespath(p): | |||
|
33 | return p.encode('utf-8') | |||
|
34 | ||||
|
35 | elif sys.version_info >= (3, 0, 0): | |||
|
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]))) | |||
|
38 | sys.exit(70) # EX_SOFTWARE from `man 3 sysexit` | |||
|
39 | else: | |||
|
40 | PYTHON3 = False | |||
|
41 | ||||
|
42 | # In python 2.x, path operations are generally done using | |||
|
43 | # bytestrings by default, so we don't have to do any extra | |||
|
44 | # fiddling there. We define the wrapper functions anyway just to | |||
|
45 | # help keep code consistent between platforms. | |||
|
46 | def _bytespath(p): | |||
|
47 | return p | |||
|
48 | ||||
|
49 | def getparser(): | |||
|
50 | """Obtain the argument parser used by the CLI.""" | |||
|
51 | parser = argparse.ArgumentParser( | |||
|
52 | description='Run tests with fsmonitor enabled.', | |||
|
53 | epilog='Unrecognized options are passed to run-tests.py.') | |||
|
54 | # - keep these sorted | |||
|
55 | # - none of these options should conflict with any in run-tests.py | |||
|
56 | parser.add_argument('--keep-fsmonitor-tmpdir', action='store_true', | |||
|
57 | help='keep temporary directory with fsmonitor state') | |||
|
58 | parser.add_argument('--watchman', | |||
|
59 | help='location of watchman binary (default: watchman in PATH)', | |||
|
60 | default='watchman') | |||
|
61 | ||||
|
62 | return parser | |||
|
63 | ||||
|
64 | @contextlib.contextmanager | |||
|
65 | def watchman(args): | |||
|
66 | basedir = tempfile.mkdtemp(prefix='hg-fsmonitor') | |||
|
67 | try: | |||
|
68 | # Much of this configuration is borrowed from Watchman's test harness. | |||
|
69 | cfgfile = os.path.join(basedir, 'config.json') | |||
|
70 | # TODO: allow setting a config | |||
|
71 | with open(cfgfile, 'w') as f: | |||
|
72 | f.write(json.dumps({})) | |||
|
73 | ||||
|
74 | logfile = os.path.join(basedir, 'log') | |||
|
75 | clilogfile = os.path.join(basedir, 'cli-log') | |||
|
76 | if os.name == 'nt': | |||
|
77 | sockfile = '\\\\.\\pipe\\watchman-test-%s' % uuid.uuid4().hex | |||
|
78 | else: | |||
|
79 | sockfile = os.path.join(basedir, 'sock') | |||
|
80 | pidfile = os.path.join(basedir, 'pid') | |||
|
81 | statefile = os.path.join(basedir, 'state') | |||
|
82 | ||||
|
83 | argv = [ | |||
|
84 | args.watchman, | |||
|
85 | '--sockname', sockfile, | |||
|
86 | '--logfile', logfile, | |||
|
87 | '--pidfile', pidfile, | |||
|
88 | '--statefile', statefile, | |||
|
89 | '--foreground', | |||
|
90 | '--log-level=2', # debug logging for watchman | |||
|
91 | ] | |||
|
92 | ||||
|
93 | envb = osenvironb.copy() | |||
|
94 | envb[b'WATCHMAN_CONFIG_FILE'] = _bytespath(cfgfile) | |||
|
95 | with open(clilogfile, 'wb') as f: | |||
|
96 | proc = subprocess.Popen( | |||
|
97 | argv, env=envb, stdin=None, stdout=f, stderr=f) | |||
|
98 | try: | |||
|
99 | yield sockfile | |||
|
100 | finally: | |||
|
101 | proc.terminate() | |||
|
102 | proc.kill() | |||
|
103 | finally: | |||
|
104 | if args.keep_fsmonitor_tmpdir: | |||
|
105 | print('fsmonitor dir available at %s' % basedir) | |||
|
106 | else: | |||
|
107 | shutil.rmtree(basedir, ignore_errors=True) | |||
|
108 | ||||
|
109 | def run(): | |||
|
110 | parser = getparser() | |||
|
111 | args, runtestsargv = parser.parse_known_args() | |||
|
112 | ||||
|
113 | with watchman(args) as sockfile: | |||
|
114 | osenvironb[b'WATCHMAN_SOCK'] = _bytespath(sockfile) | |||
|
115 | # Indicate to hghave that we're running with fsmonitor enabled. | |||
|
116 | osenvironb[b'HGFSMONITOR_TESTS'] = b'1' | |||
|
117 | ||||
|
118 | runtestdir = os.path.dirname(__file__) | |||
|
119 | runtests = os.path.join(runtestdir, 'run-tests.py') | |||
|
120 | blacklist = os.path.join(runtestdir, 'blacklists', 'fsmonitor') | |||
|
121 | ||||
|
122 | runtestsargv.insert(0, runtests) | |||
|
123 | runtestsargv.extend([ | |||
|
124 | '--extra-config', | |||
|
125 | 'extensions.fsmonitor=', | |||
|
126 | '--blacklist', | |||
|
127 | blacklist, | |||
|
128 | ]) | |||
|
129 | ||||
|
130 | return subprocess.call(runtestsargv) | |||
|
131 | ||||
|
132 | if __name__ == '__main__': | |||
|
133 | sys.exit(run()) |
@@ -1,52 +1,50 b'' | |||||
1 | # Blacklist for a full testsuite run with fsmonitor enabled. |
|
1 | # Blacklist for a full testsuite run with fsmonitor enabled. | |
2 | # Use with |
|
2 | # Used by fsmonitor-run-tests. | |
3 | # run-tests --blacklist=blacklists/fsmonitor \ |
|
|||
4 | # --extra-config="extensions.fsmonitor=" |
|
|||
5 | # The following tests all fail because they either use extensions that conflict |
|
3 | # The following tests all fail because they either use extensions that conflict | |
6 | # with fsmonitor, use subrepositories, or don't anticipate the extra file in |
|
4 | # with fsmonitor, use subrepositories, or don't anticipate the extra file in | |
7 | # the .hg directory that fsmonitor adds. |
|
5 | # the .hg directory that fsmonitor adds. | |
8 | test-basic.t |
|
6 | test-basic.t | |
9 | test-blackbox.t |
|
7 | test-blackbox.t | |
10 | test-check-commit.t |
|
8 | test-check-commit.t | |
11 | test-commandserver.t |
|
9 | test-commandserver.t | |
12 | test-copy.t |
|
10 | test-copy.t | |
13 | test-debugextensions.t |
|
11 | test-debugextensions.t | |
14 | test-eol-add.t |
|
12 | test-eol-add.t | |
15 | test-eol-clone.t |
|
13 | test-eol-clone.t | |
16 | test-eol-hook.t |
|
14 | test-eol-hook.t | |
17 | test-eol-patch.t |
|
15 | test-eol-patch.t | |
18 | test-eol-tag.t |
|
16 | test-eol-tag.t | |
19 | test-eol-update.t |
|
17 | test-eol-update.t | |
20 | test-eol.t |
|
18 | test-eol.t | |
21 | test-eolfilename.t |
|
19 | test-eolfilename.t | |
22 | test-extension.t |
|
20 | test-extension.t | |
23 | test-fncache.t |
|
21 | test-fncache.t | |
24 | test-hardlinks.t |
|
22 | test-hardlinks.t | |
25 | test-help.t |
|
23 | test-help.t | |
26 | test-inherit-mode.t |
|
24 | test-inherit-mode.t | |
27 | test-issue3084.t |
|
25 | test-issue3084.t | |
28 | test-largefiles-cache.t |
|
26 | test-largefiles-cache.t | |
29 | test-largefiles-misc.t |
|
27 | test-largefiles-misc.t | |
30 | test-largefiles-small-disk.t |
|
28 | test-largefiles-small-disk.t | |
31 | test-largefiles-update.t |
|
29 | test-largefiles-update.t | |
32 | test-largefiles-wireproto.t |
|
30 | test-largefiles-wireproto.t | |
33 | test-largefiles.t |
|
31 | test-largefiles.t | |
34 | test-lfconvert.t |
|
32 | test-lfconvert.t | |
35 | test-merge-tools.t |
|
33 | test-merge-tools.t | |
36 | test-nested-repo.t |
|
34 | test-nested-repo.t | |
37 | test-permissions.t |
|
35 | test-permissions.t | |
38 | test-push-warn.t |
|
36 | test-push-warn.t | |
39 | test-subrepo-deep-nested-change.t |
|
37 | test-subrepo-deep-nested-change.t | |
40 | test-subrepo-recursion.t |
|
38 | test-subrepo-recursion.t | |
41 | test-subrepo.t |
|
39 | test-subrepo.t | |
42 | test-tags.t |
|
40 | test-tags.t | |
43 |
|
41 | |||
44 | # The following tests remain enabled; they fail *too*, but only because they |
|
42 | # The following tests remain enabled; they fail *too*, but only because they | |
45 | # occasionally use blacklisted extensions and don't anticipate the warning |
|
43 | # occasionally use blacklisted extensions and don't anticipate the warning | |
46 | # generated. |
|
44 | # generated. | |
47 | #test-log.t |
|
45 | #test-log.t | |
48 | #test-hook.t |
|
46 | #test-hook.t | |
49 | #test-rename.t |
|
47 | #test-rename.t | |
50 | #test-histedit-fold.t |
|
48 | #test-histedit-fold.t | |
51 | #test-fileset-generated.t |
|
49 | #test-fileset-generated.t | |
52 | #test-init.t |
|
50 | #test-init.t |
General Comments 0
You need to be logged in to leave comments.
Login now