Files
openclaw/apps/shared/OpenClawMLXTTSProtocol/Tests/OpenClawMLXTTSProtocolTests/MLXTTSProtocolTests.swift
Vincent Koc 96b1be10f5 feat(macos): keep MLX TTS model resident (#104200)
* test(macos): cover MLX helper packaging

* feat(macos): define framed MLX TTS protocol

* feat(macos): keep MLX TTS model resident

* feat(macos): reuse MLX TTS helper transport

* fix(macos): preserve MLX TTS fallback lifecycle

* chore(swift): lint MLX TTS protocol sources

* fix(macos): keep MLX helper input nonblocking

* test(macos): cover forced MLX helper shutdown

* fix(macos): fall back after MLX memory eviction

* fix(macos): discard canceled MLX audio
2026-07-11 13:45:27 +08:00

76 lines
2.9 KiB
Swift

import Foundation
import OpenClawMLXTTSProtocol
import XCTest
final class MLXTTSProtocolTests: XCTestCase {
func testRequestRoundTrip() throws {
let request = MLXTTSRequest.synthesize(MLXTTSSynthesizeRequest(
id: "request-1",
text: "hello",
modelRepo: "mlx-community/Soprano-80M-bf16",
language: "en",
voice: nil))
var decoder = MLXTTSFrameDecoder()
let payloads = try decoder.append(MLXTTSFrameCodec.encode(request))
XCTAssertEqual(payloads.count, 1)
XCTAssertEqual(try MLXTTSFrameCodec.decode(MLXTTSRequest.self, payload: payloads[0]), request)
}
func testDecoderAcceptsFragmentedAndCoalescedFrames() throws {
let first = try MLXTTSFrameCodec.encode(MLXTTSRequest.cancel(id: "one"))
let second = try MLXTTSFrameCodec.encode(MLXTTSRequest.shutdown)
let combined = first + second
let split = combined.count / 2
var decoder = MLXTTSFrameDecoder()
XCTAssertTrue(try decoder.append(combined.prefix(split)).isEmpty)
let payloads = try decoder.append(combined.suffix(from: split))
XCTAssertEqual(payloads.count, 2)
XCTAssertEqual(
try MLXTTSFrameCodec.decode(MLXTTSRequest.self, payload: payloads[0]),
.cancel(id: "one"))
XCTAssertEqual(
try MLXTTSFrameCodec.decode(MLXTTSRequest.self, payload: payloads[1]),
.shutdown)
}
func testAudioEventCarriesExplicitPCMFormat() throws {
let event = MLXTTSEvent.audio(MLXTTSAudio(
id: "request-2",
sampleRate: 32000,
pcm: Data([0x00, 0x00, 0xFF, 0x7F])))
let frame = try MLXTTSFrameCodec.encode(event)
var decoder = MLXTTSFrameDecoder()
let payload = try XCTUnwrap(decoder.append(frame).first)
let decoded = try MLXTTSFrameCodec.decode(MLXTTSEvent.self, payload: payload)
XCTAssertEqual(decoded, event)
}
func testDecoderRejectsEmptyAndOversizedFrames() {
var emptyDecoder = MLXTTSFrameDecoder()
XCTAssertThrowsError(try emptyDecoder.append(Data(repeating: 0, count: 4))) { error in
XCTAssertEqual(error as? MLXTTSFrameError, .emptyFrame)
}
let oversized = UInt32(MLXTTSFrameCodec.maximumPayloadSize + 1).bigEndian
var length = oversized
let header = Data(bytes: &length, count: MemoryLayout<UInt32>.size)
var oversizedDecoder = MLXTTSFrameDecoder()
XCTAssertThrowsError(try oversizedDecoder.append(header)) { error in
XCTAssertEqual(
error as? MLXTTSFrameError,
.frameTooLarge(MLXTTSFrameCodec.maximumPayloadSize + 1))
}
}
func testCodecRejectsMalformedJSONPayload() {
XCTAssertThrowsError(
try MLXTTSFrameCodec.decode(MLXTTSRequest.self, payload: Data("not-json".utf8)))
}
}