diff --git a/kernel/src/fs/pipe/anon_pipe.rs b/kernel/src/fs/pipe/anon_pipe.rs index 5dee1ade6..0db3a46c9 100644 --- a/kernel/src/fs/pipe/anon_pipe.rs +++ b/kernel/src/fs/pipe/anon_pipe.rs @@ -234,146 +234,3 @@ impl Inode for AnonPipeInode { fn set_ctime(&self, time: Duration); fn fs(&self) -> Arc; } - -#[cfg(ktest)] -mod test { - use alloc::sync::Arc; - use core::sync::atomic::{self, AtomicBool}; - - use ostd::prelude::*; - - use super::*; - use crate::thread::{Thread, kernel_thread::ThreadOptions}; - - #[derive(Clone, Copy, Debug, PartialEq, Eq)] - enum Ordering { - WriteThenRead, - ReadThenWrite, - } - - fn test_blocking(write: W, read: R, ordering: Ordering) - where - W: FnOnce(Arc) + Send + 'static, - R: FnOnce(Arc) + Send + 'static, - { - let (reader, writer) = new_file_pair().unwrap(); - - let signal_writer = Arc::new(AtomicBool::new(false)); - let signal_reader = signal_writer.clone(); - - let writer = ThreadOptions::new(move || { - if ordering == Ordering::ReadThenWrite { - while !signal_writer.load(atomic::Ordering::Relaxed) { - Thread::yield_now(); - } - } else { - signal_writer.store(true, atomic::Ordering::Relaxed); - } - - write(writer); - }) - .spawn(); - - let reader = ThreadOptions::new(move || { - if ordering == Ordering::WriteThenRead { - while !signal_reader.load(atomic::Ordering::Relaxed) { - Thread::yield_now(); - } - } else { - signal_reader.store(true, atomic::Ordering::Relaxed); - } - - read(reader); - }) - .spawn(); - - writer.join(); - reader.join(); - } - - #[ktest] - fn test_read_empty() { - test_blocking( - |writer| { - assert_eq!(writer.write(&mut reader_from(&[1])).unwrap(), 1); - }, - |reader| { - let mut buf = [0; 1]; - assert_eq!(reader.read(&mut writer_from(&mut buf)).unwrap(), 1); - assert_eq!(&buf, &[1]); - }, - Ordering::ReadThenWrite, - ); - } - - #[ktest] - fn test_write_full() { - test_blocking( - |writer| { - assert_eq!(writer.write(&mut reader_from(&[1, 2, 3])).unwrap(), 2); - assert_eq!(writer.write(&mut reader_from(&[2])).unwrap(), 1); - }, - |reader| { - let mut buf = [0; 3]; - assert_eq!(reader.read(&mut writer_from(&mut buf)).unwrap(), 2); - assert_eq!(&buf[..2], &[1, 2]); - assert_eq!(reader.read(&mut writer_from(&mut buf)).unwrap(), 1); - assert_eq!(&buf[..1], &[2]); - }, - Ordering::WriteThenRead, - ); - } - - #[ktest] - fn test_read_closed() { - test_blocking( - drop, - |reader| { - let mut buf = [0; 1]; - assert_eq!(reader.read(&mut writer_from(&mut buf)).unwrap(), 0); - }, - Ordering::ReadThenWrite, - ); - } - - #[ktest] - fn test_write_closed() { - test_blocking( - |writer| { - assert_eq!(writer.write(&mut reader_from(&[1, 2, 3])).unwrap(), 2); - assert_eq!( - writer.write(&mut reader_from(&[2])).unwrap_err().error(), - Errno::EPIPE - ); - }, - drop, - Ordering::WriteThenRead, - ); - } - - #[ktest] - fn test_write_atomicity() { - test_blocking( - |writer| { - assert_eq!(writer.write(&mut reader_from(&[1])).unwrap(), 1); - assert_eq!(writer.write(&mut reader_from(&[1, 2])).unwrap(), 2); - }, - |reader| { - let mut buf = [0; 3]; - assert_eq!(reader.read(&mut writer_from(&mut buf)).unwrap(), 1); - assert_eq!(&buf[..1], &[1]); - assert_eq!(reader.read(&mut writer_from(&mut buf)).unwrap(), 2); - assert_eq!(&buf[..2], &[1, 2]); - }, - Ordering::WriteThenRead, - ); - } - - fn reader_from(buf: &[u8]) -> VmReader<'_> { - VmReader::from(buf).to_fallible() - } - - fn writer_from(buf: &mut [u8]) -> VmWriter<'_> { - VmWriter::from(buf).to_fallible() - } -} diff --git a/kernel/src/fs/pipe/common.rs b/kernel/src/fs/pipe/common.rs index d7ec13a13..ebf5a6fdb 100644 --- a/kernel/src/fs/pipe/common.rs +++ b/kernel/src/fs/pipe/common.rs @@ -459,3 +459,160 @@ impl Pollable for PipeWriter { .poll_with(mask, poller, || self.check_io_events()) } } + +#[cfg(ktest)] +mod test { + use alloc::sync::Arc; + use core::sync::atomic::{self, AtomicBool}; + + use ostd::prelude::*; + + use super::*; + use crate::thread::{Thread, kernel_thread::ThreadOptions}; + + #[derive(Clone, Copy, Debug, PartialEq, Eq)] + enum Ordering { + WriteThenRead, + ReadThenWrite, + } + + fn test_blocking(write: W, read: R, ordering: Ordering) + where + W: FnOnce(Box) + Send + 'static, + R: FnOnce(Box) + Send + 'static, + { + let pipe = Pipe::new(); + let reader = pipe + .open_anon(AccessMode::O_RDONLY, StatusFlags::empty()) + .unwrap(); + let writer = pipe + .open_anon(AccessMode::O_WRONLY, StatusFlags::empty()) + .unwrap(); + + let signal_writer = Arc::new(AtomicBool::new(false)); + let signal_reader = signal_writer.clone(); + + let writer = ThreadOptions::new(move || { + if ordering == Ordering::ReadThenWrite { + while !signal_writer.load(atomic::Ordering::Relaxed) { + Thread::yield_now(); + } + } else { + signal_writer.store(true, atomic::Ordering::Relaxed); + } + + write(writer); + }) + .spawn(); + + let reader = ThreadOptions::new(move || { + if ordering == Ordering::WriteThenRead { + while !signal_reader.load(atomic::Ordering::Relaxed) { + Thread::yield_now(); + } + } else { + signal_reader.store(true, atomic::Ordering::Relaxed); + } + + read(reader); + }) + .spawn(); + + writer.join(); + reader.join(); + } + + #[ktest] + fn test_read_empty() { + test_blocking( + |writer| { + assert_eq!(write(writer.as_ref(), &[1]).unwrap(), 1); + }, + |reader| { + let mut buf = [0; 1]; + assert_eq!(read(reader.as_ref(), &mut buf).unwrap(), 1); + assert_eq!(&buf, &[1]); + }, + Ordering::ReadThenWrite, + ); + } + + #[ktest] + fn test_write_full() { + test_blocking( + |writer| { + assert_eq!(write(writer.as_ref(), &[1, 2, 3]).unwrap(), 2); + assert_eq!(write(writer.as_ref(), &[2]).unwrap(), 1); + }, + |reader| { + let mut buf = [0; 3]; + assert_eq!(read(reader.as_ref(), &mut buf).unwrap(), 2); + assert_eq!(&buf[..2], &[1, 2]); + assert_eq!(read(reader.as_ref(), &mut buf).unwrap(), 1); + assert_eq!(&buf[..1], &[2]); + }, + Ordering::WriteThenRead, + ); + } + + #[ktest] + fn test_read_closed() { + test_blocking( + drop, + |reader| { + let mut buf = [0; 1]; + assert_eq!(read(reader.as_ref(), &mut buf).unwrap(), 0); + }, + Ordering::ReadThenWrite, + ); + } + + #[ktest] + fn test_write_closed() { + test_blocking( + |writer| { + assert_eq!(write(writer.as_ref(), &[1, 2, 3]).unwrap(), 2); + assert_eq!( + write(writer.as_ref(), &[2]).unwrap_err().error(), + Errno::EPIPE + ); + }, + drop, + Ordering::WriteThenRead, + ); + } + + #[ktest] + fn test_write_atomicity() { + test_blocking( + |writer| { + assert_eq!(write(writer.as_ref(), &[1]).unwrap(), 1); + assert_eq!(write(writer.as_ref(), &[1, 2]).unwrap(), 2); + }, + |reader| { + let mut buf = [0; 3]; + assert_eq!(read(reader.as_ref(), &mut buf).unwrap(), 1); + assert_eq!(&buf[..1], &[1]); + assert_eq!(read(reader.as_ref(), &mut buf).unwrap(), 2); + assert_eq!(&buf[..2], &[1, 2]); + }, + Ordering::WriteThenRead, + ); + } + + fn read(reader: &dyn FileIo, buf: &mut [u8]) -> crate::prelude::Result { + reader.read_at( + 0, + &mut VmWriter::from(buf).to_fallible(), + StatusFlags::empty(), + ) + } + + fn write(writer: &dyn FileIo, buf: &[u8]) -> crate::prelude::Result { + writer.write_at( + 0, + &mut VmReader::from(buf).to_fallible(), + StatusFlags::empty(), + ) + } +}