comparison tests/dumbhttp.py @ 23136:6eab50a34fed

tests: have dumbhttp.py use cmdutil.service() to wait for child to listen() Because the original dumbhttp.py exited without waiting for listen(), several tests could fail with "abort: error: Connection refused" if subsequent hg command is fast enough.
author Yuya Nishihara <yuya@tcha.org>
date Sun, 02 Nov 2014 13:08:46 +0900
parents 10116463b0b1
children 0bb8c405a7c7
comparison
equal deleted inserted replaced
23135:e637dd64ba72 23136:6eab50a34fed
3 """ 3 """
4 Small and dumb HTTP server for use in tests. 4 Small and dumb HTTP server for use in tests.
5 """ 5 """
6 6
7 from optparse import OptionParser 7 from optparse import OptionParser
8 import BaseHTTPServer, SimpleHTTPServer, os, signal, subprocess, sys 8 import BaseHTTPServer, SimpleHTTPServer, signal, sys
9 9
10 from mercurial import cmdutil
10 11
11 def run(server_class=BaseHTTPServer.HTTPServer, 12 class simplehttpservice(object):
12 handler_class=SimpleHTTPServer.SimpleHTTPRequestHandler, 13 def __init__(self, host, port):
13 server_address=('localhost', 8000)): 14 self.address = (host, port)
14 httpd = server_class(server_address, handler_class) 15 def init(self):
15 httpd.serve_forever() 16 self.httpd = BaseHTTPServer.HTTPServer(
16 17 self.address, SimpleHTTPServer.SimpleHTTPRequestHandler)
18 def run(self):
19 self.httpd.serve_forever()
17 20
18 if __name__ == '__main__': 21 if __name__ == '__main__':
19 parser = OptionParser() 22 parser = OptionParser()
20 parser.add_option('-p', '--port', dest='port', type='int', default=8000, 23 parser.add_option('-p', '--port', dest='port', type='int', default=8000,
21 help='TCP port to listen on', metavar='PORT') 24 help='TCP port to listen on', metavar='PORT')
24 parser.add_option('--pid', dest='pid', 27 parser.add_option('--pid', dest='pid',
25 help='file name where the PID of the server is stored') 28 help='file name where the PID of the server is stored')
26 parser.add_option('-f', '--foreground', dest='foreground', 29 parser.add_option('-f', '--foreground', dest='foreground',
27 action='store_true', 30 action='store_true',
28 help='do not start the HTTP server in the background') 31 help='do not start the HTTP server in the background')
32 parser.add_option('--daemon-pipefds')
29 33
30 (options, args) = parser.parse_args() 34 (options, args) = parser.parse_args()
31 35
32 signal.signal(signal.SIGTERM, lambda x, y: sys.exit(0)) 36 signal.signal(signal.SIGTERM, lambda x, y: sys.exit(0))
33 37
34 if options.foreground and options.pid: 38 if options.foreground and options.pid:
35 parser.error("options --pid and --foreground are mutually exclusive") 39 parser.error("options --pid and --foreground are mutually exclusive")
36 40
37 if options.foreground: 41 opts = {'pid_file': options.pid,
38 run(server_address=(options.host, options.port)) 42 'daemon': not options.foreground,
39 else: 43 'daemon_pipefds': options.daemon_pipefds}
40 # This doesn't attempt to cleanly detach the process, as it's not 44 service = simplehttpservice(options.host, options.port)
41 # meant to be a long-lived, independent process. As a consequence, 45 cmdutil.service(opts, initfn=service.init, runfn=service.run,
42 # it's still part of the same process group, and keeps any file 46 runargs=[sys.executable, __file__] + sys.argv[1:])
43 # descriptors it might have inherited besided stdin/stdout/stderr.
44 # Trying to do things cleanly is more complicated, requires
45 # OS-dependent code, and is not worth the effort.
46 proc = subprocess.Popen([sys.executable, __file__, '-f',
47 '-H', options.host, '-p', str(options.port)],
48 stdin=open(os.devnull, 'r'),
49 stdout=open(os.devnull, 'w'),
50 stderr=subprocess.STDOUT)
51 if options.pid:
52 fp = file(options.pid, 'wb')
53 fp.write(str(proc.pid) + '\n')
54 fp.close()