#![deny(clippy::all)]
#![allow(clippy::items_after_test_module)]
#[macro_use]
extern crate parameterized;
use std::io::Read;
use std::path::{Path, PathBuf};
use sic_core::image;
use sic::cli::app::{build_app_config, create_app as get_app}; use sic::cli::config::InputOutputMode;
use sic::cli::pipeline::run_with_devices;
fn setup_input_path(test_image_path: &str) -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR"))
.join("resources")
.join(test_image_path)
}
fn setup_output_path(test_output_path: &str) -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR"))
.join("target")
.join(test_output_path)
}
fn path_buf_str(pb: &Path) -> &str {
pb.to_str().unwrap()
}
fn clean_up_output_path(test_output_path: &str) {
std::fs::remove_file(setup_output_path(test_output_path))
.expect("Unable to remove file after test.");
}
fn is_image_format(output_path: &str, hope: image::ImageFormat) -> bool {
let mut file = std::fs::File::open(setup_output_path(output_path))
.expect("Failed to find (produced) test image.");
let mut bytes = vec![];
file.read_to_end(&mut bytes)
.expect("Failed to read (produced) test image.");
hope == image::guess_format(&bytes).expect("Format could not be guessed.")
}
#[cfg(test)]
mod convert_to_x {
use super::*;
ide!();
#[parameterized(ext = {
"bmp",
"farbfeld",
"gif",
"jpg",
"jpeg",
"ico",
"png",
"pbm",
"pgm",
"ppm",
"pam",
"qoi",
"tif",
"tiff",
"webp",
}, expected_format = {
image::ImageFormat::Bmp,
image::ImageFormat::Farbfeld,
image::ImageFormat::Gif,
image::ImageFormat::Jpeg,
image::ImageFormat::Jpeg,
image::ImageFormat::Ico,
image::ImageFormat::Png,
image::ImageFormat::Pnm,
image::ImageFormat::Pnm,
image::ImageFormat::Pnm,
image::ImageFormat::Pnm,
image::ImageFormat::Qoi,
image::ImageFormat::Tiff,
image::ImageFormat::Tiff,
image::ImageFormat::WebP,
})]
fn convert_to_x_by_extension(ext: &str, expected_format: image::ImageFormat) {
let input_path = setup_input_path("palette_4x4.png");
let output_path = setup_output_path(&["cli_convert_to_x_by_extension", ext].join("."));
let args = vec![
"sic",
"--input",
input_path.to_str().unwrap(),
"--output",
path_buf_str(&output_path),
];
let matches = get_app("", "", "").get_matches_from(args);
let complete = run_with_devices(
InputOutputMode::try_from_matches(&matches).unwrap(),
&build_app_config(&matches).unwrap(),
);
complete.unwrap();
assert!(output_path.exists());
assert!(is_image_format(path_buf_str(&output_path), expected_format));
clean_up_output_path(path_buf_str(&output_path));
}
}
#[cfg(test)]
mod convert_to_x_by_ff {
use super::*;
ide!();
fn args<'a>(which: &'a str, input: &'a Path, output: &'a Path) -> Vec<&'a str> {
vec![
"sic",
"--output-format",
which,
"--input",
path_buf_str(input),
"--output",
path_buf_str(output),
]
}
#[parameterized(which = {
"bmp",
"farbfeld",
"gif",
"jpg",
"jpeg",
"ico",
"png",
"pbm",
"pgm",
"ppm",
"pam",
"qoi",
"tif",
"tiff",
"webp",
}, expected_format = {
image::ImageFormat::Bmp,
image::ImageFormat::Farbfeld,
image::ImageFormat::Gif,
image::ImageFormat::Jpeg,
image::ImageFormat::Jpeg,
image::ImageFormat::Ico,
image::ImageFormat::Png,
image::ImageFormat::Pnm,
image::ImageFormat::Pnm,
image::ImageFormat::Pnm,
image::ImageFormat::Pnm,
image::ImageFormat::Qoi,
image::ImageFormat::Tiff,
image::ImageFormat::Tiff,
image::ImageFormat::WebP,
})]
fn convert_to_bmp_by_ff(which: &str, expected_format: image::ImageFormat) {
let input_path = setup_input_path("palette_4x4.png");
let output_path = setup_output_path(&format!("cli_convert_to_x_by_extension_ff_{}", which));
let args = args(which, &input_path, &output_path);
let matches = get_app("", "", "").get_matches_from(args);
let complete = run_with_devices(
InputOutputMode::try_from_matches(&matches).unwrap(),
&build_app_config(&matches).unwrap(),
);
complete.unwrap();
assert!(output_path.exists());
assert!(is_image_format(path_buf_str(&output_path), expected_format));
clean_up_output_path(path_buf_str(&output_path));
}
}
fn read_file_to_bytes<P: AsRef<Path>>(path: P) -> Vec<u8> {
let mut f = std::fs::File::open(path).unwrap();
let mut buffer = Vec::new();
f.read_to_end(&mut buffer).unwrap();
buffer
}
#[cfg(test)]
mod pnm_ascii_and_binary {
use super::*;
ide!();
fn guess_is_ascii_encoded(input: &[u8]) -> bool {
let is_ascii_p = |c: u8| c == 0x50;
let is_ascii_magic_number = |c| c == 0x31 || c == 0x32 || c == 0x33;
let mut iter = input.iter();
let first = iter.next().unwrap();
let second = iter.next().unwrap();
is_ascii_p(*first) && is_ascii_magic_number(*second) && iter.all(|c| *c <= 0x7F)
}
fn pnm_encode_test_case(which: &str, is_ascii: bool) {
let input_path = setup_input_path("palette_4x4.png");
let ascii_str = |bool: bool| if bool { "ascii" } else { "binary" };
let output_path = setup_output_path(&format!(
"cli_convert_pnm_encoding_test_{}_{}",
which,
ascii_str(is_ascii)
));
let mut args = Vec::with_capacity(8);
args.push("sic");
if is_ascii {
args.push("--pnm-encoding-ascii");
}
args.push("--output-format");
args.push(which);
args.push("--input");
args.push(path_buf_str(&input_path));
args.push("--output");
args.push(path_buf_str(&output_path));
let matches = get_app("", "", "").get_matches_from(args);
let complete = run_with_devices(
InputOutputMode::try_from_matches(&matches).unwrap(),
&build_app_config(&matches).unwrap(),
);
complete.unwrap();
assert!(output_path.exists());
let contents = read_file_to_bytes(path_buf_str(&output_path));
if is_ascii {
assert!(guess_is_ascii_encoded(&contents));
} else {
assert!(!guess_is_ascii_encoded(&contents));
}
clean_up_output_path(path_buf_str(&output_path));
}
#[parameterized(which = {
"pbm",
"pgm",
"ppm",
})]
fn pnm_encode_ascii(which: &str) {
pnm_encode_test_case(which, true)
}
#[parameterized(which = {
"pbm",
"pgm",
"ppm",
})]
fn pnm_encode_binary(which: &str) {
pnm_encode_test_case(which, false)
}
}
#[test]
fn convert_jpeg_quality_different() {
let which = "jpeg";
let our_input = setup_input_path("palette_4x4.png");
let out1 = setup_output_path("out_02_jpeg_1.jpeg");
let out2 = setup_output_path("out_02_jpeg_2.jpeg");
let args1 = vec![
"sic",
"--output-format",
which,
"--input",
path_buf_str(&our_input),
"--output",
path_buf_str(&out1),
];
let args2 = vec![
"sic",
"--jpeg-encoding-quality",
"81",
"--output-format",
which,
"--input",
path_buf_str(&our_input),
"--output",
path_buf_str(&out2),
];
let matches1 = get_app("", "", "").get_matches_from(args1);
run_with_devices(
InputOutputMode::try_from_matches(&matches1).unwrap(),
&build_app_config(&matches1).unwrap(),
)
.unwrap();
let matches2 = get_app("", "", "").get_matches_from(args2);
run_with_devices(
InputOutputMode::try_from_matches(&matches2).unwrap(),
&build_app_config(&matches2).unwrap(),
)
.unwrap();
assert!(out1.exists() && out2.exists());
let contents1 = read_file_to_bytes(path_buf_str(&out1));
let contents2 = read_file_to_bytes(path_buf_str(&out2));
assert_ne!(contents1, contents2);
clean_up_output_path(path_buf_str(&out1));
clean_up_output_path(path_buf_str(&out2));
}