test-commandserver.py
282 lines
| 7.4 KiB
| text/x-python
|
PythonLexer
/ tests / test-commandserver.py
|
r14882 | import sys, os, struct, subprocess, cStringIO, re, shutil | ||
|
r14770 | |||
def connect(path=None): | ||||
cmdline = ['hg', 'serve', '--cmdserver', 'pipe'] | ||||
if path: | ||||
cmdline += ['-R', path] | ||||
server = subprocess.Popen(cmdline, stdin=subprocess.PIPE, | ||||
stdout=subprocess.PIPE) | ||||
return server | ||||
def writeblock(server, data): | ||||
server.stdin.write(struct.pack('>I', len(data))) | ||||
server.stdin.write(data) | ||||
server.stdin.flush() | ||||
def readchannel(server): | ||||
data = server.stdout.read(5) | ||||
if not data: | ||||
|
r16687 | raise EOFError | ||
|
r14770 | channel, length = struct.unpack('>cI', data) | ||
if channel in 'IL': | ||||
return channel, length | ||||
else: | ||||
return channel, server.stdout.read(length) | ||||
def runcommand(server, args, output=sys.stdout, error=sys.stderr, input=None): | ||||
|
r15541 | print ' runcommand', ' '.join(args) | ||
|
r16117 | sys.stdout.flush() | ||
|
r14770 | server.stdin.write('runcommand\n') | ||
writeblock(server, '\0'.join(args)) | ||||
if not input: | ||||
input = cStringIO.StringIO() | ||||
while True: | ||||
ch, data = readchannel(server) | ||||
if ch == 'o': | ||||
output.write(data) | ||||
output.flush() | ||||
elif ch == 'e': | ||||
error.write(data) | ||||
error.flush() | ||||
elif ch == 'I': | ||||
writeblock(server, input.read(data)) | ||||
elif ch == 'L': | ||||
writeblock(server, input.readline(data)) | ||||
elif ch == 'r': | ||||
return struct.unpack('>i', data)[0] | ||||
else: | ||||
print "unexpected channel %c: %r" % (ch, data) | ||||
if ch.isupper(): | ||||
return | ||||
def check(func, repopath=None): | ||||
|
r15541 | |||
print 'testing %s:' % func.__name__ | ||||
|
r16117 | sys.stdout.flush() | ||
|
r14770 | server = connect(repopath) | ||
try: | ||||
return func(server) | ||||
finally: | ||||
server.stdin.close() | ||||
server.wait() | ||||
def unknowncommand(server): | ||||
server.stdin.write('unknowncommand\n') | ||||
def hellomessage(server): | ||||
ch, data = readchannel(server) | ||||
# escaping python tests output not supported | ||||
|
r16683 | print '%c, %r' % (ch, re.sub('encoding: [a-zA-Z0-9-]+', 'encoding: ***', | ||
data)) | ||||
|
r14770 | |||
# run an arbitrary command to make sure the next thing the server sends | ||||
# isn't part of the hello message | ||||
runcommand(server, ['id']) | ||||
def checkruncommand(server): | ||||
# hello block | ||||
readchannel(server) | ||||
# no args | ||||
runcommand(server, []) | ||||
# global options | ||||
runcommand(server, ['id', '--quiet']) | ||||
# make sure global options don't stick through requests | ||||
runcommand(server, ['id']) | ||||
# --config | ||||
runcommand(server, ['id', '--config', 'ui.quiet=True']) | ||||
# make sure --config doesn't stick | ||||
runcommand(server, ['id']) | ||||
def inputeof(server): | ||||
readchannel(server) | ||||
server.stdin.write('runcommand\n') | ||||
# close stdin while server is waiting for input | ||||
server.stdin.close() | ||||
# server exits with 1 if the pipe closed while reading the command | ||||
print 'server exit code =', server.wait() | ||||
def serverinput(server): | ||||
readchannel(server) | ||||
patch = """ | ||||
# HG changeset patch | ||||
# User test | ||||
# Date 0 0 | ||||
# Node ID c103a3dec114d882c98382d684d8af798d09d857 | ||||
# Parent 0000000000000000000000000000000000000000 | ||||
1 | ||||
diff -r 000000000000 -r c103a3dec114 a | ||||
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 | ||||
+++ b/a Thu Jan 01 00:00:00 1970 +0000 | ||||
@@ -0,0 +1,1 @@ | ||||
+1 | ||||
""" | ||||
runcommand(server, ['import', '-'], input=cStringIO.StringIO(patch)) | ||||
runcommand(server, ['log']) | ||||
|
r14864 | def cwd(server): | ||
""" check that --cwd doesn't persist between requests """ | ||||
readchannel(server) | ||||
os.mkdir('foo') | ||||
|
r15542 | f = open('foo/bar', 'wb') | ||
|
r14880 | f.write('a') | ||
f.close() | ||||
|
r14864 | runcommand(server, ['--cwd', 'foo', 'st', 'bar']) | ||
runcommand(server, ['st', 'foo/bar']) | ||||
os.remove('foo/bar') | ||||
|
r14882 | def localhgrc(server): | ||
""" check that local configs for the cached repo aren't inherited when -R | ||||
is used """ | ||||
readchannel(server) | ||||
|
r16683 | # the cached repo local hgrc contains ui.foo=bar, so showconfig should | ||
# show it | ||||
|
r14882 | runcommand(server, ['showconfig']) | ||
# but not for this repo | ||||
runcommand(server, ['init', 'foo']) | ||||
|
r15542 | runcommand(server, ['-R', 'foo', 'showconfig', 'ui', 'defaults']) | ||
|
r14882 | shutil.rmtree('foo') | ||
|
r14889 | def hook(**args): | ||
print 'hook talking' | ||||
print 'now try to read something: %r' % sys.stdin.read() | ||||
def hookoutput(server): | ||||
readchannel(server) | ||||
runcommand(server, ['--config', | ||||
|
r16683 | 'hooks.pre-identify=python:test-commandserver.hook', | ||
'id'], | ||||
|
r14889 | input=cStringIO.StringIO('some input')) | ||
|
r14939 | def outsidechanges(server): | ||
readchannel(server) | ||||
|
r15542 | f = open('a', 'ab') | ||
f.write('a\n') | ||||
f.close() | ||||
|
r16114 | runcommand(server, ['status']) | ||
|
r15542 | os.system('hg ci -Am2') | ||
|
r14939 | runcommand(server, ['tip']) | ||
|
r16114 | runcommand(server, ['status']) | ||
|
r14939 | |||
def bookmarks(server): | ||||
readchannel(server) | ||||
runcommand(server, ['bookmarks']) | ||||
# changes .hg/bookmarks | ||||
os.system('hg bookmark -i bm1') | ||||
os.system('hg bookmark -i bm2') | ||||
runcommand(server, ['bookmarks']) | ||||
# changes .hg/bookmarks.current | ||||
os.system('hg upd bm1 -q') | ||||
runcommand(server, ['bookmarks']) | ||||
|
r16115 | runcommand(server, ['bookmarks', 'bm3']) | ||
f = open('a', 'ab') | ||||
f.write('a\n') | ||||
f.close() | ||||
runcommand(server, ['commit', '-Amm']) | ||||
runcommand(server, ['bookmarks']) | ||||
|
r14939 | def tagscache(server): | ||
readchannel(server) | ||||
runcommand(server, ['id', '-t', '-r', '0']) | ||||
os.system('hg tag -r 0 foo') | ||||
runcommand(server, ['id', '-t', '-r', '0']) | ||||
|
r15989 | def setphase(server): | ||
readchannel(server) | ||||
runcommand(server, ['phase', '-r', '.']) | ||||
os.system('hg phase -r . -p') | ||||
runcommand(server, ['phase', '-r', '.']) | ||||
|
r16116 | def rollback(server): | ||
readchannel(server) | ||||
runcommand(server, ['phase', '-r', '.', '-p']) | ||||
f = open('a', 'ab') | ||||
f.write('a\n') | ||||
f.close() | ||||
runcommand(server, ['commit', '-Am.']) | ||||
runcommand(server, ['rollback']) | ||||
runcommand(server, ['phase', '-r', '.']) | ||||
|
r16201 | def branch(server): | ||
readchannel(server) | ||||
runcommand(server, ['branch']) | ||||
os.system('hg branch foo') | ||||
runcommand(server, ['branch']) | ||||
os.system('hg branch default') | ||||
|
r16202 | def hgignore(server): | ||
readchannel(server) | ||||
f = open('.hgignore', 'ab') | ||||
f.write('') | ||||
f.close() | ||||
runcommand(server, ['commit', '-Am.']) | ||||
f = open('ignored-file', 'ab') | ||||
f.write('') | ||||
f.close() | ||||
f = open('.hgignore', 'ab') | ||||
f.write('ignored-file') | ||||
f.close() | ||||
runcommand(server, ['status', '-i', '-u']) | ||||
|
r18757 | def phasecacheafterstrip(server): | ||
readchannel(server) | ||||
# create new head, 5:731265503d86 | ||||
runcommand(server, ['update', '-C', '0']) | ||||
f = open('a', 'ab') | ||||
f.write('a\n') | ||||
f.close() | ||||
runcommand(server, ['commit', '-Am.', 'a']) | ||||
runcommand(server, ['log', '-Gq']) | ||||
# make it public; draft marker moves to 4:7966c8e3734d | ||||
runcommand(server, ['phase', '-p', '.']) | ||||
runcommand(server, ['phase', '.']) # load _phasecache.phaseroots | ||||
# strip 1::4 outside server | ||||
os.system('hg --config extensions.mq= strip 1') | ||||
# shouldn't raise "7966c8e3734d: no node!" | ||||
runcommand(server, ['branches']) | ||||
|
r14770 | if __name__ == '__main__': | ||
os.system('hg init') | ||||
check(hellomessage) | ||||
check(unknowncommand) | ||||
check(checkruncommand) | ||||
check(inputeof) | ||||
check(serverinput) | ||||
|
r14864 | check(cwd) | ||
|
r14882 | |||
hgrc = open('.hg/hgrc', 'a') | ||||
hgrc.write('[ui]\nfoo=bar\n') | ||||
hgrc.close() | ||||
check(localhgrc) | ||||
|
r14889 | check(hookoutput) | ||
|
r14939 | check(outsidechanges) | ||
check(bookmarks) | ||||
check(tagscache) | ||||
|
r15989 | check(setphase) | ||
|
r16116 | check(rollback) | ||
|
r16201 | check(branch) | ||
|
r16202 | check(hgignore) | ||
|
r18757 | check(phasecacheafterstrip) | ||