use assert2::assert;
use std::io::{IoSlice, IoSliceMut, Seek, Write, Read};
use std::os::fd::AsFd;
use tempfile::tempfile;
use tokio_seqpacket::UnixSeqpacket;
use tokio_seqpacket::ancillary::{AncillaryMessageReader, AncillaryMessageWriter, OwnedAncillaryMessage};
pub async fn receive_file_descriptor(ancillary_buf: &mut [u8]) -> AncillaryMessageReader<'_> {
let socket_b = {
assert!(let Ok(mut file_a) = tempfile());
assert!(let Ok(_) = file_a.write_all(b"Wie dit leest is gek."));
assert!(let Ok(()) = file_a.rewind());
assert!(let Ok(mut file_b) = tempfile());
assert!(let Ok(_) = file_b.write_all(b"Wie dit leest is gek."));
assert!(let Ok(()) = file_b.rewind());
assert!(let Ok((socket_a, socket_b)) = UnixSeqpacket::pair());
let mut cmsg = [0; 64];
let mut cmsg = AncillaryMessageWriter::new(&mut cmsg);
assert!(let Ok(()) = cmsg.add_fds(&[file_a.as_fd(), file_b.as_fd()]));
assert!(let Ok(29) = socket_a.send_vectored_with_ancillary(&[IoSlice::new(b"Here, have a file descriptor.")], &mut cmsg).await);
socket_b
};
let mut read_buf = [0u8; 64];
assert!(let Ok((29, cmsg)) = socket_b.recv_vectored_with_ancillary(&mut [IoSliceMut::new(&mut read_buf)], ancillary_buf).await);
assert!(&read_buf[..29] == b"Here, have a file descriptor.");
cmsg
}
#[tokio::test]
async fn can_take_ownership_of_received_fds() {
let mut ancillary_buffer = [0; 64];
let ancillary = receive_file_descriptor(&mut ancillary_buffer).await;
let mut messages = ancillary.into_messages();
assert!(let Some(OwnedAncillaryMessage::FileDescriptors(fds)) = messages.next());
assert!(let None = messages.next());
assert!(fds.len() == 2);
let mut fds: Vec<_> = fds.collect();
assert!(fds.len() == 2);
let mut file_b = std::fs::File::from(fds.remove(1));
let mut file_a = std::fs::File::from(fds.remove(0));
let mut contents = Vec::new();
assert!(let Ok(_) = file_a.read_to_end(&mut contents));
assert!(contents == b"Wie dit leest is gek.");
let mut contents = Vec::new();
assert!(let Ok(_) = file_b.read_to_end(&mut contents));
assert!(contents == b"Wie dit leest is gek.");
}