def test_delegated_methods(self, method, mocker): self.slipstream = SlipStream(io.BufferedIOBase()) mocker.patch.object(sliplib.io.BufferedIOBase, method) getattr(sliplib.io.BufferedIOBase, method).reset_mock() getattr(self.slipstream, method)() # Don't care about the arguments getattr(sliplib.io.BufferedIOBase, method).assert_called_once_with() self.slipstream.close()
def test_recovery_from_protocol_error_with_unbuffered_reads(self): """Verify error recover for unbuffered reads.""" msg_list = [b'hallo', b'bye'] self.stream_mock.read.side_effect = list(END + msg_list[0] + END + ESC + END + msg_list[1] + END) + [b''] self.slipstream = SlipStream(self.stream_mock, 1) self.verify_error_recovery(msg_list)
def test_writing_slip_file(self): """Test writing SLIP-encoded messages""" with self.filepath.open(mode='wb', buffering=0) as f: slipstream = SlipStream(f) for msg in data: slipstream.send_msg(msg) assert self.filepath.read_bytes() == b''.join(encode(msg) for msg in data)
def test_recovery_from_protocol_error_during_iteration_with_unbuffered_reads( self): """Verify that error recovery works during iteration with unbuffered reads.""" msg_list = [b'hallo', b'bye'] self.stream_mock.read.side_effect = list(END + msg_list[0] + END + ESC + END + msg_list[1] + END) + [b''] self.slipstream = SlipStream(self.stream_mock, 1) self.verify_error_recovery_during_iteration(msg_list)
def setup(self, mocker): """Prepare the test.""" self.stream_mock = mocker.Mock(spec_set=('read', 'write', 'readable', 'writable')) self.stream_mock.read = mocker.Mock() self.stream_mock.write = mocker.Mock() self.slipstream = SlipStream(self.stream_mock) yield
def test_stream_reading_single_bytes(self): """Test reading single bytes from the bytestream""" msg_list = [b'hallo', b'bye'] self.basestream.write(END + msg_list[0] + END + END + msg_list[1] + END) self.basestream.seek(0) self.slipstream = SlipStream(self.basestream, 1) assert self.slipstream.recv_msg() == msg_list[0] assert self.slipstream.recv_msg() == msg_list[1] # No more messages assert self.slipstream.recv_msg() == b''
def test_slipstream_reading_single_bytes(self, mocker): """Verify that receiving messages works when reading the packets byte for byte.""" msg_list = [b'hallo', b'bye'] self.stream_mock.read.side_effect = list(END + msg_list[0] + END + END + msg_list[1] + END) + [b''] self.slipstream = SlipStream(self.stream_mock, 1) assert self.slipstream.recv_msg() == msg_list[0] assert self.slipstream.recv_msg() == msg_list[1] # No more messages assert self.slipstream.recv_msg() == b'' assert self.stream_mock.read.mock_calls == [mocker.call(1)] * 13
def test_file_writing(self, tmpdir): f = tmpdir.mkdir('writing').join('slip.txt') s = SlipStream(f.open(mode='wb')) s.send_msg(b'hallo') s.send_msg(b'bye') s.close() assert f.read_binary() == END + b'hallo' + END + END + b'bye' + END
def test_reading_slip_file(self): """Test reading SLIP-encoded message""" self.filepath.write_bytes(b''.join(encode(msg) for msg in data)) with self.filepath.open(mode='rb', buffering=0) as f: slipstream = SlipStream(f) for exp, act in zip(data, slipstream): assert exp == act
def setup(self, mocker): """Prepare the test.""" warnings.simplefilter('always') self.stream_mock = mocker.Mock(spec_set=['read', 'write'] + DELEGATED_METHODS) self.slipstream = SlipStream(self.stream_mock) yield warnings.simplefilter('default')
class TestSlipStreamWithFileIO: def test_file_writing(self, tmpdir): f = tmpdir.mkdir('writing').join('slip.txt') s = SlipStream(f.open(mode='wb')) s.send_msg(b'hallo') s.send_msg(b'bye') s.close() assert f.read_binary() == END + b'hallo' + END + END + b'bye' + END def test_file_reading(self, tmpdir): f = tmpdir.mkdir('reading').join('slip.txt') f.write_binary(END + b'hallo' + END + END + b'bye' + END) s = SlipStream(f.open(mode='rb')) assert s.recv_msg() == b'hallo' assert s.recv_msg() == b'bye' assert s.recv_msg() == b'' s.close() @pytest.mark.parametrize('method', [ 'detach', 'getbuffer', 'getvalue', 'peek', 'raw', 'read', 'read1', 'readinto', 'readinto1', 'readline', 'readlines', 'seek', 'tell', 'truncate', 'write', 'writelines' ]) def test_exception_for_not_supported_operations(self, method): self.slipstream = SlipStream(io.BufferedIOBase()) with pytest.raises(AttributeError): getattr(self.slipstream, method) self.slipstream.close() # noinspection PyUnresolvedReferences @pytest.mark.parametrize('method', [ attr for attr in dir(io.BytesIO) if not attr.startswith('_') and callable(getattr(io.BytesIO, attr)) and attr not in ('detach', 'getbuffer', 'getvalue', 'read', 'read1', 'readinto', 'readinto1', 'readline', 'readlines', 'seek', 'tell', 'truncate', 'write', 'writelines') ]) def test_delegated_methods(self, method, mocker): self.slipstream = SlipStream(io.BufferedIOBase()) mocker.patch.object(sliplib.io.BufferedIOBase, method) getattr(sliplib.io.BufferedIOBase, method).reset_mock() getattr(self.slipstream, method)() # Don't care about the arguments getattr(sliplib.io.BufferedIOBase, method).assert_called_once_with() self.slipstream.close()
def test_file_reading(self, tmpdir): f = tmpdir.mkdir('reading').join('slip.txt') f.write_binary(END + b'hallo' + END + END + b'bye' + END) s = SlipStream(f.open(mode='rb')) assert s.recv_msg() == b'hallo' assert s.recv_msg() == b'bye' assert s.recv_msg() == b'' s.close()
class TestSlipStreamWithBytesIO: @pytest.fixture(autouse=True) def setup(self): self.basestream = io.BytesIO() # noinspection PyTypeChecker self.slipstream = SlipStream(self.basestream) yield self.slipstream.close() def test_stream_creation(self): assert self.slipstream.stream is self.basestream def test_stream_reading(self): msg_list = [b'hallo', b'bye'] self.basestream.write(END + msg_list[0] + END + END + msg_list[1] + END) self.basestream.seek(0) assert self.slipstream.recv_msg() == msg_list[0] assert self.slipstream.recv_msg() == msg_list[1] self.basestream.close() # No more messages assert self.slipstream.recv_msg() == b'' def test_stream_writing(self): msg_list = [b'hallo', b'bye'] for msg in msg_list: self.slipstream.send_msg(msg) assert self.basestream.getvalue( ) == END + msg_list[0] + END + END + msg_list[1] + END @pytest.mark.parametrize('method', [ 'detach', 'getbuffer', 'getvalue', 'peek', 'raw', 'read', 'read1', 'readinto', 'readinto1', 'readline', 'readlines', 'seek', 'tell', 'truncate', 'write', 'writelines' ]) def test_exception_for_not_supported_operations(self, method): with pytest.raises(AttributeError): getattr(self.slipstream, method) # Cannot test delegated methods in this way, because py.test complains with # TypeError: can't set attributes of built-in/extension type '_io.BytesIO' # # noinspection PyUnresolvedReferences @pytest.mark.skip(reason="Cannot patch attributes of io.BytesIO") @pytest.mark.parametrize('method', [ attr for attr in dir(io.BytesIO) if not attr.startswith('_') and callable(getattr(io.BytesIO, attr)) and attr not in ('detach', 'getbuffer', 'getvalue', 'read', 'read1', 'readinto', 'readinto1', 'readline', 'readlines', 'seek', 'tell', 'truncate', 'write', 'writelines') ]) def test_delegated_methods(self, method, mocker): mocker.patch.object(sliplib.io.BytesIO, method) getattr(sliplib.io.BytesIO, method).reset_mock() getattr(self.slipstream, method)() # Don't care about the arguments getattr(sliplib.io.BytesIO, method).assert_called_once_with()
class TestSlipStreamWithBytesIO: """Test SlipStream with BytesIO.""" @pytest.fixture(autouse=True) def setup(self): """Setup the test""" self.basestream = io.BytesIO() self.slipstream = SlipStream(self.basestream) yield self.basestream.close() def test_stream_reading(self): """Test reading from the bytestream""" msg_list = [b'hallo', b'bye'] self.basestream.write(END + msg_list[0] + END + END + msg_list[1] + END) self.basestream.seek(0) assert self.slipstream.recv_msg() == msg_list[0] assert self.slipstream.recv_msg() == msg_list[1] # No more messages assert self.slipstream.recv_msg() == b'' def test_stream_reading_single_bytes(self): """Test reading single bytes from the bytestream""" msg_list = [b'hallo', b'bye'] self.basestream.write(END + msg_list[0] + END + END + msg_list[1] + END) self.basestream.seek(0) self.slipstream = SlipStream(self.basestream, 1) assert self.slipstream.recv_msg() == msg_list[0] assert self.slipstream.recv_msg() == msg_list[1] # No more messages assert self.slipstream.recv_msg() == b'' def test_stream_writing(self): """Test writing to the bytestream""" msg_list = [b'hallo', b'bye'] for msg in msg_list: self.slipstream.send_msg(msg) assert self.basestream.getvalue() == END + msg_list[0] + END + END + msg_list[1] + END
class TestSlipStreamBasics: """Tests for basic SlipStream functionality.""" @pytest.fixture(autouse=True) def setup(self, mocker): """Prepare the test.""" self.stream_mock = mocker.Mock(spec_set=('read', 'write', 'readable', 'writable')) self.stream_mock.read = mocker.Mock() self.stream_mock.write = mocker.Mock() self.slipstream = SlipStream(self.stream_mock) yield def test_slipstream_creation(self): """Verify the creation of the SlipStream instance.""" assert self.slipstream.stream is self.stream_mock @pytest.mark.parametrize('rbl, wbl', [(True, True), (True, False), (False, True), (False, False)]) def test_slipstream_readable_and_writable_attributes(self, rbl, wbl): """Verify the readable and writable attributes.""" self.stream_mock.configure_mock(readable=rbl, writable=wbl) assert self.slipstream.readable == rbl assert self.slipstream.writable == wbl def test_slipstream_reading(self, mocker): """Verify that receiving messages works by calling the stream's read method.""" msg_list = [b'hallo', b'bye'] self.stream_mock.read.side_effect = (END + msg_list[0] + END + END + msg_list[1] + END, b'') assert self.slipstream.recv_msg() == msg_list[0] assert self.slipstream.recv_msg() == msg_list[1] # No more messages assert self.slipstream.recv_msg() == b'' assert self.stream_mock.read.mock_calls == [ mocker.call(io.DEFAULT_BUFFER_SIZE) ] * 2 def test_slipstream_reading_single_bytes(self, mocker): """Verify that receiving messages works when reading the packets byte for byte.""" msg_list = [b'hallo', b'bye'] self.stream_mock.read.side_effect = list(END + msg_list[0] + END + END + msg_list[1] + END) + [b''] self.slipstream = SlipStream(self.stream_mock, 1) assert self.slipstream.recv_msg() == msg_list[0] assert self.slipstream.recv_msg() == msg_list[1] # No more messages assert self.slipstream.recv_msg() == b'' assert self.stream_mock.read.mock_calls == [mocker.call(1)] * 13 def test_slipstream_writing(self, mocker): """Verify that sending messages works by calling the stream's write method""" msg_list = [b'hallo', b'bye'] self.stream_mock.write.side_effect = (len(END + msg_list[0] + END), len(END + msg_list[1] + END)) for msg in msg_list: self.slipstream.send_msg(msg) assert self.stream_mock.write.mock_calls == [ mocker.call(END + msg_list[0] + END), mocker.call(END + msg_list[1] + END) ] def test_slipstream_writing_single_bytes(self, mocker): """Verify that sending messages work when the stream's write method does not handle all the bytes at once.""" msg_list = [b'hallo', b'bye'] self.stream_mock.write.return_value = 1 for msg in msg_list: self.slipstream.send_msg(msg) encoded_messages = (END + msg_list[0] + END, END + msg_list[1] + END) call_list = [ mocker.call(enc_msg[i:]) for enc_msg in encoded_messages for i in range(len(enc_msg)) ] assert self.stream_mock.write.mock_calls == call_list def test_iterating_over_slipstream(self): """Verify that a SlipStream object can be iterated over.""" msg_list = [b'hallo', b'bye'] self.stream_mock.read.side_effect = (END + msg_list[0] + END + END + msg_list[1] + END, b'') for i, msg in enumerate(self.slipstream): assert msg_list[i] == msg def verify_error_recovery(self, msg_list): """Helper function to verify error recovery.""" assert self.slipstream.recv_msg() == msg_list[0] with pytest.raises(ProtocolError): self.slipstream.recv_msg() assert self.slipstream.recv_msg() == msg_list[1] def test_recovery_from_protocol_error(self): """Verify error recovery for buffered reads.""" msg_list = [b'hallo', b'bye'] self.stream_mock.read.side_effect = (END + msg_list[0] + END + ESC + END + msg_list[1] + END, b'') self.verify_error_recovery(msg_list) def test_recovery_from_protocol_error_with_unbuffered_reads(self): """Verify error recover for unbuffered reads.""" msg_list = [b'hallo', b'bye'] self.stream_mock.read.side_effect = list(END + msg_list[0] + END + ESC + END + msg_list[1] + END) + [b''] self.slipstream = SlipStream(self.stream_mock, 1) self.verify_error_recovery(msg_list) def verify_error_recovery_during_iteration(self, msg_list): """Helper function to verify error recovery during iteration.""" received_message = [] with pytest.raises(ProtocolError): for msg in self.slipstream: received_message.append(msg) assert received_message == msg_list[:1] for msg in self.slipstream: received_message.append(msg) assert received_message == msg_list def test_recovery_from_protocol_error_during_iteration(self): """Verify that error recovery works during iteration with buffered reads.""" msg_list = [b'hallo', b'bye'] self.stream_mock.read.side_effect = (END + msg_list[0] + END + ESC + END + msg_list[1] + END, b'') self.verify_error_recovery_during_iteration(msg_list) def test_recovery_from_protocol_error_during_iteration_with_unbuffered_reads( self): """Verify that error recovery works during iteration with unbuffered reads.""" msg_list = [b'hallo', b'bye'] self.stream_mock.read.side_effect = list(END + msg_list[0] + END + ESC + END + msg_list[1] + END) + [b''] self.slipstream = SlipStream(self.stream_mock, 1) self.verify_error_recovery_during_iteration(msg_list)
def test_slip_stream_fails_if_instantiated_with_non_bytestream_argument(): """SlipStream rejects a stream with encoding.""" with pytest.raises(TypeError): SlipStream(io.StringIO())
def setup(self): self.basestream = io.BytesIO() # noinspection PyTypeChecker self.slipstream = SlipStream(self.basestream) yield self.slipstream.close()
def test_slip_stream_fails_if_instantiated_with_non_io_stream_argument(): """SlipStream requires a stream with a read and write method""" with pytest.raises(TypeError): SlipStream('string is not valid as a bytestream')
def setup(self): """Setup the test""" self.basestream = io.BytesIO() self.slipstream = SlipStream(self.basestream) yield self.basestream.close()
def test_exception_for_not_supported_operations(self, method): self.slipstream = SlipStream(io.BufferedIOBase()) with pytest.raises(AttributeError): getattr(self.slipstream, method) self.slipstream.close()