PageRenderTime 51ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/test-commandserver.py

https://bitbucket.org/mirror/mercurial/
Python | 357 lines | 331 code | 17 blank | 9 comment | 4 complexity | 95423b938505d6c1d24163d1389b83db MD5 | raw file
Possible License(s): GPL-2.0
  1. import sys, os, struct, subprocess, cStringIO, re, shutil
  2. def connect(path=None):
  3. cmdline = ['hg', 'serve', '--cmdserver', 'pipe']
  4. if path:
  5. cmdline += ['-R', path]
  6. server = subprocess.Popen(cmdline, stdin=subprocess.PIPE,
  7. stdout=subprocess.PIPE)
  8. return server
  9. def writeblock(server, data):
  10. server.stdin.write(struct.pack('>I', len(data)))
  11. server.stdin.write(data)
  12. server.stdin.flush()
  13. def readchannel(server):
  14. data = server.stdout.read(5)
  15. if not data:
  16. raise EOFError
  17. channel, length = struct.unpack('>cI', data)
  18. if channel in 'IL':
  19. return channel, length
  20. else:
  21. return channel, server.stdout.read(length)
  22. def sep(text):
  23. return text.replace('\\', '/')
  24. def runcommand(server, args, output=sys.stdout, error=sys.stderr, input=None,
  25. outfilter=lambda x: x):
  26. print ' runcommand', ' '.join(args)
  27. sys.stdout.flush()
  28. server.stdin.write('runcommand\n')
  29. writeblock(server, '\0'.join(args))
  30. if not input:
  31. input = cStringIO.StringIO()
  32. while True:
  33. ch, data = readchannel(server)
  34. if ch == 'o':
  35. output.write(outfilter(data))
  36. output.flush()
  37. elif ch == 'e':
  38. error.write(data)
  39. error.flush()
  40. elif ch == 'I':
  41. writeblock(server, input.read(data))
  42. elif ch == 'L':
  43. writeblock(server, input.readline(data))
  44. elif ch == 'r':
  45. ret, = struct.unpack('>i', data)
  46. if ret != 0:
  47. print ' [%d]' % ret
  48. return ret
  49. else:
  50. print "unexpected channel %c: %r" % (ch, data)
  51. if ch.isupper():
  52. return
  53. def check(func, repopath=None):
  54. print
  55. print 'testing %s:' % func.__name__
  56. print
  57. sys.stdout.flush()
  58. server = connect(repopath)
  59. try:
  60. return func(server)
  61. finally:
  62. server.stdin.close()
  63. server.wait()
  64. def unknowncommand(server):
  65. server.stdin.write('unknowncommand\n')
  66. def hellomessage(server):
  67. ch, data = readchannel(server)
  68. # escaping python tests output not supported
  69. print '%c, %r' % (ch, re.sub('encoding: [a-zA-Z0-9-]+', 'encoding: ***',
  70. data))
  71. # run an arbitrary command to make sure the next thing the server sends
  72. # isn't part of the hello message
  73. runcommand(server, ['id'])
  74. def checkruncommand(server):
  75. # hello block
  76. readchannel(server)
  77. # no args
  78. runcommand(server, [])
  79. # global options
  80. runcommand(server, ['id', '--quiet'])
  81. # make sure global options don't stick through requests
  82. runcommand(server, ['id'])
  83. # --config
  84. runcommand(server, ['id', '--config', 'ui.quiet=True'])
  85. # make sure --config doesn't stick
  86. runcommand(server, ['id'])
  87. # negative return code should be masked
  88. runcommand(server, ['id', '-runknown'])
  89. def inputeof(server):
  90. readchannel(server)
  91. server.stdin.write('runcommand\n')
  92. # close stdin while server is waiting for input
  93. server.stdin.close()
  94. # server exits with 1 if the pipe closed while reading the command
  95. print 'server exit code =', server.wait()
  96. def serverinput(server):
  97. readchannel(server)
  98. patch = """
  99. # HG changeset patch
  100. # User test
  101. # Date 0 0
  102. # Node ID c103a3dec114d882c98382d684d8af798d09d857
  103. # Parent 0000000000000000000000000000000000000000
  104. 1
  105. diff -r 000000000000 -r c103a3dec114 a
  106. --- /dev/null Thu Jan 01 00:00:00 1970 +0000
  107. +++ b/a Thu Jan 01 00:00:00 1970 +0000
  108. @@ -0,0 +1,1 @@
  109. +1
  110. """
  111. runcommand(server, ['import', '-'], input=cStringIO.StringIO(patch))
  112. runcommand(server, ['log'])
  113. def cwd(server):
  114. """ check that --cwd doesn't persist between requests """
  115. readchannel(server)
  116. os.mkdir('foo')
  117. f = open('foo/bar', 'wb')
  118. f.write('a')
  119. f.close()
  120. runcommand(server, ['--cwd', 'foo', 'st', 'bar'])
  121. runcommand(server, ['st', 'foo/bar'])
  122. os.remove('foo/bar')
  123. def localhgrc(server):
  124. """ check that local configs for the cached repo aren't inherited when -R
  125. is used """
  126. readchannel(server)
  127. # the cached repo local hgrc contains ui.foo=bar, so showconfig should
  128. # show it
  129. runcommand(server, ['showconfig'])
  130. # but not for this repo
  131. runcommand(server, ['init', 'foo'])
  132. runcommand(server, ['-R', 'foo', 'showconfig', 'ui', 'defaults'])
  133. shutil.rmtree('foo')
  134. def hook(**args):
  135. print 'hook talking'
  136. print 'now try to read something: %r' % sys.stdin.read()
  137. def hookoutput(server):
  138. readchannel(server)
  139. runcommand(server, ['--config',
  140. 'hooks.pre-identify=python:test-commandserver.hook',
  141. 'id'],
  142. input=cStringIO.StringIO('some input'))
  143. def outsidechanges(server):
  144. readchannel(server)
  145. f = open('a', 'ab')
  146. f.write('a\n')
  147. f.close()
  148. runcommand(server, ['status'])
  149. os.system('hg ci -Am2')
  150. runcommand(server, ['tip'])
  151. runcommand(server, ['status'])
  152. def bookmarks(server):
  153. readchannel(server)
  154. runcommand(server, ['bookmarks'])
  155. # changes .hg/bookmarks
  156. os.system('hg bookmark -i bm1')
  157. os.system('hg bookmark -i bm2')
  158. runcommand(server, ['bookmarks'])
  159. # changes .hg/bookmarks.current
  160. os.system('hg upd bm1 -q')
  161. runcommand(server, ['bookmarks'])
  162. runcommand(server, ['bookmarks', 'bm3'])
  163. f = open('a', 'ab')
  164. f.write('a\n')
  165. f.close()
  166. runcommand(server, ['commit', '-Amm'])
  167. runcommand(server, ['bookmarks'])
  168. def tagscache(server):
  169. readchannel(server)
  170. runcommand(server, ['id', '-t', '-r', '0'])
  171. os.system('hg tag -r 0 foo')
  172. runcommand(server, ['id', '-t', '-r', '0'])
  173. def setphase(server):
  174. readchannel(server)
  175. runcommand(server, ['phase', '-r', '.'])
  176. os.system('hg phase -r . -p')
  177. runcommand(server, ['phase', '-r', '.'])
  178. def rollback(server):
  179. readchannel(server)
  180. runcommand(server, ['phase', '-r', '.', '-p'])
  181. f = open('a', 'ab')
  182. f.write('a\n')
  183. f.close()
  184. runcommand(server, ['commit', '-Am.'])
  185. runcommand(server, ['rollback'])
  186. runcommand(server, ['phase', '-r', '.'])
  187. def branch(server):
  188. readchannel(server)
  189. runcommand(server, ['branch'])
  190. os.system('hg branch foo')
  191. runcommand(server, ['branch'])
  192. os.system('hg branch default')
  193. def hgignore(server):
  194. readchannel(server)
  195. f = open('.hgignore', 'ab')
  196. f.write('')
  197. f.close()
  198. runcommand(server, ['commit', '-Am.'])
  199. f = open('ignored-file', 'ab')
  200. f.write('')
  201. f.close()
  202. f = open('.hgignore', 'ab')
  203. f.write('ignored-file')
  204. f.close()
  205. runcommand(server, ['status', '-i', '-u'])
  206. def phasecacheafterstrip(server):
  207. readchannel(server)
  208. # create new head, 5:731265503d86
  209. runcommand(server, ['update', '-C', '0'])
  210. f = open('a', 'ab')
  211. f.write('a\n')
  212. f.close()
  213. runcommand(server, ['commit', '-Am.', 'a'])
  214. runcommand(server, ['log', '-Gq'])
  215. # make it public; draft marker moves to 4:7966c8e3734d
  216. runcommand(server, ['phase', '-p', '.'])
  217. # load _phasecache.phaseroots
  218. runcommand(server, ['phase', '.'], outfilter=sep)
  219. # strip 1::4 outside server
  220. os.system('hg -q --config extensions.mq= strip 1')
  221. # shouldn't raise "7966c8e3734d: no node!"
  222. runcommand(server, ['branches'])
  223. def obsolete(server):
  224. readchannel(server)
  225. runcommand(server, ['up', 'null'])
  226. runcommand(server, ['phase', '-df', 'tip'])
  227. cmd = 'hg debugobsolete `hg log -r tip --template {node}`'
  228. if os.name == 'nt':
  229. cmd = 'sh -c "%s"' % cmd # run in sh, not cmd.exe
  230. os.system(cmd)
  231. runcommand(server, ['log', '--hidden'])
  232. runcommand(server, ['log'])
  233. def mqoutsidechanges(server):
  234. readchannel(server)
  235. # load repo.mq
  236. runcommand(server, ['qapplied'])
  237. os.system('hg qnew 0.diff')
  238. # repo.mq should be invalidated
  239. runcommand(server, ['qapplied'])
  240. runcommand(server, ['qpop', '--all'])
  241. os.system('hg qqueue --create foo')
  242. # repo.mq should be recreated to point to new queue
  243. runcommand(server, ['qqueue', '--active'])
  244. def getpass(server):
  245. readchannel(server)
  246. runcommand(server, ['debuggetpass', '--config', 'ui.interactive=True'],
  247. input=cStringIO.StringIO('1234\n'))
  248. def startwithoutrepo(server):
  249. readchannel(server)
  250. runcommand(server, ['init', 'repo2'])
  251. runcommand(server, ['id', '-R', 'repo2'])
  252. if __name__ == '__main__':
  253. os.system('hg init repo')
  254. os.chdir('repo')
  255. check(hellomessage)
  256. check(unknowncommand)
  257. check(checkruncommand)
  258. check(inputeof)
  259. check(serverinput)
  260. check(cwd)
  261. hgrc = open('.hg/hgrc', 'a')
  262. hgrc.write('[ui]\nfoo=bar\n')
  263. hgrc.close()
  264. check(localhgrc)
  265. check(hookoutput)
  266. check(outsidechanges)
  267. check(bookmarks)
  268. check(tagscache)
  269. check(setphase)
  270. check(rollback)
  271. check(branch)
  272. check(hgignore)
  273. check(phasecacheafterstrip)
  274. obs = open('obs.py', 'w')
  275. obs.write('import mercurial.obsolete\nmercurial.obsolete._enabled = True\n')
  276. obs.close()
  277. hgrc = open('.hg/hgrc', 'a')
  278. hgrc.write('[extensions]\nobs=obs.py\n')
  279. hgrc.close()
  280. check(obsolete)
  281. hgrc = open('.hg/hgrc', 'a')
  282. hgrc.write('[extensions]\nmq=\n')
  283. hgrc.close()
  284. check(mqoutsidechanges)
  285. dbg = open('dbgui.py', 'w')
  286. dbg.write('from mercurial import cmdutil, commands\n'
  287. 'cmdtable = {}\n'
  288. 'command = cmdutil.command(cmdtable)\n'
  289. '@command("debuggetpass", norepo=True)\n'
  290. 'def debuggetpass(ui):\n'
  291. ' ui.write("%s\\n" % ui.getpass())\n')
  292. dbg.close()
  293. hgrc = open('.hg/hgrc', 'a')
  294. hgrc.write('[extensions]\ndbgui=dbgui.py\n')
  295. hgrc.close()
  296. check(getpass)
  297. os.chdir('..')
  298. check(hellomessage)
  299. check(startwithoutrepo)