forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			488 lines
		
	
	
	
		
			14 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			488 lines
		
	
	
	
		
			14 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
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)
 | 
						|
#[allow(dead_code)] // this is just here to test whether it compiles.
 | 
						|
#[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)
 | 
						|
#[allow(dead_code)] // this is just here to test whether it compiles.
 | 
						|
#[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 a compile error when an instrumented function body contains inner
 | 
						|
// attributes (https://github.com/tokio-rs/tracing/issues/2294).
 | 
						|
#[deny(unused_variables)]
 | 
						|
#[instrument]
 | 
						|
async fn repro_async_2294() {
 | 
						|
    #![allow(unused_variables)]
 | 
						|
    let i = 42;
 | 
						|
}
 | 
						|
 | 
						|
// 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
 | 
						|
#[allow(dead_code)] // this is just here to test whether it compiles.
 | 
						|
#[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
 | 
						|
#[allow(dead_code)] // this is just here to test whether it compiles.
 | 
						|
#[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"))
 | 
						|
        .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())
 | 
						|
        .enter(span2.clone())
 | 
						|
        .exit(span2.clone())
 | 
						|
        .drop_span(span2)
 | 
						|
        .exit(span.clone())
 | 
						|
        .enter(span.clone())
 | 
						|
        .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())
 | 
						|
        .enter(span3.clone())
 | 
						|
        .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())
 | 
						|
        .enter(span2.clone())
 | 
						|
        .exit(span2.clone())
 | 
						|
        .drop_span(span2)
 | 
						|
        .exit(span.clone())
 | 
						|
        .enter(span.clone())
 | 
						|
        .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())
 | 
						|
        .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.clone())
 | 
						|
        .enter(span4.clone())
 | 
						|
        .exit(span4)
 | 
						|
        .exit(span2.clone())
 | 
						|
        .enter(span2.clone())
 | 
						|
        .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())
 | 
						|
        .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())
 | 
						|
        .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())
 | 
						|
        .enter(span.clone())
 | 
						|
        .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())
 | 
						|
        .enter(span.clone())
 | 
						|
        .exit(span.clone())
 | 
						|
        .drop_span(span)
 | 
						|
        .done()
 | 
						|
        .run_with_handle();
 | 
						|
 | 
						|
    with_default(subscriber, || {
 | 
						|
        block_on_future(async {
 | 
						|
            manual_box_pin().await;
 | 
						|
        });
 | 
						|
    });
 | 
						|
 | 
						|
    handle.assert_finished();
 | 
						|
}
 |