1 #![warn(rust_2018_idioms)]
2 #![cfg(feature = "full")]
3 
4 use tokio::{runtime, task};
5 use tokio_test::assert_ok;
6 
7 use std::thread;
8 use std::time::Duration;
9 
10 #[tokio::test]
basic_blocking()11 async fn basic_blocking() {
12     // Run a few times
13     for _ in 0..100 {
14         let out = assert_ok!(
15             tokio::spawn(async {
16                 assert_ok!(
17                     task::spawn_blocking(|| {
18                         thread::sleep(Duration::from_millis(5));
19                         "hello"
20                     })
21                     .await
22                 )
23             })
24             .await
25         );
26 
27         assert_eq!(out, "hello");
28     }
29 }
30 
31 #[tokio::test(threaded_scheduler)]
block_in_blocking()32 async fn block_in_blocking() {
33     // Run a few times
34     for _ in 0..100 {
35         let out = assert_ok!(
36             tokio::spawn(async {
37                 assert_ok!(
38                     task::spawn_blocking(|| {
39                         task::block_in_place(|| {
40                             thread::sleep(Duration::from_millis(5));
41                         });
42                         "hello"
43                     })
44                     .await
45                 )
46             })
47             .await
48         );
49 
50         assert_eq!(out, "hello");
51     }
52 }
53 
54 #[tokio::test(threaded_scheduler)]
block_in_block()55 async fn block_in_block() {
56     // Run a few times
57     for _ in 0..100 {
58         let out = assert_ok!(
59             tokio::spawn(async {
60                 task::block_in_place(|| {
61                     task::block_in_place(|| {
62                         thread::sleep(Duration::from_millis(5));
63                     });
64                     "hello"
65                 })
66             })
67             .await
68         );
69 
70         assert_eq!(out, "hello");
71     }
72 }
73 
74 #[tokio::test(basic_scheduler)]
75 #[should_panic]
no_block_in_basic_scheduler()76 async fn no_block_in_basic_scheduler() {
77     task::block_in_place(|| {});
78 }
79 
80 #[test]
yes_block_in_threaded_block_on()81 fn yes_block_in_threaded_block_on() {
82     let mut rt = runtime::Builder::new()
83         .threaded_scheduler()
84         .build()
85         .unwrap();
86     rt.block_on(async {
87         task::block_in_place(|| {});
88     });
89 }
90 
91 #[test]
92 #[should_panic]
no_block_in_basic_block_on()93 fn no_block_in_basic_block_on() {
94     let mut rt = runtime::Builder::new().basic_scheduler().build().unwrap();
95     rt.block_on(async {
96         task::block_in_place(|| {});
97     });
98 }
99 
100 #[test]
can_enter_basic_rt_from_within_block_in_place()101 fn can_enter_basic_rt_from_within_block_in_place() {
102     let mut outer = tokio::runtime::Builder::new()
103         .threaded_scheduler()
104         .build()
105         .unwrap();
106 
107     outer.block_on(async {
108         tokio::task::block_in_place(|| {
109             let mut inner = tokio::runtime::Builder::new()
110                 .basic_scheduler()
111                 .build()
112                 .unwrap();
113 
114             inner.block_on(async {})
115         })
116     });
117 }
118 
119 #[test]
useful_panic_message_when_dropping_rt_in_rt()120 fn useful_panic_message_when_dropping_rt_in_rt() {
121     use std::panic::{catch_unwind, AssertUnwindSafe};
122 
123     let mut outer = tokio::runtime::Builder::new()
124         .threaded_scheduler()
125         .build()
126         .unwrap();
127 
128     let result = catch_unwind(AssertUnwindSafe(|| {
129         outer.block_on(async {
130             let _ = tokio::runtime::Builder::new()
131                 .basic_scheduler()
132                 .build()
133                 .unwrap();
134         });
135     }));
136 
137     assert!(result.is_err());
138     let err = result.unwrap_err();
139     let err: &'static str = err.downcast_ref::<&'static str>().unwrap();
140 
141     assert!(
142         err.find("Cannot drop a runtime").is_some(),
143         "Wrong panic message: {:?}",
144         err
145     );
146 }
147 
148 #[test]
can_shutdown_with_zero_timeout_in_runtime()149 fn can_shutdown_with_zero_timeout_in_runtime() {
150     let mut outer = tokio::runtime::Builder::new()
151         .threaded_scheduler()
152         .build()
153         .unwrap();
154 
155     outer.block_on(async {
156         let rt = tokio::runtime::Builder::new()
157             .basic_scheduler()
158             .build()
159             .unwrap();
160         rt.shutdown_timeout(Duration::from_nanos(0));
161     });
162 }
163 
164 #[test]
can_shutdown_now_in_runtime()165 fn can_shutdown_now_in_runtime() {
166     let mut outer = tokio::runtime::Builder::new()
167         .threaded_scheduler()
168         .build()
169         .unwrap();
170 
171     outer.block_on(async {
172         let rt = tokio::runtime::Builder::new()
173             .basic_scheduler()
174             .build()
175             .unwrap();
176         rt.shutdown_background();
177     });
178 }
179