Raw-rs: run tests in parallel (#1968)

* Run raw-rs tests in parallel

* cargo fmt

* Fix clippy warnings

* Use Fast CompressionType to speed up the tests

* Fix benches

* Use cfg_attr instead of cfg.

---------

Co-authored-by: hypercube <0hypercube@gmail.com>
Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Elbert Ronnie
2024-09-20 16:39:58 +05:30
committed by GitHub
parent e352c7fa71
commit d68f91ccca
4 changed files with 67 additions and 38 deletions

View File

@@ -13,7 +13,7 @@ repository = "https://github.com/GraphiteEditor/Graphite/tree/master/libraries/r
documentation = "https://docs.rs/raw-rs"
[features]
raw-rs-tests = ["dep:image", "dep:libraw-rs", "dep:reqwest"]
raw-rs-tests = ["dep:image", "dep:libraw-rs", "dep:reqwest", "dep:rayon"]
[dependencies]
# Local dependencies
@@ -33,3 +33,4 @@ reqwest = { workspace = true, optional = true }
# Optional dependencies (should be dev dependencies, but Cargo currently doesn't allow optional dev dependencies)
libraw-rs = { version = "0.0.4", optional = true }
rayon = { version = "1.10.0", optional = true }

View File

@@ -6,11 +6,13 @@ use raw_rs::RawImage;
use image::codecs::png::{CompressionType, FilterType, PngEncoder};
use image::{ColorType, ImageEncoder};
use libraw::Processor;
use rayon::prelude::*;
use std::collections::HashMap;
use std::fmt::Write;
use std::fs::{create_dir, metadata, read_dir, File};
use std::io::{BufWriter, Cursor, Read};
use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::Duration;
const TEST_FILES: [&str; 3] = ["ILCE-7M3-ARW2.3.5-blossoms.arw", "ILCE-7RM4-ARW2.3.5-kestrel.arw", "ILCE-6000-ARW2.3.1-windsock.arw"];
@@ -21,52 +23,74 @@ const BASE_PATH: &str = "./tests/images/";
fn test_images_match_with_libraw() {
download_images();
let mut failed_tests = 0;
read_dir(BASE_PATH)
let paths: Vec<_> = read_dir(BASE_PATH)
.unwrap()
.map(|dir_entry| dir_entry.unwrap().path())
.filter(|path| path.is_file() && path.file_name().map(|file_name| file_name != ".gitkeep").unwrap_or(false))
.for_each(|path| {
let mut f = File::open(&path).unwrap();
let mut content = vec![];
f.read_to_end(&mut content).unwrap();
.collect();
print!("{} => ", path.display());
let failed_tests = if std::env::var("RAW_RS_TEST_RUN_SEQUENTIALLY").is_ok() {
let mut failed_tests = 0;
let raw_image = match test_raw_data(&content) {
Err(err_msg) => {
failed_tests += 1;
return println!("{}", err_msg);
}
Ok(raw_image) => raw_image,
};
// TODO: The code below is kept commented because raw data to final image processing is
// incomplete. Remove this once it is done.
// if let Err(err_msg) = test_final_image(&content, raw_image) {
// failed_tests += 1;
// return println!("{}", err_msg);
// };
println!("Passed");
// TODO: Remove this later
let mut image = raw_rs::process_8bit(raw_image);
store_image(&path, "raw_rs", &mut image.data, image.width, image.height);
let processor = Processor::new();
let libraw_image = processor.process_8bit(&content).unwrap();
let mut data = Vec::from_iter(libraw_image.iter().copied());
store_image(&path, "libraw_rs", &mut data[..], libraw_image.width() as usize, libraw_image.height() as usize);
paths.iter().for_each(|path| {
if !test_image(path) {
failed_tests += 1;
}
});
failed_tests
} else {
let failed_tests = AtomicUsize::new(0);
paths.par_iter().for_each(|path| {
if !test_image(path) {
failed_tests.fetch_add(1, Ordering::SeqCst);
}
});
failed_tests.load(Ordering::SeqCst)
};
if failed_tests != 0 {
panic!("{} images have failed the tests", failed_tests);
}
}
fn test_image(path: &Path) -> bool {
let mut f = File::open(path).unwrap();
let mut content = vec![];
f.read_to_end(&mut content).unwrap();
let raw_image = match test_raw_data(&content) {
Err(err_msg) => {
println!("{} => {}", path.display(), err_msg);
return false;
}
Ok(raw_image) => raw_image,
};
// TODO: The code below is kept commented because raw data to final image processing is
// incomplete. Remove this once it is done.
// if let Err(err_msg) = test_final_image(&content, raw_image) {
// failed_tests += 1;
// return println!("{}", err_msg);
// };
println!("{} => Passed", path.display());
// TODO: Remove this later
let mut image = raw_rs::process_8bit(raw_image);
store_image(path, "raw_rs", &mut image.data, image.width, image.height);
let processor = Processor::new();
let libraw_image = processor.process_8bit(&content).unwrap();
let mut data = Vec::from_iter(libraw_image.iter().copied());
store_image(path, "libraw_rs", &mut data[..], libraw_image.width() as usize, libraw_image.height() as usize);
true
}
fn store_image(path: &Path, suffix: &str, data: &mut [u8], width: usize, height: usize) {
let mut output_path = PathBuf::new();
if let Some(parent) = path.parent() {
@@ -85,7 +109,7 @@ fn store_image(path: &Path, suffix: &str, data: &mut [u8], width: usize, height:
output_path.set_extension("png");
let file = BufWriter::new(File::create(output_path).unwrap());
let png_encoder = PngEncoder::new_with_quality(file, CompressionType::Best, FilterType::Adaptive);
let png_encoder = PngEncoder::new_with_quality(file, CompressionType::Fast, FilterType::Adaptive);
png_encoder.write_image(data, width as u32, height as u32, ColorType::Rgb8.into()).unwrap();
}