summaryrefslogtreecommitdiffstats
path: root/vendor/rustix/tests/io
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/rustix/tests/io')
-rw-r--r--vendor/rustix/tests/io/dup2_to_replace_stdio.rs18
-rw-r--r--vendor/rustix/tests/io/epoll.rs103
-rw-r--r--vendor/rustix/tests/io/error.rs14
-rw-r--r--vendor/rustix/tests/io/eventfd.rs24
-rw-r--r--vendor/rustix/tests/io/from_into.rs28
-rw-r--r--vendor/rustix/tests/io/ioctl.rs14
-rw-r--r--vendor/rustix/tests/io/main.rs31
-rw-r--r--vendor/rustix/tests/io/poll.rs63
-rw-r--r--vendor/rustix/tests/io/procfs.rs8
-rw-r--r--vendor/rustix/tests/io/read_write.rs118
-rw-r--r--vendor/rustix/tests/io/seals.rs41
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();
+}