// TODO change filename to something better(?) extern crate assert_cmd; extern crate failure; use failure::Error; #[macro_use] extern crate lazy_static; #[macro_use] extern crate quickcheck; use quickcheck::TestResult; extern crate size; extern crate rand; use rand::Rng; use std::io::prelude::*; use std::path::PathBuf; use std::process::Command; use std::process::*; use std::thread; lazy_static! { static ref BIN_PATH: PathBuf = assert_cmd::cargo::main_binary_path().unwrap(); } fn spawn_process(args: &[&str], input: &[u8]) -> Result { let mut proc = Command::new(&*BIN_PATH) .args(args) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn()?; // ↓ magical way of getting stdi/o to work and to get output { let mut stdin = proc.stdin.take().unwrap(); let input = input.to_owned(); thread::spawn(move || { stdin.write_all(&input).unwrap(); }); } Ok(proc.wait_with_output()?) } /// Panics if decrypting fails or output doesn't match expectations. fn verify_decrypt(passwd: &str, input: &[u8], output: &[u8]) { let plain = spawn_process(&["-d", passwd], input).unwrap(); assert!(plain.status.success()); assert_eq!(plain.stdout, output); assert!(plain.stderr.is_empty()); assert!(input != &plain.stdout[..]); } /// Returns `Output` of encryption run. fn encrypt_decrypt(passwd: &str, data: &[u8]) -> Output { let output = spawn_process(&[passwd], data).unwrap(); assert!(output.status.success()); assert!(!output.stdout.is_empty()); assert!(output.stderr.is_empty()); // decrypting encrypted data also works verify_decrypt(passwd, &output.stdout, data); output } quickcheck! { fn encrypt_decrypt_random(passwd: String, data: Vec) -> TestResult { if passwd.contains("\0") || data.is_empty() { return TestResult::discard() } let ciphertext1 = encrypt_decrypt(&passwd, &data); let ciphertext2 = encrypt_decrypt(&passwd, &data); assert!(ciphertext1.stdout != ciphertext2.stdout); TestResult::passed() } } #[test] fn encrypt_decrypt_random_large() { let passwd = "password"; // for some reason it fails to finish with some bigger sizes let mut v = vec![0; size::MiB as usize * 64]; rand::thread_rng().fill(&mut v[..]); encrypt_decrypt(passwd, &v); } #[test] fn decrypt_old() { // TODO add more inputs? let ciphertext = include_bytes!("encrypted_asdf\\n_pass.epc"); let plain = b"asdf\n"; let passwd = "pass"; verify_decrypt(passwd, ciphertext, plain); let no_line_wrap: Vec = ciphertext.iter() .map(|b| *b) .filter(|b| *b != b'\n' || *b != b'\r') .collect(); verify_decrypt(passwd, &no_line_wrap, plain); }