#![warn(rust_2018_idioms)] #![cfg(all(feature = "full", not(target_os = "wasi")))] // WASI does not support all fs operations use std::io::prelude::*; use std::io::IoSlice; use tempfile::NamedTempFile; use tokio::fs::File; use tokio::io::{AsyncReadExt, AsyncSeekExt, AsyncWriteExt, SeekFrom}; use tokio_test::task; const HELLO: &[u8] = b"hello world..."; #[tokio::test] async fn basic_read() { let mut tempfile = tempfile(); tempfile.write_all(HELLO).unwrap(); let mut file = File::open(tempfile.path()).await.unwrap(); let mut buf = [0; 1024]; let n = file.read(&mut buf).await.unwrap(); assert_eq!(n, HELLO.len()); assert_eq!(&buf[..n], HELLO); } #[tokio::test] async fn basic_write() { let tempfile = tempfile(); let mut file = File::create(tempfile.path()).await.unwrap(); file.write_all(HELLO).await.unwrap(); file.flush().await.unwrap(); let file = std::fs::read(tempfile.path()).unwrap(); assert_eq!(file, HELLO); } #[tokio::test] async fn basic_write_and_shutdown() { let tempfile = tempfile(); let mut file = File::create(tempfile.path()).await.unwrap(); file.write_all(HELLO).await.unwrap(); file.shutdown().await.unwrap(); let file = std::fs::read(tempfile.path()).unwrap(); assert_eq!(file, HELLO); } #[tokio::test] async fn write_vectored() { let tempfile = tempfile(); let mut file = File::create(tempfile.path()).await.unwrap(); let ret = file .write_vectored(&[IoSlice::new(HELLO), IoSlice::new(HELLO)]) .await .unwrap(); assert_eq!(ret, HELLO.len() * 2); file.flush().await.unwrap(); let file = std::fs::read(tempfile.path()).unwrap(); assert_eq!(file, [HELLO, HELLO].concat()); } #[tokio::test] async fn write_vectored_and_shutdown() { let tempfile = tempfile(); let mut file = File::create(tempfile.path()).await.unwrap(); let ret = file .write_vectored(&[IoSlice::new(HELLO), IoSlice::new(HELLO)]) .await .unwrap(); assert_eq!(ret, HELLO.len() * 2); file.shutdown().await.unwrap(); let file = std::fs::read(tempfile.path()).unwrap(); assert_eq!(file, [HELLO, HELLO].concat()); } #[tokio::test] async fn rewind_seek_position() { let tempfile = tempfile(); let mut file = File::create(tempfile.path()).await.unwrap(); file.seek(SeekFrom::Current(10)).await.unwrap(); file.rewind().await.unwrap(); assert_eq!(file.stream_position().await.unwrap(), 0); } #[tokio::test] async fn coop() { let mut tempfile = tempfile(); tempfile.write_all(HELLO).unwrap(); let mut task = task::spawn(async { let mut file = File::open(tempfile.path()).await.unwrap(); let mut buf = [0; 1024]; loop { let _ = file.read(&mut buf).await.unwrap(); file.seek(std::io::SeekFrom::Start(0)).await.unwrap(); } }); for _ in 0..1_000 { if task.poll().is_pending() { return; } } panic!("did not yield"); } #[tokio::test] async fn write_to_clone() { let tempfile = tempfile(); let file = File::create(tempfile.path()).await.unwrap(); let mut clone = file.try_clone().await.unwrap(); clone.write_all(HELLO).await.unwrap(); clone.flush().await.unwrap(); let contents = std::fs::read(tempfile.path()).unwrap(); assert_eq!(contents, HELLO); } #[tokio::test] async fn write_into_std() { let tempfile = tempfile(); let file = File::create(tempfile.path()).await.unwrap(); let mut std_file = file.into_std().await; std_file.write_all(HELLO).unwrap(); let contents = std::fs::read(tempfile.path()).unwrap(); assert_eq!(contents, HELLO); } #[tokio::test] async fn write_into_std_immediate() { let tempfile = tempfile(); let file = File::create(tempfile.path()).await.unwrap(); let mut std_file = file.try_into_std().unwrap(); std_file.write_all(HELLO).unwrap(); let contents = std::fs::read(tempfile.path()).unwrap(); assert_eq!(contents, HELLO); } #[tokio::test] async fn read_file_from_std() { let mut tempfile = tempfile(); tempfile.write_all(HELLO).unwrap(); let std_file = std::fs::File::open(tempfile.path()).unwrap(); let mut file = File::from(std_file); let mut buf = [0; 1024]; let n = file.read(&mut buf).await.unwrap(); assert_eq!(n, HELLO.len()); assert_eq!(&buf[..n], HELLO); } fn tempfile() -> NamedTempFile { NamedTempFile::new().unwrap() } #[tokio::test] async fn set_max_buf_size_read() { let mut tempfile = tempfile(); tempfile.write_all(HELLO).unwrap(); let mut file = File::open(tempfile.path()).await.unwrap(); let mut buf = [0; 1024]; file.set_max_buf_size(1); // A single read operation reads a maximum of 1 byte. assert_eq!(file.read(&mut buf).await.unwrap(), 1); } #[tokio::test] async fn set_max_buf_size_write() { let tempfile = tempfile(); let mut file = File::create(tempfile.path()).await.unwrap(); file.set_max_buf_size(1); // A single write operation writes a maximum of 1 byte. assert_eq!(file.write(HELLO).await.unwrap(), 1); } #[tokio::test] #[cfg_attr(miri, ignore)] #[cfg(unix)] async fn file_debug_fmt() { let tempfile = tempfile(); let file = File::open(tempfile.path()).await.unwrap(); assert_eq!( &format!("{:?}", file)[0..33], "tokio::fs::File { std: File { fd:" ); } #[tokio::test] #[cfg(windows)] async fn file_debug_fmt() { let tempfile = tempfile(); let file = File::open(tempfile.path()).await.unwrap(); assert_eq!( &format!("{:?}", file)[0..37], "tokio::fs::File { std: File { handle:" ); } #[tokio::test] #[cfg(unix)] async fn unix_fd_is_valid() { use std::os::unix::io::AsRawFd; let tempfile = tempfile(); let file = File::create(tempfile.path()).await.unwrap(); assert!(file.as_raw_fd() as u64 > 0); } #[tokio::test] #[cfg(unix)] async fn read_file_from_unix_fd() { use std::os::unix::io::{FromRawFd, IntoRawFd}; let mut tempfile = tempfile(); tempfile.write_all(HELLO).unwrap(); let file1 = File::open(tempfile.path()).await.unwrap(); let raw_fd = file1.into_std().await.into_raw_fd(); assert!(raw_fd > 0); let mut file2 = unsafe { File::from_raw_fd(raw_fd) }; let mut buf = [0; 1024]; let n = file2.read(&mut buf).await.unwrap(); assert_eq!(n, HELLO.len()); assert_eq!(&buf[..n], HELLO); } #[tokio::test] #[cfg(windows)] async fn windows_handle() { use std::os::windows::io::AsRawHandle; let tempfile = tempfile(); let file = File::create(tempfile.path()).await.unwrap(); assert!(file.as_raw_handle() as u64 > 0); }