native macOS codings agent orchestrator prowl.onev.cat
Something went wrong. Try again.
10 kB · 221 lines
Swift
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222import Foundationimport Testing
@testable import Prowl
struct MirrorProtocolTests { @Test func scrollMessagesKeepRequestAndLeaseAcrossJSONWire() throws { let requestID = UUID() let lease = UUID() let messages: [MirrorMessage] = [ .scroll(.init(requestID: requestID, direction: .upward, subscriptionID: lease)), .scroll(.init(requestID: requestID, direction: .downward, subscriptionID: lease)), .scrollResult(.init(requestID: requestID, sequence: 42, subscriptionID: lease)), .failure(.init(error: "SCROLL_BUSY", subscriptionID: lease, requestID: requestID)), ] for message in messages { let wire = try MirrorWire.encode(message) #expect(wire[4] == 0) let decoded = try MirrorWire.decode(wire.dropFirst(4)) #expect(decoded.kind == message.kind) #expect(decoded.scrollRequestID == requestID) #expect(decoded.subscriptionID == lease) #expect(decoded.scrollDirection == message.scrollDirection) #expect(decoded.sequence == message.sequence) } let legacyFailure = try MirrorWire.decode(Data([0]) + Data(#"{"failure":{"_0":{"error":"old host"}}}"#.utf8)) #expect(legacyFailure.error == "old host") #expect(legacyFailure.scrollRequestID == nil) let invalid = """ {"scroll":{"_0":{"requestID":"\(requestID)","direction":"sideways","subscriptionID":"\(lease)"}}} """ #expect(throws: (any Error).self) { try MirrorWire.decode(Data([0]) + Data(invalid.utf8)) } }
@Test func viewportControlPreservesNilAndEmptyWithoutChangingBinaryFrames() throws { let lease = UUID() for text in [nil, "", "earlier\n屏幕"] as [String?] { let message = MirrorMessage.viewport(.init(text: text, sequence: 9, subscriptionID: lease)) let encoded = try MirrorWire.encode(message) #expect(encoded[4] == 0) let decoded = try MirrorWire.decode(encoded.dropFirst(4)) #expect(decoded.kind == .viewport) #expect(decoded.viewportText == text) #expect(decoded.sequence == 9) #expect(decoded.subscriptionID == lease) } let frame = MirrorFrame(columns: 80, rows: 24, bytes: Data("styled active screen".utf8)) var overlay = frame overlay.viewportText = "earlier" #expect( try MirrorWire.encode(.frame(.init(frame: frame, sequence: 9, subscriptionID: lease))) == MirrorWire.encode(.frame(.init(frame: overlay, sequence: 9, subscriptionID: lease)))) let legacy = MirrorMessage.subscribe(.init(paneID: UUID(), representation: .terminal, intent: .ifFree)) let decoded = try MirrorWire.decode(MirrorWire.encode(legacy).dropFirst(4)) #expect(decoded.includeViewportText == nil) var gate = MirrorFrameGate() #expect(gate.offer(frame) == 1) try gate.acknowledge(1) #expect(gate.offer(overlay) == 2) try gate.acknowledge(2) overlay.viewportText = "" #expect(gate.offer(overlay) == 3) try gate.acknowledge(3) #expect(gate.offer(frame) == 4) }
@Test func scrollStatePreservesUnknownAndLeavesBinaryRepresentationsUnchanged() throws { let lease = UUID() for bounds in [MirrorScrollBounds(), .init(atTop: true, atBottom: false), .init(atTop: false, atBottom: true)] { let message = MirrorMessage.scrollState( .init( atTop: bounds.atTop, atBottom: bounds.atBottom, sequence: 7, subscriptionID: lease)) let wire = try MirrorWire.encode(message) let decoded = try MirrorWire.decode(wire.dropFirst(4)) #expect(decoded.kind == .scrollState) #expect(decoded.subscriptionID == lease) #expect(decoded.sequence == 7) #expect(decoded.scrollBounds == bounds) } let frame = MirrorFrame(columns: 80, rows: 24, bytes: Data("screen".utf8)) var bounded = frame bounded.scrollBounds = .init(atTop: false, atBottom: true) #expect( try MirrorWire.encode(.frame(.init(frame: frame, sequence: 1, subscriptionID: lease))) == MirrorWire.encode(.frame(.init(frame: bounded, sequence: 1, subscriptionID: lease)))) let text = MirrorMessage.TextFramePayload(sequence: 1, text: "screen", subscriptionID: lease) var boundedText = text boundedText.scrollBounds = bounded.scrollBounds #expect(try MirrorWire.encode(.textFrame(text)) == MirrorWire.encode(.textFrame(boundedText))) let legacy = MirrorMessage.subscribe(.init(paneID: UUID(), representation: .text, intent: .ifFree)) #expect(try MirrorWire.decode(MirrorWire.encode(legacy).dropFirst(4)).includeScrollState == nil) var gate = MirrorTextFrameGate() #expect(gate.offer("screen") == 1) try gate.acknowledge(1) #expect(gate.offer("screen", scrollBounds: bounded.scrollBounds) == 2) }
@Test func refreshPreservesBackpressureAndSequence() throws { var gate = MirrorTextFrameGate() #expect(gate.offer("unchanged") == 1) gate.requestRefresh() #expect(gate.offer("unchanged") == nil) try gate.acknowledge(1) #expect(gate.offer("unchanged") == 2) try gate.acknowledge(2) #expect(gate.offer("unchanged") == nil) }
@Test func binaryTextFrameHasStableVectorAndRejectsLegacyJSON() throws { let id = UUID(uuidString: "00000000-0000-0000-0000-000000000001")! let message = MirrorMessage.textFrame(.init(sequence: 1, text: "A", subscriptionID: id)) let wire = try MirrorWire.encode(message) var expected: [UInt8] = [0, 0, 0, 35, 2] expected += Array(repeating: 0, count: 15) expected += [1] expected += Array(repeating: 0, count: 7) expected += [1] expected += Array(repeating: 0, count: 9) expected += [65] #expect(Array(wire) == expected) #expect(try MirrorWire.decode(wire.dropFirst(4)).text == "A") #expect(throws: (any Error).self) { try MirrorWire.decode(Data(#"{"version":1,"kind":"list"}"#.utf8)) } #expect(throws: (any Error).self) { try MirrorWire.decode(Data([0]) + Data(#"{"subscribed":{}}"#.utf8)) } }
@Test func textGatePreservesEmptyReplacementAndRejectsStaleAcknowledgements() throws { var gate = MirrorTextFrameGate() #expect(gate.offer("thinking") == 1) #expect(gate.offer("") == nil) #expect(throws: MirrorProtocolError.self) { try gate.acknowledge(99) } try gate.acknowledge(1) #expect(gate.offer("") == 2) try gate.acknowledge(2) #expect(gate.offer("") == nil) #expect(gate.offer("conclusion") == 3) }
@Test func paneLabelsPreserveOptionalMetadata() throws { let pane = MirrorPaneDescriptor( id: UUID(), title: "VKChannel · Codex", directory: "/projects/VKChannel", busy: true, projectName: "VKChannel", subtitle: "Codex · master · Pane 2") let wire = try MirrorWire.encode( .panes(.init(panes: [pane], capabilities: [], hostRunID: UUID()))) #expect(try MirrorWire.decode(wire.dropFirst(4)).panes == [pane]) let minimal = Data( "{\"id\":\"\(pane.id)\",\"title\":\"master\",\"directory\":\"/projects/VKChannel\",\"busy\":false}" .utf8) let decoded = try JSONDecoder().decode(MirrorPaneDescriptor.self, from: minimal) #expect(decoded.projectName == nil) #expect(decoded.subtitle == nil) #expect(decoded.title == "master") }
@Test func frameRoundTripKeepsControlBytesAndUnicode() throws { let frame = MirrorFrame(columns: 81, rows: 25, bytes: Data("\u{1b}[2J思考中\r结论\u{1b}[H".utf8)) let wire = try MirrorWire.encode( .frame(.init(frame: frame, sequence: 1, subscriptionID: UUID()))) #expect(try MirrorWire.length(wire.prefix(4)) == wire.count - 4) #expect(try MirrorWire.decode(wire.dropFirst(4)).frame == frame) }
@Test func invalidLengthsAndVersionsAreRejectedBeforeDispatch() { #expect(throws: MirrorProtocolError.self) { try MirrorWire.length(Data([0, 0, 0])) } #expect(throws: MirrorProtocolError.self) { try MirrorWire.length(Data([0, 0, 0, 0])) } #expect(throws: MirrorProtocolError.self) { try MirrorWire.length(Data([255, 255, 255, 255])) } #expect(throws: MirrorProtocolError.self) { try MirrorWire.decode(Data(#"{"version":3,"kind":"list"}"#.utf8)) } }
@Test func slowConsumerHasOneOutstandingFrameAndReceivesLatestState() throws { var gate = MirrorFrameGate() let first = MirrorFrame(columns: 80, rows: 24, bytes: Data("thinking".utf8)) let cleared = MirrorFrame(columns: 80, rows: 24, bytes: Data()) #expect(gate.offer(first) == 1) #expect(gate.offer(cleared) == nil) #expect(throws: MirrorProtocolError.self) { try gate.acknowledge(2) } try gate.acknowledge(1) #expect(gate.offer(first) == nil) #expect(gate.offer(cleared) == 2) try gate.acknowledge(2) let resized = MirrorFrame(columns: 100, rows: 24, bytes: Data()) #expect(gate.offer(resized) == 3) }
@Test func historyPagesAreStableAndBounded() throws { let history = MirrorHistory(text: (0..<451).map(String.init).joined(separator: "\n")) let latest = try history.page(before: history.lines.count) #expect(latest.start == 251) #expect(latest.lines.first == "251") #expect(latest.lines.last == "450") let older = try history.page(before: latest.start) #expect(older.start == 51) #expect(older.lines.last == "250") #expect(try history.page(before: 0).lines.isEmpty) #expect(throws: MirrorProtocolError.self) { try history.page(before: -1) } #expect(throws: MirrorProtocolError.self) { try history.page(before: 452) } #expect(MirrorHistory(text: "changed").id != history.id) }
@Test @MainActor func malformedPairingKeysFailBeforeOpeningASocket() { for key in ["", "1234", String(repeating: "g", count: 64)] { #expect(throws: MirrorProtocolError.self) { try MirrorConnection.parameters(pairingKey: key) } } }
@Test func historyByteLimitDiscardsOnlyAnIncompleteLeadingScalar() { let tail = String(repeating: "a", count: MirrorHistory.maximumBytes - 1) let history = MirrorHistory(text: "思" + tail) #expect(history.lines == [tail]) let aligned = String(repeating: "a", count: MirrorHistory.maximumBytes - 3) #expect(MirrorHistory(text: "思" + aligned).lines == ["思" + aligned]) #expect(MirrorHistory(text: "").lines == [""]) }}