/* Test s2png's encoding and decoding, with and without encryption, for * corrupting data. */ use std::{ convert::AsRef, env, ffi::OsStr, process::Command, { io::{Result, Write}, iter::IntoIterator, }, }; use { exitcode, file_diff::diff, rand::{distributions::Uniform, Rng}, regex::Regex, tempfile::NamedTempFile, }; #[derive(Debug, Eq, PartialEq)] struct Output { code: i32, stderr: String, stdout: String, } fn s2png(args: I) -> Result where I: IntoIterator, S: AsRef, { let s2png_cmd = env::var("S2PNG_COMMAND").unwrap(); let output = Command::new(s2png_cmd).args(args).output()?; Ok(Output { code: output.status.code().unwrap(), stderr: String::from_utf8(output.stderr).unwrap(), stdout: String::from_utf8(output.stdout).unwrap(), }) } #[test] #[ignore] fn help_message() { let re = Regex::new(r"Store any data").unwrap(); let output = s2png(&["-h"]).unwrap(); assert!(re.is_match(&output.stdout)); assert_eq!(output.code, exitcode::OK); } #[test] #[ignore] fn bad_usage() { let output = s2png(&["-Q"]).unwrap(); assert_eq!(output.code, exitcode::USAGE); } fn roundtrip(data: &[u8], encode_extra: I1, decode_extra: I2) where S1: AsRef, S2: AsRef, I1: IntoIterator, I2: IntoIterator, { let mut input_file = NamedTempFile::new().unwrap(); input_file.write_all(data).unwrap(); let png_file = NamedTempFile::new().unwrap(); let extracted_file = NamedTempFile::new().unwrap(); let input_fn = input_file.path().to_str().unwrap(); let png_fn = png_file.path().to_str().unwrap(); let extracted_fn = extracted_file.path().to_str().unwrap(); let mut encode_args = vec!["-o".to_string(), png_fn.to_string(), input_fn.to_string()]; for arg in encode_extra { encode_args.push(arg.as_ref().to_string()); } let out1 = s2png(&encode_args).unwrap(); eprintln!("{}", out1.stderr); assert_eq!(out1.code, exitcode::OK); let mut decode_args = vec![ "-o".to_string(), extracted_fn.to_string(), png_fn.to_string(), ]; for arg in decode_extra { decode_args.push(arg.as_ref().to_string()); } let out2 = s2png(&decode_args).unwrap(); eprintln!("{}", out2.stderr); assert_eq!(out2.code, exitcode::OK); assert!(diff(&input_fn, &extracted_fn)); } #[test] #[ignore] fn roundtrip_basic_0xff() { let empty: Vec = vec![]; roundtrip( &vec![0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], &empty, &empty, ); } #[test] #[ignore] fn roundtrip_square_0xff() { let empty: Vec = vec![]; roundtrip( &vec![0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], vec!["-s"], &empty, ); } #[test] #[ignore] fn roundtrip_hex_key_0xff() { // printf hex_key | md5sum | cut -c 1-32 let hex_key_extra = ["-p", "5f4dcc3b5aa765d61d8327deb882cf99"]; roundtrip( &vec![0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], &hex_key_extra, &hex_key_extra, ); } #[test] #[ignore] fn roundtrip_no_banner_0xff() { roundtrip( &vec![0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], vec!["-e", "-b", ""], vec!["-d"], ); } fn random_vec(len: usize) -> Vec { let range = Uniform::from(0..=255); rand::thread_rng().sample_iter(&range).take(len).collect() } #[test] #[ignore] fn roundtrip_basic_random() { let empty: Vec = vec![]; roundtrip(&random_vec(0xffff), &empty, &empty); } #[test] #[ignore] fn roundtrip_square_random() { let empty: Vec = vec![]; roundtrip(&random_vec(0xffff), vec!["-s"], &empty); } #[test] #[ignore] fn roundtrip_hex_key_random() { // printf hex_key | md5sum | cut -c 1-32 let hex_key_extra = ["-p", "5f4dcc3b5aa765d61d8327deb882cf99"]; roundtrip(&random_vec(0xffff), &hex_key_extra, &hex_key_extra); } #[test] #[ignore] fn roundtrip_no_banner_random() { roundtrip(&random_vec(0xffff), vec!["-e", "-b", ""], vec!["-d"]); } #[test] #[ignore] fn empty_file() { roundtrip(&random_vec(0), vec!["-e"], vec!["-d"]) } #[test] #[ignore] fn empty_file_no_banner() { let empty_file = NamedTempFile::new().unwrap(); let input_fn = empty_file.path().to_str().unwrap(); let output_file = NamedTempFile::new().unwrap(); let output_fn = output_file.path().to_str().unwrap(); let out1 = s2png(&vec!["-o", &output_fn, "-b", "", &input_fn]).unwrap(); eprintln!("{}", out1.stderr); assert_eq!(out1.code, exitcode::DATAERR); } #[test] #[ignore] fn small_file_corruption_1_15() { for i in 1..=15 { roundtrip(&random_vec(i), vec!["-e", "-b", "", "-w", "10"], vec!["-d"]) } } #[test] #[ignore] fn small_file_corruption_16_255() { for i in 16..=255 { roundtrip(&random_vec(i), vec!["-e", "-b", "", "-w", "10"], vec!["-d"]) } }