use std::collections::BTreeMap;
use std::ffi::OsString;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::time::{SystemTime, UNIX_EPOCH};
use nostr_vpn_core::config::AppConfig;
#[test]
fn status_commands_do_not_migrate_legacy_config_or_create_sidecars() {
let dir = TestDir::new();
let config_path = dir.path().join("legacy.toml");
let config = AppConfig::generated();
fs::write(
&config_path,
config.plaintext_toml().expect("encode legacy config"),
)
.expect("write legacy config");
assert!(
AppConfig::config_file_needs_secret_migration(&config_path).expect("inspect legacy config")
);
let before = directory_snapshot(dir.path());
let config_arg = config_path.to_str().expect("utf8 config path");
for args in [
vec![
"status",
"--config",
config_arg,
"--discover-secs",
"0",
"--json",
],
vec!["paid-exit", "status", "--config", config_arg, "--json"],
] {
let output = Command::new(env!("CARGO_BIN_EXE_nvpn"))
.args(&args)
.output()
.expect("run nvpn status command");
assert!(
output.status.success(),
"nvpn {args:?} failed\nstdout:\n{}\nstderr:\n{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
assert_eq!(directory_snapshot(dir.path()), before, "nvpn {args:?}");
}
}
fn directory_snapshot(path: &Path) -> BTreeMap<OsString, Vec<u8>> {
fs::read_dir(path)
.expect("read test directory")
.map(|entry| {
let entry = entry.expect("read directory entry");
let name = entry.file_name();
let contents = fs::read(entry.path()).expect("read directory entry contents");
(name, contents)
})
.collect()
}
struct TestDir {
path: PathBuf,
}
impl TestDir {
fn new() -> Self {
let nonce = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("clock is after epoch")
.as_nanos();
let path = std::env::temp_dir().join(format!(
"nvpn-status-readonly-{}-{nonce}",
std::process::id()
));
fs::create_dir_all(&path).expect("create test directory");
Self { path }
}
fn path(&self) -> &Path {
&self.path
}
}
impl Drop for TestDir {
fn drop(&mut self) {
let _ = fs::remove_dir_all(&self.path);
}
}