diff options
Diffstat (limited to 'vendor/rustix/tests/io')
-rw-r--r-- | vendor/rustix/tests/io/dup2_to_replace_stdio.rs | 18 | ||||
-rw-r--r-- | vendor/rustix/tests/io/epoll.rs | 103 | ||||
-rw-r--r-- | vendor/rustix/tests/io/error.rs | 14 | ||||
-rw-r--r-- | vendor/rustix/tests/io/eventfd.rs | 24 | ||||
-rw-r--r-- | vendor/rustix/tests/io/from_into.rs | 28 | ||||
-rw-r--r-- | vendor/rustix/tests/io/ioctl.rs | 14 | ||||
-rw-r--r-- | vendor/rustix/tests/io/main.rs | 31 | ||||
-rw-r--r-- | vendor/rustix/tests/io/poll.rs | 63 | ||||
-rw-r--r-- | vendor/rustix/tests/io/procfs.rs | 8 | ||||
-rw-r--r-- | vendor/rustix/tests/io/read_write.rs | 118 | ||||
-rw-r--r-- | vendor/rustix/tests/io/seals.rs | 41 |
11 files changed, 462 insertions, 0 deletions
diff --git a/vendor/rustix/tests/io/dup2_to_replace_stdio.rs b/vendor/rustix/tests/io/dup2_to_replace_stdio.rs new file mode 100644 index 000000000..b07ec17f0 --- /dev/null +++ b/vendor/rustix/tests/io/dup2_to_replace_stdio.rs @@ -0,0 +1,18 @@ +#![cfg(not(target_os = "wasi"))] + +use std::env; +use std::process::Command; + +/// Use `dup2` to replace the stdin and stdout file descriptors. +#[test] +fn dup2_to_replace_stdio() { + // This test modifies the stdio file descriptors, so we run it in a + // separate process so that it doesn't interfere with the test harness. + assert!(Command::new(env::var("CARGO").unwrap()) + .arg("run") + .arg("--example") + .arg("dup2_to_replace_stdio") + .status() + .unwrap() + .success()); +} diff --git a/vendor/rustix/tests/io/epoll.rs b/vendor/rustix/tests/io/epoll.rs new file mode 100644 index 000000000..4cfe305fe --- /dev/null +++ b/vendor/rustix/tests/io/epoll.rs @@ -0,0 +1,103 @@ +#![cfg(any(target_os = "android", target_os = "linux"))] + +use rustix::fd::AsFd; +use rustix::io::epoll::{self, Epoll}; +use rustix::io::{ioctl_fionbio, read, write, OwnedFd}; +use rustix::net::{ + accept, bind_v4, connect_v4, getsockname, listen, socket, AddressFamily, Ipv4Addr, Protocol, + SocketAddrAny, SocketAddrV4, SocketType, +}; +use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; +use std::sync::{Arc, Condvar, Mutex}; +use std::thread; + +const BUFFER_SIZE: usize = 20; + +fn server(ready: Arc<(Mutex<u16>, Condvar)>) { + let listen_sock = socket(AddressFamily::INET, SocketType::STREAM, Protocol::default()).unwrap(); + bind_v4(&listen_sock, &SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0)).unwrap(); + listen(&listen_sock, 1).unwrap(); + + let who = match getsockname(&listen_sock).unwrap() { + SocketAddrAny::V4(addr) => addr, + _ => panic!(), + }; + + { + let (lock, cvar) = &*ready; + let mut port = lock.lock().unwrap(); + *port = who.port(); + cvar.notify_all(); + } + + let epoll = Epoll::new(epoll::CreateFlags::CLOEXEC, epoll::Owning::<OwnedFd>::new()).unwrap(); + + // Test into conversions. + let fd: OwnedFd = epoll.into(); + let epoll: Epoll<epoll::Owning<OwnedFd>> = fd.into(); + let fd: RawFd = epoll.into_raw_fd(); + let epoll = unsafe { Epoll::<epoll::Owning<OwnedFd>>::from_raw_fd(fd) }; + + let raw_listen_sock = listen_sock.as_fd().as_raw_fd(); + epoll.add(listen_sock, epoll::EventFlags::IN).unwrap(); + + let mut event_list = epoll::EventVec::with_capacity(4); + loop { + epoll.wait(&mut event_list, -1).unwrap(); + for (_event_flags, target) in &event_list { + if target.as_raw_fd() == raw_listen_sock { + let conn_sock = accept(&*target).unwrap(); + ioctl_fionbio(&conn_sock, true).unwrap(); + epoll + .add(conn_sock, epoll::EventFlags::OUT | epoll::EventFlags::ET) + .unwrap(); + } else { + write(&*target, b"hello\n").unwrap(); + let _ = epoll.del(target).unwrap(); + } + } + } +} + +fn client(ready: Arc<(Mutex<u16>, Condvar)>) { + let port = { + let (lock, cvar) = &*ready; + let mut port = lock.lock().unwrap(); + while *port == 0 { + port = cvar.wait(port).unwrap(); + } + *port + }; + + let addr = SocketAddrV4::new(Ipv4Addr::LOCALHOST, port); + let mut buffer = vec![0; BUFFER_SIZE]; + + for _ in 0..16 { + let data_socket = + socket(AddressFamily::INET, SocketType::STREAM, Protocol::default()).unwrap(); + connect_v4(&data_socket, &addr).unwrap(); + + let nread = read(&data_socket, &mut buffer).unwrap(); + assert_eq!(String::from_utf8_lossy(&buffer[..nread]), "hello\n"); + } +} + +#[test] +fn test_epoll() { + let ready = Arc::new((Mutex::new(0_u16), Condvar::new())); + let ready_clone = Arc::clone(&ready); + + let _server = thread::Builder::new() + .name("server".to_string()) + .spawn(move || { + server(ready); + }) + .unwrap(); + let client = thread::Builder::new() + .name("client".to_string()) + .spawn(move || { + client(ready_clone); + }) + .unwrap(); + client.join().unwrap(); +} diff --git a/vendor/rustix/tests/io/error.rs b/vendor/rustix/tests/io/error.rs new file mode 100644 index 000000000..128d3b59a --- /dev/null +++ b/vendor/rustix/tests/io/error.rs @@ -0,0 +1,14 @@ +#[test] +fn test_error() { + assert_eq!( + rustix::io::Errno::INVAL, + rustix::io::Errno::from_raw_os_error(rustix::io::Errno::INVAL.raw_os_error()) + ); + #[cfg(not(windows))] + assert_eq!(rustix::io::Errno::INVAL.raw_os_error(), libc::EINVAL); + #[cfg(windows)] + assert_eq!( + rustix::io::Errno::INVAL.raw_os_error(), + windows_sys::Win32::Networking::WinSock::WSAEINVAL + ); +} diff --git a/vendor/rustix/tests/io/eventfd.rs b/vendor/rustix/tests/io/eventfd.rs new file mode 100644 index 000000000..11bc8ae55 --- /dev/null +++ b/vendor/rustix/tests/io/eventfd.rs @@ -0,0 +1,24 @@ +#[cfg(any(target_os = "android", target_os = "linux"))] +#[test] +fn test_eventfd() { + use rustix::io::{eventfd, read, write, EventfdFlags}; + use std::mem::size_of; + use std::thread; + + let efd = eventfd(0, EventfdFlags::CLOEXEC).unwrap(); + + let child = thread::spawn(move || { + for u in [1_u64, 3, 6, 11, 5000].iter() { + assert_eq!(write(&efd, &u.to_ne_bytes()).unwrap(), size_of::<u64>()); + } + efd + }); + + let efd = child.join().unwrap(); + + let mut bytes = [0_u8; size_of::<u64>()]; + let s = read(&efd, &mut bytes).unwrap(); + assert_eq!(s, bytes.len()); + let u = u64::from_ne_bytes(bytes); + assert_eq!(u, 5021); +} diff --git a/vendor/rustix/tests/io/from_into.rs b/vendor/rustix/tests/io/from_into.rs new file mode 100644 index 000000000..94d915993 --- /dev/null +++ b/vendor/rustix/tests/io/from_into.rs @@ -0,0 +1,28 @@ +#[cfg(feature = "fs")] +#[cfg(not(target_os = "redox"))] +#[test] +fn test_owned() { + use rustix::fd::AsFd; + #[cfg(unix)] + use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd}; + #[cfg(target_os = "wasi")] + use std::os::wasi::io::{AsRawFd, FromRawFd, IntoRawFd}; + + let file = rustix::fs::openat( + rustix::fs::cwd(), + "Cargo.toml", + rustix::fs::OFlags::RDONLY, + rustix::fs::Mode::empty(), + ) + .unwrap(); + + let raw = file.as_raw_fd(); + assert_eq!(raw, file.as_fd().as_raw_fd()); + + let inner = file.into_raw_fd(); + assert_eq!(raw, inner); + + let new = unsafe { rustix::io::OwnedFd::from_raw_fd(inner) }; + let mut buf = [0_u8; 4]; + let _ = rustix::io::read(&new, &mut buf).unwrap(); +} diff --git a/vendor/rustix/tests/io/ioctl.rs b/vendor/rustix/tests/io/ioctl.rs new file mode 100644 index 000000000..e260e4884 --- /dev/null +++ b/vendor/rustix/tests/io/ioctl.rs @@ -0,0 +1,14 @@ +// `is_read_write` is not yet implemented on Windows. And `ioctl_fionread` +// on Windows doesn't work on files. +#[cfg(not(windows))] +#[test] +fn test_ioctls() { + let file = std::fs::File::open("Cargo.toml").unwrap(); + + assert_eq!(rustix::io::is_read_write(&file).unwrap(), (true, false)); + + assert_eq!( + rustix::io::ioctl_fionread(&file).unwrap(), + file.metadata().unwrap().len() + ); +} diff --git a/vendor/rustix/tests/io/main.rs b/vendor/rustix/tests/io/main.rs new file mode 100644 index 000000000..bdd044809 --- /dev/null +++ b/vendor/rustix/tests/io/main.rs @@ -0,0 +1,31 @@ +//! Tests for [`rustix::io`]. + +#![cfg_attr(target_os = "wasi", feature(wasi_ext))] +#![cfg_attr(io_lifetimes_use_std, feature(io_safety))] + +#[cfg(not(feature = "rustc-dep-of-std"))] +#[cfg(not(windows))] +#[cfg(not(target_os = "wasi"))] +mod dup2_to_replace_stdio; +#[cfg(not(feature = "rustc-dep-of-std"))] // TODO +#[cfg(not(windows))] +#[cfg(feature = "net")] +#[cfg(not(target_os = "wasi"))] +mod epoll; +mod error; +#[cfg(not(windows))] +#[cfg(not(target_os = "wasi"))] +mod eventfd; +#[cfg(not(windows))] +mod from_into; +#[cfg(not(target_os = "redox"))] +mod ioctl; +mod poll; +#[cfg(all(feature = "procfs", any(target_os = "android", target_os = "linux")))] +mod procfs; +#[cfg(not(windows))] +#[cfg(not(target_os = "redox"))] // redox doesn't have cwd/openat +#[cfg(not(target_os = "wasi"))] // wasi support for S_IRUSR etc. submitted to libc in #2264 +mod read_write; +#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "android"))] +mod seals; diff --git a/vendor/rustix/tests/io/poll.rs b/vendor/rustix/tests/io/poll.rs new file mode 100644 index 000000000..ff2da695b --- /dev/null +++ b/vendor/rustix/tests/io/poll.rs @@ -0,0 +1,63 @@ +use rustix::fd::{AsFd, AsRawFd, FromRawFd, IntoRawFd, OwnedFd}; +#[cfg(not(windows))] +use rustix::io::{poll, retry_on_intr}; +use rustix::io::{PollFd, PollFlags}; + +#[cfg(not(windows))] +#[test] +fn test_poll() { + use rustix::io::{pipe, read, write}; + + // Create a pipe. + let (reader, writer) = pipe().unwrap(); + let mut poll_fds = [PollFd::new(&reader, PollFlags::IN)]; + assert_eq!(poll_fds[0].as_fd().as_raw_fd(), reader.as_fd().as_raw_fd()); + + // `poll` should say there's nothing ready to be read from the pipe. + let num = retry_on_intr(|| poll(&mut poll_fds, 0)).unwrap(); + assert_eq!(num, 0); + assert!(poll_fds[0].revents().is_empty()); + assert_eq!(poll_fds[0].as_fd().as_raw_fd(), reader.as_fd().as_raw_fd()); + + // Write a byte to the pipe. + assert_eq!(retry_on_intr(|| write(&writer, b"a")).unwrap(), 1); + + // `poll` should now say there's data to be read. + let num = retry_on_intr(|| poll(&mut poll_fds, -1)).unwrap(); + assert_eq!(num, 1); + assert_eq!(poll_fds[0].revents(), PollFlags::IN); + assert_eq!(poll_fds[0].as_fd().as_raw_fd(), reader.as_fd().as_raw_fd()); + + let mut temp = poll_fds[0].clone(); + assert_eq!(temp.revents(), PollFlags::IN); + temp.clear_revents(); + assert!(temp.revents().is_empty()); + + // Read the byte from the pipe. + let mut buf = [b'\0']; + assert_eq!(retry_on_intr(|| read(&reader, &mut buf)).unwrap(), 1); + assert_eq!(buf[0], b'a'); + assert_eq!(poll_fds[0].as_fd().as_raw_fd(), reader.as_fd().as_raw_fd()); + + // Poll should now say there's no more data to be read. + let num = retry_on_intr(|| poll(&mut poll_fds, 0)).unwrap(); + assert_eq!(num, 0); + assert!(poll_fds[0].revents().is_empty()); + assert_eq!(poll_fds[0].as_fd().as_raw_fd(), reader.as_fd().as_raw_fd()); +} + +#[test] +fn test_poll_fd_set_fd() { + // Make up some file descriptors so that we can test that set_fd works. + let a = unsafe { OwnedFd::from_raw_fd(777) }; + let mut poll_fd = PollFd::new(&a, PollFlags::empty()); + assert_eq!(poll_fd.as_fd().as_raw_fd(), 777); + + let b = unsafe { OwnedFd::from_raw_fd(888) }; + poll_fd.set_fd(&b); + assert_eq!(poll_fd.as_fd().as_raw_fd(), 888); + + // Don't attempt to close our made-up file descriptors. + let _ = a.into_raw_fd(); + let _ = b.into_raw_fd(); +} diff --git a/vendor/rustix/tests/io/procfs.rs b/vendor/rustix/tests/io/procfs.rs new file mode 100644 index 000000000..4c4256bd7 --- /dev/null +++ b/vendor/rustix/tests/io/procfs.rs @@ -0,0 +1,8 @@ +use io_lifetimes::raw::AsRawFilelike; + +#[test] +fn test_proc_self() { + // Verify that this API works at all + let fd = rustix::io::proc_self_fd().unwrap(); + assert_ne!(fd.as_raw_filelike(), 0); +} diff --git a/vendor/rustix/tests/io/read_write.rs b/vendor/rustix/tests/io/read_write.rs new file mode 100644 index 000000000..65186bf21 --- /dev/null +++ b/vendor/rustix/tests/io/read_write.rs @@ -0,0 +1,118 @@ +#[cfg(feature = "fs")] +use std::io::{IoSlice, IoSliceMut}; + +#[cfg(feature = "fs")] +#[test] +fn test_readwrite_pv() { + use rustix::fs::{cwd, openat, Mode, OFlags}; + use rustix::io::{preadv, pwritev}; + + let tmp = tempfile::tempdir().unwrap(); + let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap(); + let foo = openat( + &dir, + "foo", + OFlags::RDWR | OFlags::CREATE | OFlags::TRUNC, + Mode::RUSR | Mode::WUSR, + ) + .unwrap(); + + // For most targets, just call `pwritev`. + #[cfg(not(any(target_os = "ios", target_os = "macos")))] + { + pwritev(&foo, &[IoSlice::new(b"hello")], 200).unwrap(); + } + // macOS only has pwritev in newer versions; allow it to fail with `ENOSYS`. + #[cfg(any(target_os = "ios", target_os = "macos"))] + { + match pwritev(&foo, &[IoSlice::new(b"hello")], 200) { + Ok(_) => (), + Err(rustix::io::Errno::NOSYS) => return, + Err(err) => Err(err).unwrap(), + } + } + pwritev(&foo, &[IoSlice::new(b"world")], 300).unwrap(); + let mut buf = [0_u8; 5]; + preadv(&foo, &mut [IoSliceMut::new(&mut buf)], 200).unwrap(); + assert_eq!(&buf, b"hello"); + preadv(&foo, &mut [IoSliceMut::new(&mut buf)], 300).unwrap(); + assert_eq!(&buf, b"world"); +} + +#[cfg(feature = "fs")] +#[test] +fn test_readwrite_p() { + use rustix::fs::{cwd, openat, Mode, OFlags}; + use rustix::io::{pread, pwrite}; + + let tmp = tempfile::tempdir().unwrap(); + let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap(); + let foo = openat( + &dir, + "foo", + OFlags::RDWR | OFlags::CREATE | OFlags::TRUNC, + Mode::RUSR | Mode::WUSR, + ) + .unwrap(); + + pwrite(&foo, b"hello", 200).unwrap(); + pwrite(&foo, b"world", 300).unwrap(); + let mut buf = [0_u8; 5]; + pread(&foo, &mut buf, 200).unwrap(); + assert_eq!(&buf, b"hello"); + pread(&foo, &mut buf, 300).unwrap(); + assert_eq!(&buf, b"world"); +} + +#[cfg(feature = "fs")] +#[test] +fn test_readwrite_v() { + use rustix::fs::{cwd, openat, seek, Mode, OFlags}; + use rustix::io::{readv, writev, SeekFrom}; + + let tmp = tempfile::tempdir().unwrap(); + let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap(); + let foo = openat( + &dir, + "foo", + OFlags::RDWR | OFlags::CREATE | OFlags::TRUNC, + Mode::RUSR | Mode::WUSR, + ) + .unwrap(); + + writev(&foo, &[IoSlice::new(b"hello")]).unwrap(); + writev(&foo, &[IoSlice::new(b"world")]).unwrap(); + seek(&foo, SeekFrom::Start(0)).unwrap(); + let mut buf = [0_u8; 5]; + readv(&foo, &mut [IoSliceMut::new(&mut buf)]).unwrap(); + assert_eq!(&buf, b"hello"); + readv(&foo, &mut [IoSliceMut::new(&mut buf)]).unwrap(); + assert_eq!(&buf, b"world"); +} + +#[cfg(feature = "fs")] +#[test] +fn test_readwrite() { + use rustix::fs::{cwd, openat, seek, Mode, OFlags}; + use rustix::io::{read, write}; + use std::io::SeekFrom; + + let tmp = tempfile::tempdir().unwrap(); + let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap(); + let foo = openat( + &dir, + "foo", + OFlags::RDWR | OFlags::CREATE | OFlags::TRUNC, + Mode::RUSR | Mode::WUSR, + ) + .unwrap(); + + write(&foo, b"hello").unwrap(); + write(&foo, b"world").unwrap(); + seek(&foo, SeekFrom::Start(0)).unwrap(); + let mut buf = [0_u8; 5]; + read(&foo, &mut buf).unwrap(); + assert_eq!(&buf, b"hello"); + read(&foo, &mut buf).unwrap(); + assert_eq!(&buf, b"world"); +} diff --git a/vendor/rustix/tests/io/seals.rs b/vendor/rustix/tests/io/seals.rs new file mode 100644 index 000000000..ff971fa75 --- /dev/null +++ b/vendor/rustix/tests/io/seals.rs @@ -0,0 +1,41 @@ +#[cfg(feature = "fs")] +#[test] +fn test_seals() { + use rustix::fd::FromFd; + use rustix::fs::{ + fcntl_add_seals, fcntl_get_seals, ftruncate, memfd_create, MemfdFlags, SealFlags, + }; + use std::fs::File; + use std::io::Write; + + let fd = match memfd_create("test", MemfdFlags::CLOEXEC | MemfdFlags::ALLOW_SEALING) { + Ok(fd) => fd, + Err(rustix::io::Errno::NOSYS) => return, + Err(err) => Err(err).unwrap(), + }; + let mut file = File::from_fd(fd.into()); + + let old = fcntl_get_seals(&file).unwrap(); + assert_eq!(old, SealFlags::empty()); + + writeln!(&mut file, "Hello!").unwrap(); + + fcntl_add_seals(&file, SealFlags::GROW).unwrap(); + + let now = fcntl_get_seals(&file).unwrap(); + assert_eq!(now, SealFlags::GROW); + + // We sealed growing, so this should fail. + writeln!(&mut file, "World?").unwrap_err(); + + // We can still shrink for now. + ftruncate(&mut file, 1).unwrap(); + + fcntl_add_seals(&file, SealFlags::SHRINK).unwrap(); + + let now = fcntl_get_seals(&file).unwrap(); + assert_eq!(now, SealFlags::GROW | SealFlags::SHRINK); + + // We sealed shrinking, so this should fail. + ftruncate(&mut file, 0).unwrap_err(); +} |