Signal-iOS/SignalServiceKit/tests/Messages/DeleteForMe/DeleteForMeOutgoingSyncMessageManagerTest.swift

133 lines
4.8 KiB
Swift

//
// Copyright 2024 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
@testable import SignalServiceKit
import XCTest
final class DeleteForMeOutgoingSyncMessageManagerTest: XCTestCase {
private var mockAddressableMessageFinder: MockDeleteForMeAddressableMessageFinder!
private var mockSyncMessageSender: MockSyncMessageSender!
private var mockRecipientDatabaseTable: MockRecipientDatabaseTable!
private var mockThreadStore: MockThreadStore!
private var mockTSAccountManager: MockTSAccountManager!
private var outgoingSyncMessageManager: DeleteForMeOutgoingSyncMessageManagerImpl!
override func setUp() {
mockAddressableMessageFinder = MockDeleteForMeAddressableMessageFinder()
mockSyncMessageSender = MockSyncMessageSender()
mockRecipientDatabaseTable = MockRecipientDatabaseTable()
mockThreadStore = MockThreadStore()
mockTSAccountManager = MockTSAccountManager()
outgoingSyncMessageManager = DeleteForMeOutgoingSyncMessageManagerImpl(
addressableMessageFinder: mockAddressableMessageFinder,
deleteForMeSyncMessageSettingsStore: MockDeleteForMeSyncMessageSettingsStore(),
recipientDatabaseTable: mockRecipientDatabaseTable,
syncMessageSender: mockSyncMessageSender,
threadStore: mockThreadStore,
tsAccountManager: mockTSAccountManager
)
}
func testBatchedInteractionDeletes() {
let thread = TSContactThread(contactAddress: .isolatedRandomForTesting())
let messagesToDelete = (0..<1501).map { _ -> TSOutgoingMessage in
return TSOutgoingMessage(uniqueId: .uniqueId(), thread: thread)
}
/// These should be ignored by the sync message sender, since they are
/// not addressable.
let interactionsToDelete = (0..<10).map { _ -> TSInteraction in
return TSInteraction(uniqueId: .uniqueId(), thread: thread)
}
var expectedInteractionBatches: [Int] = [500, 500, 500, 1]
mockSyncMessageSender.sendSyncMessageMock = { contents in
guard let expectedBatchSize = expectedInteractionBatches.popFirst() else {
XCTFail("Unexpected batch!")
return
}
XCTAssertEqual(contents.messageDeletes.count, 1)
XCTAssertEqual(contents.messageDeletes.first!.addressableMessages.count, expectedBatchSize)
}
MockDB().write { tx in
outgoingSyncMessageManager.send(
deletedInteractions: messagesToDelete + interactionsToDelete,
thread: thread,
tx: tx
)
}
XCTAssertTrue(expectedInteractionBatches.isEmpty)
}
func testBatchedThreadDeletes() {
let threadsToDelete = (0..<301).map { _ -> TSContactThread in
return TSContactThread(contactAddress: .isolatedRandomForTesting())
}
var expectedThreadBatches: [Int] = [100, 100, 100, 1]
mockSyncMessageSender.sendSyncMessageMock = { contents in
guard let expectedBatchSize = expectedThreadBatches.popFirst() else {
XCTFail("Unexpected batch!")
return
}
XCTAssertEqual(contents.localOnlyConversationDelete.count, expectedBatchSize)
}
MockDB().write { tx in
/// These should all be local-only deletes, since the threads have
/// no messages (the `MockDeleteForMeAddressableMessageFinder` will
/// return `[]` for all threads, at the time of writing).
let deletionContexts: [DeleteForMeSyncMessage.Outgoing.ThreadDeletionContext] = threadsToDelete.map { thread in
outgoingSyncMessageManager.buildThreadDeletionContext(
thread: thread,
isFullDelete: true,
tx: tx
)!
}
outgoingSyncMessageManager.send(
threadDeletionContexts: deletionContexts,
tx: tx
)
}
XCTAssertTrue(expectedThreadBatches.isEmpty)
}
}
private extension String {
static func uniqueId() -> String {
return UUID().uuidString
}
}
// MARK: - Mocks
private final class MockDeleteForMeSyncMessageSettingsStore: DeleteForMeSyncMessageSettingsStore {
func isSendingEnabled(tx: any DBReadTransaction) -> Bool {
return true
}
func enableSending(tx: any DBWriteTransaction) {
owsFail("Not implemented!")
}
}
private final class MockSyncMessageSender: DeleteForMeOutgoingSyncMessageManagerImpl.Shims.SyncMessageSender {
var sendSyncMessageMock: ((
_ contents: DeleteForMeOutgoingSyncMessage.Contents
) -> Void)!
func sendSyncMessage(contents: DeleteForMeOutgoingSyncMessage.Contents, localThread: TSContactThread, tx: any DBWriteTransaction) {
sendSyncMessageMock(contents)
}
}