##// END OF EJS Templates
tests: fix duplicate and failing test...
Gregory Szorc -
r37302:12bfc724 default
parent child Browse files
Show More
@@ -1,626 +1,639 b''
1 from __future__ import absolute_import, print_function
1 from __future__ import absolute_import, print_function
2
2
3 import unittest
3 import unittest
4
4
5 from mercurial import (
5 from mercurial import (
6 util,
6 util,
7 wireprotoframing as framing,
7 wireprotoframing as framing,
8 )
8 )
9
9
10 ffs = framing.makeframefromhumanstring
10 ffs = framing.makeframefromhumanstring
11
11
12 def makereactor(deferoutput=False):
12 def makereactor(deferoutput=False):
13 return framing.serverreactor(deferoutput=deferoutput)
13 return framing.serverreactor(deferoutput=deferoutput)
14
14
15 def sendframes(reactor, gen):
15 def sendframes(reactor, gen):
16 """Send a generator of frame bytearray to a reactor.
16 """Send a generator of frame bytearray to a reactor.
17
17
18 Emits a generator of results from ``onframerecv()`` calls.
18 Emits a generator of results from ``onframerecv()`` calls.
19 """
19 """
20 for frame in gen:
20 for frame in gen:
21 header = framing.parseheader(frame)
21 header = framing.parseheader(frame)
22 payload = frame[framing.FRAME_HEADER_SIZE:]
22 payload = frame[framing.FRAME_HEADER_SIZE:]
23 assert len(payload) == header.length
23 assert len(payload) == header.length
24
24
25 yield reactor.onframerecv(framing.frame(header.requestid,
25 yield reactor.onframerecv(framing.frame(header.requestid,
26 header.typeid,
26 header.typeid,
27 header.flags,
27 header.flags,
28 payload))
28 payload))
29
29
30 def sendcommandframes(reactor, rid, cmd, args, datafh=None):
30 def sendcommandframes(reactor, rid, cmd, args, datafh=None):
31 """Generate frames to run a command and send them to a reactor."""
31 """Generate frames to run a command and send them to a reactor."""
32 return sendframes(reactor,
32 return sendframes(reactor,
33 framing.createcommandframes(rid, cmd, args, datafh))
33 framing.createcommandframes(rid, cmd, args, datafh))
34
34
35 class FrameTests(unittest.TestCase):
35 class FrameTests(unittest.TestCase):
36 def testdataexactframesize(self):
36 def testdataexactframesize(self):
37 data = util.bytesio(b'x' * framing.DEFAULT_MAX_FRAME_SIZE)
37 data = util.bytesio(b'x' * framing.DEFAULT_MAX_FRAME_SIZE)
38
38
39 frames = list(framing.createcommandframes(1, b'command', {}, data))
39 frames = list(framing.createcommandframes(1, b'command', {}, data))
40 self.assertEqual(frames, [
40 self.assertEqual(frames, [
41 ffs(b'1 command-name have-data command'),
41 ffs(b'1 command-name have-data command'),
42 ffs(b'1 command-data continuation %s' % data.getvalue()),
42 ffs(b'1 command-data continuation %s' % data.getvalue()),
43 ffs(b'1 command-data eos ')
43 ffs(b'1 command-data eos ')
44 ])
44 ])
45
45
46 def testdatamultipleframes(self):
46 def testdatamultipleframes(self):
47 data = util.bytesio(b'x' * (framing.DEFAULT_MAX_FRAME_SIZE + 1))
47 data = util.bytesio(b'x' * (framing.DEFAULT_MAX_FRAME_SIZE + 1))
48 frames = list(framing.createcommandframes(1, b'command', {}, data))
48 frames = list(framing.createcommandframes(1, b'command', {}, data))
49 self.assertEqual(frames, [
49 self.assertEqual(frames, [
50 ffs(b'1 command-name have-data command'),
50 ffs(b'1 command-name have-data command'),
51 ffs(b'1 command-data continuation %s' % (
51 ffs(b'1 command-data continuation %s' % (
52 b'x' * framing.DEFAULT_MAX_FRAME_SIZE)),
52 b'x' * framing.DEFAULT_MAX_FRAME_SIZE)),
53 ffs(b'1 command-data eos x'),
53 ffs(b'1 command-data eos x'),
54 ])
54 ])
55
55
56 def testargsanddata(self):
56 def testargsanddata(self):
57 data = util.bytesio(b'x' * 100)
57 data = util.bytesio(b'x' * 100)
58
58
59 frames = list(framing.createcommandframes(1, b'command', {
59 frames = list(framing.createcommandframes(1, b'command', {
60 b'key1': b'key1value',
60 b'key1': b'key1value',
61 b'key2': b'key2value',
61 b'key2': b'key2value',
62 b'key3': b'key3value',
62 b'key3': b'key3value',
63 }, data))
63 }, data))
64
64
65 self.assertEqual(frames, [
65 self.assertEqual(frames, [
66 ffs(b'1 command-name have-args|have-data command'),
66 ffs(b'1 command-name have-args|have-data command'),
67 ffs(br'1 command-argument 0 \x04\x00\x09\x00key1key1value'),
67 ffs(br'1 command-argument 0 \x04\x00\x09\x00key1key1value'),
68 ffs(br'1 command-argument 0 \x04\x00\x09\x00key2key2value'),
68 ffs(br'1 command-argument 0 \x04\x00\x09\x00key2key2value'),
69 ffs(br'1 command-argument eoa \x04\x00\x09\x00key3key3value'),
69 ffs(br'1 command-argument eoa \x04\x00\x09\x00key3key3value'),
70 ffs(b'1 command-data eos %s' % data.getvalue()),
70 ffs(b'1 command-data eos %s' % data.getvalue()),
71 ])
71 ])
72
72
73 def testtextoutputexcessiveargs(self):
73 def testtextoutputexcessiveargs(self):
74 """At most 255 formatting arguments are allowed."""
74 """At most 255 formatting arguments are allowed."""
75 with self.assertRaisesRegexp(ValueError,
75 with self.assertRaisesRegexp(ValueError,
76 'cannot use more than 255 formatting'):
76 'cannot use more than 255 formatting'):
77 args = [b'x' for i in range(256)]
77 args = [b'x' for i in range(256)]
78 list(framing.createtextoutputframe(1, [(b'bleh', args, [])]))
78 list(framing.createtextoutputframe(1, [(b'bleh', args, [])]))
79
79
80 def testtextoutputexcessivelabels(self):
80 def testtextoutputexcessivelabels(self):
81 """At most 255 labels are allowed."""
81 """At most 255 labels are allowed."""
82 with self.assertRaisesRegexp(ValueError,
82 with self.assertRaisesRegexp(ValueError,
83 'cannot use more than 255 labels'):
83 'cannot use more than 255 labels'):
84 labels = [b'l' for i in range(256)]
84 labels = [b'l' for i in range(256)]
85 list(framing.createtextoutputframe(1, [(b'bleh', [], labels)]))
85 list(framing.createtextoutputframe(1, [(b'bleh', [], labels)]))
86
86
87 def testtextoutputformattingstringtype(self):
87 def testtextoutputformattingstringtype(self):
88 """Formatting string must be bytes."""
88 """Formatting string must be bytes."""
89 with self.assertRaisesRegexp(ValueError, 'must use bytes formatting '):
89 with self.assertRaisesRegexp(ValueError, 'must use bytes formatting '):
90 list(framing.createtextoutputframe(1, [
90 list(framing.createtextoutputframe(1, [
91 (b'foo'.decode('ascii'), [], [])]))
91 (b'foo'.decode('ascii'), [], [])]))
92
92
93 def testtextoutputargumentbytes(self):
93 def testtextoutputargumentbytes(self):
94 with self.assertRaisesRegexp(ValueError, 'must use bytes for argument'):
94 with self.assertRaisesRegexp(ValueError, 'must use bytes for argument'):
95 list(framing.createtextoutputframe(1, [
95 list(framing.createtextoutputframe(1, [
96 (b'foo', [b'foo'.decode('ascii')], [])]))
96 (b'foo', [b'foo'.decode('ascii')], [])]))
97
97
98 def testtextoutputlabelbytes(self):
98 def testtextoutputlabelbytes(self):
99 with self.assertRaisesRegexp(ValueError, 'must use bytes for labels'):
99 with self.assertRaisesRegexp(ValueError, 'must use bytes for labels'):
100 list(framing.createtextoutputframe(1, [
100 list(framing.createtextoutputframe(1, [
101 (b'foo', [], [b'foo'.decode('ascii')])]))
101 (b'foo', [], [b'foo'.decode('ascii')])]))
102
102
103 def testtextoutputtoolongformatstring(self):
103 def testtextoutputtoolongformatstring(self):
104 with self.assertRaisesRegexp(ValueError,
104 with self.assertRaisesRegexp(ValueError,
105 'formatting string cannot be longer than'):
105 'formatting string cannot be longer than'):
106 list(framing.createtextoutputframe(1, [
106 list(framing.createtextoutputframe(1, [
107 (b'x' * 65536, [], [])]))
107 (b'x' * 65536, [], [])]))
108
108
109 def testtextoutputtoolongargumentstring(self):
109 def testtextoutputtoolongargumentstring(self):
110 with self.assertRaisesRegexp(ValueError,
110 with self.assertRaisesRegexp(ValueError,
111 'argument string cannot be longer than'):
111 'argument string cannot be longer than'):
112 list(framing.createtextoutputframe(1, [
112 list(framing.createtextoutputframe(1, [
113 (b'bleh', [b'x' * 65536], [])]))
113 (b'bleh', [b'x' * 65536], [])]))
114
114
115 def testtextoutputtoolonglabelstring(self):
115 def testtextoutputtoolonglabelstring(self):
116 with self.assertRaisesRegexp(ValueError,
116 with self.assertRaisesRegexp(ValueError,
117 'label string cannot be longer than'):
117 'label string cannot be longer than'):
118 list(framing.createtextoutputframe(1, [
118 list(framing.createtextoutputframe(1, [
119 (b'bleh', [], [b'x' * 65536])]))
119 (b'bleh', [], [b'x' * 65536])]))
120
120
121 def testtextoutput1simpleatom(self):
121 def testtextoutput1simpleatom(self):
122 val = list(framing.createtextoutputframe(1, [
122 val = list(framing.createtextoutputframe(1, [
123 (b'foo', [], [])]))
123 (b'foo', [], [])]))
124
124
125 self.assertEqual(val, [
125 self.assertEqual(val, [
126 ffs(br'1 text-output 0 \x03\x00\x00\x00foo'),
126 ffs(br'1 text-output 0 \x03\x00\x00\x00foo'),
127 ])
127 ])
128
128
129 def testtextoutput2simpleatoms(self):
129 def testtextoutput2simpleatoms(self):
130 val = list(framing.createtextoutputframe(1, [
130 val = list(framing.createtextoutputframe(1, [
131 (b'foo', [], []),
131 (b'foo', [], []),
132 (b'bar', [], []),
132 (b'bar', [], []),
133 ]))
133 ]))
134
134
135 self.assertEqual(val, [
135 self.assertEqual(val, [
136 ffs(br'1 text-output 0 \x03\x00\x00\x00foo\x03\x00\x00\x00bar'),
136 ffs(br'1 text-output 0 \x03\x00\x00\x00foo\x03\x00\x00\x00bar'),
137 ])
137 ])
138
138
139 def testtextoutput1arg(self):
139 def testtextoutput1arg(self):
140 val = list(framing.createtextoutputframe(1, [
140 val = list(framing.createtextoutputframe(1, [
141 (b'foo %s', [b'val1'], []),
141 (b'foo %s', [b'val1'], []),
142 ]))
142 ]))
143
143
144 self.assertEqual(val, [
144 self.assertEqual(val, [
145 ffs(br'1 text-output 0 \x06\x00\x00\x01\x04\x00foo %sval1'),
145 ffs(br'1 text-output 0 \x06\x00\x00\x01\x04\x00foo %sval1'),
146 ])
146 ])
147
147
148 def testtextoutput2arg(self):
148 def testtextoutput2arg(self):
149 val = list(framing.createtextoutputframe(1, [
149 val = list(framing.createtextoutputframe(1, [
150 (b'foo %s %s', [b'val', b'value'], []),
150 (b'foo %s %s', [b'val', b'value'], []),
151 ]))
151 ]))
152
152
153 self.assertEqual(val, [
153 self.assertEqual(val, [
154 ffs(br'1 text-output 0 \x09\x00\x00\x02\x03\x00\x05\x00'
154 ffs(br'1 text-output 0 \x09\x00\x00\x02\x03\x00\x05\x00'
155 br'foo %s %svalvalue'),
155 br'foo %s %svalvalue'),
156 ])
156 ])
157
157
158 def testtextoutput1label(self):
158 def testtextoutput1label(self):
159 val = list(framing.createtextoutputframe(1, [
159 val = list(framing.createtextoutputframe(1, [
160 (b'foo', [], [b'label']),
160 (b'foo', [], [b'label']),
161 ]))
161 ]))
162
162
163 self.assertEqual(val, [
163 self.assertEqual(val, [
164 ffs(br'1 text-output 0 \x03\x00\x01\x00\x05foolabel'),
164 ffs(br'1 text-output 0 \x03\x00\x01\x00\x05foolabel'),
165 ])
165 ])
166
166
167 def testargandlabel(self):
167 def testargandlabel(self):
168 val = list(framing.createtextoutputframe(1, [
168 val = list(framing.createtextoutputframe(1, [
169 (b'foo %s', [b'arg'], [b'label']),
169 (b'foo %s', [b'arg'], [b'label']),
170 ]))
170 ]))
171
171
172 self.assertEqual(val, [
172 self.assertEqual(val, [
173 ffs(br'1 text-output 0 \x06\x00\x01\x01\x05\x03\x00foo %slabelarg'),
173 ffs(br'1 text-output 0 \x06\x00\x01\x01\x05\x03\x00foo %slabelarg'),
174 ])
174 ])
175
175
176 class ServerReactorTests(unittest.TestCase):
176 class ServerReactorTests(unittest.TestCase):
177 def _sendsingleframe(self, reactor, s):
177 def _sendsingleframe(self, reactor, f):
178 results = list(sendframes(reactor, [ffs(s)]))
178 results = list(sendframes(reactor, [f]))
179 self.assertEqual(len(results), 1)
179 self.assertEqual(len(results), 1)
180
180
181 return results[0]
181 return results[0]
182
182
183 def assertaction(self, res, expected):
183 def assertaction(self, res, expected):
184 self.assertIsInstance(res, tuple)
184 self.assertIsInstance(res, tuple)
185 self.assertEqual(len(res), 2)
185 self.assertEqual(len(res), 2)
186 self.assertIsInstance(res[1], dict)
186 self.assertIsInstance(res[1], dict)
187 self.assertEqual(res[0], expected)
187 self.assertEqual(res[0], expected)
188
188
189 def assertframesequal(self, frames, framestrings):
189 def assertframesequal(self, frames, framestrings):
190 expected = [ffs(s) for s in framestrings]
190 expected = [ffs(s) for s in framestrings]
191 self.assertEqual(list(frames), expected)
191 self.assertEqual(list(frames), expected)
192
192
193 def test1framecommand(self):
193 def test1framecommand(self):
194 """Receiving a command in a single frame yields request to run it."""
194 """Receiving a command in a single frame yields request to run it."""
195 reactor = makereactor()
195 reactor = makereactor()
196 results = list(sendcommandframes(reactor, 1, b'mycommand', {}))
196 results = list(sendcommandframes(reactor, 1, b'mycommand', {}))
197 self.assertEqual(len(results), 1)
197 self.assertEqual(len(results), 1)
198 self.assertaction(results[0], 'runcommand')
198 self.assertaction(results[0], 'runcommand')
199 self.assertEqual(results[0][1], {
199 self.assertEqual(results[0][1], {
200 'requestid': 1,
200 'requestid': 1,
201 'command': b'mycommand',
201 'command': b'mycommand',
202 'args': {},
202 'args': {},
203 'data': None,
203 'data': None,
204 })
204 })
205
205
206 result = reactor.oninputeof()
206 result = reactor.oninputeof()
207 self.assertaction(result, 'noop')
207 self.assertaction(result, 'noop')
208
208
209 def test1argument(self):
209 def test1argument(self):
210 reactor = makereactor()
210 reactor = makereactor()
211 results = list(sendcommandframes(reactor, 41, b'mycommand',
211 results = list(sendcommandframes(reactor, 41, b'mycommand',
212 {b'foo': b'bar'}))
212 {b'foo': b'bar'}))
213 self.assertEqual(len(results), 2)
213 self.assertEqual(len(results), 2)
214 self.assertaction(results[0], 'wantframe')
214 self.assertaction(results[0], 'wantframe')
215 self.assertaction(results[1], 'runcommand')
215 self.assertaction(results[1], 'runcommand')
216 self.assertEqual(results[1][1], {
216 self.assertEqual(results[1][1], {
217 'requestid': 41,
217 'requestid': 41,
218 'command': b'mycommand',
218 'command': b'mycommand',
219 'args': {b'foo': b'bar'},
219 'args': {b'foo': b'bar'},
220 'data': None,
220 'data': None,
221 })
221 })
222
222
223 def testmultiarguments(self):
223 def testmultiarguments(self):
224 reactor = makereactor()
224 reactor = makereactor()
225 results = list(sendcommandframes(reactor, 1, b'mycommand',
225 results = list(sendcommandframes(reactor, 1, b'mycommand',
226 {b'foo': b'bar', b'biz': b'baz'}))
226 {b'foo': b'bar', b'biz': b'baz'}))
227 self.assertEqual(len(results), 3)
227 self.assertEqual(len(results), 3)
228 self.assertaction(results[0], 'wantframe')
228 self.assertaction(results[0], 'wantframe')
229 self.assertaction(results[1], 'wantframe')
229 self.assertaction(results[1], 'wantframe')
230 self.assertaction(results[2], 'runcommand')
230 self.assertaction(results[2], 'runcommand')
231 self.assertEqual(results[2][1], {
231 self.assertEqual(results[2][1], {
232 'requestid': 1,
232 'requestid': 1,
233 'command': b'mycommand',
233 'command': b'mycommand',
234 'args': {b'foo': b'bar', b'biz': b'baz'},
234 'args': {b'foo': b'bar', b'biz': b'baz'},
235 'data': None,
235 'data': None,
236 })
236 })
237
237
238 def testsimplecommanddata(self):
238 def testsimplecommanddata(self):
239 reactor = makereactor()
239 reactor = makereactor()
240 results = list(sendcommandframes(reactor, 1, b'mycommand', {},
240 results = list(sendcommandframes(reactor, 1, b'mycommand', {},
241 util.bytesio(b'data!')))
241 util.bytesio(b'data!')))
242 self.assertEqual(len(results), 2)
242 self.assertEqual(len(results), 2)
243 self.assertaction(results[0], 'wantframe')
243 self.assertaction(results[0], 'wantframe')
244 self.assertaction(results[1], 'runcommand')
244 self.assertaction(results[1], 'runcommand')
245 self.assertEqual(results[1][1], {
245 self.assertEqual(results[1][1], {
246 'requestid': 1,
246 'requestid': 1,
247 'command': b'mycommand',
247 'command': b'mycommand',
248 'args': {},
248 'args': {},
249 'data': b'data!',
249 'data': b'data!',
250 })
250 })
251
251
252 def testmultipledataframes(self):
252 def testmultipledataframes(self):
253 frames = [
253 frames = [
254 ffs(b'1 command-name have-data mycommand'),
254 ffs(b'1 command-name have-data mycommand'),
255 ffs(b'1 command-data continuation data1'),
255 ffs(b'1 command-data continuation data1'),
256 ffs(b'1 command-data continuation data2'),
256 ffs(b'1 command-data continuation data2'),
257 ffs(b'1 command-data eos data3'),
257 ffs(b'1 command-data eos data3'),
258 ]
258 ]
259
259
260 reactor = makereactor()
260 reactor = makereactor()
261 results = list(sendframes(reactor, frames))
261 results = list(sendframes(reactor, frames))
262 self.assertEqual(len(results), 4)
262 self.assertEqual(len(results), 4)
263 for i in range(3):
263 for i in range(3):
264 self.assertaction(results[i], 'wantframe')
264 self.assertaction(results[i], 'wantframe')
265 self.assertaction(results[3], 'runcommand')
265 self.assertaction(results[3], 'runcommand')
266 self.assertEqual(results[3][1], {
266 self.assertEqual(results[3][1], {
267 'requestid': 1,
267 'requestid': 1,
268 'command': b'mycommand',
268 'command': b'mycommand',
269 'args': {},
269 'args': {},
270 'data': b'data1data2data3',
270 'data': b'data1data2data3',
271 })
271 })
272
272
273 def testargumentanddata(self):
273 def testargumentanddata(self):
274 frames = [
274 frames = [
275 ffs(b'1 command-name have-args|have-data command'),
275 ffs(b'1 command-name have-args|have-data command'),
276 ffs(br'1 command-argument 0 \x03\x00\x03\x00keyval'),
276 ffs(br'1 command-argument 0 \x03\x00\x03\x00keyval'),
277 ffs(br'1 command-argument eoa \x03\x00\x03\x00foobar'),
277 ffs(br'1 command-argument eoa \x03\x00\x03\x00foobar'),
278 ffs(b'1 command-data continuation value1'),
278 ffs(b'1 command-data continuation value1'),
279 ffs(b'1 command-data eos value2'),
279 ffs(b'1 command-data eos value2'),
280 ]
280 ]
281
281
282 reactor = makereactor()
282 reactor = makereactor()
283 results = list(sendframes(reactor, frames))
283 results = list(sendframes(reactor, frames))
284
284
285 self.assertaction(results[-1], 'runcommand')
285 self.assertaction(results[-1], 'runcommand')
286 self.assertEqual(results[-1][1], {
286 self.assertEqual(results[-1][1], {
287 'requestid': 1,
287 'requestid': 1,
288 'command': b'command',
288 'command': b'command',
289 'args': {
289 'args': {
290 b'key': b'val',
290 b'key': b'val',
291 b'foo': b'bar',
291 b'foo': b'bar',
292 },
292 },
293 'data': b'value1value2',
293 'data': b'value1value2',
294 })
294 })
295
295
296 def testunexpectedcommandargument(self):
296 def testunexpectedcommandargument(self):
297 """Command argument frame when not running a command is an error."""
297 """Command argument frame when not running a command is an error."""
298 result = self._sendsingleframe(makereactor(),
298 result = self._sendsingleframe(makereactor(),
299 b'1 command-argument 0 ignored')
299 ffs(b'1 command-argument 0 ignored'))
300 self.assertaction(result, 'error')
300 self.assertaction(result, 'error')
301 self.assertEqual(result[1], {
301 self.assertEqual(result[1], {
302 'message': b'expected command frame; got 2',
302 'message': b'expected command frame; got 2',
303 })
303 })
304
304
305 def testunexpectedcommandargumentreceiving(self):
305 def testunexpectedcommandargumentreceiving(self):
306 """Same as above but the command is receiving."""
306 """Same as above but the command is receiving."""
307 results = list(sendframes(makereactor(), [
307 results = list(sendframes(makereactor(), [
308 ffs(b'1 command-name have-data command'),
308 ffs(b'1 command-name have-data command'),
309 ffs(b'1 command-argument eoa ignored'),
309 ffs(b'1 command-argument eoa ignored'),
310 ]))
310 ]))
311
311
312 self.assertaction(results[1], 'error')
312 self.assertaction(results[1], 'error')
313 self.assertEqual(results[1][1], {
313 self.assertEqual(results[1][1], {
314 'message': b'received command argument frame for request that is '
314 'message': b'received command argument frame for request that is '
315 b'not expecting arguments: 1',
315 b'not expecting arguments: 1',
316 })
316 })
317
317
318 def testunexpectedcommanddata(self):
318 def testunexpectedcommanddata(self):
319 """Command argument frame when not running a command is an error."""
319 """Command argument frame when not running a command is an error."""
320 result = self._sendsingleframe(makereactor(),
320 result = self._sendsingleframe(makereactor(),
321 b'1 command-data 0 ignored')
321 ffs(b'1 command-data 0 ignored'))
322 self.assertaction(result, 'error')
322 self.assertaction(result, 'error')
323 self.assertEqual(result[1], {
323 self.assertEqual(result[1], {
324 'message': b'expected command frame; got 3',
324 'message': b'expected command frame; got 3',
325 })
325 })
326
326
327 def testunexpectedcommanddatareceiving(self):
327 def testunexpectedcommanddatareceiving(self):
328 """Same as above except the command is receiving."""
328 """Same as above except the command is receiving."""
329 results = list(sendframes(makereactor(), [
329 results = list(sendframes(makereactor(), [
330 ffs(b'1 command-name have-args command'),
330 ffs(b'1 command-name have-args command'),
331 ffs(b'1 command-data eos ignored'),
331 ffs(b'1 command-data eos ignored'),
332 ]))
332 ]))
333
333
334 self.assertaction(results[1], 'error')
334 self.assertaction(results[1], 'error')
335 self.assertEqual(results[1][1], {
335 self.assertEqual(results[1][1], {
336 'message': b'received command data frame for request that is not '
336 'message': b'received command data frame for request that is not '
337 b'expecting data: 1',
337 b'expecting data: 1',
338 })
338 })
339
339
340 def testmissingcommandframeflags(self):
340 def testmissingcommandframeflags(self):
341 """Command name frame must have flags set."""
341 """Command name frame must have flags set."""
342 result = self._sendsingleframe(makereactor(),
342 result = self._sendsingleframe(makereactor(),
343 b'1 command-name 0 command')
343 ffs(b'1 command-name 0 command'))
344 self.assertaction(result, 'error')
344 self.assertaction(result, 'error')
345 self.assertEqual(result[1], {
345 self.assertEqual(result[1], {
346 'message': b'missing frame flags on command frame',
346 'message': b'missing frame flags on command frame',
347 })
347 })
348
348
349 def testconflictingrequestid(self):
349 def testconflictingrequestidallowed(self):
350 """Multiple fully serviced commands with same request ID is allowed."""
350 """Multiple fully serviced commands with same request ID is allowed."""
351 results = list(sendframes(makereactor(), [
351 reactor = makereactor()
352 ffs(b'1 command-name eos command'),
352 results = []
353 ffs(b'1 command-name eos command'),
353 results.append(self._sendsingleframe(
354 ffs(b'1 command-name eos command'),
354 reactor, ffs(b'1 command-name eos command')))
355 ]))
355 result = reactor.onbytesresponseready(1, b'response1')
356 self.assertaction(result, 'sendframes')
357 list(result[1]['framegen'])
358 results.append(self._sendsingleframe(
359 reactor, ffs(b'1 command-name eos command')))
360 result = reactor.onbytesresponseready(1, b'response2')
361 self.assertaction(result, 'sendframes')
362 list(result[1]['framegen'])
363 results.append(self._sendsingleframe(
364 reactor, ffs(b'1 command-name eos command')))
365 result = reactor.onbytesresponseready(1, b'response3')
366 self.assertaction(result, 'sendframes')
367 list(result[1]['framegen'])
368
356 for i in range(3):
369 for i in range(3):
357 self.assertaction(results[i], 'runcommand')
370 self.assertaction(results[i], 'runcommand')
358 self.assertEqual(results[i][1], {
371 self.assertEqual(results[i][1], {
359 'requestid': 1,
372 'requestid': 1,
360 'command': b'command',
373 'command': b'command',
361 'args': {},
374 'args': {},
362 'data': None,
375 'data': None,
363 })
376 })
364
377
365 def testconflictingrequestid(self):
378 def testconflictingrequestid(self):
366 """Request ID for new command matching in-flight command is illegal."""
379 """Request ID for new command matching in-flight command is illegal."""
367 results = list(sendframes(makereactor(), [
380 results = list(sendframes(makereactor(), [
368 ffs(b'1 command-name have-args command'),
381 ffs(b'1 command-name have-args command'),
369 ffs(b'1 command-name eos command'),
382 ffs(b'1 command-name eos command'),
370 ]))
383 ]))
371
384
372 self.assertaction(results[0], 'wantframe')
385 self.assertaction(results[0], 'wantframe')
373 self.assertaction(results[1], 'error')
386 self.assertaction(results[1], 'error')
374 self.assertEqual(results[1][1], {
387 self.assertEqual(results[1][1], {
375 'message': b'request with ID 1 already received',
388 'message': b'request with ID 1 already received',
376 })
389 })
377
390
378 def testinterleavedcommands(self):
391 def testinterleavedcommands(self):
379 results = list(sendframes(makereactor(), [
392 results = list(sendframes(makereactor(), [
380 ffs(b'1 command-name have-args command1'),
393 ffs(b'1 command-name have-args command1'),
381 ffs(b'3 command-name have-args command3'),
394 ffs(b'3 command-name have-args command3'),
382 ffs(br'1 command-argument 0 \x03\x00\x03\x00foobar'),
395 ffs(br'1 command-argument 0 \x03\x00\x03\x00foobar'),
383 ffs(br'3 command-argument 0 \x03\x00\x03\x00bizbaz'),
396 ffs(br'3 command-argument 0 \x03\x00\x03\x00bizbaz'),
384 ffs(br'3 command-argument eoa \x03\x00\x03\x00keyval'),
397 ffs(br'3 command-argument eoa \x03\x00\x03\x00keyval'),
385 ffs(br'1 command-argument eoa \x04\x00\x03\x00key1val'),
398 ffs(br'1 command-argument eoa \x04\x00\x03\x00key1val'),
386 ]))
399 ]))
387
400
388 self.assertEqual([t[0] for t in results], [
401 self.assertEqual([t[0] for t in results], [
389 'wantframe',
402 'wantframe',
390 'wantframe',
403 'wantframe',
391 'wantframe',
404 'wantframe',
392 'wantframe',
405 'wantframe',
393 'runcommand',
406 'runcommand',
394 'runcommand',
407 'runcommand',
395 ])
408 ])
396
409
397 self.assertEqual(results[4][1], {
410 self.assertEqual(results[4][1], {
398 'requestid': 3,
411 'requestid': 3,
399 'command': 'command3',
412 'command': 'command3',
400 'args': {b'biz': b'baz', b'key': b'val'},
413 'args': {b'biz': b'baz', b'key': b'val'},
401 'data': None,
414 'data': None,
402 })
415 })
403 self.assertEqual(results[5][1], {
416 self.assertEqual(results[5][1], {
404 'requestid': 1,
417 'requestid': 1,
405 'command': 'command1',
418 'command': 'command1',
406 'args': {b'foo': b'bar', b'key1': b'val'},
419 'args': {b'foo': b'bar', b'key1': b'val'},
407 'data': None,
420 'data': None,
408 })
421 })
409
422
410 def testmissingargumentframe(self):
423 def testmissingargumentframe(self):
411 # This test attempts to test behavior when reactor has an incomplete
424 # This test attempts to test behavior when reactor has an incomplete
412 # command request waiting on argument data. But it doesn't handle that
425 # command request waiting on argument data. But it doesn't handle that
413 # scenario yet. So this test does nothing of value.
426 # scenario yet. So this test does nothing of value.
414 frames = [
427 frames = [
415 ffs(b'1 command-name have-args command'),
428 ffs(b'1 command-name have-args command'),
416 ]
429 ]
417
430
418 results = list(sendframes(makereactor(), frames))
431 results = list(sendframes(makereactor(), frames))
419 self.assertaction(results[0], 'wantframe')
432 self.assertaction(results[0], 'wantframe')
420
433
421 def testincompleteargumentname(self):
434 def testincompleteargumentname(self):
422 """Argument frame with incomplete name."""
435 """Argument frame with incomplete name."""
423 frames = [
436 frames = [
424 ffs(b'1 command-name have-args command1'),
437 ffs(b'1 command-name have-args command1'),
425 ffs(br'1 command-argument eoa \x04\x00\xde\xadfoo'),
438 ffs(br'1 command-argument eoa \x04\x00\xde\xadfoo'),
426 ]
439 ]
427
440
428 results = list(sendframes(makereactor(), frames))
441 results = list(sendframes(makereactor(), frames))
429 self.assertEqual(len(results), 2)
442 self.assertEqual(len(results), 2)
430 self.assertaction(results[0], 'wantframe')
443 self.assertaction(results[0], 'wantframe')
431 self.assertaction(results[1], 'error')
444 self.assertaction(results[1], 'error')
432 self.assertEqual(results[1][1], {
445 self.assertEqual(results[1][1], {
433 'message': b'malformed argument frame: partial argument name',
446 'message': b'malformed argument frame: partial argument name',
434 })
447 })
435
448
436 def testincompleteargumentvalue(self):
449 def testincompleteargumentvalue(self):
437 """Argument frame with incomplete value."""
450 """Argument frame with incomplete value."""
438 frames = [
451 frames = [
439 ffs(b'1 command-name have-args command'),
452 ffs(b'1 command-name have-args command'),
440 ffs(br'1 command-argument eoa \x03\x00\xaa\xaafoopartialvalue'),
453 ffs(br'1 command-argument eoa \x03\x00\xaa\xaafoopartialvalue'),
441 ]
454 ]
442
455
443 results = list(sendframes(makereactor(), frames))
456 results = list(sendframes(makereactor(), frames))
444 self.assertEqual(len(results), 2)
457 self.assertEqual(len(results), 2)
445 self.assertaction(results[0], 'wantframe')
458 self.assertaction(results[0], 'wantframe')
446 self.assertaction(results[1], 'error')
459 self.assertaction(results[1], 'error')
447 self.assertEqual(results[1][1], {
460 self.assertEqual(results[1][1], {
448 'message': b'malformed argument frame: partial argument value',
461 'message': b'malformed argument frame: partial argument value',
449 })
462 })
450
463
451 def testmissingcommanddataframe(self):
464 def testmissingcommanddataframe(self):
452 # The reactor doesn't currently handle partially received commands.
465 # The reactor doesn't currently handle partially received commands.
453 # So this test is failing to do anything with request 1.
466 # So this test is failing to do anything with request 1.
454 frames = [
467 frames = [
455 ffs(b'1 command-name have-data command1'),
468 ffs(b'1 command-name have-data command1'),
456 ffs(b'3 command-name eos command2'),
469 ffs(b'3 command-name eos command2'),
457 ]
470 ]
458 results = list(sendframes(makereactor(), frames))
471 results = list(sendframes(makereactor(), frames))
459 self.assertEqual(len(results), 2)
472 self.assertEqual(len(results), 2)
460 self.assertaction(results[0], 'wantframe')
473 self.assertaction(results[0], 'wantframe')
461 self.assertaction(results[1], 'runcommand')
474 self.assertaction(results[1], 'runcommand')
462
475
463 def testmissingcommanddataframeflags(self):
476 def testmissingcommanddataframeflags(self):
464 frames = [
477 frames = [
465 ffs(b'1 command-name have-data command1'),
478 ffs(b'1 command-name have-data command1'),
466 ffs(b'1 command-data 0 data'),
479 ffs(b'1 command-data 0 data'),
467 ]
480 ]
468 results = list(sendframes(makereactor(), frames))
481 results = list(sendframes(makereactor(), frames))
469 self.assertEqual(len(results), 2)
482 self.assertEqual(len(results), 2)
470 self.assertaction(results[0], 'wantframe')
483 self.assertaction(results[0], 'wantframe')
471 self.assertaction(results[1], 'error')
484 self.assertaction(results[1], 'error')
472 self.assertEqual(results[1][1], {
485 self.assertEqual(results[1][1], {
473 'message': b'command data frame without flags',
486 'message': b'command data frame without flags',
474 })
487 })
475
488
476 def testframefornonreceivingrequest(self):
489 def testframefornonreceivingrequest(self):
477 """Receiving a frame for a command that is not receiving is illegal."""
490 """Receiving a frame for a command that is not receiving is illegal."""
478 results = list(sendframes(makereactor(), [
491 results = list(sendframes(makereactor(), [
479 ffs(b'1 command-name eos command1'),
492 ffs(b'1 command-name eos command1'),
480 ffs(b'3 command-name have-data command3'),
493 ffs(b'3 command-name have-data command3'),
481 ffs(b'5 command-argument eoa ignored'),
494 ffs(b'5 command-argument eoa ignored'),
482 ]))
495 ]))
483 self.assertaction(results[2], 'error')
496 self.assertaction(results[2], 'error')
484 self.assertEqual(results[2][1], {
497 self.assertEqual(results[2][1], {
485 'message': b'received frame for request that is not receiving: 5',
498 'message': b'received frame for request that is not receiving: 5',
486 })
499 })
487
500
488 def testsimpleresponse(self):
501 def testsimpleresponse(self):
489 """Bytes response to command sends result frames."""
502 """Bytes response to command sends result frames."""
490 reactor = makereactor()
503 reactor = makereactor()
491 list(sendcommandframes(reactor, 1, b'mycommand', {}))
504 list(sendcommandframes(reactor, 1, b'mycommand', {}))
492
505
493 result = reactor.onbytesresponseready(1, b'response')
506 result = reactor.onbytesresponseready(1, b'response')
494 self.assertaction(result, 'sendframes')
507 self.assertaction(result, 'sendframes')
495 self.assertframesequal(result[1]['framegen'], [
508 self.assertframesequal(result[1]['framegen'], [
496 b'1 bytes-response eos response',
509 b'1 bytes-response eos response',
497 ])
510 ])
498
511
499 def testmultiframeresponse(self):
512 def testmultiframeresponse(self):
500 """Bytes response spanning multiple frames is handled."""
513 """Bytes response spanning multiple frames is handled."""
501 first = b'x' * framing.DEFAULT_MAX_FRAME_SIZE
514 first = b'x' * framing.DEFAULT_MAX_FRAME_SIZE
502 second = b'y' * 100
515 second = b'y' * 100
503
516
504 reactor = makereactor()
517 reactor = makereactor()
505 list(sendcommandframes(reactor, 1, b'mycommand', {}))
518 list(sendcommandframes(reactor, 1, b'mycommand', {}))
506
519
507 result = reactor.onbytesresponseready(1, first + second)
520 result = reactor.onbytesresponseready(1, first + second)
508 self.assertaction(result, 'sendframes')
521 self.assertaction(result, 'sendframes')
509 self.assertframesequal(result[1]['framegen'], [
522 self.assertframesequal(result[1]['framegen'], [
510 b'1 bytes-response continuation %s' % first,
523 b'1 bytes-response continuation %s' % first,
511 b'1 bytes-response eos %s' % second,
524 b'1 bytes-response eos %s' % second,
512 ])
525 ])
513
526
514 def testapplicationerror(self):
527 def testapplicationerror(self):
515 reactor = makereactor()
528 reactor = makereactor()
516 list(sendcommandframes(reactor, 1, b'mycommand', {}))
529 list(sendcommandframes(reactor, 1, b'mycommand', {}))
517
530
518 result = reactor.onapplicationerror(1, b'some message')
531 result = reactor.onapplicationerror(1, b'some message')
519 self.assertaction(result, 'sendframes')
532 self.assertaction(result, 'sendframes')
520 self.assertframesequal(result[1]['framegen'], [
533 self.assertframesequal(result[1]['framegen'], [
521 b'1 error-response application some message',
534 b'1 error-response application some message',
522 ])
535 ])
523
536
524 def test1commanddeferresponse(self):
537 def test1commanddeferresponse(self):
525 """Responses when in deferred output mode are delayed until EOF."""
538 """Responses when in deferred output mode are delayed until EOF."""
526 reactor = makereactor(deferoutput=True)
539 reactor = makereactor(deferoutput=True)
527 results = list(sendcommandframes(reactor, 1, b'mycommand', {}))
540 results = list(sendcommandframes(reactor, 1, b'mycommand', {}))
528 self.assertEqual(len(results), 1)
541 self.assertEqual(len(results), 1)
529 self.assertaction(results[0], 'runcommand')
542 self.assertaction(results[0], 'runcommand')
530
543
531 result = reactor.onbytesresponseready(1, b'response')
544 result = reactor.onbytesresponseready(1, b'response')
532 self.assertaction(result, 'noop')
545 self.assertaction(result, 'noop')
533 result = reactor.oninputeof()
546 result = reactor.oninputeof()
534 self.assertaction(result, 'sendframes')
547 self.assertaction(result, 'sendframes')
535 self.assertframesequal(result[1]['framegen'], [
548 self.assertframesequal(result[1]['framegen'], [
536 b'1 bytes-response eos response',
549 b'1 bytes-response eos response',
537 ])
550 ])
538
551
539 def testmultiplecommanddeferresponse(self):
552 def testmultiplecommanddeferresponse(self):
540 reactor = makereactor(deferoutput=True)
553 reactor = makereactor(deferoutput=True)
541 list(sendcommandframes(reactor, 1, b'command1', {}))
554 list(sendcommandframes(reactor, 1, b'command1', {}))
542 list(sendcommandframes(reactor, 3, b'command2', {}))
555 list(sendcommandframes(reactor, 3, b'command2', {}))
543
556
544 result = reactor.onbytesresponseready(1, b'response1')
557 result = reactor.onbytesresponseready(1, b'response1')
545 self.assertaction(result, 'noop')
558 self.assertaction(result, 'noop')
546 result = reactor.onbytesresponseready(3, b'response2')
559 result = reactor.onbytesresponseready(3, b'response2')
547 self.assertaction(result, 'noop')
560 self.assertaction(result, 'noop')
548 result = reactor.oninputeof()
561 result = reactor.oninputeof()
549 self.assertaction(result, 'sendframes')
562 self.assertaction(result, 'sendframes')
550 self.assertframesequal(result[1]['framegen'], [
563 self.assertframesequal(result[1]['framegen'], [
551 b'1 bytes-response eos response1',
564 b'1 bytes-response eos response1',
552 b'3 bytes-response eos response2'
565 b'3 bytes-response eos response2'
553 ])
566 ])
554
567
555 def testrequestidtracking(self):
568 def testrequestidtracking(self):
556 reactor = makereactor(deferoutput=True)
569 reactor = makereactor(deferoutput=True)
557 list(sendcommandframes(reactor, 1, b'command1', {}))
570 list(sendcommandframes(reactor, 1, b'command1', {}))
558 list(sendcommandframes(reactor, 3, b'command2', {}))
571 list(sendcommandframes(reactor, 3, b'command2', {}))
559 list(sendcommandframes(reactor, 5, b'command3', {}))
572 list(sendcommandframes(reactor, 5, b'command3', {}))
560
573
561 # Register results for commands out of order.
574 # Register results for commands out of order.
562 reactor.onbytesresponseready(3, b'response3')
575 reactor.onbytesresponseready(3, b'response3')
563 reactor.onbytesresponseready(1, b'response1')
576 reactor.onbytesresponseready(1, b'response1')
564 reactor.onbytesresponseready(5, b'response5')
577 reactor.onbytesresponseready(5, b'response5')
565
578
566 result = reactor.oninputeof()
579 result = reactor.oninputeof()
567 self.assertaction(result, 'sendframes')
580 self.assertaction(result, 'sendframes')
568 self.assertframesequal(result[1]['framegen'], [
581 self.assertframesequal(result[1]['framegen'], [
569 b'3 bytes-response eos response3',
582 b'3 bytes-response eos response3',
570 b'1 bytes-response eos response1',
583 b'1 bytes-response eos response1',
571 b'5 bytes-response eos response5',
584 b'5 bytes-response eos response5',
572 ])
585 ])
573
586
574 def testduplicaterequestonactivecommand(self):
587 def testduplicaterequestonactivecommand(self):
575 """Receiving a request ID that matches a request that isn't finished."""
588 """Receiving a request ID that matches a request that isn't finished."""
576 reactor = makereactor()
589 reactor = makereactor()
577 list(sendcommandframes(reactor, 1, b'command1', {}))
590 list(sendcommandframes(reactor, 1, b'command1', {}))
578 results = list(sendcommandframes(reactor, 1, b'command1', {}))
591 results = list(sendcommandframes(reactor, 1, b'command1', {}))
579
592
580 self.assertaction(results[0], 'error')
593 self.assertaction(results[0], 'error')
581 self.assertEqual(results[0][1], {
594 self.assertEqual(results[0][1], {
582 'message': b'request with ID 1 is already active',
595 'message': b'request with ID 1 is already active',
583 })
596 })
584
597
585 def testduplicaterequestonactivecommandnosend(self):
598 def testduplicaterequestonactivecommandnosend(self):
586 """Same as above but we've registered a response but haven't sent it."""
599 """Same as above but we've registered a response but haven't sent it."""
587 reactor = makereactor()
600 reactor = makereactor()
588 list(sendcommandframes(reactor, 1, b'command1', {}))
601 list(sendcommandframes(reactor, 1, b'command1', {}))
589 reactor.onbytesresponseready(1, b'response')
602 reactor.onbytesresponseready(1, b'response')
590
603
591 # We've registered the response but haven't sent it. From the
604 # We've registered the response but haven't sent it. From the
592 # perspective of the reactor, the command is still active.
605 # perspective of the reactor, the command is still active.
593
606
594 results = list(sendcommandframes(reactor, 1, b'command1', {}))
607 results = list(sendcommandframes(reactor, 1, b'command1', {}))
595 self.assertaction(results[0], 'error')
608 self.assertaction(results[0], 'error')
596 self.assertEqual(results[0][1], {
609 self.assertEqual(results[0][1], {
597 'message': b'request with ID 1 is already active',
610 'message': b'request with ID 1 is already active',
598 })
611 })
599
612
600 def testduplicaterequestargumentframe(self):
613 def testduplicaterequestargumentframe(self):
601 """Variant on above except we sent an argument frame instead of name."""
614 """Variant on above except we sent an argument frame instead of name."""
602 reactor = makereactor()
615 reactor = makereactor()
603 list(sendcommandframes(reactor, 1, b'command', {}))
616 list(sendcommandframes(reactor, 1, b'command', {}))
604 results = list(sendframes(reactor, [
617 results = list(sendframes(reactor, [
605 ffs(b'3 command-name have-args command'),
618 ffs(b'3 command-name have-args command'),
606 ffs(b'1 command-argument 0 ignored'),
619 ffs(b'1 command-argument 0 ignored'),
607 ]))
620 ]))
608 self.assertaction(results[0], 'wantframe')
621 self.assertaction(results[0], 'wantframe')
609 self.assertaction(results[1], 'error')
622 self.assertaction(results[1], 'error')
610 self.assertEqual(results[1][1], {
623 self.assertEqual(results[1][1], {
611 'message': 'received frame for request that is still active: 1',
624 'message': 'received frame for request that is still active: 1',
612 })
625 })
613
626
614 def testduplicaterequestaftersend(self):
627 def testduplicaterequestaftersend(self):
615 """We can use a duplicate request ID after we've sent the response."""
628 """We can use a duplicate request ID after we've sent the response."""
616 reactor = makereactor()
629 reactor = makereactor()
617 list(sendcommandframes(reactor, 1, b'command1', {}))
630 list(sendcommandframes(reactor, 1, b'command1', {}))
618 res = reactor.onbytesresponseready(1, b'response')
631 res = reactor.onbytesresponseready(1, b'response')
619 list(res[1]['framegen'])
632 list(res[1]['framegen'])
620
633
621 results = list(sendcommandframes(reactor, 1, b'command1', {}))
634 results = list(sendcommandframes(reactor, 1, b'command1', {}))
622 self.assertaction(results[0], 'runcommand')
635 self.assertaction(results[0], 'runcommand')
623
636
624 if __name__ == '__main__':
637 if __name__ == '__main__':
625 import silenttestrunner
638 import silenttestrunner
626 silenttestrunner.main(__name__)
639 silenttestrunner.main(__name__)
General Comments 0
You need to be logged in to leave comments. Login now