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