mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 13:25:20 +00:00
Expand coverage for relay, identity, and location flows (#1055)
* Expand coverage for relay, identity, and location flows * Fix macOS SwiftPM CI failures --------- Co-authored-by: jack <jackjackbits@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
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()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user