comparison tests/test-wireproto-serverreactor.py @ 37063:39304dd63589

wireproto: explicitly track which requests are active We previously only tracked which requests are receiving. A misbehaving client could accidentally have multiple requests with the same ID in flight. We now explicitly track which request IDs are currently active. We make it illegal to receive a frame associated with a request ID that has already been dispatched. Differential Revision: https://phab.mercurial-scm.org/D2901
author Gregory Szorc <gregory.szorc@gmail.com>
date Thu, 15 Mar 2018 18:05:49 -0700
parents 884a0c1604ad
children 12bfc724217d
comparison
equal deleted inserted replaced
37062:fe4c944f95bb 37063:39304dd63589
476 def testframefornonreceivingrequest(self): 476 def testframefornonreceivingrequest(self):
477 """Receiving a frame for a command that is not receiving is illegal.""" 477 """Receiving a frame for a command that is not receiving is illegal."""
478 results = list(sendframes(makereactor(), [ 478 results = list(sendframes(makereactor(), [
479 ffs(b'1 command-name eos command1'), 479 ffs(b'1 command-name eos command1'),
480 ffs(b'3 command-name have-data command3'), 480 ffs(b'3 command-name have-data command3'),
481 ffs(b'1 command-argument eoa ignored'), 481 ffs(b'5 command-argument eoa ignored'),
482 ])) 482 ]))
483 self.assertaction(results[2], 'error') 483 self.assertaction(results[2], 'error')
484 self.assertEqual(results[2][1], { 484 self.assertEqual(results[2][1], {
485 'message': b'received frame for request that is not receiving: 1', 485 'message': b'received frame for request that is not receiving: 5',
486 }) 486 })
487 487
488 def testsimpleresponse(self): 488 def testsimpleresponse(self):
489 """Bytes response to command sends result frames.""" 489 """Bytes response to command sends result frames."""
490 reactor = makereactor() 490 reactor = makereactor()
569 b'3 bytes-response eos response3', 569 b'3 bytes-response eos response3',
570 b'1 bytes-response eos response1', 570 b'1 bytes-response eos response1',
571 b'5 bytes-response eos response5', 571 b'5 bytes-response eos response5',
572 ]) 572 ])
573 573
574 def testduplicaterequestonactivecommand(self):
575 """Receiving a request ID that matches a request that isn't finished."""
576 reactor = makereactor()
577 list(sendcommandframes(reactor, 1, b'command1', {}))
578 results = list(sendcommandframes(reactor, 1, b'command1', {}))
579
580 self.assertaction(results[0], 'error')
581 self.assertEqual(results[0][1], {
582 'message': b'request with ID 1 is already active',
583 })
584
585 def testduplicaterequestonactivecommandnosend(self):
586 """Same as above but we've registered a response but haven't sent it."""
587 reactor = makereactor()
588 list(sendcommandframes(reactor, 1, b'command1', {}))
589 reactor.onbytesresponseready(1, b'response')
590
591 # We've registered the response but haven't sent it. From the
592 # perspective of the reactor, the command is still active.
593
594 results = list(sendcommandframes(reactor, 1, b'command1', {}))
595 self.assertaction(results[0], 'error')
596 self.assertEqual(results[0][1], {
597 'message': b'request with ID 1 is already active',
598 })
599
600 def testduplicaterequestargumentframe(self):
601 """Variant on above except we sent an argument frame instead of name."""
602 reactor = makereactor()
603 list(sendcommandframes(reactor, 1, b'command', {}))
604 results = list(sendframes(reactor, [
605 ffs(b'3 command-name have-args command'),
606 ffs(b'1 command-argument 0 ignored'),
607 ]))
608 self.assertaction(results[0], 'wantframe')
609 self.assertaction(results[1], 'error')
610 self.assertEqual(results[1][1], {
611 'message': 'received frame for request that is still active: 1',
612 })
613
614 def testduplicaterequestaftersend(self):
615 """We can use a duplicate request ID after we've sent the response."""
616 reactor = makereactor()
617 list(sendcommandframes(reactor, 1, b'command1', {}))
618 res = reactor.onbytesresponseready(1, b'response')
619 list(res[1]['framegen'])
620
621 results = list(sendcommandframes(reactor, 1, b'command1', {}))
622 self.assertaction(results[0], 'runcommand')
623
574 if __name__ == '__main__': 624 if __name__ == '__main__':
575 import silenttestrunner 625 import silenttestrunner
576 silenttestrunner.main(__name__) 626 silenttestrunner.main(__name__)