]>
git.proxmox.com Git - rustc.git/blob - vendor/tracing/tests/support/subscriber.rs
1 #![allow(missing_docs)]
5 span
::{MockSpan, NewSpan}
,
9 collections
::{HashMap, VecDeque}
,
12 atomic
::{AtomicUsize, Ordering}
,
17 level_filters
::LevelFilter
,
18 span
::{self, Attributes, Id}
,
19 Event
, Metadata
, Subscriber
,
22 #[derive(Debug, Eq, PartialEq)]
29 Visit(MockSpan
, mock_field
::Expect
),
39 struct Running
<F
: Fn(&Metadata
<'_
>) -> bool
> {
40 spans
: Mutex
<HashMap
<Id
, SpanState
>>,
41 expected
: Arc
<Mutex
<VecDeque
<Expect
>>>,
42 current
: Mutex
<Vec
<Id
>>,
44 max_level
: Option
<LevelFilter
>,
48 pub struct MockSubscriber
<F
: Fn(&Metadata
<'_
>) -> bool
> {
49 expected
: VecDeque
<Expect
>,
50 max_level
: Option
<LevelFilter
>,
54 pub struct MockHandle(Arc
<Mutex
<VecDeque
<Expect
>>>);
56 pub fn mock() -> MockSubscriber
<fn(&Metadata
<'_
>) -> bool
> {
58 expected
: VecDeque
::new(),
59 filter
: (|_
: &Metadata
<'_
>| true) as for<'r
, 's
> fn(&'r Metadata
<'s
>) -> _
,
64 impl<F
> MockSubscriber
<F
>
66 F
: Fn(&Metadata
<'_
>) -> bool
+ '
static,
68 pub fn enter(mut self, span
: MockSpan
) -> Self {
69 self.expected
.push_back(Expect
::Enter(span
));
73 pub fn event(mut self, event
: MockEvent
) -> Self {
74 self.expected
.push_back(Expect
::Event(event
));
78 pub fn exit(mut self, span
: MockSpan
) -> Self {
79 self.expected
.push_back(Expect
::Exit(span
));
83 pub fn clone_span(mut self, span
: MockSpan
) -> Self {
84 self.expected
.push_back(Expect
::CloneSpan(span
));
89 pub fn drop_span(mut self, span
: MockSpan
) -> Self {
90 self.expected
.push_back(Expect
::DropSpan(span
));
94 pub fn done(mut self) -> Self {
95 self.expected
.push_back(Expect
::Nothing
);
99 pub fn record
<I
>(mut self, span
: MockSpan
, fields
: I
) -> Self
101 I
: Into
<mock_field
::Expect
>,
103 self.expected
.push_back(Expect
::Visit(span
, fields
.into()));
107 pub fn new_span
<I
>(mut self, new_span
: I
) -> Self
111 self.expected
.push_back(Expect
::NewSpan(new_span
.into()));
115 pub fn with_filter
<G
>(self, filter
: G
) -> MockSubscriber
<G
>
117 G
: Fn(&Metadata
<'_
>) -> bool
+ '
static,
120 expected
: self.expected
,
122 max_level
: self.max_level
,
126 pub fn with_max_level_hint(self, hint
: impl Into
<LevelFilter
>) -> Self {
128 max_level
: Some(hint
.into()),
133 pub fn run(self) -> impl Subscriber
{
134 let (subscriber
, _
) = self.run_with_handle();
138 pub fn run_with_handle(self) -> (impl Subscriber
, MockHandle
) {
139 let expected
= Arc
::new(Mutex
::new(self.expected
));
140 let handle
= MockHandle(expected
.clone());
141 let subscriber
= Running
{
142 spans
: Mutex
::new(HashMap
::new()),
144 current
: Mutex
::new(Vec
::new()),
145 ids
: AtomicUsize
::new(1),
147 max_level
: self.max_level
,
153 impl<F
> Subscriber
for Running
<F
>
155 F
: Fn(&Metadata
<'_
>) -> bool
+ '
static,
157 fn enabled(&self, meta
: &Metadata
<'_
>) -> bool
{
161 fn max_level_hint(&self) -> Option
<LevelFilter
> {
162 self.max_level
.clone()
165 fn record(&self, id
: &Id
, values
: &span
::Record
<'_
>) {
166 let spans
= self.spans
.lock().unwrap();
167 let mut expected
= self.expected
.lock().unwrap();
170 .unwrap_or_else(|| panic
!("no span for ID {:?}", id
));
171 println
!("record: {}; id={:?}; values={:?};", span
.name
, id
, values
);
172 let was_expected
= if let Some(Expect
::Visit(_
, _
)) = expected
.front() {
178 if let Expect
::Visit(expected_span
, mut expected_values
) = expected
.pop_front().unwrap()
180 if let Some(name
) = expected_span
.name() {
181 assert_eq
!(name
, span
.name
);
183 let mut checker
= expected_values
.checker(format
!("span {}: ", span
.name
));
184 values
.record(&mut checker
);
190 fn event(&self, event
: &Event
<'_
>) {
191 let name
= event
.metadata().name();
192 println
!("event: {};", name
);
193 match self.expected
.lock().unwrap().pop_front() {
195 Some(Expect
::Event(mut expected
)) => {
196 let spans
= self.spans
.lock().unwrap();
197 expected
.check(event
);
198 match expected
.parent
{
199 Some(Parent
::ExplicitRoot
) => {
202 "expected {:?} to be an explicit root event",
206 Some(Parent
::Explicit(expected_parent
)) => {
208 event
.parent().and_then(|id
| spans
.get(id
)).map(|s
| s
.name
);
210 Some(expected_parent
.as_ref()),
212 "expected {:?} to have explicit parent {:?}",
217 Some(Parent
::ContextualRoot
) => {
219 event
.is_contextual(),
220 "expected {:?} to have a contextual parent",
224 self.current
.lock().unwrap().last().is_none(),
225 "expected {:?} to be a root, but we were inside a span",
229 Some(Parent
::Contextual(expected_parent
)) => {
231 event
.is_contextual(),
232 "expected {:?} to have a contextual parent",
235 let stack
= self.current
.lock().unwrap();
237 stack
.last().and_then(|id
| spans
.get(id
)).map(|s
| s
.name
);
239 Some(expected_parent
.as_ref()),
241 "expected {:?} to have contextual parent {:?}",
249 Some(ex
) => ex
.bad(format_args
!("observed event {:?}", event
)),
253 fn record_follows_from(&self, _span
: &Id
, _follows
: &Id
) {
254 // TODO: it should be possible to expect spans to follow from other spans
257 fn new_span(&self, span
: &Attributes
<'_
>) -> Id
{
258 let meta
= span
.metadata();
259 let id
= self.ids
.fetch_add(1, Ordering
::SeqCst
);
260 let id
= Id
::from_u64(id
as u64);
262 "new_span: name={:?}; target={:?}; id={:?};",
267 let mut expected
= self.expected
.lock().unwrap();
268 let was_expected
= match expected
.front() {
269 Some(Expect
::NewSpan(_
)) => true,
272 let mut spans
= self.spans
.lock().unwrap();
274 if let Expect
::NewSpan(mut expected
) = expected
.pop_front().unwrap() {
275 let name
= meta
.name();
279 .check(meta
, format_args
!("span `{}`", name
));
280 let mut checker
= expected
.fields
.checker(name
.to_string());
281 span
.record(&mut checker
);
283 match expected
.parent
{
284 Some(Parent
::ExplicitRoot
) => {
287 "expected {:?} to be an explicit root span",
291 Some(Parent
::Explicit(expected_parent
)) => {
293 span
.parent().and_then(|id
| spans
.get(id
)).map(|s
| s
.name
);
295 Some(expected_parent
.as_ref()),
297 "expected {:?} to have explicit parent {:?}",
302 Some(Parent
::ContextualRoot
) => {
304 span
.is_contextual(),
305 "expected {:?} to have a contextual parent",
309 self.current
.lock().unwrap().last().is_none(),
310 "expected {:?} to be a root, but we were inside a span",
314 Some(Parent
::Contextual(expected_parent
)) => {
316 span
.is_contextual(),
317 "expected {:?} to have a contextual parent",
320 let stack
= self.current
.lock().unwrap();
322 stack
.last().and_then(|id
| spans
.get(id
)).map(|s
| s
.name
);
324 Some(expected_parent
.as_ref()),
326 "expected {:?} to have contextual parent {:?}",
345 fn enter(&self, id
: &Id
) {
346 let spans
= self.spans
.lock().unwrap();
347 if let Some(span
) = spans
.get(id
) {
348 println
!("enter: {}; id={:?};", span
.name
, id
);
349 match self.expected
.lock().unwrap().pop_front() {
351 Some(Expect
::Enter(ref expected_span
)) => {
352 if let Some(name
) = expected_span
.name() {
353 assert_eq
!(name
, span
.name
);
356 Some(ex
) => ex
.bad(format_args
!("entered span {:?}", span
.name
)),
359 self.current
.lock().unwrap().push(id
.clone());
362 fn exit(&self, id
: &Id
) {
363 if std
::thread
::panicking() {
364 // `exit()` can be called in `drop` impls, so we must guard against
366 println
!("exit {:?} while panicking", id
);
369 let spans
= self.spans
.lock().unwrap();
372 .unwrap_or_else(|| panic
!("no span for ID {:?}", id
));
373 println
!("exit: {}; id={:?};", span
.name
, id
);
374 match self.expected
.lock().unwrap().pop_front() {
376 Some(Expect
::Exit(ref expected_span
)) => {
377 if let Some(name
) = expected_span
.name() {
378 assert_eq
!(name
, span
.name
);
380 let curr
= self.current
.lock().unwrap().pop();
384 "exited span {:?}, but the current span was {:?}",
386 curr
.as_ref().and_then(|id
| spans
.get(id
)).map(|s
| s
.name
)
389 Some(ex
) => ex
.bad(format_args
!("exited span {:?}", span
.name
)),
393 fn clone_span(&self, id
: &Id
) -> Id
{
394 let name
= self.spans
.lock().unwrap().get_mut(id
).map(|span
| {
395 let name
= span
.name
;
396 println
!("clone_span: {}; id={:?}; refs={:?};", name
, id
, span
.refs
);
401 println
!("clone_span: id={:?};", id
);
403 let mut expected
= self.expected
.lock().unwrap();
404 let was_expected
= if let Some(Expect
::CloneSpan(ref span
)) = expected
.front() {
405 assert_eq
!(name
, span
.name());
411 expected
.pop_front();
416 fn drop_span(&self, id
: Id
) {
417 let mut is_event
= false;
418 let name
= if let Ok(mut spans
) = self.spans
.try_lock() {
419 spans
.get_mut(&id
).map(|span
| {
420 let name
= span
.name
;
421 if name
.contains("event") {
424 println
!("drop_span: {}; id={:?}; refs={:?};", name
, id
, span
.refs
);
432 println
!("drop_span: id={:?}", id
);
434 if let Ok(mut expected
) = self.expected
.try_lock() {
435 let was_expected
= match expected
.front() {
436 Some(Expect
::DropSpan(ref span
)) => {
437 // Don't assert if this function was called while panicking,
438 // as failing the assertion can cause a double panic.
439 if !::std
::thread
::panicking() {
440 assert_eq
!(name
, span
.name());
444 Some(Expect
::Event(_
)) => {
445 if !::std
::thread
::panicking() {
453 expected
.pop_front();
460 pub fn assert_finished(&self) {
461 if let Ok(ref expected
) = self.0.lock() {
463 !expected
.iter().any(|thing
| thing
!= &Expect
::Nothing
),
464 "more notifications expected: {:?}",
472 fn bad
<'a
>(&self, what
: fmt
::Arguments
<'a
>) {
474 Expect
::Event(e
) => panic
!("expected event {}, but {} instead", e
, what
,),
475 Expect
::Enter(e
) => panic
!("expected to enter {} but {} instead", e
, what
,),
476 Expect
::Exit(e
) => panic
!("expected to exit {} but {} instead", e
, what
,),
477 Expect
::CloneSpan(e
) => panic
!("expected to clone {} but {} instead", e
, what
,),
478 Expect
::DropSpan(e
) => panic
!("expected to drop {} but {} instead", e
, what
,),
479 Expect
::Visit(e
, fields
) => {
480 panic
!("expected {} to record {} but {} instead", e
, fields
, what
,)
482 Expect
::NewSpan(e
) => panic
!("expected {} but {} instead", e
, what
),
483 Expect
::Nothing
=> panic
!("expected nothing else to happen, but {} instead", what
,),