def test_finalize_notifies_for_already_stored_message_without_upload(self): info = LongMessageStatusInfo(LongMessageStatus.READY, b'\x01\x23\x45', 123) data = b'foobar' storage = Mock() storage.read_status = Mock(return_value=info) storage.set_long_message = Mock() storage.get_long_message = Mock(return_value=data) mock_callback = Mock() handler = LongMessageHandler(storage) handler.on_message_updated(mock_callback) for mt in self.known_message_types: mock_callback.reset_mock() with self.subTest(mt=mt): handler.select_long_message_type(mt) handler.finalize_message() self.assertTrue(mock_callback.called) self.assertEqual(0, storage.set_long_message.call_count) self.assertEqual(mt, mock_callback.call_args.args[0].message_type) self.assertEqual('012345', mock_callback.call_args.args[0].md5)
def test_upload_is_only_valid_if_chunk_count_matches_expected(self): storage = LongMessageStorage(MemoryStorage(), MemoryStorage()) chunks = [b'12345', b'1234568', b'98765432'] checksum = hashlib.md5() for chunk in chunks: checksum.update(chunk) expected_md5 = checksum.hexdigest() handler = LongMessageHandler(storage) handler.select_long_message_type(LongMessageType.FIRMWARE_DATA) expectations = ((len(chunks), LongMessageStatus.READY), (0, LongMessageStatus.READY), (len(chunks) - 1, LongMessageStatus.VALIDATION_ERROR), (len(chunks) + 1, LongMessageStatus.VALIDATION_ERROR)) for length, expected_status in expectations: handler.init_transfer(expected_md5, length) for chunk in chunks: handler.upload_message(chunk) handler.finalize_message() status = handler.read_status() self.assertEqual(expected_status, status.status)
def test_finalize_validates_and_stores_uploaded_message(self, mock_hash): storage = Mock() storage.read_status = Mock(return_value=LongMessageStatusInfo( LongMessageStatus.READY, 'new_md5', 123)) storage.set_long_message = Mock() mock_hash.return_value = mock_hash mock_hash.update = Mock() mock_hash.hexdigest = Mock() handler = LongMessageHandler(storage) # message invalid for mt in self.known_message_types: mock_hash.reset_mock() mock_hash.hexdigest.return_value = 'invalid_md5' with self.subTest(mt='invalid ({})'.format(mt)): handler.select_long_message_type(mt) handler.init_transfer('new_md5') self.assertEqual(1, mock_hash.call_count) handler.upload_message(b'12345') self.assertEqual(1, mock_hash.update.call_count) handler.upload_message(b'67890') self.assertEqual(2, mock_hash.update.call_count) handler.finalize_message() self.assertEqual(1, mock_hash.hexdigest.call_count) status = handler.read_status() self.assertEqual(LongMessageStatus.VALIDATION_ERROR, status.status) self.assertEqual(0, storage.set_long_message.call_count) # message valid for mt in self.known_message_types: mock_hash.reset_mock() storage.reset_mock() mock_hash.hexdigest.return_value = 'new_md5' with self.subTest(mt='valid ({})'.format(mt)): handler.select_long_message_type(mt) handler.init_transfer('new_md5') self.assertEqual(1, mock_hash.call_count) handler.upload_message(b'12345') self.assertEqual(1, mock_hash.update.call_count) handler.upload_message(b'67890') self.assertEqual(2, mock_hash.update.call_count) handler.finalize_message() self.assertEqual(1, mock_hash.hexdigest.call_count) self.assertEqual(1, storage.set_long_message.call_count) status = handler.read_status() self.assertEqual(1, storage.read_status.call_count) self.assertEqual(LongMessageStatus.READY, status.status)
def test_finalize_notifies_for_already_stored_message_without_upload(self): storage = Mock() storage.read_status = Mock(return_value=LongMessageStatusInfo( LongMessageStatus.READY, 'new_md5', 123)) storage.set_long_message = Mock() mock_callback = Mock() handler = LongMessageHandler(storage) handler.on_message_updated(mock_callback) for mt in self.known_message_types: mock_callback.reset_mock() with self.subTest(mt=mt): handler.select_long_message_type(mt) handler.finalize_message() self.assertEqual(1, mock_callback.call_count) self.assertEqual(0, storage.set_long_message.call_count)
def test_finalize_notifies_about_valid_message(self, mock_hash): storage = Mock() storage.read_status = Mock(return_value=LongMessageStatusInfo( LongMessageStatus.READY, 'new_md5', 123)) mock_hash.return_value = mock_hash mock_hash.update = Mock() mock_hash.hexdigest = Mock() mock_callback = Mock() handler = LongMessageHandler(storage) handler.on_message_updated(mock_callback) # message invalid for mt in self.known_message_types: mock_hash.reset_mock() mock_hash.hexdigest.return_value = 'invalid_md5' with self.subTest(mt='invalid ({})'.format(mt)): handler.select_long_message_type(mt) handler.init_transfer('new_md5') handler.upload_message(b'12345') handler.finalize_message() self.assertEqual(0, mock_callback.call_count) # message valid for mt in self.known_message_types: mock_callback.reset_mock() mock_hash.hexdigest.return_value = 'new_md5' with self.subTest(mt='valid ({})'.format(mt)): handler.select_long_message_type(mt) handler.init_transfer('new_md5') handler.upload_message(b'12345') handler.finalize_message() self.assertEqual(1, mock_callback.call_count)