summaryrefslogtreecommitdiffstats
path: root/vendor/tracing-attributes/tests/async_fn.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /vendor/tracing-attributes/tests/async_fn.rs
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--vendor/tracing-attributes/tests/async_fn.rs449
1 files changed, 449 insertions, 0 deletions
diff --git a/vendor/tracing-attributes/tests/async_fn.rs b/vendor/tracing-attributes/tests/async_fn.rs
new file mode 100644
index 000000000..7e27fb5ce
--- /dev/null
+++ b/vendor/tracing-attributes/tests/async_fn.rs
@@ -0,0 +1,449 @@
+use tracing_mock::*;
+
+use std::convert::Infallible;
+use std::{future::Future, pin::Pin, sync::Arc};
+use tracing::subscriber::with_default;
+use tracing_attributes::instrument;
+
+#[instrument]
+async fn test_async_fn(polls: usize) -> Result<(), ()> {
+ let future = PollN::new_ok(polls);
+ tracing::trace!(awaiting = true);
+ future.await
+}
+
+// Reproduces a compile error when returning an `impl Trait` from an
+// instrumented async fn (see https://github.com/tokio-rs/tracing/issues/1615)
+#[instrument]
+async fn test_ret_impl_trait(n: i32) -> Result<impl Iterator<Item = i32>, ()> {
+ let n = n;
+ Ok((0..10).filter(move |x| *x < n))
+}
+
+// Reproduces a compile error when returning an `impl Trait` from an
+// instrumented async fn (see https://github.com/tokio-rs/tracing/issues/1615)
+#[instrument(err)]
+async fn test_ret_impl_trait_err(n: i32) -> Result<impl Iterator<Item = i32>, &'static str> {
+ Ok((0..10).filter(move |x| *x < n))
+}
+
+#[instrument]
+async fn test_async_fn_empty() {}
+
+// Reproduces https://github.com/tokio-rs/tracing/issues/1613
+#[instrument]
+// LOAD-BEARING `#[rustfmt::skip]`! This is necessary to reproduce the bug;
+// with the rustfmt-generated formatting, the lint will not be triggered!
+#[rustfmt::skip]
+#[deny(clippy::suspicious_else_formatting)]
+async fn repro_1613(var: bool) {
+ println!(
+ "{}",
+ if var { "true" } else { "false" }
+ );
+}
+
+// Reproduces https://github.com/tokio-rs/tracing/issues/1613
+// and https://github.com/rust-lang/rust-clippy/issues/7760
+#[instrument]
+#[deny(clippy::suspicious_else_formatting)]
+async fn repro_1613_2() {
+ // hello world
+ // else
+}
+
+// Reproduces https://github.com/tokio-rs/tracing/issues/1831
+#[instrument]
+#[deny(unused_braces)]
+fn repro_1831() -> Pin<Box<dyn Future<Output = ()>>> {
+ Box::pin(async move {})
+}
+
+// This replicates the pattern used to implement async trait methods on nightly using the
+// `type_alias_impl_trait` feature
+#[instrument(ret, err)]
+#[deny(unused_braces)]
+#[allow(clippy::manual_async_fn)]
+fn repro_1831_2() -> impl Future<Output = Result<(), Infallible>> {
+ async { Ok(()) }
+}
+
+#[test]
+fn async_fn_only_enters_for_polls() {
+ let (subscriber, handle) = subscriber::mock()
+ .new_span(span::mock().named("test_async_fn"))
+ .enter(span::mock().named("test_async_fn"))
+ .event(event::mock().with_fields(field::mock("awaiting").with_value(&true)))
+ .exit(span::mock().named("test_async_fn"))
+ .enter(span::mock().named("test_async_fn"))
+ .exit(span::mock().named("test_async_fn"))
+ .drop_span(span::mock().named("test_async_fn"))
+ .done()
+ .run_with_handle();
+ with_default(subscriber, || {
+ block_on_future(async { test_async_fn(2).await }).unwrap();
+ });
+ handle.assert_finished();
+}
+
+#[test]
+fn async_fn_nested() {
+ #[instrument]
+ async fn test_async_fns_nested() {
+ test_async_fns_nested_other().await
+ }
+
+ #[instrument]
+ async fn test_async_fns_nested_other() {
+ tracing::trace!(nested = true);
+ }
+
+ let span = span::mock().named("test_async_fns_nested");
+ let span2 = span::mock().named("test_async_fns_nested_other");
+ let (subscriber, handle) = subscriber::mock()
+ .new_span(span.clone())
+ .enter(span.clone())
+ .new_span(span2.clone())
+ .enter(span2.clone())
+ .event(event::mock().with_fields(field::mock("nested").with_value(&true)))
+ .exit(span2.clone())
+ .drop_span(span2)
+ .exit(span.clone())
+ .drop_span(span)
+ .done()
+ .run_with_handle();
+
+ with_default(subscriber, || {
+ block_on_future(async { test_async_fns_nested().await });
+ });
+
+ handle.assert_finished();
+}
+
+#[test]
+fn async_fn_with_async_trait() {
+ use async_trait::async_trait;
+
+ // test the correctness of the metadata obtained by #[instrument]
+ // (function name, functions parameters) when async-trait is used
+ #[async_trait]
+ pub trait TestA {
+ async fn foo(&mut self, v: usize);
+ }
+
+ // test nesting of async fns with aync-trait
+ #[async_trait]
+ pub trait TestB {
+ async fn bar(&self);
+ }
+
+ // test skip(self) with async-await
+ #[async_trait]
+ pub trait TestC {
+ async fn baz(&self);
+ }
+
+ #[derive(Debug)]
+ struct TestImpl(usize);
+
+ #[async_trait]
+ impl TestA for TestImpl {
+ #[instrument]
+ async fn foo(&mut self, v: usize) {
+ self.baz().await;
+ self.0 = v;
+ self.bar().await
+ }
+ }
+
+ #[async_trait]
+ impl TestB for TestImpl {
+ #[instrument]
+ async fn bar(&self) {
+ tracing::trace!(val = self.0);
+ }
+ }
+
+ #[async_trait]
+ impl TestC for TestImpl {
+ #[instrument(skip(self))]
+ async fn baz(&self) {
+ tracing::trace!(val = self.0);
+ }
+ }
+
+ let span = span::mock().named("foo");
+ let span2 = span::mock().named("bar");
+ let span3 = span::mock().named("baz");
+ let (subscriber, handle) = subscriber::mock()
+ .new_span(
+ span.clone()
+ .with_field(field::mock("self"))
+ .with_field(field::mock("v")),
+ )
+ .enter(span.clone())
+ .new_span(span3.clone())
+ .enter(span3.clone())
+ .event(event::mock().with_fields(field::mock("val").with_value(&2u64)))
+ .exit(span3.clone())
+ .drop_span(span3)
+ .new_span(span2.clone().with_field(field::mock("self")))
+ .enter(span2.clone())
+ .event(event::mock().with_fields(field::mock("val").with_value(&5u64)))
+ .exit(span2.clone())
+ .drop_span(span2)
+ .exit(span.clone())
+ .drop_span(span)
+ .done()
+ .run_with_handle();
+
+ with_default(subscriber, || {
+ let mut test = TestImpl(2);
+ block_on_future(async { test.foo(5).await });
+ });
+
+ handle.assert_finished();
+}
+
+#[test]
+fn async_fn_with_async_trait_and_fields_expressions() {
+ use async_trait::async_trait;
+
+ #[async_trait]
+ pub trait Test {
+ async fn call(&mut self, v: usize);
+ }
+
+ #[derive(Clone, Debug)]
+ struct TestImpl;
+
+ impl TestImpl {
+ fn foo(&self) -> usize {
+ 42
+ }
+ }
+
+ #[async_trait]
+ impl Test for TestImpl {
+ // check that self is correctly handled, even when using async_trait
+ #[instrument(fields(val=self.foo(), val2=Self::clone(self).foo(), test=%_v+5))]
+ async fn call(&mut self, _v: usize) {}
+ }
+
+ let span = span::mock().named("call");
+ let (subscriber, handle) = subscriber::mock()
+ .new_span(
+ span.clone().with_field(
+ field::mock("_v")
+ .with_value(&5usize)
+ .and(field::mock("test").with_value(&tracing::field::debug(10)))
+ .and(field::mock("val").with_value(&42u64))
+ .and(field::mock("val2").with_value(&42u64)),
+ ),
+ )
+ .enter(span.clone())
+ .exit(span.clone())
+ .drop_span(span)
+ .done()
+ .run_with_handle();
+
+ with_default(subscriber, || {
+ block_on_future(async { TestImpl.call(5).await });
+ });
+
+ handle.assert_finished();
+}
+
+#[test]
+fn async_fn_with_async_trait_and_fields_expressions_with_generic_parameter() {
+ use async_trait::async_trait;
+
+ #[async_trait]
+ pub trait Test {
+ async fn call();
+ async fn call_with_self(&self);
+ async fn call_with_mut_self(&mut self);
+ }
+
+ #[derive(Clone, Debug)]
+ struct TestImpl;
+
+ // we also test sync functions that return futures, as they should be handled just like
+ // async-trait (>= 0.1.44) functions
+ impl TestImpl {
+ #[instrument(fields(Self=std::any::type_name::<Self>()))]
+ fn sync_fun(&self) -> Pin<Box<dyn Future<Output = ()> + Send + '_>> {
+ let val = self.clone();
+ Box::pin(async move {
+ let _ = val;
+ })
+ }
+ }
+
+ #[async_trait]
+ impl Test for TestImpl {
+ // instrumenting this is currently not possible, see https://github.com/tokio-rs/tracing/issues/864#issuecomment-667508801
+ //#[instrument(fields(Self=std::any::type_name::<Self>()))]
+ async fn call() {}
+
+ #[instrument(fields(Self=std::any::type_name::<Self>()))]
+ async fn call_with_self(&self) {
+ self.sync_fun().await;
+ }
+
+ #[instrument(fields(Self=std::any::type_name::<Self>()))]
+ async fn call_with_mut_self(&mut self) {}
+ }
+
+ //let span = span::mock().named("call");
+ let span2 = span::mock().named("call_with_self");
+ let span3 = span::mock().named("call_with_mut_self");
+ let span4 = span::mock().named("sync_fun");
+ let (subscriber, handle) = subscriber::mock()
+ /*.new_span(span.clone()
+ .with_field(
+ field::mock("Self").with_value(&"TestImpler")))
+ .enter(span.clone())
+ .exit(span.clone())
+ .drop_span(span)*/
+ .new_span(
+ span2
+ .clone()
+ .with_field(field::mock("Self").with_value(&std::any::type_name::<TestImpl>())),
+ )
+ .enter(span2.clone())
+ .new_span(
+ span4
+ .clone()
+ .with_field(field::mock("Self").with_value(&std::any::type_name::<TestImpl>())),
+ )
+ .enter(span4.clone())
+ .exit(span4)
+ .exit(span2.clone())
+ .drop_span(span2)
+ .new_span(
+ span3
+ .clone()
+ .with_field(field::mock("Self").with_value(&std::any::type_name::<TestImpl>())),
+ )
+ .enter(span3.clone())
+ .exit(span3.clone())
+ .drop_span(span3)
+ .done()
+ .run_with_handle();
+
+ with_default(subscriber, || {
+ block_on_future(async {
+ TestImpl::call().await;
+ TestImpl.call_with_self().await;
+ TestImpl.call_with_mut_self().await
+ });
+ });
+
+ handle.assert_finished();
+}
+
+#[test]
+fn out_of_scope_fields() {
+ // Reproduces tokio-rs/tracing#1296
+
+ struct Thing {
+ metrics: Arc<()>,
+ }
+
+ impl Thing {
+ #[instrument(skip(self, _req), fields(app_id))]
+ fn call(&mut self, _req: ()) -> Pin<Box<dyn Future<Output = Arc<()>> + Send + Sync>> {
+ // ...
+ let metrics = self.metrics.clone();
+ // ...
+ Box::pin(async move {
+ // ...
+ metrics // cannot find value `metrics` in this scope
+ })
+ }
+ }
+
+ let span = span::mock().named("call");
+ let (subscriber, handle) = subscriber::mock()
+ .new_span(span.clone())
+ .enter(span.clone())
+ .exit(span.clone())
+ .drop_span(span)
+ .done()
+ .run_with_handle();
+
+ with_default(subscriber, || {
+ block_on_future(async {
+ let mut my_thing = Thing {
+ metrics: Arc::new(()),
+ };
+ my_thing.call(()).await;
+ });
+ });
+
+ handle.assert_finished();
+}
+
+#[test]
+fn manual_impl_future() {
+ #[allow(clippy::manual_async_fn)]
+ #[instrument]
+ fn manual_impl_future() -> impl Future<Output = ()> {
+ async {
+ tracing::trace!(poll = true);
+ }
+ }
+
+ let span = span::mock().named("manual_impl_future");
+ let poll_event = || event::mock().with_fields(field::mock("poll").with_value(&true));
+
+ let (subscriber, handle) = subscriber::mock()
+ // await manual_impl_future
+ .new_span(span.clone())
+ .enter(span.clone())
+ .event(poll_event())
+ .exit(span.clone())
+ .drop_span(span)
+ .done()
+ .run_with_handle();
+
+ with_default(subscriber, || {
+ block_on_future(async {
+ manual_impl_future().await;
+ });
+ });
+
+ handle.assert_finished();
+}
+
+#[test]
+fn manual_box_pin() {
+ #[instrument]
+ fn manual_box_pin() -> Pin<Box<dyn Future<Output = ()>>> {
+ Box::pin(async {
+ tracing::trace!(poll = true);
+ })
+ }
+
+ let span = span::mock().named("manual_box_pin");
+ let poll_event = || event::mock().with_fields(field::mock("poll").with_value(&true));
+
+ let (subscriber, handle) = subscriber::mock()
+ // await manual_box_pin
+ .new_span(span.clone())
+ .enter(span.clone())
+ .event(poll_event())
+ .exit(span.clone())
+ .drop_span(span)
+ .done()
+ .run_with_handle();
+
+ with_default(subscriber, || {
+ block_on_future(async {
+ manual_box_pin().await;
+ });
+ });
+
+ handle.assert_finished();
+}