annotate tests/test-wireproto-clientreactor.py @ 37656:e6870bca1f47

wireprotoframing: record when new stream is encountered Without this, we choke after receiving the 2nd frame in a stream. Not sure how we made it this far without finding this bug. Differential Revision: https://phab.mercurial-scm.org/D3334
author Gregory Szorc <gregory.szorc@gmail.com>
date Fri, 13 Apr 2018 12:49:47 -0700
parents 55b5ba8d4e68
children cb71e0f9ac6f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
37543
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
1 from __future__ import absolute_import
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
2
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
3 import unittest
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
4
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
5 from mercurial import (
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
6 error,
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
7 wireprotoframing as framing,
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
8 )
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
9
37544
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
10 ffs = framing.makeframefromhumanstring
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
11
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
12 def sendframe(reactor, frame):
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
13 """Send a frame bytearray to a reactor."""
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
14 header = framing.parseheader(frame)
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
15 payload = frame[framing.FRAME_HEADER_SIZE:]
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
16 assert len(payload) == header.length
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
17
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
18 return reactor.onframerecv(framing.frame(header.requestid,
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
19 header.streamid,
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
20 header.streamflags,
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
21 header.typeid,
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
22 header.flags,
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
23 payload))
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
24
37543
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
25 class SingleSendTests(unittest.TestCase):
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
26 """A reactor that can only send once rejects subsequent sends."""
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
27 def testbasic(self):
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
28 reactor = framing.clientreactor(hasmultiplesend=False, buffersends=True)
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
29
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
30 request, action, meta = reactor.callcommand(b'foo', {})
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
31 self.assertEqual(request.state, 'pending')
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
32 self.assertEqual(action, 'noop')
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
33
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
34 action, meta = reactor.flushcommands()
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
35 self.assertEqual(action, 'sendframes')
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
36
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
37 for frame in meta['framegen']:
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
38 self.assertEqual(request.state, 'sending')
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
39
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
40 self.assertEqual(request.state, 'sent')
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
41
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
42 with self.assertRaisesRegexp(error.ProgrammingError,
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
43 'cannot issue new commands'):
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
44 reactor.callcommand(b'foo', {})
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
45
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
46 with self.assertRaisesRegexp(error.ProgrammingError,
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
47 'cannot issue new commands'):
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
48 reactor.callcommand(b'foo', {})
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
49
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
50 class NoBufferTests(unittest.TestCase):
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
51 """A reactor without send buffering sends requests immediately."""
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
52 def testbasic(self):
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
53 reactor = framing.clientreactor(hasmultiplesend=True, buffersends=False)
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
54
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
55 request, action, meta = reactor.callcommand(b'command1', {})
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
56 self.assertEqual(request.requestid, 1)
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
57 self.assertEqual(action, 'sendframes')
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
58
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
59 self.assertEqual(request.state, 'pending')
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
60
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
61 for frame in meta['framegen']:
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
62 self.assertEqual(request.state, 'sending')
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
63
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
64 self.assertEqual(request.state, 'sent')
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
65
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
66 action, meta = reactor.flushcommands()
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
67 self.assertEqual(action, 'noop')
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
68
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
69 # And we can send another command.
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
70 request, action, meta = reactor.callcommand(b'command2', {})
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
71 self.assertEqual(request.requestid, 3)
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
72 self.assertEqual(action, 'sendframes')
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
73
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
74 for frame in meta['framegen']:
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
75 self.assertEqual(request.state, 'sending')
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
76
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
77 self.assertEqual(request.state, 'sent')
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
78
37544
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
79 class BadFrameRecvTests(unittest.TestCase):
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
80 def testoddstream(self):
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
81 reactor = framing.clientreactor()
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
82
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
83 action, meta = sendframe(reactor, ffs(b'1 1 0 1 0 foo'))
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
84 self.assertEqual(action, 'error')
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
85 self.assertEqual(meta['message'],
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
86 'received frame with odd numbered stream ID: 1')
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
87
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
88 def testunknownstream(self):
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
89 reactor = framing.clientreactor()
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
90
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
91 action, meta = sendframe(reactor, ffs(b'1 0 0 1 0 foo'))
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
92 self.assertEqual(action, 'error')
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
93 self.assertEqual(meta['message'],
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
94 'received frame on unknown stream without beginning '
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
95 'of stream flag set')
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
96
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
97 def testunhandledframetype(self):
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
98 reactor = framing.clientreactor(buffersends=False)
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
99
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
100 request, action, meta = reactor.callcommand(b'foo', {})
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
101 for frame in meta['framegen']:
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
102 pass
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
103
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
104 with self.assertRaisesRegexp(error.ProgrammingError,
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
105 'unhandled frame type'):
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
106 sendframe(reactor, ffs(b'1 0 stream-begin text-output 0 foo'))
55b5ba8d4e68 wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37543
diff changeset
107
37656
e6870bca1f47 wireprotoframing: record when new stream is encountered
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37544
diff changeset
108 class StreamTests(unittest.TestCase):
e6870bca1f47 wireprotoframing: record when new stream is encountered
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37544
diff changeset
109 def testmultipleresponseframes(self):
e6870bca1f47 wireprotoframing: record when new stream is encountered
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37544
diff changeset
110 reactor = framing.clientreactor(buffersends=False)
e6870bca1f47 wireprotoframing: record when new stream is encountered
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37544
diff changeset
111
e6870bca1f47 wireprotoframing: record when new stream is encountered
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37544
diff changeset
112 request, action, meta = reactor.callcommand(b'foo', {})
e6870bca1f47 wireprotoframing: record when new stream is encountered
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37544
diff changeset
113
e6870bca1f47 wireprotoframing: record when new stream is encountered
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37544
diff changeset
114 self.assertEqual(action, 'sendframes')
e6870bca1f47 wireprotoframing: record when new stream is encountered
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37544
diff changeset
115 for f in meta['framegen']:
e6870bca1f47 wireprotoframing: record when new stream is encountered
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37544
diff changeset
116 pass
e6870bca1f47 wireprotoframing: record when new stream is encountered
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37544
diff changeset
117
e6870bca1f47 wireprotoframing: record when new stream is encountered
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37544
diff changeset
118 action, meta = sendframe(
e6870bca1f47 wireprotoframing: record when new stream is encountered
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37544
diff changeset
119 reactor,
e6870bca1f47 wireprotoframing: record when new stream is encountered
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37544
diff changeset
120 ffs(b'%d 0 stream-begin 4 0 foo' % request.requestid))
e6870bca1f47 wireprotoframing: record when new stream is encountered
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37544
diff changeset
121 self.assertEqual(action, 'responsedata')
e6870bca1f47 wireprotoframing: record when new stream is encountered
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37544
diff changeset
122
e6870bca1f47 wireprotoframing: record when new stream is encountered
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37544
diff changeset
123 action, meta = sendframe(
e6870bca1f47 wireprotoframing: record when new stream is encountered
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37544
diff changeset
124 reactor,
e6870bca1f47 wireprotoframing: record when new stream is encountered
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37544
diff changeset
125 ffs(b'%d 0 0 4 eos bar' % request.requestid))
e6870bca1f47 wireprotoframing: record when new stream is encountered
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37544
diff changeset
126 self.assertEqual(action, 'responsedata')
e6870bca1f47 wireprotoframing: record when new stream is encountered
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37544
diff changeset
127
37543
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
128 if __name__ == '__main__':
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
129 import silenttestrunner
01361be9e2dc wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
130 silenttestrunner.main(__name__)