From 93b85d8b70b14c49a983a6ab94cec6154bb209ef Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Sat, 4 Nov 2017 11:59:39 -0600 Subject: Add AioCb::from_ptr and AioCb::from_mut_ptr --- test/sys/test_aio.rs | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) (limited to 'test/sys') diff --git a/test/sys/test_aio.rs b/test/sys/test_aio.rs index 1f807585..42e71fdb 100644 --- a/test/sys/test_aio.rs +++ b/test/sys/test_aio.rs @@ -1,4 +1,4 @@ -use libc::c_int; +use libc::{c_int, c_void}; use nix::{Error, Result}; use nix::errno::*; use nix::sys::aio::*; @@ -244,6 +244,36 @@ fn test_read_into_mut_slice() { assert!(rbuf == EXPECT); } +// Tests from_ptr +#[test] +#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] +fn test_read_into_pointer() { + const INITIAL: &'static [u8] = b"abcdef123456"; + let mut rbuf = vec![0; 4]; + const EXPECT: &'static [u8] = b"cdef"; + let mut f = tempfile().unwrap(); + f.write(INITIAL).unwrap(); + { + // Safety: ok because rbuf lives until after poll_aio + let mut aiocb = unsafe { + AioCb::from_mut_ptr( f.as_raw_fd(), + 2, //offset + rbuf.as_mut_ptr() as *mut c_void, + rbuf.len(), + 0, //priority + SigevNotify::SigevNone, + LioOpcode::LIO_NOP) + }; + aiocb.read().unwrap(); + + let err = poll_aio(&mut aiocb); + assert!(err == Ok(())); + assert!(aiocb.aio_return().unwrap() as usize == EXPECT.len()); + } + + assert!(rbuf == EXPECT); +} + // Test reading into an immutable buffer. It should fail // FIXME: This test fails to panic on Linux/musl #[test] @@ -292,6 +322,39 @@ fn test_write() { assert!(rbuf == EXPECT); } +// Tests `AioCb::from_ptr` +#[test] +#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] +fn test_write_into_pointer() { + const INITIAL: &'static [u8] = b"abcdef123456"; + let wbuf = "CDEF".to_string().into_bytes(); + let mut rbuf = Vec::new(); + const EXPECT: &'static [u8] = b"abCDEF123456"; + + let mut f = tempfile().unwrap(); + f.write(INITIAL).unwrap(); + // Safety: ok because aiocb outlives poll_aio + let mut aiocb = unsafe { + AioCb::from_ptr( f.as_raw_fd(), + 2, //offset + wbuf.as_ptr() as *const c_void, + wbuf.len(), + 0, //priority + SigevNotify::SigevNone, + LioOpcode::LIO_NOP) + }; + aiocb.write().unwrap(); + + let err = poll_aio(&mut aiocb); + assert!(err == Ok(())); + assert!(aiocb.aio_return().unwrap() as usize == wbuf.len()); + + f.seek(SeekFrom::Start(0)).unwrap(); + let len = f.read_to_end(&mut rbuf).unwrap(); + assert!(len == EXPECT.len()); + assert!(rbuf == EXPECT); +} + /// `AioCb::write` should not modify the `AioCb` object if libc::aio_write returns /// an error // Skip on Linux, because Linux's AIO implementation can't detect errors -- cgit v1.2.3 From 631e3f30f6ed58596efec58a286bad75fee482de Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Sat, 4 Nov 2017 14:48:14 -0600 Subject: aio: use `Bytes` instead of `Rc<[u8]>` It's not actually safe to read into an `Rc<[u8]>`. It only worked because of a coincidental `unsafe` block. Replace that type with `BytesMut` from the bytes crate. For consistency's sake, use `Bytes` for writing too, and completely remove methods relating to `Rc<[u8]>`. Note that the `AioCb` will actually own the `BytesMut` object. The caller must call `into_buffer` to get it back once the I/O is complete. Fixes #788 --- test/sys/test_aio.rs | 137 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 112 insertions(+), 25 deletions(-) (limited to 'test/sys') diff --git a/test/sys/test_aio.rs b/test/sys/test_aio.rs index 42e71fdb..de4a920f 100644 --- a/test/sys/test_aio.rs +++ b/test/sys/test_aio.rs @@ -1,3 +1,4 @@ +use bytes::{Bytes, BytesMut}; use libc::{c_int, c_void}; use nix::{Error, Result}; use nix::errno::*; @@ -7,7 +8,6 @@ use nix::sys::time::{TimeSpec, TimeValLike}; use std::io::{Write, Read, Seek, SeekFrom}; use std::ops::Deref; use std::os::unix::io::AsRawFd; -use std::rc::Rc; use std::sync::atomic::{AtomicBool, Ordering}; use std::{thread, time}; use tempfile::tempfile; @@ -135,9 +135,10 @@ fn test_fsync_error() { #[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] fn test_aio_suspend() { const INITIAL: &[u8] = b"abcdef123456"; - const WBUF: &[u8] = b"CDEF"; + const WBUF: &[u8] = b"CDEFG"; let timeout = TimeSpec::seconds(10); - let rbuf = Rc::new(vec![0; 4].into_boxed_slice()); + let mut rbuf = vec![0; 4]; + let rlen = rbuf.len(); let mut f = tempfile().unwrap(); f.write_all(INITIAL).unwrap(); @@ -148,9 +149,9 @@ fn test_aio_suspend() { SigevNotify::SigevNone, LioOpcode::LIO_WRITE); - let mut rcb = AioCb::from_boxed_slice( f.as_raw_fd(), + let mut rcb = AioCb::from_mut_slice( f.as_raw_fd(), 8, //offset - Rc::clone(&rbuf), + &mut rbuf, 0, //priority SigevNotify::SigevNone, LioOpcode::LIO_READ); @@ -168,7 +169,7 @@ fn test_aio_suspend() { } assert!(wcb.aio_return().unwrap() as usize == WBUF.len()); - assert!(rcb.aio_return().unwrap() as usize == WBUF.len()); + assert!(rcb.aio_return().unwrap() as usize == rlen); } // Test a simple aio operation with no completion notification. We must poll @@ -177,14 +178,14 @@ fn test_aio_suspend() { #[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] fn test_read() { const INITIAL: &[u8] = b"abcdef123456"; - let rbuf = Rc::new(vec![0; 4].into_boxed_slice()); + let mut rbuf = vec![0; 4]; const EXPECT: &[u8] = b"cdef"; let mut f = tempfile().unwrap(); f.write_all(INITIAL).unwrap(); { - let mut aiocb = AioCb::from_boxed_slice( f.as_raw_fd(), + let mut aiocb = AioCb::from_mut_slice( f.as_raw_fd(), 2, //offset - Rc::clone(&rbuf), + &mut rbuf, 0, //priority SigevNotify::SigevNone, LioOpcode::LIO_NOP); @@ -206,12 +207,12 @@ fn test_read() { #[cfg(any(target_os = "freebsd", target_os = "macos"))] fn test_read_error() { const INITIAL: &[u8] = b"abcdef123456"; - let rbuf = Rc::new(vec![0; 4].into_boxed_slice()); + let mut rbuf = vec![0; 4]; let mut f = tempfile().unwrap(); f.write_all(INITIAL).unwrap(); - let mut aiocb = AioCb::from_boxed_slice( f.as_raw_fd(), + let mut aiocb = AioCb::from_mut_slice( f.as_raw_fd(), -1, //an invalid offset - Rc::clone(&rbuf), + &mut rbuf, 0, //priority SigevNotify::SigevNone, LioOpcode::LIO_NOP); @@ -322,10 +323,93 @@ fn test_write() { assert!(rbuf == EXPECT); } +// Tests `AioCb::from_bytes` +#[test] +#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] +fn test_write_bytes() { + const INITIAL: &[u8] = b"abcdef123456"; + let wbuf = Bytes::from(&b"CDEF"[..]); + let mut rbuf = Vec::new(); + const EXPECT: &[u8] = b"abCDEF123456"; + + let mut f = tempfile().unwrap(); + f.write(INITIAL).unwrap(); + let mut aiocb = AioCb::from_bytes( f.as_raw_fd(), + 2, //offset + wbuf.clone(), + 0, //priority + SigevNotify::SigevNone, + LioOpcode::LIO_NOP); + aiocb.write().unwrap(); + + let err = poll_aio(&mut aiocb); + assert!(err == Ok(())); + assert!(aiocb.aio_return().unwrap() as usize == wbuf.len()); + + f.seek(SeekFrom::Start(0)).unwrap(); + let len = f.read_to_end(&mut rbuf).unwrap(); + assert!(len == EXPECT.len()); + assert!(rbuf == EXPECT); +} + +// Tests `AioCb::from_bytes_mut` +#[test] +#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] +fn test_read_bytes_mut_big() { + const INITIAL: &'static [u8] = b"abcdefgh12345678abcdefgh12345678abcdefgh12345678abcdefgh12345678abcdefgh12345678"; + // rbuf needs to be larger than 32 bytes (64 on 32-bit systems) so + // BytesMut::clone is implemented by reference. + let rbuf = BytesMut::from(vec![0; 70]); + const EXPECT: &'static [u8] = b"cdefgh12345678abcdefgh12345678abcdefgh12345678abcdefgh12345678abcdefgh"; + let mut f = tempfile().unwrap(); + f.write(INITIAL).unwrap(); + + let mut aiocb = AioCb::from_bytes_mut( f.as_raw_fd(), + 2, //offset + rbuf, + 0, //priority + SigevNotify::SigevNone, + LioOpcode::LIO_NOP); + aiocb.read().unwrap(); + + let err = poll_aio(&mut aiocb); + assert_eq!(err, Ok(())); + assert_eq!(aiocb.aio_return().unwrap() as usize, EXPECT.len()); + let buffer = aiocb.into_buffer(); + assert_eq!(buffer.bytes_mut().unwrap(), EXPECT); +} + +// Tests reallocation in `AioCb::from_bytes_mut` +#[test] +#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] +fn test_read_bytes_mut_small() { + const INITIAL: &'static [u8] = b"abcdef"; + // rbuf needs to be no more than 32 bytes (64 on 32-bit systems) so + // BytesMut::clone is implemented inline. + let rbuf = BytesMut::from(vec![0; 4]); + const EXPECT: &'static [u8] = b"cdef"; + let mut f = tempfile().unwrap(); + f.write(INITIAL).unwrap(); + + let mut aiocb = AioCb::from_bytes_mut( f.as_raw_fd(), + 2, //offset + rbuf, + 0, //priority + SigevNotify::SigevNone, + LioOpcode::LIO_NOP); + aiocb.read().unwrap(); + + let err = poll_aio(&mut aiocb); + assert_eq!(err, Ok(())); + assert_eq!(aiocb.aio_return().unwrap() as usize, EXPECT.len()); + let buffer = aiocb.into_buffer(); + assert_eq!(buffer.bytes_mut().unwrap(), EXPECT); +} + // Tests `AioCb::from_ptr` #[test] #[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] -fn test_write_into_pointer() { +fn test_write_from_pointer() { const INITIAL: &'static [u8] = b"abcdef123456"; let wbuf = "CDEF".to_string().into_bytes(); let mut rbuf = Vec::new(); @@ -429,7 +513,8 @@ fn test_write_sigev_signal() { fn test_lio_listio_wait() { const INITIAL: &[u8] = b"abcdef123456"; const WBUF: &[u8] = b"CDEF"; - let rbuf = Rc::new(vec![0; 4].into_boxed_slice()); + let mut rbuf = vec![0; 4]; + let rlen = rbuf.len(); let mut rbuf2 = Vec::new(); const EXPECT: &[u8] = b"abCDEF123456"; let mut f = tempfile().unwrap(); @@ -444,9 +529,9 @@ fn test_lio_listio_wait() { SigevNotify::SigevNone, LioOpcode::LIO_WRITE); - let mut rcb = AioCb::from_boxed_slice( f.as_raw_fd(), + let mut rcb = AioCb::from_mut_slice( f.as_raw_fd(), 8, //offset - Rc::clone(&rbuf), + &mut rbuf, 0, //priority SigevNotify::SigevNone, LioOpcode::LIO_READ); @@ -454,7 +539,7 @@ fn test_lio_listio_wait() { err.expect("lio_listio failed"); assert!(wcb.aio_return().unwrap() as usize == WBUF.len()); - assert!(rcb.aio_return().unwrap() as usize == WBUF.len()); + assert!(rcb.aio_return().unwrap() as usize == rlen); } assert!(rbuf.deref().deref() == b"3456"); @@ -472,7 +557,8 @@ fn test_lio_listio_wait() { fn test_lio_listio_nowait() { const INITIAL: &[u8] = b"abcdef123456"; const WBUF: &[u8] = b"CDEF"; - let rbuf = Rc::new(vec![0; 4].into_boxed_slice()); + let mut rbuf = vec![0; 4]; + let rlen = rbuf.len(); let mut rbuf2 = Vec::new(); const EXPECT: &[u8] = b"abCDEF123456"; let mut f = tempfile().unwrap(); @@ -487,9 +573,9 @@ fn test_lio_listio_nowait() { SigevNotify::SigevNone, LioOpcode::LIO_WRITE); - let mut rcb = AioCb::from_boxed_slice( f.as_raw_fd(), + let mut rcb = AioCb::from_mut_slice( f.as_raw_fd(), 8, //offset - Rc::clone(&rbuf), + &mut rbuf, 0, //priority SigevNotify::SigevNone, LioOpcode::LIO_READ); @@ -499,7 +585,7 @@ fn test_lio_listio_nowait() { poll_aio(&mut wcb).unwrap(); poll_aio(&mut rcb).unwrap(); assert!(wcb.aio_return().unwrap() as usize == WBUF.len()); - assert!(rcb.aio_return().unwrap() as usize == WBUF.len()); + assert!(rcb.aio_return().unwrap() as usize == rlen); } assert!(rbuf.deref().deref() == b"3456"); @@ -520,7 +606,8 @@ fn test_lio_listio_signal() { let m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test"); const INITIAL: &[u8] = b"abcdef123456"; const WBUF: &[u8] = b"CDEF"; - let rbuf = Rc::new(vec![0; 4].into_boxed_slice()); + let mut rbuf = vec![0; 4]; + let rlen = rbuf.len(); let mut rbuf2 = Vec::new(); const EXPECT: &[u8] = b"abCDEF123456"; let mut f = tempfile().unwrap(); @@ -540,9 +627,9 @@ fn test_lio_listio_signal() { SigevNotify::SigevNone, LioOpcode::LIO_WRITE); - let mut rcb = AioCb::from_boxed_slice( f.as_raw_fd(), + let mut rcb = AioCb::from_mut_slice( f.as_raw_fd(), 8, //offset - Rc::clone(&rbuf), + &mut rbuf, 0, //priority SigevNotify::SigevNone, LioOpcode::LIO_READ); @@ -555,7 +642,7 @@ fn test_lio_listio_signal() { } assert!(wcb.aio_return().unwrap() as usize == WBUF.len()); - assert!(rcb.aio_return().unwrap() as usize == WBUF.len()); + assert!(rcb.aio_return().unwrap() as usize == rlen); } assert!(rbuf.deref().deref() == b"3456"); -- cgit v1.2.3 From ec935e6ef6c4ec09ab2f00b84d2906e3c05c5b55 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Sat, 13 Jan 2018 15:12:08 -0700 Subject: aio: Clippy cleanup --- test/sys/test_aio.rs | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'test/sys') diff --git a/test/sys/test_aio.rs b/test/sys/test_aio.rs index de4a920f..ed9d3761 100644 --- a/test/sys/test_aio.rs +++ b/test/sys/test_aio.rs @@ -110,7 +110,7 @@ fn test_fsync() { aiocb.aio_return().unwrap(); } -/// `AioCb::fsync` should not modify the `AioCb` object if libc::aio_fsync returns +/// `AioCb::fsync` should not modify the `AioCb` object if `libc::aio_fsync` returns /// an error // Skip on Linux, because Linux's AIO implementation can't detect errors // synchronously @@ -199,8 +199,8 @@ fn test_read() { assert!(EXPECT == rbuf.deref().deref()); } -/// `AioCb::read` should not modify the `AioCb` object if libc::aio_read returns -/// an error +/// `AioCb::read` should not modify the `AioCb` object if `libc::aio_read` +/// returns an error // Skip on Linux, because Linux's AIO implementation can't detect errors // synchronously #[test] @@ -249,11 +249,11 @@ fn test_read_into_mut_slice() { #[test] #[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] fn test_read_into_pointer() { - const INITIAL: &'static [u8] = b"abcdef123456"; + const INITIAL: &[u8] = b"abcdef123456"; let mut rbuf = vec![0; 4]; - const EXPECT: &'static [u8] = b"cdef"; + const EXPECT: &[u8] = b"cdef"; let mut f = tempfile().unwrap(); - f.write(INITIAL).unwrap(); + f.write_all(INITIAL).unwrap(); { // Safety: ok because rbuf lives until after poll_aio let mut aiocb = unsafe { @@ -333,7 +333,7 @@ fn test_write_bytes() { const EXPECT: &[u8] = b"abCDEF123456"; let mut f = tempfile().unwrap(); - f.write(INITIAL).unwrap(); + f.write_all(INITIAL).unwrap(); let mut aiocb = AioCb::from_bytes( f.as_raw_fd(), 2, //offset wbuf.clone(), @@ -356,13 +356,13 @@ fn test_write_bytes() { #[test] #[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] fn test_read_bytes_mut_big() { - const INITIAL: &'static [u8] = b"abcdefgh12345678abcdefgh12345678abcdefgh12345678abcdefgh12345678abcdefgh12345678"; + const INITIAL: &[u8] = b"abcdefgh12345678abcdefgh12345678abcdefgh12345678abcdefgh12345678abcdefgh12345678"; // rbuf needs to be larger than 32 bytes (64 on 32-bit systems) so // BytesMut::clone is implemented by reference. let rbuf = BytesMut::from(vec![0; 70]); - const EXPECT: &'static [u8] = b"cdefgh12345678abcdefgh12345678abcdefgh12345678abcdefgh12345678abcdefgh"; + const EXPECT: &[u8] = b"cdefgh12345678abcdefgh12345678abcdefgh12345678abcdefgh12345678abcdefgh"; let mut f = tempfile().unwrap(); - f.write(INITIAL).unwrap(); + f.write_all(INITIAL).unwrap(); let mut aiocb = AioCb::from_bytes_mut( f.as_raw_fd(), 2, //offset @@ -383,13 +383,13 @@ fn test_read_bytes_mut_big() { #[test] #[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] fn test_read_bytes_mut_small() { - const INITIAL: &'static [u8] = b"abcdef"; + const INITIAL: &[u8] = b"abcdef"; // rbuf needs to be no more than 32 bytes (64 on 32-bit systems) so // BytesMut::clone is implemented inline. let rbuf = BytesMut::from(vec![0; 4]); - const EXPECT: &'static [u8] = b"cdef"; + const EXPECT: &[u8] = b"cdef"; let mut f = tempfile().unwrap(); - f.write(INITIAL).unwrap(); + f.write_all(INITIAL).unwrap(); let mut aiocb = AioCb::from_bytes_mut( f.as_raw_fd(), 2, //offset @@ -410,13 +410,13 @@ fn test_read_bytes_mut_small() { #[test] #[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] fn test_write_from_pointer() { - const INITIAL: &'static [u8] = b"abcdef123456"; + const INITIAL: &[u8] = b"abcdef123456"; let wbuf = "CDEF".to_string().into_bytes(); let mut rbuf = Vec::new(); - const EXPECT: &'static [u8] = b"abCDEF123456"; + const EXPECT: &[u8] = b"abCDEF123456"; let mut f = tempfile().unwrap(); - f.write(INITIAL).unwrap(); + f.write_all(INITIAL).unwrap(); // Safety: ok because aiocb outlives poll_aio let mut aiocb = unsafe { AioCb::from_ptr( f.as_raw_fd(), @@ -439,8 +439,8 @@ fn test_write_from_pointer() { assert!(rbuf == EXPECT); } -/// `AioCb::write` should not modify the `AioCb` object if libc::aio_write returns -/// an error +/// `AioCb::write` should not modify the `AioCb` object if `libc::aio_write` +/// returns an error // Skip on Linux, because Linux's AIO implementation can't detect errors // synchronously #[test] -- cgit v1.2.3 From c3ff37b0942f527295a7213f44eee13bf2590ddf Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Sat, 13 Jan 2018 20:47:38 -0700 Subject: aio: more documentation --- test/sys/test_aio.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'test/sys') diff --git a/test/sys/test_aio.rs b/test/sys/test_aio.rs index ed9d3761..f88fc268 100644 --- a/test/sys/test_aio.rs +++ b/test/sys/test_aio.rs @@ -43,8 +43,8 @@ fn test_accessors() { assert_eq!(99, sev.sigev_value.sival_ptr as i64); } -// Tests AioCb.cancel. We aren't trying to test the OS's implementation, only our -// bindings. So it's sufficient to check that AioCb.cancel returned any +// Tests AioCb.cancel. We aren't trying to test the OS's implementation, only +// our bindings. So it's sufficient to check that AioCb.cancel returned any // AioCancelStat value. #[test] #[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] -- cgit v1.2.3