use dever_runtime::{ net::{self, Listener, Socket}, task::{Limits, Runtime, Scope}, }; use std::{ future::{Future, poll_fn}, task::Poll, }; #[cfg(feature = "http")] #[path = "net/performance.rs"] mod performance; fn runtime() -> Runtime { Runtime::new(Limits { threads: 2, workers: 2, tasks: 8, }) .unwrap() } async fn pair(scope: &Scope<'_>) -> (Socket, Socket) { let listener = net::listen("127.0.0.1", 0, scope).await.unwrap(); let client = net::connect_timeout("127.0.0.1", listener.port().unwrap(), 1000) .await .unwrap(); let server = listener.accept().await.unwrap(); (client, server) } async fn pending(future: std::pin::Pin<&mut impl Future>) { let mut future = future; poll_fn(|context| { assert!(future.as_mut().poll(context).is_pending()); Poll::Ready(()) }) .await; } #[test] fn dns_connect_bidirectional_io_and_shared_close_use_the_runtime() { runtime() .run(async |scope| { let listener = net::listen("127.0.0.1", 0, scope).await.unwrap(); let port = listener.port().unwrap(); assert!((1..=65535).contains(&port)); let client = net::connect("localhost", port, scope).await.unwrap(); let server = listener.accept().await.unwrap(); client.write(b"abc").await.unwrap(); assert_eq!(server.read(2).await.unwrap(), Some(b"ab".to_vec())); assert_eq!(server.read(2).await.unwrap(), Some(b"c".to_vec())); server.write(b"reply").await.unwrap(); assert_eq!(client.read(5).await.unwrap(), Some(b"reply".to_vec())); let alias = client.clone(); alias.close().unwrap(); assert!(client.write(b"closed").await.is_err()); assert!(client.read(1).await.is_err()); assert!(client.close().is_err()); assert_eq!(server.read(1).await.unwrap(), None); listener.close().unwrap(); }) .unwrap(); } #[test] fn close_wakes_read_lock_waiters_and_pending_accepts() { runtime() .run(async |scope| { let (client, _server) = pair(scope).await; let mut first = std::pin::pin!(client.read(1)); let mut second = std::pin::pin!(client.read(1)); pending(first.as_mut()).await; pending(second.as_mut()).await; client.close().unwrap(); assert!(first.await.is_err()); assert!(second.await.is_err()); let listener = net::listen("127.0.0.1", 0, scope).await.unwrap(); let mut accepted = std::pin::pin!(listener.accept()); pending(accepted.as_mut()).await; listener.clone().close().unwrap(); assert!(accepted.await.is_err()); assert!(listener.port().is_err()); }) .unwrap(); } #[test] fn read_timeout_includes_lock_waiting_and_does_not_consume_future_data() { runtime() .run(async |scope| { let (client, server) = pair(scope).await; { let mut first = std::pin::pin!(client.read(1)); pending(first.as_mut()).await; client.timeout(10).unwrap(); assert_eq!( client.read(1).await.unwrap_err(), "network operation timed out" ); } client.timeout(1000).unwrap(); server.write(b"x").await.unwrap(); assert_eq!(client.read(1).await.unwrap(), Some(b"x".to_vec())); assert!(client.timeout(0).is_err()); assert!(client.read(0).await.is_err()); }) .unwrap(); } #[test] fn cancelled_partial_write_closes_but_cancelled_queued_write_preserves_socket() { runtime() .run(async |scope| { let (client, server) = pair(scope).await; let writer = client.clone(); let first = scope .spawn_leaf(move || async move { writer.write(&vec![7; 32 * 1024 * 1024]).await }) .unwrap(); assert_eq!(server.read(1).await.unwrap(), Some(vec![7])); let writer = client.clone(); let (started, ready) = tokio::sync::oneshot::channel(); let queued = scope .spawn_leaf(move || async move { let mut write = std::pin::pin!(writer.write(b"queued")); pending(write.as_mut()).await; started.send(()).unwrap(); write.await }) .unwrap(); ready.await.unwrap(); assert!(queued.stop().await.unwrap().is_none()); client.timeout(1000).unwrap(); assert!(first.stop().await.unwrap().is_none()); assert!(client.timeout(1000).is_err()); server.timeout(1000).unwrap(); while server.read(65536).await.unwrap().is_some() {} }) .unwrap(); } #[test] fn chunks_close_preserves_the_external_socket_and_terminal_errors_occur_once() { runtime() .run(async |scope| { let (client, server) = pair(scope).await; let chunks = client.chunks(2, std::convert::identity).unwrap(); let mut waiting = std::pin::pin!(chunks.next()); pending(waiting.as_mut()).await; chunks.close(); assert!(waiting.await.unwrap().is_none()); server.write(b"ab").await.unwrap(); assert_eq!(client.read(2).await.unwrap(), Some(b"ab".to_vec())); let chunks = client.chunks(2, std::convert::identity).unwrap(); client.close().unwrap(); assert!(chunks.next().await.unwrap().unwrap().is_err()); assert!(chunks.next().await.unwrap().is_none()); assert!(client.chunks(2, std::convert::identity).is_err()); }) .unwrap(); } #[test] fn connection_stream_is_lazy_and_closing_it_preserves_the_listener() { runtime() .run(async |scope| { let listener: Listener = net::listen("127.0.0.1", 0, scope).await.unwrap(); let connections = listener.connections(std::convert::identity); connections.close(); let _client = net::connect_timeout("127.0.0.1", listener.port().unwrap(), 1000) .await .unwrap(); let _server = listener.accept().await.unwrap(); let connections = listener.connections(std::convert::identity); listener.close().unwrap(); assert!(connections.next().await.unwrap().unwrap().is_err()); assert!(connections.next().await.unwrap().is_none()); }) .unwrap(); } #[test] fn invalid_network_arguments_fail_before_waiting() { runtime() .run(async |scope| { assert!(net::listen("127.0.0.1", -1, scope).await.is_err()); assert!(net::connect("127.0.0.1", 65536, scope).await.is_err()); assert_eq!( net::connect_timeout("localhost", 80, 1000) .await .unwrap_err(), "timed connect requires a numeric IP address" ); assert!(net::connect_timeout("127.0.0.1", 80, 0).await.is_err()); }) .unwrap(); } #[test] fn short_reads_exact_limits_and_allocation_failure_preserve_remaining_bytes() { runtime() .run(async |scope| { let (client, server) = pair(scope).await; client.timeout(1000).unwrap(); server.write(&[0, 255, 1, 0, 2, 128, 3]).await.unwrap(); let mut received = Vec::new(); while received.len() != 7 { let bytes = client.read(3).await.unwrap().unwrap(); assert!(!bytes.is_empty() && bytes.len() <= 3); received.extend(bytes); } assert_eq!(received, [0, 255, 1, 0, 2, 128, 3]); server.write(b"x").await.unwrap(); assert!(client.read(i64::MAX).await.is_err()); assert_eq!(client.read(1_048_576).await.unwrap(), Some(b"x".to_vec())); server.close().unwrap(); assert_eq!(client.read(1_048_576).await.unwrap(), None); assert_eq!(client.read(3).await.unwrap(), None); }) .unwrap(); }