Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

View File

@@ -0,0 +1,496 @@
use std::convert::Infallible;
use std::{future::Future, pin::Pin, sync::Arc};
use tracing::subscriber::with_default;
use tracing_attributes::instrument;
use tracing_mock::{expect, subscriber};
use tracing_test::{block_on_future, PollN};
#[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>, ()> {
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]
#[allow(dead_code)]
async fn test_async_fn_empty() {}
#[instrument]
#[allow(dead_code)]
async unsafe fn test_async_unsafe_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)]
#[allow(dead_code, clippy::mixed_attributes_style)]
#[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)]
#[allow(dead_code)]
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)]
#[allow(dead_code)]
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(expect::span().named("test_async_fn"))
.enter(expect::span().named("test_async_fn"))
.event(expect::event().with_fields(expect::field("awaiting").with_value(&true)))
.exit(expect::span().named("test_async_fn"))
.enter(expect::span().named("test_async_fn"))
.exit(expect::span().named("test_async_fn"))
.enter(expect::span().named("test_async_fn"))
.exit(expect::span().named("test_async_fn"))
.drop_span(expect::span().named("test_async_fn"))
.only()
.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 = expect::span().named("test_async_fns_nested");
let span2 = expect::span().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(expect::event().with_fields(expect::field("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)
.only()
.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 = expect::span().named("foo");
let span2 = expect::span().named("bar");
let span3 = expect::span().named("baz");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone()
.with_fields(expect::field("self"))
.with_fields(expect::field("v")),
)
.enter(span.clone())
.new_span(span3.clone())
.enter(span3.clone())
.event(expect::event().with_fields(expect::field("val").with_value(&2u64)))
.exit(span3.clone())
.enter(span3.clone())
.exit(span3.clone())
.drop_span(span3)
.new_span(span2.clone().with_fields(expect::field("self")))
.enter(span2.clone())
.event(expect::event().with_fields(expect::field("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)
.only()
.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 = expect::span().named("call");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone().with_fields(
expect::field("_v")
.with_value(&5usize)
.and(expect::field("test").with_value(&tracing::field::debug(10)))
.and(expect::field("val").with_value(&42u64))
.and(expect::field("val2").with_value(&42u64)),
),
)
.enter(span.clone())
.exit(span.clone())
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
.only()
.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 = expect::span().named("call_with_self");
let span3 = expect::span().named("call_with_mut_self");
let span4 = expect::span().named("sync_fun");
let (subscriber, handle) = subscriber::mock()
/*.new_span(span.clone()
.with_fields(
expect::field("Self").with_value(&"TestImpler")))
.enter(span.clone())
.exit(span.clone())
.drop_span(span)*/
.new_span(
span2
.clone()
.with_fields(expect::field("Self").with_value(&std::any::type_name::<TestImpl>())),
)
.enter(span2.clone())
.new_span(
span4
.clone()
.with_fields(expect::field("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_fields(expect::field("Self").with_value(&std::any::type_name::<TestImpl>())),
)
.enter(span3.clone())
.exit(span3.clone())
.enter(span3.clone())
.exit(span3.clone())
.drop_span(span3)
.only()
.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 = expect::span().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)
.only()
.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 = expect::span().named("manual_impl_future");
let poll_event = || expect::event().with_fields(expect::field("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)
.only()
.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 = expect::span().named("manual_box_pin");
let poll_event = || expect::event().with_fields(expect::field("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)
.only()
.run_with_handle();
with_default(subscriber, || {
block_on_future(async {
manual_box_pin().await;
});
});
handle.assert_finished();
}

View File

@@ -0,0 +1,10 @@
use tracing_attributes::instrument;
#[deny(unfulfilled_lint_expectations)]
#[expect(dead_code)]
#[instrument]
fn unused() {}
#[expect(dead_code)]
#[instrument]
async fn unused_async() {}

View File

@@ -0,0 +1,213 @@
use tracing::subscriber::with_default;
use tracing_attributes::instrument;
use tracing_mock::*;
#[test]
fn destructure_tuples() {
#[instrument]
fn my_fn((arg1, arg2): (usize, usize)) {}
let span = expect::span().named("my_fn");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone().with_fields(
expect::field("arg1")
.with_value(&format_args!("1"))
.and(expect::field("arg2").with_value(&format_args!("2")))
.only(),
),
)
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, || {
my_fn((1, 2));
});
handle.assert_finished();
}
#[test]
fn destructure_nested_tuples() {
#[instrument]
fn my_fn(((arg1, arg2), (arg3, arg4)): ((usize, usize), (usize, usize))) {}
let span = expect::span().named("my_fn");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone().with_fields(
expect::field("arg1")
.with_value(&format_args!("1"))
.and(expect::field("arg2").with_value(&format_args!("2")))
.and(expect::field("arg3").with_value(&format_args!("3")))
.and(expect::field("arg4").with_value(&format_args!("4")))
.only(),
),
)
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, || {
my_fn(((1, 2), (3, 4)));
});
handle.assert_finished();
}
#[test]
fn destructure_refs() {
#[instrument]
fn my_fn(&arg1: &usize) {}
let span = expect::span().named("my_fn");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone()
.with_fields(expect::field("arg1").with_value(&1usize).only()),
)
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, || {
my_fn(&1);
});
handle.assert_finished();
}
#[test]
fn destructure_tuple_structs() {
struct Foo(usize, usize);
#[instrument]
fn my_fn(Foo(arg1, arg2): Foo) {}
let span = expect::span().named("my_fn");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone().with_fields(
expect::field("arg1")
.with_value(&format_args!("1"))
.and(expect::field("arg2").with_value(&format_args!("2")))
.only(),
),
)
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, || {
my_fn(Foo(1, 2));
});
handle.assert_finished();
}
#[test]
fn destructure_structs() {
struct Foo {
bar: usize,
baz: usize,
}
#[instrument]
fn my_fn(
Foo {
bar: arg1,
baz: arg2,
}: Foo,
) {
let _ = (arg1, arg2);
}
let span = expect::span().named("my_fn");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone().with_fields(
expect::field("arg1")
.with_value(&format_args!("1"))
.and(expect::field("arg2").with_value(&format_args!("2")))
.only(),
),
)
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, || {
my_fn(Foo { bar: 1, baz: 2 });
});
handle.assert_finished();
}
#[test]
fn destructure_everything() {
struct Foo {
bar: Bar,
baz: (usize, usize),
qux: NoDebug,
}
struct Bar((usize, usize));
struct NoDebug;
#[instrument]
fn my_fn(
&Foo {
bar: Bar((arg1, arg2)),
baz: (arg3, arg4),
..
}: &Foo,
) {
let _ = (arg1, arg2, arg3, arg4);
}
let span = expect::span().named("my_fn");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone().with_fields(
expect::field("arg1")
.with_value(&format_args!("1"))
.and(expect::field("arg2").with_value(&format_args!("2")))
.and(expect::field("arg3").with_value(&format_args!("3")))
.and(expect::field("arg4").with_value(&format_args!("4")))
.only(),
),
)
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, || {
let foo = Foo {
bar: Bar((1, 2)),
baz: (3, 4),
qux: NoDebug,
};
let _ = foo.qux; // to eliminate unused field warning
my_fn(&foo);
});
handle.assert_finished();
}

329
vendor/tracing-attributes/tests/err.rs vendored Normal file
View File

@@ -0,0 +1,329 @@
use tracing::subscriber::with_default;
use tracing::Level;
use tracing_attributes::instrument;
use tracing_mock::*;
use tracing_subscriber::filter::EnvFilter;
use tracing_subscriber::layer::SubscriberExt;
use tracing_test::{block_on_future, PollN};
use std::convert::TryFrom;
use std::num::TryFromIntError;
#[instrument(err)]
fn err() -> Result<u8, TryFromIntError> {
u8::try_from(1234)
}
#[instrument(err)]
#[allow(dead_code)]
fn err_suspicious_else() -> Result<u8, TryFromIntError> {
{}
u8::try_from(1234)
}
#[test]
fn test() {
let span = expect::span().named("err");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(expect::event().at_level(Level::ERROR))
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, || err().ok());
handle.assert_finished();
}
#[instrument(err)]
fn err_early_return() -> Result<u8, TryFromIntError> {
u8::try_from(1234)?;
Ok(5)
}
#[test]
fn test_early_return() {
let span = expect::span().named("err_early_return");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(expect::event().at_level(Level::ERROR))
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, || err_early_return().ok());
handle.assert_finished();
}
#[instrument(err)]
async fn err_async(polls: usize) -> Result<u8, TryFromIntError> {
let future = PollN::new_ok(polls);
tracing::trace!(awaiting = true);
future.await.ok();
u8::try_from(1234)
}
#[test]
fn test_async() {
let span = expect::span().named("err_async");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(
expect::event()
.with_fields(expect::field("awaiting").with_value(&true))
.at_level(Level::TRACE),
)
.exit(span.clone())
.enter(span.clone())
.event(expect::event().at_level(Level::ERROR))
.exit(span.clone())
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, || {
block_on_future(async { err_async(2).await }).ok();
});
handle.assert_finished();
}
#[instrument(err)]
fn err_mut(out: &mut u8) -> Result<(), TryFromIntError> {
*out = u8::try_from(1234)?;
Ok(())
}
#[test]
fn test_mut() {
let span = expect::span().named("err_mut");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(expect::event().at_level(Level::ERROR))
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, || err_mut(&mut 0).ok());
handle.assert_finished();
}
#[instrument(err)]
async fn err_mut_async(polls: usize, out: &mut u8) -> Result<(), TryFromIntError> {
let future = PollN::new_ok(polls);
tracing::trace!(awaiting = true);
future.await.ok();
*out = u8::try_from(1234)?;
Ok(())
}
#[test]
fn test_mut_async() {
let span = expect::span().named("err_mut_async");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(
expect::event()
.with_fields(expect::field("awaiting").with_value(&true))
.at_level(Level::TRACE),
)
.exit(span.clone())
.enter(span.clone())
.event(expect::event().at_level(Level::ERROR))
.exit(span.clone())
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, || {
block_on_future(async { err_mut_async(2, &mut 0).await }).ok();
});
handle.assert_finished();
}
#[test]
fn impl_trait_return_type() {
// Reproduces https://github.com/tokio-rs/tracing/issues/1227
#[instrument(err)]
fn returns_impl_trait(x: usize) -> Result<impl Iterator<Item = usize>, String> {
Ok(0..x)
}
let span = expect::span().named("returns_impl_trait");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone()
.with_fields(expect::field("x").with_value(&10usize).only()),
)
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, || {
for _ in returns_impl_trait(10).unwrap() {
// nop
}
});
handle.assert_finished();
}
#[instrument(err(Debug))]
fn err_dbg() -> Result<u8, TryFromIntError> {
u8::try_from(1234)
}
#[test]
fn test_err_dbg() {
let span = expect::span().named("err_dbg");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(
expect::event().at_level(Level::ERROR).with_fields(
expect::field("error")
// use the actual error value that will be emitted, so
// that this test doesn't break if the standard library
// changes the `fmt::Debug` output from the error type
// in the future.
.with_value(&tracing::field::debug(u8::try_from(1234).unwrap_err())),
),
)
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, || err_dbg().ok());
handle.assert_finished();
}
#[test]
fn test_err_display_default() {
let span = expect::span().named("err");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(
expect::event().at_level(Level::ERROR).with_fields(
expect::field("error")
// by default, errors will be emitted with their display values
.with_value(&tracing::field::display(u8::try_from(1234).unwrap_err())),
),
)
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, || err().ok());
handle.assert_finished();
}
#[test]
fn test_err_custom_target() {
let filter: EnvFilter = "my_target=error".parse().expect("filter should parse");
let span = expect::span().named("error_span").with_target("my_target");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(
expect::event()
.at_level(Level::ERROR)
.with_target("my_target"),
)
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
let subscriber = subscriber.with(filter);
with_default(subscriber, || {
let error_span = tracing::error_span!(target: "my_target", "error_span");
{
let _enter = error_span.enter();
tracing::error!(target: "my_target", "This should display")
}
});
handle.assert_finished();
}
#[instrument(err(level = "info"))]
fn err_info() -> Result<u8, TryFromIntError> {
u8::try_from(1234)
}
#[test]
fn test_err_info() {
let span = expect::span().named("err_info");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(expect::event().at_level(Level::INFO))
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, || err_info().ok());
handle.assert_finished();
}
#[instrument(err(Debug, level = "info"))]
fn err_dbg_info() -> Result<u8, TryFromIntError> {
u8::try_from(1234)
}
#[test]
fn test_err_dbg_info() {
let span = expect::span().named("err_dbg_info");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(
expect::event().at_level(Level::INFO).with_fields(
expect::field("error")
// use the actual error value that will be emitted, so
// that this test doesn't break if the standard library
// changes the `fmt::Debug` output from the error type
// in the future.
.with_value(&tracing::field::debug(u8::try_from(1234).unwrap_err())),
),
)
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, || err_dbg_info().ok());
handle.assert_finished();
}
#[instrument(level = "warn", err(level = "info"))]
fn err_warn_info() -> Result<u8, TryFromIntError> {
u8::try_from(1234)
}
#[test]
fn test_err_warn_info() {
let span = expect::span().named("err_warn_info").at_level(Level::WARN);
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(expect::event().at_level(Level::INFO))
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, || err_warn_info().ok());
handle.assert_finished();
}

View File

@@ -0,0 +1,172 @@
use tracing::subscriber::with_default;
use tracing_attributes::instrument;
use tracing_mock::{expect, span::NewSpan, subscriber};
#[instrument(fields(foo = "bar", dsa = true, num = 1))]
fn fn_no_param() {}
#[instrument(fields(foo = "bar"))]
fn fn_param(param: u32) {}
#[instrument(fields(foo = "bar", empty))]
fn fn_empty_field() {}
#[instrument(fields(len = s.len()))]
fn fn_expr_field(s: &str) {}
#[instrument(fields(s.len = s.len(), s.is_empty = s.is_empty()))]
fn fn_two_expr_fields(s: &str) {
let _ = s;
}
#[instrument(fields(%s, s.len = s.len()))]
fn fn_clashy_expr_field(s: &str) {
let _ = s;
}
#[instrument(fields(s = "s"))]
fn fn_clashy_expr_field2(s: &str) {
let _ = s;
}
#[instrument(fields(s = &s))]
fn fn_string(s: String) {
let _ = s;
}
#[instrument(fields(keywords.impl.type.fn = _arg), skip(_arg))]
fn fn_keyword_ident_in_field(_arg: &str) {}
#[derive(Debug)]
struct HasField {
my_field: &'static str,
}
impl HasField {
#[instrument(fields(my_field = self.my_field), skip(self))]
fn self_expr_field(&self) {}
}
#[test]
fn fields() {
let span = expect::span().with_fields(
expect::field("foo")
.with_value(&"bar")
.and(expect::field("dsa").with_value(&true))
.and(expect::field("num").with_value(&1))
.only(),
);
run_test(span, || {
fn_no_param();
});
}
#[test]
fn expr_field() {
let span = expect::span().with_fields(
expect::field("s")
.with_value(&"hello world")
.and(expect::field("len").with_value(&"hello world".len()))
.only(),
);
run_test(span, || {
fn_expr_field("hello world");
});
}
#[test]
fn two_expr_fields() {
let span = expect::span().with_fields(
expect::field("s")
.with_value(&"hello world")
.and(expect::field("s.len").with_value(&"hello world".len()))
.and(expect::field("s.is_empty").with_value(&false))
.only(),
);
run_test(span, || {
fn_two_expr_fields("hello world");
});
}
#[test]
fn clashy_expr_field() {
let span = expect::span().with_fields(
// Overriding the `s` field should record `s` as a `Display` value,
// rather than as a `Debug` value.
expect::field("s")
.with_value(&tracing::field::display("hello world"))
.and(expect::field("s.len").with_value(&"hello world".len()))
.only(),
);
run_test(span, || {
fn_clashy_expr_field("hello world");
});
let span = expect::span().with_fields(expect::field("s").with_value(&"s").only());
run_test(span, || {
fn_clashy_expr_field2("hello world");
});
}
#[test]
fn self_expr_field() {
let span =
expect::span().with_fields(expect::field("my_field").with_value(&"hello world").only());
run_test(span, || {
let has_field = HasField {
my_field: "hello world",
};
has_field.self_expr_field();
});
}
#[test]
fn parameters_with_fields() {
let span = expect::span().with_fields(
expect::field("foo")
.with_value(&"bar")
.and(expect::field("param").with_value(&1u32))
.only(),
);
run_test(span, || {
fn_param(1);
});
}
#[test]
fn empty_field() {
let span = expect::span().with_fields(expect::field("foo").with_value(&"bar").only());
run_test(span, || {
fn_empty_field();
});
}
#[test]
fn string_field() {
let span = expect::span().with_fields(expect::field("s").with_value(&"hello world").only());
run_test(span, || {
fn_string(String::from("hello world"));
});
}
#[test]
fn keyword_ident_in_field_name() {
let span = expect::span().with_fields(
expect::field("keywords.impl.type.fn")
.with_value(&"test")
.only(),
);
run_test(span, || fn_keyword_ident_in_field("test"));
}
fn run_test<F: FnOnce() -> T, T>(span: NewSpan, fun: F) {
let (subscriber, handle) = subscriber::mock()
.new_span(span)
.enter(expect::span())
.exit(expect::span())
.only()
.run_with_handle();
with_default(subscriber, fun);
handle.assert_finished();
}

View File

@@ -0,0 +1,102 @@
use tracing::{subscriber::with_default, Id, Level, Span};
use tracing_attributes::instrument;
use tracing_mock::{expect, subscriber};
use tracing_test::block_on_future;
#[instrument(follows_from = causes, skip(causes))]
fn with_follows_from_sync(causes: impl IntoIterator<Item = impl Into<Option<Id>>>) {}
#[instrument(follows_from = causes, skip(causes))]
async fn with_follows_from_async(causes: impl IntoIterator<Item = impl Into<Option<Id>>>) {}
#[instrument(follows_from = [&Span::current()])]
fn follows_from_current() {}
#[test]
fn follows_from_sync_test() {
let cause_a = expect::span().named("cause_a");
let cause_b = expect::span().named("cause_b");
let cause_c = expect::span().named("cause_c");
let consequence = expect::span().named("with_follows_from_sync");
let (subscriber, handle) = subscriber::mock()
.new_span(cause_a.clone())
.new_span(cause_b.clone())
.new_span(cause_c.clone())
.new_span(consequence.clone())
.follows_from(consequence.clone(), cause_a)
.follows_from(consequence.clone(), cause_b)
.follows_from(consequence.clone(), cause_c)
.enter(consequence.clone())
.exit(consequence)
.only()
.run_with_handle();
with_default(subscriber, || {
let cause_a = tracing::span!(Level::TRACE, "cause_a");
let cause_b = tracing::span!(Level::TRACE, "cause_b");
let cause_c = tracing::span!(Level::TRACE, "cause_c");
with_follows_from_sync(&[cause_a, cause_b, cause_c])
});
handle.assert_finished();
}
#[test]
fn follows_from_async_test() {
let cause_a = expect::span().named("cause_a");
let cause_b = expect::span().named("cause_b");
let cause_c = expect::span().named("cause_c");
let consequence = expect::span().named("with_follows_from_async");
let (subscriber, handle) = subscriber::mock()
.new_span(cause_a.clone())
.new_span(cause_b.clone())
.new_span(cause_c.clone())
.new_span(consequence.clone())
.follows_from(consequence.clone(), cause_a)
.follows_from(consequence.clone(), cause_b)
.follows_from(consequence.clone(), cause_c)
.enter(consequence.clone())
.exit(consequence.clone())
.enter(consequence.clone())
.exit(consequence)
.only()
.run_with_handle();
with_default(subscriber, || {
block_on_future(async {
let cause_a = tracing::span!(Level::TRACE, "cause_a");
let cause_b = tracing::span!(Level::TRACE, "cause_b");
let cause_c = tracing::span!(Level::TRACE, "cause_c");
with_follows_from_async(&[cause_a, cause_b, cause_c]).await
})
});
handle.assert_finished();
}
#[test]
fn follows_from_current_test() {
let cause = expect::span().named("cause");
let consequence = expect::span().named("follows_from_current");
let (subscriber, handle) = subscriber::mock()
.new_span(cause.clone())
.enter(cause.clone())
.new_span(consequence.clone())
.follows_from(consequence.clone(), cause.clone())
.enter(consequence.clone())
.exit(consequence)
.exit(cause)
.only()
.run_with_handle();
with_default(subscriber, || {
tracing::span!(Level::TRACE, "cause").in_scope(follows_from_current)
});
handle.assert_finished();
}

View File

@@ -0,0 +1,346 @@
use tracing::subscriber::with_default;
use tracing::Level;
use tracing_attributes::instrument;
use tracing_mock::*;
// Reproduces a compile error when an instrumented function body contains inner
// attributes (https://github.com/tokio-rs/tracing/issues/2294).
#[deny(unused_variables)]
#[allow(dead_code, clippy::mixed_attributes_style)]
#[instrument]
fn repro_2294() {
#![allow(unused_variables)]
let i = 42;
}
#[test]
fn override_everything() {
#[instrument(target = "my_target", level = "debug")]
fn my_fn() {}
#[instrument(level = Level::DEBUG, target = "my_target")]
fn my_other_fn() {}
let span = expect::span()
.named("my_fn")
.at_level(Level::DEBUG)
.with_target("my_target");
let span2 = expect::span()
.named("my_other_fn")
.at_level(Level::DEBUG)
.with_target("my_target");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
.new_span(span2.clone())
.enter(span2.clone())
.exit(span2.clone())
.drop_span(span2)
.only()
.run_with_handle();
with_default(subscriber, || {
my_fn();
my_other_fn();
});
handle.assert_finished();
}
#[test]
fn fields() {
#[instrument(target = "my_target", level = "debug")]
fn my_fn(arg1: usize, arg2: bool, arg3: String) {}
let span = expect::span()
.named("my_fn")
.at_level(Level::DEBUG)
.with_target("my_target");
let span2 = expect::span()
.named("my_fn")
.at_level(Level::DEBUG)
.with_target("my_target");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone().with_fields(
expect::field("arg1")
.with_value(&2usize)
.and(expect::field("arg2").with_value(&false))
.and(expect::field("arg3").with_value(&"Cool".to_string()))
.only(),
),
)
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
.new_span(
span2.clone().with_fields(
expect::field("arg1")
.with_value(&3usize)
.and(expect::field("arg2").with_value(&true))
.and(expect::field("arg3").with_value(&"Still Cool".to_string()))
.only(),
),
)
.enter(span2.clone())
.exit(span2.clone())
.drop_span(span2)
.only()
.run_with_handle();
with_default(subscriber, || {
my_fn(2, false, "Cool".to_string());
my_fn(3, true, "Still Cool".to_string());
});
handle.assert_finished();
}
#[test]
fn skip() {
struct UnDebug();
#[instrument(target = "my_target", level = "debug", skip(_arg2, _arg3))]
fn my_fn(arg1: usize, _arg2: UnDebug, _arg3: UnDebug) {}
#[instrument(target = "my_target", level = "debug", skip_all)]
fn my_fn2(_arg1: usize, _arg2: UnDebug, _arg3: UnDebug) {}
let span = expect::span()
.named("my_fn")
.at_level(Level::DEBUG)
.with_target("my_target");
let span2 = expect::span()
.named("my_fn")
.at_level(Level::DEBUG)
.with_target("my_target");
let span3 = expect::span()
.named("my_fn2")
.at_level(Level::DEBUG)
.with_target("my_target");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone()
.with_fields(expect::field("arg1").with_value(&2usize).only()),
)
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
.new_span(
span2
.clone()
.with_fields(expect::field("arg1").with_value(&3usize).only()),
)
.enter(span2.clone())
.exit(span2.clone())
.drop_span(span2)
.new_span(span3.clone())
.enter(span3.clone())
.exit(span3.clone())
.drop_span(span3)
.only()
.run_with_handle();
with_default(subscriber, || {
my_fn(2, UnDebug(), UnDebug());
my_fn(3, UnDebug(), UnDebug());
my_fn2(2, UnDebug(), UnDebug());
});
handle.assert_finished();
}
#[test]
fn generics() {
#[derive(Debug)]
struct Foo;
#[instrument]
fn my_fn<S, T: std::fmt::Debug>(arg1: S, arg2: T)
where
S: std::fmt::Debug,
{
}
let span = expect::span().named("my_fn");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone().with_fields(
expect::field("arg1")
.with_value(&format_args!("Foo"))
.and(expect::field("arg2").with_value(&format_args!("false"))),
),
)
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, || {
my_fn(Foo, false);
});
handle.assert_finished();
}
#[test]
fn methods() {
#[derive(Debug)]
struct Foo;
impl Foo {
#[instrument]
fn my_fn(&self, arg1: usize) {}
}
let span = expect::span().named("my_fn");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone().with_fields(
expect::field("self")
.with_value(&format_args!("Foo"))
.and(expect::field("arg1").with_value(&42usize)),
),
)
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, || {
let foo = Foo;
foo.my_fn(42);
});
handle.assert_finished();
}
#[test]
fn impl_trait_return_type() {
#[instrument]
fn returns_impl_trait(x: usize) -> impl Iterator<Item = usize> {
0..x
}
let span = expect::span().named("returns_impl_trait");
let (subscriber, handle) = subscriber::mock()
.new_span(
span.clone()
.with_fields(expect::field("x").with_value(&10usize).only()),
)
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, || {
for _ in returns_impl_trait(10) {
// nop
}
});
handle.assert_finished();
}
#[test]
fn name_ident() {
const MY_NAME: &str = "my_name";
#[instrument(name = MY_NAME)]
fn name() {}
let span_name = expect::span().named(MY_NAME);
let (subscriber, handle) = subscriber::mock()
.new_span(span_name.clone())
.enter(span_name.clone())
.exit(span_name.clone())
.drop_span(span_name)
.only()
.run_with_handle();
with_default(subscriber, || {
name();
});
handle.assert_finished();
}
#[test]
fn target_ident() {
const MY_TARGET: &str = "my_target";
#[instrument(target = MY_TARGET)]
fn target() {}
let span_target = expect::span().named("target").with_target(MY_TARGET);
let (subscriber, handle) = subscriber::mock()
.new_span(span_target.clone())
.enter(span_target.clone())
.exit(span_target.clone())
.drop_span(span_target)
.only()
.run_with_handle();
with_default(subscriber, || {
target();
});
handle.assert_finished();
}
#[test]
fn target_name_ident() {
const MY_NAME: &str = "my_name";
const MY_TARGET: &str = "my_target";
#[instrument(target = MY_TARGET, name = MY_NAME)]
fn name_target() {}
let span_name_target = expect::span().named(MY_NAME).with_target(MY_TARGET);
let (subscriber, handle) = subscriber::mock()
.new_span(span_name_target.clone())
.enter(span_name_target.clone())
.exit(span_name_target.clone())
.drop_span(span_name_target)
.only()
.run_with_handle();
with_default(subscriber, || {
name_target();
});
handle.assert_finished();
}
#[test]
fn user_tracing_module() {
use ::tracing::field::Empty;
// Reproduces https://github.com/tokio-rs/tracing/issues/3119
#[instrument(fields(f = Empty))]
#[allow(dead_code)]
fn my_fn() {
assert_eq!("test", tracing::my_other_fn());
}
mod tracing {
#[allow(dead_code)]
pub fn my_other_fn() -> &'static str {
"test"
}
}
}

View File

@@ -0,0 +1,142 @@
use tracing::subscriber::with_default;
use tracing::Level;
use tracing_attributes::instrument;
use tracing_mock::*;
#[test]
fn named_levels() {
#[instrument(level = "trace")]
fn trace() {}
#[instrument(level = "Debug")]
fn debug() {}
#[instrument(level = "INFO")]
fn info() {}
#[instrument(level = "WARn")]
fn warn() {}
#[instrument(level = "eRrOr")]
fn error() {}
let (subscriber, handle) = subscriber::mock()
.new_span(expect::span().named("trace").at_level(Level::TRACE))
.enter(expect::span().named("trace").at_level(Level::TRACE))
.exit(expect::span().named("trace").at_level(Level::TRACE))
.new_span(expect::span().named("debug").at_level(Level::DEBUG))
.enter(expect::span().named("debug").at_level(Level::DEBUG))
.exit(expect::span().named("debug").at_level(Level::DEBUG))
.new_span(expect::span().named("info").at_level(Level::INFO))
.enter(expect::span().named("info").at_level(Level::INFO))
.exit(expect::span().named("info").at_level(Level::INFO))
.new_span(expect::span().named("warn").at_level(Level::WARN))
.enter(expect::span().named("warn").at_level(Level::WARN))
.exit(expect::span().named("warn").at_level(Level::WARN))
.new_span(expect::span().named("error").at_level(Level::ERROR))
.enter(expect::span().named("error").at_level(Level::ERROR))
.exit(expect::span().named("error").at_level(Level::ERROR))
.only()
.run_with_handle();
with_default(subscriber, || {
trace();
debug();
info();
warn();
error();
});
handle.assert_finished();
}
#[test]
fn numeric_levels() {
#[instrument(level = 1)]
fn trace() {}
#[instrument(level = 2)]
fn debug() {}
#[instrument(level = 3)]
fn info() {}
#[instrument(level = 4)]
fn warn() {}
#[instrument(level = 5)]
fn error() {}
let (subscriber, handle) = subscriber::mock()
.new_span(expect::span().named("trace").at_level(Level::TRACE))
.enter(expect::span().named("trace").at_level(Level::TRACE))
.exit(expect::span().named("trace").at_level(Level::TRACE))
.new_span(expect::span().named("debug").at_level(Level::DEBUG))
.enter(expect::span().named("debug").at_level(Level::DEBUG))
.exit(expect::span().named("debug").at_level(Level::DEBUG))
.new_span(expect::span().named("info").at_level(Level::INFO))
.enter(expect::span().named("info").at_level(Level::INFO))
.exit(expect::span().named("info").at_level(Level::INFO))
.new_span(expect::span().named("warn").at_level(Level::WARN))
.enter(expect::span().named("warn").at_level(Level::WARN))
.exit(expect::span().named("warn").at_level(Level::WARN))
.new_span(expect::span().named("error").at_level(Level::ERROR))
.enter(expect::span().named("error").at_level(Level::ERROR))
.exit(expect::span().named("error").at_level(Level::ERROR))
.only()
.run_with_handle();
with_default(subscriber, || {
trace();
debug();
info();
warn();
error();
});
handle.assert_finished();
}
#[test]
fn enum_levels() {
#[instrument(level = Level::TRACE)]
fn trace() {}
#[instrument(level = Level::DEBUG)]
fn debug() {}
#[instrument(level = tracing::Level::INFO)]
fn info() {}
#[instrument(level = Level::WARN)]
fn warn() {}
#[instrument(level = Level::ERROR)]
fn error() {}
let (subscriber, handle) = subscriber::mock()
.new_span(expect::span().named("trace").at_level(Level::TRACE))
.enter(expect::span().named("trace").at_level(Level::TRACE))
.exit(expect::span().named("trace").at_level(Level::TRACE))
.new_span(expect::span().named("debug").at_level(Level::DEBUG))
.enter(expect::span().named("debug").at_level(Level::DEBUG))
.exit(expect::span().named("debug").at_level(Level::DEBUG))
.new_span(expect::span().named("info").at_level(Level::INFO))
.enter(expect::span().named("info").at_level(Level::INFO))
.exit(expect::span().named("info").at_level(Level::INFO))
.new_span(expect::span().named("warn").at_level(Level::WARN))
.enter(expect::span().named("warn").at_level(Level::WARN))
.exit(expect::span().named("warn").at_level(Level::WARN))
.new_span(expect::span().named("error").at_level(Level::ERROR))
.enter(expect::span().named("error").at_level(Level::ERROR))
.exit(expect::span().named("error").at_level(Level::ERROR))
.only()
.run_with_handle();
with_default(subscriber, || {
trace();
debug();
info();
warn();
error();
});
handle.assert_finished();
}

View File

@@ -0,0 +1,63 @@
use tracing::subscriber::with_default;
use tracing_attributes::instrument;
use tracing_mock::*;
#[instrument]
fn default_name() {}
#[instrument(name = "my_name")]
fn custom_name() {}
// XXX: it's weird that we support both of these forms, but apparently we
// managed to release a version that accepts both syntax, so now we have to
// support it! yay!
#[instrument("my_other_name")]
fn custom_name_no_equals() {}
#[test]
fn default_name_test() {
let (subscriber, handle) = subscriber::mock()
.new_span(expect::span().named("default_name"))
.enter(expect::span().named("default_name"))
.exit(expect::span().named("default_name"))
.only()
.run_with_handle();
with_default(subscriber, || {
default_name();
});
handle.assert_finished();
}
#[test]
fn custom_name_test() {
let (subscriber, handle) = subscriber::mock()
.new_span(expect::span().named("my_name"))
.enter(expect::span().named("my_name"))
.exit(expect::span().named("my_name"))
.only()
.run_with_handle();
with_default(subscriber, || {
custom_name();
});
handle.assert_finished();
}
#[test]
fn custom_name_no_equals_test() {
let (subscriber, handle) = subscriber::mock()
.new_span(expect::span().named("my_other_name"))
.enter(expect::span().named("my_other_name"))
.exit(expect::span().named("my_other_name"))
.only()
.run_with_handle();
with_default(subscriber, || {
custom_name_no_equals();
});
handle.assert_finished();
}

View File

@@ -0,0 +1,89 @@
use tracing::{subscriber::with_default, Id, Level};
use tracing_attributes::instrument;
use tracing_mock::*;
#[instrument]
fn with_default_parent() {}
#[instrument(parent = parent_span, skip(parent_span))]
fn with_explicit_parent<P>(parent_span: P)
where
P: Into<Option<Id>>,
{
}
#[test]
fn default_parent_test() {
let contextual_parent = expect::span().named("contextual_parent");
let child = expect::span().named("with_default_parent");
let (subscriber, handle) = subscriber::mock()
.new_span(
contextual_parent
.clone()
.with_ancestry(expect::is_contextual_root()),
)
.new_span(child.clone().with_ancestry(expect::is_contextual_root()))
.enter(child.clone())
.exit(child.clone())
.enter(contextual_parent.clone())
.new_span(
child
.clone()
.with_ancestry(expect::has_contextual_parent("contextual_parent")),
)
.enter(child.clone())
.exit(child)
.exit(contextual_parent)
.only()
.run_with_handle();
with_default(subscriber, || {
let contextual_parent = tracing::span!(Level::TRACE, "contextual_parent");
with_default_parent();
contextual_parent.in_scope(|| {
with_default_parent();
});
});
handle.assert_finished();
}
#[test]
fn explicit_parent_test() {
let contextual_parent = expect::span().named("contextual_parent");
let explicit_parent = expect::span().named("explicit_parent");
let child = expect::span().named("with_explicit_parent");
let (subscriber, handle) = subscriber::mock()
.new_span(
contextual_parent
.clone()
.with_ancestry(expect::is_contextual_root()),
)
.new_span(explicit_parent.with_ancestry(expect::is_contextual_root()))
.enter(contextual_parent.clone())
.new_span(
child
.clone()
.with_ancestry(expect::has_explicit_parent("explicit_parent")),
)
.enter(child.clone())
.exit(child)
.exit(contextual_parent)
.only()
.run_with_handle();
with_default(subscriber, || {
let contextual_parent = tracing::span!(Level::INFO, "contextual_parent");
let explicit_parent = tracing::span!(Level::INFO, "explicit_parent");
contextual_parent.in_scope(|| {
with_explicit_parent(&explicit_parent);
});
});
handle.assert_finished();
}

308
vendor/tracing-attributes/tests/ret.rs vendored Normal file
View File

@@ -0,0 +1,308 @@
use std::convert::TryFrom;
use std::num::TryFromIntError;
use tracing::{subscriber::with_default, Level};
use tracing_attributes::instrument;
use tracing_mock::{expect, subscriber};
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::EnvFilter;
use tracing_test::block_on_future;
#[instrument(ret)]
fn ret() -> i32 {
42
}
#[instrument(target = "my_target", ret)]
fn ret_with_target() -> i32 {
42
}
#[test]
fn test() {
let span = expect::span().named("ret");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(
expect::event()
.with_fields(expect::field("return").with_value(&tracing::field::debug(42)))
.at_level(Level::INFO),
)
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, ret);
handle.assert_finished();
}
#[test]
fn test_custom_target() {
let filter: EnvFilter = "my_target=info".parse().expect("filter should parse");
let span = expect::span()
.named("ret_with_target")
.with_target("my_target");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(
expect::event()
.with_fields(expect::field("return").with_value(&tracing::field::debug(42)))
.at_level(Level::INFO)
.with_target("my_target"),
)
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
let subscriber = subscriber.with(filter);
with_default(subscriber, ret_with_target);
handle.assert_finished();
}
#[instrument(level = "warn", ret)]
fn ret_warn() -> i32 {
42
}
#[test]
fn test_warn() {
let span = expect::span().named("ret_warn");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(
expect::event()
.with_fields(expect::field("return").with_value(&tracing::field::debug(42)))
.at_level(Level::WARN),
)
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, ret_warn);
handle.assert_finished();
}
#[instrument(ret)]
fn ret_mut(a: &mut i32) -> i32 {
*a *= 2;
tracing::info!(?a);
*a
}
#[test]
fn test_mut() {
let span = expect::span().named("ret_mut");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(
expect::event()
.with_fields(expect::field("a").with_value(&tracing::field::display(2)))
.at_level(Level::INFO),
)
.event(
expect::event()
.with_fields(expect::field("return").with_value(&tracing::field::debug(2)))
.at_level(Level::INFO),
)
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, || ret_mut(&mut 1));
handle.assert_finished();
}
#[instrument(ret)]
async fn ret_async() -> i32 {
42
}
#[test]
fn test_async() {
let span = expect::span().named("ret_async");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(
expect::event()
.with_fields(expect::field("return").with_value(&tracing::field::debug(42)))
.at_level(Level::INFO),
)
.exit(span.clone())
.enter(span.clone())
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, || block_on_future(async { ret_async().await }));
handle.assert_finished();
}
#[instrument(ret)]
fn ret_impl_type() -> impl Copy {
42
}
#[test]
fn test_impl_type() {
let span = expect::span().named("ret_impl_type");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(
expect::event()
.with_fields(expect::field("return").with_value(&tracing::field::debug(42)))
.at_level(Level::INFO),
)
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, ret_impl_type);
handle.assert_finished();
}
#[instrument(ret(Display))]
fn ret_display() -> i32 {
42
}
#[test]
fn test_dbg() {
let span = expect::span().named("ret_display");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(
expect::event()
.with_fields(expect::field("return").with_value(&tracing::field::display(42)))
.at_level(Level::INFO),
)
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, ret_display);
handle.assert_finished();
}
#[instrument(err, ret)]
fn ret_and_err() -> Result<u8, TryFromIntError> {
u8::try_from(1234)
}
#[test]
fn test_ret_and_err() {
let span = expect::span().named("ret_and_err");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(
expect::event()
.with_fields(
expect::field("error")
.with_value(&tracing::field::display(u8::try_from(1234).unwrap_err()))
.only(),
)
.at_level(Level::ERROR),
)
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, || ret_and_err().ok());
handle.assert_finished();
}
#[instrument(err, ret)]
fn ret_and_ok() -> Result<u8, TryFromIntError> {
u8::try_from(123)
}
#[test]
fn test_ret_and_ok() {
let span = expect::span().named("ret_and_ok");
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(
expect::event()
.with_fields(
expect::field("return")
.with_value(&tracing::field::debug(u8::try_from(123).unwrap()))
.only(),
)
.at_level(Level::INFO),
)
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, || ret_and_ok().ok());
handle.assert_finished();
}
#[instrument(level = "warn", ret(level = "info"))]
fn ret_warn_info() -> i32 {
42
}
#[test]
fn test_warn_info() {
let span = expect::span().named("ret_warn_info").at_level(Level::WARN);
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(
expect::event()
.with_fields(expect::field("return").with_value(&tracing::field::debug(42)))
.at_level(Level::INFO),
)
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, ret_warn_info);
handle.assert_finished();
}
#[instrument(ret(level = "warn", Debug))]
fn ret_dbg_warn() -> i32 {
42
}
#[test]
fn test_dbg_warn() {
let span = expect::span().named("ret_dbg_warn").at_level(Level::INFO);
let (subscriber, handle) = subscriber::mock()
.new_span(span.clone())
.enter(span.clone())
.event(
expect::event()
.with_fields(expect::field("return").with_value(&tracing::field::debug(42)))
.at_level(Level::WARN),
)
.exit(span.clone())
.drop_span(span)
.only()
.run_with_handle();
with_default(subscriber, ret_dbg_warn);
handle.assert_finished();
}

View File

@@ -0,0 +1,109 @@
use tracing::subscriber::with_default;
use tracing_attributes::instrument;
use tracing_mock::*;
#[instrument]
fn default_target() {}
#[instrument(target = "my_target")]
fn custom_target() {}
mod my_mod {
use tracing_attributes::instrument;
pub const MODULE_PATH: &str = module_path!();
#[instrument]
pub fn default_target() {}
#[instrument(target = "my_other_target")]
pub fn custom_target() {}
}
#[test]
fn default_targets() {
let (subscriber, handle) = subscriber::mock()
.new_span(
expect::span()
.named("default_target")
.with_target(module_path!()),
)
.enter(
expect::span()
.named("default_target")
.with_target(module_path!()),
)
.exit(
expect::span()
.named("default_target")
.with_target(module_path!()),
)
.new_span(
expect::span()
.named("default_target")
.with_target(my_mod::MODULE_PATH),
)
.enter(
expect::span()
.named("default_target")
.with_target(my_mod::MODULE_PATH),
)
.exit(
expect::span()
.named("default_target")
.with_target(my_mod::MODULE_PATH),
)
.only()
.run_with_handle();
with_default(subscriber, || {
default_target();
my_mod::default_target();
});
handle.assert_finished();
}
#[test]
fn custom_targets() {
let (subscriber, handle) = subscriber::mock()
.new_span(
expect::span()
.named("custom_target")
.with_target("my_target"),
)
.enter(
expect::span()
.named("custom_target")
.with_target("my_target"),
)
.exit(
expect::span()
.named("custom_target")
.with_target("my_target"),
)
.new_span(
expect::span()
.named("custom_target")
.with_target("my_other_target"),
)
.enter(
expect::span()
.named("custom_target")
.with_target("my_other_target"),
)
.exit(
expect::span()
.named("custom_target")
.with_target("my_other_target"),
)
.only()
.run_with_handle();
with_default(subscriber, || {
custom_target();
my_mod::custom_target();
});
handle.assert_finished();
}

15
vendor/tracing-attributes/tests/ui.rs vendored Normal file
View File

@@ -0,0 +1,15 @@
// Only test on stable, since UI tests are bound to change over time
#[rustversion::stable]
#[test]
fn pass() {
let t = trybuild::TestCases::new();
t.pass("tests/ui/pass/*.rs");
}
#[rustversion::stable]
#[test]
fn compile_fail() {
let t = trybuild::TestCases::new();
t.compile_fail("tests/ui/fail/*.rs");
}

View File

@@ -0,0 +1,45 @@
#![allow(unreachable_code)]
#[tracing::instrument]
async fn unit() {
""
}
#[tracing::instrument]
async fn simple_mismatch() -> String {
""
}
#[tracing::instrument]
async fn opaque_unsatisfied() -> impl std::fmt::Display {
("",)
}
struct Wrapper<T>(T);
#[tracing::instrument]
async fn mismatch_with_opaque() -> Wrapper<impl std::fmt::Display> {
""
}
#[tracing::instrument]
async fn early_return_unit() {
if true {
return "";
}
}
#[tracing::instrument]
async fn early_return() -> String {
if true {
return "";
}
String::new()
}
#[tracing::instrument]
async fn extra_semicolon() -> i32 {
1;
}
fn main() {}

View File

@@ -0,0 +1,104 @@
error[E0308]: mismatched types
--> tests/ui/fail/async_instrument.rs:5:5
|
5 | ""
| ^^ expected `()`, found `&str`
|
note: return type inferred to be `()` here
--> tests/ui/fail/async_instrument.rs:4:10
|
4 | async fn unit() {
| ^^^^
error[E0308]: mismatched types
--> tests/ui/fail/async_instrument.rs:10:5
|
10 | ""
| ^^- help: try using a conversion method: `.to_string()`
| |
| expected `String`, found `&str`
|
note: return type inferred to be `String` here
--> tests/ui/fail/async_instrument.rs:9:31
|
9 | async fn simple_mismatch() -> String {
| ^^^^^^
error[E0277]: `(&str,)` doesn't implement `std::fmt::Display`
--> tests/ui/fail/async_instrument.rs:14:57
|
14 | async fn opaque_unsatisfied() -> impl std::fmt::Display {
| _________________________________________________________-
15 | | ("",)
16 | | }
| | ^
| | |
| |_`(&str,)` cannot be formatted with the default formatter
| return type was inferred to be `(&str,)` here
|
= help: the trait `std::fmt::Display` is not implemented for `(&str,)`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
error[E0277]: `(&str,)` doesn't implement `std::fmt::Display`
--> tests/ui/fail/async_instrument.rs:14:34
|
14 | async fn opaque_unsatisfied() -> impl std::fmt::Display {
| ^^^^^^^^^^^^^^^^^^^^^^ `(&str,)` cannot be formatted with the default formatter
|
= help: the trait `std::fmt::Display` is not implemented for `(&str,)`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
error[E0308]: mismatched types
--> tests/ui/fail/async_instrument.rs:22:5
|
22 | ""
| ^^ expected `Wrapper<_>`, found `&str`
|
= note: expected struct `Wrapper<_>`
found reference `&'static str`
note: return type inferred to be `Wrapper<_>` here
--> tests/ui/fail/async_instrument.rs:21:36
|
21 | async fn mismatch_with_opaque() -> Wrapper<impl std::fmt::Display> {
| ^^^^^^^
help: try wrapping the expression in `Wrapper`
|
22 | Wrapper("")
| ++++++++ +
error[E0308]: mismatched types
--> tests/ui/fail/async_instrument.rs:28:16
|
28 | return "";
| ^^ expected `()`, found `&str`
|
note: return type inferred to be `()` here
--> tests/ui/fail/async_instrument.rs:26:10
|
26 | async fn early_return_unit() {
| ^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> tests/ui/fail/async_instrument.rs:35:16
|
35 | return "";
| ^^- help: try using a conversion method: `.to_string()`
| |
| expected `String`, found `&str`
|
note: return type inferred to be `String` here
--> tests/ui/fail/async_instrument.rs:33:28
|
33 | async fn early_return() -> String {
| ^^^^^^
error[E0308]: mismatched types
--> tests/ui/fail/async_instrument.rs:40:1
|
40 | #[tracing::instrument]
| ^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `()`
41 | async fn extra_semicolon() -> i32 {
42 | 1;
| - help: remove this semicolon to return this value
|
= note: this error originates in the attribute macro `tracing::instrument` (in Nightly builds, run with -Z macro-backtrace for more info)

View File

@@ -0,0 +1,8 @@
#![allow(unreachable_code)]
#[tracing::instrument]
const fn unit() {
""
}
fn main() {}

View File

@@ -0,0 +1,15 @@
error: macros that expand to items must be delimited with braces or followed by a semicolon
--> tests/ui/fail/const_instrument.rs:3:1
|
3 | #[tracing::instrument]
| ^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in the attribute macro `tracing::instrument` (in Nightly builds, run with -Z macro-backtrace for more info)
error: the `#[instrument]` attribute may not be used with `const fn`s
--> tests/ui/fail/const_instrument.rs:3:1
|
3 | #[tracing::instrument]
| ^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in the attribute macro `tracing::instrument` (in Nightly builds, run with -Z macro-backtrace for more info)

View File

@@ -0,0 +1,6 @@
#![deny(dead_code)]
#[tracing::instrument]
fn never_used() {}
fn main() {}

View File

@@ -0,0 +1,11 @@
error: function `never_used` is never used
--> tests/ui/fail/unused_instrumented_fn.rs:4:4
|
4 | fn never_used() {}
| ^^^^^^^^^^
|
note: the lint level is defined here
--> tests/ui/fail/unused_instrumented_fn.rs:1:9
|
1 | #![deny(dead_code)]
| ^^^^^^^^^

View File

@@ -0,0 +1,17 @@
//! This program is a regression test for [#3306], where shadowing
//! caused compilation failure in certain cases due to the original
//! function body not getting its own scope.
//!
//! [#3306]: https://github.com/tokio-rs/tracing/issues/3306
type Foo = ();
enum Bar {
Foo,
}
#[tracing::instrument]
fn this_is_fine() -> Foo {
// glob import imports Bar::Foo, shadowing Foo
use Bar::*;
}
fn main() {}