// Protocol contract for optional Opus audio transport. // // Scope: inspect the protobuf schema and generated Rust structs. // Targets: `common/proto/lesavka.proto`. // Why: Opus must be introduced as an explicit payload codec on Lesavka's // bundled gRPC transport, not as a silent SIP/RTP side channel. use lesavka_common::audio_transport::{AudioTransportProfile, bundle_audio_profile}; use lesavka_common::lesavka::{AudioEncoding, AudioPacket, UpstreamMediaBundle}; const PROTO: &str = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), "/common/proto/lesavka.proto" )); #[test] fn proto_exposes_opus_without_adding_sip_or_rtp_transport() { for expected in [ "enum AudioEncoding", "PCM_S16LE = 1", "OPUS = 2", "AudioEncoding encoding = 9", "uint32 sample_rate = 10", "uint32 channels = 11", "uint32 frame_duration_us = 12", "AudioEncoding audio_encoding = 12", "rpc StreamWebcamMedia(stream UpstreamMediaBundle)", ] { assert!( PROTO.contains(expected), "proto should preserve Opus transport marker {expected}" ); } for forbidden in ["SIP", "RTP", "sipp", "rtpmap"] { assert!( !PROTO.contains(forbidden), "Opus testing should stay on Lesavka bundled gRPC transport, not {forbidden}" ); } } #[test] fn generated_bundle_can_describe_opus_audio_payloads() { let packet = AudioPacket { encoding: AudioEncoding::Opus as i32, sample_rate: 48_000, channels: 2, frame_duration_us: 20_000, data: vec![0x41; 160], ..AudioPacket::default() }; let bundle = UpstreamMediaBundle { audio_encoding: AudioEncoding::Opus as i32, audio_sample_rate: 48_000, audio_channels: 2, audio: vec![packet], ..UpstreamMediaBundle::default() }; assert_eq!( bundle_audio_profile(&bundle), AudioTransportProfile::opus_voice() ); }