mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-24 23:45:18 +00:00
* Expand coverage for relay, identity, and location flows * Fix macOS SwiftPM CI failures --------- Co-authored-by: jack <jackjackbits@users.noreply.github.com>
139 lines
5.6 KiB
Swift
139 lines
5.6 KiB
Swift
import Foundation
|
|
import XCTest
|
|
@testable import bitchat
|
|
|
|
final class SecureIdentityStateManagerTests: XCTestCase {
|
|
func test_upsertCryptographicIdentity_tracksByPeerIDPrefixAndClaimedNickname() async {
|
|
let manager = SecureIdentityStateManager(MockKeychain())
|
|
let noisePublicKey = Data(repeating: 0x11, count: 32)
|
|
let signingPublicKey = Data(repeating: 0x22, count: 32)
|
|
let fingerprint = noisePublicKey.sha256Fingerprint()
|
|
|
|
manager.upsertCryptographicIdentity(
|
|
fingerprint: fingerprint,
|
|
noisePublicKey: noisePublicKey,
|
|
signingPublicKey: signingPublicKey,
|
|
claimedNickname: "Alice"
|
|
)
|
|
|
|
let socialIdentityLoaded = await waitUntil {
|
|
manager.getSocialIdentity(for: fingerprint)?.claimedNickname == "Alice"
|
|
}
|
|
XCTAssertTrue(socialIdentityLoaded)
|
|
let matches = manager.getCryptoIdentitiesByPeerIDPrefix(PeerID(publicKey: noisePublicKey))
|
|
XCTAssertEqual(matches.count, 1)
|
|
XCTAssertEqual(matches.first?.fingerprint, fingerprint)
|
|
XCTAssertEqual(matches.first?.publicKey, noisePublicKey)
|
|
XCTAssertEqual(matches.first?.signingPublicKey, signingPublicKey)
|
|
}
|
|
|
|
func test_setBlocked_clearsFavoriteState() async {
|
|
let manager = SecureIdentityStateManager(MockKeychain())
|
|
let fingerprint = String(repeating: "ab", count: 32)
|
|
|
|
manager.setFavorite(fingerprint, isFavorite: true)
|
|
let favoriteSet = await waitUntil { manager.isFavorite(fingerprint: fingerprint) }
|
|
XCTAssertTrue(favoriteSet)
|
|
|
|
manager.setBlocked(fingerprint, isBlocked: true)
|
|
let blockedSet = await waitUntil { manager.isBlocked(fingerprint: fingerprint) }
|
|
XCTAssertTrue(blockedSet)
|
|
|
|
XCTAssertFalse(manager.isFavorite(fingerprint: fingerprint))
|
|
XCTAssertEqual(manager.getSocialIdentity(for: fingerprint)?.claimedNickname, "Unknown")
|
|
}
|
|
|
|
func test_setVerified_updatesTrustLevelAndVerifiedSet() async {
|
|
let manager = SecureIdentityStateManager(MockKeychain())
|
|
let fingerprint = String(repeating: "cd", count: 32)
|
|
|
|
manager.setFavorite(fingerprint, isFavorite: false)
|
|
_ = await waitUntil { manager.getSocialIdentity(for: fingerprint) != nil }
|
|
manager.setVerified(fingerprint: fingerprint, verified: true)
|
|
|
|
let verifiedSet = await waitUntil { manager.isVerified(fingerprint: fingerprint) }
|
|
XCTAssertTrue(verifiedSet)
|
|
XCTAssertTrue(manager.getVerifiedFingerprints().contains(fingerprint))
|
|
XCTAssertEqual(manager.getSocialIdentity(for: fingerprint)?.trustLevel, .verified)
|
|
}
|
|
|
|
func test_forceSave_persistsFavoriteStateAcrossReinit() async {
|
|
let keychain = MockKeychain()
|
|
let manager = SecureIdentityStateManager(keychain)
|
|
let fingerprint = String(repeating: "ef", count: 32)
|
|
|
|
manager.setFavorite(fingerprint, isFavorite: true)
|
|
let favoriteSet = await waitUntil { manager.isFavorite(fingerprint: fingerprint) }
|
|
XCTAssertTrue(favoriteSet)
|
|
manager.forceSave()
|
|
|
|
let reloaded = SecureIdentityStateManager(keychain)
|
|
XCTAssertTrue(reloaded.isFavorite(fingerprint: fingerprint))
|
|
}
|
|
|
|
func test_setNostrBlocked_normalizesToLowercaseAndPersists() async {
|
|
let keychain = MockKeychain()
|
|
let manager = SecureIdentityStateManager(keychain)
|
|
let pubkey = "ABCDEF1234"
|
|
|
|
manager.setNostrBlocked(pubkey, isBlocked: true)
|
|
let nostrBlocked = await waitUntil {
|
|
manager.isNostrBlocked(pubkeyHexLowercased: pubkey.lowercased())
|
|
}
|
|
XCTAssertTrue(nostrBlocked)
|
|
manager.forceSave()
|
|
|
|
let reloaded = SecureIdentityStateManager(keychain)
|
|
XCTAssertEqual(reloaded.getBlockedNostrPubkeys(), Set([pubkey.lowercased()]))
|
|
XCTAssertTrue(reloaded.isNostrBlocked(pubkeyHexLowercased: pubkey))
|
|
}
|
|
|
|
func test_corruptPersistedCache_fallsBackToEmptyState() {
|
|
let keychain = MockKeychain()
|
|
_ = keychain.saveIdentityKey(Data(repeating: 0x01, count: 32), forKey: "identityCacheEncryptionKey")
|
|
_ = keychain.saveIdentityKey(Data([0xFF, 0x00, 0xAA]), forKey: "bitchat.identityCache.v2")
|
|
|
|
let manager = SecureIdentityStateManager(keychain)
|
|
|
|
XCTAssertTrue(manager.getFavorites().isEmpty)
|
|
XCTAssertTrue(manager.getVerifiedFingerprints().isEmpty)
|
|
XCTAssertTrue(manager.getBlockedNostrPubkeys().isEmpty)
|
|
}
|
|
|
|
func test_clearAllIdentityData_removesCachedState() async {
|
|
let manager = SecureIdentityStateManager(MockKeychain())
|
|
let fingerprint = String(repeating: "12", count: 32)
|
|
|
|
manager.setFavorite(fingerprint, isFavorite: true)
|
|
manager.setVerified(fingerprint: fingerprint, verified: true)
|
|
manager.setNostrBlocked("ABCD", isBlocked: true)
|
|
let primed = await waitUntil {
|
|
manager.isFavorite(fingerprint: fingerprint) &&
|
|
manager.isVerified(fingerprint: fingerprint)
|
|
}
|
|
XCTAssertTrue(primed)
|
|
|
|
manager.clearAllIdentityData()
|
|
let cleared = await waitUntil {
|
|
!manager.isFavorite(fingerprint: fingerprint) &&
|
|
!manager.isVerified(fingerprint: fingerprint) &&
|
|
manager.getBlockedNostrPubkeys().isEmpty
|
|
}
|
|
XCTAssertTrue(cleared)
|
|
}
|
|
|
|
private func waitUntil(
|
|
timeout: TimeInterval = 1.0,
|
|
condition: @escaping () -> Bool
|
|
) async -> Bool {
|
|
let deadline = Date().addingTimeInterval(timeout)
|
|
while Date() < deadline {
|
|
if condition() {
|
|
return true
|
|
}
|
|
try? await Task.sleep(nanoseconds: 10_000_000)
|
|
}
|
|
return condition()
|
|
}
|
|
}
|