Added tests

This commit is contained in:
ManOfGoldForever 2026-03-02 10:50:01 -05:00
parent 62caefcd22
commit 8c8bee36e2
2 changed files with 106 additions and 3 deletions

View file

@ -41,9 +41,6 @@ pub struct AddPass {
pub struct GetPass { pub struct GetPass {
/// The name of the password to get /// The name of the password to get
pub name: String, pub name: String,
/// Copy the password to the clipboard instead of printing it
#[arg(short, long)]
pub copy: bool,
} }
#[derive(Args)] #[derive(Args)]
@ -51,3 +48,38 @@ pub struct DeletePass {
/// The name of the password to delete /// The name of the password to delete
pub name: String, pub name: String,
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parses_add_command() {
let cli = Cli::try_parse_from(["pm", "add", "github"]).expect("parse add");
match cli.command {
Some(Commands::Add(add)) => assert_eq!(add.name, "github"),
_ => panic!("expected add command"),
}
}
#[test]
fn parses_get_command() {
let cli = Cli::try_parse_from(["pm", "get", "email"]).expect("parse get");
match cli.command {
Some(Commands::Get(get)) => assert_eq!(get.name, "email"),
_ => panic!("expected get command"),
}
}
#[test]
fn rejects_removed_copy_flag() {
let cli = Cli::try_parse_from(["pm", "get", "email", "--copy"]);
assert!(cli.is_err());
}
#[test]
fn parses_list_command() {
let cli = Cli::try_parse_from(["pm", "list"]).expect("parse list");
assert!(matches!(cli.command, Some(Commands::List)));
}
}

View file

@ -118,3 +118,74 @@ pub fn verify_master_password(password: &str, recorded_hash: &str) -> bool {
.verify_password(password.as_bytes(), &parsed_hash) .verify_password(password.as_bytes(), &parsed_hash)
.is_ok() .is_ok()
} }
#[cfg(test)]
mod tests {
use super::*;
use std::time::{SystemTime, UNIX_EPOCH};
fn temp_file_path(prefix: &str) -> String {
let nanos = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("time went backwards")
.as_nanos();
std::env::temp_dir()
.join(format!("pm_test_{}_{}_{}", prefix, std::process::id(), nanos))
.to_string_lossy()
.to_string()
}
#[test]
fn key_derivation_is_deterministic_for_same_input() {
let mut p1 = String::from("master-password");
let mut p2 = String::from("master-password");
let salt = "abc123fixedsalt";
let k1 = derive_key(&mut p1, salt);
let k2 = derive_key(&mut p2, salt);
assert_eq!(k1, k2);
}
#[test]
fn hash_and_verify_master_password_work() {
let password = "correct-horse-battery-staple";
let hash = hash_master_password(password);
assert!(verify_master_password(password, &hash));
assert!(!verify_master_password("wrong-password", &hash));
}
#[test]
fn save_load_and_delete_roundtrip() {
let path = temp_file_path("vault");
let key = [7u8; 32];
let mut data = HashMap::new();
data.insert("email".to_string(), "pw1".to_string());
data.insert("bank".to_string(), "pw2".to_string());
save_passwords(&path, &data, &key);
let loaded = load_passwords(&path, &key);
assert_eq!(loaded, data);
delete_password(&path, "email", &key);
let after_delete = load_passwords(&path, &key);
assert!(!after_delete.contains_key("email"));
assert_eq!(after_delete.get("bank"), Some(&"pw2".to_string()));
let _ = std::fs::remove_file(path);
}
#[test]
fn get_or_create_salt_reuses_existing_value() {
let path = temp_file_path("salt");
let first = get_or_create_salt(&path);
let second = get_or_create_salt(&path);
assert_eq!(first, second);
assert_eq!(first.len(), 32);
let _ = std::fs::remove_file(path);
}
}