def setUp(self): self.channel = DummyChannel() request = Request(self.channel, False) transport = WebSocketHybiTransport(request) handler = TestHandler(transport) transport._attachHandler(handler) self.decoder = WebSocketHybiFrameDecoder(request, handler) self.decoder.MAX_LENGTH = 100 self.decoder.MAX_BINARY_LENGTH = 1000 # taken straight from the IETF draft, masking added where appropriate self.hello = "\x81\x85\x37\xfa\x21\x3d\x7f\x9f\x4d\x51\x58" self.frag_hello = ("\x01\x83\x12\x21\x65\x23\x5a\x44\x09", "\x80\x82\x63\x34\xf1\x00\x0f\x5b") self.binary_orig = "\x3f" * 256 self.binary = ("\x82\xfe\x01\x00\x12\x6d\xa6\x23" + "\x2d\x52\x99\x1c" * 64) self.ping = "\x89\x85\x56\x23\x88\x23\x1e\x46\xe4\x4f\x39" self.pong = "\x8a\x85\xde\x41\x0f\x34\x96\x24\x63\x58\xb1" self.pong_unmasked = "\x8a\x05\x48\x65\x6c\x6c\x6f" # code 1000, message "Normal Closure" self.close = ("\x88\x90\x34\x23\x87\xde\x37\xcb\xc9\xb1\x46" "\x4e\xe6\xb2\x14\x60\xeb\xb1\x47\x56\xf5\xbb") self.empty_unmasked_close = "\x88\x00" self.empty_text = "\x81\x80\x00\x01\x02\x03" self.cont_empty_text = "\x00\x80\x00\x01\x02\x03"
class WebSocketHybiFrameDecoderTestCase(TestCase): """ Test for C{WebSocketHybiFrameDecoder}. """ def setUp(self): self.channel = DummyChannel() request = Request(self.channel, False) transport = WebSocketHybiTransport(request) handler = TestHandler(transport) transport._attachHandler(handler) self.decoder = WebSocketHybiFrameDecoder(request, handler) self.decoder.MAX_LENGTH = 100 self.decoder.MAX_BINARY_LENGTH = 1000 # taken straight from the IETF draft, masking added where appropriate self.hello = "\x81\x85\x37\xfa\x21\x3d\x7f\x9f\x4d\x51\x58" self.frag_hello = ("\x01\x83\x12\x21\x65\x23\x5a\x44\x09", "\x80\x82\x63\x34\xf1\x00\x0f\x5b") self.binary_orig = "\x3f" * 256 self.binary = ("\x82\xfe\x01\x00\x12\x6d\xa6\x23" + "\x2d\x52\x99\x1c" * 64) self.ping = "\x89\x85\x56\x23\x88\x23\x1e\x46\xe4\x4f\x39" self.pong = "\x8a\x85\xde\x41\x0f\x34\x96\x24\x63\x58\xb1" self.pong_unmasked = "\x8a\x05\x48\x65\x6c\x6c\x6f" # code 1000, message "Normal Closure" self.close = ("\x88\x90\x34\x23\x87\xde\x37\xcb\xc9\xb1\x46" "\x4e\xe6\xb2\x14\x60\xeb\xb1\x47\x56\xf5\xbb") self.empty_unmasked_close = "\x88\x00" self.empty_text = "\x81\x80\x00\x01\x02\x03" self.cont_empty_text = "\x00\x80\x00\x01\x02\x03" def assertOneDecodingError(self): """ Assert that exactly one L{DecodingError} has been logged and return that error. """ errors = self.flushLoggedErrors(DecodingError) self.assertEquals(len(errors), 1) return errors[0] def test_oneTextFrame(self): """ We can send one frame handled with one C{dataReceived} call. """ self.decoder.dataReceived(self.hello) self.assertEquals(self.decoder.handler.frames, ["Hello"]) def test_chunkedTextFrame(self): """ We can send one text frame handled with multiple C{dataReceived} calls. """ # taken straight from the IETF draft for part in (self.hello[:1], self.hello[1:3], self.hello[3:7], self.hello[7:]): self.decoder.dataReceived(part) self.assertEquals(self.decoder.handler.frames, ["Hello"]) def test_fragmentedTextFrame(self): """ We can send a fragmented frame handled with one C{dataReceived} call. """ self.decoder.dataReceived("".join(self.frag_hello)) self.assertEquals(self.decoder.handler.frames, ["Hello"]) def test_chunkedfragmentedTextFrame(self): """ We can send a fragmented text frame handled with multiple C{dataReceived} calls. """ # taken straight from the IETF draft for part in (self.frag_hello[0][:3], self.frag_hello[0][3:]): self.decoder.dataReceived(part) for part in (self.frag_hello[1][:1], self.frag_hello[1][1:]): self.decoder.dataReceived(part) self.assertEquals(self.decoder.handler.frames, ["Hello"]) def test_twoFrames(self): """ We can send two frames together and they will be correctly parsed. """ self.decoder.dataReceived("".join(self.frag_hello) + self.hello) self.assertEquals(self.decoder.handler.frames, ["Hello"] * 2) def test_controlInterleaved(self): """ A control message (in this case a pong) can appear between the fragmented frames. """ data = self.frag_hello[0] + self.pong + self.frag_hello[1] for part in data[:2], data[2:7], data[7:8], data[8:14], data[14:]: self.decoder.dataReceived(part) self.assertEquals(self.decoder.handler.frames, ["Hello"]) self.assertEquals(self.decoder.handler.pongs, ["Hello"]) def test_binaryFrame(self): """ We can send a binary frame that uses a longer length field. """ data = self.binary for part in data[:3], data[3:4], data[4:]: self.decoder.dataReceived(part) self.assertEquals(self.decoder.handler.binaryFrames, [self.binary_orig]) def test_pingInterleaved(self): """ We can get a ping frame in the middle of a fragmented frame and we'll correctly send a pong resonse. """ data = self.frag_hello[0] + self.ping + self.frag_hello[1] for part in data[:12], data[12:16], data[16:]: self.decoder.dataReceived(part) self.assertEquals(self.decoder.handler.frames, ["Hello"]) result = self.channel.transport.written.getvalue() headers, response = result.split('\r\n\r\n') self.assertEquals(response, self.pong_unmasked) def test_close(self): """ A close frame causes the remaining data to be discarded and the connection to be closed. """ self.decoder.dataReceived(self.hello + self.close + "crap" * 20) self.assertEquals(self.decoder.handler.frames, ["Hello"]) self.assertEquals(self.decoder.handler.closes, [(1000, "Normal Closure")]) result = self.channel.transport.written.getvalue() headers, response = result.split('\r\n\r\n') self.assertEquals(response, self.empty_unmasked_close) self.assertTrue(self.channel.transport.disconnected) def test_emptyFrame(self): """ An empty text frame is correctly parsed. """ self.decoder.dataReceived(self.empty_text) self.assertEquals(self.decoder.handler.frames, [""]) def test_emptyFrameInterleaved(self): """ An empty fragmented frame and a interleaved pong message are received and parsed. """ data = (self.frag_hello[0] + self.cont_empty_text + self.pong + self.frag_hello[1]) for part in data[:1], data[1:8], data[8:17], data[17:]: self.decoder.dataReceived(part) self.assertEquals(self.decoder.handler.frames, ["Hello"]) self.assertEquals(self.decoder.handler.pongs, ["Hello"])