use std::io::prelude::*;
use compio_fs::{File, OpenOptions};
use compio_io::{AsyncReadAtExt, AsyncWriteAt, AsyncWriteAtExt};
use tempfile::NamedTempFile;
async fn setlen_run(file: &File, size: u64) {
file.set_len(size).await.unwrap();
compio_runtime::time::sleep(std::time::Duration::from_millis(0)).await;
let meta = file.metadata().await.unwrap();
assert_eq!(size, meta.len());
}
#[compio_macros::test]
async fn iouring_setlen_non_fixed() {
let tempfile = tempfile();
let file = OpenOptions::new()
.read(true)
.write(true)
.open(tempfile.path())
.await
.unwrap();
setlen_run(&file, 5).await;
setlen_run(&file, 0).await;
}
#[compio_macros::test]
async fn metadata() {
let meta = compio_fs::metadata("Cargo.toml").await.unwrap();
assert!(meta.is_file());
let size = meta.len();
let file = File::open("Cargo.toml").await.unwrap();
let meta = file.metadata().await.unwrap();
assert!(meta.is_file());
assert_eq!(size, meta.len());
let std_meta = std::fs::metadata("Cargo.toml").unwrap();
assert_eq!(size, std_meta.len());
}
const HELLO: &[u8] = b"hello world...";
async fn read_hello(file: &File) {
let buf = Vec::with_capacity(1024);
let (n, buf) = file.read_to_end_at(buf, 0).await.unwrap();
assert_eq!(n, HELLO.len());
assert_eq!(&buf, HELLO);
}
#[compio_macros::test]
async fn basic_read() {
let mut tempfile = tempfile();
tempfile.write_all(HELLO).unwrap();
let file = File::open(tempfile.path()).await.unwrap();
read_hello(&file).await;
}
#[compio_macros::test]
async fn basic_write() {
let tempfile = tempfile();
let mut file = File::create(tempfile.path()).await.unwrap();
file.write_all_at(HELLO, 0).await.0.unwrap();
file.sync_all().await.unwrap();
let file = std::fs::read(tempfile.path()).unwrap();
assert_eq!(file, HELLO);
}
#[compio_macros::test]
async fn writev() {
let tempfile = tempfile();
let mut file = File::create(tempfile.path()).await.unwrap();
let (write, _) = file.write_vectored_at([HELLO, HELLO], 0).await.unwrap();
assert!(write > 0);
}
#[compio_macros::test]
async fn cancel_read() {
let mut tempfile = tempfile();
tempfile.write_all(HELLO).unwrap();
let file = File::open(tempfile.path()).await.unwrap();
poll_once(async { read_hello(&file).await }).await;
read_hello(&file).await;
}
#[cfg(unix)]
#[compio_macros::test]
async fn timeout_read() {
use std::time::Duration;
use compio_fs::pipe::anonymous;
use compio_io::AsyncReadExt;
use compio_runtime::time::timeout;
let (mut rx, _) = anonymous().unwrap();
let _ = timeout(Duration::from_nanos(1), async move {
rx.read_to_string(String::new()).await
})
.await
.unwrap_err();
}
#[compio_macros::test]
async fn drop_open() {
let tempfile = tempfile();
let _ = File::create(tempfile.path()).await;
let mut file = File::create(tempfile.path()).await.unwrap();
file.write_all_at(HELLO, 0).await.0.unwrap();
let file = std::fs::read(tempfile.path()).unwrap();
assert_eq!(file, HELLO);
}
#[cfg(windows)]
#[compio_macros::test]
async fn hidden_file_truncation() {
let tmpdir = tempfile::tempdir().unwrap();
let path = tmpdir.path().join("hidden_file.txt");
const FILE_ATTRIBUTE_HIDDEN: u32 = 2;
let mut file = compio_fs::OpenOptions::new()
.write(true)
.create_new(true)
.attributes(FILE_ATTRIBUTE_HIDDEN)
.open(&path)
.await
.unwrap();
file.write_all_at("hidden world!", 0).await.unwrap();
file.close().await.unwrap();
let file = File::create(&path).await.unwrap();
let metadata = file.metadata().await.unwrap();
assert_eq!(metadata.len(), 0);
}
fn tempfile() -> NamedTempFile {
NamedTempFile::new().unwrap()
}
async fn poll_once(future: impl std::future::Future) {
use std::{future::poll_fn, pin::pin, task::Poll};
let mut future = pin!(future);
poll_fn(|cx| {
let _ = future.as_mut().poll(cx);
Poll::Ready(())
})
.await;
}