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()11async 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()32async 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()55async 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()76async fn no_block_in_basic_scheduler() { 77 task::block_in_place(|| {}); 78 } 79 80 #[test] yes_block_in_threaded_block_on()81fn 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()93fn 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()101fn 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()120fn 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()149fn 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()165fn 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