content: import logging
  import unittest
  from unittest.mock import patch
  
  from websockets.exceptions import (
      ConnectionClosedError,
      ConnectionClosedOK,
      InvalidState,
      PayloadTooBig,
      ProtocolError,
  )
  from websockets.frames import (
      OP_BINARY,
      OP_CLOSE,
      OP_CONT,
      OP_PING,
      OP_PONG,
      OP_TEXT,
      Close,
      CloseCode,
      Frame,
  )
  from websockets.protocol import *
  from websockets.protocol import CLIENT, CLOSED, CLOSING, CONNECTING, SERVER
  
  from .extensions.utils import Rsv2Extension
  from .test_frames import FramesTestCase
  
  
  class ProtocolTestCase(FramesTestCase):
      def assertFrameSent(self, connection, frame, eof=False):
          """
          Outgoing data for ``connection`` contains the given frame.
  
          ``frame`` may be ``None`` if no frame is expected.
  
          When ``eof`` is ``True``, the end of the stream is also expected.
  
          """
          frames_sent = [
              (
                  None
                  if write is SEND_EOF
                  else self.parse(
                      write,
                      mask=connection.side is CLIENT,
                      extensions=connection.extensions,
                  )
              )
              for write in connection.data_to_send()
          ]
          frames_expected = [] if frame is None else [frame]
          if eof:
              frames_expected += [None]
          self.assertEqual(frames_sent, frames_expected)
  
      def assertFrameReceived(self, connection, frame):
          """
          Incoming data for ``connection`` contains the given frame.
  
          ``frame`` may be ``None`` if no frame is expected.
  
          """
          frames_received = connection.events_received()
          frames_expected = [] if frame is None else [frame]
          self.assertEqual(frames_received, frames_expected)
  
      def assertConnectionClosing(self, connection, code=None, reason=""):
          """
          Incoming data caused the "Start the WebSocket Closing Handshake" process.
  
          """
          close_frame = Frame(
              OP_CLOSE,
              b"" if code is None else Close(code, reason).serialize(),
          )
          # A close frame was received.
          self.assertFrameReceived(connection, close_frame)
          # A close frame and possibly the end of stream were sent.
          self.assertFrameSent(connection, close_frame, eof=connection.side is SERVER)
  
      def assertConnectionFailing(self, connection, code=None, reason=""):
          """
          Incoming data caused the "Fail the WebSocket Connection" process.
  
          """
          close_frame = Frame(
              OP_CLOSE,
              b"" if code is None else Close(code, reason).serialize(),
          )
          # No frame was received.
          self.assertFrameReceived(connection, None)
          # A close frame and possibly the end of stream were sent.
          self.assertFrameSent(connection, close_frame, eof=connection.side is SERVER)
  
  
  class MaskingTests(ProtocolTestCase):
      """
      Test frame masking.
  
      5.1.  Overview
  
      """
  
      unmasked_text_frame_date = b"\x81\x04Spam"
      masked_text_frame_data = b"\x81\x84\x00\xff\x00\xff\x53\x8f\x61\x92"
  
      def test_client_sends_masked_frame(self):
          client = Protocol(CLIENT)
          with patch("secrets.token_bytes", return_value=b"\x00\xff\x00\xff"):
              client.send_text(b"Spam", True)
          self.assertEqual(client.data_to_send(), [self.masked_text_frame_data])
  
      def test_server_sends_unmasked_frame(self):
          server = Protocol(SERVER)
          server.send_text(b"Spam", True)
          self.assertEqual(server.data_to_send(), [self.unmasked_text_frame_date])
  
      def test_client_receives_unmasked_frame(self):
          client = Protocol(CLIENT)
          client.receive_data(self.unmasked_text_frame_date)
          self.assertFrameReceived(
              client,
              Frame(OP_TEXT, b"Spam"),
          )
  
      def test_server_receives_masked_frame(self):
          server = Protocol(SERVER)
          server.receive_data(self.masked_text_frame_data)
          self.assertFrameReceived(
              server,
              Frame(OP_TEXT, b"Spam"),
          )
  
      def test_client_receives_masked_frame(self):
          client = Protocol(CLIENT)
          client.receive_data(self.masked_text_frame_data)
          self.assertIsInstance(client.parser_exc, ProtocolError)
          self.assertEqual(str(client.parser_exc), "incorrect masking")
          self.assertConnectionFailing(
              client, CloseCode.PROTOCOL_ERROR, "incorrect masking"
          )
  
      def test_server_receives_unmasked_frame(self):
          server = Protocol(SERVER)
          server.receive_data(self.unmasked_text_frame_date)
          self.assertIsInstance(server.parser_exc, ProtocolError)
          self.assertEqual(str(server.parser_exc), "incorrect masking")
          self.assertConnectionFailing(
              server, CloseCode.PROTOCOL_ERROR, "incorrect masking"
          )
  
  
  class ContinuationTests(ProtocolTestCase):
      """
      Test continuation frames without text or binary frames.
  
      """
  
      def test_client_sends_unexpected_continuation(self):
          client = Protocol(CLIENT)
          with self.assertRaises(ProtocolError) as raised:
              client.send_continuation(b"", fin=False)
          self.assertEqual(str(raised.exception), "unexpected continuation frame")
  
      def test_server_sends_unexpected_continuation(self):
          server = Protocol(SERVER)
          with self.assertRaises(ProtocolError) as raised:
              server.send_continuation(b"", fin=False)
          self.assertEqual(str(raised.exception), "unexpected continuation frame")
  
      def test_client_receives_unexpected_continuation(self):
          client = Protocol(CLIENT)
          client.receive_data(b"\x00\x00")
          self.assertIsInstance(client.parser_exc, ProtocolError)
          self.assertEqual(str(client.parser_exc), "unexpected continuation frame")
          self.assertConnectionFailing(
              client, CloseCode.PROTOCOL_ERROR, "unexpected continuation frame"
          )
  
      def test_server_receives_unexpected_continuation(self):
          server = Protocol(SERVER)
          server.receive_data(b"\x00\x80\x00\x00\x00\x00")
          self.assertIsInstance(server.parser_exc, ProtocolError)
          self.assertEqual(str(server.parser_exc), "unexpected continuation frame")
          self.assertConnectionFailing(
              server, CloseCode.PROTOCOL_ERROR, "unexpected continuation frame"
          )
  
      def test_client_sends_continuation_after_sending_close(self):
          client = Protocol(CLIENT)
          # Since it isn't possible to send a close frame in a fragmented
          # message (see test_client_send_close_in_fragmented_message), in fact,
          # this is the same test as test_client_sends_unexpected_continuation.
          with patch("secrets.token_bytes", return_value=b"\x00\x00\x00\x00"):
              client.send_close(CloseCode.GOING_AWAY)
          self.assertEqual(client.data_to_send(), [b"\x88\x82\x00\x00\x00\x00\x03\xe9"])
          with self.assertRaises(ProtocolError) as raised:
              client.send_continuation(b"", fin=False)
          self.assertEqual(str(raised.exception), "unexpected continuation frame")
  
      def test_server_sends_continuation_after_sending_close(self):
          # Since it isn't possible to send a close frame in a fragmented
          # message (see test_server_send_close_in_fragmented_message), in fact,
          # this is the same test as test_server_sends_unexpected_continuation.
          server = Protocol(SERVER)
          server.send_close(CloseCode.NORMAL_CLOSURE)
          self.assertEqual(server.data_to_send(), [b"\x88\x02\x03\xe8"])
          with self.assertRaises(ProtocolError) as raised:
              server.send_continuation(b"", fin=False)
          self.assertEqual(str(raised.exception), "unexpected continuation frame")
  
      def test_client_receives_continuation_after_receiving_close(self):
          client = Protocol(CLIENT)
          client.receive_data(b"\x88\x02\x03\xe8")
          self.assertConnectionClosing(client, CloseCode.NORMAL_CLOSURE)
          client.receive_data(b"\x00\x00")
          self.assertFrameReceived(client, None)
          self.assertFrameSent(client, None)
  
      def test_server_receives_continuation_after_receiving_close(self):
          server = Protocol(SERVER)
          server.receive_data(b"\x88\x82\x00\x00\x00\x00\x03\xe9")
          self.assertConnectionClosing(server, CloseCode.GOING_AWAY)
          server.receive_data(b"\x00\x80\x00\xff\x00\xff")
          self.assertFrameReceived(server, None)
          self.assertFrameSent(server, None)
  
  
  class TextTests(ProtocolTestCase):
      """
      Test text frames and continuation frames.
  
      """
  
      def test_client_sends_text(self):
          client = Protocol(CLIENT)
          with patch("secrets.token_bytes", return_value=b"\x00\x00\x00\x00"):
              client.send_text("😀".encode())
          self.assertEqual(
              client.data_to_send(), [b"\x81\x84\x00\x00\x00\x00\xf0\x9f\x98\x80"]
          )
  
      def test_server_sends_text(self):
          server = Protocol(SERVER)
          server.send_text("😀".encode())
          self.assertEqual(server.data_to_send(), [b"\x81\x04\xf0\x9f\x98\x80"])
  
      def test_client_receives_text(self):
          client = Protocol(CLIENT)
          client.receive_data(b"\x81\x04\xf0\x9f\x98\x80")
          self.assertFrameReceived(
              client,
              Frame(OP_TEXT, "😀".encode()),
          )
  
      def test_server_receives_text(self):
          server = Protocol(SERVER)
          server.receive_data(b"\x81\x84\x00\x00\x00\x00\xf0\x9f\x98\x80")
          self.assertFrameReceived(
              server,
              Frame(OP_TEXT, "😀".encode()),
          )
  
      def test_client_receives_text_over_size_limit(self):
          client = Protocol(CLIENT, max_size=3)
          client.receive_data(b"\x81\x04\xf0\x9f\x98\x80")
          self.assertIsInstance(client.parser_exc, PayloadTooBig)
          self.assertEqual(
              str(client.parser_exc),
              "frame with 4 bytes exceeds limit of 3 bytes",
          )
          self.assertConnectionFailing(
              client,
              CloseCode.MESSAGE_TOO_BIG,
              "frame with 4 bytes exceeds limit of 3 bytes",
          )
  
      def test_server_receives_text_over_size_limit(self):
          server = Protocol(SERVER, max_size=3)
          server.receive_data(b"\x81\x84\x00\x00\x00\x00\xf0\x9f\x98\x80")
          self.assertIsInstance(server.parser_exc, PayloadTooBig)
          self.assertEqual(
              str(server.parser_exc),
              "frame with 4 bytes exceeds limit of 3 bytes",
          )
          self.assertConnectionFailing(
              server,
              CloseCode.MESSAGE_TOO_BIG,
              "frame with 4 bytes exceeds limit of 3 bytes",
          )
  
      def test_client_receives_text_without_size_limit(self):
          client = Protocol(CLIENT, max_size=None)
          client.receive_data(b"\x81\x04\xf0\x9f\x98\x80")
          self.assertFrameReceived(
              client,
              Frame(OP_TEXT, "😀".encode()),
          )
  
      def test_server_receives_text_without_size_limit(self):
          server = Protocol(SERVER, max_size=None)
          server.receive_data(b"\x81\x84\x00\x00\x00\x00\xf0\x9f\x98\x80")
          self.assertFrameReceived(
              server,
              Frame(OP_TEXT, "😀".encode()),
          )
  
      def test_client_sends_fragmented_text(self):
          client = Protocol(CLIENT)
          with patch("secrets.token_bytes", return_value=b"\x00\x00\x00\x00"):
              client.send_text("😀".encode()[:2], fin=False)
          self.assertEqual(client.data_to_send(), [b"\x01\x82\x00\x00\x00\x00\xf0\x9f"])
          with patch("secrets.token_bytes", return_value=b"\x00\x00\x00\x00"):
              client.send_continuation("😀😀".encode()[2:6], fin=False)
          self.assertEqual(
              client.data_to_send(), [b"\x00\x84\x00\x00\x00\x00\x98\x80\xf0\x9f"]
          )
          with patch("secrets.token_bytes", return_value=b"\x00\x00\x00\x00"):
              client.send_continuation("😀".encode()[2:], fin=True)
          self.assertEqual(client.data_to_send(), [b"\x80\x82\x00\x00\x00\x00\x98\x80"])
  
      def test_server_sends_fragmented_text(self):
          server = Protocol(SERVER)
          server.send_text("😀".encode()[:2], fin=False)
          self.assertEqual(server.data_to_send(), [b"\x01\x02\xf0\x9f"])
          server.send_continuation("😀😀".encode()[2:6], fin=False)
          self.assertEqual(server.data_to_send(), [b"\x00\x04\x98\x80\xf0\x9f"])
          server.send_continuation("😀".encode()[2:], fin=True)
          self.assertEqual(server.data_to_send(), [b"\x80\x02\x98\x80"])
  
      def test_client_receives_fragmented_text(self):
          client = Protocol(CLIENT)
          client.receive_data(b"\x01\x02\xf0\x9f")
          self.assertFrameReceived(
              client,
              Frame(OP_TEXT, "😀".encode()[:2], fin=False),
          )
          client.receive_data(b"\x00\x04\x98\x80\xf0\x9f")
          self.assertFrameReceived(
              client,
              Frame(OP_CONT, "😀😀".encode()[2:6], fin=False),
          )
          client.receive_data(b"\x80\x02\x98\x80")
          self.assertFrameReceived(
              client,
              Frame(OP_CONT, "😀".encode()[2:]),
          )
  
      def test_server_receives_fragmented_text(self):
          server = Protocol(SERVER)
          server.receive_data(b"\x01\x82\x00\x00\x00\x00\xf0\x9f")
          self.assertFrameReceived(
              server,
              Frame(OP_TEXT, "😀".encode()[:2], fin=False),
          )
          server.receive_data(b"\x00\x84\x00\x00\x00\x00\x98\x80\xf0\x9f")
          self.assertFrameReceived(
              server,
              Frame(OP_CONT, "😀😀".encode()[2:6], fin=False),
          )
          server.receive_data(b"\x80\x82\x00\x00\x00\x00\x98\x80")
          self.assertFrameReceived(
              server,
              Frame(OP_CONT, "😀".encode()[2:]),
          )
  
      def test_client_receives_fragmented_text_over_fragment_size_limit(self):
          client = Protocol(CLIENT, max_size=(None, 3))
          client.receive_data(b"\x01\x04\xf0\x9f\x98\x80")
          self.assertIsInstance(client.parser_exc, PayloadTooBig)
          self.assertEqual(
              str(client.parser_exc),
              "frame with 4 bytes exceeds limit of 3 bytes",
          )
  
      def test_server_receives_fragmented_text_over_fragment_size_limit(self):
          server = Protocol(SERVER, max_size=(None, 3))
          server.receive_data(b"\x01\x84\x00\x00\x00\x00\xf0\x9f\x98\x80")
          self.assertIsInstance(server.parser_exc, PayloadTooBig)
          self.assertEqual(
              str(server.parser_exc),
              "frame with 4 bytes exceeds limit of 3 bytes",
          )
  
      def test_client_receives_fragmented_text_over_message_size_limit(self):
          client = Protocol(CLIENT, max_size=(3, 2))
          client.receive_data(b"\x01\x02\xf0\x9f")
          self.assertFrameReceived(
              client,
              Frame(OP_TEXT, "😀".encode()[:2], fin=False),
          )
          client.receive_data(b"\x80\x02\x98\x80")
          self.assertIsInstance(client.parser_exc, PayloadTooBig)
          self.assertEqual(
              str(client.parser_exc),
              "frame with 2 bytes after reading 2 bytes exceeds limit of 3 bytes",
          )
          self.assertConnectionFailing(
              client,
              CloseCode.MESSAGE_TOO_BIG,
              "frame with 2 bytes after reading 2 bytes exceeds limit of 3 bytes",
          )
  
      def test_server_receives_fragmented_text_over_message_size_limit(self):
          server = Protocol(SERVER, max_size=(3, 2))
          server.receive_data(b"\x01\x82\x00\x00\x00\x00\xf0\x9f")
          self.assertFrameReceived(
              server,
              Frame(OP_TEXT, "😀".encode()[:2], fin=False),
          )
          server.receive_data(b"\x80\x82\x00\x00\x00\x00\x98\x80")
          self.assertIsInstance(server.parser_exc, PayloadTooBig)
          self.assertEqual(
              str(server.parser_exc),
              "frame with 2 bytes after reading 2 bytes exceeds limit of 3 bytes",
          )
          self.assertConnectionFailing(
              server,
              CloseCode.MESSAGE_TOO_BIG,
              "frame with 2 bytes after reading 2 bytes exceeds limit of 3 bytes",
          )
  
      def test_client_receives_fragmented_text_without_size_limit(self):
          client = Protocol(CLIENT, max_size=None)
          client.receive_data(b"\x01\x02\xf0\x9f")
          self.assertFrameReceived(
              client,
              Frame(OP_TEXT, "😀".encode()[:2], fin=False),
          )
          client.receive_data(b"\x00\x04\x98\x80\xf0\x9f")
          self.assertFrameReceived(
              client,
              Frame(OP_CONT, "😀😀".encode()[2:6], fin=False),
          )
          client.receive_data(b"\x80\x02\x98\x80")
          self.assertFrameReceived(
              client,
              Frame(OP_CONT, "😀".encode()[2:]),
          )
  
      def test_server_receives_fragmented_text_without_size_limit(self):
          server = Protocol(SERVER, max_size=None)
          server.receive_data(b"\x01\x82\x00\x00\x00\x00\xf0\x9f")
          self.assertFrameReceived(
              server,
              Frame(OP_TEXT, "😀".encode()[:2], fin=False),
          )
          server.receive_data(b"\x00\x84\x00\x00\x00\x00\x98\x80\xf0\x9f")
          self.assertFrameReceived(
              server,
              Frame(OP_CONT, "😀😀".encode()[2:6], fin=False),
          )
          server.receive_data(b"\x80\x82\x00\x00\x00\x00\x98\x80")
          self.assertFrameReceived(
              server,
              Frame(OP_CONT, "😀".encode()[2:]),
          )
  
      def test_client_sends_unexpected_text(self):
          client = Protocol(CLIENT)
          client.send_text(b"", fin=False)
          with self.assertRaises(ProtocolError) as raised:
              client.send_text(b"", fin=False)
          self.assertEqual(str(raised.exception), "expected a continuation frame")
  
      def test_server_sends_unexpected_text(self):
          server = Protocol(SERVER)
          server.send_text(b"", fin=False)
          with self.assertRaises(ProtocolError) as raised:
              server.send_text(b"", fin=False)
          self.assertEqual(str(raised.exception), "expected a continuation frame")
  
      def test_client_receives_unexpected_text(self):
          client = Protocol(CLIENT)
          client.receive_data(b"\x01\x00")
          self.assertFrameReceived(
              client,
              Frame(OP_TEXT, b"", fin=False),
          )
          client.receive_data(b"\x01\x00")
          self.assertIsInstance(client.parser_exc, ProtocolError)
          self.assertEqual(str(client.parser_exc), "expected a continuation frame")
          self.assertConnectionFailing(
              client, CloseCode.PROTOCOL_ERROR, "expected a continuation frame"
          )
  
      def test_server_receives_unexpected_text(self):
          server = Protocol(SERVER)
          server.receive_data(b"\x01\x80\x00\x00\x00\x00")
          self.assertFrameReceived(
              server,
              Frame(OP_TEXT, b"", fin=False),
          )
          server.receive_data(b"\x01\x80\x00\x00\x00\x00")
          self.assertIsInstance(server.parser_exc, ProtocolError)
          self.assertEqual(str(server.parser_exc), "expected a continuation frame")
          self.assertConnectionFailing(
              server, CloseCode.PROTOCOL_ERROR, "expected a continuation frame"
          )
  
      def test_client_sends_text_after_sending_close(self):
          client = Protocol(CLIENT)
          with patch("secrets.token_bytes", return_value=b"\x00\x00\x00\x00"):
              client.send_close(CloseCode.GOING_AWAY)
          self.assertEqual(client.data_to_send(), [b"\x88\x82\x00\x00\x00\x00\x03\xe9"])
          with self.assertRaises(InvalidState) as raised:
              client.send_text(b"")
          self.assertEqual(str(raised.exception), "connection is closing")
  
      def test_server_sends_text_after_sending_close(self):
          server = Protocol(SERVER)
          server.send_close(CloseCode.NORMAL_CLOSURE)
          self.assertEqual(server.data_to_send(), [b"\x88\x02\x03\xe8"])
          with self.assertRaises(InvalidState) as raised:
              server.send_text(b"")
          self.assertEqual(str(raised.exception), "connection is closing")
  
      def test_client_receives_text_after_receiving_close(self):
          client = Protocol(CLIENT)
          client.receive_data(b"\x88\x02\x03\xe8")
          self.assertConnectionClosing(client, CloseCode.NORMAL_CLOSURE)
          client.receive_data(b"\x81\x00")
          self.assertFrameReceived(client, None)
          self.assertFrameSent(client, None)
  
      def test_server_receives_text_after_receiving_close(self):
          server = Protocol(SERVER)
          server.receive_data(b"\x88\x82\x00\x00\x00\x00\x03\xe9")
          self.assertConnectionClosing(server, CloseCode.GOING_AWAY)
          server.receive_data(b"\x81\x80\x00\xff\x00\xff")
          self.assertFrameReceived(server, None)
          self.assertFrameSent(server, None)
  
  
  class BinaryTests(ProtocolTestCase):
      """
      Test binary frames and continuation frames.
  
      """
  
      def test_client_sends_binary(self):
          client = Protocol(CLIENT)
          with patch("secrets.token_bytes", return_value=b"\x00\x00\x00\x00"):
              client.send_binary(b"\x01\x02\xfe\xff")
          self.assertEqual(
              client.data_to_send(), [b"\x82\x84\x00\x00\x00\x00\x01\x02\xfe\xff"]
          )
  
      def test_server_sends_binary(self):
          server = Protocol(SERVER)
          server.send_binary(b"\x01\x02\xfe\xff")
          self.assertEqual(server.data_to_send(), [b"\x82\x04\x01\x02\xfe\xff"])
  
      def test_client_receives_binary(self):
          client = Protocol(CLIENT)
          client.receive_data(b"\x82\x04\x01\x02\xfe\xff")
          self.assertFrameReceived(
              client,
              Frame(OP_BINARY, b"\x01\x02\xfe\xff"),
          )
  
      def test_server_receives_binary(self):
          server = Protocol(SERVER)
          server.receive_data(b"\x82\x84\x00\x00\x00\x00\x01\x02\xfe\xff")
          self.assertFrameReceived(
              server,
              Frame(OP_BINARY, b"\x01\x02\xfe\xff"),
          )
  
      def test_client_receives_binary_over_size_limit(self):
          client = Protocol(CLIENT, max_size=3)
          client.receive_data(b"\x82\x04\x01\x02\xfe\xff")
          self.assertIsInstance(client.parser_exc, PayloadTooBig)
          self.assertEqual(
              str(client.parser_exc),
              "frame with 4 bytes exceeds limit of 3 bytes",
          )
          self.assertConnectionFailing(
              client,
              CloseCode.MESSAGE_TOO_BIG,
              "frame with 4 bytes exceeds limit of 3 bytes",
          )
  
      def test_server_receives_binary_over_size_limit(self):
          server = Protocol(SERVER, max_size=3)
          server.receive_data(b"\x82\x84\x00\x00\x00\x00\x01\x02\xfe\xff")
          self.assertIsInstance(server.parser_exc, PayloadTooBig)
          self.assertEqual(
              str(server.parser_exc),
              "frame with 4 bytes exceeds limit of 3 bytes",
          )
          self.assertConnectionFailing(
              server,
              CloseCode.MESSAGE_TOO_BIG,
              "frame with 4 bytes exceeds limit of 3 bytes",
          )
  
      def test_client_sends_fragmented_binary(self):
          client = Protocol(CLIENT)
          with patch("secrets.token_bytes", return_value=b"\x00\x00\x00\x00"):
              client.send_binary(b"\x01\x02", fin=False)
          self.assertEqual(client.data_to_send(), [b"\x02\x82\x00\x00\x00\x00\x01\x02"])
          with patch("secrets.token_bytes", return_value=b"\x00\x00\x00\x00"):
              client.send_continuation(b"\xee\xff\x01\x02", fin=False)
          self.assertEqual(
              client.data_to_send(), [b"\x00\x84\x00\x00\x00\x00\xee\xff\x01\x02"]
          )
          with patch("secrets.token_bytes", return_value=b"\x00\x00\x00\x00"):
              client.send_continuation(b"\xee\xff", fin=True)
          self.assertEqual(client.data_to_send(), [b"\x80\x82\x00\x00\x00\x00\xee\xff"])
  
      def test_server_sends_fragmented_binary(self):
          server = Protocol(SERVER)
          server.send_binary(b"\x01\x02", fin=False)
          self.assertEqual(server.data_to_send(), [b"\x02\x02\x01\x02"])
          server.send_continuation(b"\xee\xff\x01\x02", fin=False)
          self.assertEqual(server.data_to_send(), [b"\x00\x04\xee\xff\x01\x02"])
          server.send_continuation(b"\xee\xff", fin=True)
          self.assertEqual(server.data_to_send(), [b"\x80\x02\xee\xff"])
  
      def test_client_receives_fragmented_binary(self):
          client = Protocol(CLIENT)
          client.receive_data(b"\x02\x02\x01\x02")
          self.assertFrameReceived(
              client,
              Frame(OP_BINARY, b"\x01\x02", fin=False),
          )
          client.receive_data(b"\x00\x04\xfe\xff\x01\x02")
          self.assertFrameReceived(
              client,
              Frame(OP_CONT, b"\xfe\xff\x01\x02", fin=False),
          )
          client.receive_data(b"\x80\x02\xfe\xff")
          self.assertFrameReceived(
              client,
              Frame(OP_CONT, b"\xfe\xff"),
          )
  
      def test_server_receives_fragmented_binary(self):
          server = Protocol(SERVER)
          server.receive_data(b"\x02\x82\x00\x00\x00\x00\x01\x02")
          self.assertFrameReceived(
              server,
              Frame(OP_BINARY, b"\x01\x02", fin=False),
          )
          server.receive_data(b"\x00\x84\x00\x00\x00\x00\xee\xff\x01\x02")
          self.assertFrameReceived(
              server,
              Frame(OP_CONT, b"\xee\xff\x01\x02", fin=False),
          )
          server.receive_data(b"\x80\x82\x00\x00\x00\x00\xfe\xff")
          self.assertFrameReceived(
              server,
              Frame(OP_CONT, b"\xfe\xff"),
          )
  
      def test_client_receives_fragmented_binary_over_size_limit(self):
          client = Protocol(CLIENT, max_size=3)
          client.receive_data(b"\x02\x02\x01\x02")
          self.assertFrameReceived(
              client,
              Frame(OP_BINARY, b"\x01\x02", fin=False),
          )
          client.receive_data(b"\x80\x02\xfe\xff")
          self.assertIsInstance(client.parser_exc, PayloadTooBig)
          self.assertEqual(
              str(client.parser_exc),
              "frame with 2 bytes after reading 2 bytes exceeds limit of 3 bytes",
          )
          self.assertConnectionFailing(
              client,
              CloseCode.MESSAGE_TOO_BIG,
              "frame with 2 bytes after reading 2 bytes exceeds limit of 3 bytes",
          )
  
      def test_server_receives_fragmented_binary_over_size_limit(self):
          server = Protocol(SERVER, max_size=3)
          server.receive_data(b"\x02\x82\x00\x00\x00\x00\x01\x02")
          self.assertFrameReceived(
              server,
              Frame(OP_BINARY, b"\x01\x02", fin=False),
          )
          server.receive_data(b"\x80\x82\x00\x00\x00\x00\xfe\xff")
          self.assertIsInstance(server.parser_exc, PayloadTooBig)
          self.assertEqual(
              str(server.parser_exc),
              "frame with 2 bytes after reading 2 bytes exceeds limit of 3 bytes",
          )
          self.assertConnectionFailing(
              server,
              CloseCode.MESSAGE_TOO_BIG,
              "frame with 2 bytes after reading 2 bytes exceeds limit of 3 bytes",
          )
  
      def test_client_sends_unexpected_binary(self):
          client = Protocol(CLIENT)
          client.send_binary(b"", fin=False)
          with self.assertRaises(ProtocolError) as raised:
              client.send_binary(b"", fin=False)
          self.assertEqual(str(raised.exception), "expected a continuation frame")
  
      def test_server_sends_unexpected_binary(self):
          server = Protocol(SERVER)
          server.send_binary(b"", fin=False)
          with self.assertRaises(ProtocolError) as raised:
              server.send_binary(b"", fin=False)
          self.assertEqual(str(raised.exception), "expected a continuation frame")
  
      def test_client_receives_unexpected_binary(self):
          client = Protocol(CLIENT)
          client.receive_data(b"\x02\x00")
          self.assertFrameReceived(
              client,
              Frame(OP_BINARY, b"", fin=False),
          )
          client.receive_data(b"\x02\x00")
          self.assertIsInstance(client.parser_exc, ProtocolError)
          self.assertEqual(str(client.parser_exc), "expected a continuation frame")
          self.assertConnectionFailing(
              client, CloseCode.PROTOCOL_ERROR, "expected a continuation frame"
          )
  
      def test_server_receives_unexpected_binary(self):
          server = Protocol(SERVER)
          server.receive_data(b"\x02\x80\x00\x00\x00\x00")
          self.assertFrameReceived(
              server,
              Frame(OP_BINARY, b"", fin=False),
          )
          server.receive_data(b"\x02\x80\x00\x00\x00\x00")
          self.assertIsInstance(server.parser_exc, ProtocolError)
          self.assertEqual(str(server.parser_exc), "expected a continuation frame")
          self.assertConnectionFailing(
              server, CloseCode.PROTOCOL_ERROR, "expected a continuation frame"
          )
  
      def test_client_sends_binary_after_sending_close(self):
          client = Protocol(CLIENT)
          with patch("secrets.token_bytes", return_value=b"\x00\x00\x00\x00"):
              client.send_close(CloseCode.GOING_AWAY)
          self.assertEqual(client.data_to_send(), [b"\x88\x82\x00\x00\x00\x00\x03\xe9"])
          with self.assertRaises(InvalidState) as raised:
              client.send_binary(b"")
          self.assertEqual(str(raised.exception), "connection is closing")
  
      def test_server_sends_binary_after_sending_close(self):
          server = Protocol(SERVER)
          server.send_close(CloseCode.NORMAL_CLOSURE)
          self.assertEqual(server.data_to_send(), [b"\x88\x02\x03\xe8"])
          with self.assertRaises(InvalidState) as raised:
              server.send_binary(b"")
          self.assertEqual(str(raised.exception), "connection is closing")
  
      def test_client_receives_binary_after_receiving_close(self):
          client = Protocol(CLIENT)
          client.receive_data(b"\x88\x02\x03\xe8")
          self.assertConnectionClosing(client, CloseCode.NORMAL_CLOSURE)
          client.receive_data(b"\x82\x00")
          self.assertFrameReceived(client, None)
          self.assertFrameSent(client, None)
  
      def test_server_receives_binary_after_receiving_close(self):
          server = Protocol(SERVER)
          server.receive_data(b"\x88\x82\x00\x00\x00\x00\x03\xe9")
          self.assertConnectionClosing(server, CloseCode.GOING_AWAY)
          server.receive_data(b"\x82\x80\x00\xff\x00\xff")
          self.assertFrameReceived(server, None)
          self.assertFrameSent(server, None)
  
  
  class CloseTests(ProtocolTestCase):
      """
      Test close frames.
  
      See RFC 6455:
  
      5.5.1. Close
      7.1.6.  The WebSocket Connection Close Reason
      7.1.7.  Fail the WebSocket Connection
  
      """
  
      def test_close_code(self):
          client = Protocol(CLIENT)
          client.receive_data(b"\x88\x04\x03\xe8OK")
          client.receive_eof()
          self.assertEqual(client.close_code, CloseCode.NORMAL_CLOSURE)
  
      def test_close_reason(self):
          server = Protocol(SERVER)
          server.receive_data(b"\x88\x84\x00\x00\x00\x00\x03\xe8OK")
          server.receive_eof()
          self.assertEqual(server.close_reason, "OK")
  
      def test_close_code_not_provided(self):
          server = Protocol(SERVER)
          server.receive_data(b"\x88\x80\x00\x00\x00\x00")
          server.receive_eof()
          self.assertEqual(server.close_code, CloseCode.NO_STATUS_RCVD)
  
      def test_close_reason_not_provided(self):
          client = Protocol(CLIENT)
          client.receive_data(b"\x88\x00")
          client.receive_eof()
          self.assertEqual(client.close_reason, "")
  
      def test_close_code_not_available(self):
          client = Protocol(CLIENT)
          client.receive_eof()
          self.assertEqual(client.close_code, CloseCode.ABNORMAL_CLOSURE)
  
      def test_close_reason_not_available(self):
          server = Protocol(SERVER)
          server.receive_eof()
          self.assertEqual(server.close_reason, "")
  
      def test_close_code_not_available_yet(self):
          server = Protocol(SERVER)
          self.assertIsNone(server.close_code)
  
      def test_close_reason_not_available_yet(self):
          client = Protocol(CLIENT)
          self.assertIsNone(client.close_reason)
  
      def test_client_sends_close(self):
          client = Protocol(CLIENT)
          with patch("secrets.token_bytes", return_value=b"\x3c\x3c\x3c\x3c"):
              client.send_close()
          self.assertEqual(client.data_to_send(), [b"\x88\x80\x3c\x3c\x3c\x3c"])
          self.assertIs(client.state, CLOSING)
  
      def test_server_sends_close(self):
          server = Protocol(SERVER)
          server.send_close()
          self.assertEqual(server.data_to_send(), [b"\x88\x00"])
          self.assertIs(server.state, CLOSING)
  
      def test_client_receives_close(self):
          client = Protocol(CLIENT)
          with patch("secrets.token_bytes", return_value=b"\x3c\x3c\x3c\x3c"):
              client.receive_data(b"\x88\x00")
  