Files
envr/zig-vendor/age-ffi/src/tests.rs
2026-04-28 17:49:04 -04:00

337 lines
9.7 KiB
Rust

//! Tests for the age-ffi library.
use crate::*;
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
#[test]
fn test_keygen() {
let mut keypair = AgeKeypair::null();
let result = age_generate_x25519(&mut keypair);
assert_eq!(result, AgeResult::Success);
assert!(!keypair.public_key.is_null());
assert!(!keypair.private_key.is_null());
unsafe {
let public = CStr::from_ptr(keypair.public_key).to_str().unwrap();
let private = CStr::from_ptr(keypair.private_key).to_str().unwrap();
assert!(public.starts_with("age1"));
assert!(private.starts_with("AGE-SECRET-KEY-1"));
}
age_free_keypair(&mut keypair);
}
#[test]
fn test_encrypt_decrypt() {
let mut keypair = AgeKeypair::null();
age_generate_x25519(&mut keypair);
let plaintext = b"Hello, world!";
let mut encrypted = AgeBuffer::null();
let result = age_encrypt(
plaintext.as_ptr(),
plaintext.len(),
keypair.public_key,
&mut encrypted,
);
assert_eq!(result, AgeResult::Success);
assert!(!encrypted.data.is_null());
assert!(encrypted.len > 0);
let mut decrypted = AgeBuffer::null();
let result = age_decrypt(
encrypted.data,
encrypted.len,
keypair.private_key,
&mut decrypted,
);
assert_eq!(result, AgeResult::Success);
let decrypted_slice = unsafe { std::slice::from_raw_parts(decrypted.data, decrypted.len) };
assert_eq!(decrypted_slice, plaintext);
age_free_buffer(&mut encrypted);
age_free_buffer(&mut decrypted);
age_free_keypair(&mut keypair);
}
#[test]
fn test_passphrase_encrypt_decrypt() {
let plaintext = b"Secret message";
let passphrase = CString::new("my-secret-passphrase").unwrap();
let mut encrypted = AgeBuffer::null();
let result = age_encrypt_passphrase(
plaintext.as_ptr(),
plaintext.len(),
passphrase.as_ptr(),
false,
&mut encrypted,
);
assert_eq!(result, AgeResult::Success);
let mut decrypted = AgeBuffer::null();
let result = age_decrypt_passphrase(
encrypted.data,
encrypted.len,
passphrase.as_ptr(),
&mut decrypted,
);
assert_eq!(result, AgeResult::Success);
let decrypted_slice = unsafe { std::slice::from_raw_parts(decrypted.data, decrypted.len) };
assert_eq!(decrypted_slice, plaintext);
age_free_buffer(&mut encrypted);
age_free_buffer(&mut decrypted);
}
#[test]
fn test_validation() {
let invalid = CString::new("not-a-key").unwrap();
assert!(!age_is_valid_x25519_recipient(invalid.as_ptr()));
let mut keypair = AgeKeypair::null();
age_generate_x25519(&mut keypair);
assert!(age_is_valid_x25519_recipient(keypair.public_key));
assert!(age_is_valid_x25519_identity(keypair.private_key));
assert_eq!(age_recipient_type(keypair.public_key), 1);
age_free_keypair(&mut keypair);
}
#[test]
fn test_armor_encrypt_decrypt() {
let mut keypair = AgeKeypair::null();
age_generate_x25519(&mut keypair);
let plaintext = b"Armored message";
let mut armored: *mut c_char = std::ptr::null_mut();
let result = age_encrypt_armor(
plaintext.as_ptr(),
plaintext.len(),
keypair.public_key,
&mut armored,
);
assert_eq!(result, AgeResult::Success);
assert!(!armored.is_null());
let armored_str = unsafe { CStr::from_ptr(armored).to_str().unwrap() };
assert!(armored_str.contains("-----BEGIN AGE ENCRYPTED FILE-----"));
let mut dearmored = AgeBuffer::null();
let result = age_dearmor(armored, &mut dearmored);
assert_eq!(result, AgeResult::Success);
let mut decrypted = AgeBuffer::null();
let result = age_decrypt(
dearmored.data,
dearmored.len,
keypair.private_key,
&mut decrypted,
);
assert_eq!(result, AgeResult::Success);
let decrypted_slice = unsafe { std::slice::from_raw_parts(decrypted.data, decrypted.len) };
assert_eq!(decrypted_slice, plaintext);
age_free_string(armored);
age_free_buffer(&mut dearmored);
age_free_buffer(&mut decrypted);
age_free_keypair(&mut keypair);
}
#[test]
fn test_derive_public_key() {
let mut keypair = AgeKeypair::null();
age_generate_x25519(&mut keypair);
let mut derived_public: *mut c_char = std::ptr::null_mut();
let result = age_x25519_to_public(keypair.private_key, &mut derived_public);
assert_eq!(result, AgeResult::Success);
let original = unsafe { CStr::from_ptr(keypair.public_key).to_str().unwrap() };
let derived = unsafe { CStr::from_ptr(derived_public).to_str().unwrap() };
assert_eq!(original, derived);
age_free_string(derived_public);
age_free_keypair(&mut keypair);
}
#[test]
fn test_multi_recipient_encrypt() {
let mut keypair1 = AgeKeypair::null();
let mut keypair2 = AgeKeypair::null();
age_generate_x25519(&mut keypair1);
age_generate_x25519(&mut keypair2);
let plaintext = b"Message for multiple recipients";
let recipients: [*const c_char; 2] = [
keypair1.public_key as *const c_char,
keypair2.public_key as *const c_char,
];
let mut encrypted = AgeBuffer::null();
let result = age_encrypt_multi(
plaintext.as_ptr(),
plaintext.len(),
recipients.as_ptr(),
recipients.len(),
false,
&mut encrypted,
);
assert_eq!(result, AgeResult::Success);
// Decrypt with first key
let mut decrypted1 = AgeBuffer::null();
let result = age_decrypt(
encrypted.data,
encrypted.len,
keypair1.private_key,
&mut decrypted1,
);
assert_eq!(result, AgeResult::Success);
let slice1 = unsafe { std::slice::from_raw_parts(decrypted1.data, decrypted1.len) };
assert_eq!(slice1, plaintext);
// Decrypt with second key
let mut decrypted2 = AgeBuffer::null();
let result = age_decrypt(
encrypted.data,
encrypted.len,
keypair2.private_key,
&mut decrypted2,
);
assert_eq!(result, AgeResult::Success);
let slice2 = unsafe { std::slice::from_raw_parts(decrypted2.data, decrypted2.len) };
assert_eq!(slice2, plaintext);
age_free_buffer(&mut encrypted);
age_free_buffer(&mut decrypted1);
age_free_buffer(&mut decrypted2);
age_free_keypair(&mut keypair1);
age_free_keypair(&mut keypair2);
}
#[test]
fn test_version_functions() {
let version = age_version();
assert!(!version.is_null());
let version_str = unsafe { CStr::from_ptr(version).to_str().unwrap() };
assert!(!version_str.is_empty());
let lib_version = age_lib_version();
assert!(!lib_version.is_null());
let lib_version_str = unsafe { CStr::from_ptr(lib_version).to_str().unwrap() };
assert!(lib_version_str.starts_with("0.11"));
}
#[test]
fn test_passphrase_with_armor() {
let plaintext = b"Armored passphrase message";
let passphrase = CString::new("test-passphrase-123").unwrap();
let mut encrypted = AgeBuffer::null();
let result = age_encrypt_passphrase(
plaintext.as_ptr(),
plaintext.len(),
passphrase.as_ptr(),
true, // armor = true
&mut encrypted,
);
assert_eq!(result, AgeResult::Success);
// Verify it's armored
let encrypted_slice = unsafe { std::slice::from_raw_parts(encrypted.data, encrypted.len) };
let encrypted_str = std::str::from_utf8(encrypted_slice).unwrap();
assert!(encrypted_str.contains("-----BEGIN AGE ENCRYPTED FILE-----"));
// Dearmor first, then decrypt
let armored_cstr = CString::new(encrypted_str).unwrap();
let mut dearmored = AgeBuffer::null();
let result = age_dearmor(armored_cstr.as_ptr(), &mut dearmored);
assert_eq!(result, AgeResult::Success);
let mut decrypted = AgeBuffer::null();
let result = age_decrypt_passphrase(
dearmored.data,
dearmored.len,
passphrase.as_ptr(),
&mut decrypted,
);
assert_eq!(result, AgeResult::Success);
let decrypted_slice = unsafe { std::slice::from_raw_parts(decrypted.data, decrypted.len) };
assert_eq!(decrypted_slice, plaintext);
age_free_buffer(&mut encrypted);
age_free_buffer(&mut dearmored);
age_free_buffer(&mut decrypted);
}
#[test]
fn test_empty_plaintext() {
let mut keypair = AgeKeypair::null();
age_generate_x25519(&mut keypair);
let plaintext = b"";
let mut encrypted = AgeBuffer::null();
let result = age_encrypt(
plaintext.as_ptr(),
plaintext.len(),
keypair.public_key,
&mut encrypted,
);
assert_eq!(result, AgeResult::Success);
let mut decrypted = AgeBuffer::null();
let result = age_decrypt(
encrypted.data,
encrypted.len,
keypair.private_key,
&mut decrypted,
);
assert_eq!(result, AgeResult::Success);
assert_eq!(decrypted.len, 0);
age_free_buffer(&mut encrypted);
age_free_buffer(&mut decrypted);
age_free_keypair(&mut keypair);
}
#[test]
fn test_large_plaintext() {
let mut keypair = AgeKeypair::null();
age_generate_x25519(&mut keypair);
// 1MB of data
let plaintext: Vec<u8> = (0..1024 * 1024).map(|i| (i % 256) as u8).collect();
let mut encrypted = AgeBuffer::null();
let result = age_encrypt(
plaintext.as_ptr(),
plaintext.len(),
keypair.public_key,
&mut encrypted,
);
assert_eq!(result, AgeResult::Success);
let mut decrypted = AgeBuffer::null();
let result = age_decrypt(
encrypted.data,
encrypted.len,
keypair.private_key,
&mut decrypted,
);
assert_eq!(result, AgeResult::Success);
let decrypted_slice = unsafe { std::slice::from_raw_parts(decrypted.data, decrypted.len) };
assert_eq!(decrypted_slice, plaintext.as_slice());
age_free_buffer(&mut encrypted);
age_free_buffer(&mut decrypted);
age_free_keypair(&mut keypair);
}