// Copyright 2022 The ChromiumOS Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. use std::io::ErrorKind; use std::time::Duration; use base::AsRawDescriptor; use base::UnixSeqpacket; use base::UnixSeqpacketListener; use base::UnlinkUnixSeqpacketListener; use tempfile::tempdir; #[test] fn unix_seqpacket_path_not_exists() { let res = UnixSeqpacket::connect("/path/not/exists"); assert!(res.is_err()); } #[test] fn unix_seqpacket_listener_path() { let temp_dir = tempdir().expect("failed to create tempdir"); let socket_path = temp_dir.path().join("unix_seqpacket_listener_path"); let listener = UnlinkUnixSeqpacketListener( UnixSeqpacketListener::bind(&socket_path).expect("failed to create UnixSeqpacketListener"), ); let listener_path = listener.path().expect("failed to get socket listener path"); assert_eq!(socket_path, listener_path); } #[test] fn unix_seqpacket_listener_from_fd() { let temp_dir = tempdir().expect("failed to create tempdir"); let socket_path = temp_dir.path().join("unix_seqpacket_listener_from_fd"); let listener = UnlinkUnixSeqpacketListener( UnixSeqpacketListener::bind(&socket_path).expect("failed to create UnixSeqpacketListener"), ); // UnixSeqpacketListener should succeed on a valid listening descriptor. // SAFETY: Safe because `listener` is valid and the return value is checked. let good_dup = UnixSeqpacketListener::bind(format!("/proc/self/fd/{}", unsafe { libc::dup(listener.as_raw_descriptor()) })); let good_dup_path = good_dup .expect("failed to create dup UnixSeqpacketListener") .path(); // Path of socket created by descriptor should be hidden. assert!(good_dup_path.is_err()); // UnixSeqpacketListener must fail on an existing non-listener socket. let s1 = UnixSeqpacket::connect(socket_path.as_path()).expect("UnixSeqpacket::connect failed"); // SAFETY: Safe because `s1` is valid and the return value is checked. let bad_dup = UnixSeqpacketListener::bind(format!("/proc/self/fd/{}", unsafe { libc::dup(s1.as_raw_descriptor()) })); assert!(bad_dup.is_err()); } #[test] fn unix_seqpacket_path_exists_pass() { let temp_dir = tempdir().expect("failed to create tempdir"); let socket_path = temp_dir.path().join("path_to_socket"); let _listener = UnlinkUnixSeqpacketListener( UnixSeqpacketListener::bind(&socket_path).expect("failed to create UnixSeqpacketListener"), ); let _res = UnixSeqpacket::connect(socket_path.as_path()).expect("UnixSeqpacket::connect failed"); } #[test] fn unix_seqpacket_path_listener_accept_with_timeout() { let temp_dir = tempdir().expect("failed to create tempdir"); let socket_path = temp_dir.path().join("path_listerner_accept_with_timeout"); let listener = UnlinkUnixSeqpacketListener( UnixSeqpacketListener::bind(&socket_path).expect("failed to create UnixSeqpacketListener"), ); for d in [Duration::from_millis(10), Duration::ZERO] { let _ = listener.accept_with_timeout(d).expect_err(&format!( "UnixSeqpacket::accept_with_timeout {:?} connected", d )); let s1 = UnixSeqpacket::connect(socket_path.as_path()) .unwrap_or_else(|_| panic!("UnixSeqpacket::connect {:?} failed", d)); let s2 = listener .accept_with_timeout(d) .unwrap_or_else(|_| panic!("UnixSeqpacket::accept {:?} failed", d)); let data1 = &[0, 1, 2, 3, 4]; let data2 = &[10, 11, 12, 13, 14]; s2.send(data2).expect("failed to send data2"); s1.send(data1).expect("failed to send data1"); let recv_data = &mut [0; 5]; s2.recv(recv_data).expect("failed to recv data"); assert_eq!(data1, recv_data); s1.recv(recv_data).expect("failed to recv data"); assert_eq!(data2, recv_data); } } #[test] fn unix_seqpacket_path_listener_accept() { let temp_dir = tempdir().expect("failed to create tempdir"); let socket_path = temp_dir.path().join("path_listerner_accept"); let listener = UnlinkUnixSeqpacketListener( UnixSeqpacketListener::bind(&socket_path).expect("failed to create UnixSeqpacketListener"), ); let s1 = UnixSeqpacket::connect(socket_path.as_path()).expect("UnixSeqpacket::connect failed"); let s2 = listener.accept().expect("UnixSeqpacket::accept failed"); let data1 = &[0, 1, 2, 3, 4]; let data2 = &[10, 11, 12, 13, 14]; s2.send(data2).expect("failed to send data2"); s1.send(data1).expect("failed to send data1"); let recv_data = &mut [0; 5]; s2.recv(recv_data).expect("failed to recv data"); assert_eq!(data1, recv_data); s1.recv(recv_data).expect("failed to recv data"); assert_eq!(data2, recv_data); } #[test] fn unix_seqpacket_zero_timeout() { let (s1, _s2) = UnixSeqpacket::pair().expect("failed to create socket pair"); // Timeouts less than a microsecond are too small and round to zero. s1.set_read_timeout(Some(Duration::from_nanos(10))) .expect_err("successfully set zero timeout"); } #[test] fn unix_seqpacket_read_timeout() { let (s1, _s2) = UnixSeqpacket::pair().expect("failed to create socket pair"); s1.set_read_timeout(Some(Duration::from_millis(1))) .expect("failed to set read timeout for socket"); let _ = s1.recv(&mut [0]); } #[test] fn unix_seqpacket_write_timeout() { let (s1, _s2) = UnixSeqpacket::pair().expect("failed to create socket pair"); s1.set_write_timeout(Some(Duration::from_millis(1))) .expect("failed to set write timeout for socket"); } #[test] fn unix_seqpacket_send_recv() { let (s1, s2) = UnixSeqpacket::pair().expect("failed to create socket pair"); let data1 = &[0, 1, 2, 3, 4]; let data2 = &[10, 11, 12, 13, 14]; s2.send(data2).expect("failed to send data2"); s1.send(data1).expect("failed to send data1"); let recv_data = &mut [0; 5]; s2.recv(recv_data).expect("failed to recv data"); assert_eq!(data1, recv_data); s1.recv(recv_data).expect("failed to recv data"); assert_eq!(data2, recv_data); } #[test] fn unix_seqpacket_send_fragments() { let (s1, s2) = UnixSeqpacket::pair().expect("failed to create socket pair"); let data1 = &[0, 1, 2, 3, 4]; let data2 = &[10, 11, 12, 13, 14, 15, 16]; s1.send(data1).expect("failed to send data1"); s1.send(data2).expect("failed to send data2"); let recv_data = &mut [0; 32]; let size = s2.recv(recv_data).expect("failed to recv data"); assert_eq!(size, data1.len()); assert_eq!(data1, &recv_data[0..size]); let size = s2.recv(recv_data).expect("failed to recv data"); assert_eq!(size, data2.len()); assert_eq!(data2, &recv_data[0..size]); } #[test] fn unix_seqpacket_get_readable_bytes() { let (s1, s2) = UnixSeqpacket::pair().expect("failed to create socket pair"); assert_eq!(s1.get_readable_bytes().unwrap(), 0); assert_eq!(s2.get_readable_bytes().unwrap(), 0); let data1 = &[0, 1, 2, 3, 4]; s1.send(data1).expect("failed to send data"); assert_eq!(s1.get_readable_bytes().unwrap(), 0); assert_eq!(s2.get_readable_bytes().unwrap(), data1.len()); let recv_data = &mut [0; 5]; s2.recv(recv_data).expect("failed to recv data"); assert_eq!(s1.get_readable_bytes().unwrap(), 0); assert_eq!(s2.get_readable_bytes().unwrap(), 0); } #[test] fn unix_seqpacket_next_packet_size() { let (s1, s2) = UnixSeqpacket::pair().expect("failed to create socket pair"); let data1 = &[0, 1, 2, 3, 4]; s1.send(data1).expect("failed to send data"); assert_eq!(s2.next_packet_size().unwrap(), 5); s1.set_read_timeout(Some(Duration::from_micros(1))) .expect("failed to set read timeout"); assert_eq!( s1.next_packet_size().unwrap_err().kind(), ErrorKind::WouldBlock ); drop(s2); assert_eq!( s1.next_packet_size().unwrap_err().kind(), ErrorKind::ConnectionReset ); } #[test] fn unix_seqpacket_recv_to_vec() { let (s1, s2) = UnixSeqpacket::pair().expect("failed to create socket pair"); let data1 = &[0, 1, 2, 3, 4]; s1.send(data1).expect("failed to send data"); let recv_data = &mut vec![]; s2.recv_to_vec(recv_data).expect("failed to recv data"); assert_eq!(recv_data, &mut vec![0, 1, 2, 3, 4]); } #[test] fn unix_seqpacket_recv_as_vec() { let (s1, s2) = UnixSeqpacket::pair().expect("failed to create socket pair"); let data1 = &[0, 1, 2, 3, 4]; s1.send(data1).expect("failed to send data"); let recv_data = s2.recv_as_vec().expect("failed to recv data"); assert_eq!(recv_data, vec![0, 1, 2, 3, 4]); }