import Foundation import WireProtocol /// Deterministic RNG for the roundtrip property test (reproducible failures: /// the seed is baked into the test; change it only with a note in the test). struct SplitMix64: RandomNumberGenerator { private var state: UInt64 init(seed: UInt64) { state = seed } mutating func next() -> UInt64 { state &+= 0x9E37_79B9_7F4A_7C15 var z = state z = (z ^ (z >> 30)) &* 0xBF58_476D_1CE4_E5B9 z = (z ^ (z >> 27)) &* 0x94D0_49BB_1331_11EB return z ^ (z >> 31) } } enum MessageGen { /// Character pool that stresses the JSON escaper: quotes, backslashes, /// C0 control bytes (ESC / CR / TAB / ^C / NUL), CJK, emoji, plain ASCII. private static let stressPool: [Character] = [ "a", "Z", "0", " ", "\"", "\\", "/", "{", "}", "\u{1B}", "\r", "\n", "\t", "\u{03}", "\u{00}", "\u{7F}", "中", "文", "終", "端", "🚀", "🧪", "é", "ß", ] static func randomString(using rng: inout some RandomNumberGenerator, maxLength: Int = 48) -> String { let length = Int.random(in: 0...maxLength, using: &rng) return String((0.. String { "/" + randomString(using: &rng, maxLength: 24) } /// Seeded UUID v4 (version nibble 4, variant 10xx) — passes SESSION_ID_RE. static func randomUUIDv4(using rng: inout some RandomNumberGenerator) -> UUID { var bytes = (0..<16).map { _ in UInt8.random(in: 0...255, using: &rng) } bytes[6] = (bytes[6] & 0x0F) | 0x40 bytes[8] = (bytes[8] & 0x3F) | 0x80 return UUID(uuid: ( bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15] )) } static func randomClientMessage(using rng: inout some RandomNumberGenerator) -> ClientMessage { switch Int.random(in: 0...4, using: &rng) { case 0: let sessionId = Bool.random(using: &rng) ? randomUUIDv4(using: &rng) : nil let cwd = Bool.random(using: &rng) ? randomAbsolutePath(using: &rng) : nil return .attach(sessionId: sessionId, cwd: cwd) case 1: return .input(data: randomString(using: &rng)) case 2: return .resize( cols: Int.random(in: 1...1000, using: &rng), rows: Int.random(in: 1...1000, using: &rng) ) case 3: let mode = Bool.random(using: &rng) ? ApproveMode.allCases.randomElement(using: &rng) : nil return .approve(mode: mode) default: return .reject } } }