Both of these tests now pass on Python 3.
- skip-blame just b prefixes. So many b prefixes.
| pulkit |
| hg-reviewers |
Both of these tests now pass on Python 3.
| Automatic diff as part of commit; lint not applicable. |
| Automatic diff as part of commit; unit tests not applicable. |
| Path | Packages | |||
|---|---|---|---|---|
| M | contrib/python3-whitelist (2 lines) | |||
| M | tests/test-wireproto-clientreactor.py (56 lines) | |||
| M | tests/test-wireproto-serverreactor.py (204 lines) |
| test-update-names.t | test-update-names.t | ||||
| test-update-reverse.t | test-update-reverse.t | ||||
| test-upgrade-repo.t | test-upgrade-repo.t | ||||
| test-url-rev.t | test-url-rev.t | ||||
| test-username-newline.t | test-username-newline.t | ||||
| test-verify.t | test-verify.t | ||||
| test-websub.t | test-websub.t | ||||
| test-win32text.t | test-win32text.t | ||||
| test-wireproto-clientreactor.py | |||||
| test-wireproto-framing.py | test-wireproto-framing.py | ||||
| test-wireproto-serverreactor.py | |||||
| test-xdg.t | test-xdg.t | ||||
| payload)) | payload)) | ||||
| class SingleSendTests(unittest.TestCase): | class SingleSendTests(unittest.TestCase): | ||||
| """A reactor that can only send once rejects subsequent sends.""" | """A reactor that can only send once rejects subsequent sends.""" | ||||
| def testbasic(self): | def testbasic(self): | ||||
| reactor = framing.clientreactor(hasmultiplesend=False, buffersends=True) | reactor = framing.clientreactor(hasmultiplesend=False, buffersends=True) | ||||
| request, action, meta = reactor.callcommand(b'foo', {}) | request, action, meta = reactor.callcommand(b'foo', {}) | ||||
| self.assertEqual(request.state, 'pending') | self.assertEqual(request.state, b'pending') | ||||
| self.assertEqual(action, 'noop') | self.assertEqual(action, b'noop') | ||||
| action, meta = reactor.flushcommands() | action, meta = reactor.flushcommands() | ||||
| self.assertEqual(action, 'sendframes') | self.assertEqual(action, b'sendframes') | ||||
| for frame in meta['framegen']: | for frame in meta[b'framegen']: | ||||
| self.assertEqual(request.state, 'sending') | self.assertEqual(request.state, b'sending') | ||||
| self.assertEqual(request.state, 'sent') | self.assertEqual(request.state, b'sent') | ||||
| with self.assertRaisesRegexp(error.ProgrammingError, | with self.assertRaisesRegexp(error.ProgrammingError, | ||||
| 'cannot issue new commands'): | 'cannot issue new commands'): | ||||
| reactor.callcommand(b'foo', {}) | reactor.callcommand(b'foo', {}) | ||||
| with self.assertRaisesRegexp(error.ProgrammingError, | with self.assertRaisesRegexp(error.ProgrammingError, | ||||
| 'cannot issue new commands'): | 'cannot issue new commands'): | ||||
| reactor.callcommand(b'foo', {}) | reactor.callcommand(b'foo', {}) | ||||
| class NoBufferTests(unittest.TestCase): | class NoBufferTests(unittest.TestCase): | ||||
| """A reactor without send buffering sends requests immediately.""" | """A reactor without send buffering sends requests immediately.""" | ||||
| def testbasic(self): | def testbasic(self): | ||||
| reactor = framing.clientreactor(hasmultiplesend=True, buffersends=False) | reactor = framing.clientreactor(hasmultiplesend=True, buffersends=False) | ||||
| request, action, meta = reactor.callcommand(b'command1', {}) | request, action, meta = reactor.callcommand(b'command1', {}) | ||||
| self.assertEqual(request.requestid, 1) | self.assertEqual(request.requestid, 1) | ||||
| self.assertEqual(action, 'sendframes') | self.assertEqual(action, b'sendframes') | ||||
| self.assertEqual(request.state, 'pending') | self.assertEqual(request.state, b'pending') | ||||
| for frame in meta['framegen']: | for frame in meta[b'framegen']: | ||||
| self.assertEqual(request.state, 'sending') | self.assertEqual(request.state, b'sending') | ||||
| self.assertEqual(request.state, 'sent') | self.assertEqual(request.state, b'sent') | ||||
| action, meta = reactor.flushcommands() | action, meta = reactor.flushcommands() | ||||
| self.assertEqual(action, 'noop') | self.assertEqual(action, b'noop') | ||||
| # And we can send another command. | # And we can send another command. | ||||
| request, action, meta = reactor.callcommand(b'command2', {}) | request, action, meta = reactor.callcommand(b'command2', {}) | ||||
| self.assertEqual(request.requestid, 3) | self.assertEqual(request.requestid, 3) | ||||
| self.assertEqual(action, 'sendframes') | self.assertEqual(action, b'sendframes') | ||||
| for frame in meta['framegen']: | for frame in meta[b'framegen']: | ||||
| self.assertEqual(request.state, 'sending') | self.assertEqual(request.state, b'sending') | ||||
| self.assertEqual(request.state, 'sent') | self.assertEqual(request.state, b'sent') | ||||
| class BadFrameRecvTests(unittest.TestCase): | class BadFrameRecvTests(unittest.TestCase): | ||||
| def testoddstream(self): | def testoddstream(self): | ||||
| reactor = framing.clientreactor() | reactor = framing.clientreactor() | ||||
| action, meta = sendframe(reactor, ffs(b'1 1 0 1 0 foo')) | action, meta = sendframe(reactor, ffs(b'1 1 0 1 0 foo')) | ||||
| self.assertEqual(action, 'error') | self.assertEqual(action, b'error') | ||||
| self.assertEqual(meta['message'], | self.assertEqual(meta[b'message'], | ||||
| 'received frame with odd numbered stream ID: 1') | b'received frame with odd numbered stream ID: 1') | ||||
| def testunknownstream(self): | def testunknownstream(self): | ||||
| reactor = framing.clientreactor() | reactor = framing.clientreactor() | ||||
| action, meta = sendframe(reactor, ffs(b'1 0 0 1 0 foo')) | action, meta = sendframe(reactor, ffs(b'1 0 0 1 0 foo')) | ||||
| self.assertEqual(action, 'error') | self.assertEqual(action, b'error') | ||||
| self.assertEqual(meta['message'], | self.assertEqual(meta[b'message'], | ||||
| 'received frame on unknown stream without beginning ' | b'received frame on unknown stream without beginning ' | ||||
| 'of stream flag set') | b'of stream flag set') | ||||
| def testunhandledframetype(self): | def testunhandledframetype(self): | ||||
| reactor = framing.clientreactor(buffersends=False) | reactor = framing.clientreactor(buffersends=False) | ||||
| request, action, meta = reactor.callcommand(b'foo', {}) | request, action, meta = reactor.callcommand(b'foo', {}) | ||||
| for frame in meta['framegen']: | for frame in meta[b'framegen']: | ||||
| pass | pass | ||||
| with self.assertRaisesRegexp(error.ProgrammingError, | with self.assertRaisesRegexp(error.ProgrammingError, | ||||
| 'unhandled frame type'): | 'unhandled frame type'): | ||||
| sendframe(reactor, ffs(b'1 0 stream-begin text-output 0 foo')) | sendframe(reactor, ffs(b'1 0 stream-begin text-output 0 foo')) | ||||
| class StreamTests(unittest.TestCase): | class StreamTests(unittest.TestCase): | ||||
| def testmultipleresponseframes(self): | def testmultipleresponseframes(self): | ||||
| reactor = framing.clientreactor(buffersends=False) | reactor = framing.clientreactor(buffersends=False) | ||||
| request, action, meta = reactor.callcommand(b'foo', {}) | request, action, meta = reactor.callcommand(b'foo', {}) | ||||
| self.assertEqual(action, 'sendframes') | self.assertEqual(action, b'sendframes') | ||||
| for f in meta['framegen']: | for f in meta[b'framegen']: | ||||
| pass | pass | ||||
| action, meta = sendframe( | action, meta = sendframe( | ||||
| reactor, | reactor, | ||||
| ffs(b'%d 0 stream-begin 4 0 foo' % request.requestid)) | ffs(b'%d 0 stream-begin 4 0 foo' % request.requestid)) | ||||
| self.assertEqual(action, 'responsedata') | self.assertEqual(action, b'responsedata') | ||||
| action, meta = sendframe( | action, meta = sendframe( | ||||
| reactor, | reactor, | ||||
| ffs(b'%d 0 0 4 eos bar' % request.requestid)) | ffs(b'%d 0 0 4 eos bar' % request.requestid)) | ||||
| self.assertEqual(action, 'responsedata') | self.assertEqual(action, b'responsedata') | ||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||
| import silenttestrunner | import silenttestrunner | ||||
| silenttestrunner.main(__name__) | silenttestrunner.main(__name__) | ||||
| self.assertEqual(list(frames), expected) | self.assertEqual(list(frames), expected) | ||||
| def test1framecommand(self): | def test1framecommand(self): | ||||
| """Receiving a command in a single frame yields request to run it.""" | """Receiving a command in a single frame yields request to run it.""" | ||||
| reactor = makereactor() | reactor = makereactor() | ||||
| stream = framing.stream(1) | stream = framing.stream(1) | ||||
| results = list(sendcommandframes(reactor, stream, 1, b'mycommand', {})) | results = list(sendcommandframes(reactor, stream, 1, b'mycommand', {})) | ||||
| self.assertEqual(len(results), 1) | self.assertEqual(len(results), 1) | ||||
| self.assertaction(results[0], 'runcommand') | self.assertaction(results[0], b'runcommand') | ||||
| self.assertEqual(results[0][1], { | self.assertEqual(results[0][1], { | ||||
| 'requestid': 1, | b'requestid': 1, | ||||
| 'command': b'mycommand', | b'command': b'mycommand', | ||||
| 'args': {}, | b'args': {}, | ||||
| 'data': None, | b'data': None, | ||||
| }) | }) | ||||
| result = reactor.oninputeof() | result = reactor.oninputeof() | ||||
| self.assertaction(result, 'noop') | self.assertaction(result, b'noop') | ||||
| def test1argument(self): | def test1argument(self): | ||||
| reactor = makereactor() | reactor = makereactor() | ||||
| stream = framing.stream(1) | stream = framing.stream(1) | ||||
| results = list(sendcommandframes(reactor, stream, 41, b'mycommand', | results = list(sendcommandframes(reactor, stream, 41, b'mycommand', | ||||
| {b'foo': b'bar'})) | {b'foo': b'bar'})) | ||||
| self.assertEqual(len(results), 1) | self.assertEqual(len(results), 1) | ||||
| self.assertaction(results[0], 'runcommand') | self.assertaction(results[0], b'runcommand') | ||||
| self.assertEqual(results[0][1], { | self.assertEqual(results[0][1], { | ||||
| 'requestid': 41, | b'requestid': 41, | ||||
| 'command': b'mycommand', | b'command': b'mycommand', | ||||
| 'args': {b'foo': b'bar'}, | b'args': {b'foo': b'bar'}, | ||||
| 'data': None, | b'data': None, | ||||
| }) | }) | ||||
| def testmultiarguments(self): | def testmultiarguments(self): | ||||
| reactor = makereactor() | reactor = makereactor() | ||||
| stream = framing.stream(1) | stream = framing.stream(1) | ||||
| results = list(sendcommandframes(reactor, stream, 1, b'mycommand', | results = list(sendcommandframes(reactor, stream, 1, b'mycommand', | ||||
| {b'foo': b'bar', b'biz': b'baz'})) | {b'foo': b'bar', b'biz': b'baz'})) | ||||
| self.assertEqual(len(results), 1) | self.assertEqual(len(results), 1) | ||||
| self.assertaction(results[0], 'runcommand') | self.assertaction(results[0], b'runcommand') | ||||
| self.assertEqual(results[0][1], { | self.assertEqual(results[0][1], { | ||||
| 'requestid': 1, | b'requestid': 1, | ||||
| 'command': b'mycommand', | b'command': b'mycommand', | ||||
| 'args': {b'foo': b'bar', b'biz': b'baz'}, | b'args': {b'foo': b'bar', b'biz': b'baz'}, | ||||
| 'data': None, | b'data': None, | ||||
| }) | }) | ||||
| def testsimplecommanddata(self): | def testsimplecommanddata(self): | ||||
| reactor = makereactor() | reactor = makereactor() | ||||
| stream = framing.stream(1) | stream = framing.stream(1) | ||||
| results = list(sendcommandframes(reactor, stream, 1, b'mycommand', {}, | results = list(sendcommandframes(reactor, stream, 1, b'mycommand', {}, | ||||
| util.bytesio(b'data!'))) | util.bytesio(b'data!'))) | ||||
| self.assertEqual(len(results), 2) | self.assertEqual(len(results), 2) | ||||
| self.assertaction(results[0], 'wantframe') | self.assertaction(results[0], b'wantframe') | ||||
| self.assertaction(results[1], 'runcommand') | self.assertaction(results[1], b'runcommand') | ||||
| self.assertEqual(results[1][1], { | self.assertEqual(results[1][1], { | ||||
| 'requestid': 1, | b'requestid': 1, | ||||
| 'command': b'mycommand', | b'command': b'mycommand', | ||||
| 'args': {}, | b'args': {}, | ||||
| 'data': b'data!', | b'data': b'data!', | ||||
| }) | }) | ||||
| def testmultipledataframes(self): | def testmultipledataframes(self): | ||||
| frames = [ | frames = [ | ||||
| ffs(b'1 1 stream-begin command-request new|have-data ' | ffs(b'1 1 stream-begin command-request new|have-data ' | ||||
| b"cbor:{b'name': b'mycommand'}"), | b"cbor:{b'name': b'mycommand'}"), | ||||
| ffs(b'1 1 0 command-data continuation data1'), | 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 continuation data2'), | ||||
| ffs(b'1 1 0 command-data eos data3'), | ffs(b'1 1 0 command-data eos data3'), | ||||
| ] | ] | ||||
| reactor = makereactor() | reactor = makereactor() | ||||
| results = list(sendframes(reactor, frames)) | results = list(sendframes(reactor, frames)) | ||||
| self.assertEqual(len(results), 4) | self.assertEqual(len(results), 4) | ||||
| for i in range(3): | for i in range(3): | ||||
| self.assertaction(results[i], 'wantframe') | self.assertaction(results[i], b'wantframe') | ||||
| self.assertaction(results[3], 'runcommand') | self.assertaction(results[3], b'runcommand') | ||||
| self.assertEqual(results[3][1], { | self.assertEqual(results[3][1], { | ||||
| 'requestid': 1, | b'requestid': 1, | ||||
| 'command': b'mycommand', | b'command': b'mycommand', | ||||
| 'args': {}, | b'args': {}, | ||||
| 'data': b'data1data2data3', | b'data': b'data1data2data3', | ||||
| }) | }) | ||||
| def testargumentanddata(self): | def testargumentanddata(self): | ||||
| frames = [ | frames = [ | ||||
| ffs(b'1 1 stream-begin command-request new|have-data ' | ffs(b'1 1 stream-begin command-request new|have-data ' | ||||
| b"cbor:{b'name': b'command', b'args': {b'key': b'val'," | b"cbor:{b'name': b'command', b'args': {b'key': b'val'," | ||||
| b"b'foo': b'bar'}}"), | b"b'foo': b'bar'}}"), | ||||
| ffs(b'1 1 0 command-data continuation value1'), | ffs(b'1 1 0 command-data continuation value1'), | ||||
| ffs(b'1 1 0 command-data eos value2'), | ffs(b'1 1 0 command-data eos value2'), | ||||
| ] | ] | ||||
| reactor = makereactor() | reactor = makereactor() | ||||
| results = list(sendframes(reactor, frames)) | results = list(sendframes(reactor, frames)) | ||||
| self.assertaction(results[-1], 'runcommand') | self.assertaction(results[-1], b'runcommand') | ||||
| self.assertEqual(results[-1][1], { | self.assertEqual(results[-1][1], { | ||||
| 'requestid': 1, | b'requestid': 1, | ||||
| 'command': b'command', | b'command': b'command', | ||||
| 'args': { | b'args': { | ||||
| b'key': b'val', | b'key': b'val', | ||||
| b'foo': b'bar', | b'foo': b'bar', | ||||
| }, | }, | ||||
| 'data': b'value1value2', | b'data': b'value1value2', | ||||
| }) | }) | ||||
| def testnewandcontinuation(self): | def testnewandcontinuation(self): | ||||
| result = self._sendsingleframe(makereactor(), | result = self._sendsingleframe(makereactor(), | ||||
| ffs(b'1 1 stream-begin command-request new|continuation ')) | ffs(b'1 1 stream-begin command-request new|continuation ')) | ||||
| self.assertaction(result, 'error') | self.assertaction(result, b'error') | ||||
| self.assertEqual(result[1], { | self.assertEqual(result[1], { | ||||
| 'message': b'received command request frame with both new and ' | b'message': b'received command request frame with both new and ' | ||||
| b'continuation flags set', | b'continuation flags set', | ||||
| }) | }) | ||||
| def testneithernewnorcontinuation(self): | def testneithernewnorcontinuation(self): | ||||
| result = self._sendsingleframe(makereactor(), | result = self._sendsingleframe(makereactor(), | ||||
| ffs(b'1 1 stream-begin command-request 0 ')) | ffs(b'1 1 stream-begin command-request 0 ')) | ||||
| self.assertaction(result, 'error') | self.assertaction(result, b'error') | ||||
| self.assertEqual(result[1], { | self.assertEqual(result[1], { | ||||
| 'message': b'received command request frame with neither new nor ' | b'message': b'received command request frame with neither new nor ' | ||||
| b'continuation flags set', | b'continuation flags set', | ||||
| }) | }) | ||||
| def testunexpectedcommanddata(self): | def testunexpectedcommanddata(self): | ||||
| """Command data frame when not running a command is an error.""" | """Command data frame when not running a command is an error.""" | ||||
| result = self._sendsingleframe(makereactor(), | result = self._sendsingleframe(makereactor(), | ||||
| ffs(b'1 1 stream-begin command-data 0 ignored')) | ffs(b'1 1 stream-begin command-data 0 ignored')) | ||||
| self.assertaction(result, 'error') | self.assertaction(result, b'error') | ||||
| self.assertEqual(result[1], { | self.assertEqual(result[1], { | ||||
| 'message': b'expected command request frame; got 3', | b'message': b'expected command request frame; got 3', | ||||
| }) | }) | ||||
| def testunexpectedcommanddatareceiving(self): | def testunexpectedcommanddatareceiving(self): | ||||
| """Same as above except the command is receiving.""" | """Same as above except the command is receiving.""" | ||||
| results = list(sendframes(makereactor(), [ | results = list(sendframes(makereactor(), [ | ||||
| ffs(b'1 1 stream-begin command-request new|more ' | ffs(b'1 1 stream-begin command-request new|more ' | ||||
| b"cbor:{b'name': b'ignored'}"), | b"cbor:{b'name': b'ignored'}"), | ||||
| ffs(b'1 1 0 command-data eos ignored'), | ffs(b'1 1 0 command-data eos ignored'), | ||||
| ])) | ])) | ||||
| self.assertaction(results[0], 'wantframe') | self.assertaction(results[0], b'wantframe') | ||||
| self.assertaction(results[1], 'error') | self.assertaction(results[1], b'error') | ||||
| self.assertEqual(results[1][1], { | self.assertEqual(results[1][1], { | ||||
| 'message': b'received command data frame for request that is not ' | b'message': b'received command data frame for request that is not ' | ||||
| b'expecting data: 1', | b'expecting data: 1', | ||||
| }) | }) | ||||
| def testconflictingrequestidallowed(self): | def testconflictingrequestidallowed(self): | ||||
| """Multiple fully serviced commands with same request ID is allowed.""" | """Multiple fully serviced commands with same request ID is allowed.""" | ||||
| reactor = makereactor() | reactor = makereactor() | ||||
| results = [] | results = [] | ||||
| outstream = reactor.makeoutputstream() | outstream = reactor.makeoutputstream() | ||||
| results.append(self._sendsingleframe( | results.append(self._sendsingleframe( | ||||
| reactor, ffs(b'1 1 stream-begin command-request new ' | reactor, ffs(b'1 1 stream-begin command-request new ' | ||||
| b"cbor:{b'name': b'command'}"))) | b"cbor:{b'name': b'command'}"))) | ||||
| result = reactor.onbytesresponseready(outstream, 1, b'response1') | result = reactor.onbytesresponseready(outstream, 1, b'response1') | ||||
| self.assertaction(result, 'sendframes') | self.assertaction(result, b'sendframes') | ||||
| list(result[1]['framegen']) | list(result[1][b'framegen']) | ||||
| results.append(self._sendsingleframe( | results.append(self._sendsingleframe( | ||||
| reactor, ffs(b'1 1 stream-begin command-request new ' | reactor, ffs(b'1 1 stream-begin command-request new ' | ||||
| b"cbor:{b'name': b'command'}"))) | b"cbor:{b'name': b'command'}"))) | ||||
| result = reactor.onbytesresponseready(outstream, 1, b'response2') | result = reactor.onbytesresponseready(outstream, 1, b'response2') | ||||
| self.assertaction(result, 'sendframes') | self.assertaction(result, b'sendframes') | ||||
| list(result[1]['framegen']) | list(result[1][b'framegen']) | ||||
| results.append(self._sendsingleframe( | results.append(self._sendsingleframe( | ||||
| reactor, ffs(b'1 1 stream-begin command-request new ' | reactor, ffs(b'1 1 stream-begin command-request new ' | ||||
| b"cbor:{b'name': b'command'}"))) | b"cbor:{b'name': b'command'}"))) | ||||
| result = reactor.onbytesresponseready(outstream, 1, b'response3') | result = reactor.onbytesresponseready(outstream, 1, b'response3') | ||||
| self.assertaction(result, 'sendframes') | self.assertaction(result, b'sendframes') | ||||
| list(result[1]['framegen']) | list(result[1][b'framegen']) | ||||
| for i in range(3): | for i in range(3): | ||||
| self.assertaction(results[i], 'runcommand') | self.assertaction(results[i], b'runcommand') | ||||
| self.assertEqual(results[i][1], { | self.assertEqual(results[i][1], { | ||||
| 'requestid': 1, | b'requestid': 1, | ||||
| 'command': b'command', | b'command': b'command', | ||||
| 'args': {}, | b'args': {}, | ||||
| 'data': None, | b'data': None, | ||||
| }) | }) | ||||
| def testconflictingrequestid(self): | def testconflictingrequestid(self): | ||||
| """Request ID for new command matching in-flight command is illegal.""" | """Request ID for new command matching in-flight command is illegal.""" | ||||
| results = list(sendframes(makereactor(), [ | results = list(sendframes(makereactor(), [ | ||||
| ffs(b'1 1 stream-begin command-request new|more ' | ffs(b'1 1 stream-begin command-request new|more ' | ||||
| b"cbor:{b'name': b'command'}"), | b"cbor:{b'name': b'command'}"), | ||||
| ffs(b'1 1 0 command-request new ' | ffs(b'1 1 0 command-request new ' | ||||
| b"cbor:{b'name': b'command1'}"), | b"cbor:{b'name': b'command1'}"), | ||||
| ])) | ])) | ||||
| self.assertaction(results[0], 'wantframe') | self.assertaction(results[0], b'wantframe') | ||||
| self.assertaction(results[1], 'error') | self.assertaction(results[1], b'error') | ||||
| self.assertEqual(results[1][1], { | self.assertEqual(results[1][1], { | ||||
| 'message': b'request with ID 1 already received', | b'message': b'request with ID 1 already received', | ||||
| }) | }) | ||||
| def testinterleavedcommands(self): | def testinterleavedcommands(self): | ||||
| cbor1 = cbor.dumps({ | cbor1 = cbor.dumps({ | ||||
| b'name': b'command1', | b'name': b'command1', | ||||
| b'args': { | b'args': { | ||||
| b'foo': b'bar', | b'foo': b'bar', | ||||
| b'key1': b'val', | b'key1': b'val', | ||||
| ffs(b'3 1 0 command-request new|more %s' % cbor3[0:10]), | 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'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|more %s' % cbor3[10:13]), | ||||
| ffs(b'3 1 0 command-request continuation %s' % cbor3[13:]), | ffs(b'3 1 0 command-request continuation %s' % cbor3[13:]), | ||||
| ffs(b'1 1 0 command-request continuation %s' % cbor1[9:]), | ffs(b'1 1 0 command-request continuation %s' % cbor1[9:]), | ||||
| ])) | ])) | ||||
| self.assertEqual([t[0] for t in results], [ | self.assertEqual([t[0] for t in results], [ | ||||
| 'wantframe', | b'wantframe', | ||||
| 'wantframe', | b'wantframe', | ||||
| 'wantframe', | b'wantframe', | ||||
| 'wantframe', | b'wantframe', | ||||
| 'runcommand', | b'runcommand', | ||||
| 'runcommand', | b'runcommand', | ||||
| ]) | ]) | ||||
| self.assertEqual(results[4][1], { | self.assertEqual(results[4][1], { | ||||
| 'requestid': 3, | b'requestid': 3, | ||||
| 'command': 'command3', | b'command': b'command3', | ||||
| 'args': {b'biz': b'baz', b'key': b'val'}, | b'args': {b'biz': b'baz', b'key': b'val'}, | ||||
| 'data': None, | b'data': None, | ||||
| }) | }) | ||||
| self.assertEqual(results[5][1], { | self.assertEqual(results[5][1], { | ||||
| 'requestid': 1, | b'requestid': 1, | ||||
| 'command': 'command1', | b'command': b'command1', | ||||
| 'args': {b'foo': b'bar', b'key1': b'val'}, | b'args': {b'foo': b'bar', b'key1': b'val'}, | ||||
| 'data': None, | b'data': None, | ||||
| }) | }) | ||||
| def testmissingcommanddataframe(self): | def testmissingcommanddataframe(self): | ||||
| # The reactor doesn't currently handle partially received commands. | # The reactor doesn't currently handle partially received commands. | ||||
| # So this test is failing to do anything with request 1. | # So this test is failing to do anything with request 1. | ||||
| frames = [ | frames = [ | ||||
| ffs(b'1 1 stream-begin command-request new|have-data ' | ffs(b'1 1 stream-begin command-request new|have-data ' | ||||
| b"cbor:{b'name': b'command1'}"), | b"cbor:{b'name': b'command1'}"), | ||||
| ffs(b'3 1 0 command-request new ' | ffs(b'3 1 0 command-request new ' | ||||
| b"cbor:{b'name': b'command2'}"), | b"cbor:{b'name': b'command2'}"), | ||||
| ] | ] | ||||
| results = list(sendframes(makereactor(), frames)) | results = list(sendframes(makereactor(), frames)) | ||||
| self.assertEqual(len(results), 2) | self.assertEqual(len(results), 2) | ||||
| self.assertaction(results[0], 'wantframe') | self.assertaction(results[0], b'wantframe') | ||||
| self.assertaction(results[1], 'runcommand') | self.assertaction(results[1], b'runcommand') | ||||
| def testmissingcommanddataframeflags(self): | def testmissingcommanddataframeflags(self): | ||||
| frames = [ | frames = [ | ||||
| ffs(b'1 1 stream-begin command-request new|have-data ' | ffs(b'1 1 stream-begin command-request new|have-data ' | ||||
| b"cbor:{b'name': b'command1'}"), | b"cbor:{b'name': b'command1'}"), | ||||
| ffs(b'1 1 0 command-data 0 data'), | ffs(b'1 1 0 command-data 0 data'), | ||||
| ] | ] | ||||
| results = list(sendframes(makereactor(), frames)) | results = list(sendframes(makereactor(), frames)) | ||||
| self.assertEqual(len(results), 2) | self.assertEqual(len(results), 2) | ||||
| self.assertaction(results[0], 'wantframe') | self.assertaction(results[0], b'wantframe') | ||||
| self.assertaction(results[1], 'error') | self.assertaction(results[1], b'error') | ||||
| self.assertEqual(results[1][1], { | self.assertEqual(results[1][1], { | ||||
| 'message': b'command data frame without flags', | b'message': b'command data frame without flags', | ||||
| }) | }) | ||||
| def testframefornonreceivingrequest(self): | def testframefornonreceivingrequest(self): | ||||
| """Receiving a frame for a command that is not receiving is illegal.""" | """Receiving a frame for a command that is not receiving is illegal.""" | ||||
| results = list(sendframes(makereactor(), [ | results = list(sendframes(makereactor(), [ | ||||
| ffs(b'1 1 stream-begin command-request new ' | ffs(b'1 1 stream-begin command-request new ' | ||||
| b"cbor:{b'name': b'command1'}"), | b"cbor:{b'name': b'command1'}"), | ||||
| ffs(b'3 1 0 command-request new|have-data ' | ffs(b'3 1 0 command-request new|have-data ' | ||||
| b"cbor:{b'name': b'command3'}"), | b"cbor:{b'name': b'command3'}"), | ||||
| ffs(b'5 1 0 command-data eos ignored'), | ffs(b'5 1 0 command-data eos ignored'), | ||||
| ])) | ])) | ||||
| self.assertaction(results[2], 'error') | self.assertaction(results[2], b'error') | ||||
| self.assertEqual(results[2][1], { | self.assertEqual(results[2][1], { | ||||
| 'message': b'received frame for request that is not receiving: 5', | b'message': b'received frame for request that is not receiving: 5', | ||||
| }) | }) | ||||
| def testsimpleresponse(self): | def testsimpleresponse(self): | ||||
| """Bytes response to command sends result frames.""" | """Bytes response to command sends result frames.""" | ||||
| reactor = makereactor() | reactor = makereactor() | ||||
| instream = framing.stream(1) | instream = framing.stream(1) | ||||
| list(sendcommandframes(reactor, instream, 1, b'mycommand', {})) | list(sendcommandframes(reactor, instream, 1, b'mycommand', {})) | ||||
| outstream = reactor.makeoutputstream() | outstream = reactor.makeoutputstream() | ||||
| result = reactor.onbytesresponseready(outstream, 1, b'response') | result = reactor.onbytesresponseready(outstream, 1, b'response') | ||||
| self.assertaction(result, 'sendframes') | self.assertaction(result, b'sendframes') | ||||
| self.assertframesequal(result[1]['framegen'], [ | self.assertframesequal(result[1][b'framegen'], [ | ||||
| b'1 2 stream-begin bytes-response eos response', | b'1 2 stream-begin bytes-response eos response', | ||||
| ]) | ]) | ||||
| def testmultiframeresponse(self): | def testmultiframeresponse(self): | ||||
| """Bytes response spanning multiple frames is handled.""" | """Bytes response spanning multiple frames is handled.""" | ||||
| first = b'x' * framing.DEFAULT_MAX_FRAME_SIZE | first = b'x' * framing.DEFAULT_MAX_FRAME_SIZE | ||||
| second = b'y' * 100 | second = b'y' * 100 | ||||
| reactor = makereactor() | reactor = makereactor() | ||||
| instream = framing.stream(1) | instream = framing.stream(1) | ||||
| list(sendcommandframes(reactor, instream, 1, b'mycommand', {})) | list(sendcommandframes(reactor, instream, 1, b'mycommand', {})) | ||||
| outstream = reactor.makeoutputstream() | outstream = reactor.makeoutputstream() | ||||
| result = reactor.onbytesresponseready(outstream, 1, first + second) | result = reactor.onbytesresponseready(outstream, 1, first + second) | ||||
| self.assertaction(result, 'sendframes') | self.assertaction(result, b'sendframes') | ||||
| self.assertframesequal(result[1]['framegen'], [ | self.assertframesequal(result[1][b'framegen'], [ | ||||
| b'1 2 stream-begin bytes-response continuation %s' % first, | b'1 2 stream-begin bytes-response continuation %s' % first, | ||||
| b'1 2 0 bytes-response eos %s' % second, | b'1 2 0 bytes-response eos %s' % second, | ||||
| ]) | ]) | ||||
| def testapplicationerror(self): | def testapplicationerror(self): | ||||
| reactor = makereactor() | reactor = makereactor() | ||||
| instream = framing.stream(1) | instream = framing.stream(1) | ||||
| list(sendcommandframes(reactor, instream, 1, b'mycommand', {})) | list(sendcommandframes(reactor, instream, 1, b'mycommand', {})) | ||||
| outstream = reactor.makeoutputstream() | outstream = reactor.makeoutputstream() | ||||
| result = reactor.onapplicationerror(outstream, 1, b'some message') | result = reactor.onapplicationerror(outstream, 1, b'some message') | ||||
| self.assertaction(result, 'sendframes') | self.assertaction(result, b'sendframes') | ||||
| self.assertframesequal(result[1]['framegen'], [ | self.assertframesequal(result[1][b'framegen'], [ | ||||
| b'1 2 stream-begin error-response application some message', | b'1 2 stream-begin error-response application some message', | ||||
| ]) | ]) | ||||
| def test1commanddeferresponse(self): | def test1commanddeferresponse(self): | ||||
| """Responses when in deferred output mode are delayed until EOF.""" | """Responses when in deferred output mode are delayed until EOF.""" | ||||
| reactor = makereactor(deferoutput=True) | reactor = makereactor(deferoutput=True) | ||||
| instream = framing.stream(1) | instream = framing.stream(1) | ||||
| results = list(sendcommandframes(reactor, instream, 1, b'mycommand', | results = list(sendcommandframes(reactor, instream, 1, b'mycommand', | ||||
| {})) | {})) | ||||
| self.assertEqual(len(results), 1) | self.assertEqual(len(results), 1) | ||||
| self.assertaction(results[0], 'runcommand') | self.assertaction(results[0], b'runcommand') | ||||
| outstream = reactor.makeoutputstream() | outstream = reactor.makeoutputstream() | ||||
| result = reactor.onbytesresponseready(outstream, 1, b'response') | result = reactor.onbytesresponseready(outstream, 1, b'response') | ||||
| self.assertaction(result, 'noop') | self.assertaction(result, b'noop') | ||||
| result = reactor.oninputeof() | result = reactor.oninputeof() | ||||
| self.assertaction(result, 'sendframes') | self.assertaction(result, b'sendframes') | ||||
| self.assertframesequal(result[1]['framegen'], [ | self.assertframesequal(result[1][b'framegen'], [ | ||||
| b'1 2 stream-begin bytes-response eos response', | b'1 2 stream-begin bytes-response eos response', | ||||
| ]) | ]) | ||||
| def testmultiplecommanddeferresponse(self): | def testmultiplecommanddeferresponse(self): | ||||
| reactor = makereactor(deferoutput=True) | reactor = makereactor(deferoutput=True) | ||||
| instream = framing.stream(1) | instream = framing.stream(1) | ||||
| list(sendcommandframes(reactor, instream, 1, b'command1', {})) | list(sendcommandframes(reactor, instream, 1, b'command1', {})) | ||||
| list(sendcommandframes(reactor, instream, 3, b'command2', {})) | list(sendcommandframes(reactor, instream, 3, b'command2', {})) | ||||
| outstream = reactor.makeoutputstream() | outstream = reactor.makeoutputstream() | ||||
| result = reactor.onbytesresponseready(outstream, 1, b'response1') | result = reactor.onbytesresponseready(outstream, 1, b'response1') | ||||
| self.assertaction(result, 'noop') | self.assertaction(result, b'noop') | ||||
| result = reactor.onbytesresponseready(outstream, 3, b'response2') | result = reactor.onbytesresponseready(outstream, 3, b'response2') | ||||
| self.assertaction(result, 'noop') | self.assertaction(result, b'noop') | ||||
| result = reactor.oninputeof() | result = reactor.oninputeof() | ||||
| self.assertaction(result, 'sendframes') | self.assertaction(result, b'sendframes') | ||||
| self.assertframesequal(result[1]['framegen'], [ | self.assertframesequal(result[1][b'framegen'], [ | ||||
| b'1 2 stream-begin bytes-response eos response1', | b'1 2 stream-begin bytes-response eos response1', | ||||
| b'3 2 0 bytes-response eos response2' | b'3 2 0 bytes-response eos response2' | ||||
| ]) | ]) | ||||
| def testrequestidtracking(self): | def testrequestidtracking(self): | ||||
| reactor = makereactor(deferoutput=True) | reactor = makereactor(deferoutput=True) | ||||
| instream = framing.stream(1) | instream = framing.stream(1) | ||||
| list(sendcommandframes(reactor, instream, 1, b'command1', {})) | list(sendcommandframes(reactor, instream, 1, b'command1', {})) | ||||
| list(sendcommandframes(reactor, instream, 3, b'command2', {})) | list(sendcommandframes(reactor, instream, 3, b'command2', {})) | ||||
| list(sendcommandframes(reactor, instream, 5, b'command3', {})) | list(sendcommandframes(reactor, instream, 5, b'command3', {})) | ||||
| # Register results for commands out of order. | # Register results for commands out of order. | ||||
| outstream = reactor.makeoutputstream() | outstream = reactor.makeoutputstream() | ||||
| reactor.onbytesresponseready(outstream, 3, b'response3') | reactor.onbytesresponseready(outstream, 3, b'response3') | ||||
| reactor.onbytesresponseready(outstream, 1, b'response1') | reactor.onbytesresponseready(outstream, 1, b'response1') | ||||
| reactor.onbytesresponseready(outstream, 5, b'response5') | reactor.onbytesresponseready(outstream, 5, b'response5') | ||||
| result = reactor.oninputeof() | result = reactor.oninputeof() | ||||
| self.assertaction(result, 'sendframes') | self.assertaction(result, b'sendframes') | ||||
| self.assertframesequal(result[1]['framegen'], [ | self.assertframesequal(result[1][b'framegen'], [ | ||||
| b'3 2 stream-begin bytes-response eos response3', | b'3 2 stream-begin bytes-response eos response3', | ||||
| b'1 2 0 bytes-response eos response1', | b'1 2 0 bytes-response eos response1', | ||||
| b'5 2 0 bytes-response eos response5', | b'5 2 0 bytes-response eos response5', | ||||
| ]) | ]) | ||||
| def testduplicaterequestonactivecommand(self): | def testduplicaterequestonactivecommand(self): | ||||
| """Receiving a request ID that matches a request that isn't finished.""" | """Receiving a request ID that matches a request that isn't finished.""" | ||||
| reactor = makereactor() | reactor = makereactor() | ||||
| stream = framing.stream(1) | stream = framing.stream(1) | ||||
| list(sendcommandframes(reactor, stream, 1, b'command1', {})) | list(sendcommandframes(reactor, stream, 1, b'command1', {})) | ||||
| results = list(sendcommandframes(reactor, stream, 1, b'command1', {})) | results = list(sendcommandframes(reactor, stream, 1, b'command1', {})) | ||||
| self.assertaction(results[0], 'error') | self.assertaction(results[0], b'error') | ||||
| self.assertEqual(results[0][1], { | self.assertEqual(results[0][1], { | ||||
| 'message': b'request with ID 1 is already active', | b'message': b'request with ID 1 is already active', | ||||
| }) | }) | ||||
| def testduplicaterequestonactivecommandnosend(self): | def testduplicaterequestonactivecommandnosend(self): | ||||
| """Same as above but we've registered a response but haven't sent it.""" | """Same as above but we've registered a response but haven't sent it.""" | ||||
| reactor = makereactor() | reactor = makereactor() | ||||
| instream = framing.stream(1) | instream = framing.stream(1) | ||||
| list(sendcommandframes(reactor, instream, 1, b'command1', {})) | list(sendcommandframes(reactor, instream, 1, b'command1', {})) | ||||
| outstream = reactor.makeoutputstream() | outstream = reactor.makeoutputstream() | ||||
| reactor.onbytesresponseready(outstream, 1, b'response') | reactor.onbytesresponseready(outstream, 1, b'response') | ||||
| # We've registered the response but haven't sent it. From the | # We've registered the response but haven't sent it. From the | ||||
| # perspective of the reactor, the command is still active. | # perspective of the reactor, the command is still active. | ||||
| results = list(sendcommandframes(reactor, instream, 1, b'command1', {})) | results = list(sendcommandframes(reactor, instream, 1, b'command1', {})) | ||||
| self.assertaction(results[0], 'error') | self.assertaction(results[0], b'error') | ||||
| self.assertEqual(results[0][1], { | self.assertEqual(results[0][1], { | ||||
| 'message': b'request with ID 1 is already active', | b'message': b'request with ID 1 is already active', | ||||
| }) | }) | ||||
| def testduplicaterequestaftersend(self): | def testduplicaterequestaftersend(self): | ||||
| """We can use a duplicate request ID after we've sent the response.""" | """We can use a duplicate request ID after we've sent the response.""" | ||||
| reactor = makereactor() | reactor = makereactor() | ||||
| instream = framing.stream(1) | instream = framing.stream(1) | ||||
| list(sendcommandframes(reactor, instream, 1, b'command1', {})) | list(sendcommandframes(reactor, instream, 1, b'command1', {})) | ||||
| outstream = reactor.makeoutputstream() | outstream = reactor.makeoutputstream() | ||||
| res = reactor.onbytesresponseready(outstream, 1, b'response') | res = reactor.onbytesresponseready(outstream, 1, b'response') | ||||
| list(res[1]['framegen']) | list(res[1][b'framegen']) | ||||
| results = list(sendcommandframes(reactor, instream, 1, b'command1', {})) | results = list(sendcommandframes(reactor, instream, 1, b'command1', {})) | ||||
| self.assertaction(results[0], 'runcommand') | self.assertaction(results[0], b'runcommand') | ||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||
| import silenttestrunner | import silenttestrunner | ||||
| silenttestrunner.main(__name__) | silenttestrunner.main(__name__) | ||||