uds/src/lib_tests.rs
121 lines
use std::io::ErrorKind;use pretty_assertions::assert_eq;use tokio::io::AsyncReadExt;use tokio::io::AsyncWriteExt;use super::*;#[tokio::test]async fn prepare_private_socket_directory_creates_directory() { let temp_dir = tempfile::TempDir::new().expect("temp dir"); let socket_dir = temp_dir.path().join("app-server-control"); prepare_private_socket_directory(&socket_dir) .await .expect("socket dir should be created"); assert!(socket_dir.is_dir());}#[cfg(unix)]#[tokio::test]async fn prepare_private_socket_directory_sets_existing_permissions_to_owner_only() { use std::os::unix::fs::PermissionsExt; let temp_dir = tempfile::TempDir::new().expect("temp dir"); for mode in [0o755, 0o600] { let socket_dir = temp_dir.path().join(format!("app-server-control-{mode:o}")); std::fs::create_dir(&socket_dir).expect("socket dir should be created"); std::fs::set_permissions(&socket_dir, std::fs::Permissions::from_mode(mode)) .expect("socket dir permissions should be changed"); prepare_private_socket_directory(&socket_dir) .await .expect("socket dir permissions should be set exactly"); let mode = std::fs::metadata(&socket_dir) .expect("socket dir metadata") .permissions() .mode(); assert_eq!(mode & 0o777, 0o700); }}#[cfg(unix)]#[tokio::test]async fn regular_file_path_is_not_stale_socket_path() { let temp_dir = tempfile::TempDir::new().expect("temp dir"); let regular_file = temp_dir.path().join("not-a-socket"); std::fs::write(®ular_file, b"not a socket").expect("regular file should be created"); assert!( !is_stale_socket_path(®ular_file) .await .expect("stale socket check should succeed") );}#[tokio::test]async fn bound_listener_path_is_stale_socket_path() { let temp_dir = tempfile::TempDir::new().expect("temp dir"); let socket_path = temp_dir.path().join("socket"); let _listener = match UnixListener::bind(&socket_path).await { Ok(listener) => listener, Err(err) if err.kind() == ErrorKind::PermissionDenied => { eprintln!("skipping test: failed to bind unix socket: {err}"); return; } Err(err) => panic!("failed to bind test socket: {err}"), }; assert!( is_stale_socket_path(&socket_path) .await .expect("stale socket check should succeed") );}#[tokio::test]async fn stream_round_trips_data_between_listener_and_client() { let temp_dir = tempfile::TempDir::new().expect("temp dir"); let socket_path = temp_dir.path().join("socket"); let mut listener = match UnixListener::bind(&socket_path).await { Ok(listener) => listener, Err(err) if err.kind() == ErrorKind::PermissionDenied => { eprintln!("skipping test: failed to bind unix socket: {err}"); return; } Err(err) => panic!("failed to bind test socket: {err}"), }; let server_task = tokio::spawn(async move { let mut server_stream = listener.accept().await.expect("connection should accept"); let mut request = [0; 7]; server_stream .read_exact(&mut request) .await .expect("server should read request"); assert_eq!(&request, b"request"); server_stream .write_all(b"response") .await .expect("server should write response"); }); let mut client_stream = UnixStream::connect(&socket_path) .await .expect("client should connect"); client_stream .write_all(b"request") .await .expect("client should write request"); let mut response = [0; 8]; client_stream .read_exact(&mut response) .await .expect("client should read response"); assert_eq!(&response, b"response"); server_task.await.expect("server task should join");}