use super::tests::virtual_system_with_executor;
use super::*;
use assert_matches::assert_matches;
use futures_util::FutureExt;
fn create_fifo(system: &VirtualSystem) {
system
.state
.borrow_mut()
.file_system
.save(
"/myfifo",
Rc::new(RefCell::new(Inode {
body: FileBody::Fifo {
content: VecDeque::new(),
readers: 0,
writers: 0,
pending_open_wakers: WakerSet::new(),
pending_read_wakers: WakerSet::new(),
pending_write_wakers: WakerSet::new(),
},
permissions: Mode::empty(),
})),
)
.unwrap();
}
#[test]
fn open_fifo_reading_then_writing_blocking() {
let (system, mut executor) = virtual_system_with_executor();
create_fifo(&system);
let system_2 = system.clone();
let read_open_result = Rc::new(Cell::new(None));
let read_open_result_2 = read_open_result.clone();
executor
.spawner()
.spawn(Box::pin(async move {
let result = system_2
.open(
c"/myfifo",
OfdAccess::ReadOnly,
EnumSet::empty(),
Mode::empty(),
)
.await;
read_open_result_2.set(Some(result));
}))
.unwrap();
executor.run_until_stalled();
assert_eq!(read_open_result.get(), None);
let write_open_result = Rc::new(Cell::new(None));
let write_open_result_2 = write_open_result.clone();
executor
.spawner()
.spawn(Box::pin(async move {
let result = system
.open(
c"/myfifo",
OfdAccess::WriteOnly,
EnumSet::empty(),
Mode::empty(),
)
.await;
write_open_result_2.set(Some(result));
}))
.unwrap();
executor.run_until_stalled();
assert_matches!(
(read_open_result.get(), write_open_result.get()),
(Some(Ok(read_fd)), Some(Ok(write_fd))) if read_fd != write_fd
)
}
#[test]
fn open_fifo_writing_then_reading_blocking() {
let (system, mut executor) = virtual_system_with_executor();
create_fifo(&system);
let system_2 = system.clone();
let write_open_result = Rc::new(Cell::new(None));
let write_open_result_2 = write_open_result.clone();
executor
.spawner()
.spawn(Box::pin(async move {
let result = system_2
.open(
c"/myfifo",
OfdAccess::WriteOnly,
EnumSet::empty(),
Mode::empty(),
)
.await;
write_open_result_2.set(Some(result));
}))
.unwrap();
executor.run_until_stalled();
assert_eq!(write_open_result.get(), None);
let read_open_result = Rc::new(Cell::new(None));
let read_open_result_2 = read_open_result.clone();
executor
.spawner()
.spawn(Box::pin(async move {
let result = system
.open(
c"/myfifo",
OfdAccess::ReadOnly,
EnumSet::empty(),
Mode::empty(),
)
.await;
read_open_result_2.set(Some(result));
}))
.unwrap();
executor.run_until_stalled();
assert_matches!(
(write_open_result.get(), read_open_result.get()),
(Some(Ok(write_fd)), Some(Ok(read_fd))) if write_fd != read_fd
);
}
#[test]
fn open_fifo_reading_and_writing_does_not_block() {
let system = VirtualSystem::new();
create_fifo(&system);
let result = system
.open(
c"/myfifo",
OfdAccess::ReadWrite,
EnumSet::empty(),
Mode::empty(),
)
.now_or_never()
.unwrap();
assert_matches!(result, Ok(_));
}
#[test]
fn open_fifo_reading_nonblocking() {
let system = VirtualSystem::new();
create_fifo(&system);
let result = system
.open(
c"/myfifo",
OfdAccess::ReadOnly,
EnumSet::only(OpenFlag::NonBlock),
Mode::empty(),
)
.now_or_never()
.unwrap();
assert_matches!(result, Ok(_));
}
#[test]
fn open_fifo_writing_nonblocking_without_readers() {
let system = VirtualSystem::new();
create_fifo(&system);
let result = system
.open(
c"/myfifo",
OfdAccess::WriteOnly,
EnumSet::only(OpenFlag::NonBlock),
Mode::empty(),
)
.now_or_never()
.unwrap();
assert_matches!(result, Err(Errno::ENXIO));
}
#[test]
fn open_fifo_writing_nonblocking_with_readers() {
let system = VirtualSystem::new();
create_fifo(&system);
let read_result = system
.open(
c"/myfifo",
OfdAccess::ReadOnly,
EnumSet::only(OpenFlag::NonBlock),
Mode::empty(),
)
.now_or_never()
.unwrap();
assert_matches!(read_result, Ok(_));
let write_result = system
.open(
c"/myfifo",
OfdAccess::WriteOnly,
EnumSet::only(OpenFlag::NonBlock),
Mode::empty(),
)
.now_or_never()
.unwrap();
assert_matches!(write_result, Ok(_));
}