mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-26 00:00:16 +02:00
171 lines
5.5 KiB
Rust
171 lines
5.5 KiB
Rust
#[macro_use]
|
|||
|
|
extern crate tokio_trace;
|
||
|
|
mod support;
|
||
|
|
|
||
|
|
use self::support::*;
|
||
|
|
use tokio_trace::{dispatcher, Dispatch};
|
||
|
|
|
||
|
|
use std::sync::{
|
||
|
|
atomic::{AtomicUsize, Ordering},
|
||
|
|
Arc,
|
||
|
|
};
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn filters_are_not_reevaluated_for_the_same_span() {
|
||
|
|
// Asserts that the `span!` macro caches the result of calling
|
||
|
|
// `Subscriber::enabled` for each span.
|
||
|
|
let alice_count = Arc::new(AtomicUsize::new(0));
|
||
|
|
let bob_count = Arc::new(AtomicUsize::new(0));
|
||
|
|
let alice_count2 = alice_count.clone();
|
||
|
|
let bob_count2 = bob_count.clone();
|
||
|
|
|
||
|
|
let (subscriber, handle) = subscriber::mock()
|
||
|
|
.with_filter(move |meta| match meta.name {
|
||
|
|
"alice" => {
|
||
|
|
alice_count2.fetch_add(1, Ordering::Relaxed);
|
||
|
|
false
|
||
|
|
}
|
||
|
|
"bob" => {
|
||
|
|
bob_count2.fetch_add(1, Ordering::Relaxed);
|
||
|
|
true
|
||
|
|
}
|
||
|
|
_ => false,
|
||
|
|
})
|
||
|
|
.run_with_handle();
|
||
|
|
|
||
|
|
dispatcher::with_default(Dispatch::new(subscriber), move || {
|
||
|
|
// Enter "alice" and then "bob". The dispatcher expects to see "bob" but
|
||
|
|
// not "alice."
|
||
|
|
let mut alice = span!("alice");
|
||
|
|
let mut bob = alice.enter(|| {
|
||
|
|
let mut bob = span!("bob");
|
||
|
|
bob.enter(|| ());
|
||
|
|
bob
|
||
|
|
});
|
||
|
|
|
||
|
|
// The filter should have seen each span a single time.
|
||
|
|
assert_eq!(alice_count.load(Ordering::Relaxed), 1);
|
||
|
|
assert_eq!(bob_count.load(Ordering::Relaxed), 1);
|
||
|
|
|
||
|
|
alice.enter(|| bob.enter(|| {}));
|
||
|
|
|
||
|
|
// The subscriber should see "bob" again, but the filter should not have
|
||
|
|
// been called.
|
||
|
|
assert_eq!(alice_count.load(Ordering::Relaxed), 1);
|
||
|
|
assert_eq!(bob_count.load(Ordering::Relaxed), 1);
|
||
|
|
|
||
|
|
bob.enter(|| {});
|
||
|
|
assert_eq!(alice_count.load(Ordering::Relaxed), 1);
|
||
|
|
assert_eq!(bob_count.load(Ordering::Relaxed), 1);
|
||
|
|
});
|
||
|
|
handle.assert_finished();
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn filters_are_reevaluated_for_different_call_sites() {
|
||
|
|
// Asserts that the `span!` macro caches the result of calling
|
||
|
|
// `Subscriber::enabled` for each span.
|
||
|
|
let charlie_count = Arc::new(AtomicUsize::new(0));
|
||
|
|
let dave_count = Arc::new(AtomicUsize::new(0));
|
||
|
|
let charlie_count2 = charlie_count.clone();
|
||
|
|
let dave_count2 = dave_count.clone();
|
||
|
|
|
||
|
|
let subscriber = subscriber::mock()
|
||
|
|
.with_filter(move |meta| {
|
||
|
|
println!("Filter: {:?}", meta.name);
|
||
|
|
match meta.name {
|
||
|
|
"charlie" => {
|
||
|
|
charlie_count2.fetch_add(1, Ordering::Relaxed);
|
||
|
|
false
|
||
|
|
}
|
||
|
|
"dave" => {
|
||
|
|
dave_count2.fetch_add(1, Ordering::Relaxed);
|
||
|
|
true
|
||
|
|
}
|
||
|
|
_ => false,
|
||
|
|
}
|
||
|
|
})
|
||
|
|
.run();
|
||
|
|
|
||
|
|
dispatcher::with_default(Dispatch::new(subscriber), move || {
|
||
|
|
// Enter "charlie" and then "dave". The dispatcher expects to see "dave" but
|
||
|
|
// not "charlie."
|
||
|
|
let mut charlie = span!("charlie");
|
||
|
|
let mut dave = charlie.enter(|| {
|
||
|
|
let mut dave = span!("dave");
|
||
|
|
dave.enter(|| {});
|
||
|
|
dave
|
||
|
|
});
|
||
|
|
|
||
|
|
// The filter should have seen each span a single time.
|
||
|
|
assert_eq!(charlie_count.load(Ordering::Relaxed), 1);
|
||
|
|
assert_eq!(dave_count.load(Ordering::Relaxed), 1);
|
||
|
|
|
||
|
|
charlie.enter(|| dave.enter(|| {}));
|
||
|
|
|
||
|
|
// The subscriber should see "dave" again, but the filter should not have
|
||
|
|
// been called.
|
||
|
|
assert_eq!(charlie_count.load(Ordering::Relaxed), 1);
|
||
|
|
assert_eq!(dave_count.load(Ordering::Relaxed), 1);
|
||
|
|
|
||
|
|
// A different span with the same name has a different call site, so it
|
||
|
|
// should cause the filter to be reapplied.
|
||
|
|
let mut charlie2 = span!("charlie");
|
||
|
|
charlie.enter(|| {});
|
||
|
|
assert_eq!(charlie_count.load(Ordering::Relaxed), 2);
|
||
|
|
assert_eq!(dave_count.load(Ordering::Relaxed), 1);
|
||
|
|
|
||
|
|
// But, the filter should not be re-evaluated for the new "charlie" span
|
||
|
|
// when it is re-entered.
|
||
|
|
charlie2.enter(|| span!("dave").enter(|| {}));
|
||
|
|
assert_eq!(charlie_count.load(Ordering::Relaxed), 2);
|
||
|
|
assert_eq!(dave_count.load(Ordering::Relaxed), 2);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn filter_caching_is_lexically_scoped() {
|
||
|
|
pub fn my_great_function() -> bool {
|
||
|
|
span!("emily").enter(|| true)
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn my_other_function() -> bool {
|
||
|
|
span!("frank").enter(|| true)
|
||
|
|
}
|
||
|
|
|
||
|
|
let count = Arc::new(AtomicUsize::new(0));
|
||
|
|
let count2 = count.clone();
|
||
|
|
|
||
|
|
let subscriber = subscriber::mock()
|
||
|
|
.with_filter(move |meta| match meta.name {
|
||
|
|
"emily" | "frank" => {
|
||
|
|
count2.fetch_add(1, Ordering::Relaxed);
|
||
|
|
true
|
||
|
|
}
|
||
|
|
_ => false,
|
||
|
|
})
|
||
|
|
.run();
|
||
|
|
|
||
|
|
dispatcher::with_default(Dispatch::new(subscriber), || {
|
||
|
|
// Call the function once. The filter should be re-evaluated.
|
||
|
|
assert!(my_great_function());
|
||
|
|
assert_eq!(count.load(Ordering::Relaxed), 1);
|
||
|
|
|
||
|
|
// Call the function again. The cached result should be used.
|
||
|
|
assert!(my_great_function());
|
||
|
|
assert_eq!(count.load(Ordering::Relaxed), 1);
|
||
|
|
|
||
|
|
assert!(my_other_function());
|
||
|
|
assert_eq!(count.load(Ordering::Relaxed), 2);
|
||
|
|
|
||
|
|
assert!(my_great_function());
|
||
|
|
assert_eq!(count.load(Ordering::Relaxed), 2);
|
||
|
|
|
||
|
|
assert!(my_other_function());
|
||
|
|
assert_eq!(count.load(Ordering::Relaxed), 2);
|
||
|
|
|
||
|
|
assert!(my_great_function());
|
||
|
|
assert_eq!(count.load(Ordering::Relaxed), 2);
|
||
|
|
});
|
||
|
|
}
|