#![warn(rust_2018_idioms)] #![cfg(all(feature = "time", not(target_os = "wasi")))] // Wasi does not support panic recovery #![cfg(panic = "unwind")] use parking_lot::{const_mutex, Mutex}; use std::error::Error; use std::panic; use std::sync::Arc; use tokio::time::Duration; use tokio_stream::{self as stream, StreamExt}; fn test_panic(func: Func) -> Option { static PANIC_MUTEX: Mutex<()> = const_mutex(()); { let _guard = PANIC_MUTEX.lock(); let panic_file: Arc>> = Arc::new(Mutex::new(None)); let prev_hook = panic::take_hook(); { let panic_file = panic_file.clone(); panic::set_hook(Box::new(move |panic_info| { let panic_location = panic_info.location().unwrap(); panic_file .lock() .clone_from(&Some(panic_location.file().to_string())); })); } let result = panic::catch_unwind(func); // Return to the previously set panic hook (maybe default) so that we get nice error // messages in the tests. panic::set_hook(prev_hook); if result.is_err() { panic_file.lock().clone() } else { None } } } #[test] fn stream_chunks_timeout_panic_caller() -> Result<(), Box> { let panic_location_file = test_panic(|| { let iter = vec![1, 2, 3].into_iter(); let stream0 = stream::iter(iter); let _chunk_stream = stream0.chunks_timeout(0, Duration::from_secs(2)); }); // The panic location should be in this file assert_eq!(&panic_location_file.unwrap(), file!()); Ok(()) }