//! Include-based coverage for microphone level-tap publishing. //! //! Scope: include `client/src/input/microphone.rs` and exercise level-tap //! publishing behavior without requiring a live microphone. //! Targets: `client/src/input/microphone.rs`. //! Why: the local launcher tap should stay best-effort and never destabilize //! microphone uplink startup. #[allow(warnings)] mod live_capture_clock { include!("support/live_capture_clock_shim.rs"); } #[allow(warnings)] mod microphone_tap_contract { include!(env!("LESAVKA_CLIENT_MICROPHONE_SRC")); use tempfile::tempdir; #[test] fn spawned_mic_level_tap_tolerates_publish_errors() { gst::init().ok(); let dir = tempdir().expect("tempdir"); let path = dir.path().join("missing-parent").join("mic-level.value"); let pipeline: gst::Pipeline = gst::parse::launch( "appsrc name=src is-live=true format=time caps=audio/x-raw,format=S16LE,channels=2,rate=48000 ! \ appsink name=sink emit-signals=false sync=false max-buffers=4 drop=true", ) .expect("pipeline") .downcast() .expect("pipeline cast"); let src: gst_app::AppSrc = pipeline .by_name("src") .expect("appsrc") .downcast() .expect("appsrc cast"); let sink: gst_app::AppSink = pipeline .by_name("sink") .expect("appsink") .downcast() .expect("appsink cast"); pipeline.set_state(gst::State::Playing).expect("playing"); let running = spawn_mic_level_tap(sink, path); src.push_buffer(gst::Buffer::from_slice(i16::MAX.to_le_bytes().repeat(4))) .expect("push buffer"); std::thread::sleep(std::time::Duration::from_millis(100)); running.store(false, AtomicOrdering::Release); let _ = pipeline.set_state(gst::State::Null); } }