use excelreader::workbook::Workbook;
use excelreader::writer::{encrypt_package, write_columns, Column, ColumnData};
use excelreader::{Error, OpenOptions, XL_FORMAT_AUTO, XL_FORMAT_XLSX};
use std::path::PathBuf;
use std::sync::atomic::{AtomicU32, Ordering};
fn fixture(name: &str) -> String {
std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
.join("../../tests/ExcelReader.Tests/data/encrypted")
.join(name)
.to_str()
.expect("fixture path must be UTF-8")
.to_string()
}
static COUNTER: AtomicU32 = AtomicU32::new(0);
fn temp_path(name: &str) -> PathBuf {
let mut path = std::env::temp_dir();
path.push(format!(
"excelreader-rs-{}-{}-{name}",
std::process::id(),
COUNTER.fetch_add(1, Ordering::Relaxed)
));
path
}
#[test]
fn opens_encrypted_workbook_with_password() {
let options = OpenOptions::new().password("hunter2");
let book = Workbook::open_with(
&fixture("agile-aes256-sha512.xlsx"),
XL_FORMAT_AUTO,
Some(&options),
)
.unwrap();
assert!(book.sheet_count().unwrap() > 0);
}
#[test]
fn encrypt_package_produces_a_file_openable_with_the_same_password() {
let inteiros = [1i64, 2];
let columns = [Column {
name: Some("inteiro"),
data: ColumnData::I64(&inteiros),
validity: None,
}];
let plain_path = temp_path("encrypt-plain.xlsx");
let encrypted_path = temp_path("encrypt-cipher.xlsx");
let plain_target = plain_path.to_str().expect("temp path must be UTF-8");
let encrypted_target = encrypted_path.to_str().expect("temp path must be UTF-8");
write_columns(plain_target, XL_FORMAT_XLSX, &columns, None)
.expect("write_columns must succeed");
encrypt_package(plain_target, encrypted_target, "hunter2").expect("encrypt_package must succeed");
let options = OpenOptions::new().password("hunter2");
let book = Workbook::open_with(encrypted_target, XL_FORMAT_AUTO, Some(&options))
.expect("the encrypted file must open with the right password");
assert!(book.sheet_count().unwrap() > 0);
let err = Workbook::open_with(encrypted_target, XL_FORMAT_AUTO, None).unwrap_err();
assert!(matches!(err, Error::PasswordRequired { .. }), "got {err:?}");
let _ = std::fs::remove_file(&plain_path);
let _ = std::fs::remove_file(&encrypted_path);
}
#[test]
fn encrypt_package_rejects_an_empty_password() {
let inteiros = [1i64];
let columns = [Column {
name: Some("inteiro"),
data: ColumnData::I64(&inteiros),
validity: None,
}];
let plain_path = temp_path("encrypt-empty-pw.xlsx");
let plain_target = plain_path.to_str().expect("temp path must be UTF-8");
write_columns(plain_target, XL_FORMAT_XLSX, &columns, None)
.expect("write_columns must succeed");
let destination = temp_path("encrypt-empty-pw-out.xlsx");
let err = encrypt_package(plain_target, destination.to_str().unwrap(), "").unwrap_err();
assert_eq!(err.code(), excelreader::XL_INVALID_ARGUMENT, "got {err:?}");
let _ = std::fs::remove_file(&plain_path);
}
#[test]
fn reports_password_required_without_password() {
let err = Workbook::open_with(&fixture("agile-aes256-sha512.xlsx"), XL_FORMAT_AUTO, None)
.unwrap_err();
assert!(matches!(err, Error::PasswordRequired { .. }), "got {err:?}");
}
#[test]
fn reports_password_incorrect_with_wrong_password() {
let options = OpenOptions::new().password("wrong");
let err = Workbook::open_with(
&fixture("agile-aes256-sha512.xlsx"),
XL_FORMAT_AUTO,
Some(&options),
)
.unwrap_err();
assert!(
matches!(err, Error::PasswordIncorrect { .. }),
"got {err:?}"
);
}
#[test]
fn password_survives_a_temporary_source() {
let options = OpenOptions::new().password(String::from("hunter2"));
let book = Workbook::open_with(
&fixture("agile-aes256-sha512.xlsx"),
XL_FORMAT_AUTO,
Some(&options),
)
.unwrap();
assert!(book.sheet_count().unwrap() > 0);
}