summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHubert Figuière <hub@figuiere.net>2023-08-19 23:01:17 -0400
committerHubert Figuière <hub@figuiere.net>2023-08-19 23:03:56 -0400
commitc21be9f3a7c03a681198cbb01a6be40d8fb631ac (patch)
tree0bfde69d1e719d69bd4d369117c4b9d7e063e3fd
parentb338eb81f6dcfc4ed82bda45eb3fa3e39cc6e09b (diff)
testsuite: extract testsuite infrastructure
-rw-r--r--Cargo.toml1
-rw-r--r--libopenraw-testing/Cargo.toml12
-rw-r--r--libopenraw-testing/src/lib.rs206
-rw-r--r--src/lib.rs44
-rw-r--r--tests/testsuite.rs443
5 files changed, 446 insertions, 260 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 4b0032c..ce035a3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -36,6 +36,7 @@ crc = "2.1.0"
serde = { version = "^1, <=1.0.171", features = [ "derive" ] }
serde-xml-rs = "^0.5.1"
criterion = { version = "0.5.1", features = ["html_reports"] }
+libopenraw-testing = { path = "libopenraw-testing" }
image = { version = "0.24.6", features = [ "png", "jpeg" ], default-features = false }
[features]
diff --git a/libopenraw-testing/Cargo.toml b/libopenraw-testing/Cargo.toml
new file mode 100644
index 0000000..d3f0476
--- /dev/null
+++ b/libopenraw-testing/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "libopenraw-testing"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+crc = "2.1.0"
+libopenraw = { path = ".." }
+serde = { version = "^1, <=1.0.171", features = [ "derive" ] }
+serde-xml-rs = "^0.5.1"
diff --git a/libopenraw-testing/src/lib.rs b/libopenraw-testing/src/lib.rs
new file mode 100644
index 0000000..c87a45b
--- /dev/null
+++ b/libopenraw-testing/src/lib.rs
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: LGPL-3.0-or-later
+/*
+ * libopenraw - libopenraw-testing.rs
+ *
+ * Copyright (C) 2022-2023 Hubert Figuière
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+use std::fmt::Display;
+use std::str::FromStr;
+
+use serde::{de::Error, Deserialize};
+
+use libopenraw::{metadata::Value, Bitmap, DataType, Ifd, RawFile, Rect};
+
+/// CRC checksum for the RAW data (8 bits only)
+pub fn raw_checksum(buf: &[u8]) -> u16 {
+ // This is the same algorithm as used in the C++ implementation
+ let crc = crc::Crc::<u16>::new(&crc::CRC_16_IBM_3740);
+ let mut digest = crc.digest();
+ digest.update(buf);
+
+ digest.finalize()
+}
+
+#[derive(Clone, Debug, Deserialize, PartialEq)]
+#[serde(rename_all = "camelCase")]
+pub struct Results {
+ pub raw_type: Option<String>,
+ pub raw_type_id: Option<u32>,
+ /// MakeNoteCount can be -1 for an error (expected)
+ pub maker_note_count: Option<i32>,
+ pub maker_note_id: Option<String>,
+ pub exif_make: Option<String>,
+ pub exif_model: Option<String>,
+ pub thumb_num: Option<u32>,
+ #[serde(deserialize_with = "from_list")]
+ #[serde(default)]
+ pub thumb_sizes: Option<Vec<u32>>,
+ pub thumb_formats: Option<String>, // XXX split array
+ #[serde(deserialize_with = "from_list")]
+ #[serde(default)]
+ pub thumb_data_sizes: Option<Vec<u32>>,
+ #[serde(deserialize_with = "from_list")]
+ #[serde(default)]
+ pub thumb_md5: Option<Vec<u16>>,
+ pub raw_data_type: Option<String>,
+ pub raw_data_size: Option<u32>,
+ #[serde(deserialize_with = "from_list")]
+ #[serde(default)]
+ pub raw_data_dimensions: Option<Vec<u32>>,
+ #[serde(deserialize_with = "from_list")]
+ #[serde(default)]
+ pub raw_data_active_area: Option<Vec<u32>>,
+ pub raw_cfa_pattern: Option<String>,
+ #[serde(deserialize_with = "from_list")]
+ #[serde(default)]
+ pub raw_min_value: Option<Vec<u16>>,
+ #[serde(deserialize_with = "from_list")]
+ #[serde(default)]
+ pub raw_max_value: Option<Vec<u16>>,
+ pub raw_md5: Option<u16>,
+ pub meta_orientation: Option<u32>,
+}
+
+/// Deserialize a space separated list on numbers to a vector.
+fn from_list<'de, D, T>(deserializer: D) -> Result<Option<Vec<T>>, D::Error>
+where
+ D: serde::Deserializer<'de>,
+ T: FromStr,
+ <T as FromStr>::Err: Display,
+{
+ let s: String = Deserialize::deserialize(deserializer)?;
+ let v: Vec<&str> = s.split(' ').collect();
+ let mut ints = vec![];
+ for num in v {
+ let n = num.parse::<T>().map_err(D::Error::custom)?;
+ ints.push(n);
+ }
+ Ok(Some(ints))
+}
+
+#[derive(Clone, Debug, Deserialize, PartialEq)]
+#[serde(rename = "test")]
+pub struct Test {
+ pub name: String,
+ pub file: String,
+ pub source: Option<String>,
+ pub results: Results,
+}
+
+fn make_results(rawfile: &dyn RawFile) -> Results {
+ let raw_type = Some(rawfile.type_().into());
+ let raw_type_id = Some(rawfile.type_id().into());
+ let exif_make = rawfile
+ .metadata_value(&"Exif.Image.Make".to_string())
+ .as_ref()
+ .and_then(Value::string);
+ let exif_model = rawfile
+ .metadata_value(&"Exif.Image.Model".to_string())
+ .as_ref()
+ .and_then(Value::string);
+ let meta_orientation = Some(rawfile.orientation());
+
+ let maker_note = rawfile.maker_note_ifd();
+ let maker_note_count = maker_note
+ .map(|mnote| mnote.num_entries() as i32)
+ .or(Some(-1));
+ let maker_note_id = maker_note.and_then(|mnote| String::from_utf8(mnote.id().to_vec()).ok());
+
+ let thumbnail_sizes = rawfile.thumbnail_sizes();
+ let thumb_num = Some(thumbnail_sizes.len() as u32);
+ let thumb_sizes = Some(thumbnail_sizes.to_vec());
+
+ let thumbnails = rawfile.thumbnails();
+ let thumb_formats = Some(
+ thumbnails
+ .thumbnails
+ .iter()
+ .map(|t| t.1.data_type.into())
+ .collect::<Vec<String>>()
+ .join(" "),
+ );
+ let thumb_data_sizes = Some(
+ thumbnails
+ .thumbnails
+ .iter()
+ .map(|t| t.1.data_size() as u32)
+ .collect(),
+ );
+ let thumb_md5 = Some(
+ thumbnails
+ .thumbnails
+ .iter()
+ .flat_map(|t| {
+ rawfile
+ .thumbnail(t.0)
+ .ok()
+ .and_then(|t| t.data8().map(raw_checksum))
+ })
+ .collect(),
+ );
+
+ let rawdata = rawfile.raw_data(false);
+ let rawdata = rawdata.as_ref();
+ let raw_data_type = rawdata.map(|rawdata| rawdata.data_type().into()).ok();
+ let raw_data_size = rawdata.map(|rawdata| rawdata.data_size() as u32).ok();
+ let raw_data_dimensions = rawdata
+ .map(|rawdata| vec![rawdata.width(), rawdata.height()])
+ .ok();
+ let raw_data_active_area = rawdata
+ .ok()
+ .and_then(|rawdata| rawdata.active_area())
+ .map(Rect::to_vec);
+ let raw_cfa_pattern = rawdata
+ .map(|rawdata| rawdata.mosaic_pattern().to_string())
+ .ok();
+ let raw_min_value = rawdata.map(|rawdata| rawdata.blacks().to_vec()).ok();
+ let raw_max_value = rawdata.map(|rawdata| rawdata.whites().to_vec()).ok();
+ let raw_md5 = rawdata
+ .ok()
+ .and_then(|rawdata| {
+ if rawdata.data_type() == DataType::CompressedRaw {
+ rawdata.data8()
+ } else {
+ rawdata.data16_as_u8()
+ }
+ })
+ .map(raw_checksum);
+
+ Results {
+ raw_type,
+ raw_type_id,
+ exif_make,
+ exif_model,
+ meta_orientation,
+ maker_note_count,
+ maker_note_id,
+ thumb_num,
+ thumb_sizes,
+ thumb_formats,
+ thumb_data_sizes,
+ thumb_md5,
+ raw_data_type,
+ raw_data_size,
+ raw_data_dimensions,
+ raw_data_active_area,
+ raw_cfa_pattern,
+ raw_min_value,
+ raw_max_value,
+ raw_md5,
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 73422e4..2e97caf 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -171,6 +171,20 @@ impl From<&str> for DataType {
}
}
+impl From<DataType> for String {
+ fn from(t: DataType) -> String {
+ match t {
+ DataType::Jpeg => "JPEG",
+ DataType::Raw => "RAW",
+ DataType::PixmapRgb8 => "8RGB",
+ DataType::PixmapRgb16 => "16RGB",
+ DataType::CompressedRaw => "COMP_RAW",
+ DataType::Unknown => "UNKNOWN",
+ }
+ .to_string()
+ }
+}
+
/// RAW file type. This list the type of files, which
/// coincidentally match the vendor, except for DNG.
///
@@ -227,6 +241,7 @@ impl From<&str> for Type {
"CRW" => Self::Crw,
"DNG" => Self::Dng,
"ERF" => Self::Erf,
+ "GPR" => Self::Gpr,
"MRW" => Self::Mrw,
"NEF" => Self::Nef,
"NRW" => Self::Nrw,
@@ -234,11 +249,40 @@ impl From<&str> for Type {
"PEF" => Self::Pef,
"RAF" => Self::Raf,
"RW2" => Self::Rw2,
+ "SR2" => Self::Sr2,
_ => Self::Unknown,
}
}
}
+impl From<Type> for String {
+ fn from(t: Type) -> String {
+ match t {
+ Type::Arw => "ARW",
+ Type::Cr2 => "CR2",
+ Type::Cr3 => "CR3",
+ Type::Crw => "CRW",
+ Type::Dng => "DNG",
+ Type::Erf => "ERF",
+ Type::Gpr => "GPR",
+ Type::Jpeg => "JPEG",
+ Type::Mrw => "MRW",
+ Type::Nef => "NEF",
+ Type::Nrw => "NRW",
+ Type::Orf => "ORF",
+ Type::Pef => "PEF",
+ Type::Raf => "RAF",
+ Type::Rw2 => "RW2",
+ Type::Sr2 => "SR2",
+ #[cfg(test)]
+ Type::Test => "TEST",
+ Type::Tiff => "TIF",
+ Type::Unknown => "UNKNOWN",
+ }
+ .to_string()
+ }
+}
+
/// Type ID (vendor, model)
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct TypeId(u16, u16);
diff --git a/tests/testsuite.rs b/tests/testsuite.rs
index 2e954f3..03fae7f 100644
--- a/tests/testsuite.rs
+++ b/tests/testsuite.rs
@@ -19,279 +19,215 @@
* <http://www.gnu.org/licenses/>.
*/
-use std::fmt::Display;
use std::path::Path;
-use std::str::FromStr;
-use serde::{de::Error, Deserialize};
+use serde::Deserialize;
use serde_xml_rs::{de::Deserializer, from_reader};
use libopenraw::metadata::Value;
use libopenraw::{Bitmap, DataType, Ifd, RawFile, Type, TypeId};
+use libopenraw_testing::{raw_checksum, Results, Test};
-#[derive(Clone, Debug, Deserialize, PartialEq)]
-#[serde(rename_all = "camelCase")]
-struct Results {
- raw_type: Option<String>,
- raw_type_id: Option<u32>,
- /// MakeNoteCount can be -1 for an error (expected)
- maker_note_count: Option<i32>,
- maker_note_id: Option<String>,
- exif_make: Option<String>,
- exif_model: Option<String>,
- thumb_num: Option<u32>,
- #[serde(deserialize_with = "from_list")]
- #[serde(default)]
- thumb_sizes: Option<Vec<u32>>,
- thumb_formats: Option<String>, // XXX split array
- #[serde(deserialize_with = "from_list")]
- #[serde(default)]
- thumb_data_sizes: Option<Vec<u32>>,
- #[serde(deserialize_with = "from_list")]
- #[serde(default)]
- thumb_md5: Option<Vec<u16>>,
- raw_data_type: Option<String>,
- raw_data_size: Option<u32>,
- #[serde(deserialize_with = "from_list")]
- #[serde(default)]
- raw_data_dimensions: Option<Vec<u32>>,
- #[serde(deserialize_with = "from_list")]
- #[serde(default)]
- raw_data_active_area: Option<Vec<u32>>,
- raw_cfa_pattern: Option<String>,
- #[serde(deserialize_with = "from_list")]
- #[serde(default)]
- raw_min_value: Option<Vec<u16>>,
- #[serde(deserialize_with = "from_list")]
- #[serde(default)]
- raw_max_value: Option<Vec<u16>>,
- raw_md5: Option<u32>,
- meta_orientation: Option<u32>,
+trait TestRun {
+ fn run(&self, rawfile: &dyn RawFile, filename: &str) -> u32;
}
-/// Deserialize a space separated list on numbers to a vector.
-fn from_list<'de, D, T>(deserializer: D) -> Result<Option<Vec<T>>, D::Error>
-where
- D: serde::Deserializer<'de>,
- T: FromStr,
- <T as FromStr>::Err: Display,
-{
- let s: String = Deserialize::deserialize(deserializer)?;
- let v: Vec<&str> = s.split(' ').collect();
- let mut ints = vec![];
- for num in v {
- let n = num.parse::<T>().map_err(D::Error::custom)?;
- ints.push(n);
- }
- Ok(Some(ints))
-}
+/// Test for RAW
+fn raw_test(results: &Results, rawfile: &dyn RawFile) -> u32 {
+ let mut count = 0;
-impl Results {
- /// CRC checksum for the RAW data (8 bits only)
- fn raw_checksum(buf: &[u8]) -> u16 {
- // This is the same algorithm as used in the C++ implementation
- let crc = crc::Crc::<u16>::new(&crc::CRC_16_IBM_3740);
- let mut digest = crc.digest();
- digest.update(buf);
+ let rawdata = rawfile.raw_data(false);
+ assert_eq!(
+ rawdata.is_ok(),
+ results.raw_data_type.is_some(),
+ "Expected Raw data wasn't found"
+ );
- digest.finalize()
+ // no raw data, bail out
+ if rawdata.is_err() {
+ return count;
}
- /// Test for RAW
- fn raw_test(&self, rawfile: &dyn RawFile) -> u32 {
- let mut count = 0;
+ let rawdata = rawdata.unwrap();
- let rawdata = rawfile.raw_data(false);
+ // RAW data type
+ if let Some(ref raw_data_type) = results.raw_data_type {
+ count += 1;
assert_eq!(
- rawdata.is_ok(),
- self.raw_data_type.is_some(),
- "Expected Raw data wasn't found"
+ DataType::from(raw_data_type.as_str()),
+ rawdata.data_type(),
+ "Incorrect type for Raw data"
);
+ }
+ // RAW data size
+ if let Some(raw_data_size) = results.raw_data_size {
+ count += 1;
+ assert_eq!(
+ raw_data_size as usize,
+ rawdata.data_size(),
+ "Incorrect Raw data size"
+ );
+ }
- // no raw data, bail out
- if rawdata.is_err() {
- return count;
- }
-
- let rawdata = rawdata.unwrap();
-
- // RAW data type
- if let Some(ref raw_data_type) = self.raw_data_type {
- count += 1;
- assert_eq!(
- DataType::from(raw_data_type.as_str()),
- rawdata.data_type(),
- "Incorrect type for Raw data"
- );
- }
- // RAW data size
- if let Some(raw_data_size) = self.raw_data_size {
- count += 1;
- assert_eq!(
- raw_data_size as usize,
- rawdata.data_size(),
- "Incorrect Raw data size"
- );
- }
-
- // RAW dimensions
- if let Some(ref dims) = self.raw_data_dimensions {
- count += 1;
- assert_eq!(dims.len(), 2, "Incorrect number of Raw dimensions");
- assert_eq!(
- dims,
- &[rawdata.width(), rawdata.height()],
- "Incorrect dimensions"
- );
- }
+ // RAW dimensions
+ if let Some(ref dims) = results.raw_data_dimensions {
+ count += 1;
+ assert_eq!(dims.len(), 2, "Incorrect number of Raw dimensions");
+ assert_eq!(
+ dims,
+ &[rawdata.width(), rawdata.height()],
+ "Incorrect dimensions"
+ );
+ }
- // RAW active area
- if let Some(ref raw_data_active_area) = self.raw_data_active_area {
- count += 1;
- assert_eq!(raw_data_active_area.len(), 4, "Incorrect active area");
- let active_area = rawdata.active_area();
- assert!(active_area.is_some(), "No active area found");
- let active_area = active_area.unwrap();
- assert_eq!(
- raw_data_active_area,
- &active_area.to_vec(),
- "Incorrect active area"
- );
- }
+ // RAW active area
+ if let Some(ref raw_data_active_area) = results.raw_data_active_area {
+ count += 1;
+ assert_eq!(raw_data_active_area.len(), 4, "Incorrect active area");
+ let active_area = rawdata.active_area();
+ assert!(active_area.is_some(), "No active area found");
+ let active_area = active_area.unwrap();
+ assert_eq!(
+ raw_data_active_area,
+ &active_area.to_vec(),
+ "Incorrect active area"
+ );
+ }
- // CFA pattern
- if let Some(ref raw_cfa_pattern) = self.raw_cfa_pattern {
- count += 1;
- assert_eq!(
- &rawdata.mosaic_pattern().to_string(),
- raw_cfa_pattern,
- "Incorrect CFA pattern"
- );
- }
+ // CFA pattern
+ if let Some(ref raw_cfa_pattern) = results.raw_cfa_pattern {
+ count += 1;
+ assert_eq!(
+ &rawdata.mosaic_pattern().to_string(),
+ raw_cfa_pattern,
+ "Incorrect CFA pattern"
+ );
+ }
- // RAW black and white
- if let Some(ref raw_min_value) = self.raw_min_value {
- count += 1;
- assert_eq!(
- &rawdata.blacks().to_vec(),
- raw_min_value,
- "Incorrect black point"
- );
- }
- if let Some(ref raw_max_value) = self.raw_max_value {
- count += 1;
- assert_eq!(
- &rawdata.whites().to_vec(),
- raw_max_value,
- "Incorrect white point"
- );
- }
+ // RAW black and white
+ if let Some(ref raw_min_value) = results.raw_min_value {
+ count += 1;
+ assert_eq!(
+ &rawdata.blacks().to_vec(),
+ raw_min_value,
+ "Incorrect black point"
+ );
+ }
+ if let Some(ref raw_max_value) = results.raw_max_value {
+ count += 1;
+ assert_eq!(
+ &rawdata.whites().to_vec(),
+ raw_max_value,
+ "Incorrect white point"
+ );
+ }
- // RAW data checksum. It's not even a md5.
- if let Some(raw_md5) = self.raw_md5 {
- count += 1;
- let buf = if rawdata.data_type() == DataType::CompressedRaw {
- let buf = rawdata.data8();
- assert!(buf.is_some(), "Compressed Raw data not found");
- buf.unwrap()
- } else {
- let buf = rawdata.data16_as_u8();
- assert!(buf.is_some(), "16-bits Raw data not found");
- buf.unwrap()
- };
- let r = Self::raw_checksum(buf);
- assert_eq!(raw_md5, r as u32, "Incorrect Raw data checksum");
- }
- count
+ // RAW data checksum. It's not even a md5.
+ if let Some(raw_md5) = results.raw_md5 {
+ count += 1;
+ let buf = if rawdata.data_type() == DataType::CompressedRaw {
+ let buf = rawdata.data8();
+ assert!(buf.is_some(), "Compressed Raw data not found");
+ buf.unwrap()
+ } else {
+ let buf = rawdata.data16_as_u8();
+ assert!(buf.is_some(), "16-bits Raw data not found");
+ buf.unwrap()
+ };
+ let r = raw_checksum(buf);
+ assert_eq!(raw_md5, r, "Incorrect Raw data checksum");
}
+ count
+}
- fn thumbnail_test(&self, rawfile: &dyn RawFile) -> u32 {
- let mut count = 0;
- // Check the number of thumbnails
- if let Some(thumb_num) = self.thumb_num {
- count += 1;
- let thumbnail_sizes = rawfile.thumbnail_sizes();
- assert_eq!(
- thumb_num as usize,
- thumbnail_sizes.len(),
- "Different number of thumbnails"
- );
- }
+fn thumbnail_test(results: &Results, rawfile: &dyn RawFile) -> u32 {
+ let mut count = 0;
+ // Check the number of thumbnails
+ if let Some(thumb_num) = results.thumb_num {
+ count += 1;
+ let thumbnail_sizes = rawfile.thumbnail_sizes();
+ assert_eq!(
+ thumb_num as usize,
+ thumbnail_sizes.len(),
+ "Different number of thumbnails"
+ );
+ }
- if let Some(ref sizes) = self.thumb_sizes {
- count += 1;
- let thumbnail_sizes = rawfile.thumbnail_sizes();
+ if let Some(ref sizes) = results.thumb_sizes {
+ count += 1;
+ let thumbnail_sizes = rawfile.thumbnail_sizes();
+ assert_eq!(
+ thumbnail_sizes.len(),
+ sizes.len(),
+ "Mismatch number of thumbnails"
+ );
+ for (index, size) in sizes.iter().enumerate() {
assert_eq!(
- thumbnail_sizes.len(),
- sizes.len(),
- "Mismatch number of thumbnails"
+ size, &thumbnail_sizes[index],
+ "Incorrect size for thumbnail {index}"
);
- for (index, size) in sizes.iter().enumerate() {
- assert_eq!(
- size, &thumbnail_sizes[index],
- "Incorrect size for thumbnail {index}"
- );
- }
}
+ }
- if let Some(ref thumb_formats) = self.thumb_formats {
- count += 1;
- let thumbnails = rawfile.thumbnails();
- let formats: Vec<DataType> = thumb_formats.split(' ').map(DataType::from).collect();
+ if let Some(ref thumb_formats) = results.thumb_formats {
+ count += 1;
+ let thumbnails = rawfile.thumbnails();
+ let formats: Vec<DataType> = thumb_formats.split(' ').map(DataType::from).collect();
+ assert_eq!(
+ thumbnails.sizes.len(),
+ formats.len(),
+ "Mismatch number of thumbnail format"
+ );
+ for (index, thumbnail) in thumbnails.thumbnails.iter().enumerate() {
assert_eq!(
- thumbnails.sizes.len(),
- formats.len(),
- "Mismatch number of thumbnail format"
+ thumbnail.1.data_type, formats[index],
+ "Incorrect data type for thumbnail {index}"
);
- for (index, thumbnail) in thumbnails.thumbnails.iter().enumerate() {
- assert_eq!(
- thumbnail.1.data_type, formats[index],
- "Incorrect data type for thumbnail {index}"
- );
- }
}
+ }
- if let Some(ref data_sizes) = self.thumb_data_sizes {
- count += 1;
- let thumbnails = rawfile.thumbnails();
+ if let Some(ref data_sizes) = results.thumb_data_sizes {
+ count += 1;
+ let thumbnails = rawfile.thumbnails();
+ assert_eq!(
+ thumbnails.thumbnails.len(),
+ data_sizes.len(),
+ "Mismatch number of thumbnail data sizes"
+ );
+ for (index, thumbnail) in thumbnails.thumbnails.iter().enumerate() {
assert_eq!(
- thumbnails.thumbnails.len(),
- data_sizes.len(),
- "Mismatch number of thumbnail data sizes"
+ thumbnail.1.data_size(),
+ data_sizes[index] as u64,
+ "Incorrect data size for thumbnail {index}"
);
- for (index, thumbnail) in thumbnails.thumbnails.iter().enumerate() {
- assert_eq!(
- thumbnail.1.data_size(),
- data_sizes[index] as u64,
- "Incorrect data size for thumbnail {index}"
- );
- }
}
+ }
- if let Some(ref md5s) = self.thumb_md5 {
- count += 1;
- let thumbnails = rawfile.thumbnails();
- assert_eq!(
- thumbnails.thumbnails.len(),
- md5s.len(),
- "Mismatch number of thumbnail checksum"
- );
- for (index, thumbnail_desc) in thumbnails.thumbnails.iter().enumerate() {
- let thumbnail = rawfile
- .thumbnail(thumbnail_desc.0)
- .expect("Thumbnail not found");
- let buf = thumbnail.data8().unwrap();
- let r = Self::raw_checksum(buf);
- assert_eq!(r, md5s[index], "Incorrect checksum for thumbnail {index}");
- }
+ if let Some(ref md5s) = results.thumb_md5 {
+ count += 1;
+ let thumbnails = rawfile.thumbnails();
+ assert_eq!(
+ thumbnails.thumbnails.len(),
+ md5s.len(),
+ "Mismatch number of thumbnail checksum"
+ );
+ for (index, thumbnail_desc) in thumbnails.thumbnails.iter().enumerate() {
+ let thumbnail = rawfile
+ .thumbnail(thumbnail_desc.0)
+ .expect("Thumbnail not found");
+ let buf = thumbnail.data8().unwrap();
+ let r = raw_checksum(buf);
+ assert_eq!(r, md5s[index], "Incorrect checksum for thumbnail {index}");
}
+ }
- // XXX todo
+ // XXX todo
- count
- }
+ count
+}
+impl TestRun for Results {
fn run(&self, rawfile: &dyn RawFile, filename: &str) -> u32 {
let mut count = 0;
// Check RAW type
@@ -379,35 +315,12 @@ impl Results {
);
}
- count += self.thumbnail_test(rawfile);
- count += self.raw_test(rawfile);
+ count += thumbnail_test(self, rawfile);
+ count += raw_test(self, rawfile);
count
}
}
-#[derive(Clone, Debug, Deserialize, PartialEq)]
-#[serde(rename = "test")]
-struct Test {
- name: String,
- file: String,
- source: Option<String>,
- results: Results,
-}
-
-impl Test {
- fn run(&self) {
- let rawfile = libopenraw::rawfile_from_file(self.file.clone(), None);
- match rawfile {
- Ok(rawfile) => {
- print!("Test '{}'", &self.name);
- let count = self.results.run(rawfile.as_ref(), &self.file);
- println!(" produced {count} results");
- }
- Err(err) => println!("Test '{}' skipped ({}): {}", &self.name, self.file, err),
- }
- }
-}
-
#[derive(Debug, Deserialize, PartialEq)]
#[serde(rename = "testsuite")]
struct TestSuite {
@@ -434,12 +347,22 @@ struct Overrides {
}
impl TestSuite {
- fn run(&mut self) {
- for test in &self.tests {
- test.run();
+ fn run_test(test: &Test) {
+ let rawfile = libopenraw::rawfile_from_file(test.file.clone(), None);
+ match rawfile {
+ Ok(rawfile) => {
+ print!("Test '{}'", &test.name);
+ let count = test.results.run(rawfile.as_ref(), &test.file);
+ println!(" produced {count} results");
+ }
+ Err(err) => println!("Test '{}' skipped ({}): {}", &test.name, test.file, err),
}
}
+ fn run(&mut self) {
+ self.tests.iter().for_each(TestSuite::run_test);
+ }
+
/// Load the overrides to, notably, change the local path of the files.
fn load_overrides<P>(&mut self, path: P)
where