TM-SGNL-iOS/SignalServiceKit/tests/Calls/CallRecord/IncomingCallLogEventSyncMessageManagerTest.swift
TeleMessage developers dde0620daf initial commit
2025-05-03 12:28:28 -07:00

189 lines
6.3 KiB
Swift

//
// Copyright 2024 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
@testable import SignalServiceKit
import XCTest
final class IncomingCallLogEventSyncMessageManagerTest: XCTestCase {
private typealias CallIdentifiers = IncomingCallLogEventSyncMessageParams.CallIdentifiers
private var mockCallRecordConversationIdAdapter: MockCallRecordSyncMessageConversationIdAdapter!
private var mockDeleteAllCallsJobQueue: MockDeleteAllCallsJobQueue!
private var mockMissedCallManager: MockMissedCallManager!
private var syncMessageManager: IncomingCallLogEventSyncMessageManagerImpl!
override func setUp() {
mockCallRecordConversationIdAdapter = MockCallRecordSyncMessageConversationIdAdapter()
mockDeleteAllCallsJobQueue = MockDeleteAllCallsJobQueue()
mockMissedCallManager = MockMissedCallManager()
syncMessageManager = IncomingCallLogEventSyncMessageManagerImpl(
callRecordConversationIdAdapter: mockCallRecordConversationIdAdapter,
deleteAllCallsJobQueue: mockDeleteAllCallsJobQueue,
missedCallManager: mockMissedCallManager
)
}
private func handle(incomingSyncMessage: IncomingCallLogEventSyncMessageParams) {
InMemoryDB().write { tx in
syncMessageManager.handleIncomingSyncMessage(
incomingSyncMessage: incomingSyncMessage, tx: tx
)
}
}
func testClearingWithFoundAnchor() {
let callId: UInt64 = .maxRandom
let timestamp: UInt64 = .maxRandomInt64Compat
mockCallRecordConversationIdAdapter.mockHydratedCallRecord = .fixture(
callId: callId,
threadRowId: .maxRandom,
callBeganTimestamp: timestamp
)
mockDeleteAllCallsJobQueue.deleteAllCallsMock = { beforeTimestamp in
XCTAssertEqual(beforeTimestamp, timestamp)
}
handle(incomingSyncMessage: IncomingCallLogEventSyncMessageParams(
eventType: .cleared,
anchorCallIdentifiers: CallIdentifiers(
callId: callId,
conversationId: Data()
),
anchorTimestamp: timestamp + 1
))
}
func testClearingWithMissingAnchor() {
let timestamp: UInt64 = .maxRandomInt64Compat
var deleteAttempts = 0
mockDeleteAllCallsJobQueue.deleteAllCallsMock = { beforeTimestamp in
deleteAttempts += 1
XCTAssertEqual(beforeTimestamp, timestamp)
}
handle(incomingSyncMessage: IncomingCallLogEventSyncMessageParams(
eventType: .cleared,
anchorCallIdentifiers: CallIdentifiers(
callId: .maxRandom,
conversationId: Data()
),
anchorTimestamp: timestamp
))
handle(incomingSyncMessage: IncomingCallLogEventSyncMessageParams(
eventType: .cleared,
anchorCallIdentifiers: nil,
anchorTimestamp: timestamp
))
XCTAssertEqual(deleteAttempts, 2)
}
func testMarkAsReadWithFoundAnchor() {
let callId: UInt64 = .maxRandom
let timestamp: UInt64 = .maxRandomInt64Compat
mockCallRecordConversationIdAdapter.mockHydratedCallRecord = .fixture(
callId: callId,
threadRowId: .maxRandom,
callBeganTimestamp: timestamp
)
mockMissedCallManager.markUnreadCallsAsReadMock = { beforeTimestamp in
XCTAssertEqual(beforeTimestamp, timestamp)
}
handle(incomingSyncMessage: IncomingCallLogEventSyncMessageParams(
eventType: .markedAsRead,
anchorCallIdentifiers: CallIdentifiers(
callId: callId,
conversationId: Data()
),
anchorTimestamp: timestamp + 1
))
}
func testMarkAsReadWithMissingAnchor() {
let timestamp: UInt64 = .maxRandomInt64Compat
var markAsReadAttempts = 0
mockMissedCallManager.markUnreadCallsAsReadMock = { beforeTimestamp in
markAsReadAttempts += 1
XCTAssertEqual(beforeTimestamp, timestamp)
}
handle(incomingSyncMessage: IncomingCallLogEventSyncMessageParams(
eventType: .markedAsRead,
anchorCallIdentifiers: CallIdentifiers(
callId: .maxRandom,
conversationId: Data()
),
anchorTimestamp: timestamp
))
handle(incomingSyncMessage: IncomingCallLogEventSyncMessageParams(
eventType: .markedAsRead,
anchorCallIdentifiers: nil,
anchorTimestamp: timestamp
))
XCTAssertEqual(markAsReadAttempts, 2)
}
}
// MARK: - Mocks
private extension CallRecord {
static func fixture(
callId: UInt64,
threadRowId: Int64,
callBeganTimestamp: UInt64
) -> CallRecord {
return CallRecord(
callId: callId,
interactionRowId: 0,
threadRowId: threadRowId,
callType: .groupCall,
callDirection: .incoming,
callStatus: .group(.generic),
callBeganTimestamp: callBeganTimestamp
)
}
}
private class MockMissedCallManager: CallRecordMissedCallManager {
func countUnreadMissedCalls(tx: DBReadTransaction) -> UInt {
owsFail("Not implemented!")
}
func markUnreadCallsInConversationAsRead(beforeCallRecord: CallRecord, sendSyncMessage: Bool, tx: DBWriteTransaction) {
// TODO: implement, because we'll need this when handling incoming sync messages
owsFail("Not implemented!")
}
var markUnreadCallsAsReadMock: ((_ beforeTimestamp: UInt64?) -> Void)!
func markUnreadCallsAsRead(beforeTimestamp: UInt64?, sendSyncMessage: Bool, tx: DBWriteTransaction) {
XCTAssertFalse(sendSyncMessage)
markUnreadCallsAsReadMock(beforeTimestamp)
}
}
private class MockDeleteAllCallsJobQueue: IncomingCallLogEventSyncMessageManagerImpl.Shims.DeleteAllCallsJobQueue {
var deleteAllCallsMock: ((_ beforeTimestamp: UInt64) -> Void)!
func deleteAllCalls(before: CallRecordDeleteAllJobQueue.DeleteAllBeforeOptions, tx: DBWriteTransaction) {
switch before {
case .callRecord(let callRecord):
deleteAllCallsMock(callRecord.callBeganTimestamp)
case .timestamp(let timestamp):
deleteAllCallsMock(timestamp)
}
}
}