tracing/tracing-mock/tests/span_ancestry.rs
Hayden Stainsby 21c5ce05cc
mock: match parent span on ExpectedSpan (#3098)
## Motivation

The `with_ancestry` methods on `NewSpan` and `ExpectedEvent` provide a
way to match whether the span or event is a contextual or explicit root
or if it has a contextual or explicit parent span.

However, in the case of matching on a contextual or explicit parent
span, only the span name could be used for matching. This is
sufficiently precise when testing tracing instrumentation in other
libraries or applications as opposed to testing tracing itself.

It is likely that a user would like to test that some span or event has
a specific span as a parent, and not just any span with a specific name,
in many cases, all the possible parent spans may have the same name.
This is the case when testing tracing instrumentation in Tokio.

## Solution

To solve this problem, the `Ancestry` struct was renamed to
`ExpectedAncestry` and in the case of expecting an explicit or
conextual parent, an `ExpectedSpan` object can be passed in. This
provides the maximum possible flexibility.

The convenience functions in the `expect` module now take
`Into<ExpectedSpan>` so that existing tests that pass a string type
object for the parent will see the same behaviour as previously and
shorthand use for expected Ids is also available.

Additionally, the span checking code has been unified between the
`MockCollector` and `MockSubscriber` cases and the assertion
descriptions have been improved to make them more readable.
2024-10-30 15:31:46 +01:00

473 lines
13 KiB
Rust

//! Tests assertions for the parent made on [`ExpectedSpan`].
//!
//! The tests in this module completely cover the positive and negative cases
//! when expecting that a span is a contextual or explicit root or expecting
//! that a span has a specific contextual or explicit parent.
//!
//! [`ExpectedSpan`]: crate::span::ExpectedSpan
//!
use tracing::{collect::with_default, Level};
use tracing_mock::{collector, expect};
#[test]
fn contextual_parent() {
let span = expect::span()
.named("span")
.with_ancestry(expect::has_contextual_parent("contextual parent"));
let (collector, handle) = collector::mock()
.enter(expect::span())
.new_span(span)
.run_with_handle();
with_default(collector, || {
let _guard = tracing::info_span!("contextual parent").entered();
tracing::info_span!("span");
});
handle.assert_finished();
}
#[test]
#[should_panic(
expected = "to have a contextual parent span named `contextual parent`,\n\
[contextual_parent_wrong_name] but got one named `another parent` instead."
)]
fn contextual_parent_wrong_name() {
let span = expect::span()
.named("span")
.with_ancestry(expect::has_contextual_parent("contextual parent"));
let (collector, handle) = collector::mock()
.enter(expect::span())
.new_span(span)
.run_with_handle();
with_default(collector, || {
let _guard = tracing::info_span!("another parent").entered();
tracing::info_span!("span");
});
handle.assert_finished();
}
#[test]
#[should_panic(expected = "to have a contextual parent span a span with Id `1`,\n\
[contextual_parent_wrong_id] but got one with Id `2` instead")]
fn contextual_parent_wrong_id() {
let id = expect::id();
let span = expect::span()
.named("span")
.with_ancestry(expect::has_contextual_parent(&id));
let (collector, handle) = collector::mock()
.new_span(&id)
.new_span(expect::span())
.enter(expect::span())
.new_span(span)
.run_with_handle();
with_default(collector, || {
let _span = tracing::info_span!("contextual parent");
let _guard = tracing::info_span!("another parent").entered();
tracing::info_span!("span");
});
handle.assert_finished();
}
#[test]
#[should_panic(
expected = "to have a contextual parent span at level `Level(Info)`,\n\
[contextual_parent_wrong_level] but got one at level `Level(Debug)` instead."
)]
fn contextual_parent_wrong_level() {
let parent = expect::span().at_level(Level::INFO);
let span = expect::span()
.named("span")
.with_ancestry(expect::has_contextual_parent(parent));
let (collector, handle) = collector::mock()
.enter(expect::span())
.new_span(span)
.run_with_handle();
with_default(collector, || {
let _guard = tracing::debug_span!("contextual parent").entered();
tracing::info_span!("span");
});
handle.assert_finished();
}
#[test]
#[should_panic(expected = "to have a contextual parent span, but it is actually a \
contextual root")]
fn expect_contextual_parent_actual_contextual_root() {
let span = expect::span()
.named("span")
.with_ancestry(expect::has_contextual_parent("contextual parent"));
let (collector, handle) = collector::mock().new_span(span).run_with_handle();
with_default(collector, || {
tracing::info_span!("span");
});
handle.assert_finished();
}
#[test]
#[should_panic(expected = "to have a contextual parent span, but it actually has an \
explicit parent span")]
fn expect_contextual_parent_actual_explicit_parent() {
let span = expect::span()
.named("span")
.with_ancestry(expect::has_contextual_parent("contextual parent"));
let (collector, handle) = collector::mock()
.new_span(expect::span())
.new_span(span)
.run_with_handle();
with_default(collector, || {
let span = tracing::info_span!("explicit parent");
tracing::info_span!(parent: span.id(), "span");
});
handle.assert_finished();
}
#[test]
#[should_panic(expected = "to have a contextual parent span, but it is actually an \
explicit root")]
fn expect_contextual_parent_actual_explicit_root() {
let span = expect::span()
.named("span")
.with_ancestry(expect::has_contextual_parent("contextual parent"));
let (collector, handle) = collector::mock()
.enter(expect::span())
.new_span(span)
.run_with_handle();
with_default(collector, || {
let _guard = tracing::info_span!("contextual parent").entered();
tracing::info_span!(parent: None, "span");
});
handle.assert_finished();
}
#[test]
fn contextual_root() {
let span = expect::span()
.named("span")
.with_ancestry(expect::is_contextual_root());
let (collector, handle) = collector::mock().new_span(span).run_with_handle();
with_default(collector, || {
tracing::info_span!("span");
});
handle.assert_finished();
}
#[test]
#[should_panic(expected = "to be a contextual root, but it actually has a contextual parent span")]
fn expect_contextual_root_actual_contextual_parent() {
let span = expect::span()
.named("span")
.with_ancestry(expect::is_contextual_root());
let (collector, handle) = collector::mock()
.enter(expect::span())
.new_span(span)
.run_with_handle();
with_default(collector, || {
let _guard = tracing::info_span!("contextual parent").entered();
tracing::info_span!("span");
});
handle.assert_finished();
}
#[test]
#[should_panic(expected = "to be a contextual root, but it actually has an explicit parent span")]
fn expect_contextual_root_actual_explicit_parent() {
let span = expect::span()
.named("span")
.with_ancestry(expect::is_contextual_root());
let (collector, handle) = collector::mock()
.new_span(expect::span())
.new_span(span)
.run_with_handle();
with_default(collector, || {
let span = tracing::info_span!("explicit parent");
tracing::info_span!(parent: span.id(), "span");
});
handle.assert_finished();
}
#[test]
#[should_panic(expected = "to be a contextual root, but it is actually an explicit root")]
fn expect_contextual_root_actual_explicit_root() {
let span = expect::span()
.named("span")
.with_ancestry(expect::is_contextual_root());
let (collector, handle) = collector::mock()
.enter(expect::span())
.new_span(span)
.run_with_handle();
with_default(collector, || {
let _guard = tracing::info_span!("contextual parent").entered();
tracing::info_span!(parent: None, "span");
});
handle.assert_finished();
}
#[test]
fn explicit_parent() {
let span = expect::span()
.named("span")
.with_ancestry(expect::has_explicit_parent("explicit parent"));
let (collector, handle) = collector::mock()
.new_span(expect::span())
.new_span(span)
.run_with_handle();
with_default(collector, || {
let span = tracing::info_span!("explicit parent");
tracing::info_span!(parent: span.id(), "span");
});
handle.assert_finished();
}
#[test]
#[should_panic(
expected = "to have an explicit parent span named `explicit parent`,\n\
[explicit_parent_wrong_name] but got one named `another parent` instead."
)]
fn explicit_parent_wrong_name() {
let span = expect::span()
.named("span")
.with_ancestry(expect::has_explicit_parent("explicit parent"));
let (collector, handle) = collector::mock()
.new_span(expect::span())
.new_span(span)
.run_with_handle();
with_default(collector, || {
let span = tracing::info_span!("another parent");
tracing::info_span!(parent: span.id(), "span");
});
handle.assert_finished();
}
#[test]
#[should_panic(expected = "to have an explicit parent span a span with Id `1`,\n\
[explicit_parent_wrong_id] but got one with Id `2` instead")]
fn explicit_parent_wrong_id() {
let id = expect::id();
let span = expect::span()
.named("span")
.with_ancestry(expect::has_explicit_parent(&id));
let (collector, handle) = collector::mock()
.new_span(&id)
.new_span(expect::span())
.new_span(span)
.run_with_handle();
with_default(collector, || {
let _span = tracing::info_span!("explicit parent");
let another_span = tracing::info_span!("another parent");
tracing::info_span!(parent: another_span.id(), "span");
});
handle.assert_finished();
}
#[test]
#[should_panic(expected = "to have an explicit parent span at level `Level(Info)`,\n\
[explicit_parent_wrong_level] but got one at level `Level(Debug)` instead.")]
fn explicit_parent_wrong_level() {
let parent = expect::span().at_level(Level::INFO);
let span = expect::span()
.named("span")
.with_ancestry(expect::has_explicit_parent(parent));
let (collector, handle) = collector::mock()
.new_span(expect::span())
.new_span(span)
.run_with_handle();
with_default(collector, || {
let span = tracing::debug_span!("explicit parent");
tracing::info_span!(parent: span.id(), "span");
});
handle.assert_finished();
}
#[test]
#[should_panic(expected = "to have an explicit parent span, but it actually has a \
contextual parent span")]
fn expect_explicit_parent_actual_contextual_parent() {
let span = expect::span()
.named("span")
.with_ancestry(expect::has_explicit_parent("explicit parent"));
let (collector, handle) = collector::mock()
.enter(expect::span())
.new_span(span)
.run_with_handle();
with_default(collector, || {
let _guard = tracing::info_span!("contextual parent").entered();
tracing::info_span!("span");
});
handle.assert_finished();
}
#[test]
#[should_panic(expected = "to have an explicit parent span, but it is actually a \
contextual root")]
fn expect_explicit_parent_actual_contextual_root() {
let span = expect::span()
.named("span")
.with_ancestry(expect::has_explicit_parent("explicit parent"));
let (collector, handle) = collector::mock().new_span(span).run_with_handle();
with_default(collector, || {
tracing::info_span!("span");
});
handle.assert_finished();
}
#[test]
#[should_panic(expected = "to have an explicit parent span, but it is actually an \
explicit root")]
fn expect_explicit_parent_actual_explicit_root() {
let span = expect::span()
.named("span")
.with_ancestry(expect::has_explicit_parent("explicit parent"));
let (collector, handle) = collector::mock()
.enter(expect::span())
.new_span(span)
.run_with_handle();
with_default(collector, || {
let _guard = tracing::info_span!("contextual parent").entered();
tracing::info_span!(parent: None, "span");
});
handle.assert_finished();
}
#[test]
fn explicit_root() {
let span = expect::span()
.named("span")
.with_ancestry(expect::is_explicit_root());
let (collector, handle) = collector::mock()
.new_span(expect::span())
.enter(expect::span())
.new_span(span)
.run_with_handle();
with_default(collector, || {
let _guard = tracing::info_span!("contextual parent").entered();
tracing::info_span!(parent: None, "span");
});
handle.assert_finished();
}
#[test]
#[should_panic(expected = "to be an explicit root, but it actually has a contextual parent span")]
fn expect_explicit_root_actual_contextual_parent() {
let span = expect::span()
.named("span")
.with_ancestry(expect::is_explicit_root());
let (collector, handle) = collector::mock()
.enter(expect::span())
.new_span(span)
.run_with_handle();
with_default(collector, || {
let _guard = tracing::info_span!("contextual parent").entered();
tracing::info_span!("span");
});
handle.assert_finished();
}
#[test]
#[should_panic(expected = "to be an explicit root, but it is actually a contextual root")]
fn expect_explicit_root_actual_contextual_root() {
let span = expect::span()
.named("span")
.with_ancestry(expect::is_explicit_root());
let (collector, handle) = collector::mock().new_span(span).run_with_handle();
with_default(collector, || {
tracing::info_span!("span");
});
handle.assert_finished();
}
#[test]
#[should_panic(expected = "to be an explicit root, but it actually has an explicit parent span")]
fn expect_explicit_root_actual_explicit_parent() {
let span = expect::span()
.named("span")
.with_ancestry(expect::is_explicit_root());
let (collector, handle) = collector::mock()
.new_span(expect::span())
.new_span(span)
.run_with_handle();
with_default(collector, || {
let span = tracing::info_span!("explicit parent");
tracing::info_span!(parent: span.id(), "span");
});
handle.assert_finished();
}
#[test]
fn explicit_and_contextual_root_is_explicit() {
let span = expect::span()
.named("span")
.with_ancestry(expect::is_explicit_root());
let (collector, handle) = collector::mock().new_span(span).run_with_handle();
with_default(collector, || {
tracing::info_span!(parent: None, "span");
});
handle.assert_finished();
}