]> git.proxmox.com Git - rustc.git/blob - vendor/tracing-attributes/tests/async_fn.rs
New upstream version 1.58.1+dfsg1
[rustc.git] / vendor / tracing-attributes / tests / async_fn.rs
1 #[path = "../../tracing-futures/tests/support.rs"]
2 // we don't use some of the test support functions, but `tracing-futures` does.
3 #[allow(dead_code)]
4 mod support;
5 use support::*;
6
7 use std::{future::Future, pin::Pin, sync::Arc};
8 use tracing::subscriber::with_default;
9 use tracing_attributes::instrument;
10
11 #[instrument]
12 async fn test_async_fn(polls: usize) -> Result<(), ()> {
13 let future = PollN::new_ok(polls);
14 tracing::trace!(awaiting = true);
15 future.await
16 }
17
18 // Reproduces a compile error when returning an `impl Trait` from an
19 // instrumented async fn (see https://github.com/tokio-rs/tracing/issues/1615)
20 #[instrument]
21 async fn test_ret_impl_trait(n: i32) -> Result<impl Iterator<Item = i32>, ()> {
22 let n = n;
23 Ok((0..10).filter(move |x| *x < n))
24 }
25
26 // Reproduces a compile error when returning an `impl Trait` from an
27 // instrumented async fn (see https://github.com/tokio-rs/tracing/issues/1615)
28 #[instrument(err)]
29 async fn test_ret_impl_trait_err(n: i32) -> Result<impl Iterator<Item = i32>, &'static str> {
30 Ok((0..10).filter(move |x| *x < n))
31 }
32
33 #[instrument]
34 async fn test_async_fn_empty() {}
35
36 // Reproduces https://github.com/tokio-rs/tracing/issues/1613
37 #[instrument]
38 // LOAD-BEARING `#[rustfmt::skip]`! This is necessary to reproduce the bug;
39 // with the rustfmt-generated formatting, the lint will not be triggered!
40 #[rustfmt::skip]
41 #[deny(clippy::suspicious_else_formatting)]
42 async fn repro_1613(var: bool) {
43 println!(
44 "{}",
45 if var { "true" } else { "false" }
46 );
47 }
48
49 // Reproduces https://github.com/tokio-rs/tracing/issues/1613
50 // and https://github.com/rust-lang/rust-clippy/issues/7760
51 #[instrument]
52 #[deny(clippy::suspicious_else_formatting)]
53 async fn repro_1613_2() {
54 // hello world
55 // else
56 }
57
58 #[test]
59 fn async_fn_only_enters_for_polls() {
60 let (subscriber, handle) = subscriber::mock()
61 .new_span(span::mock().named("test_async_fn"))
62 .enter(span::mock().named("test_async_fn"))
63 .event(event::mock().with_fields(field::mock("awaiting").with_value(&true)))
64 .exit(span::mock().named("test_async_fn"))
65 .enter(span::mock().named("test_async_fn"))
66 .exit(span::mock().named("test_async_fn"))
67 .drop_span(span::mock().named("test_async_fn"))
68 .done()
69 .run_with_handle();
70 with_default(subscriber, || {
71 block_on_future(async { test_async_fn(2).await }).unwrap();
72 });
73 handle.assert_finished();
74 }
75
76 #[test]
77 fn async_fn_nested() {
78 #[instrument]
79 async fn test_async_fns_nested() {
80 test_async_fns_nested_other().await
81 }
82
83 #[instrument]
84 async fn test_async_fns_nested_other() {
85 tracing::trace!(nested = true);
86 }
87
88 let span = span::mock().named("test_async_fns_nested");
89 let span2 = span::mock().named("test_async_fns_nested_other");
90 let (subscriber, handle) = subscriber::mock()
91 .new_span(span.clone())
92 .enter(span.clone())
93 .new_span(span2.clone())
94 .enter(span2.clone())
95 .event(event::mock().with_fields(field::mock("nested").with_value(&true)))
96 .exit(span2.clone())
97 .drop_span(span2)
98 .exit(span.clone())
99 .drop_span(span)
100 .done()
101 .run_with_handle();
102
103 with_default(subscriber, || {
104 block_on_future(async { test_async_fns_nested().await });
105 });
106
107 handle.assert_finished();
108 }
109
110 #[test]
111 fn async_fn_with_async_trait() {
112 use async_trait::async_trait;
113
114 // test the correctness of the metadata obtained by #[instrument]
115 // (function name, functions parameters) when async-trait is used
116 #[async_trait]
117 pub trait TestA {
118 async fn foo(&mut self, v: usize);
119 }
120
121 // test nesting of async fns with aync-trait
122 #[async_trait]
123 pub trait TestB {
124 async fn bar(&self);
125 }
126
127 // test skip(self) with async-await
128 #[async_trait]
129 pub trait TestC {
130 async fn baz(&self);
131 }
132
133 #[derive(Debug)]
134 struct TestImpl(usize);
135
136 #[async_trait]
137 impl TestA for TestImpl {
138 #[instrument]
139 async fn foo(&mut self, v: usize) {
140 self.baz().await;
141 self.0 = v;
142 self.bar().await
143 }
144 }
145
146 #[async_trait]
147 impl TestB for TestImpl {
148 #[instrument]
149 async fn bar(&self) {
150 tracing::trace!(val = self.0);
151 }
152 }
153
154 #[async_trait]
155 impl TestC for TestImpl {
156 #[instrument(skip(self))]
157 async fn baz(&self) {
158 tracing::trace!(val = self.0);
159 }
160 }
161
162 let span = span::mock().named("foo");
163 let span2 = span::mock().named("bar");
164 let span3 = span::mock().named("baz");
165 let (subscriber, handle) = subscriber::mock()
166 .new_span(
167 span.clone()
168 .with_field(field::mock("self"))
169 .with_field(field::mock("v")),
170 )
171 .enter(span.clone())
172 .new_span(span3.clone())
173 .enter(span3.clone())
174 .event(event::mock().with_fields(field::mock("val").with_value(&2u64)))
175 .exit(span3.clone())
176 .drop_span(span3)
177 .new_span(span2.clone().with_field(field::mock("self")))
178 .enter(span2.clone())
179 .event(event::mock().with_fields(field::mock("val").with_value(&5u64)))
180 .exit(span2.clone())
181 .drop_span(span2)
182 .exit(span.clone())
183 .drop_span(span)
184 .done()
185 .run_with_handle();
186
187 with_default(subscriber, || {
188 let mut test = TestImpl(2);
189 block_on_future(async { test.foo(5).await });
190 });
191
192 handle.assert_finished();
193 }
194
195 #[test]
196 fn async_fn_with_async_trait_and_fields_expressions() {
197 use async_trait::async_trait;
198
199 #[async_trait]
200 pub trait Test {
201 async fn call(&mut self, v: usize);
202 }
203
204 #[derive(Clone, Debug)]
205 struct TestImpl;
206
207 impl TestImpl {
208 fn foo(&self) -> usize {
209 42
210 }
211 }
212
213 #[async_trait]
214 impl Test for TestImpl {
215 // check that self is correctly handled, even when using async_trait
216 #[instrument(fields(val=self.foo(), val2=Self::clone(self).foo(), test=%_v+5))]
217 async fn call(&mut self, _v: usize) {}
218 }
219
220 let span = span::mock().named("call");
221 let (subscriber, handle) = subscriber::mock()
222 .new_span(
223 span.clone().with_field(
224 field::mock("_v")
225 .with_value(&5usize)
226 .and(field::mock("test").with_value(&tracing::field::debug(10)))
227 .and(field::mock("val").with_value(&42u64))
228 .and(field::mock("val2").with_value(&42u64)),
229 ),
230 )
231 .enter(span.clone())
232 .exit(span.clone())
233 .drop_span(span)
234 .done()
235 .run_with_handle();
236
237 with_default(subscriber, || {
238 block_on_future(async { TestImpl.call(5).await });
239 });
240
241 handle.assert_finished();
242 }
243
244 #[test]
245 fn async_fn_with_async_trait_and_fields_expressions_with_generic_parameter() {
246 use async_trait::async_trait;
247
248 #[async_trait]
249 pub trait Test {
250 async fn call();
251 async fn call_with_self(&self);
252 async fn call_with_mut_self(&mut self);
253 }
254
255 #[derive(Clone, Debug)]
256 struct TestImpl;
257
258 // we also test sync functions that return futures, as they should be handled just like
259 // async-trait (>= 0.1.44) functions
260 impl TestImpl {
261 #[instrument(fields(Self=std::any::type_name::<Self>()))]
262 fn sync_fun(&self) -> Pin<Box<dyn Future<Output = ()> + Send + '_>> {
263 let val = self.clone();
264 Box::pin(async move {
265 let _ = val;
266 })
267 }
268 }
269
270 #[async_trait]
271 impl Test for TestImpl {
272 // instrumenting this is currently not possible, see https://github.com/tokio-rs/tracing/issues/864#issuecomment-667508801
273 //#[instrument(fields(Self=std::any::type_name::<Self>()))]
274 async fn call() {}
275
276 #[instrument(fields(Self=std::any::type_name::<Self>()))]
277 async fn call_with_self(&self) {
278 self.sync_fun().await;
279 }
280
281 #[instrument(fields(Self=std::any::type_name::<Self>()))]
282 async fn call_with_mut_self(&mut self) {}
283 }
284
285 //let span = span::mock().named("call");
286 let span2 = span::mock().named("call_with_self");
287 let span3 = span::mock().named("call_with_mut_self");
288 let span4 = span::mock().named("sync_fun");
289 let (subscriber, handle) = subscriber::mock()
290 /*.new_span(span.clone()
291 .with_field(
292 field::mock("Self").with_value(&"TestImpler")))
293 .enter(span.clone())
294 .exit(span.clone())
295 .drop_span(span)*/
296 .new_span(
297 span2
298 .clone()
299 .with_field(field::mock("Self").with_value(&std::any::type_name::<TestImpl>())),
300 )
301 .enter(span2.clone())
302 .new_span(
303 span4
304 .clone()
305 .with_field(field::mock("Self").with_value(&std::any::type_name::<TestImpl>())),
306 )
307 .enter(span4.clone())
308 .exit(span4)
309 .exit(span2.clone())
310 .drop_span(span2)
311 .new_span(
312 span3
313 .clone()
314 .with_field(field::mock("Self").with_value(&std::any::type_name::<TestImpl>())),
315 )
316 .enter(span3.clone())
317 .exit(span3.clone())
318 .drop_span(span3)
319 .done()
320 .run_with_handle();
321
322 with_default(subscriber, || {
323 block_on_future(async {
324 TestImpl::call().await;
325 TestImpl.call_with_self().await;
326 TestImpl.call_with_mut_self().await
327 });
328 });
329
330 handle.assert_finished();
331 }
332
333 #[test]
334 fn out_of_scope_fields() {
335 // Reproduces tokio-rs/tracing#1296
336
337 struct Thing {
338 metrics: Arc<()>,
339 }
340
341 impl Thing {
342 #[instrument(skip(self, _req), fields(app_id))]
343 fn call(&mut self, _req: ()) -> Pin<Box<dyn Future<Output = Arc<()>> + Send + Sync>> {
344 // ...
345 let metrics = self.metrics.clone();
346 // ...
347 Box::pin(async move {
348 // ...
349 metrics // cannot find value `metrics` in this scope
350 })
351 }
352 }
353
354 let span = span::mock().named("call");
355 let (subscriber, handle) = subscriber::mock()
356 .new_span(span.clone())
357 .enter(span.clone())
358 .exit(span.clone())
359 .drop_span(span)
360 .done()
361 .run_with_handle();
362
363 with_default(subscriber, || {
364 block_on_future(async {
365 let mut my_thing = Thing {
366 metrics: Arc::new(()),
367 };
368 my_thing.call(()).await;
369 });
370 });
371
372 handle.assert_finished();
373 }