tests: Generalize Sq::encrypt and Sq::decrypt to work with files.

- `Sq::encrypt` and `Sq::decrypt` only work with in-memory buffers.

  - Introduce `FileOrBytes`, which represents a path or bytes.  Change
    `Sq::encrypt` and `Sq::decrypt` to use them, and thus support
    messages stored in files in addition to inline messages.
This commit is contained in:
Neal H. Walfield 2024-10-31 12:23:29 +01:00
parent e4c40da649
commit fae8f689a2
No known key found for this signature in database
GPG Key ID: 6863C9AD5B4D22D3
2 changed files with 93 additions and 8 deletions

View File

@ -155,6 +155,73 @@ impl FileOrKeyHandle {
}
}
/// Designates data by path, or bytes (which are fed to stdin).
#[derive(Clone, Debug)]
pub enum FileOrBytes {
FileOrStdin(PathBuf),
Bytes(Vec<u8>),
}
impl From<&[u8]> for FileOrBytes {
fn from(s: &[u8]) -> Self {
FileOrBytes::Bytes(s.to_vec())
}
}
impl From<Vec<u8>> for FileOrBytes {
fn from(s: Vec<u8>) -> Self {
FileOrBytes::Bytes(s)
}
}
impl From<&Vec<u8>> for FileOrBytes {
fn from(s: &Vec<u8>) -> Self {
FileOrBytes::Bytes(s.clone())
}
}
impl From<&Path> for FileOrBytes {
fn from(path: &Path) -> Self {
path.to_path_buf().into()
}
}
impl From<&PathBuf> for FileOrBytes {
fn from(path: &PathBuf) -> Self {
path.clone().into()
}
}
impl From<PathBuf> for FileOrBytes {
fn from(path: PathBuf) -> Self {
FileOrBytes::FileOrStdin(path.into())
}
}
impl From<&FileOrBytes> for FileOrBytes {
fn from(h: &FileOrBytes) -> Self {
h.clone()
}
}
impl FileOrBytes {
/// Returns whether this contains a `FileOrStdin`.
pub fn is_file(&self) -> bool {
match self {
FileOrBytes::FileOrStdin(_) => true,
FileOrBytes::Bytes(_) => false,
}
}
/// Returns whether this contains bytes.
pub fn is_bytes(&self) -> bool {
match self {
FileOrBytes::FileOrStdin(_) => false,
FileOrBytes::Bytes(_) => true,
}
}
}
pub struct Sq {
base: TempDir,
// Whether to preserve the directory on exit. Normally we clean
@ -486,21 +553,30 @@ impl Sq {
/// Decrypts a message.
pub fn decrypt<M>(&self, args: &[&str], msg: M) -> Vec<u8>
where M: AsRef<[u8]>,
where M: Into<FileOrBytes>,
{
self.decrypt_maybe(args, msg).expect("can decrypt")
}
/// Decrypts a message.
pub fn decrypt_maybe<M>(&self, args: &[&str], msg: M) -> Result<Vec<u8>>
where M: AsRef<[u8]>,
where M: Into<FileOrBytes>,
{
let mut cmd = self.command();
cmd.args([ "decrypt" ]);
for arg in args {
cmd.arg(arg);
}
cmd.write_stdin(msg.as_ref());
match msg.into() {
FileOrBytes::FileOrStdin(path) => {
cmd.arg(path);
}
FileOrBytes::Bytes(bytes) => {
cmd.write_stdin(bytes);
}
}
let output = self.run(cmd, None);
if output.status.success() {
@ -513,7 +589,7 @@ impl Sq {
/// Encrypts a message.
pub fn encrypt<A, M>(&self, args: &[A], msg: M) -> Vec<u8>
where A: AsRef<str>,
M: AsRef<[u8]>,
M: Into<FileOrBytes>,
{
self.encrypt_maybe(args, msg).expect("can encrypt")
}
@ -521,14 +597,23 @@ impl Sq {
/// Encrypts a message.
pub fn encrypt_maybe<A, M>(&self, args: &[A], msg: M) -> Result<Vec<u8>>
where A: AsRef<str>,
M: AsRef<[u8]>,
M: Into<FileOrBytes>,
{
let mut cmd = self.command();
cmd.args([ "encrypt" ]);
for arg in args {
cmd.arg(arg.as_ref());
}
cmd.write_stdin(msg.as_ref());
match msg.into() {
FileOrBytes::FileOrStdin(path) => {
cmd.arg(path);
}
FileOrBytes::Bytes(bytes) => {
cmd.write_stdin(bytes);
}
}
let output = self.run(cmd, None);
if output.status.success() {

View File

@ -49,7 +49,7 @@ fn try_encrypt(sq: &Sq, extra_args: &[&str],
let message = format!("{:?}", args);
let result = sq.encrypt_maybe(&args, &message);
let result = sq.encrypt_maybe(&args, message.as_bytes());
match result {
Err(err) => {
@ -142,7 +142,7 @@ fn sq_encrypt_using_cert_store() -> Result<()>
KeyHandle::from(cert.keyid())]
{
assert!(
sq.encrypt_maybe(&["--for", &kh.to_string()], b"")
sq.encrypt_maybe(&["--for", &kh.to_string()], &b""[..])
.is_err());
}