1 #![allow(missing_docs)]
2 use super::{field, metadata, Parent};
3 use std::fmt;
4
5 /// A mock span.
6 ///
7 /// This is intended for use with the mock subscriber API in the
8 /// `subscriber` module.
9 #[derive(Clone, Default, Eq, PartialEq)]
10 pub struct MockSpan {
11 pub(in crate::support) metadata: metadata::Expect,
12 }
13
14 #[derive(Default, Eq, PartialEq)]
15 pub struct NewSpan {
16 pub(in crate::support) span: MockSpan,
17 pub(in crate::support) fields: field::Expect,
18 pub(in crate::support) parent: Option<Parent>,
19 }
20
mock() -> MockSpan21 pub fn mock() -> MockSpan {
22 MockSpan {
23 ..Default::default()
24 }
25 }
26
27 impl MockSpan {
named<I>(self, name: I) -> Self where I: Into<String>,28 pub fn named<I>(self, name: I) -> Self
29 where
30 I: Into<String>,
31 {
32 Self {
33 metadata: metadata::Expect {
34 name: Some(name.into()),
35 ..self.metadata
36 },
37 }
38 }
39
at_level(self, level: tracing::Level) -> Self40 pub fn at_level(self, level: tracing::Level) -> Self {
41 Self {
42 metadata: metadata::Expect {
43 level: Some(level),
44 ..self.metadata
45 },
46 }
47 }
48
with_target<I>(self, target: I) -> Self where I: Into<String>,49 pub fn with_target<I>(self, target: I) -> Self
50 where
51 I: Into<String>,
52 {
53 Self {
54 metadata: metadata::Expect {
55 target: Some(target.into()),
56 ..self.metadata
57 },
58 }
59 }
60
with_explicit_parent(self, parent: Option<&str>) -> NewSpan61 pub fn with_explicit_parent(self, parent: Option<&str>) -> NewSpan {
62 let parent = match parent {
63 Some(name) => Parent::Explicit(name.into()),
64 None => Parent::ExplicitRoot,
65 };
66 NewSpan {
67 parent: Some(parent),
68 span: self,
69 ..Default::default()
70 }
71 }
72
with_contextual_parent(self, parent: Option<&str>) -> NewSpan73 pub fn with_contextual_parent(self, parent: Option<&str>) -> NewSpan {
74 let parent = match parent {
75 Some(name) => Parent::Contextual(name.into()),
76 None => Parent::ContextualRoot,
77 };
78 NewSpan {
79 parent: Some(parent),
80 span: self,
81 ..Default::default()
82 }
83 }
84
name(&self) -> Option<&str>85 pub fn name(&self) -> Option<&str> {
86 self.metadata.name.as_ref().map(String::as_ref)
87 }
88
level(&self) -> Option<tracing::Level>89 pub fn level(&self) -> Option<tracing::Level> {
90 self.metadata.level
91 }
92
target(&self) -> Option<&str>93 pub fn target(&self) -> Option<&str> {
94 self.metadata.target.as_deref()
95 }
96
with_field<I>(self, fields: I) -> NewSpan where I: Into<field::Expect>,97 pub fn with_field<I>(self, fields: I) -> NewSpan
98 where
99 I: Into<field::Expect>,
100 {
101 NewSpan {
102 span: self,
103 fields: fields.into(),
104 ..Default::default()
105 }
106 }
107 }
108
109 impl fmt::Debug for MockSpan {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result110 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111 let mut s = f.debug_struct("MockSpan");
112
113 if let Some(name) = self.name() {
114 s.field("name", &name);
115 }
116
117 if let Some(level) = self.level() {
118 s.field("level", &format_args!("{:?}", level));
119 }
120
121 if let Some(target) = self.target() {
122 s.field("target", &target);
123 }
124
125 s.finish()
126 }
127 }
128
129 impl fmt::Display for MockSpan {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result130 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131 if self.metadata.name.is_some() {
132 write!(f, "a span{}", self.metadata)
133 } else {
134 write!(f, "any span{}", self.metadata)
135 }
136 }
137 }
138
139 impl From<MockSpan> for NewSpan {
from(span: MockSpan) -> Self140 fn from(span: MockSpan) -> Self {
141 Self {
142 span,
143 ..Default::default()
144 }
145 }
146 }
147
148 impl NewSpan {
with_explicit_parent(self, parent: Option<&str>) -> NewSpan149 pub fn with_explicit_parent(self, parent: Option<&str>) -> NewSpan {
150 let parent = match parent {
151 Some(name) => Parent::Explicit(name.into()),
152 None => Parent::ExplicitRoot,
153 };
154 NewSpan {
155 parent: Some(parent),
156 ..self
157 }
158 }
159
with_contextual_parent(self, parent: Option<&str>) -> NewSpan160 pub fn with_contextual_parent(self, parent: Option<&str>) -> NewSpan {
161 let parent = match parent {
162 Some(name) => Parent::Contextual(name.into()),
163 None => Parent::ContextualRoot,
164 };
165 NewSpan {
166 parent: Some(parent),
167 ..self
168 }
169 }
170
with_field<I>(self, fields: I) -> NewSpan where I: Into<field::Expect>,171 pub fn with_field<I>(self, fields: I) -> NewSpan
172 where
173 I: Into<field::Expect>,
174 {
175 NewSpan {
176 fields: fields.into(),
177 ..self
178 }
179 }
180
check( &mut self, span: &tracing_core::span::Attributes<'_>, get_parent_name: impl FnOnce() -> Option<String>, subscriber_name: &str, )181 pub fn check(
182 &mut self,
183 span: &tracing_core::span::Attributes<'_>,
184 get_parent_name: impl FnOnce() -> Option<String>,
185 subscriber_name: &str,
186 ) {
187 let meta = span.metadata();
188 let name = meta.name();
189 self.span
190 .metadata
191 .check(meta, format_args!("span `{}`", name), subscriber_name);
192 let mut checker = self.fields.checker(name, subscriber_name);
193 span.record(&mut checker);
194 checker.finish();
195
196 if let Some(expected_parent) = self.parent.as_ref() {
197 let actual_parent = get_parent_name();
198 expected_parent.check_parent_name(
199 actual_parent.as_deref(),
200 span.parent().cloned(),
201 format_args!("span `{}`", name),
202 subscriber_name,
203 )
204 }
205 }
206 }
207
208 impl fmt::Display for NewSpan {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result209 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
210 write!(f, "a new span{}", self.span.metadata)?;
211 if !self.fields.is_empty() {
212 write!(f, " with {}", self.fields)?;
213 }
214 Ok(())
215 }
216 }
217
218 impl fmt::Debug for NewSpan {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result219 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
220 let mut s = f.debug_struct("NewSpan");
221
222 if let Some(name) = self.span.name() {
223 s.field("name", &name);
224 }
225
226 if let Some(level) = self.span.level() {
227 s.field("level", &format_args!("{:?}", level));
228 }
229
230 if let Some(target) = self.span.target() {
231 s.field("target", &target);
232 }
233
234 if let Some(ref parent) = self.parent {
235 s.field("parent", &format_args!("{:?}", parent));
236 }
237
238 if !self.fields.is_empty() {
239 s.field("fields", &self.fields);
240 }
241
242 s.finish()
243 }
244 }
245