diff --git a/.gitignore b/.gitignore index a506f99b..fcb5d1d7 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,9 @@ # # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore +## implementation plans +plans/ + ## User settings xcuserdata/ @@ -58,4 +61,4 @@ __pycache__/ ## Temporary files *.tmp -*.temp \ No newline at end of file +*.temp diff --git a/bitchat.xcodeproj/project.pbxproj b/bitchat.xcodeproj/project.pbxproj index 34f6bcf6..76227d63 100644 --- a/bitchat.xcodeproj/project.pbxproj +++ b/bitchat.xcodeproj/project.pbxproj @@ -28,6 +28,8 @@ 04636BDE2E30BE5100FBCFA8 /* NoiseProtocolTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04636BCA2E30BE5100FBCFA8 /* NoiseProtocolTests.swift */; }; 04636BDF2E30BE5100FBCFA8 /* TestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04636BCF2E30BE5100FBCFA8 /* TestHelpers.swift */; }; 04636BE02E30BE5100FBCFA8 /* PublicChatE2ETests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04636BC52E30BE5100FBCFA8 /* PublicChatE2ETests.swift */; }; + 04636BE82E30BEC600FBCFA8 /* IntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04636BE12E30BEC600FBCFA8 /* IntegrationTests.swift */; }; + 04636BEB2E30BEC600FBCFA8 /* IntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04636BE12E30BEC600FBCFA8 /* IntegrationTests.swift */; }; 04891CA92E22971E0064A111 /* LRUCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04891CA82E22971E0064A111 /* LRUCache.swift */; }; 04891CAA2E22971E0064A111 /* LRUCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04891CA82E22971E0064A111 /* LRUCache.swift */; }; 04AD0B4E2E25B9580002A40A /* IdentityModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E2446380E7A44E49A35B664 /* IdentityModels.swift */; }; @@ -130,6 +132,7 @@ 04636BCC2E30BE5100FBCFA8 /* BinaryProtocolTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BinaryProtocolTests.swift; sourceTree = ""; }; 04636BCE2E30BE5100FBCFA8 /* TestConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestConstants.swift; sourceTree = ""; }; 04636BCF2E30BE5100FBCFA8 /* TestHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestHelpers.swift; sourceTree = ""; }; + 04636BE12E30BEC600FBCFA8 /* IntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegrationTests.swift; sourceTree = ""; }; 04891CA82E22971E0064A111 /* LRUCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LRUCache.swift; sourceTree = ""; }; 04B6BA412E2035530090FE39 /* NoiseProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoiseProtocol.swift; sourceTree = ""; }; 04B6BA422E2035530090FE39 /* NoiseSecurityConsiderations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoiseSecurityConsiderations.swift; sourceTree = ""; }; @@ -212,6 +215,14 @@ path = TestUtilities; sourceTree = ""; }; + 04636BE22E30BEC600FBCFA8 /* Integration */ = { + isa = PBXGroup; + children = ( + 04636BE12E30BEC600FBCFA8 /* IntegrationTests.swift */, + ); + path = Integration; + sourceTree = ""; + }; 04B6BA442E2035530090FE39 /* Noise */ = { isa = PBXGroup; children = ( @@ -327,6 +338,7 @@ C3D98EB3E1B455E321F519F4 /* bitchatTests */ = { isa = PBXGroup; children = ( + 04636BE22E30BEC600FBCFA8 /* Integration */, 04636BC62E30BE5100FBCFA8 /* EndToEnd */, 04636BC92E30BE5100FBCFA8 /* Mocks */, 04636BCB2E30BE5100FBCFA8 /* Noise */, @@ -595,6 +607,7 @@ buildActionMask = 2147483647; files = ( 04636BD92E30BE5100FBCFA8 /* BinaryProtocolTests.swift in Sources */, + 04636BE82E30BEC600FBCFA8 /* IntegrationTests.swift in Sources */, 04636BDA2E30BE5100FBCFA8 /* MockNoiseSession.swift in Sources */, 04636BDB2E30BE5100FBCFA8 /* PrivateChatE2ETests.swift in Sources */, 04636BDC2E30BE5100FBCFA8 /* TestConstants.swift in Sources */, @@ -610,6 +623,7 @@ buildActionMask = 2147483647; files = ( 04636BD12E30BE5100FBCFA8 /* BinaryProtocolTests.swift in Sources */, + 04636BEB2E30BEC600FBCFA8 /* IntegrationTests.swift in Sources */, 04636BD22E30BE5100FBCFA8 /* MockNoiseSession.swift in Sources */, 04636BD32E30BE5100FBCFA8 /* PrivateChatE2ETests.swift in Sources */, 04636BD42E30BE5100FBCFA8 /* TestConstants.swift in Sources */, diff --git a/bitchatTests/EndToEnd/PrivateChatE2ETests.swift b/bitchatTests/EndToEnd/PrivateChatE2ETests.swift index 75a9642a..171d47b7 100644 --- a/bitchatTests/EndToEnd/PrivateChatE2ETests.swift +++ b/bitchatTests/EndToEnd/PrivateChatE2ETests.swift @@ -7,6 +7,7 @@ // import XCTest +import CryptoKit @testable import bitchat final class PrivateChatE2ETests: XCTestCase { @@ -134,7 +135,7 @@ final class PrivateChatE2ETests: XCTestCase { hopCount: 1 ) { // Send ACK back - let ackData = ack.serialize() + let ackData = ack.encode()! let ackPacket = TestHelpers.createTestPacket( type: 0x03, senderID: TestConstants.testPeerID2, @@ -149,20 +150,25 @@ final class PrivateChatE2ETests: XCTestCase { // Setup Alice to process ACK alice.packetDeliveryHandler = { packet in if packet.type == 0x03 { - if let ack = DeliveryAck.deserialize(from: packet.payload) { + if let ack = DeliveryAck.decode(from: packet.payload) { self.deliveryTracker.processDeliveryAck(ack) } } } // Track the message - let message = TestHelpers.createTestMessage( + let trackedMessage = BitchatMessage( + id: messageID, + sender: TestConstants.testNickname1, content: TestConstants.testMessage1, + timestamp: Date(), + isRelay: false, + originalSender: nil, isPrivate: true, - recipientNickname: TestConstants.testNickname2 + recipientNickname: TestConstants.testNickname2, + senderPeerID: TestConstants.testPeerID1, + mentions: nil ) - var trackedMessage = message - trackedMessage.id = messageID deliveryTracker.trackMessage( trackedMessage, @@ -187,8 +193,8 @@ final class PrivateChatE2ETests: XCTestCase { let messageID = UUID().uuidString let expectation = XCTestExpectation(description: "Delivery failed due to timeout") - // Use shorter timeout for testing - let shortTimeoutTracker = DeliveryTracker() + // Use shared instance (can't create new one due to private init) + let shortTimeoutTracker = DeliveryTracker.shared let cancellable = shortTimeoutTracker.deliveryStatusUpdated.sink { update in if update.messageID == messageID { @@ -202,13 +208,18 @@ final class PrivateChatE2ETests: XCTestCase { } } - let message = TestHelpers.createTestMessage( + let trackedMessage = BitchatMessage( + id: messageID, + sender: TestConstants.testNickname1, content: TestConstants.testMessage1, + timestamp: Date(), + isRelay: false, + originalSender: nil, isPrivate: true, - recipientNickname: TestConstants.testNickname2 + recipientNickname: TestConstants.testNickname2, + senderPeerID: TestConstants.testPeerID1, + mentions: nil ) - var trackedMessage = message - trackedMessage.id = messageID // Track with short timeout (will use default 30s for private messages) shortTimeoutTracker.trackMessage( @@ -347,9 +358,15 @@ final class PrivateChatE2ETests: XCTestCase { message.isPrivate { do { let encrypted = try aliceManager.encrypt(packet.payload, for: TestConstants.testPeerID2) - var encryptedPacket = packet - encryptedPacket.type = 0x02 // Encrypted message type - encryptedPacket.payload = encrypted + let encryptedPacket = BitchatPacket( + type: 0x02, // Encrypted message type + senderID: packet.senderID, + recipientID: packet.recipientID, + timestamp: packet.timestamp, + payload: encrypted, + signature: packet.signature, + ttl: packet.ttl + ) self.bob.simulateIncomingPacket(encryptedPacket) } catch { XCTFail("Encryption failed: \(error)") @@ -527,7 +544,7 @@ final class PrivateChatE2ETests: XCTestCase { myNickname: TestConstants.testNickname2, hopCount: 1 ) { - let ackData = ack.serialize() + let ackData = ack.encode()! let ackPacket = TestHelpers.createTestPacket( type: 0x03, senderID: TestConstants.testPeerID2, @@ -548,8 +565,8 @@ final class PrivateChatE2ETests: XCTestCase { private func createMockService(peerID: String, nickname: String) -> MockBluetoothMeshService { let service = MockBluetoothMeshService() - service.peerID = peerID - service.nickname = nickname + service.myPeerID = peerID + service.mockNickname = nickname return service } diff --git a/bitchatTests/EndToEnd/PublicChatE2ETests.swift b/bitchatTests/EndToEnd/PublicChatE2ETests.swift index 99caf1e6..c1994d50 100644 --- a/bitchatTests/EndToEnd/PublicChatE2ETests.swift +++ b/bitchatTests/EndToEnd/PublicChatE2ETests.swift @@ -101,14 +101,29 @@ final class PublicChatE2ETests: XCTestCase { message.sender == TestConstants.testNickname1 { // Create relay message - var relayMessage = message - relayMessage.isRelay = true - relayMessage.originalSender = message.sender + let relayMessage = BitchatMessage( + id: message.id, + sender: message.sender, + content: message.content, + timestamp: message.timestamp, + isRelay: true, + originalSender: message.sender, + isPrivate: message.isPrivate, + recipientNickname: message.recipientNickname, + senderPeerID: message.senderPeerID, + mentions: message.mentions + ) if let relayPayload = relayMessage.toBinaryPayload() { - var relayPacket = packet - relayPacket.payload = relayPayload - relayPacket.ttl = packet.ttl - 1 + let relayPacket = BitchatPacket( + type: packet.type, + senderID: packet.senderID, + recipientID: packet.recipientID, + timestamp: packet.timestamp, + payload: relayPayload, + signature: packet.signature, + ttl: packet.ttl - 1 + ) // Simulate relay to Charlie self.charlie.simulateIncomingPacket(relayPacket) @@ -394,8 +409,8 @@ final class PublicChatE2ETests: XCTestCase { private func createMockService(peerID: String, nickname: String) -> MockBluetoothMeshService { let service = MockBluetoothMeshService() - service.peerID = peerID - service.nickname = nickname + service.myPeerID = peerID + service.mockNickname = nickname return service } @@ -414,17 +429,29 @@ final class PublicChatE2ETests: XCTestCase { guard message.senderPeerID != node.peerID else { return } // Create relay message - var relayMessage = message - if !relayMessage.isRelay { - relayMessage.isRelay = true - relayMessage.originalSender = message.sender - } + let relayMessage = BitchatMessage( + id: message.id, + sender: message.sender, + content: message.content, + timestamp: message.timestamp, + isRelay: true, + originalSender: message.isRelay ? message.originalSender : message.sender, + isPrivate: message.isPrivate, + recipientNickname: message.recipientNickname, + senderPeerID: message.senderPeerID, + mentions: message.mentions + ) if let relayPayload = relayMessage.toBinaryPayload() { - var relayPacket = packet - relayPacket.payload = relayPayload - relayPacket.ttl = packet.ttl - 1 - relayPacket.senderID = node.peerID.data(using: .utf8)! + let relayPacket = BitchatPacket( + type: packet.type, + senderID: node.peerID.data(using: .utf8)!, + recipientID: packet.recipientID, + timestamp: packet.timestamp, + payload: relayPayload, + signature: packet.signature, + ttl: packet.ttl - 1 + ) // Relay to next hops for nextHop in nextHops { diff --git a/bitchatTests/Integration/IntegrationTests.swift b/bitchatTests/Integration/IntegrationTests.swift index 99eafa35..dd129963 100644 --- a/bitchatTests/Integration/IntegrationTests.swift +++ b/bitchatTests/Integration/IntegrationTests.swift @@ -7,6 +7,7 @@ // import XCTest +import CryptoKit @testable import bitchat final class IntegrationTests: XCTestCase { @@ -40,7 +41,7 @@ final class IntegrationTests: XCTestCase { var messageMatrix: [String: Set] = [:] // Each node should receive messages from all others - for (senderName, sender) in nodes { + for (senderName, _) in nodes { messageMatrix[senderName] = [] for (receiverName, receiver) in nodes where receiverName != senderName { @@ -106,7 +107,7 @@ final class IntegrationTests: XCTestCase { connect("Charlie", "David") let expectation = XCTestExpectation(description: "Partitions merge and communicate") - var messagesBeforeMerge = 0 + let messagesBeforeMerge = 0 var messagesAfterMerge = 0 // Monitor cross-partition messages @@ -189,8 +190,15 @@ final class IntegrationTests: XCTestCase { } else if packet.type == 0x02 { // Would be encrypted // Simulate encryption if let encrypted = try? self.noiseManagers["Alice"]!.encrypt(packet.payload, for: TestConstants.testPeerID2) { - var encPacket = packet - encPacket.payload = encrypted + let encPacket = BitchatPacket( + type: packet.type, + senderID: packet.senderID, + recipientID: packet.recipientID, + timestamp: packet.timestamp, + payload: encrypted, + signature: packet.signature, + ttl: packet.ttl + ) self.nodes["Bob"]!.simulateIncomingPacket(encPacket) } } @@ -403,9 +411,15 @@ final class IntegrationTests: XCTestCase { message.isPrivate && packet.recipientID != nil { // Encrypt private messages if let encrypted = try? self.noiseManagers["Alice"]!.encrypt(packet.payload, for: TestConstants.testPeerID2) { - var encPacket = packet - encPacket.type = 0x02 - encPacket.payload = encrypted + let encPacket = BitchatPacket( + type: 0x02, + senderID: packet.senderID, + recipientID: packet.recipientID, + timestamp: packet.timestamp, + payload: encrypted, + signature: packet.signature, + ttl: packet.ttl + ) self.nodes["Bob"]!.simulateIncomingPacket(encPacket) } } @@ -451,8 +465,8 @@ final class IntegrationTests: XCTestCase { private func createNode(_ name: String, peerID: String) { let node = MockBluetoothMeshService() - node.peerID = peerID - node.nickname = name + node.myPeerID = peerID + node.mockNickname = name nodes[name] = node // Create Noise manager @@ -490,16 +504,29 @@ final class IntegrationTests: XCTestCase { if let message = BitchatMessage.fromBinaryPayload(packet.payload) { guard message.senderPeerID != node.peerID else { return } - var relayMessage = message - if !relayMessage.isRelay { - relayMessage.isRelay = true - relayMessage.originalSender = message.sender - } + let relayMessage = BitchatMessage( + id: message.id, + sender: message.sender, + content: message.content, + timestamp: message.timestamp, + isRelay: true, + originalSender: message.isRelay ? message.originalSender : message.sender, + isPrivate: message.isPrivate, + recipientNickname: message.recipientNickname, + senderPeerID: message.senderPeerID, + mentions: message.mentions + ) if let relayPayload = relayMessage.toBinaryPayload() { - var relayPacket = packet - relayPacket.payload = relayPayload - relayPacket.ttl = packet.ttl - 1 + let relayPacket = BitchatPacket( + type: packet.type, + senderID: packet.senderID, + recipientID: packet.recipientID, + timestamp: packet.timestamp, + payload: relayPayload, + signature: packet.signature, + ttl: packet.ttl - 1 + ) for hop in nextHops { self.nodes[hop]?.simulateIncomingPacket(relayPacket) diff --git a/bitchatTests/Mocks/MockBluetoothMeshService.swift b/bitchatTests/Mocks/MockBluetoothMeshService.swift index 6a98c7d5..b2ec7bbf 100644 --- a/bitchatTests/Mocks/MockBluetoothMeshService.swift +++ b/bitchatTests/Mocks/MockBluetoothMeshService.swift @@ -17,44 +17,58 @@ class MockBluetoothMeshService: BluetoothMeshService { var messageDeliveryHandler: ((BitchatMessage) -> Void)? var packetDeliveryHandler: ((BitchatPacket) -> Void)? + // Override these properties + var mockNickname: String = "MockUser" + + override var myPeerID: String { + didSet { + // Update when changed + } + } + + var nickname: String { + return mockNickname + } + + var peerID: String { + return myPeerID + } + override init() { super.init() + self.myPeerID = "MOCK1234" } func simulateConnectedPeer(_ peerID: String) { connectedPeers.insert(peerID) - delegate?.bluetoothMeshService(self, didConnectToPeer: peerID, peerInfo: PeerInfo( - mcPeerID: MCPeerID(displayName: peerID), - peerID: peerID, - nickname: "Test User", - publicKey: nil, - capabilities: PeerCapabilities(supportedProtocolVersions: [1]) - )) + delegate?.didConnectToPeer(peerID) + delegate?.didUpdatePeerList(Array(connectedPeers)) } func simulateDisconnectedPeer(_ peerID: String) { connectedPeers.remove(peerID) - delegate?.bluetoothMeshService(self, didDisconnectFromPeer: peerID) + delegate?.didDisconnectFromPeer(peerID) + delegate?.didUpdatePeerList(Array(connectedPeers)) } override func sendMessage(_ content: String, mentions: [String], to room: String? = nil, messageID: String? = nil, timestamp: Date? = nil) { let message = BitchatMessage( id: messageID ?? UUID().uuidString, - sender: nickname, + sender: mockNickname, content: content, timestamp: timestamp ?? Date(), isRelay: false, originalSender: nil, isPrivate: false, recipientNickname: nil, - senderPeerID: peerID, + senderPeerID: myPeerID, mentions: mentions.isEmpty ? nil : mentions ) if let payload = message.toBinaryPayload() { let packet = BitchatPacket( type: 0x01, - senderID: peerID.data(using: .utf8)!, + senderID: myPeerID.data(using: .utf8)!, recipientID: nil, timestamp: UInt64(Date().timeIntervalSince1970 * 1000), payload: payload, @@ -67,7 +81,7 @@ class MockBluetoothMeshService: BluetoothMeshService { // Simulate local echo DispatchQueue.main.async { [weak self] in - self?.delegate?.bluetoothMeshService(self!, didReceiveMessage: message) + self?.delegate?.didReceiveMessage(message) } // Call delivery handler if set @@ -78,21 +92,21 @@ class MockBluetoothMeshService: BluetoothMeshService { override func sendPrivateMessage(_ content: String, to recipientPeerID: String, recipientNickname: String, messageID: String? = nil) { let message = BitchatMessage( id: messageID ?? UUID().uuidString, - sender: nickname, + sender: mockNickname, content: content, timestamp: Date(), isRelay: false, originalSender: nil, isPrivate: true, recipientNickname: recipientNickname, - senderPeerID: peerID, + senderPeerID: myPeerID, mentions: nil ) if let payload = message.toBinaryPayload() { let packet = BitchatPacket( type: 0x01, - senderID: peerID.data(using: .utf8)!, + senderID: myPeerID.data(using: .utf8)!, recipientID: recipientPeerID.data(using: .utf8)!, timestamp: UInt64(Date().timeIntervalSince1970 * 1000), payload: payload, @@ -105,7 +119,7 @@ class MockBluetoothMeshService: BluetoothMeshService { // Simulate local echo DispatchQueue.main.async { [weak self] in - self?.delegate?.bluetoothMeshService(self!, didReceiveMessage: message) + self?.delegate?.didReceiveMessage(message) } // Call delivery handler if set @@ -114,18 +128,18 @@ class MockBluetoothMeshService: BluetoothMeshService { } func simulateIncomingMessage(_ message: BitchatMessage) { - delegate?.bluetoothMeshService(self, didReceiveMessage: message) + delegate?.didReceiveMessage(message) } func simulateIncomingPacket(_ packet: BitchatPacket) { // Process through the actual handling logic if let message = BitchatMessage.fromBinaryPayload(packet.payload) { - delegate?.bluetoothMeshService(self, didReceiveMessage: message) + delegate?.didReceiveMessage(message) } packetDeliveryHandler?(packet) } - override func getConnectedPeers() -> [String] { + func getConnectedPeers() -> [String] { return Array(connectedPeers) } } \ No newline at end of file diff --git a/bitchatTests/Noise/NoiseProtocolTests.swift b/bitchatTests/Noise/NoiseProtocolTests.swift index 2d9124fe..8b6d3b68 100644 --- a/bitchatTests/Noise/NoiseProtocolTests.swift +++ b/bitchatTests/Noise/NoiseProtocolTests.swift @@ -84,13 +84,13 @@ final class NoiseProtocolTests: XCTestCase { ) // Cannot process message before starting handshake - XCTAssertThrows(try aliceSession.processHandshakeMessage(Data())) + XCTAssertThrowsError(try aliceSession.processHandshakeMessage(Data())) // Start handshake _ = try aliceSession.startHandshake() // Cannot start handshake twice - XCTAssertThrows(try aliceSession.startHandshake()) + XCTAssertThrowsError(try aliceSession.startHandshake()) } // MARK: - Encryption/Decryption Tests @@ -150,8 +150,8 @@ final class NoiseProtocolTests: XCTestCase { let plaintext = "test".data(using: .utf8)! // Should throw when not established - XCTAssertThrows(try aliceSession.encrypt(plaintext)) - XCTAssertThrows(try aliceSession.decrypt(plaintext)) + XCTAssertThrowsError(try aliceSession.encrypt(plaintext)) + XCTAssertThrowsError(try aliceSession.decrypt(plaintext)) } // MARK: - Session Manager Tests @@ -255,7 +255,7 @@ final class NoiseProtocolTests: XCTestCase { ciphertext[ciphertext.count / 2] ^= 0xFF // Decryption should fail - XCTAssertThrows(try bobSession.decrypt(ciphertext)) + XCTAssertThrowsError(try bobSession.decrypt(ciphertext)) } func testReplayPrevention() throws { @@ -268,7 +268,7 @@ final class NoiseProtocolTests: XCTestCase { _ = try bobSession.decrypt(ciphertext) // Replaying the same ciphertext should fail - XCTAssertThrows(try bobSession.decrypt(ciphertext)) + XCTAssertThrowsError(try bobSession.decrypt(ciphertext)) } func testSessionIsolation() throws { @@ -288,7 +288,7 @@ final class NoiseProtocolTests: XCTestCase { let ciphertext1 = try aliceSession1.encrypt(plaintext) // Should not be able to decrypt with session 2 - XCTAssertThrows(try bobSession2.decrypt(ciphertext1)) + XCTAssertThrowsError(try bobSession2.decrypt(ciphertext1)) // But should work with correct session let decrypted = try bobSession1.decrypt(ciphertext1) diff --git a/bitchatTests/Protocol/BinaryProtocolTests.swift b/bitchatTests/Protocol/BinaryProtocolTests.swift index 43a75509..a087b3e6 100644 --- a/bitchatTests/Protocol/BinaryProtocolTests.swift +++ b/bitchatTests/Protocol/BinaryProtocolTests.swift @@ -58,8 +58,9 @@ final class BinaryProtocolTests: XCTestCase { } func testPacketWithSignature() throws { - var packet = TestHelpers.createTestPacket() - packet.signature = TestConstants.testSignature + let packet = TestHelpers.createTestPacket( + signature: TestConstants.testSignature + ) // Encode and decode guard let encodedData = BinaryProtocol.encode(packet), @@ -208,9 +209,18 @@ final class BinaryProtocolTests: XCTestCase { } func testRelayMessageEncoding() throws { - var message = TestHelpers.createTestMessage() - message.isRelay = true - message.originalSender = TestConstants.testNickname3 + let message = BitchatMessage( + id: UUID().uuidString, + sender: TestConstants.testNickname1, + content: TestConstants.testMessage1, + timestamp: Date(), + isRelay: true, + originalSender: TestConstants.testNickname3, + isPrivate: false, + recipientNickname: nil, + senderPeerID: TestConstants.testPeerID1, + mentions: nil + ) guard let payload = message.toBinaryPayload(), let decodedMessage = BitchatMessage.fromBinaryPayload(payload) else { @@ -234,7 +244,7 @@ final class BinaryProtocolTests: XCTestCase { XCTAssertNil(BinaryProtocol.decode(random)) // Corrupted header - var packet = TestHelpers.createTestPacket() + let packet = TestHelpers.createTestPacket() guard var encoded = BinaryProtocol.encode(packet) else { XCTFail("Failed to encode test packet") return @@ -275,17 +285,8 @@ final class BinaryProtocolTests: XCTestCase { // MARK: - Protocol Version Tests func testProtocolVersionHandling() throws { - // Test with supported version - let packet = BitchatPacket( - version: 1, - type: 0x01, - senderID: TestConstants.testPeerID1.data(using: .utf8)!, - recipientID: nil, - timestamp: UInt64(Date().timeIntervalSince1970 * 1000), - payload: "test".data(using: .utf8)!, - signature: nil, - ttl: 3 - ) + // Test with supported version (version is always 1 in init) + let packet = TestHelpers.createTestPacket() guard let encoded = BinaryProtocol.encode(packet), let decoded = BinaryProtocol.decode(encoded) else { @@ -297,15 +298,17 @@ final class BinaryProtocolTests: XCTestCase { } func testUnsupportedProtocolVersion() throws { - // Create packet with unsupported version - var packet = TestHelpers.createTestPacket() - packet.version = 99 // Unsupported version + // Create packet data with unsupported version + let packet = TestHelpers.createTestPacket() - guard let encoded = BinaryProtocol.encode(packet) else { + guard var encoded = BinaryProtocol.encode(packet) else { XCTFail("Failed to encode packet") return } + // Manually change version byte to unsupported value + encoded[0] = 99 // Unsupported version + // Should fail to decode XCTAssertNil(BinaryProtocol.decode(encoded)) } diff --git a/bitchatTests/TestUtilities/TestConstants.swift b/bitchatTests/TestUtilities/TestConstants.swift index 4d5a8719..be4670ab 100644 --- a/bitchatTests/TestUtilities/TestConstants.swift +++ b/bitchatTests/TestUtilities/TestConstants.swift @@ -28,6 +28,5 @@ struct TestConstants { static let testMessage3 = "This is a test message" static let testLongMessage = String(repeating: "This is a long message. ", count: 100) - static let testRoomID = "test-room" static let testSignature = Data(repeating: 0xAB, count: 64) -} \ No newline at end of file +} diff --git a/bitchatTests/TestUtilities/TestHelpers.swift b/bitchatTests/TestUtilities/TestHelpers.swift index 32cc59dc..41aa4e2d 100644 --- a/bitchatTests/TestUtilities/TestHelpers.swift +++ b/bitchatTests/TestUtilities/TestHelpers.swift @@ -20,14 +20,9 @@ class TestHelpers { return (privateKey, publicKey) } - static func generateTestIdentity(peerID: String, nickname: String) -> UserProfile { + static func generateTestIdentity(peerID: String, nickname: String) -> (peerID: String, nickname: String, privateKey: Curve25519.KeyAgreement.PrivateKey, publicKey: Curve25519.KeyAgreement.PublicKey) { let (privateKey, publicKey) = generateTestKeyPair() - return UserProfile( - nickname: nickname, - peerID: peerID, - publicKey: publicKey.rawRepresentation, - privateKey: privateKey.rawRepresentation - ) + return (peerID: peerID, nickname: nickname, privateKey: privateKey, publicKey: publicKey) } // MARK: - Message Creation @@ -59,6 +54,7 @@ class TestHelpers { senderID: String = TestConstants.testPeerID1, recipientID: String? = nil, payload: Data = "test payload".data(using: .utf8)!, + signature: Data? = nil, ttl: UInt8 = 3 ) -> BitchatPacket { return BitchatPacket( @@ -67,7 +63,7 @@ class TestHelpers { recipientID: recipientID?.data(using: .utf8), timestamp: UInt64(Date().timeIntervalSince1970 * 1000), payload: payload, - signature: nil, + signature: signature, ttl: ttl ) }