Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stream: add track_caller to public APIs #4786

Merged
merged 1 commit into from Jun 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions tokio-stream/Cargo.toml
Expand Up @@ -34,6 +34,7 @@ tokio-util = { version = "0.7.0", path = "../tokio-util", optional = true }
[dev-dependencies]
tokio = { version = "1.2.0", path = "../tokio", features = ["full", "test-util"] }
async-stream = "0.3"
parking_lot = "0.12.0"
tokio-test = { path = "../tokio-test" }
futures = { version = "0.3", default-features = false }

Expand Down
1 change: 1 addition & 0 deletions tokio-stream/src/stream_ext.rs
Expand Up @@ -1056,6 +1056,7 @@ pub trait StreamExt: Stream {
/// ```
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
#[track_caller]
fn chunks_timeout(self, max_size: usize, duration: Duration) -> ChunksTimeout<Self>
where
Self: Sized,
Expand Down
55 changes: 55 additions & 0 deletions tokio-stream/tests/stream_panic.rs
@@ -0,0 +1,55 @@
#![warn(rust_2018_idioms)]
#![cfg(feature = "time")]

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: FnOnce() + panic::UnwindSafe>(func: Func) -> Option<String> {
static PANIC_MUTEX: Mutex<()> = const_mutex(());

{
let _guard = PANIC_MUTEX.lock();
let panic_file: Arc<Mutex<Option<String>>> = 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<dyn Error>> {
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(())
}