This commit is contained in:
2026-05-14 23:57:58 -05:00
parent b6124537f9
commit 04d9f22d41
6 changed files with 190 additions and 1 deletions
+182
View File
@@ -104,3 +104,185 @@ pub fn validate_ssh_key(key: &Option<PathBuf>) -> Result<(), DrawerError> {
.map_err(|_| DrawerError::KeyNotValidSsh)?; .map_err(|_| DrawerError::KeyNotValidSsh)?;
Ok(()) Ok(())
} }
#[cfg(test)]
mod tests {
use super::*;
const TEST_KEY: &[u8] = include_bytes!("../tests/fixtures/test.key");
const TEST_DRAWER: &[u8] = include_bytes!("../tests/fixtures/test.drawer");
fn temp_path(suffix: &str) -> PathBuf {
let nanos = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.subsec_nanos();
std::env::temp_dir().join(format!("drawer_test_{nanos}{suffix}"))
}
fn write_fixture(data: &[u8], suffix: &str) -> PathBuf {
let p = temp_path(suffix);
std::fs::write(&p, data).unwrap();
p
}
fn make_test_archive() -> Vec<u8> {
use flate2::{write::GzEncoder, Compression};
let mut buf = Vec::new();
let gz = GzEncoder::new(&mut buf, Compression::default());
let mut ar = tar::Builder::new(gz);
let data = b"hello archive";
let mut header = tar::Header::new_gnu();
header.set_size(data.len() as u64);
header.set_mode(0o644);
header.set_cksum();
ar.append_data(&mut header, "hello.txt", data.as_ref()).unwrap();
ar.into_inner().unwrap().finish().unwrap();
buf
}
// --- parent_or_dot ---
#[test]
fn parent_or_dot_with_parent() {
assert_eq!(parent_or_dot(Path::new("foo/bar")), Path::new("foo"));
}
#[test]
fn parent_or_dot_no_directory_component() {
assert_eq!(parent_or_dot(Path::new("foo")), Path::new("."));
}
#[test]
fn parent_or_dot_empty_path() {
assert_eq!(parent_or_dot(Path::new("")), Path::new("."));
}
// --- default_target ---
#[test]
fn default_target_single_file() {
let result = default_target(Path::new("unused.drawer"), Some(Path::new("archive/file.txt")));
assert_eq!(result, PathBuf::from("file.txt"));
}
#[test]
fn default_target_directory_stem() {
let result = default_target(Path::new("myproject.drawer"), None);
assert_eq!(result, PathBuf::from("myproject"));
}
#[test]
fn default_target_directory_stem_nested_drawer() {
let result = default_target(Path::new("a/b/myproject.drawer"), None);
assert_eq!(result, PathBuf::from("myproject"));
}
// --- validate_drawer_extension ---
#[test]
fn validate_extension_valid() {
assert!(validate_drawer_extension(Path::new("foo.drawer")).is_ok());
}
#[test]
fn validate_extension_wrong() {
assert!(validate_drawer_extension(Path::new("foo.tar")).is_err());
}
#[test]
fn validate_extension_missing() {
assert!(validate_drawer_extension(Path::new("foo")).is_err());
}
// --- key_path ---
#[test]
fn key_path_explicit() {
let result = key_path(&Some(PathBuf::from("/some/key")));
assert_eq!(result.unwrap(), PathBuf::from("/some/key"));
}
#[test]
fn key_path_none_no_env_var() {
// Remove the env var for this check; if it happens to be set in the
// test environment this test would be misleading, so we clear it first.
unsafe { std::env::remove_var("DRAWER_KEY") };
assert!(key_path(&None).is_err());
}
// --- validate_drawer_file_exists ---
#[test]
fn validate_file_exists_present() {
assert!(validate_drawer_file_exists(Path::new("Cargo.toml")).is_ok());
}
#[test]
fn validate_file_exists_missing() {
assert!(validate_drawer_file_exists(
Path::new("/tmp/drawer_definitely_missing_xyz123.drawer")
).is_err());
}
// --- archive_reader_for ---
#[test]
fn archive_reader_for_reads_entry() {
let data = make_test_archive();
let mut archive = archive_reader_for(&data);
let entries: Vec<_> = archive.entries().unwrap()
.filter_map(|e| e.ok())
.collect();
assert_eq!(entries.len(), 1);
assert_eq!(entries[0].path().unwrap().as_ref(), Path::new("hello.txt"));
}
// --- validate_ssh_key ---
#[test]
fn validate_ssh_key_valid() {
let key = write_fixture(TEST_KEY, ".key");
assert!(validate_ssh_key(&Some(key)).is_ok());
}
#[test]
fn validate_ssh_key_garbage() {
let key = write_fixture(b"not a real key", ".key");
assert!(validate_ssh_key(&Some(key)).is_err());
}
#[test]
fn validate_ssh_key_no_path() {
unsafe { std::env::remove_var("DRAWER_KEY") };
assert!(validate_ssh_key(&None).is_err());
}
// --- identity ---
#[test]
fn identity_loads_valid_key() {
let key = write_fixture(TEST_KEY, ".key");
let result = identity(&Some(key.clone()), Path::new("dummy.drawer"));
let (returned_path, _id) = result.unwrap();
assert_eq!(returned_path, key);
}
// --- encrypt / decrypt ---
#[test]
fn encrypt_decrypt_round_trip() {
let key = write_fixture(TEST_KEY, ".key");
let plaintext = b"round trip test";
let ciphertext = encrypt(plaintext, &Some(key.clone()), Path::new("dummy.drawer")).unwrap();
let decrypted = decrypt(ciphertext, &Some(key), Path::new("dummy.drawer")).unwrap();
assert_eq!(decrypted, plaintext);
}
#[test]
fn decrypt_test_drawer_fixture() {
let key = write_fixture(TEST_KEY, ".key");
let result = decrypt(TEST_DRAWER.to_vec(), &Some(key), Path::new("test.drawer"));
assert!(result.is_ok());
}
}
+1 -1
View File
@@ -2,7 +2,7 @@
set -euo pipefail set -euo pipefail
DRAWER=./target/debug/drawer DRAWER=./target/debug/drawer
TEST_DIR="$(cd "$(dirname "$0")/test" && pwd)" TEST_DIR="$(cd "$(dirname "$0")/tests/testcontents" && pwd)"
WORK="$TMPDIR/drawer_test_$$" WORK="$TMPDIR/drawer_test_$$"
mkdir -p "$WORK" mkdir -p "$WORK"
BIN
View File
Binary file not shown.
+7
View File
@@ -0,0 +1,7 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACDX3jE2g37mBoQTky3PYwlrgyJQ2rfBZQoEVXNDhMRl3AAAAIjd219V3dtf
VQAAAAtzc2gtZWQyNTUxOQAAACDX3jE2g37mBoQTky3PYwlrgyJQ2rfBZQoEVXNDhMRl3A
AAAEB8nkWm+dRgovs/PoFmnFPWinK757HlccvMUgXk3UMtl9feMTaDfuYGhBOTLc9jCWuD
IlDat8FlCgRVc0OExGXcAAAAAAECAwQF
-----END OPENSSH PRIVATE KEY-----