Move pipe ktests into `pipe::common`
This commit is contained in:
parent
b25e41dd4f
commit
8eade9b631
|
|
@ -234,146 +234,3 @@ impl Inode for AnonPipeInode {
|
|||
fn set_ctime(&self, time: Duration);
|
||||
fn fs(&self) -> Arc<dyn FileSystem>;
|
||||
}
|
||||
|
||||
#[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<W, R>(write: W, read: R, ordering: Ordering)
|
||||
where
|
||||
W: FnOnce(Arc<AnonPipeFile>) + Send + 'static,
|
||||
R: FnOnce(Arc<AnonPipeFile>) + 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()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<W, R>(write: W, read: R, ordering: Ordering)
|
||||
where
|
||||
W: FnOnce(Box<dyn FileIo>) + Send + 'static,
|
||||
R: FnOnce(Box<dyn FileIo>) + 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<usize> {
|
||||
reader.read_at(
|
||||
0,
|
||||
&mut VmWriter::from(buf).to_fallible(),
|
||||
StatusFlags::empty(),
|
||||
)
|
||||
}
|
||||
|
||||
fn write(writer: &dyn FileIo, buf: &[u8]) -> crate::prelude::Result<usize> {
|
||||
writer.write_at(
|
||||
0,
|
||||
&mut VmReader::from(buf).to_fallible(),
|
||||
StatusFlags::empty(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue