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