def test_recv_message_separator_time(self): """ Verify that message_separator_time works correctly. Receive a message over time t, where t > message_separator_time, and each part of the message is delayed by t' < message_separator_time. Given: A SerialConnection using MockSerial, and: timeout set to 60ms. and: message_separator_time set 20ms When: User calls SerialConnection.recv(max_bytes=60). and: MockSerial.recv set to return increasing bytes. and: MockSerial.recv set to delay very briefly on each call (0.001ms (1 microsecond)). Then: SerialConnection.recv calls MockSerial.recv multiple times (more than 2). and: SerialConnection.recv returns data with multiple bytes (more than 2). """ # Given self.uut = SerialConnection(timeout=.060, message_separator_time=.020) self.uut._connection = self.mock # When self.mock.recv_return_queue = [b'1'] * 60 self.mock.recv_wait_times = [0.000001] * 60 data = self.uut.recv(max_bytes=60) # Then self.assertGreater(len(self.mock.recv_max_bytes_lengths), 2) self.assertGreater(len(data), 2)
def test_recv_message_separator_time_2(self): """ Verify that message_separator_time works correctly. Receive a message that times out with message_separator_time, but which would not time out with only a timeout. Given: A SerialConnection using MockSerial, and: timeout set to 60ms. and: message_separator_time set 20ms When: User calls SerialConnection.recv(60). and: MockSerial.recv set to return 1 byte, then 1 byte, then 58 bytes. and: MockSerial.recv set to delay 1ms, then 40ms, then 1ms. Then: SerialConnection.recv calls MockSerial.recv twice. and: SerialConnection.recv returns only the first two bytes. """ # Given self.uut = SerialConnection(timeout=.060, message_separator_time=.020) self.uut._connection = self.mock # When self.mock.recv_return_queue = [b'1', b'2', b'3' * 58] self.mock.recv_wait_times = [.001, .040, .001] data = self.uut.recv(max_bytes=60) # Then self.assertEqual(len(self.mock.recv_max_bytes_lengths), 2) self.assertEqual(data, b'12')
def test_recv_timeout(self): """ Verify that recv() returns partial messages after the timeout expires. Given: A SerialConnection using MockSerial, with timeout set to a smallish value. When: User calls SerialConnection.recv(n) several times with different values of n. and: MockSerial.recv set to return a single message, then repeatedly return nothing. Then: SerialConnection.recv calls MockSerial.recv at least once. and: SerialConnection.recv returns the MockSerial.recv() return value after the timeout. Note: Timeout functionality is tested, but not the precise timing. """ self.uut = SerialConnection(timeout=.001) # 1ms self.uut._connection = self.mock # n == 1 self.mock.recv_return_nothing_by_default = True self.mock.recv_return_queue = [b''] data = self.uut.recv(max_bytes=1) self.assertGreaterEqual(len(self.mock.recv_max_bytes_lengths), 1) self.assertEqual(data, b'') # n == 2 self.mock.recv_return_nothing_by_default = True self.mock.recv_return_queue = [b'1'] data = self.uut.recv(max_bytes=2) self.assertGreaterEqual(len(self.mock.recv_max_bytes_lengths), 1) self.assertEqual(data, b'1') # n == 3, len(data) == 1 self.mock.recv_return_nothing_by_default = True self.mock.recv_return_queue = [b'1'] data = self.uut.recv(max_bytes=5) self.assertGreaterEqual(len(self.mock.recv_max_bytes_lengths), 1) self.assertEqual(data, b'1') # n == 3, len(data) == 2 self.mock.recv_return_nothing_by_default = True self.mock.recv_return_queue = [b'12'] data = self.uut.recv(max_bytes=3) self.assertGreaterEqual(len(self.mock.recv_max_bytes_lengths), 1) self.assertEqual(data, b'12')
def setUp(self): self.mock = MockSerial() self.uut = SerialConnection() self.uut._connection = self.mock
def test_recv_message_content_checker(self): """ Verify that content_checker is used correctly. The content_checker indicates how much of a message is valid, if any. Verify behavior when the content_checker consumes a part of the buffer, the full buffer, and then part of it again. Given: A SerialConnection using MockSerial, and: timeout set to 100ms. and: message_separator_time set 20ms and: content_checker set to a function that returns 0, 3, 0, 5, 0, 3 When: User calls SerialConnection.recv(100) 3 times. and: MockSerial.recv set to return 2 bytes repeatedly. Then: SerialConnection.recv calls MockSerial.recv 6 times. and: SerialConnection.recv returns only the first 3 bytes, then the next 5 bytes, then the next 3. """ # Given # PyUnusedLocal suppression: args/kwargs make the method callable by SerialConnection, but are not used. # noinspection PyUnusedLocal def test_checker(*args, **kwargs): """ :param args: Ignored. Makes method callable with arguments. :param kwargs: Ignored. Makes method callable with arguments. :return: 0, 3, 0, 5, 0, 3, 0, 0... """ if not hasattr(test_checker, "counter"): test_checker.counter = 0 test_checker.counter += 1 if test_checker.counter == 2: return 3 elif test_checker.counter == 4: return 5 elif test_checker.counter == 6: return 3 else: return 0 self.uut = SerialConnection(timeout=.100, message_separator_time=.020, content_checker=test_checker) self.uut._connection = self.mock # When self.mock.recv_return_queue = [ b'12', b'34', b'56', b'78', b'9A', b'BC' ] data = self.uut.recv(max_bytes=100) self.assertEqual(len(self.mock.recv_max_bytes_lengths), 2) self.assertEqual(data, b'123') data = self.uut.recv(max_bytes=100) self.assertEqual(len(self.mock.recv_max_bytes_lengths), 4) self.assertEqual(data, b'45678') data = self.uut.recv(max_bytes=100) self.assertEqual(len(self.mock.recv_max_bytes_lengths), 6) self.assertEqual(data, b'9AB')