예제 #1
0
    def test_read_message_buffered(self, mocked_sys_action, mocked_cows):
        """ Tests that we can read a message when we get an extra buffered one. """
        # Create two messages to read.
        message1 = test_pb2.TestMessage()
        message1.field1 = 42
        message1.field2 = True
        bin_message1 = message1.SerializeToString()

        message2 = test_pb2.TestMessage()
        message2.field1 = 1337
        message2.field2 = True
        bin_message2 = message2.SerializeToString()

        # Configure the fake cows implementation.
        fake_cows = self.FakeCowsUnstuff([bin_message1, bin_message2])
        mocked_cows.side_effect = fake_cows

        mocked_sys_action.return_value = message1

        # Create the SerialCom object.
        com, mocked_socket = self.__make_serial()

        # Make it look like synchronizing to the packet boundary worked. It will
        # attempt to read the first message first. In this case, it will get the
        # second message as well.
        fake_message1 = self.__fake_message(len(bin_message1))
        fake_message2 = self.__fake_message(len(bin_message2))
        mocked_socket.recv.side_effect = [
            _SEPARATOR, fake_message1 + fake_message2
        ]

        # Try to read the first message.
        got_message1 = com.read_message()

        # The first call to recv() should have been for the initial separator. The
        # second call should have been for the first message, ending separator,
        # and second message and its ending separator.
        expected_calls = [mock.call.recv(len(_SEPARATOR)), mock.call.recv()]
        mocked_socket.assert_has_calls(expected_calls)
        mocked_socket.recv.reset_mock()
        # It should have tried to unstuff it.
        mocked_cows.assert_called_once()
        mocked_cows.reset_mock()

        # Make sure the message matches.
        self.assertEqual(message1, got_message1)

        # We should be able to call read_message again and essentially get the next
        # message for free.
        got_message2 = com.read_message()

        # There should be no calls to the recv method.
        mocked_socket.recv.assert_not_called()
        # It should have tried to unstuff the message.
        mocked_cows.assert_called_once()

        # Make sure the message matches.
        self.assertEqual(message2, got_message2)
예제 #2
0
    def test_read_message(self, mocked_sys_action, mocked_cows):
        """ Tests that we can read a message under normal conditions. """
        # Create the message to read.
        message = test_pb2.TestMessage()
        message.field1 = 42
        message.field2 = True
        mocked_sys_action.return_value = message
        bin_message = message.SerializeToString()

        # Configure the fake cows implementation.
        fake_cows = self.FakeCowsUnstuff(bin_message)
        mocked_cows.side_effect = fake_cows

        # Create the SerialCom object.
        com, mocked_socket = self.__make_serial()

        # Make it look like synchronizing to the packet boundary worked. It will
        # then attempt to read the entire message.
        fake_message = self.__fake_message(len(bin_message))
        mocked_socket.recv.side_effect = [_SEPARATOR, fake_message]

        # Try to read the message.
        got_message = com.read_message()

        # The first call to read() should have been for the initial separator. The
        # second call should have been for the message and ending separator.
        expected_calls = [mock.call.recv(len(_SEPARATOR)), mock.call.recv()]
        mocked_socket.assert_has_calls(expected_calls)
        # It should have tried to unstuff it.
        mocked_cows.assert_called_once()

        # Make sure the message matches.
        self.assertEqual(message, got_message)
예제 #3
0
    def test_write_partial_message(self, mocked_cows):
        """ Tests that we can write a message when the message gets broken up across
    multiple writes. """
        # Create a message to write.
        message = test_pb2.TestMessage()
        message.field1 = 42
        message.field2 = True

        # Create the SerialCom object.
        com, mocked_socket = self.__make_serial()

        # Make it look like the write succeeded in two tries. (Add two bytes for the
        # overhead.)
        mocked_socket.send.side_effect = [
            message.ByteSize() + 2, len(_SEPARATOR)
        ]
        # For the cows stuffing, we're just not going to do anything.

        com.write_message(message)

        # It should have written the message.
        bin_message = message.SerializeToString()
        mocked_cows.assert_called_once_with(bytearray(2) + bin_message)
        # It should have made two calls to write.
        expected_calls = [
            mock.call.send(bytearray(2) + bin_message + _SEPARATOR),
            mock.call.send(_SEPARATOR)
        ]
        mocked_socket.assert_has_calls(expected_calls)
예제 #4
0
    def test_read_message_split(self, mocked_sys_action, mocked_cows):
        """ Tests that we can read a message when it is split across multiple read
    calls. """
        # Create the message to read.
        message = test_pb2.TestMessage()
        message.field1 = 42
        message.field2 = True
        mocked_sys_action.return_value = message
        bin_message = message.SerializeToString()

        # Configure the fake cows implementation.
        fake_cows = self.FakeCowsUnstuff(bin_message)
        mocked_cows.side_effect = fake_cows

        # Create the SerialCom object.
        com, mocked_socket = self.__make_serial()

        # Make it look like synchronizing to the packet boundary worked. It will
        # attempt to read the entire message afterwards, but initially, it will only
        # get the first byte. It will then have to make another call to get the
        # rest.
        fake_message = self.__fake_message(len(bin_message))
        mocked_socket.recv.side_effect = [
            _SEPARATOR, fake_message[0], fake_message[1], fake_message[2:]
        ]

        # Try to read the message.
        got_message = com.read_message()

        # The first call to recv() should have been for the initial separator. The
        # second call should have been for the first byte of the message, the
        # third call should have been for reading the second byte of the message,
        # and the fourth call should have been for reading the rest of the message
        # and the next separator.
        expected_calls = [
            mock.call.recv(len(_SEPARATOR)),
            mock.call.recv(),
            mock.call.recv(),
            mock.call.recv()
        ]
        mocked_socket.assert_has_calls(expected_calls)
        # It should have tried to unstuff it.
        mocked_cows.assert_called_once()

        # Make sure the message matches.
        self.assertEqual(message, got_message)
예제 #5
0
    def test_write(self, mocked_cows):
        """ Tests that we can write a message under normal conditions. """
        # Create a message to write.
        message = test_pb2.TestMessage()
        message.field1 = 42
        message.field2 = True

        # Create the SerialCom object.
        com, mocked_socket = self.__make_serial()

        # Make it look like the write succeeded in one go.
        mocked_socket.send.return_value = message.ByteSize() + 2 + len(
            _SEPARATOR)
        # For the cows stuffing, we're just not going to do anything.

        com.write_message(message)

        # It should have written the message, plus an overhead word.
        bin_message = message.SerializeToString()
        mocked_cows.assert_called_once_with(bytearray(2) + bin_message)
        mocked_socket.send.assert_called_once_with(
            bytearray(2) + bin_message + _SEPARATOR)
예제 #6
0
    def test_sync_to_packet(self, mocked_sys_action, mocked_cows):
        """ Tests that we can successfully synchronize to the packet boundary when
    it requires multiple tries. """
        com, mocked_socket = self.__make_serial()

        # Fake the cows unstuffing so we get a valid message.
        message = test_pb2.TestMessage()
        bin_message = message.SerializeToString()
        mocked_sys_action.return_value = message
        fake_cows = self.FakeCowsUnstuff(bin_message)
        mocked_cows.side_effect = fake_cows

        fake_message = self.__fake_message(len(bin_message))

        # Mock the read function so it looks like finding the separator failed and
        # then succeeded. The final 2 calls are just dummy separators so that the
        # read terminates.
        mocked_socket.recv.side_effect = [
            b'10', b'1', _SEPARATOR[0], _SEPARATOR[1],
            fake_message + _SEPARATOR
        ]

        # If we try to read now, it should first synchronize to the packet.
        got_message = com.read_message()

        # Make sure it tried to call read the proper number of times.
        expected_calls = [
            mock.call.recv(len(_SEPARATOR)),
            mock.call.recv(1),
            mock.call.recv(1),
            mock.call.recv(1),
            mock.call.recv()
        ]
        mocked_socket.assert_has_calls(expected_calls)
        # It should have tried to unstuff the message.
        mocked_cows.assert_called_once()

        # Make sure the messages match.
        self.assertEqual(message, got_message)
예제 #7
0
    def test_read_message_continued(self, mocked_sys_action, mocked_cows):
        """ Tests that we can read a message when we read part of the next one. """
        # Create two messages to read.
        message1 = test_pb2.TestMessage()
        message1.field1 = 42
        message1.field2 = True
        bin_message1 = message1.SerializeToString()

        message2 = test_pb2.TestMessage()
        message2.field1 = 1337
        message2.field2 = True
        bin_message2 = message2.SerializeToString()

        # Configure the fake cows implementation.
        fake_cows = self.FakeCowsUnstuff([bin_message1, bin_message2])
        mocked_cows.side_effect = fake_cows

        mocked_sys_action.return_value = message1

        # Create the SerialCom object.
        com, mocked_socket = self.__make_serial()

        # Make it look like synchronizing to the packet boundary worked. It will
        # attempt to read the first byte of the message first, and then it will read
        # the rest. In this case, it will get part of the second message as well.
        fake_message1 = self.__fake_message(len(bin_message1))
        fake_message2 = self.__fake_message(len(bin_message2))
        mocked_socket.recv.side_effect = [
            _SEPARATOR, fake_message1 + fake_message2[0]
        ]

        # Try to read the first message.
        got_message1 = com.read_message()

        # The first call to read() should have been for the initial separator. The
        # second call should have been for the first message, ending separator, and
        # first byte of the second message.
        expected_calls = [mock.call.recv(len(_SEPARATOR)), mock.call.recv()]
        mocked_socket.assert_has_calls(expected_calls)
        mocked_socket.recv.reset_mock()
        # It should have tried to unstuff it.
        mocked_cows.assert_called_once()
        mocked_cows.reset_mock()

        # Make sure the message matches.
        self.assertEqual(message1, got_message1)

        # When we read the next message, it will read the entire reset of the
        # message including the ending separator.
        mocked_socket.recv.side_effect = [fake_message2[1:]]

        # Try to read the second message.
        got_message2 = com.read_message()

        # It should have made one call to recv() which should have gotten the end of
        # the second message plus the ending separator.
        mocked_socket.recv.assert_called_once_with()
        # It should have tried to unstuff it.
        mocked_cows.assert_called_once()

        # Make sure the message matches.
        self.assertEqual(message2, got_message2)