mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 19:05:20 +00:00
Remove dead code found by full Periphery audit; add scan config + advisory CI (#1410)
Periphery 3.7.4 audit of both schemes (macOS + iOS, intersected so platform-specific code is never touched), with test targets indexed and the share extension built. 277 dead declarations removed or demoted: dead forwarding wrappers (ChatViewModel+Nostr/+PrivateChat), removed- feature remnants (autocomplete command suggestions, back-swipe tuning, MediaSendError, GeohashParticipantTracker), unused Tor dormancy bindings, assign-only properties, unused parameters (renamed to _), and redundant public accessibility. 13 orphaned localization keys deleted across all 29 locales (old pre-#1392 location-notes UI, app_info warnings). Two real tests were flagged as unused because they never ran: Swift Testing methods missing @Test (NostrProtocolTests. testAckRoundTripNIP44V2_Delivered, NotificationStreamAssemblerTests. testAssemblesCompressedLargeFrame). Re-armed both; they pass. Deliberately kept, now recorded in .periphery.baseline.json: iOS-only code invisible to the CI macOS scan, C FFI signatures, keep-alive NWPathMonitor reference, InboundEventKey.eventID (dedup semantics), wifiBulk capability bit (reserved for Wi-Fi bulk work, used by BitFoundation package tests), and the String secureClear cluster (exercised by package tests). New: .periphery.yml config and an advisory Dead Code CI job (mirrors the SwiftLint precedent from #1361) that fails on findings not in the committed baseline. Verified: full macOS app suite, BitFoundation (119) and BitLogger (13) package tests green; periphery scan --strict exits clean. Co-authored-by: jack <jackjackbits@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
jack
Claude Fable 5
parent
d5cf64f99e
commit
ef848857b7
@@ -70,7 +70,6 @@ private final class MockChatNostrContext: ChatNostrContext {
|
||||
private(set) var mentionCheckedMessageIDs: [String] = []
|
||||
private(set) var hapticMessageIDs: [String] = []
|
||||
|
||||
func handlePublicMessage(_ message: BitchatMessage) { handledPublicMessages.append(message) }
|
||||
func handlePublicMessage(_ message: BitchatMessage, powBits: Int) { handledPublicMessages.append(message) }
|
||||
func checkForMentions(_ message: BitchatMessage) { mentionCheckedMessageIDs.append(message.id) }
|
||||
func sendHapticFeedback(for message: BitchatMessage) { hapticMessageIDs.append(message.id) }
|
||||
@@ -214,8 +213,6 @@ private final class MockChatNostrContext: ChatNostrContext {
|
||||
|
||||
// Favorites & notifications
|
||||
var favoriteRelationshipsByNoiseKey: [Data: FavoritesPersistenceService.FavoriteRelationship] = [:]
|
||||
private(set) var addedFavorites: [(noiseKey: Data, nostrPublicKey: String?, nickname: String)] = []
|
||||
private(set) var postedLocalNotifications: [(title: String, body: String, identifier: String)] = []
|
||||
private(set) var geohashActivityNotifications: [(geohash: String, bodyPreview: String)] = []
|
||||
|
||||
func favoriteRelationship(forNoiseKey noiseKey: Data) -> FavoritesPersistenceService.FavoriteRelationship? {
|
||||
@@ -226,14 +223,6 @@ private final class MockChatNostrContext: ChatNostrContext {
|
||||
Array(favoriteRelationshipsByNoiseKey.values)
|
||||
}
|
||||
|
||||
func addFavorite(noiseKey: Data, nostrPublicKey: String?, nickname: String) {
|
||||
addedFavorites.append((noiseKey, nostrPublicKey, nickname))
|
||||
}
|
||||
|
||||
func postLocalNotification(title: String, body: String, identifier: String) {
|
||||
postedLocalNotifications.append((title, body, identifier))
|
||||
}
|
||||
|
||||
func notifyGeohashActivity(geohash: String, bodyPreview: String) {
|
||||
geohashActivityNotifications.append((geohash, bodyPreview))
|
||||
}
|
||||
@@ -250,24 +239,6 @@ private func drainMainQueue() async {
|
||||
}
|
||||
}
|
||||
|
||||
private func makeFavoriteRelationship(
|
||||
noiseKey: Data,
|
||||
nostrPublicKey: String? = nil,
|
||||
nickname: String = "alice",
|
||||
isFavorite: Bool = false,
|
||||
theyFavoritedUs: Bool = false
|
||||
) -> FavoritesPersistenceService.FavoriteRelationship {
|
||||
FavoritesPersistenceService.FavoriteRelationship(
|
||||
peerNoisePublicKey: noiseKey,
|
||||
peerNostrPublicKey: nostrPublicKey,
|
||||
peerNickname: nickname,
|
||||
isFavorite: isFavorite,
|
||||
theyFavoritedUs: theyFavoritedUs,
|
||||
favoritedAt: Date(timeIntervalSince1970: 0),
|
||||
lastUpdated: Date(timeIntervalSince1970: 0)
|
||||
)
|
||||
}
|
||||
|
||||
// MARK: - Coordinator Tests Against Mock Context
|
||||
|
||||
/// Exercises `ChatNostrCoordinator` against `MockChatNostrContext` with no
|
||||
|
||||
@@ -29,7 +29,6 @@ private final class MockChatPeerIdentityContext: ChatPeerIdentityContext {
|
||||
var unreadPrivateMessages: Set<PeerID> = []
|
||||
var selectedPrivateChatPeer: PeerID?
|
||||
var selectedPrivateChatFingerprint: String?
|
||||
var nickname = "me"
|
||||
var myPeerID = PeerID(str: "0011223344556677")
|
||||
var activeChannel: ChannelID = .mesh
|
||||
private(set) var notifyUIChangedCount = 0
|
||||
|
||||
@@ -100,11 +100,6 @@ private final class MockChatPrivateConversationContext: ChatPrivateConversationC
|
||||
unreadPrivateMessages.remove(peerID)
|
||||
}
|
||||
|
||||
func removePrivateChat(_ peerID: PeerID) {
|
||||
privateChats.removeValue(forKey: peerID)
|
||||
unreadPrivateMessages.remove(peerID)
|
||||
}
|
||||
|
||||
func migratePrivateChat(from oldPeerID: PeerID, to newPeerID: PeerID) {
|
||||
migratedChats.append((oldPeerID, newPeerID))
|
||||
guard oldPeerID != newPeerID, let source = privateChats[oldPeerID] else { return }
|
||||
@@ -177,12 +172,10 @@ private final class MockChatPrivateConversationContext: ChatPrivateConversationC
|
||||
// Routing & acknowledgements
|
||||
private(set) var routedPrivateMessages: [(content: String, peerID: PeerID, messageID: String)] = []
|
||||
private(set) var routedReadReceipts: [(messageID: String, peerID: PeerID)] = []
|
||||
private(set) var routedFavoriteNotifications: [(peerID: PeerID, isFavorite: Bool)] = []
|
||||
private(set) var meshReadReceipts: [(messageID: String, peerID: PeerID)] = []
|
||||
private(set) var geoPrivateMessages: [(content: String, recipientHex: String, messageID: String)] = []
|
||||
private(set) var geoDeliveryAcks: [(messageID: String, recipientHex: String)] = []
|
||||
private(set) var geoReadReceipts: [(messageID: String, recipientHex: String)] = []
|
||||
private(set) var embeddedDeliveryAckMessageIDs: [String] = []
|
||||
|
||||
func routePrivateMessage(_ content: String, to peerID: PeerID, recipientNickname: String, messageID: String) {
|
||||
routedPrivateMessages.append((content, peerID, messageID))
|
||||
@@ -192,10 +185,6 @@ private final class MockChatPrivateConversationContext: ChatPrivateConversationC
|
||||
routedReadReceipts.append((receipt.originalMessageID, peerID))
|
||||
}
|
||||
|
||||
func routeFavoriteNotification(to peerID: PeerID, isFavorite: Bool) {
|
||||
routedFavoriteNotifications.append((peerID, isFavorite))
|
||||
}
|
||||
|
||||
func sendMeshReadReceipt(_ receipt: ReadReceipt, to peerID: PeerID) {
|
||||
meshReadReceipts.append((receipt.originalMessageID, peerID))
|
||||
}
|
||||
@@ -212,10 +201,6 @@ private final class MockChatPrivateConversationContext: ChatPrivateConversationC
|
||||
geoReadReceipts.append((messageID, recipientHex))
|
||||
}
|
||||
|
||||
func sendDeliveryAckViaNostrEmbedded(_ message: BitchatMessage, wasReadBefore: Bool, senderPubkey: String, key: Data?) {
|
||||
embeddedDeliveryAckMessageIDs.append(message.id)
|
||||
}
|
||||
|
||||
// Favorites & notifications
|
||||
var favoriteRelationshipsByNoiseKey: [Data: FavoritesPersistenceService.FavoriteRelationship] = [:]
|
||||
private(set) var peerFavoritedUsUpdates: [(noiseKey: Data, favorited: Bool, nickname: String, nostrPublicKey: String?)] = []
|
||||
|
||||
@@ -58,11 +58,6 @@ private final class MockChatPublicConversationContext: ChatPublicConversationCon
|
||||
return true
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func appendGeohashMessageIfAbsent(_ message: BitchatMessage, toGeohash geohash: String) -> Bool {
|
||||
appendPublicMessage(message, to: .geohash(geohash.lowercased()))
|
||||
}
|
||||
|
||||
func publicConversationContainsMessage(withID messageID: String, in conversationID: ConversationID) -> Bool {
|
||||
conversations[conversationID]?.contains(where: { $0.id == messageID }) == true
|
||||
}
|
||||
|
||||
@@ -675,10 +675,6 @@ private final class MockCommandContextProvider: CommandContextProvider {
|
||||
toggledFavorites.append(peerID)
|
||||
}
|
||||
|
||||
func sendFavoriteNotification(to peerID: PeerID, isFavorite: Bool) {
|
||||
favoriteNotifications.append((peerID, isFavorite))
|
||||
}
|
||||
|
||||
// Groups: record the parsed subcommand + argument the processor forwarded.
|
||||
private(set) var groupCommands: [(subcommand: String, argument: String)] = []
|
||||
|
||||
|
||||
@@ -590,9 +590,6 @@ private final class CourierCaptureTransport: Transport {
|
||||
private(set) var courierSends: [(messageID: String, recipientKey: Data, couriers: [PeerID])] = []
|
||||
private(set) var directSends: [String] = []
|
||||
|
||||
var peerSnapshotPublisher: AnyPublisher<[TransportPeerSnapshot], Never> {
|
||||
Just(snapshots).eraseToAnyPublisher()
|
||||
}
|
||||
func currentPeerSnapshots() -> [TransportPeerSnapshot] { snapshots }
|
||||
|
||||
var myPeerID = PeerID(str: "00000000000000aa")
|
||||
|
||||
@@ -18,9 +18,7 @@ struct PublicChatE2ETests {
|
||||
private let charlie: MockBLEService
|
||||
private let david: MockBLEService
|
||||
private let bus = MockBLEBus()
|
||||
|
||||
private var receivedMessages: [String: [BitchatMessage]] = [:]
|
||||
|
||||
|
||||
init() {
|
||||
// Create mock services with unique peer IDs to avoid any collision
|
||||
alice = MockBLEService(peerID: PeerID(str: UUID().uuidString), nickname: TestConstants.testNickname1, bus: bus)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import SwiftUI
|
||||
import XCTest
|
||||
@testable import bitchat
|
||||
|
||||
final class FontBitchatTests: XCTestCase {
|
||||
// func testMonospacedMapping() {
|
||||
|
||||
@@ -369,7 +369,6 @@ extension FragmentationTests {
|
||||
func didUpdateMessageDeliveryStatus(_ messageID: String, status: DeliveryStatus) {}
|
||||
func didReceiveNoisePayload(from peerID: PeerID, type: NoisePayloadType, payload: Data, timestamp: Date) {}
|
||||
func didUpdateBluetoothState(_ state: CBManagerState) {}
|
||||
func didReceiveRegionalPublicMessage(from peerID: PeerID, nickname: String, content: String, timestamp: Date) {}
|
||||
}
|
||||
|
||||
// Helper: build a large message packet (unencrypted public message)
|
||||
|
||||
@@ -33,14 +33,6 @@ final class TestNetworkHelper {
|
||||
return node
|
||||
}
|
||||
|
||||
func getNode(_ name: String) -> MockBLEService? {
|
||||
nodes[name]
|
||||
}
|
||||
|
||||
func getManager(_ name: String) -> NoiseSessionManager? {
|
||||
noiseManagers[name]
|
||||
}
|
||||
|
||||
// MARK: - Topology
|
||||
|
||||
func connect(_ a: String, _ b: String) {
|
||||
|
||||
@@ -10,7 +10,6 @@ struct LocalizationCoverageTests {
|
||||
.deletingLastPathComponent() // repo root
|
||||
|
||||
private struct Catalog {
|
||||
let sourceLanguage: String
|
||||
/// key -> set of locales with a localization entry
|
||||
let coverage: [String: Set<String>]
|
||||
/// all locales appearing anywhere in the catalog
|
||||
@@ -22,7 +21,6 @@ struct LocalizationCoverageTests {
|
||||
let data = try Data(contentsOf: url)
|
||||
let root = try #require(try JSONSerialization.jsonObject(with: data) as? [String: Any])
|
||||
let strings = try #require(root["strings"] as? [String: Any])
|
||||
let sourceLanguage = try #require(root["sourceLanguage"] as? String)
|
||||
|
||||
var coverage: [String: Set<String>] = [:]
|
||||
for (key, value) in strings {
|
||||
@@ -43,7 +41,7 @@ struct LocalizationCoverageTests {
|
||||
}
|
||||
coverage[key] = locales
|
||||
}
|
||||
return Catalog(sourceLanguage: sourceLanguage, coverage: coverage)
|
||||
return Catalog(coverage: coverage)
|
||||
}
|
||||
|
||||
@Test func mainCatalogCoversAllLocalesForEveryKey() throws {
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
import Foundation
|
||||
import BitFoundation
|
||||
@testable import bitchat
|
||||
|
||||
final class MockBLEBus {
|
||||
private var registry: [PeerID: MockBLEService] = [:]
|
||||
|
||||
@@ -48,10 +48,6 @@ final class MockBLEService: NSObject {
|
||||
set { myNickname = newValue }
|
||||
}
|
||||
|
||||
var nickname: String {
|
||||
return myNickname
|
||||
}
|
||||
|
||||
var peerID: PeerID {
|
||||
return myPeerID
|
||||
}
|
||||
@@ -62,12 +58,6 @@ final class MockBLEService: NSObject {
|
||||
self.bus = bus
|
||||
}
|
||||
|
||||
// MARK: - Methods matching BLEService
|
||||
|
||||
func setNickname(_ nickname: String) {
|
||||
self.myNickname = nickname
|
||||
}
|
||||
|
||||
// MARK: - In-memory test bus (for E2E/Integration)
|
||||
|
||||
/// Registers this instance on first use.
|
||||
@@ -92,10 +82,6 @@ final class MockBLEService: NSObject {
|
||||
return connectedPeers.contains(peerID)
|
||||
}
|
||||
|
||||
func peerNickname(peerID: String) -> String? {
|
||||
"MockPeer_\(peerID)"
|
||||
}
|
||||
|
||||
func getPeerNicknames() -> [PeerID: String] {
|
||||
var nicknames: [PeerID: String] = [:]
|
||||
for peer in connectedPeers {
|
||||
@@ -103,10 +89,6 @@ final class MockBLEService: NSObject {
|
||||
}
|
||||
return nicknames
|
||||
}
|
||||
|
||||
func getPeers() -> [PeerID: String] {
|
||||
return getPeerNicknames()
|
||||
}
|
||||
|
||||
/// Keep local echo synchronous so Swift Testing confirmations observe it deterministically.
|
||||
private func deliverLocalEcho(_ message: BitchatMessage) {
|
||||
@@ -155,14 +137,6 @@ final class MockBLEService: NSObject {
|
||||
}
|
||||
}
|
||||
|
||||
func sendFileBroadcast(_ packet: BitchatFilePacket, transferId: String) {
|
||||
// Tests currently ignore file transfer flows; keep stub for protocol conformance.
|
||||
}
|
||||
|
||||
func sendFilePrivate(_ packet: BitchatFilePacket, to peerID: PeerID, transferId: String) {
|
||||
// Tests currently ignore file transfer flows; keep stub for protocol conformance.
|
||||
}
|
||||
|
||||
func sendPrivateMessage(_ content: String, to recipientPeerID: PeerID, recipientNickname: String, messageID: String) {
|
||||
let message = BitchatMessage(
|
||||
id: messageID,
|
||||
@@ -209,39 +183,6 @@ final class MockBLEService: NSObject {
|
||||
}
|
||||
}
|
||||
|
||||
func sendFavoriteNotification(to peerID: String, isFavorite: Bool) {
|
||||
// Mock implementation
|
||||
}
|
||||
|
||||
func sendReadReceipt(_ receipt: ReadReceipt, to peerID: String) {
|
||||
// Mock implementation
|
||||
}
|
||||
|
||||
func sendBroadcastAnnounce() {
|
||||
// Mock implementation
|
||||
}
|
||||
|
||||
func getPeerFingerprint(_ peerID: String) -> String? {
|
||||
return nil
|
||||
}
|
||||
|
||||
func getNoiseSessionState(for peerID: String) -> LazyHandshakeState {
|
||||
return .none
|
||||
}
|
||||
|
||||
func triggerHandshake(with peerID: String) {
|
||||
// Mock implementation
|
||||
}
|
||||
|
||||
func emergencyDisconnectAll() {
|
||||
connectedPeers.removeAll()
|
||||
delegate?.didUpdatePeerList([])
|
||||
}
|
||||
|
||||
func getFingerprint(for peerID: String) -> String? {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MARK: - Test Helper Methods
|
||||
|
||||
func simulateConnectedPeer(_ peerID: PeerID) {
|
||||
@@ -314,9 +255,6 @@ final class MockBLEService: NSObject {
|
||||
}
|
||||
}
|
||||
|
||||
// Backward compatibility for older tests
|
||||
typealias MockSimplifiedBluetoothService = MockBLEService
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
extension MockBLEService {
|
||||
|
||||
@@ -11,18 +11,11 @@ import BitFoundation
|
||||
@testable import bitchat
|
||||
|
||||
final class MockIdentityManager: SecureIdentityStateManagerProtocol {
|
||||
private let keychain: KeychainManagerProtocol
|
||||
private var blockedFingerprints: Set<String> = []
|
||||
private var blockedNostrPubkeys: Set<String> = []
|
||||
private var socialIdentities: [String: SocialIdentity] = [:]
|
||||
|
||||
init(_ keychain: KeychainManagerProtocol) {
|
||||
self.keychain = keychain
|
||||
}
|
||||
|
||||
func loadIdentityCache() {}
|
||||
|
||||
func saveIdentityCache() {}
|
||||
|
||||
init(_: KeychainManagerProtocol) {}
|
||||
|
||||
func forceSave() {}
|
||||
|
||||
@@ -45,12 +38,6 @@ final class MockIdentityManager: SecureIdentityStateManagerProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
func getFavorites() -> Set<String> {
|
||||
Set()
|
||||
}
|
||||
|
||||
func setFavorite(_ fingerprint: String, isFavorite: Bool) {}
|
||||
|
||||
func isFavorite(fingerprint: String) -> Bool {
|
||||
false
|
||||
}
|
||||
@@ -99,9 +86,7 @@ final class MockIdentityManager: SecureIdentityStateManagerProtocol {
|
||||
}
|
||||
|
||||
func registerEphemeralSession(peerID: PeerID, handshakeState: HandshakeState) {}
|
||||
|
||||
func updateHandshakeState(peerID: PeerID, state: HandshakeState) {}
|
||||
|
||||
|
||||
func clearAllIdentityData() {}
|
||||
|
||||
func removeEphemeralSession(peerID: PeerID) {}
|
||||
@@ -139,10 +124,6 @@ final class MockIdentityManager: SecureIdentityStateManagerProtocol {
|
||||
!(vouchesByVouchee[fingerprint] ?? []).isEmpty
|
||||
}
|
||||
|
||||
func effectiveTrustLevel(for fingerprint: String) -> TrustLevel {
|
||||
socialIdentities[fingerprint]?.trustLevel ?? .unknown
|
||||
}
|
||||
|
||||
func lastVouchBatchSent(to fingerprint: String) -> Date? {
|
||||
vouchBatchSentAt[fingerprint]
|
||||
}
|
||||
|
||||
@@ -26,9 +26,6 @@ final class MockTransport: Transport {
|
||||
var myNickname: String = "TestUser"
|
||||
|
||||
private let peerSnapshotSubject = CurrentValueSubject<[TransportPeerSnapshot], Never>([])
|
||||
var peerSnapshotPublisher: AnyPublisher<[TransportPeerSnapshot], Never> {
|
||||
peerSnapshotSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
// MARK: - Recording Properties (for test assertions)
|
||||
|
||||
|
||||
@@ -31,11 +31,8 @@ struct NoiseTestVector: Codable {
|
||||
let init_prologue: String
|
||||
let init_static: String
|
||||
let init_ephemeral: String
|
||||
let init_psks: [String]?
|
||||
let resp_prologue: String
|
||||
let resp_static: String
|
||||
let resp_ephemeral: String
|
||||
let resp_psks: [String]?
|
||||
let handshake_hash: String?
|
||||
let messages: [TestMessage]
|
||||
|
||||
|
||||
@@ -156,6 +156,7 @@ struct NostrProtocolTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
func testAckRoundTripNIP44V2_Delivered() throws {
|
||||
// Identities
|
||||
let sender = try NostrIdentity.generate()
|
||||
|
||||
@@ -118,6 +118,7 @@ struct NotificationStreamAssemblerTests {
|
||||
#expect(decoded.timestamp == packet2.timestamp)
|
||||
}
|
||||
|
||||
@Test
|
||||
func testAssemblesCompressedLargeFrame() throws {
|
||||
var assembler = NotificationStreamAssembler()
|
||||
|
||||
|
||||
@@ -610,7 +610,6 @@ private final class PerfNostrContext: ChatNostrContext {
|
||||
func appendGeohashMessageIfAbsent(_ message: BitchatMessage, toGeohash geohash: String) -> Bool { true }
|
||||
|
||||
private(set) var handledPublicMessageCount = 0
|
||||
func handlePublicMessage(_ message: BitchatMessage) { handledPublicMessageCount += 1 }
|
||||
func handlePublicMessage(_ message: BitchatMessage, powBits: Int) { handledPublicMessageCount += 1 }
|
||||
func checkForMentions(_ message: BitchatMessage) {}
|
||||
func sendHapticFeedback(for message: BitchatMessage) {}
|
||||
@@ -668,8 +667,6 @@ private final class PerfNostrContext: ChatNostrContext {
|
||||
|
||||
func favoriteRelationship(forNoiseKey noiseKey: Data) -> FavoritesPersistenceService.FavoriteRelationship? { nil }
|
||||
func allFavoriteRelationships() -> [FavoritesPersistenceService.FavoriteRelationship] { [] }
|
||||
func addFavorite(noiseKey: Data, nostrPublicKey: String?, nickname: String) {}
|
||||
func postLocalNotification(title: String, body: String, identifier: String) {}
|
||||
func notifyGeohashActivity(geohash: String, bodyPreview: String) {}
|
||||
}
|
||||
|
||||
@@ -779,7 +776,6 @@ private final class PerfDeliveryContext: ChatDeliveryContext {
|
||||
@MainActor
|
||||
private final class PerfPipelineFixture {
|
||||
let viewModel: ChatViewModel
|
||||
let transport: MockTransport
|
||||
let conversations: ConversationStore
|
||||
let privateInbox: PrivateInboxModel
|
||||
let publicChat: PublicChatModel
|
||||
@@ -791,7 +787,6 @@ private final class PerfPipelineFixture {
|
||||
let transport = MockTransport()
|
||||
let conversations = ConversationStore()
|
||||
|
||||
self.transport = transport
|
||||
self.conversations = conversations
|
||||
self.viewModel = ChatViewModel(
|
||||
keychain: keychain,
|
||||
|
||||
@@ -23,10 +23,6 @@ private final class DefaultTransportProbe: Transport {
|
||||
var myNickname = "Tester"
|
||||
private(set) var sentMessages: [(content: String, mentions: [String])] = []
|
||||
|
||||
var peerSnapshotPublisher: AnyPublisher<[TransportPeerSnapshot], Never> {
|
||||
subject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
func currentPeerSnapshots() -> [TransportPeerSnapshot] { subject.value }
|
||||
func setNickname(_ nickname: String) { myNickname = nickname }
|
||||
func startServices() {}
|
||||
|
||||
@@ -27,28 +27,28 @@ private final class TestPipelineDelegate: PublicMessagePipelineDelegate {
|
||||
committed.filter { $0.conversationID == conversationID }.map(\.message)
|
||||
}
|
||||
|
||||
func pipeline(_ pipeline: PublicMessagePipeline, normalizeContent content: String) -> String {
|
||||
func pipeline(_: PublicMessagePipeline, normalizeContent content: String) -> String {
|
||||
dedupService.normalizedContentKey(content)
|
||||
}
|
||||
|
||||
func pipeline(_ pipeline: PublicMessagePipeline, contentTimestampForKey key: String) -> Date? {
|
||||
func pipeline(_: PublicMessagePipeline, contentTimestampForKey key: String) -> Date? {
|
||||
dedupService.contentTimestamp(forKey: key)
|
||||
}
|
||||
|
||||
func pipeline(_ pipeline: PublicMessagePipeline, recordContentKey key: String, timestamp: Date) {
|
||||
func pipeline(_: PublicMessagePipeline, recordContentKey key: String, timestamp: Date) {
|
||||
dedupService.recordContentKey(key, timestamp: timestamp)
|
||||
recordedContentKeys.append(key)
|
||||
}
|
||||
|
||||
func pipeline(_ pipeline: PublicMessagePipeline, commit message: BitchatMessage, to conversationID: ConversationID) -> Bool {
|
||||
func pipeline(_: PublicMessagePipeline, commit message: BitchatMessage, to conversationID: ConversationID) -> Bool {
|
||||
guard !rejectedMessageIDs.contains(message.id) else { return false }
|
||||
committed.append((message, conversationID))
|
||||
return true
|
||||
}
|
||||
|
||||
func pipelinePrewarmMessage(_ pipeline: PublicMessagePipeline, message: BitchatMessage) {}
|
||||
func pipelinePrewarmMessage(_: PublicMessagePipeline, message: BitchatMessage) {}
|
||||
|
||||
func pipelineSetBatchingState(_ pipeline: PublicMessagePipeline, isBatching: Bool) {
|
||||
func pipelineSetBatchingState(_: PublicMessagePipeline, isBatching: Bool) {
|
||||
batchingStates.append(isBatching)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,8 +230,4 @@ private final class MockGeohashPresenceTimer: GeohashPresenceTimerProtocol {
|
||||
invalidateCallCount += 1
|
||||
isValid = false
|
||||
}
|
||||
|
||||
func fire() {
|
||||
handler()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +120,6 @@ final class NetworkActivationServiceTests: XCTestCase {
|
||||
return NetworkActivationTestContext(
|
||||
service: service,
|
||||
storage: storage,
|
||||
permissionSubject: permissionSubject,
|
||||
favoritesSubject: favoritesSubject,
|
||||
torController: torController,
|
||||
relayController: relayController,
|
||||
@@ -148,7 +147,6 @@ final class NetworkActivationServiceTests: XCTestCase {
|
||||
private struct NetworkActivationTestContext {
|
||||
let service: NetworkActivationService
|
||||
let storage: UserDefaults
|
||||
let permissionSubject: CurrentValueSubject<LocationChannelManager.PermissionState, Never>
|
||||
let favoritesSubject: CurrentValueSubject<Set<Data>, Never>
|
||||
let torController: MockNetworkActivationTorController
|
||||
let relayController: MockNetworkActivationRelayController
|
||||
|
||||
@@ -1483,7 +1483,6 @@ final class NostrRelayManagerTests: XCTestCase {
|
||||
return RelayManagerTestContext(
|
||||
manager: manager,
|
||||
permissionSubject: permissionSubject,
|
||||
favoritesSubject: favoritesSubject,
|
||||
sessionFactory: sessionFactory,
|
||||
scheduler: scheduler,
|
||||
clock: clock,
|
||||
@@ -1537,7 +1536,6 @@ final class NostrRelayManagerTests: XCTestCase {
|
||||
private struct RelayManagerTestContext {
|
||||
let manager: NostrRelayManager
|
||||
let permissionSubject: CurrentValueSubject<LocationChannelManager.PermissionState, Never>
|
||||
let favoritesSubject: CurrentValueSubject<Set<Data>, Never>
|
||||
let sessionFactory: MockRelaySessionFactory
|
||||
let scheduler: MockRelayScheduler
|
||||
let clock: MutableClock
|
||||
@@ -1644,7 +1642,6 @@ private final class MockRelaySessionFactory: NostrRelaySessionProtocol {
|
||||
}
|
||||
|
||||
private final class MockRelayConnection: NostrRelayConnectionProtocol {
|
||||
private let url: String
|
||||
private let pingError: Error?
|
||||
private let sendError: Error?
|
||||
private var receiveHandler: ((Result<URLSessionWebSocketTask.Message, Error>) -> Void)?
|
||||
@@ -1662,8 +1659,7 @@ private final class MockRelayConnection: NostrRelayConnectionProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
init(url: String, pingError: Error? = nil, sendError: Error? = nil) {
|
||||
self.url = url
|
||||
init(url _: String, pingError: Error? = nil, sendError: Error? = nil) {
|
||||
self.pingError = pingError
|
||||
self.sendError = sendError
|
||||
}
|
||||
|
||||
@@ -214,18 +214,6 @@ private final class TestIdentityManager: SecureIdentityStateManagerProtocol {
|
||||
socialIdentities[identity.fingerprint] = identity
|
||||
}
|
||||
|
||||
func getFavorites() -> Set<String> {
|
||||
favorites
|
||||
}
|
||||
|
||||
func setFavorite(_ fingerprint: String, isFavorite: Bool) {
|
||||
if isFavorite {
|
||||
favorites.insert(fingerprint)
|
||||
} else {
|
||||
favorites.remove(fingerprint)
|
||||
}
|
||||
}
|
||||
|
||||
func isFavorite(fingerprint: String) -> Bool {
|
||||
favorites.contains(fingerprint)
|
||||
}
|
||||
@@ -266,8 +254,6 @@ private final class TestIdentityManager: SecureIdentityStateManagerProtocol {
|
||||
|
||||
func registerEphemeralSession(peerID: PeerID, handshakeState: HandshakeState) {}
|
||||
|
||||
func updateHandshakeState(peerID: PeerID, state: HandshakeState) {}
|
||||
|
||||
func clearAllIdentityData() {
|
||||
socialIdentities.removeAll()
|
||||
favorites.removeAll()
|
||||
@@ -308,10 +294,6 @@ private final class TestIdentityManager: SecureIdentityStateManagerProtocol {
|
||||
false
|
||||
}
|
||||
|
||||
func effectiveTrustLevel(for fingerprint: String) -> TrustLevel {
|
||||
verified.contains(fingerprint) ? .verified : .unknown
|
||||
}
|
||||
|
||||
func lastVouchBatchSent(to fingerprint: String) -> Date? {
|
||||
nil
|
||||
}
|
||||
|
||||
@@ -25,9 +25,5 @@ struct TestConstants {
|
||||
static let testNickname4 = "David"
|
||||
|
||||
static let testMessage1 = "Hello, World!"
|
||||
static let testMessage2 = "How are you?"
|
||||
static let testMessage3 = "This is a test message"
|
||||
static let testLongMessage = String(repeating: "This is a long message. ", count: 100)
|
||||
|
||||
static let testSignature = Data(repeating: 0xAB, count: 64)
|
||||
}
|
||||
|
||||
@@ -12,20 +12,7 @@ import BitFoundation
|
||||
@testable import bitchat
|
||||
|
||||
final class TestHelpers {
|
||||
|
||||
// MARK: - Key Generation
|
||||
|
||||
static func generateTestKeyPair() -> (privateKey: Curve25519.KeyAgreement.PrivateKey, publicKey: Curve25519.KeyAgreement.PublicKey) {
|
||||
let privateKey = Curve25519.KeyAgreement.PrivateKey()
|
||||
let publicKey = privateKey.publicKey
|
||||
return (privateKey, publicKey)
|
||||
}
|
||||
|
||||
static func generateTestIdentity(peerID: String, nickname: String) -> (peerID: String, nickname: String, privateKey: Curve25519.KeyAgreement.PrivateKey, publicKey: Curve25519.KeyAgreement.PublicKey) {
|
||||
let (privateKey, publicKey) = generateTestKeyPair()
|
||||
return (peerID: peerID, nickname: nickname, privateKey: privateKey, publicKey: publicKey)
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Message Creation
|
||||
|
||||
static func createTestMessage(
|
||||
@@ -78,11 +65,7 @@ final class TestHelpers {
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
static func generateTestPeerID() -> String {
|
||||
return "PEER" + UUID().uuidString.prefix(8)
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Async Helpers
|
||||
|
||||
static func waitFor(_ condition: @escaping () -> Bool, timeout: TimeInterval = TestConstants.defaultTimeout) async throws {
|
||||
@@ -110,32 +93,10 @@ final class TestHelpers {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
static func expectAsync<T>(
|
||||
timeout: TimeInterval = TestConstants.defaultTimeout,
|
||||
operation: @escaping () async throws -> T
|
||||
) async throws -> T {
|
||||
return try await withThrowingTaskGroup(of: T.self) { group in
|
||||
group.addTask {
|
||||
return try await operation()
|
||||
}
|
||||
|
||||
group.addTask {
|
||||
try await sleep(1)
|
||||
throw TestError.timeout
|
||||
}
|
||||
|
||||
let result = try await group.next()!
|
||||
group.cancelAll()
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum TestError: Error {
|
||||
case timeout
|
||||
case unexpectedValue
|
||||
case testFailure(String)
|
||||
}
|
||||
|
||||
// MARK: - Private chat seeding (ConversationStore migration)
|
||||
@@ -164,18 +125,6 @@ extension ChatViewModel {
|
||||
}
|
||||
}
|
||||
|
||||
/// Test-only replacement for `messages.removeAll()`: empties a public
|
||||
/// channel's conversation.
|
||||
@MainActor
|
||||
func clearPublicMessages(for channel: ChannelID = .mesh) {
|
||||
conversations.clear(ConversationID(channelID: channel))
|
||||
}
|
||||
|
||||
/// Test-only: drops every private chat and unread flag.
|
||||
@MainActor
|
||||
func clearAllPrivateChats() {
|
||||
conversations.removeAllDirectConversations()
|
||||
}
|
||||
}
|
||||
|
||||
func sleep(_ seconds: TimeInterval) async throws {
|
||||
|
||||
Reference in New Issue
Block a user