def test_stream_messages_archiving(self) -> None: msg_ids = [] for i in range(0, 3): msg_ids.append(self.send_stream_message(self.sender, "Verona")) (user_msgs_ids_before, all_msgs_ids_before) = self._check_messages_before_archiving(msg_ids) move_messages_to_archive(message_ids=msg_ids) self._check_messages_after_archiving(msg_ids, user_msgs_ids_before, all_msgs_ids_before)
def test_personal_messages_archiving(self) -> None: msg_ids = [] for i in range(0, 3): msg_ids.append(self.send_personal_message(self.sender, self.recipient)) (user_msgs_ids_before, all_msgs_ids_before) = self._check_messages_before_archiving(msg_ids) move_messages_to_archive(message_ids=msg_ids) self._check_messages_after_archiving(msg_ids, user_msgs_ids_before, all_msgs_ids_before)
def test_archiving_messages_with_attachment(self) -> None: self._create_attachments() body1 = """Some files here ...[zulip.txt]( http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/zulip.txt) http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/temp_file.py .... Some more.... http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/abc.py """ body2 = """Some files here http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/zulip.txt ... http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/hello.txt .... http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/new.py .... """ msg_ids = [] msg_ids.append(self.send_personal_message(self.sender, self.recipient, body1)) msg_ids.append(self.send_personal_message(self.sender, self.recipient, body2)) attachment_id_to_message_ids = {} attachments = Attachment.objects.filter(messages__id__in=msg_ids) for attachment in attachments: attachment_id_to_message_ids[attachment.id] = {message.id for message in attachment.messages.all()} (user_msgs_ids_before, all_msgs_ids_before) = self._check_messages_before_archiving(msg_ids) attachments_ids_before = list(attachments.order_by("id").values_list("id", flat=True)) self.assertEqual(ArchivedAttachment.objects.count(), 0) move_messages_to_archive(message_ids=msg_ids) self._check_messages_after_archiving(msg_ids, user_msgs_ids_before, all_msgs_ids_before) self.assertEqual(Attachment.objects.count(), 0) archived_attachments = ArchivedAttachment.objects.filter(messages__id__in=msg_ids) arc_attachments_ids_after = list(archived_attachments.order_by("id").values_list("id", flat=True)) self.assertEqual(attachments_ids_before, arc_attachments_ids_after) for attachment in archived_attachments: self.assertEqual(attachment_id_to_message_ids[attachment.id], {message.id for message in attachment.messages.all()})
def test_archiving_message_with_shared_attachment(self) -> None: # Check do not removing attachments which is used in other messages. self._create_attachments() body = """Some files here ...[zulip.txt]( http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/zulip.txt) http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/temp_file.py .... Some more.... http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/abc.py ... http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/new.py .... http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/hello.txt .... """ msg_id = self.send_personal_message(self.sender, self.recipient, body) # Simulate a reply with the same contents. msg_id_shared_attachments = self.send_personal_message( from_email=self.recipient, to_email=self.sender, content=body, ) (user_msgs_ids_before, all_msgs_ids_before) = self._check_messages_before_archiving([msg_id]) attachments_ids_before = list(Attachment.objects.filter( messages__id=msg_id).order_by("id").values_list("id", flat=True)) self.assertEqual(ArchivedAttachment.objects.count(), 0) move_messages_to_archive(message_ids=[msg_id]) self._check_messages_after_archiving([msg_id], user_msgs_ids_before, all_msgs_ids_before) self.assertEqual(Attachment.objects.count(), 5) arc_attachments_ids_after = list(ArchivedAttachment.objects.filter( messages__id=msg_id).order_by("id").values_list("id", flat=True)) self.assertEqual(attachments_ids_before, arc_attachments_ids_after) move_messages_to_archive(message_ids=[msg_id_shared_attachments]) self.assertEqual(Attachment.objects.count(), 0)
def test_archiving_messages_second_time(self) -> None: msg_ids = [] for i in range(0, 3): msg_ids.append(self.send_stream_message(self.sender, "Verona")) (user_msgs_ids_before, all_msgs_ids_before) = self._check_messages_before_archiving(msg_ids) move_messages_to_archive(message_ids=msg_ids) self._check_messages_after_archiving(msg_ids, user_msgs_ids_before, all_msgs_ids_before) with self.assertRaises(Message.DoesNotExist): move_messages_to_archive(message_ids=msg_ids)
def test_archiving_messages_second_time(self) -> None: msg_ids = [ self.send_stream_message(self.sender, "Verona") for i in range(0, 3) ] usermsg_ids = self._get_usermessage_ids(msg_ids) self._assert_archive_empty() move_messages_to_archive(message_ids=msg_ids) self._verify_archive_data(msg_ids, usermsg_ids) with self.assertRaises(Message.DoesNotExist): move_messages_to_archive(message_ids=msg_ids)
def test_stream_messages_archiving(self) -> None: msg_ids = [ self.send_stream_message(self.sender, "Verona") for i in range(0, 3) ] usermsg_ids = self._get_usermessage_ids(msg_ids) self._assert_archive_empty() move_messages_to_archive(message_ids=msg_ids) self._verify_archive_data(msg_ids, usermsg_ids) restore_all_data_from_archive() self._verify_restored_data(msg_ids, usermsg_ids)
def test_move_messages_to_archive_with_realm_argument(self) -> None: realm = get_realm("zulip") msg_ids = [ self.send_personal_message(self.sender, self.recipient) for i in range(0, 3) ] usermsg_ids = self._get_usermessage_ids(msg_ids) self._assert_archive_empty() move_messages_to_archive(message_ids=msg_ids, realm=realm) self._verify_archive_data(msg_ids, usermsg_ids) archive_transaction = ArchiveTransaction.objects.last() self.assertEqual(archive_transaction.realm, realm)
def test_restore_retention_policy_deletions_for_stream(self) -> None: cordelia = self.example_user("cordelia") hamlet = self.example_user("hamlet") realm = get_realm("zulip") stream_name = "Verona" stream = get_stream(stream_name, realm) message_ids_to_archive_manually = [ self.send_stream_message(cordelia, stream_name, str(i)) for i in range(0, 2) ] usermessage_ids_to_archive_manually = self._get_usermessage_ids( message_ids_to_archive_manually) message_ids_to_archive_by_policy = [ self.send_stream_message(hamlet, stream_name, str(i)) for i in range(0, 2) ] usermessage_ids_to_archive_by_policy = self._get_usermessage_ids( message_ids_to_archive_by_policy) expected_archived_message_ids = (message_ids_to_archive_manually + message_ids_to_archive_by_policy) expected_archived_usermessage_ids = ( usermessage_ids_to_archive_manually + usermessage_ids_to_archive_by_policy) self._set_stream_message_retention_value(stream, 5) self._change_messages_date_sent(message_ids_to_archive_by_policy, timezone_now() - timedelta(days=6)) move_messages_to_archive(message_ids_to_archive_manually) archive_messages() self._verify_archive_data(expected_archived_message_ids, expected_archived_usermessage_ids) restore_retention_policy_deletions_for_stream(stream) # Verify that we restore the stream messages that were archived due to retention policy, # but not the ones manually deleted. self.assert_length( Message.objects.filter(id__in=message_ids_to_archive_by_policy), len(message_ids_to_archive_by_policy), ) self.assertFalse( Message.objects.filter(id__in=message_ids_to_archive_manually))
def test_archiving_messages_with_attachment(self) -> None: self._create_attachments() body1 = """Some files here ...[zulip.txt]( http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/zulip.txt) http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/temp_file.py .... Some more.... http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/abc.py """ body2 = """Some files here http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/zulip.txt ... http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/hello.txt .... http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/new.py .... """ msg_ids = [ self.send_personal_message(self.sender, self.recipient, body1), self.send_personal_message(self.sender, self.recipient, body2) ] attachment_id_to_message_ids = {} # type: Dict[int, List[int]] attachment_ids = list( Attachment.objects.filter(messages__id__in=msg_ids).values_list( "id", flat=True)) for attachment_id in attachment_ids: attachment_id_to_message_ids[attachment_id] = list( Message.objects.filter( attachment__id=attachment_id).values_list("id", flat=True)) usermsg_ids = self._get_usermsg_ids(msg_ids) self._assert_archive_empty() move_messages_to_archive(message_ids=msg_ids) self._check_messages_after_archiving(msg_ids, usermsg_ids) self.assertFalse(Attachment.objects.exists()) archived_attachment_ids = list( ArchivedAttachment.objects.filter( messages__id__in=msg_ids).values_list("id", flat=True)) self.assertEqual(set(attachment_ids), set(archived_attachment_ids)) for attachment_id in archived_attachment_ids: self.assertEqual( set(attachment_id_to_message_ids[attachment_id]), set( ArchivedMessage.objects.filter( archivedattachment__id=attachment_id).values_list( "id", flat=True)))
def test_archiving_messages_with_attachment(self) -> None: self._create_attachments() body1 = """Some files here ...[zulip.txt]( http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/zulip.txt) http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/temp_file.py .... Some more.... http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/abc.py """ body2 = """Some files here http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/zulip.txt ... http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/hello.txt .... http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/new.py .... """ msg_ids = [] msg_ids.append( self.send_personal_message(self.sender, self.recipient, body1)) msg_ids.append( self.send_personal_message(self.sender, self.recipient, body2)) attachment_id_to_message_ids = {} attachments = Attachment.objects.filter(messages__id__in=msg_ids) for attachment in attachments: attachment_id_to_message_ids[attachment.id] = { message.id for message in attachment.messages.all() } (user_msgs_ids_before, all_msgs_ids_before) = self._check_messages_before_archiving(msg_ids) attachments_ids_before = list( attachments.order_by("id").values_list("id", flat=True)) self.assertEqual(ArchivedAttachment.objects.count(), 0) move_messages_to_archive(message_ids=msg_ids) self._check_messages_after_archiving(msg_ids, user_msgs_ids_before, all_msgs_ids_before) self.assertEqual(Attachment.objects.count(), 0) archived_attachments = ArchivedAttachment.objects.filter( messages__id__in=msg_ids) arc_attachments_ids_after = list( archived_attachments.order_by("id").values_list("id", flat=True)) self.assertEqual(attachments_ids_before, arc_attachments_ids_after) for attachment in archived_attachments: self.assertEqual( attachment_id_to_message_ids[attachment.id], {message.id for message in attachment.messages.all()})
def test_archiving_message_with_submessages(self) -> None: msg_id = self.send_stream_message(self.sender, "Verona") cordelia = self.example_user("cordelia") hamlet = self.example_user("hamlet") do_add_submessage( realm=get_realm("zulip"), sender_id=cordelia.id, message_id=msg_id, msg_type="whatever", content='{"name": "alice", "salary": 20}', ) do_add_submessage( realm=get_realm("zulip"), sender_id=hamlet.id, message_id=msg_id, msg_type="whatever", content='{"name": "john", "salary": 30}', ) submessage_ids = list( SubMessage.objects.filter(message_id=msg_id).values_list( "id", flat=True), ) self.assertEqual( SubMessage.objects.filter(id__in=submessage_ids).count(), 2) move_messages_to_archive(message_ids=[msg_id]) self.assertEqual( set( ArchivedSubMessage.objects.filter( message_id=msg_id).values_list("id", flat=True)), set(submessage_ids), ) self.assertEqual( SubMessage.objects.filter(id__in=submessage_ids).count(), 0) restore_all_data_from_archive() self.assertEqual( set( SubMessage.objects.filter(id__in=submessage_ids).values_list( "id", flat=True)), set(submessage_ids), )
def do_delete_messages(realm: Realm, messages: Iterable[Message]) -> None: # messages in delete_message event belong to the same topic # or is a single private message, as any other behaviour is not possible with # the current callers to this method. messages = list(messages) message_ids = [message.id for message in messages] if not message_ids: return event: DeleteMessagesEvent = { "type": "delete_message", "message_ids": message_ids, } sample_message = messages[0] message_type = "stream" users_to_notify = [] if not sample_message.is_stream_message(): assert len(messages) == 1 message_type = "private" ums = UserMessage.objects.filter(message_id__in=message_ids) users_to_notify = [um.user_profile_id for um in ums] archiving_chunk_size = retention.MESSAGE_BATCH_SIZE if message_type == "stream": stream_id = sample_message.recipient.type_id event["stream_id"] = stream_id event["topic"] = sample_message.topic_name() subscriptions = get_active_subscriptions_for_stream_id( stream_id, include_deactivated_users=False) # We exclude long-term idle users, since they by definition have no active clients. subscriptions = subscriptions.exclude( user_profile__long_term_idle=True) users_to_notify = list( subscriptions.values_list("user_profile_id", flat=True)) archiving_chunk_size = retention.STREAM_MESSAGE_BATCH_SIZE move_messages_to_archive(message_ids, realm=realm, chunk_size=archiving_chunk_size) event["message_type"] = message_type transaction.on_commit(lambda: send_event(realm, event, users_to_notify))
def test_archiving_message_with_reactions(self) -> None: msg_id = self.send_stream_message(self.sender, "Verona") self.post_zulip_reaction(msg_id, 'hamlet') self.post_zulip_reaction(msg_id, 'cordelia') reaction_ids = list( Reaction.objects.filter(message_id=msg_id).values_list('id', flat=True)) self.assertEqual( Reaction.objects.filter(id__in=reaction_ids).count(), 2) move_messages_to_archive(message_ids=[msg_id]) self.assertEqual( set( ArchivedReaction.objects.filter(message_id=msg_id).values_list( "id", flat=True)), set(reaction_ids)) self.assertEqual( Reaction.objects.filter(id__in=reaction_ids).count(), 0)
def test_archiving_message_with_shared_attachment(self) -> None: # Make sure that attachments still in use in other messages don't get deleted: self._create_attachments() realm_id = get_realm("zulip").id host = get_realm("zulip").host body = """Some files here ...[zulip.txt]( http://{host}/user_uploads/{id}/31/4CBjtTLYZhk66pZrF8hnYGwc/zulip.txt) http://{host}/user_uploads/{id}/31/4CBjtTLYZhk66pZrF8hnYGwc/temp_file.py .... Some more.... http://{host}/user_uploads/{id}/31/4CBjtTLYZhk66pZrF8hnYGwc/abc.py ... http://{host}/user_uploads/{id}/31/4CBjtTLYZhk66pZrF8hnYGwc/new.py .... http://{host}/user_uploads/{id}/31/4CBjtTLYZhk66pZrF8hnYGwc/hello.txt .... """.format(id=realm_id, host=host) msg_id = self.send_personal_message(self.sender, self.recipient, body) # Simulate a reply with the same contents. reply_msg_id = self.send_personal_message( from_user=self.recipient, to_user=self.sender, content=body, ) usermsg_ids = self._get_usermessage_ids([msg_id]) attachment_ids = list( Attachment.objects.filter(messages__id=msg_id).values_list( "id", flat=True), ) self._assert_archive_empty() # Archive one of the messages: move_messages_to_archive(message_ids=[msg_id]) self._verify_archive_data([msg_id], usermsg_ids) # Attachments shouldn't have been deleted, as the second message links to them: self.assertEqual(Attachment.objects.count(), 5) self.assertEqual( set( ArchivedAttachment.objects.filter( messages__id=msg_id).values_list("id", flat=True)), set(attachment_ids), ) # Restore the first message: restore_all_data_from_archive() # Archive the second: move_messages_to_archive(message_ids=[reply_msg_id]) # The restored messages links to the Attachments, so they shouldn't be deleted: self.assertEqual(Attachment.objects.count(), 5) # Archive the first message again: move_messages_to_archive(message_ids=[msg_id]) # Now the attachment should have been deleted: self.assertEqual(Attachment.objects.count(), 0) # Restore everything: restore_all_data_from_archive() self.assertEqual( set( Attachment.objects.filter(messages__id=msg_id).values_list( "id", flat=True)), set(attachment_ids), )
def test_archiving_message_with_shared_attachment(self) -> None: # Make sure that attachments still in use in other messages don't get deleted: self._create_attachments() body = """Some files here ...[zulip.txt]( http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/zulip.txt) http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/temp_file.py .... Some more.... http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/abc.py ... http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/new.py .... http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/hello.txt .... """ msg_id = self.send_personal_message(self.sender, self.recipient, body) # Simulate a reply with the same contents. reply_msg_id = self.send_personal_message( from_email=self.recipient, to_email=self.sender, content=body, ) usermsg_ids = self._get_usermsg_ids([msg_id]) attachment_ids = list( Attachment.objects.filter(messages__id=msg_id).values_list( "id", flat=True)) self._assert_archive_empty() move_messages_to_archive(message_ids=[msg_id]) self._check_messages_after_archiving([msg_id], usermsg_ids) self.assertEqual(Attachment.objects.count(), 5) self.assertEqual( set( ArchivedAttachment.objects.filter( messages__id=msg_id).values_list("id", flat=True)), set(attachment_ids)) move_messages_to_archive(message_ids=[reply_msg_id]) # Now the attachment should have been deleted: self.assertEqual(Attachment.objects.count(), 0)
def test_archiving_messages_multiple_realms(self) -> None: """ Verifies that move_messages_to_archive works correctly if called on messages in multiple realms. """ iago = self.example_user("iago") othello = self.example_user("othello") cordelia = self.lear_user("cordelia") king = self.lear_user("king") zulip_msg_ids = [self.send_personal_message(iago, othello) for i in range(0, 3)] leary_msg_ids = [self.send_personal_message(cordelia, king) for i in range(0, 3)] msg_ids = zulip_msg_ids + leary_msg_ids usermsg_ids = self._get_usermessage_ids(msg_ids) self._assert_archive_empty() move_messages_to_archive(message_ids=msg_ids) self._verify_archive_data(msg_ids, usermsg_ids) restore_all_data_from_archive() self._verify_restored_data(msg_ids, usermsg_ids)
def test_archiving_message_with_shared_attachment(self) -> None: # Check do not removing attachments which is used in other messages. self._create_attachments() body = """Some files here ...[zulip.txt]( http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/zulip.txt) http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/temp_file.py .... Some more.... http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/abc.py ... http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/new.py .... http://localhost:9991/user_uploads/1/31/4CBjtTLYZhk66pZrF8hnYGwc/hello.txt .... """ msg_id = self.send_personal_message(self.sender, self.recipient, body) # Simulate a reply with the same contents. msg_id_shared_attachments = self.send_personal_message( from_email=self.recipient, to_email=self.sender, content=body, ) (user_msgs_ids_before, all_msgs_ids_before) = self._check_messages_before_archiving([msg_id]) attachments_ids_before = list( Attachment.objects.filter( messages__id=msg_id).order_by("id").values_list("id", flat=True)) self.assertEqual(ArchivedAttachment.objects.count(), 0) move_messages_to_archive(message_ids=[msg_id]) self._check_messages_after_archiving([msg_id], user_msgs_ids_before, all_msgs_ids_before) self.assertEqual(Attachment.objects.count(), 5) arc_attachments_ids_after = list( ArchivedAttachment.objects.filter( messages__id=msg_id).order_by("id").values_list("id", flat=True)) self.assertEqual(attachments_ids_before, arc_attachments_ids_after) move_messages_to_archive(message_ids=[msg_id_shared_attachments]) self.assertEqual(Attachment.objects.count(), 0)
def test_old_event_format_processed_correctly(self) -> None: """ do_delete_messages used to send events with users in dict format {"id": <int>}. We have a block in process_notification to deal with that old format, that should be deleted in a later release. This test is meant to ensure correctness of that block. """ realm = get_realm("zulip") cordelia = self.example_user("cordelia") hamlet = self.example_user("hamlet") message_id = self.send_personal_message(cordelia, hamlet) message = Message.objects.get(id=message_id) event = { "type": "delete_message", "sender": message.sender.email, "sender_id": message.sender_id, "message_id": message.id, "message_type": "private", "recipient_id": message.recipient_id, } move_messages_to_archive([message_id]) # We only send the event to see no exception is thrown - as it would be if the block # in process_notification to handle this old format of "users to notify" wasn't correct. send_event(realm, event, [{"id": cordelia.id}, {"id": hamlet.id}])
def test_archiving_messages_with_attachment(self) -> None: self._create_attachments() realm_id = get_realm("zulip").id host = get_realm("zulip").host body1 = """Some files here ...[zulip.txt]( http://{host}/user_uploads/{id}/31/4CBjtTLYZhk66pZrF8hnYGwc/zulip.txt) http://{host}/user_uploads/{id}/31/4CBjtTLYZhk66pZrF8hnYGwc/temp_file.py .... Some more.... http://{host}/user_uploads/{id}/31/4CBjtTLYZhk66pZrF8hnYGwc/abc.py """.format(id=realm_id, host=host) body2 = """Some files here http://{host}/user_uploads/{id}/31/4CBjtTLYZhk66pZrF8hnYGwc/zulip.txt ... http://{host}/user_uploads/{id}/31/4CBjtTLYZhk66pZrF8hnYGwc/hello.txt .... http://{host}/user_uploads/{id}/31/4CBjtTLYZhk66pZrF8hnYGwc/new.py .... """.format(id=realm_id, host=host) msg_ids = [ self.send_personal_message(self.sender, self.recipient, body1), self.send_personal_message(self.sender, self.recipient, body2), ] attachment_id_to_message_ids: Dict[int, List[int]] = {} attachment_ids = list( Attachment.objects.filter(messages__id__in=msg_ids).values_list( "id", flat=True), ) for attachment_id in attachment_ids: attachment_id_to_message_ids[attachment_id] = list( Message.objects.filter( attachment__id=attachment_id).values_list("id", flat=True), ) usermsg_ids = self._get_usermessage_ids(msg_ids) self._assert_archive_empty() move_messages_to_archive(message_ids=msg_ids) self._verify_archive_data(msg_ids, usermsg_ids) self.assertFalse(Attachment.objects.exists()) archived_attachment_ids = list( ArchivedAttachment.objects.filter( messages__id__in=msg_ids).values_list("id", flat=True), ) self.assertEqual(set(attachment_ids), set(archived_attachment_ids)) for attachment_id in archived_attachment_ids: self.assertEqual( set(attachment_id_to_message_ids[attachment_id]), set( ArchivedMessage.objects.filter( archivedattachment__id=attachment_id).values_list( "id", flat=True)), ) restore_all_data_from_archive() self._verify_restored_data(msg_ids, usermsg_ids) restored_attachment_ids = list( Attachment.objects.filter(messages__id__in=msg_ids).values_list( "id", flat=True), ) self.assertEqual(set(attachment_ids), set(restored_attachment_ids)) for attachment_id in restored_attachment_ids: self.assertEqual( set(attachment_id_to_message_ids[attachment_id]), set( Message.objects.filter( attachment__id=attachment_id).values_list("id", flat=True)), )