Files
wgcloak/tests/control.rs
T

101 lines
3.3 KiB
Rust

use wgcloak::control;
use std::os::unix::fs::PermissionsExt;
use tempfile::tempdir;
#[tokio::test]
async fn control_commands_and_socket_permissions() {
let dir = tempdir().unwrap();
let runtime_dir = dir.path().join("runtime");
let path = runtime_dir.join("control.sock");
let state = control::ControlState::default();
state.enable_reconnect();
state.set_status("ready").await;
state.set_stats_json("{\"packets\":3}").await;
let server = control::ControlServer::bind(&path, state.clone())
.await
.unwrap();
assert_eq!(
std::fs::metadata(&runtime_dir)
.unwrap()
.permissions()
.mode()
& 0o777,
0o700
);
assert_eq!(
std::fs::metadata(&path).unwrap().permissions().mode() & 0o777,
0o600
);
let task = tokio::spawn(server.run());
let second_bind = control::ControlServer::bind(&path, control::ControlState::default()).await;
assert!(matches!(
second_bind,
Err(error) if error.kind() == std::io::ErrorKind::AddrInUse
));
assert!(control::send_command(&path, "status")
.await
.unwrap()
.contains("ready"));
assert!(control::send_command(&path, "stats")
.await
.unwrap()
.contains("packets"));
assert!(control::send_command(&path, "reconnect")
.await
.unwrap()
.contains("true"));
let reload = control::send_command(&path, "reload").await.unwrap();
assert!(reload.contains("\"ok\":false"));
assert!(reload.contains("not supported"));
assert!(control::send_command(&path, "shutdown")
.await
.unwrap()
.contains("true"));
task.await.unwrap().unwrap();
}
#[tokio::test]
async fn replaces_only_a_verified_stale_socket() {
let dir = tempdir().unwrap();
let private_dir = dir.path().join("runtime");
std::fs::create_dir(&private_dir).unwrap();
std::fs::set_permissions(&private_dir, std::fs::Permissions::from_mode(0o700)).unwrap();
let path = private_dir.join("stale.sock");
let stale = std::os::unix::net::UnixListener::bind(&path).unwrap();
drop(stale);
let server = control::ControlServer::bind(&path, control::ControlState::default())
.await
.expect("verified stale socket should be replaced");
assert_eq!(
std::fs::metadata(&path).unwrap().permissions().mode() & 0o777,
0o600
);
drop(server);
assert!(!path.exists());
}
#[tokio::test]
async fn refuses_to_replace_a_non_socket_path() {
let dir = tempdir().unwrap();
let private_dir = dir.path().join("runtime");
std::fs::create_dir(&private_dir).unwrap();
std::fs::set_permissions(&private_dir, std::fs::Permissions::from_mode(0o700)).unwrap();
let path = private_dir.join("control.sock");
std::fs::write(&path, b"keep this file").unwrap();
let result = control::ControlServer::bind(&path, control::ControlState::default()).await;
assert!(matches!(
result,
Err(error) if error.kind() == std::io::ErrorKind::AlreadyExists
));
assert_eq!(std::fs::read(&path).unwrap(), b"keep this file");
}
#[test]
fn default_socket_path_never_targets_the_shared_tmp_socket() {
let path = control::default_socket_path();
assert_eq!(path.file_name().unwrap(), "wgcloak.sock");
assert_ne!(path.parent().unwrap(), std::path::Path::new("/tmp"));
}