gigastt-core 2.18.0

Core inference engine for gigastt — GigaAM v3 ONNX Runtime, model management, quantization
Documentation
use super::*;

#[test]
fn test_protocol_version_constant() {
    assert_eq!(PROTOCOL_VERSION, "1.0");
}

#[test]
fn test_ready_serialization_includes_version() {
    let msg = ServerMessage::Ready {
        model: "test-model".into(),
        sample_rate: 48000,
        version: PROTOCOL_VERSION.into(),
        supported_rates: vec![],
        diarization: false,
        min_protocol_version: Some(PROTOCOL_VERSION.into()),
        max_session_secs: 3600,
        idle_timeout_secs: 300,
    };
    let json = serde_json::to_string(&msg).unwrap();
    let v: serde_json::Value = serde_json::from_str(&json).unwrap();
    assert_eq!(v["type"], "ready");
    assert_eq!(v["version"], "1.0");
    assert_eq!(v["model"], "test-model");
    assert_eq!(v["sample_rate"], 48000);
    assert_eq!(v["min_protocol_version"], "1.0");
}

#[test]
fn test_ready_session_limits_always_serialized() {
    // The session caps are plain `u64` fields (no skip attr): they must be
    // present in every ready payload so clients can plan around them
    // before hitting a close frame. A zero cap serializes as `0`, not null
    // or an omitted key.
    let msg = ServerMessage::Ready {
        model: "test".into(),
        sample_rate: 48000,
        version: "1.0".into(),
        supported_rates: vec![],
        diarization: false,
        min_protocol_version: None,
        max_session_secs: 0,
        idle_timeout_secs: 42,
    };
    let v = serde_json::to_value(&msg).unwrap();
    assert_eq!(v["max_session_secs"], 0);
    assert_eq!(v["idle_timeout_secs"], 42);
}

#[test]
fn test_partial_serialization_no_version() {
    let msg = ServerMessage::Partial(crate::inference::TranscriptSegment {
        text: "hello".into(),
        timestamp: 1.0,
        words: vec![],
        is_final: false,
        speech_final: false,
        endpoint_reason: None,
        confidence: None,
    });
    let json = serde_json::to_string(&msg).unwrap();
    let v: serde_json::Value = serde_json::from_str(&json).unwrap();
    assert_eq!(v["type"], "partial");
    assert!(v.get("version").is_none());
    // Partials omit speech_final / endpoint_reason for backward-compatible wire size.
    assert!(v.get("speech_final").is_none());
    assert!(v.get("endpoint_reason").is_none());
}

#[test]
fn test_final_serialization_no_version() {
    let msg = ServerMessage::Final(crate::inference::TranscriptSegment {
        text: "hello".into(),
        timestamp: 1.0,
        words: vec![],
        is_final: true,
        speech_final: true,
        endpoint_reason: Some(crate::inference::EndpointReason::Vad),
        confidence: None,
    });
    let json = serde_json::to_string(&msg).unwrap();
    let v: serde_json::Value = serde_json::from_str(&json).unwrap();
    assert_eq!(v["type"], "final");
    assert!(v.get("version").is_none());
    assert_eq!(v["speech_final"], true);
    assert_eq!(v["endpoint_reason"], "vad");
}

#[test]
fn test_error_serialization_no_version() {
    let msg = ServerMessage::Error {
        message: "fail".into(),
        code: "err".into(),
        retry_after_ms: None,
    };
    let json = serde_json::to_string(&msg).unwrap();
    let v: serde_json::Value = serde_json::from_str(&json).unwrap();
    assert_eq!(v["type"], "error");
    assert!(v.get("version").is_none());
    assert!(
        v.get("retry_after_ms").is_none(),
        "retry_after_ms must be omitted when None"
    );
}

#[test]
fn test_error_serialization_with_retry_after() {
    let msg = ServerMessage::Error {
        message: "Server busy, try again later".into(),
        code: "timeout".into(),
        retry_after_ms: Some(30_000),
    };
    let json = serde_json::to_string(&msg).unwrap();
    let v: serde_json::Value = serde_json::from_str(&json).unwrap();
    assert_eq!(v["type"], "error");
    assert_eq!(v["code"], "timeout");
    assert_eq!(v["retry_after_ms"], 30_000);
}

#[test]
fn test_client_message_stop_deserialize() {
    let json = r#"{"type":"stop"}"#;
    let msg: ClientMessage = serde_json::from_str(json).unwrap();
    assert!(matches!(msg, ClientMessage::Stop));
}

#[test]
fn test_client_message_configure_deserialize() {
    let json = r#"{"type":"configure","sample_rate":8000}"#;
    let msg: ClientMessage = serde_json::from_str(json).unwrap();
    match msg {
        ClientMessage::Configure { sample_rate, .. } => assert_eq!(sample_rate, Some(8000)),
        _ => panic!("Expected Configure"),
    }
}

#[test]
fn test_ready_supported_rates_serialization() {
    let msg = ServerMessage::Ready {
        model: "test".into(),
        sample_rate: 48000,
        version: "1.0".into(),
        supported_rates: vec![8000, 16000, 24000, 44100, 48000],
        diarization: false,
        min_protocol_version: None,
        max_session_secs: 3600,
        idle_timeout_secs: 300,
    };
    let json = serde_json::to_string(&msg).unwrap();
    let v: serde_json::Value = serde_json::from_str(&json).unwrap();
    assert_eq!(v["supported_rates"].as_array().unwrap().len(), 5);
}

#[test]
fn test_ready_empty_supported_rates_omitted() {
    let msg = ServerMessage::Ready {
        model: "test".into(),
        sample_rate: 48000,
        version: "1.0".into(),
        supported_rates: vec![],
        diarization: false,
        min_protocol_version: None,
        max_session_secs: 3600,
        idle_timeout_secs: 300,
    };
    let json = serde_json::to_string(&msg).unwrap();
    let v: serde_json::Value = serde_json::from_str(&json).unwrap();
    assert!(v.get("supported_rates").is_none());
}

#[test]
fn test_word_info_speaker_none_omitted() {
    let word = crate::inference::WordInfo {
        word: "hello".into(),
        start: 0.0,
        end: 1.0,
        confidence: 0.9,
        speaker: None,
    };
    let json = serde_json::to_string(&word).unwrap();
    let v: serde_json::Value = serde_json::from_str(&json).unwrap();
    assert!(v.get("speaker").is_none());
}

#[test]
fn test_word_info_speaker_present() {
    let word = crate::inference::WordInfo {
        word: "hello".into(),
        start: 0.0,
        end: 1.0,
        confidence: 0.9,
        speaker: Some(2),
    };
    let json = serde_json::to_string(&word).unwrap();
    let v: serde_json::Value = serde_json::from_str(&json).unwrap();
    assert_eq!(v["speaker"], 2);
}

#[test]
fn test_configure_diarization_deserialize() {
    let json = r#"{"type":"configure","diarization":true}"#;
    let msg: ClientMessage = serde_json::from_str(json).unwrap();
    match msg {
        ClientMessage::Configure { diarization, .. } => assert_eq!(diarization, Some(true)),
        _ => panic!("Expected Configure"),
    }
}

#[test]
fn test_configure_sample_rate_only() {
    let json = r#"{"type":"configure","sample_rate":8000}"#;
    let msg: ClientMessage = serde_json::from_str(json).unwrap();
    match msg {
        ClientMessage::Configure {
            sample_rate,
            diarization,
            ..
        } => {
            assert_eq!(sample_rate, Some(8000));
            assert_eq!(diarization, None);
        }
        _ => panic!("Expected Configure"),
    }
}

#[test]
fn test_configure_protocol_version_deserialize() {
    let json = r#"{"type":"configure","protocol_version":"1.0"}"#;
    let msg: ClientMessage = serde_json::from_str(json).unwrap();
    match msg {
        ClientMessage::Configure {
            protocol_version, ..
        } => assert_eq!(protocol_version, Some("1.0".into())),
        _ => panic!("Expected Configure"),
    }
}

#[test]
fn test_configure_protocol_version_absent() {
    let json = r#"{"type":"configure","sample_rate":16000}"#;
    let msg: ClientMessage = serde_json::from_str(json).unwrap();
    match msg {
        ClientMessage::Configure {
            protocol_version, ..
        } => assert_eq!(protocol_version, None),
        _ => panic!("Expected Configure"),
    }
}

#[test]
fn test_configure_punctuation_itn_deserialize() {
    let json = r#"{"type":"configure","punctuation":false,"itn":true}"#;
    let msg: ClientMessage = serde_json::from_str(json).unwrap();
    match msg {
        ClientMessage::Configure {
            punctuation, itn, ..
        } => {
            assert_eq!(punctuation, Some(false));
            assert_eq!(itn, Some(true));
        }
        _ => panic!("Expected Configure"),
    }
}

#[test]
fn test_configure_punctuation_itn_absent() {
    // Older clients omit the post-processing knobs entirely; both must
    // deserialize to None (server default) — additive backward compat.
    let json = r#"{"type":"configure","sample_rate":16000}"#;
    let msg: ClientMessage = serde_json::from_str(json).unwrap();
    match msg {
        ClientMessage::Configure {
            punctuation,
            itn,
            endpoint_mode,
            min_silence_ms,
            ..
        } => {
            assert_eq!(punctuation, None);
            assert_eq!(itn, None);
            assert_eq!(endpoint_mode, None);
            assert_eq!(min_silence_ms, None);
        }
        _ => panic!("Expected Configure"),
    }
}

#[test]
fn test_configure_endpoint_mode_and_min_silence_deserialize() {
    let json = r#"{"type":"configure","endpoint_mode":"assistant","min_silence_ms":1200}"#;
    let msg: ClientMessage = serde_json::from_str(json).unwrap();
    match msg {
        ClientMessage::Configure {
            endpoint_mode,
            min_silence_ms,
            ..
        } => {
            assert_eq!(endpoint_mode.as_deref(), Some("assistant"));
            assert_eq!(min_silence_ms, Some(1200));
        }
        _ => panic!("Expected Configure"),
    }
}

#[test]
fn test_ready_min_protocol_version_omitted_when_none() {
    let msg = ServerMessage::Ready {
        model: "test".into(),
        sample_rate: 48000,
        version: "1.0".into(),
        supported_rates: vec![],
        diarization: false,
        min_protocol_version: None,
        max_session_secs: 3600,
        idle_timeout_secs: 300,
    };
    let json = serde_json::to_string(&msg).unwrap();
    let v: serde_json::Value = serde_json::from_str(&json).unwrap();
    assert!(v.get("min_protocol_version").is_none());
}

#[test]
fn test_ready_diarization_false_omitted() {
    let msg = ServerMessage::Ready {
        model: "test".into(),
        sample_rate: 48000,
        version: "1.0".into(),
        supported_rates: vec![],
        diarization: false,
        min_protocol_version: None,
        max_session_secs: 3600,
        idle_timeout_secs: 300,
    };
    let json = serde_json::to_string(&msg).unwrap();
    let v: serde_json::Value = serde_json::from_str(&json).unwrap();
    assert!(v.get("diarization").is_none());
}