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:
parent
442b5ed947
commit
ee31774078
4 changed files with 164 additions and 10 deletions
30
src/lib.rs
30
src/lib.rs
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
131
tests/oxipng.rs
Normal 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);
|
||||
}
|
||||
Loading…
Reference in a new issue