Convert the remaining tests to Swift Testing (#781)

* SwiftTesting: NoiseProtocolTests + BinaryProtocolPaddingTests

* SwiftTesting: `NotificationStreamAssemblerTests`

* SwiftTesting: `NostrProtocolTests`

* SwiftTesting: `BinaryProtocolTests`

* SwiftTesting: `PeerIDTests`

* SwiftTesting: `BLEServiceTests`

* SwiftTesting: `CommandProcessorTests`

* SwiftTesting: `GCSFilterTests`

* SwiftTesting: `GeohashBookmarksStoreTests`

* Remove `peerID` test constants

* Remove PeerID + String interop from tests

* Refactor IntegrationTests to extract state management

* Refactor global state management of MockBLEService

* NoiseProtocolSwiftTests: `actor` -> `struct`

* Remove measurement tests w/ no benchmark

* `NoiseProtocolSwiftTests` -> `NoiseProtocolTests`

* SwiftTesting: `LocationChannelsTests`

* SwiftTesting: `GossipSyncManagerTests`

* SwiftTesting: `LocationNotesManagerTests`

* Global `sleep` function for tests

* SwiftTesting: `IntegrationTests`

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
This commit is contained in:
Islam
2025-10-15 00:33:35 +01:00
committed by islam
co-authored by jack
parent 790dcda8e5
commit 5267489fa2
24 changed files with 1504 additions and 1707 deletions
+61 -62
View File
@@ -5,20 +5,20 @@
// Tests for NIP-17 gift-wrapped private messages
//
import XCTest
import Testing
import CryptoKit
import Foundation
@testable import bitchat
final class NostrProtocolTests: XCTestCase {
struct NostrProtocolTests {
func testNIP17MessageRoundTrip() throws {
@Test func nip17MessageRoundTrip() throws {
// Create sender and recipient identities
let sender = try NostrIdentity.generate()
let recipient = try NostrIdentity.generate()
#if DEBUG
print("Sender pubkey: \(sender.publicKeyHex)")
print("Recipient pubkey: \(recipient.publicKeyHex)")
#endif
// Create a test message
let originalContent = "Hello from NIP-17 test!"
@@ -30,10 +30,8 @@ final class NostrProtocolTests: XCTestCase {
senderIdentity: sender
)
#if DEBUG
print("Gift wrap created with ID: \(giftWrap.id)")
print("Gift wrap pubkey: \(giftWrap.pubkey)")
#endif
// Decrypt the gift wrap
let (decryptedContent, senderPubkey, timestamp) = try NostrProtocol.decryptPrivateMessage(
@@ -42,20 +40,18 @@ final class NostrProtocolTests: XCTestCase {
)
// Verify
XCTAssertEqual(decryptedContent, originalContent)
XCTAssertEqual(senderPubkey, sender.publicKeyHex)
#expect(decryptedContent == originalContent)
#expect(senderPubkey == sender.publicKeyHex)
// Verify timestamp is reasonable (within last minute)
let messageDate = Date(timeIntervalSince1970: TimeInterval(timestamp))
let timeDiff = abs(messageDate.timeIntervalSinceNow)
XCTAssertLessThan(timeDiff, 60, "Message timestamp should be recent")
#expect(timeDiff < 60, "Message timestamp should be recent")
#if DEBUG
print("✅ Successfully decrypted message: '\(decryptedContent)' from \(senderPubkey) at \(messageDate)")
#endif
}
func testGiftWrapUsesUniqueEphemeralKeys() throws {
@Test func giftWrapUsesUniqueEphemeralKeys() throws {
// Create identities
let sender = try NostrIdentity.generate()
let recipient = try NostrIdentity.generate()
@@ -74,11 +70,10 @@ final class NostrProtocolTests: XCTestCase {
)
// Gift wrap pubkeys should be different (unique ephemeral keys)
XCTAssertNotEqual(message1.pubkey, message2.pubkey)
#if DEBUG
#expect(message1.pubkey != message2.pubkey)
print("Message 1 gift wrap pubkey: \(message1.pubkey)")
print("Message 2 gift wrap pubkey: \(message2.pubkey)")
#endif
// Both should decrypt successfully
let (content1, _, _) = try NostrProtocol.decryptPrivateMessage(
@@ -90,11 +85,11 @@ final class NostrProtocolTests: XCTestCase {
recipientIdentity: recipient
)
XCTAssertEqual(content1, "Message 1")
XCTAssertEqual(content2, "Message 2")
#expect(content1 == "Message 1")
#expect(content2 == "Message 2")
}
func testDecryptionFailsWithWrongRecipient() throws {
@Test func decryptionFailsWithWrongRecipient() throws {
let sender = try NostrIdentity.generate()
let recipient = try NostrIdentity.generate()
let wrongRecipient = try NostrIdentity.generate()
@@ -107,13 +102,20 @@ final class NostrProtocolTests: XCTestCase {
)
// Try to decrypt with wrong recipient
XCTAssertThrowsError(try NostrProtocol.decryptPrivateMessage(
giftWrap: giftWrap,
recipientIdentity: wrongRecipient
)) { error in
#if DEBUG
print("Expected error when decrypting with wrong key: \(error)")
#endif
if #available(macOS 14.4, iOS 17.4, *) {
#expect(throws: CryptoKitError.authenticationFailure) {
try NostrProtocol.decryptPrivateMessage(
giftWrap: giftWrap,
recipientIdentity: wrongRecipient
)
}
} else {
#expect(throws: (any Error).self) {
try NostrProtocol.decryptPrivateMessage(
giftWrap: giftWrap,
recipientIdentity: wrongRecipient
)
}
}
}
@@ -125,10 +127,11 @@ final class NostrProtocolTests: XCTestCase {
// Build a DELIVERED ack embedded payload (geohash-style, no recipient peer ID)
let messageID = "TEST-MSG-DELIVERED-1"
let senderPeerID = "0123456789abcdef" // 8-byte hex peer ID
guard let embedded = NostrEmbeddedBitChat.encodeAckForNostrNoRecipient(type: .delivered, messageID: messageID, senderPeerID: senderPeerID) else {
XCTFail("Failed to embed delivered ack")
return
}
let embedded = try #require(
NostrEmbeddedBitChat.encodeAckForNostrNoRecipient(type: .delivered, messageID: messageID, senderPeerID: senderPeerID),
"Failed to embed delivered ack"
)
// Create NIP-17 gift wrap to recipient (uses NIP-44 v2 internally)
let giftWrap = try NostrProtocol.createPrivateMessage(
@@ -138,7 +141,7 @@ final class NostrProtocolTests: XCTestCase {
)
// Ensure v2 format was used for ciphertext
XCTAssertTrue(giftWrap.content.hasPrefix("v2:"))
#expect(giftWrap.content.hasPrefix("v2:"))
// Decrypt as recipient
let (content, senderPubkey, _) = try NostrProtocol.decryptPrivateMessage(
@@ -147,39 +150,37 @@ final class NostrProtocolTests: XCTestCase {
)
// Verify sender is correct
XCTAssertEqual(senderPubkey, sender.publicKeyHex)
#expect(senderPubkey == sender.publicKeyHex)
// Parse BitChat payload
XCTAssertTrue(content.hasPrefix("bitchat1:"))
#expect(content.hasPrefix("bitchat1:"))
let base64url = String(content.dropFirst("bitchat1:".count))
guard let packetData = Self.base64URLDecode(base64url),
let packet = BitchatPacket.from(packetData) else {
return XCTFail("Failed to decode bitchat packet")
}
XCTAssertEqual(packet.type, MessageType.noiseEncrypted.rawValue)
guard let payload = NoisePayload.decode(packet.payload) else {
return XCTFail("Failed to decode NoisePayload")
}
let packetData = try #require(Self.base64URLDecode(base64url))
let packet = try #require(BitchatPacket.from(packetData), "Failed to decode bitchat packet")
#expect(packet.type == MessageType.noiseEncrypted.rawValue)
let payload = try #require(NoisePayload.decode(packet.payload), "Failed to decode NoisePayload")
switch payload.type {
case .delivered:
let mid = String(data: payload.data, encoding: .utf8)
XCTAssertEqual(mid, messageID)
#expect(mid == messageID)
default:
XCTFail("Unexpected payload type: \(payload.type)")
Issue.record("Unexpected payload type: \(payload.type)")
}
}
func testAckRoundTripNIP44V2_ReadReceipt() throws {
@Test func ackRoundTripNIP44V2_ReadReceipt() throws {
// Identities
let sender = try NostrIdentity.generate()
let recipient = try NostrIdentity.generate()
let messageID = "TEST-MSG-READ-1"
let senderPeerID = "fedcba9876543210" // 8-byte hex peer ID
guard let embedded = NostrEmbeddedBitChat.encodeAckForNostrNoRecipient(type: .readReceipt, messageID: messageID, senderPeerID: senderPeerID) else {
XCTFail("Failed to embed read ack")
return
}
let embedded = try #require(
NostrEmbeddedBitChat.encodeAckForNostrNoRecipient(type: .readReceipt, messageID: messageID, senderPeerID: senderPeerID),
"Failed to embed read ack"
)
let giftWrap = try NostrProtocol.createPrivateMessage(
content: embedded,
@@ -187,30 +188,28 @@ final class NostrProtocolTests: XCTestCase {
senderIdentity: sender
)
XCTAssertTrue(giftWrap.content.hasPrefix("v2:"))
#expect(giftWrap.content.hasPrefix("v2:"))
let (content, senderPubkey, _) = try NostrProtocol.decryptPrivateMessage(
giftWrap: giftWrap,
recipientIdentity: recipient
)
XCTAssertEqual(senderPubkey, sender.publicKeyHex)
#expect(senderPubkey == sender.publicKeyHex)
XCTAssertTrue(content.hasPrefix("bitchat1:"))
#expect(content.hasPrefix("bitchat1:"))
let base64url = String(content.dropFirst("bitchat1:".count))
guard let packetData = Self.base64URLDecode(base64url),
let packet = BitchatPacket.from(packetData) else {
return XCTFail("Failed to decode bitchat packet")
}
XCTAssertEqual(packet.type, MessageType.noiseEncrypted.rawValue)
guard let payload = NoisePayload.decode(packet.payload) else {
return XCTFail("Failed to decode NoisePayload")
}
let packetData = try #require(Self.base64URLDecode(base64url))
let packet = try #require(BitchatPacket.from(packetData), "Failed to decode bitchat packet")
#expect(packet.type == MessageType.noiseEncrypted.rawValue)
let payload = try #require(NoisePayload.decode(packet.payload), "Failed to decode NoisePayload")
switch payload.type {
case .readReceipt:
let mid = String(data: payload.data, encoding: .utf8)
XCTAssertEqual(mid, messageID)
#expect(mid == messageID)
default:
XCTFail("Unexpected payload type: \(payload.type)")
Issue.record("Unexpected payload type: \(payload.type)")
}
}