test(lesavka): cover audio transport metadata paths

This commit is contained in:
Brad Stein 2026-05-19 09:47:13 -03:00
parent a85eb98be3
commit 31e19069ad
3 changed files with 195 additions and 0 deletions

View File

@ -199,6 +199,30 @@ mod tests {
UpstreamAudioCodec::PcmS16le UpstreamAudioCodec::PcmS16le
); );
}); });
temp_env::with_var(AUDIO_CODEC_ENV, Some("opus"), || {
temp_env::with_var(AUDIO_CODEC_LEGACY_ENV, Some("pcm"), || {
assert_eq!(
requested_upstream_audio_codec_from_env(),
UpstreamAudioCodec::Opus
);
});
});
temp_env::with_var(AUDIO_CODEC_ENV, None::<&str>, || {
temp_env::with_var(AUDIO_CODEC_LEGACY_ENV, Some("compressed"), || {
assert_eq!(
requested_upstream_audio_codec_from_env(),
UpstreamAudioCodec::Opus
);
});
});
temp_env::with_var(AUDIO_CODEC_ENV, Some("aac"), || {
temp_env::with_var(AUDIO_CODEC_LEGACY_ENV, Some("opus"), || {
assert_eq!(
requested_upstream_audio_codec_from_env(),
UpstreamAudioCodec::PcmS16le
);
});
});
} }
#[test] #[test]
@ -275,6 +299,47 @@ mod tests {
); );
} }
#[test]
fn packet_metadata_keeps_capture_timing_without_pcm_payload() {
let packet = AudioPacket {
pts: 987_000,
encoding: AudioEncoding::PcmS16le as i32,
sample_rate: 48_000,
channels: 2,
frame_duration_us: 20_000,
data: vec![0x11; 3_840],
..AudioPacket::default()
};
let metadata = packet_metadata(&packet);
assert_eq!(metadata.pts, 987_000);
assert_eq!(metadata.encoding, AudioEncoding::PcmS16le as i32);
assert_eq!(metadata.sample_rate, 48_000);
assert_eq!(metadata.channels, 2);
assert_eq!(metadata.frame_duration_us, 20_000);
assert!(metadata.data.is_empty());
}
#[test]
fn pending_packet_metadata_drops_oldest_when_encoder_lags() {
let mut pending = VecDeque::new();
for pts in 100..120 {
push_pending_packet(
&mut pending,
AudioPacket {
pts,
..AudioPacket::default()
},
);
}
assert_eq!(pending.len(), MAX_PENDING_OPUS_METADATA);
assert_eq!(pending.front().expect("oldest retained").pts, 104);
assert_eq!(pending.back().expect("newest retained").pts, 119);
}
fn sine_pcm_packet(freq_hz: f32, len: usize) -> Vec<u8> { fn sine_pcm_packet(freq_hz: f32, len: usize) -> Vec<u8> {
let mut out = Vec::with_capacity(len); let mut out = Vec::with_capacity(len);
let frames = len / 4; let frames = len / 4;

View File

@ -195,6 +195,47 @@ mod tests {
); );
} }
#[test]
fn packet_metadata_keeps_timing_and_clears_payload() {
let packet = AudioPacket {
pts: 123_000,
encoding: AudioEncoding::Opus as i32,
sample_rate: 48_000,
channels: 2,
frame_duration_us: 20_000,
data: vec![1, 2, 3, 4],
..AudioPacket::default()
};
let metadata = packet_metadata(&packet);
assert_eq!(metadata.pts, 123_000);
assert_eq!(metadata.encoding, AudioEncoding::Opus as i32);
assert_eq!(metadata.sample_rate, 48_000);
assert_eq!(metadata.channels, 2);
assert_eq!(metadata.frame_duration_us, 20_000);
assert!(metadata.data.is_empty());
}
#[test]
fn pending_packet_metadata_is_bounded_to_recent_frames() {
let mut pending = VecDeque::new();
for pts in 0..20 {
push_pending_packet(
&mut pending,
AudioPacket {
pts,
..AudioPacket::default()
},
);
}
assert_eq!(pending.len(), MAX_PENDING_OPUS_METADATA);
assert_eq!(pending.front().expect("oldest retained").pts, 4);
assert_eq!(pending.back().expect("newest retained").pts, 19);
}
fn encode_silent_opus_payload() -> Option<Vec<u8>> { fn encode_silent_opus_payload() -> Option<Vec<u8>> {
let desc = "\ let desc = "\
appsrc name=src is-live=true block=false format=time \ appsrc name=src is-live=true block=false format=time \

View File

@ -96,14 +96,42 @@ fn marking_helpers_keep_current_pcm_path_explicit() {
#[test] #[test]
fn upstream_audio_codec_parser_keeps_opus_and_pcm_names_stable() { fn upstream_audio_codec_parser_keeps_opus_and_pcm_names_stable() {
assert_eq!(UpstreamAudioCodec::PcmS16le.as_id(), "pcm");
assert_eq!(UpstreamAudioCodec::PcmS16le.label(), "PCM");
assert_eq!(
UpstreamAudioCodec::PcmS16le.profile(),
AudioTransportProfile::pcm_s16le()
);
assert_eq!(UpstreamAudioCodec::Opus.as_id(), "opus");
assert_eq!(UpstreamAudioCodec::Opus.label(), "Opus");
assert_eq!(
UpstreamAudioCodec::Opus.profile(),
AudioTransportProfile::opus_voice()
);
assert_eq!( assert_eq!(
parse_upstream_audio_codec("opus"), parse_upstream_audio_codec("opus"),
Some(UpstreamAudioCodec::Opus) Some(UpstreamAudioCodec::Opus)
); );
assert_eq!(
parse_upstream_audio_codec(" compressed "),
Some(UpstreamAudioCodec::Opus)
);
assert_eq!(
parse_upstream_audio_codec("voice"),
Some(UpstreamAudioCodec::Opus)
);
assert_eq!( assert_eq!(
parse_upstream_audio_codec("raw"), parse_upstream_audio_codec("raw"),
Some(UpstreamAudioCodec::PcmS16le) Some(UpstreamAudioCodec::PcmS16le)
); );
assert_eq!(
parse_upstream_audio_codec("PCM_S16LE"),
Some(UpstreamAudioCodec::PcmS16le)
);
assert_eq!(
parse_upstream_audio_codec("uncompressed"),
Some(UpstreamAudioCodec::PcmS16le)
);
assert_eq!(parse_upstream_audio_codec("aac"), None); assert_eq!(parse_upstream_audio_codec("aac"), None);
let mut packet = AudioPacket { let mut packet = AudioPacket {
@ -117,3 +145,64 @@ fn upstream_audio_codec_parser_keeps_opus_and_pcm_names_stable() {
AudioTransportProfile::opus_voice() AudioTransportProfile::opus_voice()
); );
} }
#[test]
fn packet_profiles_preserve_explicit_nonzero_pcm_metadata() {
let packet = AudioPacket {
encoding: AudioEncoding::PcmS16le as i32,
sample_rate: 44_100,
channels: 1,
frame_duration_us: 10_000,
..AudioPacket::default()
};
assert_eq!(
packet_audio_profile(&packet),
AudioTransportProfile {
encoding: AudioEncoding::PcmS16le,
sample_rate: 44_100,
channels: 1,
frame_duration_us: 10_000,
target_bitrate_bps: None,
}
);
}
#[test]
fn bundle_profiles_fallback_from_envelope_to_first_packet() {
let packet = AudioPacket {
encoding: AudioEncoding::Opus as i32,
frame_duration_us: 40_000,
..AudioPacket::default()
};
let bundle = UpstreamMediaBundle {
audio: vec![packet],
..UpstreamMediaBundle::default()
};
assert_eq!(
bundle_audio_profile(&bundle),
AudioTransportProfile {
encoding: AudioEncoding::Opus,
sample_rate: 48_000,
channels: 2,
frame_duration_us: 40_000,
target_bitrate_bps: Some(96_000),
}
);
assert_eq!(
bundle_audio_profile(&UpstreamMediaBundle::default()),
AudioTransportProfile::pcm_s16le()
);
}
#[test]
fn marking_helpers_fill_default_frame_duration_when_absent() {
let mut pcm_packet = AudioPacket::default();
mark_packet_pcm_s16le(&mut pcm_packet);
assert_eq!(pcm_packet.frame_duration_us, 20_000);
let mut opus_packet = AudioPacket::default();
mark_packet_opus(&mut opus_packet);
assert_eq!(opus_packet.frame_duration_us, 20_000);
}