Add basic integration tests

Also add force option--necessary for testing but may be useful to some people
who like to live dangerously
This commit is contained in:
Joshua Holmer 2016-01-11 14:16:05 -05:00
parent 442b5ed947
commit ee31774078
4 changed files with 164 additions and 10 deletions

View file

@ -28,6 +28,7 @@ pub struct Options {
pub recursive: bool,
pub clobber: bool,
pub create: bool,
pub force: bool,
pub preserve_attrs: bool,
pub verbosity: Option<u8>,
pub filter: HashSet<u8>,
@ -129,7 +130,7 @@ pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), String> {
// TODO: Perform stripping
let output_data = png.output();
if file_original_size <= output_data.len() {
if file_original_size <= output_data.len() && !opts.force {
println!("File already optimized");
return Ok(());
}
@ -174,13 +175,26 @@ pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), String> {
}
}
}
println!(" IDAT size = {} bytes ({} bytes decrease)",
png.idat_data.len(),
idat_original_size - png.idat_data.len());
println!(" file size = {} bytes ({} bytes = {:.2}% decrease)",
output_data.len(),
file_original_size - output_data.len(),
(file_original_size - output_data.len()) as f64 / file_original_size as f64);
if idat_original_size >= png.idat_data.len() {
println!(" IDAT size = {} bytes ({} bytes decrease)",
png.idat_data.len(),
idat_original_size - png.idat_data.len());
} else {
println!(" IDAT size = {} bytes ({} bytes increate)",
png.idat_data.len(),
png.idat_data.len() - idat_original_size);
}
if file_original_size >= output_data.len() {
println!(" file size = {} bytes ({} bytes = {:.2}% decrease)",
output_data.len(),
file_original_size - output_data.len(),
(file_original_size - output_data.len()) as f64 / file_original_size as f64);
} else {
println!(" file size = {} bytes ({} bytes = {:.2}% increase)",
output_data.len(),
output_data.len() - file_original_size,
(output_data.len() - file_original_size) as f64 / file_original_size as f64);
}
Ok(())
}

View file

@ -30,6 +30,7 @@ fn main() {
fix_errors: false,
clobber: true,
create: true,
force: false,
preserve_attrs: false,
verbosity: Some(0),
filter: filter,
@ -70,6 +71,10 @@ fn main() {
.help("Back up modified files")
.short("b")
.long("backup"))
.arg(Arg::with_name("force")
.help("Write output even if larger than the original")
.short("F")
.long("force"))
.arg(Arg::with_name("recursive")
.help("Recurse into subdirectories")
.short("r")
@ -409,6 +414,10 @@ fn parse_opts_into_struct(matches: &ArgMatches, opts: &mut oxipng::Options) -> R
opts.backup = true;
}
if matches.is_present("force") {
opts.force = true;
}
if matches.is_present("recursive") {
opts.recursive = true;
}

View file

@ -8,7 +8,7 @@ use std::io::prelude::*;
use std::iter::Iterator;
use std::path::Path;
#[derive(Debug)]
#[derive(Debug,PartialEq)]
pub enum ColorType {
Grayscale,
RGB,
@ -43,7 +43,7 @@ impl ColorType {
}
}
#[derive(Debug)]
#[derive(Debug,PartialEq)]
pub enum BitDepth {
One,
Two,

131
tests/oxipng.rs Normal file
View file

@ -0,0 +1,131 @@
extern crate oxipng;
use oxipng::png;
use std::collections::HashSet;
use std::fs::remove_file;
use std::path::Path;
use std::path::PathBuf;
fn get_opts(input: &Path) -> oxipng::Options {
let mut filter = HashSet::new();
filter.insert(0);
filter.insert(5);
let mut compression = HashSet::new();
compression.insert(9);
let mut memory = HashSet::new();
memory.insert(9);
let mut strategies = HashSet::new();
for i in 0..4 {
strategies.insert(i);
}
oxipng::Options {
backup: false,
out_file: input.with_extension("out.png").to_owned(),
out_dir: None,
stdout: false,
pretend: false,
recursive: false,
fix_errors: false,
force: true,
clobber: true,
create: true,
preserve_attrs: false,
verbosity: Some(0),
filter: filter,
interlace: None,
compression: compression,
memory: memory,
strategies: strategies,
window: 15,
bit_depth_reduction: true,
color_type_reduction: true,
palette_reduction: true,
idat_recoding: true,
strip: false,
}
}
#[test]
fn reduce_rgba_png() {
let input = PathBuf::from("tests/files/test_rgba.png");
let opts = get_opts(&input);
let output = opts.out_file.clone();
match oxipng::optimize(&input, &opts) {
Ok(_) => (),
Err(x) => panic!(x.to_owned())
};
assert!(output.exists());
let png = match png::PngData::new(&output) {
Ok(x) => {
remove_file(output).ok();
x
},
Err(x) => {
remove_file(output).ok();
panic!(x.to_owned())
},
};
assert!(png.ihdr_data.color_type == png::ColorType::Indexed);
assert!(png.ihdr_data.bit_depth == png::BitDepth::Eight);
assert!(png.palette.unwrap().len() == 43 * 3);
}
#[test]
fn reduce_rgb_png() {
let input = PathBuf::from("tests/files/test_rgb.png");
let opts = get_opts(&input);
let output = opts.out_file.clone();
match oxipng::optimize(&input, &opts) {
Ok(_) => (),
Err(x) => panic!(x.to_owned())
};
assert!(output.exists());
let png = match png::PngData::new(&output) {
Ok(x) => {
remove_file(output).ok();
x
},
Err(x) => {
remove_file(output).ok();
panic!(x.to_owned())
},
};
assert!(png.ihdr_data.color_type == png::ColorType::Indexed);
assert!(png.ihdr_data.bit_depth == png::BitDepth::Eight);
assert!(png.palette.unwrap().len() == 43 * 3);
}
#[test]
fn reduce_palette_png() {
let input = PathBuf::from("tests/files/test_palette.png");
let opts = get_opts(&input);
let output = opts.out_file.clone();
match oxipng::optimize(&input, &opts) {
Ok(_) => (),
Err(x) => panic!(x.to_owned())
};
assert!(output.exists());
let png = match png::PngData::new(&output) {
Ok(x) => {
remove_file(output).ok();
x
},
Err(x) => {
remove_file(output).ok();
panic!(x.to_owned())
},
};
assert!(png.ihdr_data.color_type == png::ColorType::Indexed);
assert!(png.ihdr_data.bit_depth == png::BitDepth::Eight);
assert!(png.palette.unwrap().len() == 43 * 3);
}