Skip to content

Commit 3dc4d18

Browse files
committed
bpo-41279: Add BufferedProtocol to unix read pipe transport tests (GH-21446)
1 parent 9e81f1a commit 3dc4d18

File tree

1 file changed

+128
-52
lines changed

1 file changed

+128
-52
lines changed

Lib/test/test_asyncio/test_unix_events.py

Lines changed: 128 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -652,12 +652,14 @@ def test_sock_sendfile_exception(self):
652652
self.assertEqual(1000, self.file.tell())
653653

654654

655-
class UnixReadPipeTransportTests(test_utils.TestCase):
655+
class UnixReadPipeTransportTestsBase:
656656

657-
def setUp(self):
658-
super().setUp()
657+
def make_test_protocol(self):
658+
raise NotImplementedError
659+
660+
def setup_globals(self):
659661
self.loop = self.new_test_loop()
660-
self.protocol = test_utils.make_test_protocol(asyncio.Protocol)
662+
self.protocol = None
661663
self.pipe = mock.Mock(spec_set=io.RawIOBase)
662664
self.pipe.fileno.return_value = 5
663665

@@ -672,6 +674,8 @@ def setUp(self):
672674
m_fstat.return_value = st
673675
self.addCleanup(fstat_patcher.stop)
674676

677+
self.make_test_protocol()
678+
675679
def read_pipe_transport(self, waiter=None):
676680
transport = unix_events._UnixReadPipeTransport(self.loop, self.pipe,
677681
self.protocol,
@@ -688,54 +692,6 @@ def test_ctor(self):
688692
self.loop.assert_reader(5, tr._read_ready)
689693
self.assertIsNone(waiter.result())
690694

691-
@mock.patch('os.read')
692-
def test__read_ready(self, m_read):
693-
tr = self.read_pipe_transport()
694-
m_read.return_value = b'data'
695-
tr._read_ready()
696-
697-
m_read.assert_called_with(5, tr.max_size)
698-
self.protocol.data_received.assert_called_with(b'data')
699-
700-
@mock.patch('os.read')
701-
def test__read_ready_eof(self, m_read):
702-
tr = self.read_pipe_transport()
703-
m_read.return_value = b''
704-
tr._read_ready()
705-
706-
m_read.assert_called_with(5, tr.max_size)
707-
self.assertFalse(self.loop.readers)
708-
test_utils.run_briefly(self.loop)
709-
self.protocol.eof_received.assert_called_with()
710-
self.protocol.connection_lost.assert_called_with(None)
711-
712-
@mock.patch('os.read')
713-
def test__read_ready_blocked(self, m_read):
714-
tr = self.read_pipe_transport()
715-
m_read.side_effect = BlockingIOError
716-
tr._read_ready()
717-
718-
m_read.assert_called_with(5, tr.max_size)
719-
test_utils.run_briefly(self.loop)
720-
self.assertFalse(self.protocol.data_received.called)
721-
722-
@mock.patch('asyncio.log.logger.error')
723-
@mock.patch('os.read')
724-
def test__read_ready_error(self, m_read, m_logexc):
725-
tr = self.read_pipe_transport()
726-
err = OSError()
727-
m_read.side_effect = err
728-
tr._close = mock.Mock()
729-
tr._read_ready()
730-
731-
m_read.assert_called_with(5, tr.max_size)
732-
tr._close.assert_called_with(err)
733-
m_logexc.assert_called_with(
734-
test_utils.MockPattern(
735-
'Fatal read error on pipe transport'
736-
'\nprotocol:.*\ntransport:.*'),
737-
exc_info=(OSError, MOCK_ANY, MOCK_ANY))
738-
739695
@mock.patch('os.read')
740696
def test_pause_reading(self, m_read):
741697
tr = self.read_pipe_transport()
@@ -829,6 +785,126 @@ def test_resume_reading_on_paused_pipe(self):
829785
tr.resume_reading()
830786

831787

788+
class UnixReadPipeTransportWithProtocolTests(test_utils.TestCase, UnixReadPipeTransportTestsBase):
789+
790+
def make_test_protocol(self):
791+
self.protocol = test_utils.make_test_protocol(asyncio.Protocol)
792+
793+
def setUp(self):
794+
super().setUp()
795+
self.setup_globals()
796+
797+
@mock.patch('os.read')
798+
def test__read_ready(self, m_read):
799+
tr = self.read_pipe_transport()
800+
m_read.return_value = b'data'
801+
tr._read_ready()
802+
803+
m_read.assert_called_with(5, tr.max_size)
804+
self.protocol.data_received.assert_called_with(b'data')
805+
806+
@mock.patch('os.read')
807+
def test__read_ready_eof(self, m_read):
808+
tr = self.read_pipe_transport()
809+
m_read.return_value = b''
810+
tr._read_ready()
811+
812+
m_read.assert_called_with(5, tr.max_size)
813+
self.assertFalse(self.loop.readers)
814+
test_utils.run_briefly(self.loop)
815+
self.protocol.eof_received.assert_called_with()
816+
self.protocol.connection_lost.assert_called_with(None)
817+
818+
@mock.patch('os.read')
819+
def test__read_ready_blocked(self, m_read):
820+
tr = self.read_pipe_transport()
821+
m_read.side_effect = BlockingIOError
822+
tr._read_ready()
823+
824+
m_read.assert_called_with(5, tr.max_size)
825+
test_utils.run_briefly(self.loop)
826+
self.assertFalse(self.protocol.data_received.called)
827+
828+
@mock.patch('asyncio.log.logger.error')
829+
@mock.patch('os.read')
830+
def test__read_ready_error(self, m_read, m_logexc):
831+
tr = self.read_pipe_transport()
832+
err = OSError()
833+
m_read.side_effect = err
834+
tr._close = mock.Mock()
835+
tr._read_ready()
836+
837+
m_read.assert_called_with(5, tr.max_size)
838+
tr._close.assert_called_with(err)
839+
m_logexc.assert_called_with(
840+
test_utils.MockPattern(
841+
'Fatal read error on pipe transport'
842+
'\nprotocol:.*\ntransport:.*'),
843+
exc_info=(OSError, MOCK_ANY, MOCK_ANY))
844+
845+
846+
class UnixReadPipeTransportWithBufferedProtocolTests(test_utils.TestCase, UnixReadPipeTransportTestsBase):
847+
848+
def make_test_protocol(self):
849+
self.protocol = test_utils.make_test_buffered_protocol(
850+
asyncio.BufferedProtocol, 65536)
851+
852+
def setUp(self):
853+
super().setUp()
854+
self.setup_globals()
855+
856+
def set_next_buffered_read(self, data):
857+
data_length = len(data)
858+
buf = self.protocol.get_buffer(data_length)
859+
buf[:data_length] = data
860+
self.pipe.readinto.return_value = data_length
861+
862+
def test__read_ready(self):
863+
tr = self.read_pipe_transport()
864+
data = b'data'
865+
self.set_next_buffered_read(data)
866+
tr._read_ready()
867+
868+
self.pipe.readinto.assert_called_once()
869+
self.assertTrue(self.protocol.buffer_updated.called)
870+
self.assertEqual(self.protocol._last_called_buffer[:len(data)], bytearray(data))
871+
872+
def test__read_ready_eof(self):
873+
tr = self.read_pipe_transport()
874+
self.set_next_buffered_read(b'')
875+
tr._read_ready()
876+
877+
self.pipe.readinto.assert_called_once()
878+
self.assertFalse(self.loop.readers)
879+
test_utils.run_briefly(self.loop)
880+
self.protocol.eof_received.assert_called_with()
881+
882+
def test__read_ready_blocked(self):
883+
tr = self.read_pipe_transport()
884+
self.pipe.readinto.side_effect = BlockingIOError
885+
tr._read_ready()
886+
887+
self.pipe.readinto.assert_called_once()
888+
test_utils.run_briefly(self.loop)
889+
self.assertFalse(self.protocol.buffer_updated.called)
890+
891+
@mock.patch('asyncio.log.logger.error')
892+
def test__read_ready_error(self, m_logexc):
893+
tr = self.read_pipe_transport()
894+
err = OSError()
895+
self.pipe.readinto.side_effect = err
896+
tr._close = mock.Mock()
897+
tr._read_ready()
898+
899+
self.pipe.readinto.assert_called_once()
900+
tr._close.assert_called_with(err)
901+
m_logexc.assert_called_with(
902+
test_utils.MockPattern(
903+
'Fatal read error on pipe transport'
904+
'\nprotocol:.*\ntransport:.*'),
905+
exc_info=(OSError, MOCK_ANY, MOCK_ANY))
906+
907+
832908
class UnixWritePipeTransportTests(test_utils.TestCase):
833909

834910
def setUp(self):

0 commit comments

Comments
 (0)