##// END OF EJS Templates
tests: migrate test-wireproto-serverreactor.py to our internal CBOR...
tests: migrate test-wireproto-serverreactor.py to our internal CBOR This leaves the only client of thirdparty.cbor as test-cbor.py, which appears to be testing the behavior of cborutil against cbor. We should figure out some appropriate test strings and drop thirdparty.cbor, but that's a mission for another day. Differential Revision: https://phab.mercurial-scm.org/D5522

File last commit:

r41172:a181a1c8 default
r41172:a181a1c8 default
Show More
test-wireproto-serverreactor.py
630 lines | 24.6 KiB | text/x-python | PythonLexer
/ tests / test-wireproto-serverreactor.py
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 from __future__ import absolute_import, print_function
import unittest
from mercurial import (
Gregory Szorc
wireprotov2: pass ui into clientreactor and serverreactor...
r40165 ui as uimod,
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 util,
wireprotoframing as framing,
)
Gregory Szorc
wireprotov2: handle sender protocol settings frames...
r40162 from mercurial.utils import (
cborutil,
)
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070
ffs = framing.makeframefromhumanstring
Augie Fackler
tests: migrate test-wireproto-serverreactor.py to our internal CBOR...
r41172 OK = b''.join(cborutil.streamencode({b'status': b'ok'}))
Gregory Szorc
wireprotov2: change command response protocol to include a leading map...
r37743
Gregory Szorc
wireproto: buffer output frames when in half duplex mode...
r37074 def makereactor(deferoutput=False):
Gregory Szorc
wireprotov2: pass ui into clientreactor and serverreactor...
r40165 ui = uimod.ui()
return framing.serverreactor(ui, deferoutput=deferoutput)
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070
def sendframes(reactor, gen):
"""Send a generator of frame bytearray to a reactor.
Emits a generator of results from ``onframerecv()`` calls.
"""
for frame in gen:
Gregory Szorc
wireproto: define attr-based classes for representing frames...
r37079 header = framing.parseheader(frame)
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 payload = frame[framing.FRAME_HEADER_SIZE:]
Gregory Szorc
wireproto: define attr-based classes for representing frames...
r37079 assert len(payload) == header.length
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070
Gregory Szorc
wireproto: define attr-based classes for representing frames...
r37079 yield reactor.onframerecv(framing.frame(header.requestid,
Gregory Szorc
wireproto: add streams to frame-based protocol...
r37304 header.streamid,
header.streamflags,
Gregory Szorc
wireproto: define attr-based classes for representing frames...
r37079 header.typeid,
header.flags,
payload))
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070
Gregory Szorc
wireproto: start to associate frame generation with a stream...
r37303 def sendcommandframes(reactor, stream, rid, cmd, args, datafh=None):
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 """Generate frames to run a command and send them to a reactor."""
Gregory Szorc
wireproto: add request IDs to frames...
r37075 return sendframes(reactor,
Gregory Szorc
wireproto: start to associate frame generation with a stream...
r37303 framing.createcommandframes(stream, rid, cmd, args,
datafh))
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070
Gregory Szorc
wireproto: define human output side channel frame...
r37078
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 class ServerReactorTests(unittest.TestCase):
Gregory Szorc
tests: fix duplicate and failing test...
r37302 def _sendsingleframe(self, reactor, f):
results = list(sendframes(reactor, [f]))
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 self.assertEqual(len(results), 1)
return results[0]
def assertaction(self, res, expected):
self.assertIsInstance(res, tuple)
self.assertEqual(len(res), 2)
self.assertIsInstance(res[1], dict)
self.assertEqual(res[0], expected)
Gregory Szorc
wireproto: define and implement responses in framing protocol...
r37073 def assertframesequal(self, frames, framestrings):
expected = [ffs(s) for s in framestrings]
self.assertEqual(list(frames), expected)
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 def test1framecommand(self):
"""Receiving a command in a single frame yields request to run it."""
reactor = makereactor()
Gregory Szorc
wireproto: add streams to frame-based protocol...
r37304 stream = framing.stream(1)
Gregory Szorc
wireproto: start to associate frame generation with a stream...
r37303 results = list(sendcommandframes(reactor, stream, 1, b'mycommand', {}))
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 self.assertEqual(len(results), 1)
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(results[0], b'runcommand')
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 self.assertEqual(results[0][1], {
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'requestid': 1,
b'command': b'mycommand',
b'args': {},
Gregory Szorc
wireprotov2: server support for sending content redirects...
r40061 b'redirect': None,
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'data': None,
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 })
Gregory Szorc
wireproto: buffer output frames when in half duplex mode...
r37074 result = reactor.oninputeof()
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(result, b'noop')
Gregory Szorc
wireproto: buffer output frames when in half duplex mode...
r37074
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 def test1argument(self):
reactor = makereactor()
Gregory Szorc
wireproto: add streams to frame-based protocol...
r37304 stream = framing.stream(1)
Gregory Szorc
wireproto: start to associate frame generation with a stream...
r37303 results = list(sendcommandframes(reactor, stream, 41, b'mycommand',
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 {b'foo': b'bar'}))
Gregory Szorc
wireproto: use CBOR for command requests...
r37308 self.assertEqual(len(results), 1)
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(results[0], b'runcommand')
Gregory Szorc
wireproto: use CBOR for command requests...
r37308 self.assertEqual(results[0][1], {
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'requestid': 41,
b'command': b'mycommand',
b'args': {b'foo': b'bar'},
Gregory Szorc
wireprotov2: server support for sending content redirects...
r40061 b'redirect': None,
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'data': None,
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 })
def testmultiarguments(self):
reactor = makereactor()
Gregory Szorc
wireproto: add streams to frame-based protocol...
r37304 stream = framing.stream(1)
Gregory Szorc
wireproto: start to associate frame generation with a stream...
r37303 results = list(sendcommandframes(reactor, stream, 1, b'mycommand',
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 {b'foo': b'bar', b'biz': b'baz'}))
Gregory Szorc
wireproto: use CBOR for command requests...
r37308 self.assertEqual(len(results), 1)
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(results[0], b'runcommand')
Gregory Szorc
wireproto: use CBOR for command requests...
r37308 self.assertEqual(results[0][1], {
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'requestid': 1,
b'command': b'mycommand',
b'args': {b'foo': b'bar', b'biz': b'baz'},
Gregory Szorc
wireprotov2: server support for sending content redirects...
r40061 b'redirect': None,
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'data': None,
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 })
def testsimplecommanddata(self):
reactor = makereactor()
Gregory Szorc
wireproto: add streams to frame-based protocol...
r37304 stream = framing.stream(1)
Gregory Szorc
wireproto: start to associate frame generation with a stream...
r37303 results = list(sendcommandframes(reactor, stream, 1, b'mycommand', {},
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 util.bytesio(b'data!')))
self.assertEqual(len(results), 2)
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(results[0], b'wantframe')
self.assertaction(results[1], b'runcommand')
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 self.assertEqual(results[1][1], {
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'requestid': 1,
b'command': b'mycommand',
b'args': {},
Gregory Szorc
wireprotov2: server support for sending content redirects...
r40061 b'redirect': None,
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'data': b'data!',
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 })
def testmultipledataframes(self):
frames = [
Gregory Szorc
wireproto: use CBOR for command requests...
r37308 ffs(b'1 1 stream-begin command-request new|have-data '
b"cbor:{b'name': b'mycommand'}"),
Gregory Szorc
wireproto: add streams to frame-based protocol...
r37304 ffs(b'1 1 0 command-data continuation data1'),
ffs(b'1 1 0 command-data continuation data2'),
ffs(b'1 1 0 command-data eos data3'),
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 ]
reactor = makereactor()
results = list(sendframes(reactor, frames))
self.assertEqual(len(results), 4)
for i in range(3):
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(results[i], b'wantframe')
self.assertaction(results[3], b'runcommand')
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 self.assertEqual(results[3][1], {
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'requestid': 1,
b'command': b'mycommand',
b'args': {},
Gregory Szorc
wireprotov2: server support for sending content redirects...
r40061 b'redirect': None,
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'data': b'data1data2data3',
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 })
def testargumentanddata(self):
frames = [
Gregory Szorc
wireproto: use CBOR for command requests...
r37308 ffs(b'1 1 stream-begin command-request new|have-data '
b"cbor:{b'name': b'command', b'args': {b'key': b'val',"
b"b'foo': b'bar'}}"),
Gregory Szorc
wireproto: add streams to frame-based protocol...
r37304 ffs(b'1 1 0 command-data continuation value1'),
ffs(b'1 1 0 command-data eos value2'),
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 ]
reactor = makereactor()
results = list(sendframes(reactor, frames))
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(results[-1], b'runcommand')
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 self.assertEqual(results[-1][1], {
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'requestid': 1,
b'command': b'command',
b'args': {
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 b'key': b'val',
b'foo': b'bar',
},
Gregory Szorc
wireprotov2: server support for sending content redirects...
r40061 b'redirect': None,
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'data': b'value1value2',
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 })
Gregory Szorc
wireproto: use CBOR for command requests...
r37308 def testnewandcontinuation(self):
result = self._sendsingleframe(makereactor(),
ffs(b'1 1 stream-begin command-request new|continuation '))
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(result, b'error')
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 self.assertEqual(result[1], {
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'message': b'received command request frame with both new and '
b'continuation flags set',
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 })
Gregory Szorc
wireproto: use CBOR for command requests...
r37308 def testneithernewnorcontinuation(self):
result = self._sendsingleframe(makereactor(),
ffs(b'1 1 stream-begin command-request 0 '))
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(result, b'error')
Gregory Szorc
wireproto: use CBOR for command requests...
r37308 self.assertEqual(result[1], {
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'message': b'received command request frame with neither new nor '
b'continuation flags set',
Gregory Szorc
wireproto: support for receiving multiple requests...
r37076 })
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 def testunexpectedcommanddata(self):
Gregory Szorc
wireproto: use CBOR for command requests...
r37308 """Command data frame when not running a command is an error."""
result = self._sendsingleframe(makereactor(),
ffs(b'1 1 stream-begin command-data 0 ignored'))
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(result, b'error')
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 self.assertEqual(result[1], {
Gregory Szorc
wireprotov2: handle sender protocol settings frames...
r40162 b'message': b'expected sender protocol settings or command request '
b'frame; got 2',
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 })
Gregory Szorc
wireproto: support for receiving multiple requests...
r37076 def testunexpectedcommanddatareceiving(self):
"""Same as above except the command is receiving."""
results = list(sendframes(makereactor(), [
Gregory Szorc
wireproto: use CBOR for command requests...
r37308 ffs(b'1 1 stream-begin command-request new|more '
b"cbor:{b'name': b'ignored'}"),
Gregory Szorc
wireproto: add streams to frame-based protocol...
r37304 ffs(b'1 1 0 command-data eos ignored'),
Gregory Szorc
wireproto: support for receiving multiple requests...
r37076 ]))
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(results[0], b'wantframe')
self.assertaction(results[1], b'error')
Gregory Szorc
wireproto: support for receiving multiple requests...
r37076 self.assertEqual(results[1][1], {
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'message': b'received command data frame for request that is not '
b'expecting data: 1',
Gregory Szorc
wireproto: support for receiving multiple requests...
r37076 })
Gregory Szorc
tests: fix duplicate and failing test...
r37302 def testconflictingrequestidallowed(self):
Gregory Szorc
wireproto: support for receiving multiple requests...
r37076 """Multiple fully serviced commands with same request ID is allowed."""
Gregory Szorc
tests: fix duplicate and failing test...
r37302 reactor = makereactor()
results = []
Gregory Szorc
wireproto: explicit API to create outgoing streams...
r37305 outstream = reactor.makeoutputstream()
Gregory Szorc
tests: fix duplicate and failing test...
r37302 results.append(self._sendsingleframe(
Gregory Szorc
wireproto: use CBOR for command requests...
r37308 reactor, ffs(b'1 1 stream-begin command-request new '
b"cbor:{b'name': b'command'}")))
Gregory Szorc
wireprotov2: remove functions for creating response frames from bytes...
r40170 result = reactor.oncommandresponsereadyobjects(
outstream, 1, [b'response1'])
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(result, b'sendframes')
list(result[1][b'framegen'])
Gregory Szorc
tests: fix duplicate and failing test...
r37302 results.append(self._sendsingleframe(
Gregory Szorc
wireproto: use CBOR for command requests...
r37308 reactor, ffs(b'1 1 stream-begin command-request new '
b"cbor:{b'name': b'command'}")))
Gregory Szorc
wireprotov2: remove functions for creating response frames from bytes...
r40170 result = reactor.oncommandresponsereadyobjects(
outstream, 1, [b'response2'])
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(result, b'sendframes')
list(result[1][b'framegen'])
Gregory Szorc
tests: fix duplicate and failing test...
r37302 results.append(self._sendsingleframe(
Gregory Szorc
wireproto: use CBOR for command requests...
r37308 reactor, ffs(b'1 1 stream-begin command-request new '
b"cbor:{b'name': b'command'}")))
Gregory Szorc
wireprotov2: remove functions for creating response frames from bytes...
r40170 result = reactor.oncommandresponsereadyobjects(
outstream, 1, [b'response3'])
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(result, b'sendframes')
list(result[1][b'framegen'])
Gregory Szorc
tests: fix duplicate and failing test...
r37302
Gregory Szorc
wireproto: support for receiving multiple requests...
r37076 for i in range(3):
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(results[i], b'runcommand')
Gregory Szorc
wireproto: support for receiving multiple requests...
r37076 self.assertEqual(results[i][1], {
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'requestid': 1,
b'command': b'command',
b'args': {},
Gregory Szorc
wireprotov2: server support for sending content redirects...
r40061 b'redirect': None,
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'data': None,
Gregory Szorc
wireproto: support for receiving multiple requests...
r37076 })
def testconflictingrequestid(self):
"""Request ID for new command matching in-flight command is illegal."""
results = list(sendframes(makereactor(), [
Gregory Szorc
wireproto: use CBOR for command requests...
r37308 ffs(b'1 1 stream-begin command-request new|more '
b"cbor:{b'name': b'command'}"),
ffs(b'1 1 0 command-request new '
b"cbor:{b'name': b'command1'}"),
Gregory Szorc
wireproto: support for receiving multiple requests...
r37076 ]))
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(results[0], b'wantframe')
self.assertaction(results[1], b'error')
Gregory Szorc
wireproto: support for receiving multiple requests...
r37076 self.assertEqual(results[1][1], {
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'message': b'request with ID 1 already received',
Gregory Szorc
wireproto: support for receiving multiple requests...
r37076 })
def testinterleavedcommands(self):
Augie Fackler
tests: migrate test-wireproto-serverreactor.py to our internal CBOR...
r41172 cbor1 = b''.join(cborutil.streamencode({
Gregory Szorc
wireproto: use CBOR for command requests...
r37308 b'name': b'command1',
b'args': {
b'foo': b'bar',
b'key1': b'val',
}
Augie Fackler
tests: migrate test-wireproto-serverreactor.py to our internal CBOR...
r41172 }))
cbor3 = b''.join(cborutil.streamencode({
Gregory Szorc
wireproto: use CBOR for command requests...
r37308 b'name': b'command3',
b'args': {
b'biz': b'baz',
b'key': b'val',
},
Augie Fackler
tests: migrate test-wireproto-serverreactor.py to our internal CBOR...
r41172 }))
Gregory Szorc
wireproto: use CBOR for command requests...
r37308
Gregory Szorc
wireproto: support for receiving multiple requests...
r37076 results = list(sendframes(makereactor(), [
Gregory Szorc
wireproto: use CBOR for command requests...
r37308 ffs(b'1 1 stream-begin command-request new|more %s' % cbor1[0:6]),
ffs(b'3 1 0 command-request new|more %s' % cbor3[0:10]),
ffs(b'1 1 0 command-request continuation|more %s' % cbor1[6:9]),
ffs(b'3 1 0 command-request continuation|more %s' % cbor3[10:13]),
ffs(b'3 1 0 command-request continuation %s' % cbor3[13:]),
ffs(b'1 1 0 command-request continuation %s' % cbor1[9:]),
Gregory Szorc
wireproto: support for receiving multiple requests...
r37076 ]))
self.assertEqual([t[0] for t in results], [
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'wantframe',
b'wantframe',
b'wantframe',
b'wantframe',
b'runcommand',
b'runcommand',
Gregory Szorc
wireproto: support for receiving multiple requests...
r37076 ])
self.assertEqual(results[4][1], {
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'requestid': 3,
b'command': b'command3',
b'args': {b'biz': b'baz', b'key': b'val'},
Gregory Szorc
wireprotov2: server support for sending content redirects...
r40061 b'redirect': None,
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'data': None,
Gregory Szorc
wireproto: support for receiving multiple requests...
r37076 })
self.assertEqual(results[5][1], {
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'requestid': 1,
b'command': b'command1',
b'args': {b'foo': b'bar', b'key1': b'val'},
Gregory Szorc
wireprotov2: server support for sending content redirects...
r40061 b'redirect': None,
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'data': None,
Gregory Szorc
wireproto: support for receiving multiple requests...
r37076 })
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 def testmissingcommanddataframe(self):
Gregory Szorc
wireproto: support for receiving multiple requests...
r37076 # The reactor doesn't currently handle partially received commands.
# So this test is failing to do anything with request 1.
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 frames = [
Gregory Szorc
wireproto: use CBOR for command requests...
r37308 ffs(b'1 1 stream-begin command-request new|have-data '
b"cbor:{b'name': b'command1'}"),
ffs(b'3 1 0 command-request new '
b"cbor:{b'name': b'command2'}"),
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 ]
results = list(sendframes(makereactor(), frames))
self.assertEqual(len(results), 2)
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(results[0], b'wantframe')
self.assertaction(results[1], b'runcommand')
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070
def testmissingcommanddataframeflags(self):
frames = [
Gregory Szorc
wireproto: use CBOR for command requests...
r37308 ffs(b'1 1 stream-begin command-request new|have-data '
b"cbor:{b'name': b'command1'}"),
Gregory Szorc
wireproto: add streams to frame-based protocol...
r37304 ffs(b'1 1 0 command-data 0 data'),
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 ]
results = list(sendframes(makereactor(), frames))
self.assertEqual(len(results), 2)
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(results[0], b'wantframe')
self.assertaction(results[1], b'error')
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 self.assertEqual(results[1][1], {
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'message': b'command data frame without flags',
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 })
Gregory Szorc
wireproto: support for receiving multiple requests...
r37076 def testframefornonreceivingrequest(self):
"""Receiving a frame for a command that is not receiving is illegal."""
results = list(sendframes(makereactor(), [
Gregory Szorc
wireproto: use CBOR for command requests...
r37308 ffs(b'1 1 stream-begin command-request new '
b"cbor:{b'name': b'command1'}"),
ffs(b'3 1 0 command-request new|have-data '
b"cbor:{b'name': b'command3'}"),
ffs(b'5 1 0 command-data eos ignored'),
Gregory Szorc
wireproto: support for receiving multiple requests...
r37076 ]))
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(results[2], b'error')
Gregory Szorc
wireproto: support for receiving multiple requests...
r37076 self.assertEqual(results[2][1], {
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'message': b'received frame for request that is not receiving: 5',
Gregory Szorc
wireproto: support for receiving multiple requests...
r37076 })
Gregory Szorc
wireproto: define and implement responses in framing protocol...
r37073 def testsimpleresponse(self):
"""Bytes response to command sends result frames."""
reactor = makereactor()
Gregory Szorc
wireproto: add streams to frame-based protocol...
r37304 instream = framing.stream(1)
Gregory Szorc
wireproto: start to associate frame generation with a stream...
r37303 list(sendcommandframes(reactor, instream, 1, b'mycommand', {}))
Gregory Szorc
wireproto: define and implement responses in framing protocol...
r37073
Gregory Szorc
wireproto: explicit API to create outgoing streams...
r37305 outstream = reactor.makeoutputstream()
Gregory Szorc
wireprotov2: remove functions for creating response frames from bytes...
r40170 result = reactor.oncommandresponsereadyobjects(
outstream, 1, [b'response'])
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(result, b'sendframes')
self.assertframesequal(result[1][b'framegen'], [
Gregory Szorc
wireprotov2: send content encoded frames from server...
r40173 b'1 2 stream-begin stream-settings eos cbor:b"identity"',
b'1 2 encoded command-response continuation %s' % OK,
b'1 2 encoded command-response continuation cbor:b"response"',
Gregory Szorc
wireprotov2: remove functions for creating response frames from bytes...
r40170 b'1 2 0 command-response eos ',
Gregory Szorc
wireproto: define and implement responses in framing protocol...
r37073 ])
def testmultiframeresponse(self):
"""Bytes response spanning multiple frames is handled."""
first = b'x' * framing.DEFAULT_MAX_FRAME_SIZE
second = b'y' * 100
reactor = makereactor()
Gregory Szorc
wireproto: add streams to frame-based protocol...
r37304 instream = framing.stream(1)
Gregory Szorc
wireproto: start to associate frame generation with a stream...
r37303 list(sendcommandframes(reactor, instream, 1, b'mycommand', {}))
Gregory Szorc
wireproto: define and implement responses in framing protocol...
r37073
Gregory Szorc
wireproto: explicit API to create outgoing streams...
r37305 outstream = reactor.makeoutputstream()
Gregory Szorc
wireprotov2: remove functions for creating response frames from bytes...
r40170 result = reactor.oncommandresponsereadyobjects(
outstream, 1, [first + second])
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(result, b'sendframes')
self.assertframesequal(result[1][b'framegen'], [
Gregory Szorc
wireprotov2: send content encoded frames from server...
r40173 b'1 2 stream-begin stream-settings eos cbor:b"identity"',
b'1 2 encoded command-response continuation %s' % OK,
b'1 2 encoded command-response continuation Y\x80d',
b'1 2 encoded command-response continuation %s' % first,
b'1 2 encoded command-response continuation %s' % second,
Gregory Szorc
wireprotov2: remove functions for creating response frames from bytes...
r40170 b'1 2 0 command-response eos '
Gregory Szorc
wireproto: define and implement responses in framing protocol...
r37073 ])
Gregory Szorc
wireprotov2: change behavior of error frame...
r37744 def testservererror(self):
Gregory Szorc
wireproto: define and implement responses in framing protocol...
r37073 reactor = makereactor()
Gregory Szorc
wireproto: add streams to frame-based protocol...
r37304 instream = framing.stream(1)
Gregory Szorc
wireproto: start to associate frame generation with a stream...
r37303 list(sendcommandframes(reactor, instream, 1, b'mycommand', {}))
Gregory Szorc
wireproto: define and implement responses in framing protocol...
r37073
Gregory Szorc
wireproto: explicit API to create outgoing streams...
r37305 outstream = reactor.makeoutputstream()
Gregory Szorc
wireprotov2: change behavior of error frame...
r37744 result = reactor.onservererror(outstream, 1, b'some message')
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(result, b'sendframes')
self.assertframesequal(result[1][b'framegen'], [
Gregory Szorc
wireprotov2: change behavior of error frame...
r37744 b"1 2 stream-begin error-response 0 "
b"cbor:{b'type': b'server', "
b"b'message': [{b'msg': b'some message'}]}",
Gregory Szorc
wireproto: define and implement responses in framing protocol...
r37073 ])
Gregory Szorc
wireproto: buffer output frames when in half duplex mode...
r37074 def test1commanddeferresponse(self):
"""Responses when in deferred output mode are delayed until EOF."""
reactor = makereactor(deferoutput=True)
Gregory Szorc
wireproto: add streams to frame-based protocol...
r37304 instream = framing.stream(1)
Gregory Szorc
wireproto: start to associate frame generation with a stream...
r37303 results = list(sendcommandframes(reactor, instream, 1, b'mycommand',
{}))
Gregory Szorc
wireproto: buffer output frames when in half duplex mode...
r37074 self.assertEqual(len(results), 1)
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(results[0], b'runcommand')
Gregory Szorc
wireproto: buffer output frames when in half duplex mode...
r37074
Gregory Szorc
wireproto: explicit API to create outgoing streams...
r37305 outstream = reactor.makeoutputstream()
Gregory Szorc
wireprotov2: remove functions for creating response frames from bytes...
r40170 result = reactor.oncommandresponsereadyobjects(
outstream, 1, [b'response'])
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(result, b'noop')
Gregory Szorc
wireproto: buffer output frames when in half duplex mode...
r37074 result = reactor.oninputeof()
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(result, b'sendframes')
self.assertframesequal(result[1][b'framegen'], [
Gregory Szorc
wireprotov2: send content encoded frames from server...
r40173 b'1 2 stream-begin stream-settings eos cbor:b"identity"',
b'1 2 encoded command-response continuation %s' % OK,
b'1 2 encoded command-response continuation cbor:b"response"',
Gregory Szorc
wireprotov2: remove functions for creating response frames from bytes...
r40170 b'1 2 0 command-response eos ',
Gregory Szorc
wireproto: buffer output frames when in half duplex mode...
r37074 ])
def testmultiplecommanddeferresponse(self):
reactor = makereactor(deferoutput=True)
Gregory Szorc
wireproto: add streams to frame-based protocol...
r37304 instream = framing.stream(1)
Gregory Szorc
wireproto: start to associate frame generation with a stream...
r37303 list(sendcommandframes(reactor, instream, 1, b'command1', {}))
list(sendcommandframes(reactor, instream, 3, b'command2', {}))
Gregory Szorc
wireproto: buffer output frames when in half duplex mode...
r37074
Gregory Szorc
wireproto: explicit API to create outgoing streams...
r37305 outstream = reactor.makeoutputstream()
Gregory Szorc
wireprotov2: remove functions for creating response frames from bytes...
r40170 result = reactor.oncommandresponsereadyobjects(
outstream, 1, [b'response1'])
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(result, b'noop')
Gregory Szorc
wireprotov2: remove functions for creating response frames from bytes...
r40170 result = reactor.oncommandresponsereadyobjects(
outstream, 3, [b'response2'])
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(result, b'noop')
Gregory Szorc
wireproto: buffer output frames when in half duplex mode...
r37074 result = reactor.oninputeof()
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(result, b'sendframes')
self.assertframesequal(result[1][b'framegen'], [
Gregory Szorc
wireprotov2: send content encoded frames from server...
r40173 b'1 2 stream-begin stream-settings eos cbor:b"identity"',
b'1 2 encoded command-response continuation %s' % OK,
b'1 2 encoded command-response continuation cbor:b"response1"',
Gregory Szorc
wireprotov2: remove functions for creating response frames from bytes...
r40170 b'1 2 0 command-response eos ',
Gregory Szorc
wireprotov2: send content encoded frames from server...
r40173 b'3 2 encoded command-response continuation %s' % OK,
b'3 2 encoded command-response continuation cbor:b"response2"',
Gregory Szorc
wireprotov2: remove functions for creating response frames from bytes...
r40170 b'3 2 0 command-response eos ',
Gregory Szorc
wireproto: add request IDs to frames...
r37075 ])
def testrequestidtracking(self):
reactor = makereactor(deferoutput=True)
Gregory Szorc
wireproto: add streams to frame-based protocol...
r37304 instream = framing.stream(1)
Gregory Szorc
wireproto: start to associate frame generation with a stream...
r37303 list(sendcommandframes(reactor, instream, 1, b'command1', {}))
list(sendcommandframes(reactor, instream, 3, b'command2', {}))
list(sendcommandframes(reactor, instream, 5, b'command3', {}))
Gregory Szorc
wireproto: add request IDs to frames...
r37075
# Register results for commands out of order.
Gregory Szorc
wireproto: explicit API to create outgoing streams...
r37305 outstream = reactor.makeoutputstream()
Gregory Szorc
wireprotov2: remove functions for creating response frames from bytes...
r40170 reactor.oncommandresponsereadyobjects(outstream, 3, [b'response3'])
reactor.oncommandresponsereadyobjects(outstream, 1, [b'response1'])
reactor.oncommandresponsereadyobjects(outstream, 5, [b'response5'])
Gregory Szorc
wireproto: add request IDs to frames...
r37075
result = reactor.oninputeof()
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(result, b'sendframes')
self.assertframesequal(result[1][b'framegen'], [
Gregory Szorc
wireprotov2: send content encoded frames from server...
r40173 b'3 2 stream-begin stream-settings eos cbor:b"identity"',
b'3 2 encoded command-response continuation %s' % OK,
b'3 2 encoded command-response continuation cbor:b"response3"',
Gregory Szorc
wireprotov2: remove functions for creating response frames from bytes...
r40170 b'3 2 0 command-response eos ',
Gregory Szorc
wireprotov2: send content encoded frames from server...
r40173 b'1 2 encoded command-response continuation %s' % OK,
b'1 2 encoded command-response continuation cbor:b"response1"',
Gregory Szorc
wireprotov2: remove functions for creating response frames from bytes...
r40170 b'1 2 0 command-response eos ',
Gregory Szorc
wireprotov2: send content encoded frames from server...
r40173 b'5 2 encoded command-response continuation %s' % OK,
b'5 2 encoded command-response continuation cbor:b"response5"',
Gregory Szorc
wireprotov2: remove functions for creating response frames from bytes...
r40170 b'5 2 0 command-response eos ',
Gregory Szorc
wireproto: buffer output frames when in half duplex mode...
r37074 ])
Gregory Szorc
wireproto: explicitly track which requests are active...
r37081 def testduplicaterequestonactivecommand(self):
"""Receiving a request ID that matches a request that isn't finished."""
reactor = makereactor()
Gregory Szorc
wireproto: add streams to frame-based protocol...
r37304 stream = framing.stream(1)
Gregory Szorc
wireproto: start to associate frame generation with a stream...
r37303 list(sendcommandframes(reactor, stream, 1, b'command1', {}))
results = list(sendcommandframes(reactor, stream, 1, b'command1', {}))
Gregory Szorc
wireproto: explicitly track which requests are active...
r37081
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(results[0], b'error')
Gregory Szorc
wireproto: explicitly track which requests are active...
r37081 self.assertEqual(results[0][1], {
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'message': b'request with ID 1 is already active',
Gregory Szorc
wireproto: explicitly track which requests are active...
r37081 })
def testduplicaterequestonactivecommandnosend(self):
"""Same as above but we've registered a response but haven't sent it."""
reactor = makereactor()
Gregory Szorc
wireproto: add streams to frame-based protocol...
r37304 instream = framing.stream(1)
Gregory Szorc
wireproto: start to associate frame generation with a stream...
r37303 list(sendcommandframes(reactor, instream, 1, b'command1', {}))
Gregory Szorc
wireproto: explicit API to create outgoing streams...
r37305 outstream = reactor.makeoutputstream()
Gregory Szorc
wireprotov2: remove functions for creating response frames from bytes...
r40170 reactor.oncommandresponsereadyobjects(outstream, 1, [b'response'])
Gregory Szorc
wireproto: explicitly track which requests are active...
r37081
# We've registered the response but haven't sent it. From the
# perspective of the reactor, the command is still active.
Gregory Szorc
wireproto: start to associate frame generation with a stream...
r37303 results = list(sendcommandframes(reactor, instream, 1, b'command1', {}))
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(results[0], b'error')
Gregory Szorc
wireproto: explicitly track which requests are active...
r37081 self.assertEqual(results[0][1], {
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 b'message': b'request with ID 1 is already active',
Gregory Szorc
wireproto: explicitly track which requests are active...
r37081 })
def testduplicaterequestaftersend(self):
"""We can use a duplicate request ID after we've sent the response."""
reactor = makereactor()
Gregory Szorc
wireproto: add streams to frame-based protocol...
r37304 instream = framing.stream(1)
Gregory Szorc
wireproto: start to associate frame generation with a stream...
r37303 list(sendcommandframes(reactor, instream, 1, b'command1', {}))
Gregory Szorc
wireproto: explicit API to create outgoing streams...
r37305 outstream = reactor.makeoutputstream()
Gregory Szorc
wireprotov2: remove functions for creating response frames from bytes...
r40170 res = reactor.oncommandresponsereadyobjects(outstream, 1, [b'response'])
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 list(res[1][b'framegen'])
Gregory Szorc
wireproto: explicitly track which requests are active...
r37081
Gregory Szorc
wireproto: start to associate frame generation with a stream...
r37303 results = list(sendcommandframes(reactor, instream, 1, b'command1', {}))
Augie Fackler
tests: add all missing b prefixes in reactor tests...
r37700 self.assertaction(results[0], b'runcommand')
Gregory Szorc
wireproto: explicitly track which requests are active...
r37081
Gregory Szorc
wireprotov2: handle sender protocol settings frames...
r40162 def testprotocolsettingsnoflags(self):
result = self._sendsingleframe(
makereactor(),
ffs(b'0 1 stream-begin sender-protocol-settings 0 '))
self.assertaction(result, b'error')
self.assertEqual(result[1], {
b'message': b'sender protocol settings frame must have '
b'continuation or end of stream flag set',
})
def testprotocolsettingsconflictflags(self):
result = self._sendsingleframe(
makereactor(),
ffs(b'0 1 stream-begin sender-protocol-settings continuation|eos '))
self.assertaction(result, b'error')
self.assertEqual(result[1], {
b'message': b'sender protocol settings frame cannot have both '
b'continuation and end of stream flags set',
})
def testprotocolsettingsemptypayload(self):
result = self._sendsingleframe(
makereactor(),
ffs(b'0 1 stream-begin sender-protocol-settings eos '))
self.assertaction(result, b'error')
self.assertEqual(result[1], {
b'message': b'sender protocol settings frame did not contain CBOR '
b'data',
})
def testprotocolsettingsmultipleobjects(self):
result = self._sendsingleframe(
makereactor(),
ffs(b'0 1 stream-begin sender-protocol-settings eos '
b'\x46foobar\x43foo'))
self.assertaction(result, b'error')
self.assertEqual(result[1], {
b'message': b'sender protocol settings frame contained multiple '
b'CBOR values',
})
def testprotocolsettingscontentencodings(self):
reactor = makereactor()
result = self._sendsingleframe(
reactor,
ffs(b'0 1 stream-begin sender-protocol-settings eos '
b'cbor:{b"contentencodings": [b"a", b"b"]}'))
self.assertaction(result, b'wantframe')
self.assertEqual(reactor._state, b'idle')
self.assertEqual(reactor._sendersettings[b'contentencodings'],
[b'a', b'b'])
def testprotocolsettingsmultipleframes(self):
reactor = makereactor()
data = b''.join(cborutil.streamencode({
b'contentencodings': [b'value1', b'value2'],
}))
results = list(sendframes(reactor, [
ffs(b'0 1 stream-begin sender-protocol-settings continuation %s' %
data[0:5]),
ffs(b'0 1 0 sender-protocol-settings eos %s' % data[5:]),
]))
self.assertEqual(len(results), 2)
self.assertaction(results[0], b'wantframe')
self.assertaction(results[1], b'wantframe')
self.assertEqual(reactor._state, b'idle')
self.assertEqual(reactor._sendersettings[b'contentencodings'],
[b'value1', b'value2'])
def testprotocolsettingsbadcbor(self):
result = self._sendsingleframe(
makereactor(),
ffs(b'0 1 stream-begin sender-protocol-settings eos badvalue'))
self.assertaction(result, b'error')
def testprotocolsettingsnoninitial(self):
# Cannot have protocol settings frames as non-initial frames.
reactor = makereactor()
stream = framing.stream(1)
results = list(sendcommandframes(reactor, stream, 1, b'mycommand', {}))
self.assertEqual(len(results), 1)
self.assertaction(results[0], b'runcommand')
result = self._sendsingleframe(
reactor,
ffs(b'0 1 0 sender-protocol-settings eos '))
self.assertaction(result, b'error')
self.assertEqual(result[1], {
b'message': b'expected command request frame; got 8',
})
Gregory Szorc
wireproto: implement basic frame reading and processing...
r37070 if __name__ == '__main__':
import silenttestrunner
silenttestrunner.main(__name__)